.TITLE INPNET Network interface routines .SBTTL System and module definitions .NLIST BEX,CND .ENABL LC ; ; Pdp11/dcn network interface routines ; ; This module contains a number of interface subroutines called both ; by the internet process and its protocol modules and by user programs ; (by means of the rt-11 emulator). ; ; External symbols ; .GLOBL $NETID,$HOSAD,$GATPT,GATVPT ;host/gateway tables .GLOBL WOLFF ;sneaky pete ; ; Entry symbols ; .GLOBL NETIN ;input packet .GLOBL NETOT ;output packet .GLOBL NETPKT ;allocate packet .GLOBL GATE ;get net process pid .GLOBL ADRMAP,ADRGAT ;match logical address .GLOBL NETMAP ;test local net .GLOBL NETCHK ;test special address ; ; System definitions ; .ASECT .MCALL .COM ;dcnlib definitions .MCALL .FPKT,.GPKT,.UNIQ,.WIND ;dcnlib macros .MCALL $DFTCB,$DFIH,$DFTIM,$DFSIG,$DFTBL ;moslib definitions .MCALL $SGNLI ;moslib macros .COM ;define common data $DFTCB ;define connection control block $DFIH ;define internet header $DFTIM ;define timer values $DFSIG ;define interprocess signals $DFTBL ;define gateway/host table formats .PAGE ; ; Module definitions ; MAXPKT = 2 ;max packets ; .SBTTL Network interface routines ; ; Procedure segment ; .PSECT $SUPI,RO,I ; ; Process-state procedure ; Dsects: r5 = psa ; ; This module is the interface between the internet process and its ; Protocol modules and the gateway/bridge processes. it consists of ; A number of subroutines to open/close net connections, construct, ; Send and discard net packets. ; ; Netin (net) release input packet ; R1 = packet ptr, r5 = control block ptr, returns r0 = status ; NETIN: MOV R1,R0 ;is there another fragment BEQ 2$ ;branch if no MOV PH.LNK(R0),R1 ;yes. release it .FPKT DECB SNDCNT(R5) ;regain credit BR NETIN ; 2$: RTS PC ; ; Netot (net) send packet to net ; R1 = packet ptr, r5 = control block ptr, returns r0 = status (conn code) ; NETOT: MOV R2,-(SP) ;save MOV #PK.OPN,R2 ;presume guilty MOV INPCID(R5),R0 ;is connection id assigned BEQ 9$ ;branch if no MOV R1,-(SP) ;yes. preserve pointers and mapping MOV (R0)+,-(SP) MOV (R0)+,-(SP) MOV #IH.LEN,R2 ;point to options area 1$: CMP R2,PH.OFS(R1) ;are more options present BHIS 7$ ;branch if no ADD R1,R2 ;yes. scan for route options TSTB @R2 ;is this end BEQ 7$ ;branch if yes CMPB (R2)+,#1 ;no. is this no-op BEQ 2$ ;branch if yes CMPB -(R2),#203 ;no. is this loose source route BEQ 3$ ;branch if yes CMPB @R2,#211 ;no. is this strict source route BEQ 3$ ;branch if yes CLR R0 ;no. advance to next option BISB 1(R2),R0 ADD R0,R2 2$: SUB R1,R2 BR 1$ ; 3$: MOVB 1(R2),R0 ;get route pointers ADD R2,R0 ADD #7,R2 4$: CMP R2,R0 ;slide all entries up one slot BHIS 5$ MOVB -4(R2),-(SP) MOVB @R2,-4(R2) MOVB (SP)+,(R2)+ BR 4$ ; 5$: MOV R1,R0 ;exchange new last entry with destination ADD #IH.DST+4,R0 MOV #4,R1 6$: MOVB -(R0),-(SP) MOVB -(R2),@R0 MOVB (SP)+,@R2 SOB R1,6$ 7$: MOV $GATPT,R0 ;map to routing tables MOV $GATPT+2,R1 .WIND MOV 4(SP),R1 ;restore packet pointer JSR PC,GATE ;yes. unravel route MOV R0,R2 ;save pid/error code MOV (SP)+,R1 ;restore control block pointers MOV (SP)+,R0 BCS 8$ ;branch if error .WIND ;restore mapping MOV (SP)+,R1 ;send packet JSR PC,WOLFF $SGNLI R2,#SG.INP,INPPID(R5),INPCID(R5),R1,IH.ID(R1) CLR R2 ;return inoccuous status BR 10$ ; 8$: .WIND ;restore mapping MOV (SP)+,R1 ;free packet 9$: JSR PC,NETIN 10$: ASL R2 ;translate return code MOV ERRCOD(R2),R0 MOV (SP)+,R2 ;evas RTS PC ; ; Netpkt (net) allocate packet ; R5 = control block ptr, returns r0 = status, r1 = packet ptr ; Also sets ph.ofs(r1) = data offset, ph.lng(r1) = data length ; NETPKT: MOVB SNDCNT(R5),R1 ;is internal quota exceeded CMPB R1,#MAXPKT BHIS 3$ ;branch if yes MOV MAXSIZ(R5),R0 ;allocate packet buffer MUL R0,R1 .GPKT BNE 2$ ;branch if ok 3$: MOV #PK.RES,R0 ;insufficient resources RTS PC ; 2$: INCB SNDCNT(R5) ;charge packet MOV R0,R1 ;align for nethdr ; ; Nethdr (net) preset ip header and options ; R1 = packet ptr, r5 = control block ptr, returns r0 = status ; Also sets ph.ofs(r1) = data offset, ph.lng(r1) = data length ; NETHDR: MOV R2,-(SP) ;save registers MOV R1,-(SP) MOV R1,R2 ;initialize leader .UNIQ MOV R0,PH.TIM(R2) MOV R1,PH.TIM+2(R2) MOV R1,R0 CLR PH.LNK(R2) ADD #BUFLDR,R2 MOV R5,R1 ;get options pointer ADD #TYPSRV,R1 MOVB #,(R2)+ ;0 ih.ver MOVB (R1)+,(R2)+ ;1 ih.tos CLR (R2)+ ;2 ih.fl MOV R0,(R2)+ ;4 ih.id CLR (R2)+ ;6 ih.frg MOVB #TM.TTL/1000.,(R2)+ ;10 ih.ttl MOVB PROTCL(R5),(R2)+ ;11 ih.pro CLR (R2)+ ;12 ih.chk MOV LSOCK(R5),(R2)+ ;14 ih.src MOV LSOCK+2(R5),(R2)+ MOV FSOCK(R5),(R2)+ ;20 ih.dst MOV FSOCK+2(R5),(R2)+ MOVB (R1)+,R0 ;copy options BEQ 2$ 1$: MOVB (R1)+,(R2)+ SOB R0,1$ 2$: MOV (SP)+,R1 3$: MOV R2,R0 ;pad to big-endian boundary SUB R1,R0 SUB #BUFLDR,R0 BIT #3,R0 BEQ 4$ CLRB (R2)+ BR 3$ ; 4$: MOV LPORT(R5),(R2)+ ;gratuitous ports MOV FPORT(R5),(R2)+ CMP -(R2),-(R2) SUB R1,R2 ;save data offset MOV R2,PH.OFS(R1) ASR R0 ;compute header length ASR R0 BISB R0,IH.VER(R1) MOV MAXSIZ(R5),R0 ;compute data length SUB PH.OFS(R1),R0 ADD #BUFLDR,R0 BPL 5$ CLR R0 5$: MOV R0,PH.LNG(R1) ;save data length MOV (SP)+,R2 CLR R0 ;return inoccuous status RTS PC ; ; Gate (gat) get net process pid ; R1 = packet pointer, returns r0 = pid if cc(c) = 0, ; R0 = connection code if cc(c) = 1 ; GATE: MOV R2,-(SP) ;save MOV R1,-(SP) MOVB IH.TOS(R1),R0 ADD #IH.DST,R1 ;match destination address JSR PC,ADRGAT BCS 4$ ;branch if cant MOV @SP,R2 ;ok. is leader defined ADD #PH.LDR,R2 TST HOSLNA(R1) BNE 2$ ;branch if yes TST HOSLNA+2(R1) BNE 2$ ;branch if yes TST HOSLNA+4(R1) BNE 2$ ;branch if yes MOV #377*400,(R2)+ ;no. save target address and flag for later TST GATLDR(R0) ;is gateway defined BEQ 1$ ;branch if no MOV GATLDR(R0),(R2)+ ;yes. use gateway address MOV GATLDR+2(R0),(R2)+ BR 3$ ; 1$: MOV @SP,R0 ;use destination address MOV IH.DST(R0),(R2)+ MOV IH.DST+2(R0),(R2)+ BR 3$ ; 2$: MOV HOSLNA(R1),(R2)+ ;save leader for later MOV HOSLNA+2(R1),(R2)+ MOV HOSLNA+4(R1),(R2)+ 3$: CLR R0 ;get pid (cc(c) = 0) BISB HOSPID(R1),R0 4$: MOV (SP)+,R1 ;evas MOV (SP)+,R2 RTS PC ; ; adrmap (gat) get table pointers for routing update ; r1 = internet address (word) pointer, returns r0 = host pointer, ; r1 = route pointer and c(cc) = 1 if not found ; ADRMAP: MOV R1,-(SP) ;save JSR PC,ADRINS ;find first match BCS 2$ ;branch if cant 1$: BITB #GT.ERR+GT.HOL,GATFLG(R0) BEQ 3$ ;branch if found 2$: BITB #GT.END,GATFLG(R0) BNE 3$ ;branch if end MOV @SP,R1 ;yes. try next match JSR PC,ADRCNT BCS 2$ ;branch if cant BR 1$ ; 3$: BIT (SP)+,R1 ;discard trash (preserve c(cc)) RTS PC ; ; adrgat (gat) get table pointers for routing function ; r0 = tos, r1 = internet address (word) pointer, returns r0 = host pointer, ; r1 = route pointer and c(cc) = 0 if up; r0 = connection code if cc(c) = 1 ; ADRGAT: MOV R1,-(SP) ;save MOV R0,-(SP) JSR PC,ADRINS ;find first match BCS 6$ ;branch if cant 1$: BITB #GT.ERR,GATFLG(R0) ;found. is this unreachable BNE 5$ ;branch if yes BITB #GT.HOL,GATFLG(R0) ;found. is this black hole BNE 4$ ;branch if yes CMP HOSDLY(R1),#TM.TTL ;no. is host up BLO 2$ ;branch if yes TST HOSDLY(R1) ;no. is host in hold-down BPL 3$ ;branch if no 2$: BITB #GT.TOS,GATFLG(R0) ;yes. is tos okay BEQ 8$ ;branch if yes TSTB @SP BNE 8$ ;branch if yes 3$: BITB #GT.ALT,GATFLG(R0) ;no. is alt route enabled BEQ 5$ ;branch if no MOV 2(SP),R1 ;yes. try next match JSR PC,ADRCNT BCS 6$ ;branch if cant BR 1$ ; 4$: MOV #PK.PAR,@SP ;invalid parameter BR 7$ ; 5$: MOV #PK.NNR,@SP ;assume net unreachable TST GATMSK(R0) ;is this isolate BNE 7$ ;branch if no TST GATMSK+2(R0) BNE 7$ ;branch if no 6$: MOV #PK.GNR,@SP ;yes. host unreachable 7$: MOV (SP)+,R0 ;evas MOV (SP)+,R1 SEC ;error return RTS PC ; 8$: CMP (SP)+,(SP)+ ;stackaches CLC ;normal return RTS PC ; ; Adrins (rut) match first logical address ; Adrcnt (rut) match next logical address ; R0 = gateway table pointer (adrins only), R1 = internet address (word) ; pointer, returns r0 = gateway table pointer, R1 = host table pointer, ; cc(c) = 1 if not found or invalid hid ; ADRINS: MOV R2,-(SP) ;save JSR PC,NETMAP ;is this local net BNE 1$ ;branch if no MOV #$LOCAD,R0 ;yes. use local host table BR RUT1 ; 1$: MOV GATVPT,R0 ;foreign net. use that table BR RUT1 ; ADRCNT: MOV R2,-(SP) ;save RUT2: BITB #GT.END,GATFLG(R0) ;is there another entry BNE RUT3 ;branch if no ADD #GATLEN,R0 ;yes. advance to next entry RUT1: BITB #GT.CAC,GATFLG(R0) ;is this active entry BEQ 1$ ;branch if yes TSTB GATTTL(R0) BEQ RUT2 ;branch if no 1$: MOV @R1,R2 ;yes. mask address BIC GATMSK(R0),R2 CMP GATNET(R0),R2 ;does entry match BNE RUT2 ;branch if no MOV 2(R1),R2 BIC GATMSK+2(R0),R2 CMP GATNET+2(R0),R2 BNE RUT2 ;branch if no CLR R1 ;is hid in range BISB GATHID(R0),R1 CMPB R1,$HOSAD-2 BHIS RUT3 ;branch if no MUL #HOSLEN,R1 ;yes. get host table pointer ADD PC,R1 ADD #$HOSAD-.,R1 CLC ;normal return BR RUT5 ; RUT3: SEC ;error return RUT5: MOV (SP)+,R2 ;evas RTS PC ; ; Netmap (rut) test local net ; R1 = internet address (word) pointer ; Returns c(z) = 1 if local net ; NETMAP: MOV @R1,-(SP) ;is address on local subnet BIC $NETID+4,@SP MOV $NETID,-(SP) BIC $NETID+4,@SP CMP (SP)+,(SP)+ BNE 1$ ;branch if no MOV 2(R1),-(SP) BIC $NETID+6,@SP MOV $NETID+2,-(SP) BIC $NETID+6,@SP CMP (SP)+,(SP)+ 1$: RTS PC ; ; Netchk (chk) test special address ; R1 = internet address (word) pointer ; Returns c(z) = 1 if local use or local broadcast ; NETCHK: MOV $NETID,-(SP) ;is address local use BIC $NETID+4,@SP CMP @R1,@SP BEQ 1$ ;branch if maybe BIS $NETID+4,@SP ;no. is address local broadcast CMP @R1,(SP)+ BNE 3$ ;branch if no MOV $NETID+2,-(SP) ;maybe. continue check BIS $NETID+6,@SP BR 2$ ; 1$: MOV $NETID+2,@SP ;maybe local use. continue check BIC $NETID+6,@SP 2$: CMP 2(R1),(SP)+ ;set cc 3$: RTS PC ; ; Data segment ; .PSECT $KERD,RO,D ; ; Error code translate table ; ERRCOD: .WORD 0 ;operation complete .WORD ER.PAR ;connection open error .WORD ER.PAR ;parameter error .WORD ER.USP ;insufficient resources .WORD ER.DWN+0 ;gateway down .WORD ER.DWN+1 ;host down ; .END