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. dCopyright (C) 1983, 1985 by Xerox Corporation. All rights reserved. The following program was created in 1983 but has not been published within the meaning of the copyright law, is furnished under license, and may not be used, copied and/or disclosed except in accordance with the terms of said license. IPMain.mesa Last Edited by: Nichols, August 16, 1983 11:35 am Last Edited by: Taft, January 5, 1984 5:10 pm John Larson, April 14, 1986 9:30:57 pm PST Hal Murray June 27, 1985 0:24:57 am PDT Add a new request for incoming packets. Returns a handle on the Internet. If the reqest conflicts with an existing one, then CreateIPHandle returns NIL. Removes the request and flushes all waiting datagrams. Fills in header of datagram from the handle and sends it. Sends a datagram whose header has already been filled in. Waits for a datagram that matches the request that was used to create the handle. Returns the datagram or NIL if timeout milliseconds (?) pass with no packet arriving. A value of neverTimeout for timeout will cause Receive to wait forever. Print a representation of the datagram on the stream. สZ– "cedar" style˜Icode2šœฏ™ฏhead™ Icode™1J™-M™*M™'šฯk ˜ Kšœœ1œ˜AKšœ˜Kšœœ˜%Kšœœ,˜9Kšœ œ˜ Kšœ œ˜Kšœœ ˜Kšœœ ˜Kšœœœ˜——šฯnœœ˜Kšœœ(˜2Kšœ˜Kšœœœ˜Kšžœœœœ˜-Kšœ œฯc˜:šžœœœœ˜[Kšœžœ œ™šKšœ'Ÿ˜EK˜—šžœœœ˜9K™6Kšœ!Ÿ˜5K˜—šžœœœ-˜>K™9Kšœ ˜Kšœ˜Kšœ ˜ Kšœ˜Kšœ˜Kšœœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜K˜K˜—šž œœœ˜.K™9Kšœœ˜Kšœœ˜K˜KšœC˜CKšœ.˜.K˜Kšœ œ˜"Kšœ'˜'Kšœ7Ÿ+˜bKšœœ˜!K˜K˜K˜Kšœ1˜1Kšœ˜K˜—š žœœœ#œœ˜gKšœูžœ™๑Kšœ"˜(K˜—š ž œœœœœ˜DK™5šžœœœœ˜6Kš œœœœœ˜_—š žœœœœœ˜5šœœ˜Kšœ!˜!Kšœ˜Kšœ˜Kšœœ˜—Kšœh˜h—šœ˜%KšœBœ!œ!˜ˆ—Kšœ:œœœœ œœœ,˜ึKšœ˜šœ˜šœœ˜ Kš œœœœœ œ ˜:Kš œDœœœœœ˜ฎ—šœœ˜Kš œœœœœ œ ˜9Kš œ@œœœœ˜——šœ˜ š œœœœ)˜@Kšœœ œœ˜OKšœœ˜-Kšœ˜—K˜———Kšœ˜——…— ไข