// PeekEther.bcpl -- Peek stuff that needs to deal with the // Ether interface at level 0. // Copyright Xerox Corporation 1979 // Last modified March 14, 1982 8:12 PM by Boggs get "Pup0.decl" get "PupAlEth.decl" get "Pup1.decl" get "Streams.d" get "AltoDefs.d" external [ // outgoing procedures CreatePeekServ; CreateEtherEchoer // incoming procedures CreateDisplayStream; MyShowDisplayStream; MakeBar InitializeContext; Block; Enqueue; Dequeue Allocate; CallSwat; SetBlock; EtherPupFilter OpenFile; Puts; Closes; FileLength PutTemplate; WRITEUDT; Wss; LoadRam; StartIO // incoming statics ctxQ; sysZone; sysFont; ndbQ quitFlag; quitCount; pbiFreeQ PeekEther1Mc; PeekEther2Mc; lvUserFinishProc ] static [ ourHostAddress; savedUFP ] manifest [ black = -1 peekHost = 376b peekTypeDMT = 1 etPeekReport = 402b etEchoMe = 700b etImAnEcho = 701b ] structure PeekPBI: [ @EtherPBI peekType word contents↑0,1 word ] //---------------------------------------------------------------------------- let CreatePeekServ(fileName) be //---------------------------------------------------------------------------- [ ourHostAddress = StartIO(0) & 377b // Try to load special version of Ethernet microcode which accepts // packets to host 376b in addition to the standard filtering rules. let mcOK = LoadRam((table [ 61014b; 1401b ])()<<VERS.eng le 1? PeekEther1Mc, PeekEther2Mc, true) eq 0 if mcOK then [ savedUFP = @lvUserFinishProc @lvUserFinishProc = PeekEtherUFP ] let ctx = InitializeContext(Allocate(sysZone, 1000), 1000, PeekServ, 4) let ndb = ndbQ!0; while ndb ne 0 do [ if ndb>>NDB.netType eq netTypeEther then [ let pf = Allocate(sysZone, lenPF) pf>>PF.predicate = PeekPacketFilter pf>>PF.queue = ctx+5 // the IQ is in the extension to the ctx Enqueue(lv ndb>>NDB.pfQ, pf) unless mcOK do // if failed to load microcode then filter in software [ pf = ndb>>NDB.pfQ.head; while pf ne 0 do [ if pf>>PF.predicate eq EtherPupFilter then [ pf>>PF.predicate = SpecialPupFilter @(ndb>>EtherNDB.eHLoc) = 0 // promiscuous ] pf = pf>>PF.link ] ] ] ndb = ndb>>NDB.link ] // make a display window let dsp = CreateDisplayStream(20, Allocate(sysZone, 5000), 5000, sysFont) MyShowDisplayStream(dsp) MyShowDisplayStream(MakeBar(black, 1)) // set up a split stream to disk and display let st = Allocate(sysZone, lST); SetBlock(st, CallSwat, lST) st>>ST.par2 = dsp st>>ST.puts = PeekPuts let file = OpenFile(fileName, ksTypeWriteOnly, charItem) st>>ST.par1 = file ctx!3 = file ctx!4 = st ctx!5 = 0 // ctx!5 & 6 used as Peek IQ Enqueue(ctxQ, ctx) unless mcOK do Wss(st, "*N Failed to load microcode: using software packet filter") ] //---------------------------------------------------------------------------- and PeekServ(ctx) be //a context //---------------------------------------------------------------------------- // ctx!3 is the file stream // ctx!4 is the split stream // ctx!5 is the raw Ether input queue [ let file = ctx!3 let split = ctx!4 let iq = ctx+5 quitCount = quitCount +1 FileLength(file) //positions to the end of file quickly PutTemplate(split, "*N Peeking started at $P*N", WRITEUDT, 0) [ Block() repeatuntil iq!0 ne 0 % quitFlag if quitFlag break let pbi = Dequeue(iq) PutTemplate(split,"*N$UO#$3UF0O# $S", pbi>>PBI.ndb>>NDB.localNet, pbi>>PeekPBI.src, lv pbi>>PeekPBI.contents) Enqueue(pbiFreeQ, pbi) ] repeat PutTemplate(split, "*N Peeking stopped at $P*N", WRITEUDT, 0) // clean up in preparation for finishing Closes(file) quitCount = quitCount -1 // returning from a context does an implicit Block() ] //---------------------------------------------------------------------------- and SpecialPupFilter(pbi) = //---------------------------------------------------------------------------- (pbi>>EtherPBI.dest eq ourHostAddress % pbi>>EtherPBI.dest eq 0) & (pbi>>PBI.pup.length+5) rshift 1 eq pbi>>PBI.packetLength & pbi>>EtherPBI.type eq typePup //---------------------------------------------------------------------------- and PeekPacketFilter(pbi) = //---------------------------------------------------------------------------- pbi>>PeekPBI.dest eq peekHost & pbi>>PeekPBI.src ne 0 & pbi>>PeekPBI.type eq etPeekReport & pbi>>PeekPBI.peekType eq peekTypeDMT //---------------------------------------------------------------------------- and PeekEtherUFP() be //---------------------------------------------------------------------------- [ (table [ 61010b; 1401b ])(177776b, 1) // BootLocusVector ← 177776b StartIO(100000b) // Flip ether task back into the Rom @lvUserFinishProc = savedUFP ] //---------------------------------------------------------------------------- and PeekPuts(stream, item) be //a stream splitter //---------------------------------------------------------------------------- [ Puts(stream>>ST.par1, item) Puts(stream>>ST.par2, item) ] //---------------------------------------------------------------------------- and CreateEtherEchoer() be //---------------------------------------------------------------------------- [ ourHostAddress = StartIO(0) & 377b let ctx = InitializeContext(Allocate(sysZone, 200), 200, RawEtherEchoer, 2) ctx!3 = 0 // ctx!3 & 4 used as Echo IQ Enqueue(ctxQ, ctx) // set up an Ether packet filter for raw Ether Echo packets let ndb = ndbQ!0; while ndb ne 0 do [ if ndb>>NDB.netType eq netTypeEther then [ let pf = Allocate(sysZone, lenPF) pf>>PF.predicate = RawEtherEchoFilter pf>>PF.queue = ctx+3 Enqueue(lv ndb>>NDB.pfQ, pf) ] ndb = ndb>>NDB.link ] ] //---------------------------------------------------------------------------- and RawEtherEchoer(ctx) be //a context //---------------------------------------------------------------------------- [ let iq = ctx+3 Block() repeatwhile iq!0 eq 0 let pbi = Dequeue(iq) pbi>>EtherPBI.dest = pbi>>EtherPBI.src pbi>>EtherPBI.src = ourHostAddress pbi>>EtherPBI.type = etImAnEcho pbi>>PBI.queue = pbiFreeQ (pbi>>PBI.ndb>>NDB.level0Transmit)(pbi) ] repeat //---------------------------------------------------------------------------- and RawEtherEchoFilter(pbi) = //---------------------------------------------------------------------------- pbi>>EtherPBI.dest eq ourHostAddress & pbi>>EtherPBI.src ne 0 & pbi>>EtherPBI.type eq etEchoMe