<> <> <> DIRECTORY Driver USING [Buffer, Network, NoThankYou, RecvInterceptor, RecvProc, RecvType, SendInterceptor, SendProc, SendType], Process USING [Pause]; DriverInterceptImpl: CEDAR MONITOR IMPORTS Driver, Process EXPORTS Driver = { Buffer: TYPE = Driver.Buffer; Network: TYPE = Driver.Network; networks: Network _ NIL; numberOfNetworks: CARDINAL _ 0; defaultRecvProcs: ARRAY Driver.RecvType OF Driver.RecvProc _ ALL[Driver.NoThankYou]; GetNetworkChain: PUBLIC PROC RETURNS [Network] = { RETURN[networks]; }; GetNumberOfNetworks: PUBLIC PROC RETURNS [CARDINAL] = { RETURN[numberOfNetworks]; }; AddNetwork: PUBLIC ENTRY PROC [network: Network] = { IF network.next # NIL THEN ERROR; network.ip.recv _ defaultRecvProcs[ip]; network.ip.recvTranslate _ defaultRecvProcs[ipTranslate]; network.ns.recv _ defaultRecvProcs[ns]; network.ns.recvTranslate _ defaultRecvProcs[nsTranslate]; network.pup.recv _ defaultRecvProcs[pup]; network.pup.recvTranslate _ defaultRecvProcs[pupTranslate]; network.other.recv _ defaultRecvProcs[other]; network.other.recvTranslate _ defaultRecvProcs[otherTranslate]; network.error.recv _ defaultRecvProcs[error]; IF networks = NIL THEN networks _ network ELSE { FOR finger: Network _ networks, finger.next DO IF finger.next # NIL THEN LOOP; finger.next _ network; EXIT; ENDLOOP; }; numberOfNetworks _ numberOfNetworks + 1; network.index _ numberOfNetworks; }; InsertReceiveProc: PUBLIC ENTRY PROC [ network: Network, -- NIL => all networks type: Driver.RecvType, proc: Driver.RecvProc] = { ENABLE UNWIND => NULL; IF network # NIL THEN { InsertReceiveInner[network, type, proc]; RETURN; }; FOR network: Network _ networks, network.next UNTIL network = NIL DO InsertReceiveInner[network, type, proc]; ENDLOOP; defaultRecvProcs[type] _ proc; -- only if all networks }; SlotAlreadyCaptured: SIGNAL = CODE; InsertReceiveInner: INTERNAL PROC [ network: Network, type: Driver.RecvType, proc: Driver.RecvProc] = { interceptor: Interceptor _ network.interceptor; IF interceptor = NIL THEN { -- normal case, no interception in progress previous: Driver.RecvProc; SELECT type FROM ip => previous _ network.ip.recv; ipTranslate => previous _ network.ip.recvTranslate; ns => previous _ network.ns.recv; nsTranslate => previous _ network.ns.recvTranslate; pup => previous _ network.pup.recv; pupTranslate => previous _ network.pup.recvTranslate; other => previous _ network.other.recv; otherTranslate => previous _ network.other.recvTranslate; error => previous _ network.error.recv; ENDCASE => ERROR; IF previous # Driver.NoThankYou THEN SIGNAL SlotAlreadyCaptured; SELECT type FROM ip => network.ip.recv _ proc; ipTranslate => network.ip.recvTranslate _ proc; ns => network.ns.recv _ proc; nsTranslate => network.ns.recvTranslate _ proc; pup => network.pup.recv _ proc; pupTranslate => network.pup.recvTranslate _ proc; other => network.other.recv _ proc; otherTranslate => network.other.recvTranslate _ proc; error => network.error.recv _ proc; ENDCASE => ERROR; } ELSE { -- Interesting case, interception in progress procs: REF Procs _ interceptor.procs; IF procs.recv[type] # Driver.NoThankYou THEN SIGNAL SlotAlreadyCaptured; procs.recv[type] _ proc; }; }; Interceptor: TYPE = REF InterceptorRep; InterceptorRep: PUBLIC TYPE = RECORD [ next: Interceptor, alive: BOOL, procs: REF Procs, network: Network, sendMask: PACKED ARRAY Driver.SendType OF BOOL, sendProc: Driver.SendInterceptor, recvMask: PACKED ARRAY Driver.RecvType OF BOOL, recvProc: Driver.RecvInterceptor, data: REF ANY, promiscuous: BOOL ]; Procs: TYPE = RECORD [ send: ARRAY Driver.SendType OF Driver.SendProc, recv: ARRAY Driver.RecvType OF Driver.RecvProc ]; CreateInterceptor: PUBLIC ENTRY PROC [ network: Network, sendMask: PACKED ARRAY Driver.SendType OF BOOL, sendProc: Driver.SendInterceptor, recvMask: PACKED ARRAY Driver.RecvType OF BOOL, recvProc: Driver.RecvInterceptor, data: REF ANY, promiscuous: BOOL] RETURNS [interceptor: Interceptor] = { others: Interceptor _ network.interceptor; procs: REF Procs; IF others # NIL THEN procs _ others.procs ELSE procs _ NEW[Procs _ [ send: [ ip: network.ip.send, ipReturn: network.ip.return, ipTranslate: network.ip.sendTranslate, ns: network.ns.send, nsReturn: network.ns.return, nsTranslate: network.ns.sendTranslate, pup: network.pup.send, pupReturn: network.pup.return, pupTranslate: network.pup.sendTranslate, other: network.other.send, otherReturn: network.other.return, otherTranslate: network.other.sendTranslate, raw: network.raw.send], recv: [ ip: network.ip.recv, ipTranslate: network.ip.recvTranslate, ns: network.ns.recv, nsTranslate: network.ns.recvTranslate, pup: network.pup.recv, pupTranslate: network.pup.recvTranslate, other: network.other.recv, otherTranslate: network.other.recvTranslate, error: network.error.recv] ]]; interceptor _ NEW[InterceptorRep _ [ next: others, alive: TRUE, procs: procs, network: network, sendMask: sendMask, sendProc: sendProc, recvMask: recvMask, recvProc: recvProc, data: data, promiscuous: promiscuous] ]; network.interceptor _ interceptor; IF others = NIL THEN { network.ip.send _ IPSend; network.ip.return _ IPReturn; network.ip.recv _ IPRecv; network.ip.sendTranslate _ IPSendTranslate; network.ip.recvTranslate _ IPRecvTranslate; network.ns.send _ NSSend; network.ns.return _ NSReturn; network.ns.recv _ NSRecv; network.ns.sendTranslate _ NSSendTranslate; network.ns.recvTranslate _ NSRecvTranslate; network.pup.send _ PupSend; network.pup.return _ PupReturn; network.pup.recv _ PupRecv; network.pup.sendTranslate _ PupSendTranslate; network.pup.recvTranslate _ PupRecvTranslate; network.other.send _ OtherSend; network.other.return _ OtherReturn; network.other.recv _ OtherRecv; network.other.sendTranslate _ OtherSendTranslate; network.other.recvTranslate _ OtherRecvTranslate; network.raw.send _ RawSend; network.error.recv _ ErrorRecv; }; IF promiscuous THEN network.setPromiscuous[network, TRUE]; }; DestroyInterceptor: PUBLIC ENTRY PROC [interceptor: Interceptor] = { network: Network _ interceptor.network; IF ~interceptor.alive THEN RETURN; interceptor.alive _ FALSE; IF network.interceptor = interceptor THEN { IF interceptor.next = NIL THEN { procs: REF Procs _ interceptor.procs; network.setPromiscuous[network, FALSE]; <> Process.Pause[5]; network.ip.send _ procs.send[ip]; network.ip.return _ procs.send[ipReturn]; network.ip.sendTranslate _ procs.send[ipTranslate]; network.ns.send _ procs.send[ns]; network.ns.return _ procs.send[nsReturn]; network.ns.sendTranslate _ procs.send[nsTranslate]; network.pup.send _ procs.send[pup]; network.pup.return _ procs.send[pupReturn]; network.pup.sendTranslate _ procs.send[pupTranslate]; network.other.send _ procs.send[other]; network.other.return _ procs.send[otherReturn]; network.other.sendTranslate _ procs.send[otherTranslate]; network.raw.send _ procs.send[raw]; network.ip.recv _ procs.recv[ip]; network.ip.recvTranslate _ procs.recv[ipTranslate]; network.ns.recv _ procs.recv[ns]; network.ns.recvTranslate _ procs.recv[nsTranslate]; network.pup.recv _ procs.recv[pup]; network.pup.recvTranslate _ procs.recv[pupTranslate]; network.other.recv _ procs.recv[other]; network.other.recvTranslate _ procs.recv[otherTranslate]; network.error.recv _ procs.recv[error]; }; network.interceptor _ interceptor.next; } ELSE { first: Interceptor _ network.interceptor; FOR finger: Interceptor _ first, finger.next DO -- NIL fault if not found IF finger.next # interceptor THEN LOOP; finger.next _ interceptor.next; EXIT; ENDLOOP; }; }; IPSend: Driver.SendProc = { SendOne[ip, network, buffer, bytes]; }; IPReturn: Driver.SendProc = { SendOne[ipReturn, network, buffer, bytes]; }; IPSendTranslate: Driver.SendProc = { SendOne[ipTranslate, network, buffer, bytes]; }; NSSend: Driver.SendProc = { SendOne[ns, network, buffer, bytes]; }; NSReturn: Driver.SendProc = { SendOne[nsReturn, network, buffer, bytes]; }; NSSendTranslate: Driver.SendProc = { SendOne[nsTranslate, network, buffer, bytes]; }; PupSend: Driver.SendProc = { SendOne[pup, network, buffer, bytes]; }; PupReturn: Driver.SendProc = { SendOne[pupReturn, network, buffer, bytes]; }; PupSendTranslate: Driver.SendProc = { SendOne[pupTranslate, network, buffer, bytes]; }; OtherSend: Driver.SendProc = { SendOne[other, network, buffer, bytes]; }; OtherReturn: Driver.SendProc = { SendOne[otherReturn, network, buffer, bytes]; }; OtherSendTranslate: Driver.SendProc = { SendOne[otherTranslate, network, buffer, bytes]; }; RawSend: Driver.SendProc = { SendOne[raw, network, buffer, bytes]; }; SendOne: PROC [send: Driver.SendType, network: Network, buffer: Buffer, bytes: NAT] = { first: Interceptor _ network.interceptor; kill: BOOL _ FALSE; IF first = NIL THEN RETURN; -- Race with DeleteInterceptor FOR interceptor: Interceptor _ first, interceptor.next UNTIL interceptor = NIL DO IF ~interceptor.sendMask[send] THEN LOOP; kill _ kill OR interceptor.sendProc[send, interceptor.data, network, buffer, bytes]; ENDLOOP; IF kill THEN RETURN; first.procs.send[send][network, buffer, bytes]; }; IPRecv: Driver.RecvProc = { RETURN[RecvOne[ip, network, buffer, bytes]]; }; IPRecvTranslate: Driver.RecvProc = { RETURN[RecvOne[ipTranslate, network, buffer, bytes]]; }; NSRecv: Driver.RecvProc = { RETURN[RecvOne[ns, network, buffer, bytes]]; }; NSRecvTranslate: Driver.RecvProc = { RETURN[RecvOne[nsTranslate, network, buffer, bytes]]; }; PupRecv: Driver.RecvProc = { RETURN[RecvOne[pup, network, buffer, bytes]]; }; PupRecvTranslate: Driver.RecvProc = { RETURN[RecvOne[pupTranslate, network, buffer, bytes]]; }; OtherRecv: Driver.RecvProc = { RETURN[RecvOne[other, network, buffer, bytes]]; }; OtherRecvTranslate: Driver.RecvProc = { RETURN[RecvOne[otherTranslate, network, buffer, bytes]]; }; ErrorRecv: PROC [network: Network, buffer: Buffer, bytes: NAT] RETURNS [Buffer] = { RETURN[RecvOne[error, network, buffer, bytes]]; }; RecvOne: PROC [recv: Driver.RecvType, network: Network, buffer: Buffer, bytes: NAT] RETURNS [Buffer] = { first: Interceptor _ network.interceptor; forMe: BOOL _ network.isThisForMe[network, buffer]; kill: BOOL _ FALSE; IF first = NIL THEN RETURN[buffer]; -- Race with DeleteInterceptor FOR interceptor: Interceptor _ first, interceptor.next UNTIL interceptor = NIL DO IF ~interceptor.recvMask[recv] THEN LOOP; IF ~forMe AND ~interceptor.promiscuous THEN LOOP; kill _ kill OR interceptor.recvProc[recv, interceptor.data, network, buffer, bytes]; ENDLOOP; IF kill THEN RETURN[buffer]; IF ~forMe THEN RETURN[buffer]; RETURN[first.procs.recv[recv][network, buffer, bytes]]; }; }.