Copyright (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
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] ~ {
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.
RETURN IPQueue.CreateIPHandle[requestData]; -- Do this in a monitor.
};
DestroyIPHandle: PUBLIC PROC [handle: InternetHandle] ~ {
Removes the request and flushes all waiting datagrams.
IPQueue.DestroyIPHandle[handle]; -- Do in the monitor
};
Send: PUBLIC PROC [handle: InternetHandle, data: Datagram] ~ {
Fills in header of datagram from the handle and sends it.
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] ~ {
Sends a datagram whose header has already been filled in.
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] ~ {
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.
RETURN IPQueue.Receive[handle, timeout];
};
PrintDatagram: PUBLIC PROC [s: IO.STREAM, data: IPDefs.Datagram] = {
Print a representation of the datagram on the stream.
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.