; UPD ID= 2123, SNARK:<6.1.MONITOR>MNETDV.MAC.11, 5-Jun-85 09:58:02 by MCCOLLUM ;TCO 6.1.1406 - Update copyright notice. ; UPD ID= 1957, SNARK:<6.1.MONITOR>MNETDV.MAC.10, 12-May-85 14:54:53 by PAETZOLD ;TCO 6.1.1380 - Make HOSTN larger. ; UPD ID= 1608, SNARK:<6.1.MONITOR>MNETDV.MAC.9, 8-Mar-85 11:53:53 by PAETZOLD ;Document BUGxxx's ; UPD ID= 1570, SNARK:<6.1.MONITOR>MNETDV.MAC.8, 26-Feb-85 17:17:32 by PAETZOLD ;document BUGxxx's ; UPD ID= 1235, SNARK:<6.1.MONITOR>MNETDV.MAC.7, 22-Dec-84 11:43:29 by PAETZOLD ;More TCO 6.1.1079 - Make the XJRST conditional based on REL6 switch for 5.4. ; UPD ID= 1178, SNARK:<6.1.MONITOR>MNETDV.MAC.6, 11-Dec-84 13:15:23 by PAETZOLD ;TCO 6.1.1079 - Use an XJRST referecing TVTJFN in ATNVT. ; UPD ID= 1038, SNARK:<6.1.MONITOR>MNETDV.MAC.5, 12-Nov-84 15:25:34 by PAETZOLD ;TCO 6.1041 - Move ARPANET to XCDSEC ; UPD ID= 999, SNARK:<6.1.MONITOR>MNETDV.MAC.4, 7-Nov-84 14:46:40 by PRATT ;TCO 6.1.1030 - Add IPCI to INTNAM for communicating over the CI ; UPD ID= 917, SNARK:<6.1.MONITOR>MNETDV.MAC.3, 23-Oct-84 19:49:20 by PAETZOLD ; UPD ID= 312, SNARK:MNETDV.MAC.11, 18-Oct-84 15:41:24 by PAETZOLD ;TCO 6.1.1024 - Add .GTHLA function to GTHST%. ; UPD ID= 304, SNARK:MNETDV.MAC.10, 15-Oct-84 14:46:20 by PAETZOLD ;Fix alphabetical order problem in OPSTAB. ; UPD ID= 287, SNARK:MNETDV.MAC.9, 24-Sep-84 13:55:04 by PURRETTA ;Update copyright notice. ; UPD ID= 163, SNARK:MNETDV.MAC.8, 3-Jun-84 17:26:35 by PAETZOLD ;Make MNTHLT reset NETON for each interface so that it stays down. ;Clean up MNTHLT in general. Remove MNTKIL since no one uses it. ;Add VMS, TACs, and MSDOS to OPSTAB. ; UPD ID= 159, SNARK:MNETDV.MAC.7, 1-Jun-84 11:35:17 by PAETZOLD ;AOS INTFLG in MNTSET. ; UPD ID= 156, SNARK:MNETDV.MAC.6, 31-May-84 11:25:18 by PAETZOLD ;Use indirects in MNTRSV ; UPD ID= 155, SNARK:MNETDV.MAC.5, 31-May-84 10:58:54 by PAETZOLD ;Add MNTRSV. Add some ENDSV.'s. ; UPD ID= 129, SNARK:MNETDV.MAC.4, 14-May-84 16:13:25 by PAETZOLD ;MNTHLT needs an EA.ENT. ; UPD ID= 33, SNARK:MNETDV.MAC.3, 7-Apr-84 13:15:19 by PAETZOLD ;Remove some spaces in initial HSTINI message. ; UPD ID= 31, SNARK:MNETDV.MAC.2, 5-Apr-84 22:46:02 by PAETZOLD ;Add IPNI to INTNAM. Change SITE-ADDRESS.TXT to INTERNET.ADDRESS. Clean ;up MNTSTS output. Use NETPRT to print out network numbers. Add ;informational message during startup when calling HSTINI. ; UPD ID= 4022, SNARK:<6.MONITOR>MNETDV.MAC.13, 31-Mar-84 16:20:59 by PAETZOLD ;TCO 6.2019 - Use ADJSPs ; UPD ID= 3941, SNARK:<6.MONITOR>MNETDV.MAC.12, 18-Mar-84 13:15:57 by PAETZOLD ;More TCO 6.1733 - Do not check for dots in GTHSIL. ; UPD ID= 3935, SNARK:<6.MONITOR>MNETDV.MAC.11, 17-Mar-84 13:01:33 by PAETZOLD ;More TCO 6.1733 - Add Fuzzballs to OPSTAB ; UPD ID= 3921, SNARK:<6.MONITOR>MNETDV.MAC.10, 14-Mar-84 10:17:06 by PAETZOLD ;More TCO 6.1733 - Add Foonex to OPSTAB as Tenex ; UPD ID= 3901, SNARK:<6.MONITOR>MNETDV.MAC.9, 11-Mar-84 14:28:21 by PAETZOLD ;More TCO 6.1733 - 5.3 needs a EA.ENT in MNTINI ; UPD ID= 3894, SNARK:<6.MONITOR>MNETDV.MAC.8, 11-Mar-84 10:36:16 by PAETZOLD ;More TCO 6.1733 - Allow JFNs in ATNVT%. New HSTINI preference scheme. ;Make HSTINI set up gateway (HS%GAT) and network (HS%NET) entries. ;Make RDFLD fold case to upper. Add TAC and WAITS to OPSTAB. Check and ;dispatch for Pup JFN in .ATNVT. ; UPD ID= 3826, SNARK:<6.MONITOR>MNETDV.MAC.7, 29-Feb-84 18:15:40 by PAETZOLD ;More TCO 6.1733 - ANBSEC and MNTSEC removal. Bug fixes. Cleanup. ;MNETDV.MAC.4, 6-Dec-83 23:53:55, Edit by PAETZOLD ;Call CHKI7 from MNTCHK ;TCO 6.1867 - Use SAVEAC and not SAVP1 ;Add subtitles. Make code that was RSCOD SWAPCD. ;More TCO 6.1733 - Fix day one off by one bug with NUMOPS ;More TCO 6.1733 - NCPFRK has gone away. HSTLUK Changes. HSTINI changes. ;MNETDV.MAC.42, 5-Jul-83 08:28:09, Edit by PAETZOLD ;New host table support ;IP debuging switch support ;Use ANAUNV as the universal ;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED ;OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE. ; ;COPYRIGHT (C) DIGITAL EQUIPMENT CORPORATION 1976, 1985. ;ALL RIGHTS RESERVED. SEARCH ANAUNV,PROLOG TTITLE (MNETDV,MNETDV,< - Internet Multinet Interface>) IFNDEF REL6, SUBTTL MNTINI - Initialization IFE REL6, IFN REL6, ;Called at system startup, initializes tables and storage needed by ;Multinet. IFE REL6, IFN REL6, IFE REL6, ; enter section one CALL NETINI ; initialize the 1822 buffers MOVEI T1,BMNTLK ; Beginning of pages needed to lock down SETSEC T1,INTSEC ; In proper section MOVEI T2,EMNTLK ; End of area to lock SETSEC T2,INTSEC ; Same section CALL LKSTOR ; Lock storage SETZM DEFADR ; Clear default address field SETZM PRFADR ; Clear preferred address field SETZM PRFNFD ; Also clear preferred shifted network SETZM PRFNET ; And preferred network SETZM NETSUP ; Networks not yet up MOVSI T1,-%NETS ; Get number of networks we handle SKIPA P1,NCTVT ; get link to the first NCT MNTIN0: LOAD P1,NTLNK,(P1) ; get next on list MOVE T2,NCTVT+1(T1) ; Get next pointer STOR T2,NTLNK,(P1) ; Link it to this one AOBJN T1,MNTIN0 ; Loop through all SETZRO NTLNK,(P1) ; Clear last pointer (End of list) CALL ADRINI ; Init addresses BUG.(INF,NOADDR,MNETDV,SOFT,,,< Cause: The SYSTEM:INTERNET.ADDRESS file was either not found or is corrupted. >) TMSG < [Loading Internet host names]> CALL HSTINI ;GET THE SYSTEM TO KNOW NAMES OF SITES TRNA ; skip on error JRST MNTIN1 ; no error BUG.(INF,NOHSTN,MNETDV,SOFT,,,< Cause: The SYSTEM:HOSTS.TXT file was not found. >) JRST MNTIN2 ; continue with flow MNTIN1: TMSG < [OK] > MNTIN2: CALL NETHSI ; Initialize the network hash table MOVE T1,DBUGSW ; Get system switch CAIG T1,1 ; are we stand alone? TDZA T1,T1 ; we are not stand alone MOVEI T1,1 ; we are stand alone SKIPE DBUGIP ; IP Debuging? XORI T1,1 ; yes so reverse flag SKIPN T1 ; System normal? SKIPN DEFADR ; Did addresses initialize properly? JRST MNTINX ; No, return now JRST MNTON1 ; Go turn on networks ;LKSTOR - Lock down a region of core ;1 - Xtended address of start ;2 - Xtened address of end LKSTOR: TRZ T1,777 ; Round down to nearest page LKST1: PUSH P,T1 ; Save start PUSH P,T2 ; and end IFE REL6, ; Lock down the page IFN REL6, ; Lock down the page POP P,T2 ; Restore ACs POP P,T1 ; ... ADDI T1,PGSIZ ; Increment to next page CAMG T1,T2 ; Past last address? JRST LKST1 ; Loop RET SUBTTL MNETON - Turn Networks On if They Have Never Been On ;Turn networks on if NETSUP has been off. Called by CALL MNETON$X IFE REL6, IFN REL6, MNTON1: SKIPA P1,NCTVT ; Point to vector table MNTON2: LOAD P1,NTLNK,(P1) ; get next in list JUMPE P1,MNTINY ; Return when done MNTCALL NTINI ; Initialize network device SETOM NETON(P1) ; Turn it on SETZM NTPRIO(P1) ; Clear priority cell MNTCALL NTRSRT ; get it going JRST MNTON2 ; and loop MNTINY: SETOM NETSUP ; Networks are now initialized MNTINX: RET ; And return SUBTTL MNTCHK - CHKR Fork Routine ;CHKR Fork routine for keeping things going on all nets. Called every ;four minutes or whenever JB0FLG is non-zero. IFE REL6, IFN REL6, SKIPA P1,NCTVT ; Point to the vector table MNTCH0: LOAD P1,NTLNK,(P1) ; Get next in list JUMPE P1,MNTCH2 ; Go check the rest SKIPE NTSTCH(P1) ; Change of state? CALL MNTSTS ; Yes SKIPN NETON(P1) ; If network off JRST MNTCH0 ; Loop ; Want net on MNTCALL NTSCHK ; Check status, keep stuff consistent JFCL ; Ignore error return SKIPG NETON(P1) ; If needs restarting SKIPL NTRDY(P1) ; Or isn't ready MNTCALL NTRSRT ; Restart it MOVE T1,TODCLK ; Get time now CAML T1,NTTOUT(P1) ; Output timed out? SKIPN NTTOUT(P1) ; Output actually going? JRST MNTCH1 ; No timeout BUG.(INF,NTOHNG,MNETDV,SOFT,,<>,< Cause: Multinet has declared the output interface for a network hung. >) MNTCALL NTRSRT ; If timeout, reset net MNTCH1: MNTCALL NTISRT ; Make sure input is happening MOVE T1,SCTLW ; System shutdown? TXNN T1,<1B3> JRST MNTCH0 ; No, loop through all ; System shutdown SETZM NTRDY(P1) ; Imp off SETZM NETON(P1) ; Net off SETZM NTORDY(P1) ; output off SETO T1, ; Abort entry MNTCALL NTKILL ; Drop ready line JRST MNTCH0 ; and loop through the rest MNTCH2: SKIPE IMPGDM ; Any "imp going down" messages? CALL CHKI7 ; Yes, go print it RET ; And return SUBTTL MNTSTS - Report Network State Changes MNTSTS: ; Log network change of state MOVE T2,NTLADR(P1) ; Get number JUMPL T2,R ; Don't report if no address set HRROI T1,[ASCIZ / [Internet Network /] PSOUT CALL NETPRT ; Print out the network number HRROI T1,[ASCIZ / on/] ; Assume it is on SKIPN NETON(P1) ; Is it on? HRROI T1,[ASCIZ / off/] ; no PSOUT ; output it HRROI T1,[ASCIZ /, Output /] ;delimit PSOUT ; output it HRROI T1,[ASCIZ /on/] ; assume on SKIPN NTORDY(P1) ; is output on? HRROI T1,[ASCIZ /off/] ; no PSOUT ; output it MOVEI T1," " ; delimit PBOUT ; output it SETZM NTSTCH(P1) ; reset the state change time CALL LGTAD ; get time of this change SKIPGE T2,T1 ; If time known JRST MNTC5X ; Not known. MOVEI T1,.PRIOU ; Still on CTY MOVEI T3,0 ; this time ODTIM ; output it MNTC5X: TMSG <] > SKIPN NTORDY(P1) ; Did the hardware come up? CALLRET INTDWN ; No, signal it's down CALLRET INTUP ; Signal that it's available for use SUBTTL NETPRT - Print Network Name or Number NETPRT: ; Print the network number for current NCT STKVAR MOVEI T1,.PRIOU ; Primary output DOBE% ; dismiss until output done ERJMP .+1 ; Handle errors MOVE T1,NTNET(P1) ; Get the network number LSH T1,10 ; Move it over one byte CAMG T1,[BYTE (4)0(8)0,377,377,377] ; Class A or B? LSH T1,10 ; yes move it over one more byte CAMG T1,[BYTE (4)0(8)0,377,377,377] ; Class A? LSH T1,10 ; yes move it over one more byte MOVEM T1,NPRTX ; save it MOVEI T1,.GTHNS ; Get host name function MOVEI T2,.PRIOU ; Output to CTY MOVE T3,NPRTX ; Get the network number GTHST% ; Output the network number ERJMP NETPR1 ; on error assume no name RET ; and return NETPR1: ; here when we do not have a network name MOVX T1, ; get the byte pointer MOVEM T1,NPRBP ; and save it MOVEI T4,4 ; four octets NETPR2: ; output loop ILDB T2,NPRBP ; get a byte MOVEI T1,.PRIOU ; output to cty MOVEI T3,12 ; in decimal NOUT% ; output the octet ERJMP .+1 ; handle errors SOJE T4,R ; on the last one return MOVEI T1,"." ; otherwise get a dot PBOUT% ; output it JRST NETPR2 ; and do the rest ENDSV. SUBTTL Low and High Priority Packet Output Queueing ;NTHSND - Put packet on High priority Q. ;T2/ packet pointer ;P1/ NCT address ;Returns+1 Refused ;Returns+2 Packet succesfully queued IFE REL6, IFN REL6, NTSNDX: BUG.(CHK,BADADR,MNETDV,SOFT,,<>,< Cause: The multinet output queuing mechanism was called for a local address that has not been defined. >) RET ; return NTHSND::SAVEAC CALL FNDNCT JSP CX,NTSNDX ; Nope XMOVEI T1,NTHOBO(P1) ; Point to Q JRST NTQPKT ; And queue it ;NTLSND - Put packet on low priority Q ;T2/ packet pointer ;P1/ NCT address ;Returns+1 Refused ;Returns+2 Packet succesfully queued NTLSND::SAVEAC CALL FNDNCT JSP CX,NTSNDX ; Not found XMOVEI T1,NTLOBO(P1) JRST NTQPKT SUBTTL NTWPKT - Packet Queueing Routine ;NTWPKT - Put packet on FIFO Q ;T1/ pointer to Q head ;T2/ packet pointer ;P1/ NCT address ;Returns+1 Refused ;Returns+2 Packet succesfully queued NTQPKT: SKIPN NTORDY(P1) ; Output allowed? RET ; No, fail TRNN T2,-1 ; Is the address good? BUG.(HLT,BADBUF,MNETDV,SOFT,,,< Cause: Multinet has been called to queue an output buffer with a null address. >) HRRZS 0(T2) ; Make sure succesor chain is NIL PIOFF ; Insure intergrety of queues SKIPE T3,1(T1) ; Q empty? JRST NTQPK2 ; No, put on tail MOVEM T2,0(T1) ; Yes, set head pointer SKIPA ; Don't chain, no predecessor NTQPK2: STOR T2,NBQUE,(T3) ; Chain from predecessor to new guy MOVEM T2,1(T1) ; This is new tail of Q PION ; Allow interrupts again MNTCALL NTOSRT ; Start output if needed RETSKP ; And return succesfully SUBTTL NTSNDI - Queue an Internet Packet ;NTSNDI - Default routine for enquing an internet packet ; T1/ Local host ; T2/ packet pointer ; P1/ NCT address ;Returns+1 Refused, T1 has an ICMP error code ;Returns+2 Packet succesfully queued NTSNDI::MNTCALL NTOTOK ; Can this packet be sent? RET ; No, T1 has reason MNTCALL NTLLDR ; Make a local header XMOVEI T1,NTIOBO(P1) ; Point to right Q CALL NTQPKT ; And Q the packet CAIA ; Failed RETSKP ; Success MOVX T1, ; Back off a minute, interface unusable RET ; return SUBTTL Routines to Find NCTs ;FNDNCT - Host number to NCT ;T1/ Host address ;Returns+1 No NCT for that net ;Returns+2 P1/ pointer to the NCT for a (usable) interface on that net FNDNCT::SAVET ; Save temps NETNUM T2,T1 ; Get the network number CALL NETHSH ; Look it up in the tables RET ; No, knowledge of that net SKIPL P1,NETGWY(T2) ; Get the interface RET ; Not directly connected RETSKP ; And skip return ;NETNCT - Host or Net to NCT of a (possibly down) interface on that net. ;T1/ Host address or Net number ;Returns+1 No NCT for that net ;Returns+2 P1/ pointer to the NCT for a (usable) interface on that net NETNCT::SAVET ; Save temps TXNN T1,-1B11 ; Host address? JRST NETNC0 ; No NETNUM T1,T1 ; Get the network number NETNC0: XMOVEI P1,NCTVT ; Point to the table NETNCL: LOAD P1,NTLNK,(P1) ; Get net in the chain JUMPE P1,R ; No more CAMN T1,NTNET(P1) ; Same network? RETSKP ; yes, success JRST NETNCL ; else loop SUBTTL HSTHSH - Find Host Table Entries ;Given a host number in T1 finds entry for that number in host ;tables. Does skip return if found. is table index, or -1 if no more ;room in tables. HSTHSH:: MOVE T2,T1 ;DO A HASH IDIVI T2,NHOSTS ;GET INITIAL GUESS, DIV BY PRIME EXCH T2,T3 ;2/ FIRST GUESS IDIVI T3,NHOSTS ;DIV BY PRIME AGAIN CAIN T4,0 ;GET INCREMENT MOVEI T4,1 MOVEI T3,NHOSTS ;COUNTER FOR GUESSES SETSEC T2,INTSEC ;LOOK IN THE RIGHT SECTION HSTHLP: SKIPG HOSTNN(T2) ;NO HOST THERE? RET ;NO, 2/ WHERE TO PUT IT CAMN T1,HOSTNN(T2) ;MATCH? RETSKP ADDI T2,(T4) ;STEP BY INCREMENT CAML T2,[XWD INTSEC,NHOSTS] ;CHECK FOR OVERFLOW SUBI T2,NHOSTS ;WRAP AROUND IF NEEDED SOJG T3,HSTHLP ;COUNT DOWN GUESSES SETO T2, ;-1 TABLE FULL RET ;RETURN ERROR SUBTTL Host, Network Status and Configuration Routines IFE REL6, IFN REL6, ;NETCHK - Check if our interface on a given net is up ;T1/ Host number ;Returns+1 if interface is down ;Returns+2 if it is up NETCHK::SAVEAC CALL NETNCT ; Find the NCT TRNA ; No such Net SKIPL NTRDY(P1) ; Network up? RET ; No RETSKP ; Yes, return good ;NETCMP - Check if a host is on a given interface. ;T1/ Host number ;P1/ Pointer to NCT ;Returns+1 if host is not on that interface ;Returns+2 if it is NETCMP::SAVET ; Save temps NETNUM T1,T1 ; Get the net number MOVE T2,NTNET(P1) ; And that of this NCT CAME T2,T1 ; Same? RET ; No RETSKP ; Yes ;LCLNET - Check if a host address is on a net we're connected to. ;T1/ Host address ;Returns+1 If no intersecting network ;Returns+2 If we have an intersecting network ;(Note that this doesn't mean that the interface is currently usable) LCLNET::SAVET ; Save temps NETNUM T1,T1 ; Get the net number XMOVEI T3,NCTVT ; Point to the interface table LCLNT0: LOAD T3,NTLNK,(T3) ; get the next in the list JUMPE T3,R ; end of the list CAMN T1,NTNET(T3) ; On this network? RETSKP ; yes, return success JRST LCLNT0 ; loop through all ;LCLHST ;Check if a given address (possibly with non-zero logical host ;field) is one of ours ;T1/ 32 bit address ;Returns+1 if it is not one of ours ;Returns+2 if it is LCLHST::SAVEAC PUSH P,T1 ; Save address SKIPA P1,NCTVT ; First interface LCLHS0: LOAD P1,NTLNK,(P1) ; Next interface JUMPE P1,LCLHS9 ; No more MOVE T1,(P) ; Address again ANDCM T1,NTNLHM(P1) ; without logical host field CAME T1,NTLADR(P1) ; Is this one of ours? JRST LCLHS0 ; No, loop through all AOS -1(P) ; Success! it's me, skip return LCLHS9: POP P,T1 ; Restore address RET SUBTTL Routines Dealing With Network Shutdown ;T1/ Reason, a la 1822 ;T2/ GTAD when back up IFE REL6, IFN REL6, ; Tell all interfaces we are going away. IFE REL6, ; enter section one SAVEAC STKVAR <> DMOVEM T1,MHLTRS ; save the time and reason MOVX T1,<377777777777> ; Stop pings MOVEM T1,PINGTM ; Save new ping time ; shutdown each interface SKIPA P1,NCTVT ; Get pointer to tables MNTHL2: LOAD P1,NTLNK,(P1) ; Get next NCT JUMPE P1,R ; done? SETZM NETON(P1) ; No, say that we want this interface off. DMOVE T1,MHLTRS ; Get why/when. MNTCALL NTKILL ; Do halt instruction JRST MNTHL2 ; Loop through all SUBTTL Routines Dealing With Network States ;MNTSET - Set a network status. ; T1/ Network number, or host address ; T2/ value ; Possible values are: <0 = on ; 0 = off ; >0 = request cycle MNTSET::SAVEAC CALL NETNCT ; Find the NCT RET ; If none SKIPGE T2 SETO T2, ; Either -1 SKIPE T2 ; or 0 HRRZI T2,-1 ; or 0,,-1 MOVEM T2,NETON(P1) ; Set function AOS INTFLG ; Ask for the internet fork RETSKP ; Success return MNTRED:: ; ROUTINE TO RETURN NETWORK STATE SAVEAC SETZ T2, ; ASSUME NET IS DOWN CALL NETNCT ; GET THE NCT RET ; NO NCT MOVE T2,NETON(P1) ; GET THE STATE RETSKP ; SUCCESS RETURN SUBTTL Routine to Resolve Interface State MNTRSV:: ; Resolve interface state (P1/ NCT) SKIPL NETON(P1) ; do we want it up? JRST MNTRS2 ; no SKIPE NTRDY(P1) ; yes. is it up? RET ; want up and is up so return. CALL @NTRSRT(P1) ; want up and is down so make it up. RET ; and return MNTRS2: ; Here when not wanted up. SKIPE NETON(P1) ; want it down? JRST MNTRS3 ; no must want it cycled. SKIPN NTRDY(P1) ; is it down? RET ; want down and is down so return. CALL @NTKILL(P1) ; want down and is up so take it down. RET ; and return to caller MNTRS3: ; here when we want to cycle SKIPE NTRDY(P1) ; is it up now? CALL @NTKILL(P1) ; yes so make it down SETOM NETON(P1) ; and say that we want it up RET ; and return to caller SUBTTL Host Table Initialization COMMENT \ Initialize the Host tables. Called at system startup (And possibly other times). Reads in system Hostname file and sets up the host tables from it. In order to save Section 0/1 space Host tables are put in INTSEC. This is the new Internet host table parser. This is intended as a stopgap measure to allow TOPS-20's to use the Internet format host table until they can really take advantage of it. Structures in the Host tables For reference the Host tables have the following formats: Tables indexed by a hash of the host number: HOSTNN - The 32 bit host number HSTSTS - Status bits HOSTPN - index in HOSTN of primary name for this number Tables indexed by order in the host name file: HOSTN - LH 18 bit address in HSTNAM RH Index into hashed tables HSTNAM - a block NHSTN long which holds the null terminated name strings \ HSTINI:: SAVEAC TRVAR ,NAMPTR,NAMIDX,NAMSPC,NAMCNT,SAVEP,BOL,TERM,HSTS,HBEST,HGOOD,NAMLST,NUMLST,NETMSK,ENTTYP> MOVEM P,SAVEP ;SAVE A STACK FENCE IN CASE OF ERRORS MOVX T1,GJ%SHT!GJ%OLD ;GTJFN FLAGS. FILE MUST EXIST. HRROI T2,[ASCIZ/SYSTEM:HOSTS.TXT/] ;FILENAME GTJFN% ;LOOK FOR THE FILE ERJMP R ;FILE NOT FOUND MOVEM T1,HTBJFN ;SAVE THE JFN MOVX T2,7B5!OF%RD ;WE NEED READ ACCESS OPENF% ;OPEN UP THE JFN ERJMP HSTIE1 ;HANDLE ERRORS PUTSEC T1,INTSEC ;INITIAL HOSTN INDEX MOVEM T1,NAMIDX MOVEI T1,NHOSTN ;SIZE OF HOSTN MOVEM T1,NAMCNT ;SAVE MOVNI T1,NHSTN ;SIZE OF NAME SPACE MOVEM T1,NAMSPC ;SAVE PUTSEC T1,INTSEC ;INITIAL INDEX INTO NAME SPACE MOVEM T1,NAMPTR ;SAVE ;... MOVE T1,[XWD INTSEC,HSTNAM] ;CLEAR THE CURRENT TABLES SETZM 0(T1) ;CLEAR FIRST WORD OF NAME SPACE MOVE T2,[XWD HSTNAM,HSTNAM+1] ;GET THE BLT AC BLT T2,NHSTN-1(T1) ;ZAP MOVE T1,[XWD INTSEC,HOSTN] ;GET THE ADDRESS OF HOSTN SETZM 0(T1) ;ZERO THE FIRST WORD MOVE T2,[XWD HOSTN,HOSTN+1] ;GET THE BLT AC BLT T2,NHOSTN-1(T1) ;ZERO THE REST OF THE TABLE PUTSEC T1,INTSEC ;GET AN INDEX INTO THE CORRECT SECTION SETZM HOSTNN(T1) ;ZERO THE FIRST WORD OF HOSTNN MOVE T2,[HOSTNN,,HOSTNN+1] ;GET THE BLT AC BLT T2,HOSTNN+NHOSTS-1(T1) ;ZERO THE REST OF HOSTNN SETZM HSTSTS(T1) ;ZERO THE FIRST WORD OF HSTSTS MOVE T2,[HSTSTS,,HSTSTS+1] ;GET THE BLT AC BLT T2,HSTSTS+NHOSTS-1(T1) ;ZERO THE REST OF HSTSTS SETZM HOSTPN(T1) ;ZERO THE FIRST WORD OF HOSTPN MOVE T2,[HOSTPN,,HOSTPN+1] ;GET THE BLT AC BLT T2,HOSTPN+NHOSTS-1(T1) ;ZERO THE REST OF HOSTNN MOVE T1,PRFNET ;GET PREFERRED NETWORK NUMBER MOVX T2, ;NETWORK MASK FOR CLASS C NETWORK LSH T1,^D8 ;SHIFT INTO POSITION FOR CLASS C NETWORK CAMN T1,PRFNFD ;CLASS C? IFSKP. MOVX T2, ;NETWORK MASK FOR CLASS B NETWORK LSH T1,^D8 ;SHIFT INTO POSITION CAMN T1,PRFNFD ;CLASS B? ANSKP. MOVX T2, ;NETWORK MASK FOR CLASS A NETWORK LSH T1,^D8 CAME T1,PRFNFD ;CLASS A? BUG.(HLT,HSTNET,MNETDV,SOFT,,,< Cause: The preferred network number is messed up. This probably indicates that the SYSTEM:INTERNET.ADDRESS file is messed up. >) ENDIF. MOVEM T2,NETMSK ;SAVE HOST MASK FOR LATER HSTIN6: ;LOOP FOR PROCESSING ENTRIES MOVE P,SAVEP ;RESET STACK FENCE CALL GBOLX ;SKIP TO START OF NEXT NON-BLANK, ;NON-COMMENT LINE @ FIRST NON-WHITE CALL RDFLD ;READ A VALUE MOVE T1,TMPBUF ;GET FIRST WORD SETZ T2, ;ZERO MEANS UNKNOWN TYPE OF ENTRY CAMN T1,[ASCIZ/HOST/] ;HOST? MOVX T2,HS%SRV ;YES CAMN T1,[ASCIZ/NET/] ;NETWORK? MOVX T2,HS%NET ;YES CAMN T1,[ASCIZ/GATEW/] ;GATEWAY? MOVX T2,HS%GAT ;YES JUMPE T2,HSTIN6 ;FLUSH IF AN UNKNOWN ENTRY TYPE MOVEM T2,ENTTYP ;SAVE ENTRY TYPE ;Should also check if it is a gateway, and if so fill in in routing ;tables.... MOVEM P,NUMLST ;SAVE POINTER TO NUMBERS HSTIN7: ;LOOP FOR READING IN ALL THE NUMBERS CALL RDHNUM ;READ A HOST NUMBER CALL HSTHSH ;HASH IT INTO THE TABLES NOP ;IGNORE SKIP RETURN JUMPL T2,HSTIE2 MOVEM T1,HOSTNN(T2) ;SAVE THE NUMBER PUSH P,T2 ;AND THE INDEX MOVE T1,TERM ;GET FIELD TERMINATOR CAIE T1,":" ;END? JRST HSTIN7 PUSH P,[-1] ;FLAG END OF LIST ;... ;... ;HERE WITH ALL ADDRESSES ON THE STACK MOVEM P,NAMLST ;START OF NAME LIST HSTIN9: CALL RDFLD ;READ THE NEXT FIELD JUMPE T1,HSTIE3 ADDI T1,1 ;COUNT THE NULL TERMINATOR IDIVI T1,5 ;CONVERT CHAR COUNT TO WORD COUNT SKIPE T2 ;ROUND UP IF NEEDED ADDI T1,1 ;... PUSH P,T1 ;SAVE ADDM T1,NAMSPC ;DECREMENT NAME SPACE LEFT SKIPLE NAMSPC ;TABLE FULL? JRST HSTIE4 MOVE T1,0(P) ;GET COUNT BACK XMOVEI T2,TMPBUF ;POINT TO NAME READ MOVE T3,NAMPTR ;NEXT EMPTY SPACE IN TABLE ADDI T3,HSTNAM ;... CALL XBLTA ;MOVE THE NAME POP P,T1 ;RESTORE COUNT PUSH P,NAMPTR ;SAVE THIS INDEX ADDM T1,NAMPTR ;UPDATE TABLE MOVE T1,TERM ;GET TERMINATOR CAIE T1,":" ;END OF LIST? JRST HSTIN9 ;NO, ONWARD FOR THE NEXT PUSH P,[-1] ;FLAG END OF LIST MOVE T2,ENTTYP ;GET ENTRY TYPE CAME T2,[HS%SRV] ;SKIP IF A HOST ENTRY JRST HST12A ;NETS AND GW'S SKIP MACHINE TYPE/OS/PROTOCOLS CALL SKPFLD ;SKIP MACHINE TYPE CALL RDFLD ;READ OPERATING SYSTEM SETZ T2, JUMPE T1,HSTI12 MOVEI T1,OPSTAB ;OPERATING SYSTEM TYPE TABLE MOVE T2,[POINT 7,TMPBUF] ;POINT TO NAME TBLUK% ERJMP .+1 TXNE T2,TL%NOM!TL%AMB ;NO MATCH? TDZA T2,T2 ;THEN NO OPSYS HRRZ T2,(T1) ;ELSE GET TABLE VALUE HSTI12: TXO T2,HS%SRV ;PRETEND THEY'RE ALL SERVERS HST12A: MOVEM T2,HSTS ;SAVE IT ;Now things are set up as follows: NUMLST points to a list of HOSTNN ;indices for this host. NAMLST points to a list of HSTNAM indices for ;its names. HSTS holds the operating system type. HRRZ T3,NUMLST ;POINT TO LIST OF NUMBERS MOVE T2,NAMIDX ;INDEX OF PRIMARY NAME IN HOSTN ;Select the primary address. We will always prefer the PRFADR address ;in the event this is our local host. Failing that, we prefer an ;address that is on PRFADR's network, which is presumably the best ;network to reach that host. Failing that, we prefer any network we ;are directly connected to, so we can avoid gateways. If all else ;fails, we'll take the first listed address. SETZM HBEST ;INITIALLY NO BEST INDEX SETZM HGOOD ;NOR A GOOD INDEX ;... HSTI13: ;... SKIPG T4,1(T3) ;GET AN INDEX JRST HSTI14 ;DONE WITH THE LIST MOVEM T2,HOSTPN(T4) ;SAVE MOVE T1,HSTS ;AND OPSYS TYPE MOVEM T1,HSTSTS(T4) ;... MOVE T1,HOSTNN(T4) ;GET THE NUMBER CAMN T1,DEFADR ;OUR DEFAULT ADDRESS IS ALWAYS BEST JRST HSTI15 ;SO SET IT AS BEST UNCONDITIONALLY CAMN T1,PRFADR ;(PROBABLY UNNECESSARY) PREFERRED ADDRESS IS JRST HSTI15 ; ALMOST AS GOOD SKIPE HBEST ;HAVE A BEST ADDRESS YET? JRST HSTI16 ;YES, NO NEED TO CONSIDER ANY OTHERS AND T1,NETMSK ;NO, GET NETWORK BYTES ONLY CAME T1,PRFNFD ;IS THIS ADDRESS ON PREFERRED NETWORK? JRST HSTI17 HSTI15: MOVEM T4,HBEST ;YES, CONSIDER IT BEST JRST HSTI16 HSTI17: SKIPE HGOOD ;NOT ON DEFAULT NET, HAVE A GOOD ADDRESS YET? JRST HSTI16 MOVE T1,HOSTNN(T4) ;NO, GET ADDRESS AGAIN CALL NETNCT ;HAVE AN INTERFACE ON THAT NET? JRST HSTI16 MOVEM T4,HGOOD ;YES, CONSIDER IT A GOOD ADDRESS HSTI16: AOJA T3,HSTI13 ;LOOP THROUGH NUMBER LIST HSTI14: HRRZ T2,NAMLST ;GET NAME LIST MOVE T3,NAMIDX ;GET INDEX INTO NAME TABLE SKIPE T1,HBEST ;GET BEST NUMBER INDEX JRST HSTI18 SKIPE T1,HGOOD ;NO BEST INDEX, GET A GOOD INDEX JRST HSTI18 HRRZ T1,NUMLST ;NO GOOD INDEX, POINT TO LIST OF NUMBERS MOVE T1,1(T1) ;USE FIRST AS DEFAULT HSTI18: SKIPG T4,1(T2) ;GET NEXT NAME ON THE LIST JRST HSTI19 ;DONE STOR T4,HSTNMP,(T3) ;SET NAME POINTER STOR T1,HSTIDX,(T3) ;SAVE NUMBER INDEX MOVX T4,1B0 ;NICKNAME FLAG HRRZ CX,NAMLST ;START OF LIST CAME T2,CX ;THIS THE FIRST NAME? IORM T4,HOSTN(T3) ;NO, FLAG AS A NICKNAME ADDI T3,1 ;INCREMENT NAME TABLE INDEX SOSG NAMCNT ;COUNT DOWN TOTAL NUMBER OF NAMES JRST HSTIE5 AOJA T2,HSTI18 ;AND NAME LIST INDEX HSTI19: MOVEM T3,NAMIDX ;SAVE NEW INDEX INTO NAME TABLE JRST HSTIN6 ;ONWARD ; TBLUK% table for operating system names OPSTAB: XWD NUMOPS,NUMOPS XWD [ASCIZ/ANTS/],.HSANT XWD [ASCIZ/ELF/],.HSELF XWD [ASCIZ/FOONEX/],.HS10X XWD [ASCIZ/FUZZ/],.HSFUZ XWD [ASCIZ/ITS/],.HSITS XWD [ASCIZ/MSDOS/],.HSDOS XWD [ASCIZ/MTIP/],.HSMTP XWD [ASCIZ/MULTICS/],.HSMLT XWD [ASCIZ/TAC/],.HSTAC XWD [ASCIZ/TENEX/],.HS10X XWD [ASCIZ/TIP/],.HSTIP XWD [ASCIZ/TOPS10/],.HSDEC XWD [ASCIZ/TOPS20/],.HST20 XWD [ASCIZ/TOPS20AN/],.HST20 XWD [ASCIZ/UNIX/],.HSUNX XWD [ASCIZ/VMS/],.HSVMS XWD [ASCIZ/WAITS/],.HSDEC NUMOPS=.-OPSTAB-1 ;GBOLX - Move to start of next line ;returns BOL - file pointer of start of this line GBOLX: MOVE T1,HTBJFN ;GET JFN BACK GBOLX1: BIN% ;READ A BYTE ERJMP HFILDN ;END OF FILE CAIE T2,.CHLFD ;EOL? JRST GBOLX1 ;LOOP RFPTR% ;READ FILE POSITION ERJMP HFILER ;FATAL MOVEM T2,BOL ;SAVE START OF THIS LINE GBOLX2: BIN% ;READ START OF NEXT LINE ERJMP HFILDN ;END OF FILE CAIE T2,";" ;COMMENT? CAIN T2,.CHCRT ;OR BLANK LINE? JRST GBOLX1 ;SKIP CAIE T2," " ;LSWP? CAIN T2,.CHTAB ;? JRST GBOLX2 ;YES BKJFN% ;BACK UP ERJMP .+1 RET ;RETURN ;RDFLD - Read next field. Terminated by a "," or ":". ;Returns ;T1/ number of characters read ;TERM -- terminating character ;TMPBUF -- holds string (Null terminated) RDFLD: STKVAR SETZM COUNT ;CLEAR FIELD LENGTH MOVE T1,[POINT 7,TMPBUF] ;POINT TO START OF BUFFER MOVEM T1,PTR ; TO STORE STRING IN SETZM TMPBUF ;FIRST WORD OF BUFFER MBZ MOVE T1,HTBJFN ;GET FILE HANDLE ; SKIP LWS RDFLD1: BIN% ;READ A BYTE ERJMP PEOF CAIL T2,140 ;LOWER CASE? TRZ T2,40 ;YES SO MAKE IT UPPERCASE CAIE T2,.CHTAB ;TAB? CAIN T2," " ;BLANK? JRST RDFLD1 ;YES RDFLD2: CAIE T2,":" ;END OF FIELD? CAIN T2,"," ;? JRST RDFLDD ;YES CAIE T2," " ;? CAIN T2,.CHTAB ;? JRST RDFLDD ;YES CAIN T2,.CHCRT ;EOL? JRST PEOLX ;ERROR CAIL T2,140 ;LOWER CASE? TRZ T2,40 ;YES, RAISE IDPB T2,PTR ;SAVE CHARACTER AOS COUNT ;COUNT IT BIN% ;READ THE NEXT ERJMP PEOF ;PREMATURE END OF FILE JRST RDFLD2 ;CONTINUE RDFLDD: CAIE T2,"," ;FIELD TERMINATOR SEEN? CAIN T2,":" ;? JRST RDFLDX ;YES CAIN T2,.CHCRT ;EOL? JRST PEOLX ;ERROR BIN% ;SKIP TWS ERJMP PEOF JRST RDFLDD ;LOOP RDFLDX: MOVEM T2,TERM ;SAVE TERMINATOR SETZ T2, IDPB T2,PTR ;NULL TERMINATE THE STRING MOVE T1,COUNT ;GET SIZE OF FIELD RET ENDSV. ;SKPFLD - Skip to next field (next ":"). SKPFLD: MOVE T1,HTBJFN SKPFL1: BIN% ;READ A BYTE ERJMP PEOF CAIN T2,":" ;START OF NEW FIELD? RET ;YES, DONE CAIN T2,.CHCRT ;END OF LINE? JRST PEOLX ;YES SO ERROR JRST SKPFL1 ;NO, CONTINUE ;RDHNUM - Read a host number. ;returns number in T1 RDHNUM: STKVAR CALL RDFLD ;Read in a field JUMPE T1,RDHNE1 MOVEI T1,4 ;Size of a number (bytes) MOVEM T1,COUNT ;Save SETZM HOST MOVE T1,[POINT 7,TMPBUF] MOVX T3,^D10 ;Read in decimal RDHNM3: NIN% ;Read part of number ERJMP RDHNE2 EXCH T2,HOST ;Get part read so far LSH T2,^D8 ;Shift over ADDM T2,HOST ;Add in new part SOSLE COUNT ;Decrement count JRST RDHNM3 ;Loop MOVE T1,HOST ;Get number back RET ;And return ENDSV. ;ERROR handlers for HSTINI and friends HSTIE1: ;ERROR ON OPENF MOVE T1,HTBJFN ;RECOVER THE JFN RLJFN% ;RELEASE THE JFN ERJMP .+1 ;IGNORE ERRORS RET ;RETURN TO CALLER HSTIE2: TMSG JRST HFILER HSTIE3: TMSG JRST HFILER HSTIE4: TMSG JRST HFILER HSTIE5: TMSG JRST HFILER RDHNE1: TMSG JRST HFILER RDHNE2: TMSG JRST HFILER ;PEOF -- premature end of file PEOF: TMSG JRST HFILER PEOLX: TMSG JRST HFILER ;HFILER - Error printout routine. HFILER: MOVE T1,HTBJFN ;Get JFN RFPTR% ;Read current file position ERJMP .+1 PUSH P,T2 ;Save MOVE T2,BOL ;Get start of line pointer SFPTR% ;... ERJMP .+1 SUBM T2,0(P) ;Difference HFILE2: MOVE T1,HTBJFN BIN% ;Read a byte ERJMP HFILDN ;End of file MOVX T1,.PRIOU BOUT% ;Write to primary output ERJMP .+1 SOSE 0(P) ;Count down to error position JRST HFILE3 MOVEI T2,"^" BOUT% ERJMP .+1 HFILE3: CAIE T2,.CHLFD ;End of line? JRST HFILE2 ;Loop ;HFILDN - Routine to finish up HOSTS.TXT HFILDN: ;Here when finished HRRZ T1,NAMIDX ;Get count of host names MOVNM T1,MHOSTS ;Save MOVE T1,HTBJFN ;Get back JFN CLOSF% ERJMP .+1 MOVE P,SAVEP ;Get back stack fence RETSKP ;And return ENDTV. ;PERROR - Print out the erring line in the file. ;Called P1 - JFN ;P2 - Byte index of BOL PERROR: MOVE T1,P1 RFPTR ; Read where we are TRN MOVE T3,T2 ; Save it in T3 MOVE T2,P2 ; Get BOL pointer SFPTR ; set back to beginning of line TRN PERLP: MOVE T1,P1 RFPTR ; Read where we are TRN CAMN T2,T3 ; Are we where error occured? CALL PMARK ; Yes, Mark it CALL GCH1 ; Get a character MOVEI T2,.CHLFD ; Fake EOL if done CAIN T2,.CHLFD ; End of line? JRST PERLPX ; Yes, exit MOVE T1,T2 ; Get caharacter PBOUT ; Type it out JRST PERLP ; And loop ; PMARK, Mark where error occured PMARK: PUSH P,T1 ; Save AC1 MOVEI T1,"^" ; A convenient character PBOUT ; Write it out POP P,T1 ; And restore it RET ; And back to caller ; PERLPX - Done with error line PERLPX: HRROI T1,[ASCIZ / /] PSOUT ; Write a carridge return RET ; Return when done ;GBOL - Get Set pointer to the beginning of a line. ;Returns +1 if EOF hit ;else +2 with T1 - JFN ;P2 - Byte number of beginning of line GBOL: MOVE T1,P1 ; Get JFN CALL GCH ; Get a character RET CAIN T2,.CHLFD ; Line feed? JRST GBOL ; Yes, blank line BKJFN ; Backup over that character MOVE T1,P1 ; Restore JFN RFPTR ; get pointer NOP MOVE P2,T2 ; Save it RETSKP ; And return with it ;GCH - read the next non-comment, non-blank character. ;returns +2 if character (character in T2) ;+1 if EOF GCH: MOVE T1,P1 ; Get JFN GCH2: CALL GCH1 ; Get a byte RET ; EOF CAIN T2,";" ; Comment, JRST GCHSMC ; ignore it CAIE T2,.CHTAB ; TAB? CAIN T2," " ; or SPACE? JRST GCH2 ; Skip it RETSKP ; Else return with character GCH1: CALL GBIN ; BIN a byte RET ; EOF CAIE T2,.CHCRT ; Ignore CAIN T2,.CHFFD ; and form-feed JRST GCH1 ; .. RETSKP ; return with character GCHSMC: CALL GBIN ; Get a byte RET ; EOF CAIN T2,.CHLFD ; Until end of line RETSKP ; when we return JRST GCHSMC ; Else lop GBIN: BIN ; get a char ERJMP R ; If end of file return +1 JUMPN T2,RSKP ; If good JRST GBIN ; flush NULLS SUBTTL GTFIL - GTJFN Routine for HSTINI and ADRINI ;Get a JFN for a file, and setup ACs, used in HSTINI and ADRINI, ;called with T2 pointing to file name returns +2 if successful with ;AC's setup P1 - Contains JFN GTFIL: MOVX T1, ; Olf file, short GTJFN ; GEt JFN RET ; Can't file not found MOVE P1,T1 ;Save JFN in P1 MOVX T2,7B5+OF%RD ; Open for reading OPENF ; .. JRST [ MOVE T1,P1 ; If fails, get JFN back RLJFN ; Release it NOP RET] RETSKP ; Succesful return SUBTTL ADRINI - Routine to Read SYSTEM:SITE-ADDRESS.TXT ;ADRINI ;Reads in the file SYSTEM:SITE-ADDRESS.TXT and initializes the ;interface tables from it. Called from HSTINI at system startup, does ;skip return if successful. ; AC usage ; P1 - JFN of input file ; P2 - Local address once read ; P3 - NCT associated with that address, if any ADRINI:: ; Read interface descriptor file IFE REL6, SAVEPQ ; Save registers clobbered STKVAR > HRROI T2,[ASCIZ /SYSTEM:INTERNET.ADDRESS/] CALL GTFIL ; Get the file RET SETZ T1, ; clear an index ADRIN1: SKIPN NLHOST(T1) ; slot used? JRST ADRLP0 ; no, done with table, enter main loop SETOM NLHOST(T1) ; empty that slot AOJA T1,ADRIN1 ; and loop ADRLP0: CALL GBOL ; Start off a line JRST ADRDUN ; Done with file MOVE T1,P1 ; Get JFN ; Now read in the interface type MOVE T3,[POINT 7,BUFFER] ; point to temp buffer ADGINM: CALL GCH JRST ADREOF ; enf of file CAIN T2,"#" ; end of name? JRST [ SETZM NONUM ; flag that there is a number JRST ADGINX] ; and leave loop CAIN T2,.CHLFD ; end of line? JRST ADIERR ; error CAIN T2,"," ; or field delimiter? JRST [ SETOM NONUM ; flag that number is 0 JRST ADGINX] ; and join below IDPB T2,T3 ; save character in string JRST ADGINM ; and loop ; Here if error in interface descriptor ADIERR: HRROI T1,[ASCIZ /Error in interface descriptor/] JRST ADRERR ; goto error printer ADGINX: SETZ T2, ; put a null IDPB T2,T3 ; at end MOVEI T1,INTNAM ; point to type table MOVE T2,[POINT 7,0] ; make a pointer ADDI T2,BUFFER ; to the string buffer TBLUK ; and look it up TXNE T2,TL%NOM!TL%AMB ; match? JRST ADIERR ; error HRRZ T4,(T1) ; get entry SETZ P3, ; assume no NCT MOVE T1,P1 ; GET JFN SKIPE NONUM ; is there a number? JRST [ SETZ T2, ; no, use 0 JRST ADGIN2] ; and skip reading it MOVEI T3,^D10 ; read in decimal NIN JRST ADIERR ; error ADGIN2: BKJFN ; Backup over terminator NOP ; Shouldn't fail CAIN T4,NT.NIN ; No particular interface? JRST ADGNUM ; right, No NCT associated with it ; Now find the NCT for the interface XMOVEI P3,NCTVT ; point to vector table ADFINT: MOVE P3,(P3) ; get next in list JUMPE P3,ADIERR ; error if no more LOAD T1,NTDEV,(P3) ; get interface type CAIE T1,(T4) ; Same as we're looking for? JRST ADFINT ; No, try next SOJGE T2,ADFINT ; Try another if not right number ; Read in the address on that interface ADGNUM: CALL NXTFLD ; read to the next field HRROI T4,[ASCIZ/ Invalid address /] CALL ADG4DB ; Get 4 decimal bytes into T1 ; Goes ADRERR on error MOVEM T1,P2 ; Get into right register CALL HSTHSH ; Hash it into table JUMPL T2,NETFUL ; No room for number MOVEM P2,HOSTNN(T2) ; Put number in table MOVX CX,HS%UP!HS%SLF!HS%VAL ; It is me , and valid status IORM CX,HSTSTS(T2) ; Mark it so ; ... ; ... SETZ T2, ; clear an index ADGNM1: SKIPLE NLHOST(T2) ; anything in this slot? AOJA T2,ADGNM1 ; No, try next SKIPL NLHOST(T2) ; empty? JRST NETFUL ; No, table overflow. MOVEM P2,NLHOST(T2) ; save number JUMPE P3,ADGNM2 ; Skip next if no NCT associated with number MOVEM P2,NTLADR(P3) ; Set local address NETNUM T1,P2 ; Get the network number MOVEM T1,NTNET(P3) ; Set it in NCT ADGNM2: MOVE T1,P1 ; get JFN back BKJFN ; Back over last terminator NOP ADRLP3: CALL GCH ; Read it in JRST ADREOF ; Eof error CAIN T2,.CHLFD ; Was it a linefeed? JRST ADRLP0 ; Yes, loop ; Must be a comma, means a type name MOVE T3,[POINT 7,BUFFER] ; point to buffer ADGTYP: ; Here to read in a modifier CALL GCH ; Get first char of keyword JRST ADREOF ; Error CAIE T2,"," ; end of field? CAIN T2,.CHLFD ; line feed? JRST ADGTYX ; got full field CAIN T2,":" ; Value? JRST ADGTYX ; yes IDPB T2,T3 ; else save in string JRST ADGTYP ; and loop ADGTYX: SETZ T2, ; put a null IDPB T2,T3 ; at end of string MOVEI T1,TYPNAM ; point to type table MOVE T2,[POINT 7,0] ; and to string ADDI T2,BUFFER ; in the buffer TBLUK ; and look it up in table TXNE T2,TL%NOM!TL%AMB ; good name? JRST [ HRROI T1,[asciz /Bad network type descriptor/] JRST ADRERR] ; no MOVE T1,(T1) ; get routine address CALL (T1) ; go to it MOVE T1,P1 ; Get JFN BKJFN ; Back up NOP ; shouldn't fail JRST ADRLP3 ; and loop ADDFLT: ; Here on DEFAULT keyword NETNUM T1,P2 ; Get the network number MOVEM T1,DEFNET ; Save as default network number SKIPN PRFNET ; Preferred network set up? MOVEM T1,PRFNET ; Save as preferred network number MOVE T2,P2 ; Get number ANDX T2,-1B27 ; mask off network number (Class C) CAIG T1,177777 ; Class B or A? ANDX T2,-1B19 ; Mask for class B CAIG T1,377 ; Class A? ANDX T2,-1B11 ; yes, mask appropriately MOVEM T2,NETFLD ; Set as default network field MOVEM P2,DEFADR ; Save as default address SKIPN PRFNFD ; Preferred network field set up? MOVEM T2,PRFNFD ; Set as preferred network field SKIPN PRFADR ; Preferred address set up? MOVEM P2,PRFADR ; Save as preferred address ; Kludge up the 8 bit host address MOVE T2,P2 ; get number again ROTC T2,-6 ; Save IMP number LSH T2,-^D10 ; Flush middle bits ROTC T2,6 ; Combine Host and IMP ANDI T2,377 ; Round to 8 bits MOVEM T2,NOHOST ; Save in proper cell RET ; and return ADDPRF: ; Here on PREFERRED keyword NETNUM T1,P2 ; Get the network number MOVEM T1,PRFNET ; Save as preferred network number MOVE T2,P2 ; Get number ANDX T2,-1B27 ; mask off network number (Class C) CAIG T1,177777 ; Class B or A? ANDX T2,-1B19 ; Mask for class B CAIG T1,377 ; Class A? ANDX T2,-1B11 ; yes, mask appropriately MOVEM T2,PRFNFD ; Set as preferred network field MOVEM P2,PRFADR ; Save as preferred address RET ADNCP: ; Here on NCP keyword MOVEI T1,NT.NCP ; get NCP network type STOR T1,NTTYP,(P3) ; save in NCT MOVE T1,NTNET(P3) ; Get the network number CAILE T1,^D255 ; Valid type A address? JFCL ; error *** ; once host tables are right, find hosts for this net and set in NCP tables RET ; and done ; Here on PACKET-SIZE keyword, next parameter is the maximum packet ; size for this interface in decimal bytes ADPSIZ: MOVE T1,P1 ; Get JFN MOVEI T3,^D10 ; decimal NIN JRST [ HRROI T1,[ASCIZ /Invalid PACKET-SIZE /] JRST ADRERR] ; error MOVEM T2,NTPSIZ(P3) ; save the size RET ; and return ; Here on LOGICAL-HOST-MASK keyword, next parameter is the 32-bit mask ; for this interface in decimal bytes ADLHM: HRROI T4,[ASCIZ / Invalid LOGICAL-HOST-MASK value field/] CALL ADG4DB ; Read 4 decimal bytes ; Goes ADRERR on error MOVEM T1,NTNLHM(P3) ; Save the mask RET ; and return ; ADG4DB - Read in 4 decimal bytes ; T4/ String pointer to error message ; P1/ JFN ; Returns+1 Success, T1 has address ; ADRERR Error detected ADG4DB: PUSH P,BHC ; Save a blank MOVEI Q1,4 ; There are 4 fields to an address ADG4D2: MOVE T1,P1 ; Get JFN back MOVX T3,^D10 ; Again decimal NIN JRST [ADJSP P,-2 ; Pop address & return MOVE T1,T4 ; Error message JRST ADRERR] ; Error exit IORM T2,0(P) ; Merge in latest part SOJLE Q1,ADG4D8 ; All parts read? MOVE T2,0(P) ; No, get so far LSH T2,^D8 ; Shift over one byte MOVEM T2,0(P) ; Store back JRST ADG4D2 ; Loop through all 4 fields ADG4D8: POP P,T1 ; Get full address RET ; Error handler routine NETFUL: POP P,T4 ; Clean stack BUG.(HLT,NORMIA,MNETDV,SOFT,,,< Cause: Multinet is unable to allocate space in the network hash table for a local address from the SYSTEM:INTERNET.ADDRESS file. >) HRROI T1,[ASCIZ /No room in host tables for local address/] ADRERR: PSOUT ; Write error string HRROI T1,[ASCIZ / In ADDRESS file /] PSOUT CALL PERROR ; Print offending line JRST ADRLP0 ; And loop ADREOF: HRROI T1,[ASCIZ /Premature EOF in ADDRESS file/] PSOUT CALL PERROR ; Print bad line ADRDUN: CLOSF ; Close the JFN NOP ; Don't worry if fails MOVE P2,NLHOST+0 ; Get default default network SKIPN DEFADR ; was default address set? CALL ADDFLT ; No, use this one RETSKP ; And return succesfully ; Here to skip to the next field of keyword NXTFLD: CALL GCH ; Get character RET ; Return now if EOF CAIE B,"," ; comma? CAIN B,.CHLFD ; EOL? RET ; yes, return now JRST NXTFLD ; else read more ; Tables for address file keywords ; Start a table definition DEFINE TABLE(NAME)< NAME: XWD ..'NAME,..'NAME ..TABLE==0 ; Init count > DEFINE TABEND(NAME) < ..'NAME==..TABLE> DEFINE KEY(NAME,DATA) < XWD [ASCIZ /NAME/],DATA ..TABLE==..TABLE+1 ; Increment the count of entries > ; Table of interface type names TABLE(INTNAM) KEY AN20,NT.ANX ; AN20 Interface IFN REL6, ; KLIPA Interface KEY IPNI,NT.NIP ; KLNI Interface TABEND(INTNAM) ; Take of modifiers TABLE(TYPNAM) KEY DEFAULT,ADDFLT ; This is the 'primary' address for host KEY LOGICAL-HOST-MASK,ADLHM ; Logical host mask for this network KEY NCP,ADNCP ; network uses Arpanet NCP protocal KEY PACKET-SIZE,ADPSIZ ; Maximum packet size allowed KEY PREFERRED,ADDPRF ; This is the 'preferred' address for host TABEND(TYPNAM) SUBTTL CVHST% JSYS - Convert Host Number to String REPEAT 1,< ;THIS JSYS IS VERY TEMPORARY IFE REL6,<.CVHST::> IFN REL6, MCENT SETOB P1,P2 ;NO NAME YET MOVE T1,T2 ;GET HOST NUMBER IN RIGHT PLACE CALL GTHNTS ;CONVERT NUMBER TO STRING JUMPL P1,[EMRETN(CVHST1)] ;STRING NOT FOUND LOAD P4,HSTNMP,(P1) ;GET THE NAME POINTER SETSEC P4,INTSEC ;INTO PROPER SECTION ADDI P4,HSTNAM ;POINT TO NAME MOVE P3,[!1B12] ;EXTENDED POINTER WORD UMOVE T1,1 ;GET DESINATION CALL GTHSOU ;WRITE STRING TO USER SPACE UMOVEM T1,1 ;WRITE UPDATED POINTER TO USER SPACE JRST SKMRTN > SUBTTL GTHST% JSYS ;The GTHST% JSYS, Get information on a Host or Network, Moved here ;from NETWRK because expansion allows it to be general over all ;Interfaces rather than just NCP. Called as in JSYS documentation ;The following register conventions are used in it ; ;P1 - Index into Name tables ;P2 - Index into Hash tables ;P3,P4 - Byte pointers (extended or otherwise) ;P5,P6 - Scratch IFE REL6,<.GTHST::> IFN REL6, MCENT SKIPL T1 ;CHECK RANGE OF FUNCTION CODE CAIL T1,GTHMAX RETERR (ARGX02) ;BAD FUNCTION CODE SETOB P1,P2 ;NO NUMBER NOR NAME XCT GTHDSP(T1) ;DO THE FUNCTION GTHDSP: JRST GTHSIZ ;(00)GET NAME TABLE SIZE JRST GTHIDX ;(01)INDEX INTO NAME SPACE JRST GTHNUM ;(02)CONVERT NUMBER TO STRING JRST GTHSTR ;(03)CONVERT STRING TO NUMBER JRST GTHHNN ;(04)STATUS BY NUMBER JRST GTHHNI ;(05)STATUS BY INDEX JRST GTHNHN ;(06)Get local number on a network JRST GTHNST ;(07)Get status table of a network JRST GTHNLA ;(10)Get local addresses on networks GTHMAX==.-GTHDSP ;NUMBER OF FUNCTIONS GTHSXX: MOVX T4,HS%NCK ;SET THE NICKNAME FLAG SKIPL P1 ;NO NAME SKIPL HOSTN(P1) ;DID WE HAVE ONE? SKIPA T4,HSTSTS(P2) ;NO IOR T4,HSTSTS(P2) ;RETURN STATUS UMOVEM T4,4 MOVE T3,HOSTNN(P2) ;RETURN HOST NUMBER UMOVEM T3,3 JRST SKMRTN ;SKIP RETURN SUBTTL GTHST% JSYS - Individual Functions GTHSIZ: HRLZ T2,MHOSTS ;-LENGTH,,1ST INDEX UMOVEM T2,2 ;RETURN TO USER MOVSI T3,-NHOSTS ;NUMBER OF HOST SLOTS UMOVEM T3,3 ;RETURN TO USER MOVE T4,PRFADR ;GET PREFERRED ADDRESS UMOVEM T4,4 ;RETURN TO USER JRST SKMRTN ;DONE GTHIDX: MOVN T1,MHOSTS ;GET NUMBER OF HOST NAMES IN USE HRRZ P1,T3 ;CHECK RANGE OF HOST NAME INDEX CAML P1,T1 RETERR (GTJIX1) ;BAD INDEX TO HOSTN SETSEC P1,INTSEC ;IN THE RIGHT SECTION LOAD P2,HSTIDX,(P1) ;GET INDEX INTO HOSTNN SETSEC P2,INTSEC ;AND IN THE PROPER SECTION JRST GTHTUS ;WRITE THE STRING GTHNUM: MOVE T1,T3 ;GET HOST NUMBER CALL GTHNTS ;CONVERT NUMBER TO STRING JUMPL P1,[RETERR(GTHSX3)] ;NO STRING FOR THAT NUMBER ; Write host string to user space GTHTUS: LOAD P4,HSTNMP,(P1) ;GET THE NAME POINTER SETSEC P4,INTSEC ;INTO PROPER SECTION ADDI P4,HSTNAM ;POINT TO NAME MOVE P3,[!1B12] ;EXTENDED POINTER WORD UMOVE T1,2 ;GET DEST CALL GTHSOU ;WRITE STRING UMOVEM T1,2 ;UPDATE USER'S POINTER JRST GTHSXX ;EXIT GTHNTS: CALL CVNHST ;MAKE IT NEW FORMAT CALL HSTHSH ;GET ITS INDEX RET ;NOT THERE MOVE P2,T2 ;SAVE INDEX SKIPG P1,HOSTPN(T2) ;HAS IT A NAME? SETO P1, ;NO RET GTHSTR: CALL GTHSTN ;CONVERT STRING TO NUMBER SKIPL T2 ;VAILD STRING FOUND? RETERR(GTHSX5) ; no, return error MOVE P1,T2 ; Save SETSEC P1,INTSEC ; in the right section SKIPN T1,T4 ;COPY HOST NUMBER RETERR(GTHSX2) ;NO HOST FOUND....ERROR CALL CVNHST ; Convert number to 32 bits if necessary CALL HSTHSH ; Look it up in tables RETERR(GTHSX2) ; Not there MOVE P2,T2 ; Save that index JRST GTHSXX ;EXIT ; Convert host string to a number GTHSTN: STKVAR <> MOVEI P3,GTHSBF ; Point to buffer HRLI P3,() ; .... CALL GTHSIN ;GET STRING FROM USER MOVEI T1,GTHSBF ;MAKE BYTE POINTER HRLI T1,() CALLRET HSTLUK ;LOOKUP NAME GTHHNI: HRRZ T1,T3 ;GET INDEX CAIL T1,NHOSTS ; Compare to table size RETERR (GTJIX1) ; Bad index SETSEC T1,INTSEC ; Put in proper section LOAD T1,HSTIDX,(T1) ; get index to tables SETSEC T1,INTSEC ; Again in right section SKIPA T1,HOSTNN(T1) ; Get number GTHHNN: MOVE T1,T3 ;GET HOST NUMBER CALL GTHNTS ;CONVERT NUMBER TO INDEX JUMPL P2,[RETERR (GTHSX1)] ;UNKNOWN HOST JRST GTHSXX ;EXIT ; Move string from user space GTHSIN: UMOVE T1,2 ; GET POINTER MOVE T4,[XCTBU [ILDB T2,T1]] TLNN T1,777777 ; IF JFN DO THE JSYS MOVE T4,[BIN] TLC T1,777777 ; CHECK FOR LH -1 TLCN T1,777777 HRLI T1,() ; USE STANDARD POINTER MOVEI P5,MAXLC ; UP TO 39 CHARS GTHSIL: XCT T4 ; DO RIGHT OPERATION SOSG P5 ; Decrement counter MOVEI T2,0 ; AFTER MAXLC CHARS FORCE NULL CAIL T2,140 ; LOWER CASE? TRZ T2,40 ; YES, RAISE CAIG T2,40 ; END ON SPACE OR LESS MOVEI T2,0 ; terminating with null IDPB T2,P3 ; Stick it in destination string JUMPG T2,GTHSIL ; loop if more to it CAME T4,[BIN] ; DON'T BACKUP A TTY BKJFN ; backup to before termination NOP ; (shouldn't fail) UMOVEM T1,2 ; restore updated pointer RET ; and return ; Write string to user space ; Called with T1 - Dest in user space ; Returns +1 T1 updated pointer GTHSOU: MOVE T4,[XCTBU [IDPB T2,T1]] TLNN T1,777777 ; IF JFN DO THE JSYS MOVE T4,[BOUT] TLC T1,777777 ; CHECK FOR LH -1 TLCN T1,777777 HRLI T1,() ; USE STANDARD POINTER GTHSOL: ILDB T2,P3 ; Get next byte JUMPE T2,GTHSOX ; If a null XCT T4 ; DO RIGHT OPERATION JRST GTHSOL ; Loop GTHSOX: CAMN T4,[BOUT] ; Don't backup a JFN RET ; Retrun now if a JFN XCT T4 ; Stick on NULL BKJFN ; Backup destination NOP ; ... RET ; and return ; Get hostnumber on a network ; Accepts T2 - Network number, or host number on the net ; Returns +1 if no interface on that network ; +2 if we have one, T2 - Hostnumber GTHNHN: MOVE T1,T2 ; Get number CALL NETNCT ; Look for an NCT for that net RETERR (GTHSX5) ; Return error if none MOVE T1,NTLADR(P1) ; Get our number there UMOVEM T1,T2 ; Restore it to user JRST SKMRTN ; And do a skip return ; Get status of a network ; Accepts T2 - Network number or host number on the net ; T3 - Pointer to where to store data ; T4 - -Number of words,,offset of first ; Returns +1 if no such network or invalid offset ; +2 if good arguments with data in table GTHNST: MOVE T1,T2 ; Get number CALL NETNCT ; Look it up RETERR(GTHSX5) ; Bad number HLRE T1,T4 ; Get number wanted MOVMS T1 ; Magnitude ADDI T1,(T4) ; Add in first CAILE T1,NTXUPP-NTRDY+1 ; Size of area RETERR(GTJIX1) ; Bad XMOVEI P1,NTRDY(P1) ; Point to start of area ADDI P1,(T4) ; Add in offset of fist word XCTU [HRR T4,T3] ; Setup an AOBJN destination pointer GTHNS0: MOVE T1,0(P1) ; get a word UMOVEM T1,0(T4) ; Store it AOS P1 ; Increment source pointer AOBJN T4,GTHNS0 ; And loop through all desired JRST SKMRTN ; And do a skip return ; Get Local Network Addresses ; Accepts T3/ Address of where to store data ; T4/ Number of words ; Returns +1 if invalid offset ; +2 if good arguments with data in table ; Updates callers T4 count of items returned. GTHNLA: ; Get local addresses SKIPG T4 ; Legit count? RETERR(ARGX24) ; No MOVE P1,NCTVT ; Get address of the first NCT JRST GTHLA3 ; Report on this NCT GTHLA1: ; Get the next NCT LOAD P1,NTLNK,(P1) ; Get address of the next NCT JUMPN P1,GTHLA3 ; Go report on this NCT GTHLA2: ; Here when all NCTs examined XCTU [SUB T4,4] ; Fix up the count XCTU [MOVNM T4,4] ; Save the count for the caller JRST SKMRTN ; And do a skip return GTHLA3: ; NCT Chasing loop SKIPG T1,NTLADR(P1) ; Get address on this NCT JRST GTHLA1 ; No address defined. get next NCT. UMOVEM T1,(T3) ; Save interface address for user SOJLE T4,GTHLA2 ; Count exhausted? AOJA T3,GTHLA1 ; No so do the next NCT SUBTTL ATNVT% JSYS and NETRDY GETAB Table ; ATtach connection to NVT ; Call: 1 ; [Receive] jfn of opened network connection (JCN for TCP) ; 2 ; Send jfn of open network connection (NCP only) ; ATNVT ; Returns ; +1 ; Cannot attach ; +2 ; Ok. the jfn is released, ac 1 has line number of ; ; Attached pty. IFE REL6,<.ATNVT::> IFN REL6, MCENT TXNE T1,AN%TCP ; Attach TCP Virtual Terminal? JRST TATNVT ; Yes, go to TCP code IFN REL6, ; we were given a JFN IFE REL6, ; we were given a JFN ; GNTRDY ; Get the NETRDY table. Attempts to find the data from the NCT for ; the primary network IFE REL6, IFN REL6, MOVE T1,DEFADR ; get primary address CALL NETNCT ; Find an NCT for it RETERR() ; Error MOVE T1,@GNTAB(T2) ; get an entry RET ; And return ; Indirect table for deriving the data GNTAB: IFIW!B17+NTRDY ; NETRDY From the NCT IFIW!B17+NETON ; As NETON IFIW+NETENT ; NETENT has its own cell IFIW!B17+NTIUPT ; NCPUPT IFIW+IGDMSG ; Last Imp going down message IFIW!B17+NTXDNT ; Last ready line drop IFIW!B17+NTXUPP ; last ready line up time IFIW+IGDTIM ; Last Imp going down message time SUBTTL HSTLUK - Lookup Host Names HSTLUK: SAVEPQ ;GET SOME ROOM MOVE Q1,T1 ;SAVE POINTER MOVEI T3,10 NIN ;TRY TO GET A NUMBER JRST HSTLKI ;TRY A NAME MOVE Q1,T1 ;SAVE UPDATED POINTER MOVE T1,T2 CALL CVNHST MOVE T4,T1 ;RETURN HOST NUMBER MOVE T1,Q1 ;AND UPDATED POINTER SETZ T2, ;HOST NUMBER FOUND RET HSTLKI: HRLZ T2,MHOSTS ;SCAN THE TABLE PUTSEC P1,INTSEC ;IN THIS SECTION HSTLK0: MOVE T1,Q1 ;DO NAME POINTER LOAD T4,HSTNMP,(P1) ADD T4,[XWD INTSEC,HSTNAM] ;POINT TO THE TABLE MOVE T3,[!1B12] ;MAKE EXTENDED POINTER HSTCMP: ILDB Q2,T1 ;COMPARE A STRING ILDB Q3,T3 SKIPN Q2 ;NULL BYTE? JUMPE Q3,HSTCM2 ;YES. IS THE OTHER BYTE BYTE ALSO? CAIN Q2,(Q3) ;NOT NULL. ARE THEY THE SAME? JRST HSTCMP ;YES SO KEEP COMPARING HSTLK2: AOS P1 ;POINT TO NEXT SLOT IN TABLE AOBJN T2,HSTLK0 ;STEP TO NEXT HOST SETZ T4, ;NO HOST FOUND RET HSTCM2: LOAD T4,HSTIDX,(P1) ;WE HAVE A MATCH. GET THE INDEX SETSEC T4,INTSEC ;IN THE CORRECT SECTION MOVE Q3,HSTSTS(T4) ;GET ENTRY STATUS BITS TXNN Q3,HS%SRV ;HOST NAME? JRST HSTLK2 ;NO, A GW OR NET. SKIP OVER IT. MOVE T4,HOSTNN(T4) ;GET THE HOST NUMBER HRR T2,P1 ;GET THE NAME STRING ADDRESS RET ;AND RETURN TO CALLER CVNHST:: ;CONVERT HOST NUMBER IN AC1 TO NEW FORMAT CAMN T1,[-1] ;IF -1 USE LOCAL HOST NUMBER MOVE T1,PRFADR ;DEFAULT LOCAL HOST AND T1,[HSTMSK] ;CUT DOWN TO SIZE TLNE T1,37700 ;ANY NETWORK NUMBER STUFF? RET ;YES SO RETURN ANDI T1,377 ;TURN OFF ALL OTHER BITS TRZE T1,100 ;SET THE HOST BITS TRO T1,200000 ;UNITS HOST BIT TRZE T1,200 TRO T1,400000 ;TWOS HOST BIT JUMPE T1,R ;IF ZERO LEAVE IT ZERO IOR T1,NETFLD ;ADD DEFAULT NETWORK NUMBER RET TNXEND END