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.