<> <> <> <> <<>> DIRECTORY CommDriver USING [Buffer, Network], Endian USING [HWORD], Process USING [Detach, Pause, priorityNormal, SecondsToTicks, SetPriority, Ticks], Pup USING [allHosts, allNets, Host], PupBuffer USING [Buffer, noChecksum, RoundUpForChecksum, WordsWithoutChecksum], PupHop USING [maxHop], PupInternal USING [CaptureForwarding, ProcessGatewayInfo, ProcessGatewayRequest, Route], PupSocket USING [CreateServer, FreeBuffer, Get, SetRemoteAddress, Socket, waitForever], PupSocketBackdoor USING [ReturnErrorNoFree], PupWKS USING [gatewayInfo]; PupForwarderImpl: CEDAR MONITOR IMPORTS Process, PupBuffer, PupInternal, PupSocket, PupSocketBackdoor = { BYTE: TYPE = [0..100H); Buffer: TYPE = PupBuffer.Buffer; Network: TYPE = CommDriver.Network; TempDriverBuffer: PROC [b: Buffer] RETURNS [CommDriver.Buffer] = TRUSTED INLINE { RETURN[LOOPHOLE[b]]; }; <> socket: PupSocket.Socket; -- Overlays the one in PupRouterImpl RoutingSlurper: PROC = { socket _ PupSocket.CreateServer[ local: PupWKS.gatewayInfo, getTimeout: PupSocket.waitForever ]; PupSocket.SetRemoteAddress[socket, [Pup.allNets, Pup.allHosts, PupWKS.gatewayInfo]]; Process.SetPriority[Process.priorityNormal]; DO b: Buffer _ PupSocket.Get[socket]; SELECT b.type FROM gatewayRequest => PupInternal.ProcessGatewayRequest[b, FALSE]; gatewayInfo => IF PupInternal.ProcessGatewayInfo[b] THEN kick _ TRUE; ENDCASE => NULL; PupSocket.FreeBuffer[b]; ENDLOOP; }; kick: BOOL _ FALSE; RoutingDemon: PROC = { second: Process.Ticks = Process.SecondsToTicks[1]; Process.SetPriority[Process.priorityNormal]; DO FOR i: CARDINAL IN [0..15) UNTIL kick DO Process.Pause[2*second]; ENDLOOP; kick _ FALSE; PupInternal.ProcessGatewayRequest[NIL, FALSE]; ENDLOOP; }; RealForwarder: PROC [b: Buffer] RETURNS [Buffer] = { source: Network _ NARROW[b.ovh.network]; dest: Network; immediate: Pup.Host; old: Endian.HWORD; IF b.hopCount = PupHop.maxHop THEN { PupSocketBackdoor.ReturnErrorNoFree[b, tooManyHops, "Too many hops"]; BumpStats[source.index, 0, 0]; RETURN[b]; }; [dest, immediate] _ PupInternal.Route[b.dest]; IF dest = NIL THEN { PupSocketBackdoor.ReturnErrorNoFree[b, cantGetThere, "No route to that net"]; BumpStats[source.index, 0, 0]; RETURN[b]; }; TRUSTED { old _ (@b.hWord[0]+magicOne)^; }; <> b.hopCount _ b.hopCount.SUCC; UpdatePupChecksum[b, magicTwo, old]; b.ovh.encap _ dest.pup.getEncapsulation[dest, immediate]; dest.pup.send[dest, TempDriverBuffer[b], PupBuffer.RoundUpForChecksum[b.byteLength]]; BumpStats[source.index, dest.index, b.byteLength]; RETURN[b]; }; packetsForwarded: LONG CARDINAL _ 0; bytesForwarded: LONG CARDINAL _ 0; BumpStats: ENTRY PROC [source, dest: CARDINAL, bytes: CARDINAL] = { IF dest # 0 THEN { packetsForwarded _ packetsForwarded.SUCC; bytesForwarded _ bytesForwarded + bytes; }; }; magicOne: INTEGER = -9; -- offset for pupTransportControl magicTwo: CARDINAL = 1; UpdatePupChecksum: PROC [b: Buffer, offset: INTEGER, oldValue: WORD] = TRUSTED { words: NAT _ PupBuffer.WordsWithoutChecksum[b.byteLength]; checksumLoc: LONG POINTER TO Endian.HWORD _ @b.byteLength + words; diff: WORD; IF checksumLoc^ = PupBuffer.noChecksum THEN RETURN; diff _ OnesSub[(@b.hWord[0] + (offset + (magicOne - magicTwo)))^, oldValue]; checksumLoc^ _ OnesAdd[checksumLoc^, LeftCycle[diff, words - offset]]; }; OnesAdd: PROC [a, b: CARDINAL] RETURNS [c: CARDINAL] = INLINE { c _ a + b; IF c < a THEN c _ c + 1; IF c = 177777B THEN c _ 0; }; OnesSub: PROC [a, b: CARDINAL] RETURNS [c: CARDINAL] = INLINE { c _ a + (-b - 1); IF c < a THEN c _ c + 1; IF c = 177777B THEN c _ 0; }; LeftCycle: PROC [a, b: CARDINAL] RETURNS [c: CARDINAL] = INLINE { c _ a; THROUGH [0..(b MOD 16)) DO IF c < 100000B THEN c _ c*2 ELSE c _ c*2 + 1; ENDLOOP; }; PupInternal.CaptureForwarding[RealForwarder]; TRUSTED { Process.Detach[FORK RoutingSlurper[]]; }; TRUSTED { Process.Detach[FORK RoutingDemon[]]; }; }.