.TITLE INET - INTERNETWORK INTERFACE ROUTINES .INSRT ../../mos/moscnf-1.sml .INSRT mosdev-1.sml .INSRT ../../mos/mosmac.sml .INSRT ../../mos/mostbl.sml .INSRT utlmac-1.sml .INSRT inet-1.sml .INSRT pktdef-1.sml $CNFIG $DFIOR $DFNCT .CSECT XINETI .GLOBL $INET ;INET entry point .GLOBL INETUP ;Network initialize routine .GLOBL INETIN ;Network input routine .GLOBL INETIC ;Network input completion routine .GLOBL INETOT ;Network output routine .GLOBL $NETBL ;Network characteristics table .GLOBL $NETID ;Local network ID .GLOBL $GATBL ;Gateway routing table .GLOBL GROUTE ;Get local destination for INET addr .SBTTL Internetwork Protcol Module ; ; The INET protocol module runs as a process seperate from TCP and ; provides other protocol modules with an interface to the internetworking ; world. This module translates the network-independent INET interface ; into a network specific one. It also handles the various aspects of ; internet protocol, such as INET header checksum, gateway routing, and ; interpretation of INET error-messages. ; $INET: 1$: CALL WAIT ;Wait for work to do ; CMP R0,#MAXSIG ;Signal valid BHI 2$ ;If not, error ASL R0 ;Convert to word index CALL @OPCTBL(R0) ;and call signal handler BR 1$ ;and loop 2$: BUGHLT ;Invalid signal opcode BR 1$ OPCTBL: .WORD 0 .SBTTL INETUP - Network initialization INETUP: CALL @$NETBL+NT.UP ;Call network initialization RET .SBTTL INETIN - Network receive transfer initialization ; ; Called with: R0 - input signal opcode ; INETIN: CALL @$NETBL+NT.IN ;Call network input handler RET .SBTTL INETIC - INET input completion handler ; ; INETIC is called to perform INET processing after a packet has been ; received. The processing consists of calling a local network routine ; to handle its processing, verifying the INET header fields, checking ; the checksum, and constructing the pseudo-header ; ; Called with: R1 - address of IORB ; ; Returns with: R2 - address of pseudo header ; R0 - return code ; INETIC: CALL @$NETBL+NT.INC ;Call network-specific handler ; returns with R2 pointing to start ; of inet header BNE 1$ ;If local net control msg, skip CMP IRBX(R1),#IH.LEN ;Message large enough? BLO 2$ ;If not, error MOVB IH.VER(R2),R0 ;Get INET version & header length BIC #^CIH.HL,R0 ;Clear extra junk ASL R0 ;Convert length to bytes ASL R0 CMP R0,#IH.LEN ;Reasonable header length? BLO 2$ ;If not, discard CALL CHKSM ;Calculate inet header checksum TST IH.CHK(R2) ;Check result BNE 2$ ;If non-zero, checksum error TSTB IH.TTL(R2) ;Packet time-to-live expired? BEQ 2$ ;If so, discard BIT #IH.MF!IH.OFF,IH.FRG(R2) ;Check if fragmented? BNE 3$ ;If so, discard SWAB IH.FL(R2) ;Swap fragment length CMP IH.FL(R2),IRBX(R1) ;Byte counts agree? BHI 4$ ;If not, error in data transfer SUB R0,IH.FL(R2) ;Convert to data length SWAB IH.FL(R2) ;Swap back for consistency $PUSH IH.DST(R2) ;Save destination net $PUSH IH.DST+2(R2) ; ... destination tcp id $PUSH IH.SRC(R2) ; ... source net $PUSH IH.SRC+2(R2) ; ... source tcp id MOVB IH.PRO(R2),-(SP) ; ... protocol number $PUSH IH.FL(R2) ; ... data length ADD R0,R2 ;Advance to start of inet data SUB #PH.LEN,R2 ;And backup to start of pseudo header $POP PH.DL(R2) ;Set data length CLRB PH.PAD(R2) ;Clear padding word MOVB (SP)+,PH.PRO(R2) ;Put protocol # in pseudo-header $POP PH.SRC+2(R2) ; ... source tcp id $POP PH.SRC(R2) ; ... source net $POP PH.DST+2(R2) ; ... destination tcp id $POP PH.DST(R2) ; ... destination net CLR R0 ;Indicate OK 1$: RET 2$: MOV #ER.INH,R0 ;Error in Inet header BR 1$ 3$: MOV #ER.FRG,R0 ;Fragmented segment BR 1$ 4$: MOV #ER.SIZ,R0 ;Size error in INET header BR 1$ .SBTTL INETOT - Internetwork output routine ; ; Called with: R2 - pointer to header ; R1 - address of IORB ; R0 - I/O completion signal opcode ; INETOT: $PUSH R0,R1,R2,R3 MOV PH.DL(R2),R3 ;Get data length SWAB R3 ADD #IH.LEN,R3 ;add in INET header length $PUSH PH.DST(R2) ;Save destination net $PUSH PH.DST+2(R2) ; ... destination tcp id $PUSH PH.SRC(R2) ; ... source net $PUSH PH.SRC+2(R2) ; ... source tcp id MOVB PH.PRO(R2),-(SP) ; ... protocol number SUB #IH.LEN-PH.LEN,R2 ;Backup pointer to inet header MOVB (SP)+,IH.PRO(R2) ;Put protocol # in pseudo-header $POP IH.SRC+2(R2) ; ... source tcp id $POP IH.SRC(R2) ; ... source net $POP IH.DST+2(R2) ; ... destination tcp id $POP IH.DST(R2) ; ... destination net MOV R3,IH.FL(R2) ;Place fragment length in inet header SWAB IH.FL(R2) ;Correct for byte addressing INC R3 BIC #1,R3 ;Round up to a word boundary MOV R3,IRBR(R1) ;Set bytes requested MOV R2,IRUVA(R1) ; and pointer to inet header MOVB #4*20+5,IH.VER(R2) ;Set header version & header length MOVB #0,IH.TOS(R2) ;Set type of service MOVB #10,IH.TTL(R2) ;Set inet time-to-live CLR IH.FRG(R2) ;Clear fragment offset CLR IH.CHK(R2) ;Clear checksum CALL CHKSM ;Calculate inet header checksum CALL @$NETBL+NT.OT ;And send packet to network $POP R3,R2,R1,R0 RET .SBTTL CHKSM - Internet header checksum ; ; Called with: R2 - pointer to INET header ; ; Returns with: IH.CHK(R2) - value of checksum remainder ; CHKSM: $PUSH R0,R1,R3 ; ; R0 - checksum accumulator ; R1 - loop counter ; R3 - roving packet pointer ; MOV R2,R3 ;Get pointer to header MOVB IH.VER(R2),R1 ;Get version & header length BIC #^CIH.HL,R1 ;And zap extra stuff ASL R1 ;Convert double word length to words CLR R0 1$: ADD (R3)+,R0 ADC R0 $LOOP R1,1$ TST R0 ;Result zero? BEQ 2$ ;If so, don't complement COM R0 2$: MOV R0,IH.CHK(R2) ;Put in checksum field of packet $POP R3,R1,R0 RET .SBTTL GROUTE - Get addr of local net destination ; ; Called with: R2 - pointer to INET header ; ; Returns with: R1,R2 - Local net destination addr ; GROUTE: $PUSH R0 MOVB IH.DST+ID.NET(R2),R0 ;Get destination net ID CMPB R0,$NETID ;Destination within local net BEQ 2$ ;If so, send directly to it ; ; If the destination is not in the local network, consult the gateway ; routing tables to determine the gateway address in the local network ; CMPB R0,$GATBL ;Known network number? BLOS 1$ ;If so, skip MOVB $NETID,R0 ;Else, send to gateway on our net 1$: BIC #^C377,R0 ;Clear out junk in hi byte ASL R0 ;Convert to double-word index ASL R0 MOV $GATBL(R0),R1 ;Get destination from table MOV $GATBL+2(R0),R2 BR 3$ ; ; If the destination is in the local network, route directly ; 2$: MOV R2,R0 MOV IH.DST(R0),R1 ;Send directly to destination MOV IH.DST+2(R0),R2 3$: $POP R0 RET .END