ArpaNameTool.mesa
Copyright © 1987 by Xerox Corporation. All rights reserved.
John Larson, February 28, 1988 1:34:30 pm PST
DIRECTORY
Arpa,
ArpaNameBuf USING [domainPort, Port],
ArpaName USING [AddressToName, AliasToName, MyName, NameToAddress, ReplyStatus],
ArpaNameSupport USING [IsAddressRope],
ArpaNameQuery USING [ARR, NsRR, CNameRR, PtrRR, MbRR, MgRR, MrRR, MdRR, MfRR, SoaRR, WksRR, HinfoRR, MinfoRR, MxRR, Error, Protocol, QClass, QType, Query, QuestionRecord, RRClass, RRType, Reply, ResourceRecord, Seconds],
ArpaUDP USING [Milliseconds],
Atom USING [GetPName],
Buttons USING [Button, ButtonProc, Create, Destroy, SetDisplayStyle],
Commander USING [CommandProc, Register],
Containers USING [ChildXBound, ChildYBound, Create],
Convert USING [CardFromRope],
ConvertExtras USING [RopeFromArpaAddress],
IO USING [Flush, PutF, PutFR, PutRope, STREAM, Value],
Labels USING [Create],
Loader USING [BCDBuildTime],
Rope USING [ROPE, IsEmpty],
Rules USING [Create],
TypeScript USING [ChangeLooks, Create],
ViewerClasses USING [Viewer],
ViewerIO USING [CreateViewerStreams],
ViewerOps USING [AddProp, ComputeColumn, CreateViewer, MoveViewer, OpenIcon, SetOpenHeight],
ViewerTools USING [GetContents, MakeNewTextViewer, SetContents, SetSelection];
ArpaNameTool: CEDAR MONITOR
IMPORTS
ArpaName, ArpaNameSupport, ArpaNameQuery, Atom, Buttons, Commander, Containers, Convert, ConvertExtras, IO, Labels, Loader, Rope, Rules, TypeScript, ViewerIO, ViewerOps, ViewerTools =
BEGIN
ROPE: TYPE = Rope.ROPE;
STREAM: TYPE = IO.STREAM;
Viewer: TYPE = ViewerClasses.Viewer;
Viewer layout parameters
buttonHeight: INTEGER ← 0;
buttonWidth: INTEGER ← 0;
ClientData: TYPE = REF ClientDataRep;
ClientDataRep: TYPE = RECORD [
log: STREAMNIL,
in: STREAMNIL,
class: ArpaNameQuery.QClass ← in,
protocol: ArpaNameQuery.Protocol ← udpOnly,
recursionDesired: BOOLFALSE,
showErr: BOOLTRUE,
target, timeout, query: Viewer ← NIL ];
sequenceNumber: CARDINAL ← 0;
Create: Commander.CommandProc = TRUSTED {
data: ClientData ← NEW[ClientDataRep ← []];
viewer, buttons, log: Viewer ← NIL;
viewer ← ViewerOps.CreateViewer [
flavor: $Container,
info: [name: "ArpaNameTool", column: right, iconic: TRUE, scrollable: FALSE]];
ViewerOps.AddProp[viewer, $ArpaNameTool, data];
{ -- Kludge to find Button size
temp: Buttons.Button = Buttons.Create[
info: [name: "Length:", parent: viewer, border: FALSE,
wx: 0, wy: 0],
proc: NIL, clientData: NIL, fork: FALSE, paint: FALSE];
buttonWidth ← temp.ww;
buttonHeight ← temp.wh;
Buttons.Destroy[temp]; };
log ← TypeScript.Create[
[name: "ArpaNameTool.log", wy: 27+4, parent: viewer, border: FALSE], FALSE];
[data.in, data.log] ← ViewerIO.CreateViewerStreams [
name: "ArpaNameTool.log", backingFile: "ArpaNameTool.log", viewer: log, editedStream: FALSE];
Containers.ChildXBound[viewer, log];
Containers.ChildYBound[viewer, log];
CreateButtons[data, viewer, log];
TypeScript.ChangeLooks[log, 'f];
IO.PutF[data.log, "ArpaNameTool of %G.\n", [time[Loader.BCDBuildTime[Create]]]];
ViewerOps.OpenIcon[viewer]; };
CreateButtons: PROC[data: ClientData, parent, log: Viewer] = {
child: Viewer ← NIL;
kids: Viewer = Containers.Create[
info: [parent: parent, border: FALSE, scrollable: FALSE, wx: 0, wy: -9999, ww: 9999, wh: 0] ];
Containers.ChildXBound[parent, kids];
child ← MakeRule[kids, child];
child ← data.target ← MakeLabeledText[
parent: kids,
sibling: child,
name: "Server:",
data: "parcvax",
prev: data.target ];
child ← data.query ← MakeLabeledText[
parent: kids,
sibling: child,
name: "Query:",
data: ArpaName.MyName[],
prev: data.query];
child ← data.timeout ← MakeLabeledText[
parent: kids,
sibling: child,
name: "Timeout:",
data: "30000",
prev: data.timeout ];
child ← MakeRule[kids, child];
child ← MakeBool[kids, child, data, "recurse", NEW[BOOLFALSE], RecurseP];
child ← MakeBool[kids, child, data, "errors", NEW[BOOLTRUE], ShowErr];
child ← MakeSelector[kids, child, data, LIST[$in, $ch, $star], " QClass ", NEW[ATOM ← $in], QClassP];
child ← MakeSelector[kids, child, data, LIST[$udp, $tcp], " Protocol ", NEW[ATOM ← $udp], ProtocolP];
child ← MakeRule[kids, child];
child ← MakeLabel[kids, child, "QType:"];
child ← MakeButton[kids, child, data, " A ", Address];
child ← MakeButton[kids, child, data, "NS", Server];
child ← MakeButton[kids, child, data, "CN", CName];
child ← MakeButton[kids, child, data, "MX", MX];
child ← MakeButton[kids, child, data, "SOA", SOA];
child ← MakeButton[kids, child, data, " * ", Star];
child ← MakeRule[kids, child];
child ← MakeButton[kids, child, data, "Inv", Inverse];
child ← MakeButton[kids, child, data, "MB", MB];
child ← MakeButton[kids, child, data, "MG", MG];
child ← MakeButton[kids, child, data, "MR", MR];
child ← MakeButton[kids, child, data, "Null", Null];
child ← MakeButton[kids, child, data, "WKS", Wks];
child ← MakeRule[kids, child];
child ← MakeButton[kids, child, data, "Ptr", Ptr];
child ← MakeButton[kids, child, data, "HInfo", HInfo];
child ← MakeButton[kids, child, data, "MInfo", MInfo];
child ← MakeButton[kids, child, data, "MailA", Maila];
child ← MakeButton[kids, child, data, "MailB", Mailb];
child ← MakeButton[kids, child, data, "AXFR", Axfr];
child ← MakeRule[kids, child];
{
kidsY: INTEGER = 2;
kidsH: INTEGER = child.wy + child.wh + 2;
ViewerOps.MoveViewer[viewer: log, x: 0, y: kidsY + kidsH, w: log.ww, h: parent.ch - (kids.wy + kidsH), paint: FALSE];
ViewerOps.SetOpenHeight[parent, kidsY + kidsH + 12 * buttonHeight];
IF ~parent.iconic THEN ViewerOps.ComputeColumn[parent.column];
ViewerOps.MoveViewer[viewer: kids, x: kids.wx, y: kidsY, w: kids.ww, h: kidsH]; };
};
QClassP: SelectorProc = TRUSTED {
parent: REF, clientData: REF, value: BOOL
data: ClientData ← NARROW[clientData];
data.class ←
SELECT value FROM
$in => in,
$ch => ch,
ENDCASE => star;
};
ProtocolP: SelectorProc = TRUSTED {
parent: REF, clientData: REF, value: BOOL
data: ClientData ← NARROW[clientData];
data.protocol ←
SELECT value FROM
$udp => udpOnly,
ENDCASE => tcpOnly;
};
RecurseP: BoolProc = TRUSTED {
parent: REF, clientData: REF, value: BOOL
data: ClientData ← NARROW[clientData];
data.recursionDesired ← value;
};
ShowErr: BoolProc = TRUSTED {
parent: REF, clientData: REF, value: BOOL
data: ClientData ← NARROW[clientData];
data.showErr ← value;
};
Address: Buttons.ButtonProc = TRUSTED {
parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL
data: ClientData ← NARROW[clientData];
Query[data, a]; };
Server: Buttons.ButtonProc = TRUSTED {
parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL
data: ClientData ← NARROW[clientData];
Query[data, ns]; };
CName: Buttons.ButtonProc = TRUSTED {
parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL
data: ClientData ← NARROW[clientData];
Query[data, cName]; };
Star: Buttons.ButtonProc = TRUSTED {
parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL
data: ClientData ← NARROW[clientData];
Query[data, star]; };
SOA: Buttons.ButtonProc = TRUSTED {
parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL
data: ClientData ← NARROW[clientData];
Query[data, soa]; };
MX: Buttons.ButtonProc = TRUSTED {
parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL
data: ClientData ← NARROW[clientData];
Query[data, mx];
};
MB: Buttons.ButtonProc = TRUSTED {
parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL
data: ClientData ← NARROW[clientData];
Query[data, mb];
};
MG: Buttons.ButtonProc = TRUSTED {
parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL
data: ClientData ← NARROW[clientData];
Query[data, mg];
};
MR: Buttons.ButtonProc = TRUSTED {
parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL
data: ClientData ← NARROW[clientData];
Query[data, mr];
};
Null: Buttons.ButtonProc = TRUSTED {
parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL
data: ClientData ← NARROW[clientData];
Query[data, null];
};
Wks: Buttons.ButtonProc = TRUSTED {
parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL
data: ClientData ← NARROW[clientData];
Query[data, wks];
};
Ptr: Buttons.ButtonProc = TRUSTED {
parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL
data: ClientData ← NARROW[clientData];
Query[data, ptr];
};
HInfo: Buttons.ButtonProc = TRUSTED {
parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL
data: ClientData ← NARROW[clientData];
Query[data, hinfo];
};
MInfo: Buttons.ButtonProc = TRUSTED {
parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL
data: ClientData ← NARROW[clientData];
Query[data, minfo];
};
Maila: Buttons.ButtonProc = TRUSTED {
parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL
data: ClientData ← NARROW[clientData];
Query[data, maila];
};
Mailb: Buttons.ButtonProc = TRUSTED {
parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL
data: ClientData ← NARROW[clientData];
Query[data, mailb];
};
Axfr: Buttons.ButtonProc = TRUSTED {
parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL
data: ClientData ← NARROW[clientData];
Query[data, axfr];
};
Inverse: Buttons.ButtonProc = TRUSTED {
parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL
data: ClientData ← NARROW[clientData];
log: IO.STREAM ← data.log;
serverName: ROPE = ViewerTools.GetContents[data.target];
rope: ROPE ← ViewerTools.GetContents[data.query];
port: ArpaNameBuf.Port ← ArpaNameBuf.domainPort;
timeoutRope: ROPE ← ViewerTools.GetContents[data.timeout];
timeout: ArpaUDP.Milliseconds ← Convert.CardFromRope[timeoutRope];
server, address, source: Arpa.Address;
query: ROPE;
reply: ArpaNameQuery.Reply ← NIL;
status: ArpaName.ReplyStatus;
IF Rope.IsEmpty[serverName] THEN RETURN;
IF Rope.IsEmpty[rope] THEN RETURN;
[server, status, source] ← ArpaName.NameToAddress[serverName];
SELECT status FROM
bogus => {Report[log, serverName, ": not a valid name (", ArpaName.AddressToName[source].name, ").\n"]; RETURN};
down => {Report[log, "Name servers not responding.\n"]; RETURN};
other => {Report[log, serverName, ": no address for this name (", ArpaName.AddressToName[source].name, ").\n"]; RETURN};
ENDCASE;
IF server = Arpa.nullAddress THEN {Report[log, serverName, ": unable to lookup name.\n"]};
IF ~ArpaNameSupport.IsAddressRope[rope] THEN {Report[log, "Needs to be an Arpa address.\n"]; RETURN};
address ← ArpaName.NameToAddress[rope].addr;
IF address = Arpa.nullAddress THEN {Report[log, "Needs to be an Arpa address.\n"]; RETURN};
query ← IO.PutFR["%G.%G.%G.%G.IN-ADDR.ARPA", [integer[address.d]], [integer[address.c]], [integer[address.b]], [integer[address.a]]];
PrintOutgoing[server, serverName, query, ptr, data.class, data.recursionDesired, log];
reply ← DoQuery[server, query, ptr, data.class, data.protocol, data.recursionDesired, port, timeout, data.showErr, log];
PrintReply[server, reply, log];
};
Query: PROC [data: ClientData, type: ArpaNameQuery.QType] = {
log: IO.STREAM ← data.log;
server, source: Arpa.Address;
reply: ArpaNameQuery.Reply ← NIL;
serverName: ROPE = ViewerTools.GetContents[data.target];
query: ROPE ← ViewerTools.GetContents[data.query];
port: ArpaNameBuf.Port ← ArpaNameBuf.domainPort;
timeoutRope: ROPE ← ViewerTools.GetContents[data.timeout];
timeout: ArpaUDP.Milliseconds ← Convert.CardFromRope[timeoutRope];
status: ArpaName.ReplyStatus;
IF Rope.IsEmpty[serverName] THEN RETURN;
IF Rope.IsEmpty[query] THEN RETURN;
[server, status, source] ← ArpaName.NameToAddress[serverName];
SELECT status FROM
bogus => {Report[log, serverName, ": not a valid name (", ArpaName.AddressToName[source].name, ").\n"]; RETURN};
down => {Report[log, "Name servers not responding.\n"]; RETURN};
other => {Report[log, serverName, ": no address for this name (", ArpaName.AddressToName[source].name, ").\n"]; RETURN};
ENDCASE;
IF server = Arpa.nullAddress THEN {Report[log, serverName, ": unable to lookup name.\n"]};
PrintOutgoing[server, serverName, query, type, data.class, data.recursionDesired, log];
reply ← DoQuery[server, query, type, data.class, data.protocol, data.recursionDesired, port, timeout, data.showErr, log];
PrintReply[server, reply, log];
};
DoQuery: PROC [
server: Arpa.Address,
query: Rope.ROPE,
type: ArpaNameQuery.QType,
class: ArpaNameQuery.QClass,
protocol: ArpaNameQuery.Protocol,
recurDesired: BOOL,
port: ArpaNameBuf.Port,
timeout: ArpaUDP.Milliseconds,
showErrs: BOOL,
log: IO.STREAM] RETURNS[reply: ArpaNameQuery.Reply] = {
{ENABLE {UNWIND => NULL; ArpaNameQuery.Error => {PrintCode[code, log]; GOTO Quit}};
reply ← ArpaNameQuery.Query[server: server, query: query, type: type, class: class, recurDesired: recurDesired, protocol: protocol, port: port, timeout: timeout, retry: 0, acceptErrors: showErrs];
};
EXITS
Quit => {};
};
PrintCode: PROC [code: ATOM, log: IO.STREAM] = {
SELECT code FROM
$destUnreachable => Report[log, "\nError: Destination unreachable.\n"];
$badRemoteAddress => Report[log, "\nError: Attempt to use broadcast address.\n"];
$nullDestination => Report[log, "\nError: Attempt to use null address.\n"];
$netUnreachable => Report[log, "\nICMP message: Net unreachable.\n"];
$hostUnreachable => Report[log, "\nICMP message: Host unreachable.\n"];
$portUnreachable => Report[log, "\nICMP message: Port unreachable.\n"];
$mustFragment => Report[log, "\nICMP message: Must fragment.\n"];
$sourceRouteFailure => Report[log, "\nICMP message: Source route failure.\n"];
$timeoutTimeToLive => Report[log, "\nICMP message: Timeout TimeToLive.\n"];
$parameterProblem => Report[log, "\nICMP message: Parameter problem.\n"];
$sourceQuench => Report[log, "\nICMP message: Source quench.\n"];
ENDCASE => Report[log, "\nError: ", Atom.GetPName[code], "\n"];
};
PrintOutgoing: PROC [
server: Arpa.Address,
serverName: ROPE,
query: Rope.ROPE,
type: ArpaNameQuery.QType,
class: ArpaNameQuery.QClass,
recurDesired: BOOLEAN,
log: IO.STREAM] = {
IF log = NIL THEN RETURN;
IF ArpaNameSupport.IsAddressRope[serverName] THEN
Report[log, "\nAsking ", serverName, " = ", ArpaName.AddressToName[server].name, "\n"]
ELSE
Report[log, "\nAsking ", ArpaName.AliasToName[serverName].name, " = ", ConvertExtras.RopeFromArpaAddress[server], "\n"];
PrintQuery[query, type, class, log];
Report[log, "Recursion desired: "];
SELECT recurDesired FROM
TRUE => Report[log, "TRUE\n"];
ENDCASE => Report[log, "FALSE\n"];
Report[log, "\n"];
IO.Flush[log];
};
Report: PROC [log: IO.STREAM, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10: ROPENIL] = {
IF log = NIL THEN RETURN;
IF r1 # NIL THEN {IO.PutRope[log, r1]};
IF r2 # NIL THEN {IO.PutRope[log, r2]};
IF r3 # NIL THEN {IO.PutRope[log, r3]};
IF r4 # NIL THEN {IO.PutRope[log, r4]};
IF r5 # NIL THEN {IO.PutRope[log, r5]};
IF r6 # NIL THEN {IO.PutRope[log, r6]};
IF r7 # NIL THEN {IO.PutRope[log, r7]};
IF r8 # NIL THEN {IO.PutRope[log, r8]};
IF r9 # NIL THEN {IO.PutRope[log, r9]};
IF r10 # NIL THEN {IO.PutRope[log, r10]};
};
PrintReply: PROC [server: Arpa.Address, reply: ArpaNameQuery.Reply, log: IO.STREAM] = {
IF log = NIL THEN RETURN;
IF reply = NIL THEN {Report[log, "No reply to query.\n"]; RETURN;};
IF reply.source # server THEN
Report[log, IO.PutFR["Strange source address: expected %G, found %G.\n",
[rope[ConvertExtras.RopeFromArpaAddress[server]]],
[rope[ConvertExtras.RopeFromArpaAddress[reply.source]]]]];
Report[log, "Reply: \n"];
SELECT reply.hdr.qr FROM
query => Report[log, "qr: query, "];
response => Report[log, "qr: response, "];
ENDCASE => ERROR;
SELECT reply.hdr.opcode FROM
query => Report[log, "opcode: query"];
iquery => Report[log, "opcode: iquery"];
cquerym => Report[log, "opcode: cquerym"];
cqueryu => Report[log, "opcode: cqueryu"];
ENDCASE => ERROR;
Report[log, IO.PutFR[", length: %G bytes.\n", [integer[reply.domainPacketLength]]]];
Report[log, IO.PutFR["aa: %G, tc: %G, rd: %G, ra: %G, ",
[boolean[reply.hdr.authoritative]], [boolean[reply.hdr.truncated]], [boolean[reply.hdr.recurDesired]], [boolean[reply.hdr.recurAvail]]]];
SELECT reply.hdr.rcode FROM
ok => Report[log, "rcode: ok"];
format => Report[log, "rcode: format"];
serverFailed => Report[log, "rcode: serverFailed"];
nameError => Report[log, "rcode: nameError"];
notImplemented => Report[log, "rcode: notImplemented"];
refused => Report[log, "rcode: refused"];
ENDCASE => ERROR;
IF reply.hdr.truncated THEN Report[log, " ** TRUNCATED **"];
Report[log, "\n"];
Report[log, IO.PutFR["qdCount: %G, anCount: %G, nsCount: %G, arCount: %G\n",
[integer[reply.hdr.qdCount]], [integer[reply.hdr.anCount]], [integer[reply.hdr.nsCount]], [integer[reply.hdr.arCount]]]];
IF reply.hdr.qdCount # reply.qdCount THEN Report[log, IO.PutFR[" ** INCORRECT QUERY RECORD COUNT.\n ** Query records found: %g.\n", [integer[reply.qdCount]]]];
IF reply.hdr.anCount # reply.anCount THEN Report[log, IO.PutFR[" ** INCORRECT ANSWER RR COUNT.\n ** Answer RRs found: %g.\n", [integer[reply.anCount]]]];
IF reply.hdr.nsCount # reply.nsCount THEN Report[log, IO.PutFR[" ** INCORRECT AUTHORITY RR COUNT.\n ** Authority RRs found: %g.\n", [integer[reply.nsCount]]]];
IF reply.hdr.arCount # reply.arCount THEN Report[log, IO.PutFR[" ** INCORRECT ADDITIONAL RR COUNT.\n ** Additional RRs found: %g.\n", [integer[reply.arCount]]]];
PrintQueries[reply, log];
PrintAnswerRRs[reply, log];
PrintAuthorityRRs[reply, log];
PrintAdditionalRRs[reply, log];
Report[log, "\n"];
Report[log, IO.PutFR["The response time was %G ms.\n", [integer[reply.responseTime]]]];
Report[log, "\n"];
IO.Flush[log];
};
PrintQueries: PROC [reply: ArpaNameQuery.Reply, log: IO.STREAM] = {
IF reply.questions = NIL THEN RETURN;
FOR i: INT IN[0..reply.qdCount) DO
q: ArpaNameQuery.QuestionRecord ← reply.questions[i];
IF q = NIL THEN RETURN;
PrintQuery[q.name, q.type, q.class, log];
ENDLOOP;
};
PrintQuery: PROC [name: ROPE, type: ArpaNameQuery.QType, class: ArpaNameQuery.QClass, log: IO.STREAM] = {
Report[log, IO.PutFR["Query Name: \"%G\", ", [rope[name]]]];
PrintQType[log, "Type: %G, ", type];
PrintQClass[log, "Class: %G\n", class];
};
PrintAnswerRRs: PROC [reply: ArpaNameQuery.Reply, log: IO.STREAM] = {
IF reply.answers = NIL THEN RETURN;
FOR i: INT IN[0..reply.anCount) DO
an: ArpaNameQuery.ResourceRecord ← reply.answers[i];
IF an = NIL THEN RETURN;
PrintRR[an, log];
ENDLOOP;
};
PrintAuthorityRRs: PROC [reply: ArpaNameQuery.Reply, log: IO.STREAM] = {
IF reply.authority = NIL THEN RETURN;
FOR i: INT IN[0..reply.nsCount) DO
ns: ArpaNameQuery.ResourceRecord ← reply.authority[i];
IF ns = NIL THEN RETURN;
PrintRR[ns, log];
ENDLOOP;
};
PrintAdditionalRRs: PROC [reply: ArpaNameQuery.Reply, log: IO.STREAM] = {
IF reply.additional = NIL THEN RETURN;
FOR i: INT IN[0..reply.arCount) DO
ar: ArpaNameQuery.ResourceRecord ← reply.additional[i];
IF ar = NIL THEN RETURN;
PrintRR[ar, log];
ENDLOOP;
};
PrintRR: PROC [thisRR: ArpaNameQuery.ResourceRecord, log: IO.STREAM] = {
OPEN ArpaNameQuery;
name: ROPE ← thisRR.name;
type: RRType ← thisRR.type;
class: RRClass ← thisRR.class;
ttl: ArpaNameQuery.Seconds ← thisRR.ttl;
rDataLength: CARDINAL ← thisRR.dataLength;
Report[log, IO.PutFR["RR Name: \"%G\", ", [rope[name]]]];
PrintRRType[log, "Type: %G, ", type];
PrintRRClass[log, "Class: %G", class];
Report[log, ".\n"];
Report[log, IO.PutFR[" TTL: %G, ", [cardinal[ttl]]]];
Report[log, IO.PutFR["RDataLength: %G", [integer[rDataLength]]]];
WITH thisRR SELECT FROM
rr: ARR => {
IF rDataLength = 4 THEN {
rope: ROPE ← ConvertExtras.RopeFromArpaAddress[rr.address];
IO.PutF[log, " Addr: %G\n", [rope[rope]]]; }
ELSE {
Report[log, "Funny Length for type A.\n"]; }; };
rr: NsRR =>
IO.PutF[log, " Server is \"%G\".\n", [rope[rr.serverRope]]];
rr: MdRR =>
IO.PutF[log, " Mail Host is \"%G\".\n", [rope[rr.mdRope]]];
rr: MfRR =>
IO.PutF[log, " Forwarding Host is \"%G\".\n", [rope[rr.mfRope]]];
rr: CNameRR =>
IO.PutF[log, " Alias for \"%G\".\n", [rope[rr.cNameRope]]];
rr: SoaRR => {
IO.PutRope[log, "\n"];
IO.PutF[log, " Primary server is \"%G\".\n", [rope[rr.soaRec.primaryServer]]];
IO.PutF[log, " Contact is \"%G\".\n", [rope[rr.soaRec.domainContact]]];
IO.PutF[log, " Serial: %G", [cardinal[rr.soaRec.serial]]];
IO.PutF[log, ", Refresh: %G", [cardinal[rr.soaRec.refresh]]];
IO.PutF[log, ", Retry: %G", [cardinal[rr.soaRec.retry]]];
IO.PutF[log, ", Expire: %G", [cardinal[rr.soaRec.expire]]];
IO.PutF[log, ", Min TTL: %G\n", [cardinal[rr.soaRec.minTtl]]]; };
rr: MbRR =>
IO.PutF[log, " Mail Host \"%G\".\n", [rope[rr.mbRope]]];
rr: MgRR =>
IO.PutF[log, " Member is \"%G\".\n", [rope[rr.mgRope]]];
rr: MrRR =>
IO.PutF[log, " New Name is \"%G\".\n", [rope[rr.mrRope]]];
rr: WksRR => {
rope: ROPE ← ConvertExtras.RopeFromArpaAddress[rr.wksRec.address];
IO.PutF[log, " Addr: %G\n", [rope[rope]]];
IO.PutF[log, " Protocol: %G, Ports: ", [integer[rr.wksRec.protocol]]];
FOR i: INT IN [0..rr.wksRec.nPorts) DO
IO.PutF[log, " %G ", [integer[rr.wksRec.ports[i]]]];
ENDLOOP;
IO.PutRope[log, "\n"]; };
rr: PtrRR =>
IO.PutF[log, " PTR is \"%G\".\n", [rope[rr.ptrRope]]];
rr: HinfoRR => {
IO.PutF[log, " CPU: %G, OS: %G.\n", [rope[rr.hinfoRec.cpu]], [rope[rr.hinfoRec.os]]];};
rr: MinfoRR => {
IO.PutF[log, " List owner: %G, Errors-To: %G.\n", [rope[rr.minfoRec.rmailbx]], [rope[rr.minfoRec.emailbx]]];};
rr: MxRR => {
IO.PutF[log, " Preference Value: %G,", [cardinal[rr.mxRec.preference]]];
IO.PutF[log, " Host Name: \"%G\".\n", [rope[rr.mxRec.host]]]};
ENDCASE => {
IO.PutRope[log, ", Unknown Type.\n"]; };
};
PrintQType: PROC [
log: IO.STREAM, arg: ROPE, type: ArpaNameQuery.QType] = {
text: ROPESELECT type FROM
a => "a",
ns => "ns",
md => "md",
mf => "mf",
cName => "cName",
soa => "soa",
mb => "mb",
mg => "mg",
mr => "mr",
null => "null",
wks => "wks",
ptr => "ptr",
hinfo => "hinfo",
minfo => "minfo",
mx => "mx",
axfr => "axfr",
mailb => "mailb",
maila => "maila",
star => "*",
ENDCASE => " * Unknown Query Type *";
IO.PutF[log, arg, [rope[text]]]; };
PrintQClass: PROC [
log: IO.STREAM, arg: ROPE, class: ArpaNameQuery.QClass] = {
text: ROPESELECT class FROM
in => "in",
cs => "cs",
ch => "ch",
star => "*",
ENDCASE => " * Unknown Query Class *";
IO.PutF[log, arg, [rope[text]]]; };
PrintRRType: PROC [
log: IO.STREAM, arg: ROPE, type: ArpaNameQuery.RRType] = {
text: ROPESELECT type FROM
a => "a",
ns => "ns",
md => "md",
mf => "mf",
cName => "cName",
soa => "soa",
mb => "mb",
mg => "mg",
mr => "mr",
null => "null",
wks => "wks",
ptr => "ptr",
hinfo => "hinfo",
minfo => "minfo",
mx => "mx",
ENDCASE => " * Unknown RR Type *";
IO.PutF[log, arg, [rope[text]]]; };
PrintRRClass: PROC [
log: IO.STREAM, arg: ROPE, class: ArpaNameQuery.RRClass] = {
text: ROPESELECT class FROM
in => "in",
cs => "cs",
ch => "ch",
ENDCASE => " * Unknown RR Class *";
IO.PutF[log, arg, [rope[text]]]; };
MakeRule: PROC [parent, sibling: Viewer] RETURNS [child: Viewer] = {
child ← Rules.Create[
info: [parent: parent, border: FALSE,
wy: IF sibling = NIL THEN 0 ELSE sibling.wy + sibling.wh + 2, wx: 0, ww: parent.ww, wh: 1],
paint: FALSE ];
Containers.ChildXBound[parent, child]; };
MakeButton: PROC [parent, sibling: Viewer, data: REF ANY, name: ROPE, proc: Buttons.ButtonProc] RETURNS[child: Viewer] = {
child ← Buttons.Create[
info: [name: name, parent: parent, border: TRUE,
wy: sibling.wy, wx: sibling.wx + buttonWidth - 1, ww: buttonWidth],
proc: proc,
clientData: data,
fork: TRUE,
paint: FALSE]; };
SelectorProc: TYPE = PROC [parent: Viewer, clientData: REF, value: ATOM];
Selector: TYPE = REF SelectorRec;
SelectorRec: TYPE = RECORD [
value: REF ATOM,
change: PROC [parent: Viewer, clientData: REF, value: ATOM],
clientData: REF,
buttons: LIST OF Buttons.Button,
values: LIST OF ATOM ];
MakeSelector: PROC [parent, sibling: Viewer, clientData: REFNIL, values: LIST OF ATOM, name: ROPE, init: REF ATOMNIL, change: SelectorProc ← NIL] RETURNS [child: Viewer] = {
selector: Selector ← NEW [SelectorRec ← [
value: IF init # NIL THEN init ELSE NEW [ATOM ← values.first],
change: change,
clientData: clientData,
buttons: NIL,
values: values ] ];
last: LIST OF Buttons.Button ← NIL;
child ← Labels.Create[info: [name: name, parent: parent, border: FALSE, wx: sibling.wx + buttonWidth - 1, wy: sibling.wy] ];
FOR a: LIST OF ATOM ← values, a.rest UNTIL a = NIL DO
child ← Buttons.Create[
info: [name: Atom.GetPName[a.first], parent: parent, border: TRUE, wx: child.wx + child.ww + 2, wy: child.wy],
proc: SelectorHelper, clientData: selector, fork: TRUE, paint: TRUE];
IF last = NIL THEN last ← selector.buttons ← LIST[child]
ELSE { last.rest ← LIST[child]; last ← last.rest };
IF a.first = selector.value^ THEN Buttons.SetDisplayStyle[child, $WhiteOnBlack];
ENDLOOP; };
SelectorHelper: Buttons.ButtonProc = {
parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL
self: Buttons.Button = NARROW[parent];
selector: Selector = NARROW[clientData];
buttons: LIST OF Buttons.Button ← selector.buttons;
FOR a: LIST OF ATOM ← selector.values, a.rest UNTIL a = NIL DO
IF self = buttons.first THEN {
selector.value^ ← a.first;
IF selector.change # NIL THEN selector.change[self.parent, selector.clientData, a.first];
Buttons.SetDisplayStyle[buttons.first, $WhiteOnBlack]; }
ELSE Buttons.SetDisplayStyle[buttons.first, $BlackOnWhite];
buttons ← buttons.rest;
ENDLOOP; };
BoolProc: TYPE = PROC [parent: Viewer, clientData: REF, value: BOOL];
Bool: TYPE = REF BoolRec;
BoolRec: TYPE = RECORD [
value: REF BOOL,
change: BoolProc,
clientData: REF,
button: Viewer ];
MakeBool: PROC
[parent, sibling: Viewer, clientData: REFNIL, name: ROPE, init: REF BOOLNIL, change: BoolProc ← NIL]
RETURNS [child: Viewer] = {
bool: Bool ← NEW [BoolRec ← [
value: IF init = NIL THEN NEW [BOOLFALSE] ELSE init,
change: change,
clientData: clientData,
button: NIL ] ];
child ← Buttons.Create[
info: [name: name, parent: parent, border: TRUE, wx: sibling.wx + buttonWidth - 1, wy: sibling.wy, ww: buttonWidth],
proc: BoolHelper, clientData: bool, fork: TRUE, paint: TRUE];
bool.button ← child;
IF bool.value^ THEN Buttons.SetDisplayStyle[child, $WhiteOnBlack]; };
BoolHelper: Buttons.ButtonProc = {
parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL
self: Buttons.Button = NARROW[parent];
bool: Bool = NARROW[clientData];
bool.value^ ← ~bool.value^;
IF bool.value^ THEN Buttons.SetDisplayStyle[bool.button, $WhiteOnBlack]
ELSE Buttons.SetDisplayStyle[bool.button, $BlackOnWhite];
IF bool.change # NIL THEN bool.change[self.parent, bool.clientData, bool.value^]; };
MakeLabel: PROC [parent, sibling: Viewer, name: ROPE] RETURNS [child: Viewer] = {
child ← Labels.Create[
info: [name: name, parent: parent, border: FALSE,
wy: sibling.wy + sibling.wh + (IF sibling.class.flavor = $Button THEN -1 ELSE 2),
wx: 2],
paint: FALSE ]; };
MakeLabeledText: PROC [
parent, sibling: Viewer, name, data: ROPE, prev: Viewer, newline: BOOLTRUE] RETURNS [child: Viewer] = {
x: INTEGER = IF newline THEN 2 ELSE sibling.wx + sibling.ww + 10;
y: INTEGER = IF newline THEN sibling.wy + sibling.wh + 1 ELSE sibling.wy;
child ← ViewerTools.MakeNewTextViewer[
info: [parent: parent, wh: buttonHeight, ww: 999, scrollable: TRUE,
data: IF prev = NIL THEN data ELSE ViewerTools.GetContents[prev],
border: FALSE,
wx: x + buttonWidth + 2, wy: y],
paint: FALSE ];
Containers.ChildXBound[parent, child];
[] ← Buttons.Create[
info: [name: name, parent: parent, wh: buttonHeight, border: FALSE, wx: x, wy: y],
proc: LabeledTextProc, clientData: child, fork: FALSE, paint: FALSE];
RETURN[child]; };
LabeledTextProc: Buttons.ButtonProc = {
parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL
text: Viewer = NARROW[clientData];
SELECT mouseButton FROM
red => ViewerTools.SetSelection[text, NIL];
yellow => NULL;
blue => { ViewerTools.SetContents[text, NIL]; ViewerTools.SetSelection[text, NIL] };
ENDCASE => ERROR; };
Commander.Register["ArpaNameTool", Create, "Probe Arpa Name Servers."];
END.