<> <> <> <> <> <> DIRECTORY IO USING [bool, char, int, PutChar, PutF, PutRope, rope, STREAM], IPDefs, IPOps USING [HeaderChecksum, maxTTL], IPQueue USING [CreateIPHandle, DestroyIPHandle, Receive], IPReassembly USING [IsFragment], IPRouter USING [SendDatagram], ICMP USING [BodyRec], UDP USING [BodyRec], Rope USING [ROPE]; IPMain: CEDAR PROGRAM IMPORTS IO, IPOps, IPQueue, IPReassembly, IPRouter EXPORTS IPDefs ~ BEGIN OPEN IPDefs; Error: PUBLIC ERROR [type: Errorcode] = CODE; fragmentID: CARDINAL _ 0; -- put into outgoing datagrams. CreateIPHandle: PUBLIC PROC [requestData: RequestData] RETURNS [handle: InternetHandle] ~ { <> RETURN IPQueue.CreateIPHandle[requestData]; -- Do this in a monitor. }; DestroyIPHandle: PUBLIC PROC [handle: InternetHandle] ~ { <> IPQueue.DestroyIPHandle[handle]; -- Do in the monitor }; Send: PUBLIC PROC [handle: InternetHandle, data: Datagram] ~ { <> OPEN data.inHdr; precedence _ 0; delay _ 0; throughput _ 0; reliability _ 0; dontFragment _ FALSE; timeToLive _ IPOps.maxTTL; protocol _ handle.protocol; source _ handle.localAddress; destination _ handle.address; SendSpecific[data]; }; SendSpecific: PUBLIC PROC [data: Datagram] ~ { <> headerLength: INT; packetLength: INT; headerLength _ IPDefs.minIHL*4 + ((data.optionLength + 3) / 4) * 4; packetLength _ headerLength + data.dataLength; data.inHdr.version _ 4; data.inHdr.IHL _ headerLength / 4; data.inHdr.packetLength _ packetLength; data.inHdr.fragmentId _ (fragmentID _ fragmentID + 1); -- not synchronized, but it doesn't matter. data.inHdr.moreFragments _ FALSE; data.inHdr.fragmentOffset _ 0; data.inHdr.filler1 _ 0; data.inHdr.filler2 _ 0; data.inHdr.checksum _ IPOps.HeaderChecksum[data]; IPRouter.SendDatagram[data]; }; Receive: PUBLIC PROC [handle: InternetHandle, timeout: INT _ neverTimeout] RETURNS [data: Datagram] ~ { <> RETURN IPQueue.Receive[handle, timeout]; }; PrintDatagram: PUBLIC PROC [s: IO.STREAM, data: IPDefs.Datagram] = { <> PutAddr: PROC [s: IO.STREAM, addr: IPDefs.Address] = { s.PutF["[%g.%g.%g.%g]", IO.int[addr[0]], IO.int[addr[1]], IO.int[addr[2]], IO.int[addr[3]]]; }; LookupProtocol: PROC [p: INT] RETURNS [Rope.ROPE] = { RETURN [SELECT p FROM IPDefs.ICMPProtocol => " (ICMP)", IPDefs.TCPProtocol => " (TCP)", IPDefs.UDPProtocol => " (UDP)", ENDCASE => NIL]; }; PutAddr[s, data.inHdr.source]; s.PutRope[" -> "]; PutAddr[s, data.inHdr.destination]; s.PutChar['\n]; IF IPReassembly.IsFragment[data] THEN s.PutF[" fragment: moreFragments = %g, fragmentOffset = %g\n", IO.bool[data.inHdr.moreFragments], IO.int[data.inHdr.fragmentOffset]]; s.PutF[" IHL = %g, data length = %g, protocol = %g%g\n", IO.int[data.inHdr.IHL], IO.int[data.inHdr.packetLength - INT[data.inHdr.IHL*4]], IO.int[data.inHdr.protocol], IO.rope[LookupProtocol[data.inHdr.protocol]]]; s.PutRope[" data: "]; SELECT data.inHdr.protocol FROM IPDefs.ICMPProtocol => TRUSTED { body: LONG POINTER TO ICMP.BodyRec _ LOOPHOLE[@data.data]; s.PutF["type = %g, code = %g, checksum = %bb, id = %d, seq = %d\n", IO.int[body.type], IO.int[body.code], IO.int[body.checksum], IO.int[body.id], IO.int[body.sequenceNo]]; }; IPDefs.UDPProtocol => TRUSTED { body: LONG POINTER TO UDP.BodyRec _ LOOPHOLE[@data.data]; s.PutF["source = %g, dest = %g, length = %bb, checksum = %d\n", IO.int[body.source], IO.int[body.dest], IO.int[body.length], IO.int[body.checksum]]; }; ENDCASE => { FOR i: INT IN [0..MIN[IPDefs.maxDataLength, data.dataLength]) DO IF data.data[i] IN [40b..176b] THEN s.PutF["%c", IO.char['\000 + data.data[i]]] ELSE s.PutF["<%03bb>", IO.int[data.data[i]]]; ENDLOOP; s.PutChar['\n]; }; }; END.