DIRECTORY Basics USING [BITNOT, HighHalf, LowHalf], BasicTime USING [GMT, Now, Period], CommBuffer USING [], CommDriver USING [Buffer, GetNetworkChain, InsertReceiveProc, Network, RecvProc], CommDriverType USING [Encapsulation], IPDefs USING [Datagram, DatagramRec, Address, InternetHeader, maxDataLength, maxOptionLength, minIHL, DByte], IPOps, IPQueue USING [QueueDatagram], IPReassembly USING [AgeFragments, Reassemble], IPRouter USING [DatagramPointer], PrincOpsUtils USING [ByteBlt], Process USING [MsecToTicks, Pause], Pup USING [Host]; IPOpsImpl: CEDAR PROGRAM IMPORTS Basics, BasicTime, CommDriver, IPQueue, IPReassembly, IPRouter, PrincOpsUtils, Process EXPORTS IPOps, CommBuffer = BEGIN OPEN IPOps; Encapsulation: PUBLIC TYPE = CommDriverType.Encapsulation; MoveBytes: PUBLIC UNSAFE PROC [toPtr: LONG POINTER, toOffset: INT, fromPtr: LONG POINTER, fromOffset: INT, length: INT] = UNCHECKED BEGIN moved: INT; to: LONG POINTER TO PACKED ARRAY [0..500) OF CHAR = LOOPHOLE[toPtr]; from: LONG POINTER TO PACKED ARRAY [0..500) OF CHAR = LOOPHOLE[fromPtr]; IF ~(length IN [0..LAST[CARDINAL]]) THEN ERROR; moved _ PrincOpsUtils.ByteBlt[[toPtr, toOffset, toOffset+length], [fromPtr, fromOffset, fromOffset+length]]; IF length # moved THEN ERROR; END; UnsafeHeaderChecksum: UNSAFE PROC [header: LONG POINTER TO IPDefs.InternetHeader] RETURNS [checksum: IPDefs.DByte] ~ UNCHECKED { p: LONG POINTER TO CARDINAL _ LOOPHOLE[header]; maxHeaderLength: INT ~ 10 + IPDefs.maxOptionLength / 2; nWords: INT ~ MIN[header.IHL, maxHeaderLength]; cs: CARDINAL _ OnesComplementAddBlock[ptr: p, count: 2*nWords, initialSum: Basics.BITNOT[header.checksum]]; -- Start with negative of the checksum that's in the header so that we don't have to smash it to zero to compute the real checksum. RETURN [Basics.BITNOT[cs]]; -- return one's complement of computed sum }; HeaderChecksum: PUBLIC PROC [data: IPDefs.Datagram] RETURNS [checksum: IPDefs.DByte] ~ TRUSTED { RETURN UnsafeHeaderChecksum[@data.inHdr]; }; ChecksumsMatch: PROC [c1, c2: IPDefs.DByte] RETURNS [BOOL] ~ { RETURN [c1 = c2 OR ((c1 = 0 OR c1 = 65535) AND (c2 = 0 OR c2 = 65535))]; }; OnesComplementAddBlock: PUBLIC UNSAFE PROC [ptr: LONG POINTER, count: CARDINAL, initialSum: CARDINAL _ 0] RETURNS [sum: CARDINAL] ~ UNCHECKED { p: LONG POINTER TO ARRAY [0..8) OF CARDINAL _ LOOPHOLE[ptr]; s: LONG CARDINAL _ initialSum; FOR i: CARDINAL IN [0..count MOD 8) DO s _ s + p[i]; ENDLOOP; p _ p+count MOD 8; THROUGH [0..count/8) DO s _ s + LONG[p[0]] + LONG[p[1]] + LONG[p[2]] + LONG[p[3]] + LONG[p[4]] + LONG[p[5]] + LONG[p[6]] + LONG[p[7]]; p _ p+8; ENDLOOP; WHILE Basics.HighHalf[s]#0 DO s _ LONG[Basics.HighHalf[s]]+LONG[Basics.LowHalf[s]]; ENDLOOP; RETURN[Basics.LowHalf[s]]; }; Send: PUBLIC PROC [etherDest: Pup.Host, buffer: CommDriver.Buffer, bytes: CARDINAL] = { buffer.ovh.encap _ Encapsulation[ethernetOne [etherSpare1:, etherSpare2:, etherSpare3:, etherSpare4:, etherSpare5:, ethernetOneDest: etherDest, ethernetOneSource: network.pup.host, ethernetOneType: toImp]]; network.other.send[network, buffer, bytes]; }; network: CommDriver.Network; -- handle on the Ethernet HandleIncomingPacket: CommDriver.RecvProc = TRUSTED BEGIN headerPtr: LONG POINTER TO IPDefs.InternetHeader; headerLength: INT; data: IPDefs.Datagram; IF buffer.ovh.encap.ethernetOneType # fromImp THEN RETURN[buffer]; headerPtr _ IPRouter.DatagramPointer[buffer]; IF headerPtr.IHL < 5 OR NOT headerPtr.packetLength IN [20..IPDefs.maxDataLength+20] OR NOT ChecksumsMatch[headerPtr.checksum, UnsafeHeaderChecksum[headerPtr]] THEN { -- bad packet RETURN [buffer]; }; data _ NEW[IPDefs.DatagramRec]; headerLength _ headerPtr.IHL*4; MoveBytes[@data.inHdr, 0, headerPtr, 0, headerLength]; MoveBytes[@data.data, 0, headerPtr, headerLength, headerPtr.packetLength-headerLength]; data.dataLength _ headerPtr.packetLength-headerLength; data.optionLength _ headerLength - IPDefs.minIHL*4; data _ IPReassembly.Reassemble[data]; IF data # NIL THEN IPQueue.QueueDatagram[data]; RETURN [buffer]; END; ipRunning: BOOL _ FALSE; timerProcess: PROCESS; TimerProc: PROC ~ { newTime, oldTime: BasicTime.GMT; oldTime _ BasicTime.Now[]; WHILE ipRunning DO Process.Pause[Process.MsecToTicks[5000]]; newTime _ BasicTime.Now[]; IPReassembly.AgeFragments[BasicTime.Period[from: oldTime, to: newTime]]; oldTime _ newTime; ENDLOOP; }; StartupIP: PROC ~ { network _ CommDriver.GetNetworkChain[]; -- Should be loop if > 1 ethernet board IF network.type # ethernetOne THEN ERROR; ipRunning _ TRUE; timerProcess _ FORK TimerProc[]; CommDriver.InsertReceiveProc[network, other, HandleIncomingPacket]; -- Tell the driver to give us incoming packets. }; StartupIP[]; END. rCopyright (C) 1983, 1984, 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. IPOpsImpl.mesa Last Edited by: HGM, October 7, 1984 6:33:26 am PDT Last Edited by: Nichols, August 16, 1983 2:06 pm Last Edited by: Taft, January 5, 1984 4:20 pm Hal Murray May 16, 1985 2:46:55 am PDT John Larson, June 4, 1986 11:28:05 pm PDT Exported Compute the header checksum for a datagram. Compute the header checksum for a datagram. Computes (efficiently) the ones-complement sum of the 16-bit words in the block [ptr .. ptr+count)^. [network: CommDriver.Network, buffer: CommDriver.Buffer, bytes: NAT] RETURNS [CommDriver.Buffer] The receiver process calls this procedure with new packets. While here, we check that the packet checksums and lengths are ok. Then we dive into the monitor to do reassembly and queueing. Crosscheck IP length with bytes above Private stuff Wakes up every so often and ages things. Κi– "cedar" style˜Icode2šœ΅™΅head™Icode™3J™0J™-J™&M™)šΟk ˜ Kšœœœ˜)Kšœ œœ˜#Kšœ œ˜Kšœ œA˜QKšœœ˜%Kšœœa˜mK˜Kšœœ˜Kšœ œ˜.Kšœ œ˜!Kšœœ ˜Kšœœ˜#Kšœœ˜K˜——šΟn œœ˜KšœW˜^Kšœ˜Kšœœ˜Kšœœœ ˜:—™šž œœœœ œœ œ œœœ œ ˜ƒKš˜Kšœœ˜ Kšœœœœœœ œœœ˜DKšœœœœœœ œœœ ˜HKš œ œœœœœ˜/Kšœl˜lKšœœœ˜Kšœ˜—šžœœœ œœœœ œ˜€K™+Kš œœœœœœ ˜/Kšœœ#˜7Kšœœœœ˜/KšœœFœΟcƒ˜οKšœ œŸ*˜FK˜—š žœœœœœ˜`K™+Kšœ#˜)Kšœ˜—šžœœœœ˜>Kš œ œ œ œ œ˜HK˜—šžœœœœœœ œœœœ œ˜K™dMšœœœœœœœœ˜