StateToRope:
PROC [state: ConnectionState]
RETURNS [stateRope: Rope.
ROPE] = {
SELECT state
FROM
closed => stateRope ← "CLS";
listen => stateRope ← "LSN";
synSent => stateRope ← "SSN";
synRcvd => stateRope ← "SRD";
established => stateRope ← "EST";
finWait1 => stateRope ← "FW1";
finWait2 => stateRope ← "FW2";
closeWait => stateRope ← "CWT";
closing => stateRope ← "CLG";
lastAck => stateRope ← "LAK";
timeWait => stateRope ← "TWT"
ENDCASE; };
PutData:
PROC [s:
IO.
STREAM, data: ArpaIP.Buffers, fudge:
BOOL] = {
cruft: INT ← 0;
length: INT ← ArpaIP.GetUserBytes[data].bodyBytes;
c: INT;
tcpDataStart: INT;
tcpHdrPtr: TCPHeaderP;
IF length <= ArpaTCPOps.tcpHdrByteLength THEN RETURN;
TRUSTED {
tcpHdrPtr ← LOOPHOLE[@data.body];
tcpDataStart ← tcpHdrPtr.dataWordOffset*4;
IF fudge
THEN {
-- Recv case ??
IF tcpHdrPtr.dataWordOffset # 5
THEN {
-- TCP Options
end: INT = tcpHdrPtr.dataWordOffset*4;
s.PutRope["Options: "];
FOR i:
INT
IN [4*5..end)
DO
c ← data.body.bytes[tcpDataStart+i];
s.PutF["%b ", IO.int[c]];
ENDLOOP;
s.PutChar['\n]; };
length ← length - tcpHdrPtr.dataWordOffset*4; }; };
IF length = 0 THEN RETURN;
FOR i:
INT
IN [0..
MIN[length,pktBytesPrinted])
DO
c ← data.body.bytes[tcpDataStart+i];
IF c
IN [40b..176b]
THEN
s.PutChar['\000 + c]
ELSE {
cruft ← cruft + 1;
IF cruft > 10 THEN { s.PutRope["(more)"]; EXIT; };
s.PutF["<%b>", IO.int[c]]; };
ENDLOOP;
s.PutChar['\n]; };
PrintTCPPacket:
PUBLIC
ENTRY
PROC [handle: ArpaTCPOps.TCPHandle, data: ArpaIP.Buffers, dir: Direction] =
TRUSTED {
Print or log TCP packets. The following information is printed for each packet:
state of Connection
Received, Sent or Retransmitted (R, S or X)
Control Flags (Urgent, Ack, Push, Reset, SYN, FIN)
Sequence number mod 100000
Ack number mod 100000
Window
length (number of bytes of TCP header and data)
source Address and Port -> Destination Address and Port
ENABLE UNWIND => NULL;
tcpHdrPtr: TCPHeaderP ← LOOPHOLE[@data.body];
ipHdr: ArpaBuf.Hdr ← LOOPHOLE[data.hdr1];
dirString, stateString, ctlString, time: Rope.ROPE;
IF pktFile = NIL AND logFile = NIL THEN RETURN;
IF ipHdr.protocol # tcp THEN RETURN;
IF addrToWatch = Arpa.nullAddress THEN RETURN;
IF addrToWatch # allAddresses AND addrToWatch # data.hdr1.dest AND addrToWatch # data.hdr1.source THEN RETURN;
time ← Convert.RopeFromTime[
from: BasicTime.Now[], start: hours, end: seconds, useAMPM: FALSE, includeZone: FALSE];
SELECT dir
FROM
fromNet => dirString ← "R";
toNet => dirString ← "S";
rexmitToNet => dirString ← "X"
ENDCASE;
IF handle =
NIL
THEN
stateString ← "CLS"
ELSE
stateString ← StateToRope[handle.state];
ctlString ← "";
IF tcpHdrPtr.urg THEN ctlString ← ctlString.Cat["U"];
IF tcpHdrPtr.ack THEN ctlString ← ctlString.Cat["A"];
IF tcpHdrPtr.psh THEN ctlString ← ctlString.Cat["P"];
IF tcpHdrPtr.rst THEN ctlString ← ctlString.Cat["R"];
IF tcpHdrPtr.syn THEN ctlString ← ctlString.Cat["S"];
IF tcpHdrPtr.fin THEN ctlString ← ctlString.Cat["F"];
IF pktFile #
NIL
THEN {
pktFile.PutChar['\n];
PutAddr[pktFile, data.hdr1.source];
pktFile.PutF[" %g -> ", IO.int[tcpHdrPtr.sourcePort]];
PutAddr[pktFile, data.hdr1.dest];
pktFile.PutF[" %g\n", IO.int[tcpHdrPtr.dstnPort]];
pktFile.PutF[" %g %g %6g ", IO.rope[stateString], IO.rope[dirString], IO.rope[ctlString]];
pktFile.PutF["%7g %7g %7g %7g\n", IO.int[Flip[tcpHdrPtr.seqNumber] MOD 100000], IO.int[Flip[tcpHdrPtr.ackNumber] MOD 100000], IO.int[tcpHdrPtr.window], IO.int[ArpaIP.GetUserBytes[data].bodyBytes]];
PutData[pktFile, data, dir = fromNet]; };
IF logFile #
NIL
THEN {
logFile.PutChar['\n];
logFile.PutF["%g ", IO.rope[time]];
PutAddr[logFile, data.hdr1.source];
logFile.PutF[" %g -> ", IO.int[tcpHdrPtr.sourcePort]];
PutAddr[logFile, data.hdr1.dest];
logFile.PutF[" %g\n", IO.int[tcpHdrPtr.dstnPort]];
logFile.PutF[" %g %g %6g ", IO.rope[stateString], IO.rope[dirString], IO.rope[ctlString]];
logFile.PutF["%7g %7g %7g %7g\n", IO.int[Flip[tcpHdrPtr.seqNumber] MOD 100000], IO.int[Flip[tcpHdrPtr.ackNumber] MOD 100000], IO.int[tcpHdrPtr.window], IO.int[ArpaIP.GetUserBytes[data].bodyBytes]];
PutData[logFile, data, dir = fromNet];
logFile.Flush[]; }; };
PrintStateChange:
PUBLIC
ENTRY
PROC [handle: ArpaTCPOps.TCPHandle, newState: ArpaTCPOps.ConnectionState] = {
Print or log state transitions.
ENABLE UNWIND => NULL;
old, new, time: Rope.ROPE;
IF pktFile = NIL AND logFile = NIL THEN RETURN;
IF addrToWatch = Arpa.nullAddress THEN RETURN;
IF addrToWatch # allAddresses AND addrToWatch # handle.foreignAddr THEN RETURN;
time ← Convert.RopeFromTime[
from: BasicTime.Now[], start: hours, end: seconds, useAMPM: FALSE, includeZone: FALSE];
old ← StateToRope[handle.state];
new ← StateToRope[newState];
IF pktFile #
NIL
THEN {
pktFile.PutChar['\n];
pktFile.PutF["[ME] %g <-> ", IO.int[handle.localPort]];
PutAddr[pktFile, handle.foreignAddr];
pktFile.PutF[" %g", IO.int[handle.foreignPort]];
pktFile.PutF[" %g -> %g\n", IO.rope[old], IO.rope[new]]; };
IF logFile #
NIL
THEN {
logFile.PutF["\n%g ", IO.rope[time]];
logFile.PutF["[ME] %g <-> ", IO.int[handle.localPort]];
PutAddr[logFile, handle.foreignAddr];
logFile.PutF[" %g", IO.int[handle.foreignPort]];
logFile.PutF[" %g -> %g\n", IO.rope[old], IO.rope[new]];
logFile.Flush[]; }; };
PrintMessageWithSrc:
PUBLIC
ENTRY
PROC [r: Rope.
ROPE, sourceAddr: Arpa.Address] = {
ENABLE UNWIND => NULL;
IF pktFile = NIL AND logFile = NIL THEN RETURN;
IF addrToWatch = Arpa.nullAddress THEN RETURN;
IF addrToWatch # allAddresses AND addrToWatch # sourceAddr THEN RETURN;
IF pktFile # NIL THEN pktFile.PutF["%g, source: %g\n", IO.rope[r], IO.rope[ConvertExtras.RopeFromArpaAddress[sourceAddr]]];
IF logFile # NIL THEN { logFile.PutF["%g, source: %g\n", IO.rope[r], IO.rope[ConvertExtras.RopeFromArpaAddress[sourceAddr]]]; logFile.Flush[]; };
};