;-*- Mode:MIDAS; -*- ; Netwrk subroutines ; Canonical location is [MIT-AI] SYSNET;NETWRK > ; All changes must be made or copied to this location, ; or they will be lost! ; ; New version partially fixed for HOSTS3, 2/17/83. --KLH ; ITS/20X version, 4/8/83. --Ian ; ; $$ARPA is understood to mean Internet; any address with NE%UNT off ; qualifies as an Internet address. ; ;*************************************************************************** ;******* In order to help clean things up and keep stuff working, ;******* please enter here the names of any programs you are aware of ;******* which insert this file! This will assure that future changes ;******* will not break your favorite software. ; AI:SYSENG;CRTSTY ; AI:SYSENG;TELSER ; AI:SYSEN1;HSTLOK ; AI:SYSEN1;PWORD ; AI:SYSEN1;UP ; AI:SYSEN2;PEEK ; AI:SYSEN2;TELNET ; AI:KSC;COMSAT ; AI:SYSNET;FTPS ; AI:SYSNET;FTPU ; AI:KSC;QMAIL ; MX:MT;NTELSUP ; AI:SYSEN1;SENDER ; AI:BAWDEN;PROBE IFNDEF ITS,[ IFE .OSMID-SIXBIT/ITS/,ITS==1 .ELSE ITS==0 ];IFNDEF ITS IFNDEF 20X,[ IFE .OSMID-SIXBIT/TWENEX/,20X==1 .ELSE 20X==0 ];IFNDEF 20X IFNDEF 10X,[ IFE .OSMID-SIXBIT/TENEX/,10X==1 .ELSE 10X==0 ];IFNDEF 10X TNX==20X\10X ; This is the normally used switch. .AUXIL ;Don't mention all my symbols in crefs of programs that use me. .BEGIN NETWRK ;Calling Conventions: ; ;All subroutines herein are called by PUSHJ P, ;and take their skip return if successful, non-skip if error. ;Arguments are passed in ACs A,B,C,D,E. ACs T and TT are freely smashable. ;However, "low level" subroutines generally take arguments and ;return values in T and TT and leave A-E alone. ;Subroutines may alter A-E as documented with each routine. ;The only ACs assumed are A,B,C,D,E,T,TT,P. TT=T+1 is assumed. ; ;The following externally defined symbols are assumed: ; ;GETCHR Routine to read character for HOSTNM/SYMGET routine. ; Returns in T, clobbers TT, skip return unless no chars available. ; ;PUTCHR Routine to write character for HOSTNM/SYMGET and ANALYZE routines. ; Char is passed in T (!!). Mustn't clobber any ACs. Never skips (!!). ; ;SPCHAN Routine to handle special characters for HOSTNM/SYMGET. ; Char is passed in T, number so far read in TT. ; Non-skip return to restart reader, skip to ignore char. ; ;DEBUG Nonzero if debugging. SERVE doesn't time out, and .VALUE'S ; if anything bad happens. ; ;The usual values for ITS predefined symbols are assumed. ; ;The NETWRK subroutines are enclosed in a MIDAS begin block to avoid ;confusion in the local tags. All code produced is pure. Any impure ;locations needed are created as MIDAS variables (eg, .VECTOR). ;Print file version .TYO6 .IFNM1 .TYO 40 IFN ITS,.TYO6 .IFNM2 IFN TNX,[ DEFINE TYPN ARG PRINTX "ARG" TERMIN RADIX 10. TYPN \.IFVRS RADIX 8. ] ;TNX PRINTX / included in this assembly. / qmtch==.qmtch ;In case the .INSRTer didn't have this set, turn it on so that .qmtch==-1 ;we use "foo" construct, for other-assembler compatability. ;The following symbols are used to select only necessary routines IFNDEF $$HST3, $$HST3==1 ; 1 = use HOSTS3 format and file. IFNDEF $$HOSTNM, $$HOSTNM==0 ;Host name file lookup routines. IFNDEF $$SYMGET, $$SYMGET==0 ;Interactive symbol input routine IFNDEF $$SYMLOOK,$$SYMLOOK==0 ;table lookup routine. IFNDEF $$HSTMAP, $$HSTMAP==0 ;HSTMAP, HSTUNMAP, HSTSRC host name table rts IFNDEF $$HSTSIX, $$HSTSIX==0 ;Sixbit host name abbreviation IFNDEF $$MIT, $$MIT==1 ;Flush "MIT-" in HSTSIX IFNDEF $$OWNHST, $$OWNHST==0 ;Routine to get own host address IFNDEF $$HSTCMP, $$HSTCMP==0 ;Routine to compare two host addresses IFNDEF $$NETSRC, $$NETSRC==0 ;NETSRC routine to get network names IFNDEF $$ICP, $$ICP==0 ;Initial Connection Protocol IFNDEF $$SERVE, $$SERVE==0 ;Respond to an ICP (for a server) IFNDEF $$SYSDBG, $$SYSDBG==0 ;ARPSRV, CHASRV shouldn't handle SYSDBG itself IFNDEF $$CONNECT, $$CONNECT==0 ;Network Connection Routine (ARPCON, CHACON) IFNDEF $$SIMPLE, $$SIMPLE==0 ;Simple-transaction for Chaosnet IFNDEF $$ANALYZE, $$ANALYZE==0 ;Network Error Analysis Routine IFNDEF $$ERRHAN, $$ERRHAN==0 ;Automatic ANALYZE in ARPCON, CHACON, etc. IFNDEF $$LOGGING, $$LOGGING==0 ;Network library usage logging IFNDEF $$UPTM, $$UPTM==1 ;ANALYZ should give estimated time up again IFNDEF $$CVH, $$CVH==0 ;1 to include host number conversions IFNDEF $$LOOK, $$LOOK==0 ;1 to support no network (just lookups) IFNDEF $$CHAOS, $$CHAOS==0 ;1 to support Chaosnet hosts and rtns IFNDEF $$ARPA, $$ARPA==0 ;1 to support Arpanet hosts and rtns IFNDEF $$TCP, $$TCP==0 ;1 to support /TCP switch & routines IFN $$TCP*$$SYMLOOK,[ $$ARPA==1 ;arpa must be set for TCP to work here ] IFNDEF $$ALLNET,[ ; 1 for lookup rtns to support all nets IFE $$HST3,$$ALLNET==0 ; Including ones ITS doesn't handle. .ELSE $$ALLNET==$$ARPA ] IFN $$ARPA,[ IFNDEF ARPHST, .SCALAR ARPHST ] IFN $$TCP,[ IFNDEF USENCP, .SCALAR USENCP IFNDEF USETCP, .SCALAR USETCP ] IFNDEF $$PROMPT, $$PROMPT==1 ;1 to use default prompt "Host: " IFNDEF $$TCPTO, $$TCPTO==15.*30. IFNDEF $$CHATO, $$CHATO==15.*30. ;;; Summary of entry-points and calling sequences. ;;; Note that all routines listed here skip-return on success, clobber T and TT. ;;; ;;; SYMGET(E:table_p) => A:symbol_value, B,C,D,E:junk ;;; SYMLOOK(A:input, E:table_p) => B:result_descr, T:numeric_value ;;; HSTMAP(A:page#, B:channel#) => RH(A):next_free_page ;;; HSTUNMAP() ;;; HSTSRC(B:host#) => A:TIP_flag,,name_p, D:site_p ;;; HOSTNM() => A:host#, TT:network#, B,C,D,E:junk ;;; HSTLOOK(A:input) => A:host#, TT:network#, B:result_desc, E:junk ;;; HSTSIX(A:host#) => A:sixbit_host_name ;;; OWNHST(A:network#) => A:host# (address of this machine on that network) ;;; HSTCMP(A:host#,B:host#) => skip iff 2 hosts are the same ;;; NETSRC(B:net#) => A:name_p ;;; ARPICP(A:pin#, B:host#, C:socket#, D:imode,,omode) => clobbers all, opens pin+2,pin+3 ;;; ICPASN(A:pin#, B:host#, C:socket#, D:imode,,omode, E:phase#) ;;; ARPSRV(A:pin#, B:socket#, C:imode,,omode) => B:host#, C:sysdbg, A,D:junk, opens pin+2,+3 ;;; ARPCON(A:pin#, B:host#, C:frn_socket#, D:async,,mode) ;;; CONFIN(A:pin#, , , D:mode) ;;; CHASRV(A:channel#, C:contact_name_p, D:window_size) => B:host#, C:sysdbg, A,D:junk ;;; CHACON(A:channel#, B:host#, C:contact_name_p, D:window_size) ;;; CHASMP(A:channel#, B:host#, C:request, D:answer) ;;; CHALSN(A:channel#, B:zero_or_host#, C:contact_name_p, D:window_size) ;;; TCPCON(A:channel#, B:host#, C:port#) ;;; TCPSRV(A:channel#, B:port#) => B:host#, C:sysdbg, A,D:junk ;;; ANALYZE(A:channel#) => prints error message, with no CRLF IFE $$LOOK+$$CHAOS+$$ARPA, .FATAL You have to specify at least one network IFN $$ERRHAN,$$ANALYZE==1 IFN $$SYMGET,$$SYMLOOK==1 IFN $$HOSTNM,$$HSTMAP==1 IFN $$HSTCMP,$$HSTMAP==1 IFN $$SIMPLE,$$CONNECT==1 DEFINE $$LOG IFN $$LOGGING!TERMIN $$LOG,[ IFE ITS, .ERR Sorry the LOGging feature is only supported under ITS ;;; For logging connections. Example: LOG OPEN,[B,C] DEFINE LOG NETOP,CRUFT %%ZZ==1 PUSHJ P,[ PUSH P,A PUSH P,[SIXBIT /NETOP/] IRP CRUFTY,,[CRUFT] MOVE A,CRUFTY PUSH P,A %%ZZ==%%ZZ+1 TERMIN MOVEI A,%%ZZ PUSHJ P,NETWRK"LOGACT REPEAT %%ZZ, POP P,A POP P,A POPJ P, ] TERMIN ];$$LOG NE%UNT==:<1_32.> ; Escape bit indicating non-Internet address IFN $$HST3,[ NW$BYT==:301400 ; Byte pointer to network number (approx!) NE%STR==:<1_33.> ; Escape bit indicating string-type address ; Useful HOSTS3 full word network # values NW%CHS==:> ; CHAOSNET NW%ARP==:<10._24.> ; ARPANET NW%MIL==:<26._24.> ; MILNET NW%LCS==:<18._24.> ; MIT-LCS (18) NW%AI==:<20015,,> ; MIT-AI-NET (128.52) DEFINE GETNET AC,(ADDR) IFNB [ADDR] MOVE AC,ADDR TLNN AC,(17_32.) ; Check for non-Internet type addrs TLNN AC,(1_31.) ; Internet address, see if class A net TDZA AC,[77,,-1] ; Unternet or class A, zap low 3 octets TLNN AC,(1_30.) ; Class B or C, see which. TRZA AC,177777 ; Class B network, zap low 2 octets TRZ AC,377 ; Class C net, only zap 1 low octet TERMIN ] ;$$HST3 .ELSE [ ; HOSTS2 format stuff NW%CHS==:7 ;Chaos net NW%ARP==:12 ;Arpa net NW%LCS==:22 ;LCS net ;NW%DLN==:26 ;Dial net (not supported by these routines) NW$BYT==:331000 ; Byte pointer to network number DEFINE GETNET AC,(ADDR) LDB AC,[NW$BYT,,ADDR] TERMIN ] ;HOSTS2 IFN $$CHAOS,[ IFNDEF $CPKOP,[ IFN ITS, .INSRT SYSENG; CHSDEF > .ELSE .INSRT SYSTEM:CHSDEF ] ] IFN ITS,[ .CALL==43_33 ;IN CASE OUR .INSRT'ER USES CALRET .CALL MACRO. DEFINE SYSCAL NAME,ARGS .CALL [SETZ ? SIXBIT /NAME/ ? ARGS ((SETZ))] TERMIN ];ITS POP2J: SUB P,[1,,1] ;Exits used in a few places. POP1J: SUB P,[1,,1] CPOPJ: POPJ P, POPJ1: AOS (P) POPJ P, IFNDEF NWLOSS,[ ; SO .INSRT'ER CAN SUBSTITUTE SOMETHING FOR LOSSAGE CHKS IFN ITS,[ DEFINE NWLOSS .LOSE TERMIN ];ITS IFN TNX,[ DEFINE NWLOSS HALTF TERMIN ];TNX ];NWLOSS IFN $$SYMGET+$$SYMLOOK,[ .SCALAR HSTNMF ;Document these! .SCALAR NOABRV .SCALAR NTSPCF ] IFN $$SYMGET,[ ;Interactive symbol readin and lookup. ; ; Call: MOVE E,TABLEP ; PUSHJ P,SYMGET ; error ; value of symbol now in A. ; ;Smashes B, C, D, E, T, TT. ; ; TABLEP should be an aobjn ptr to the table ; of symbols from which user input is to select. ; Num is an arbitrary 18-bit field derived from the table. ; The format of the table is: ; [asciz/prompt string/] ; --> value1,,[asciz/upper-case-symbol-1/] ; value2,,[asciz/upper-case-symbol-2/] ; . . . ; Note that this table is an argument to the SYMGET entry. The ; HOSTNM entry uses the table from the HOSTS3 file, not in the same format. ; ;Subroutines used: ; GETCHR, PUTCHR, SPCHAN (see previous page for call sequences) ; ; GETCHR subroutine to get a character (1 arg) ; PUTCHR subroutine to type a character (1 arg). ; input is echoed/completed through PUTCHR ; SPCHAN if a character other than a letter, a number, ; a hyphen, a period, a space, or a CR is seen, ; SPCHAN is called with the char in T. Variable NUMGOT ; will have value of number read thus far (-1 if none). ; Non-skip return restarts reader, skip return ignores char ; and continues. ; .VECTOR RCPBUF(6) ;input buffer for this routine .SCALAR CHRCNT,NUMGOT ;Register Usage ; ;A octal host number accum - scratch, if reading name. ;B decimal host number accum - scratch, if reading name. ;C scratch. ;D byte pointer into input buffer ;E (aobjn) pointer to table ;T character or random data ;TT miscellany IFN $$PROMPT,[ PROMPT: [ASCIZ /Host: /] ; default prompt ]; IFN $$PROMPT SYMGET: ;interactive symbol input routine, with completion. SETZM HSTNMF ;Say we are not using the host names table (it has no prompt string). HSTNM1: REGO: SKIPN HSTNMF SKIPA TT,-1(E) ;prompt MOVE TT,PROMPT PUSHJ P,ZTYPE GO3A: MOVEI D,RCPBUF ;PTR TO SPEC STRING HRLI D,440700 ;PTR INTO COLLECTED STRING SETZM CHRCNT ;COUNT OF CHARS IN STRING SETOM NUMGOT ; Value of number read thus far GO1: PUSHJ P,GETCHR ;GET INPUT CHARACTER MOVEI T,^M ;NO CHARS AVAIL SAME AS A CR. JUMPE T,GO1 ;IGNORE NULLS. CAIL T,"a" CAILE T,"z" CAIA ;NOT LOWER CASE SUBI T,40 ;CONVERT LOWER CASE TO UPPER CAIE T,12 CAIN T,15 JRST GOTRM ;E-O-L MEANS USER DONE WITH SPEC. CAIN T,40 JRST GOTRM0 ;SPACE COMPLETE BUT DON'T TERM CAIN T,177 ;RUBOUT CAUSES COMPLETE RESTART JRST [ MOVEI TT,[ASCIZ\? \] ? PUSHJ P, ZTYPE JRST REGO ] CAIE T,"?" CAIN T,33 ;? OR ALT MEANS LIST ALL POSSIBLE HOSTS, JRST GOTALT ;GIVEN TYPEIN THUS FAR. JRST GOTC BAD1: SUB P,[1,,1] BAD: MOVEI T,7 ;IF BAD CHAR GIVEN, DING BELL. GOECH: PUSHJ P,PUTCHR JRST GO1 ;GOT A CHARACTER. IS EITHER SPECIAL OR PART OF A NAME GOTC: CAIN T,"-" ;BY SPECIAL DISPENSATION, HYPHEN JRST GOTC00 CAIN T,"." ; Also allow period as part of name JRST GOTC00 CAIN T,"/" ;SLASH AT THIS LEVEL IS JUST A CHARACTER JRST GOTC00 ;SYML1 WILL HANDLE HOST/IMP AND ADDRESS/NETWORK-NAME CONSTRUCTS CAIGE T,"0" ;NUMBERS JRST SPECL CAIG T,"9" JRST GOTC00 CAIGE T,"A" ;LETTERS JRST SPECL CAIG T,"Z" JRST GOTC00 ;OTHERWISE SPECIAL CHARACTER, HANDLE IT SPECL: MOVE TT,A PUSHJ P,SPCHAN JRST GO3A ;RESTART FROM THE BEGINNING JRST GO1 ;IGNORE THIS CHAR ;GOT A CHAR. STORE IF IT PLUS STRING THUS FAR MATCHES A NAME, DON'T STORE IF NOT. ;CHAR (NOT ECHOED YET) IS IN T. GOTC00: PUSH P,D ;PREPARE TO FLUSH THE CHAR IF IT MAKES AN UNDEF SYMBOL. IDPB T,D ;STORE CHAR IN STRING, FOLLOWED BY A NULL. PUSH P,D SETZ TT, IDPB TT,D POP P,D AOS CHRCNT ;INCREMENT COUNT OF CHARS IN STR. PUSH P,T MOVEI A,RCPBUF PUSHJ P,SYML1 ;SEARCH THE TABLE FOR THIS STRING. JFCL CAIGE B, MOVEM T,NUMGOT ; Store number got thus far. POP P,T POP P,TT JUMPN B,GOECH ;NUMBER, OR SYMBOL FOUND OR AMBIGUOUS => THIS CHARACTER IS OK. SETZ TT, ;SYMBOL UNDEFINED => ZERO OUT THIS CHAR IN THE STRING DPB TT,D MOVE D,TT ;BACK UP POINTER TO END OF STRING SOS CHRCNT JRST BAD ;AND COMPLAIN. ;GOT A E-O-L, SEE IF HAVE ENOUGH OF NAME TO RENDER IT UNIQUE. GOTRM: TDZA C,C ;COMPLETE AND TERMINATE GOTRM0: SETOM C ;JUST COMPLETE SKIPG CHRCNT ;HMMM, ANYTHING IN STRING STORED? JRST BAD ;NO, DING... MOVEI A,RCPBUF ;ELSE LOOK THE STRING UP. PUSHJ P,SYML1 JRST BAD ;UNDEFINED OR AMBIGUOUS => LOSE. MOVE A,T MOVE TT,B ;NUMBER => OK, AND DON'T TYPE ANYTHING. RETURN NUMBER IN A. AOJE TT,WIN HRRZ TT,(B) ;FOUND AND UNAMBIGUOUS. COMPLETE THE NAME IF ABBREVIATED. SKIPE HSTNMF ADD TT,HSTADR ;GET POINTER TO THE FULL NAME. HRLI TT,440700 MOVE A,CHRCNT ILDB T,TT ;IGNORE AS MANY CHARS AS THE USER ACTUALLY GAVE. JUMPE T,GOTRM2 ;HANDLE USER ABBREVIATION AND /NET FORMS RIGHT SOJG A,.-2 GOTRM1: ILDB T,TT JUMPE T,GOTRM2 IDPB T,D ;AS WE COMPLETE THE NAME, STORE THE CHARS INTO THE ARG AOS CHRCNT ;SO THAT IF THIS IS A SPACE, THE FOLLOWING CR DOESN'T PUSHJ P,PUTCHR ;TYPE THE SAME STUFF OUT AGAIN. JRST GOTRM1 GOTRM2: HLRZ A,(B) ;WIN. RETURN LH. OF TABLE WORD. SKIPE HSTNMF ;NORMALLY IS SYMBOL VALUE, BUT IF READING HOST NAME, IS FILE- SETO TT, ;RELATIVE ADDRESS OF SITE TABLE ENTRY, TT NON-ZERO MEANS NOT NUMBER WIN: JUMPN C,GO1 ;SHOULD TERMINATE? NO => GO READ MORE CHARS. PUSHJ P,CRLF ;YES, GIVE CRLF JRST POPJ1 ;AND RETURN WINNING NUMBER IN A ;GOT ? OR ALT, LIST ALL NAMES POSSIBLE AT THIS STAGE. GOTALT: SKIPN CHRCNT JRST GO1 ;ALTMODE OR ? AFTER A NUMBER IS A NO-OP. MOVEI A,RCPBUF SETOM NOABRV PUSHJ P,SYMLA ;SEARCH FOR ALL POSSIBLE ALTERNATIVES. JFCL TLNN B,-1 HRLS B ;IF ONLY ONE, SET IT UP AS RANGE ,,. MOVE TT,B AOJE TT,GO1 ;IF ARG IS A NUMBER, DON'T TYPE ANYTHING. PUSHJ P,CRLF HLRZ A,B ;A POINTS TO FIRST, RH(B) POINTS TO LAST. GOTAL1: HRRZ TT,(A) ;GET THE ADDR OF THE NEXT POSSIBLE MATCH'S NAME STRING SKIPE HSTNMF ADD TT,HSTADR PUSHJ P,ZTYPE ;TYPE IT. PUSHJ P,CRLF ADDI A,1 CAIG A,(B) JRST GOTAL1 SKIPN HSTNMF ;GIVE PROMPT STRING AGAIN SKIPA TT,-1(E) MOVE TT,PROMPT PUSHJ P,ZTYPE MOVEI TT,RCPBUF ;FOLLOWED BY THE ARG CHARS WE HAVE SO FAR. PUSHJ P,ZTYPE JRST GO1 ] ;END IFN $$SYMGET IFN $$SYMLOOK,[ ; SYMLOOK - Non-incremental hostname/hostaddr (symbol) lookup routine ; called by the incremental one. ;Numbers are normally octal, but a "." at the end implies decimal. ;Decimal host slash decimal Imp and any address slash network name are allowed. ; The decimal "octet" form is allowed, right justified. ;In the address slash network-name form, the argument is smashed then restored! ; ; A/ ; Can also be 0,, or -1,, ; E/ ; e.g. -tablelen,,table ; Returns .+1 if fail: ; B/ 0 for an undefined sym, or ,, for an ambiguous one. ; Returns .+2 if won: ; B/ addr of table entry for symbol we found. ; or -1 if argument was a number; value returned in T. ; Clobbers T, TT. SYMLOOK: SETZM HSTNMF SYML1: SETZM NOABRV SYMLA: PUSH P,C PUSH P,D HLRZ TT,A SKIPE TT ;If A is an address, CAIN TT,-1 ;or HRROI-style TWENEX string pointer, HRLI A,440700 ;then turn into canonical PDP-10 BP MOVE TT,A MOVE T,A ILDB T,T ;First character of string CAIL T,"0" ;Is the argument a number (starts with a digit)? CAILE T,"9" JRST SYML6 SETZB C,D ;Yes => accumulate octal number in C, decimal in D. SYML7: ILDB T,TT CAIL T,"0" CAILE T,"9" JRST SYML8 IMULI C,10 IMULI D,10. ADDI C,-"0"(T) ADDI D,-"0"(T) JRST SYML7 SYML8: CAIN T,"/" JRST SYMSL1 ;Digits followed by slash CAIE T,"." ;Out of digits => "." means use the decimal number JRST SYML9 ;(else use the octal). MOVE C,D ILDB T,TT CAIN T,"/" ;OK to have both a decimal point and a slash JRST SYMSL1 JUMPE T,SYML9 CAIL T,"0" ; Another number? CAILE T,"9" JRST SYML9 ; Aha, have num.num so keep going in this vein. MOVEI D,-"0"(T) ; Initialize D with 1st digit of 2nd number SYML41: ILDB T,TT CAIL T,"0" CAILE T,"9" JRST [LSH C,8. ADDI C,(D) SETZ D, CAIN T,"." JRST SYML41 CAIN T,"/" JRST SYMSL1 JRST SYML9] IMULI D,10. ADDI D,-"0"(T) JRST SYML41 SYML9: JUMPN T,SYMUND ;Any stray chars after the last digit or the "." => error. MOVE T,C SETO B, ;Return the number in T and -1 (=> this is a number) in B. JRST SYMWIN SYMSL1: SKIPN HSTNMF ;Slash only magic if hacking hosts JRST SYML9 ILDB T,TT ;Look at character after slash CAIL T,"0" CAILE T,"9" JRST [ADD TT,[070000,,] ; Back up byte-pointer PUSHJ P,SYMSL4 ; Process slash network-name. SETZ T, JRST SYML9 ] IFE $$ARPA, JRST SYML9 IFN $$ARPA,[ MOVE C,D ;Number slash number, use decimal MOVEI D,-"0"(T) SYMSL2: ILDB T,TT CAIL T,"0" CAILE T,"9" JRST [ IFN $$HST3,[ LSH C,16. ? DPB D,[002000,,C] ; Move HOST over and add IMP ADD D,[NW%ARP] MOVE TT,[NW%ARP] MOVEM TT,NTSPCF ];$$HST3 .ELSE [ DPB D,[112000,,C] ;Deposit IMP number into HOST number MOVEI D,NW%ARP ;And this is obviously Arpa net DPB D,[NW$BYT,,C] ];HOSTS2 JRST SYML9 ] IMULI D,10. ADDI D,-"0"(T) JRST SYMSL2 ];$$ARPA ;;Subroutine to read network name and set NTSPCF to network number ;; Note if HOSTS3 this is a full-word value. IFE $$ALLNET,[ SYMSL4: MOVEI D,0 SYMSL5: ILDB T,TT JUMPE T,SYMSL6 LSH D,6 CAIL T,"a" SUBI T,40 IORI D,-40(T) JRST SYMSL5 SYMSL6: IRPS FLAG,,[$$CHAOS $$ARPA $$TCP $$TCP ]NAME,,[CHAOS ARPA TCP NCP ]NUM,,[NW%CHS NW%ARP NW%ARP NW%ARP] IFN FLAG,[ ;Make sure we claim to support this network MOVE TT,[SIXBIT \NAME\] PUSHJ P,SYMSXC MOVE T,[NUM] ;Prefix -- set it ];FLAG TERMIN IFN $$TCP,[ MOVE TT,[SIXBIT \TCP\] PUSHJ P,SYMSXC JRST [ SETOM USETCP SETZM USENCP JRST .+1] MOVE TT,[SIXBIT \NCP\] PUSHJ P,SYMSXC JRST [ SETOM USENCP SETZM USETCP JRST .+1] ] JUMPE T,[POP P,T ? JRST SYMUND] ;Unknown network name, barf MOVEM T,NTSPCF POPJ P, ;; Compares sixbit arg in D with sixbit Network name in TT. ;; Returns .+1 if arg is prefix of net name ;; .+2 otherwise SYMSXC: PUSH P,D JUMPE D,SYMSX1 ; Don't loop forever if arg is 0 TLNN D,770000 ; Shift until high byte is non-zero JRST [ LSH D,6 ? JRST .-1 ] TRNN D,77 ; Shift both until low char non-zero JRST [ LSH D,-6 ? LSH TT,-6 ? JRST .-1 ] CAMN D,TT CAIN D,0 SYMSX1: AOS -1(P) POP P,D POPJ P, ];$$ALLNET IFN $$ALLNET,[ ;; Like SYMCMP, but user's string needn't start on word boundary. ;; Compare strings, address of one in T, Byte Pointer to another in C. ;; Smash T, TT, but NOT A, B, C, or D SYMCMC: PUSH P,C PUSH P,D PUSHJ P,SYMCM0 ;Do comparison w/o setting up C CAIA AOS -2(P) ; Success, skip return POP P,D POP P,C POPJ P, SYMSL4: PUSH P,C MOVE C,TT ;ptr to string MOVE T,HSTADR ADD T,NETPTR(T) ;Ptr to network tables MOVN D,(T) ;Count of networks HRLZS D ;Prepare AOBJN ptr HRRI D,2(T) ;Ptr to first network SYSL4A: HLRZ T,NTLNAM(D) ;Ptr to host string ADD T,HSTADR PUSHJ P,SYMCMC ;Is this the network we were given? JRST SYSL4B ; Nope, try next MOVE T,NETNUM(D) ;Get the network number MOVEM T,NTSPCF ;Remember that we specified it POP P,C POPJ P, SYSL4B: MOVE T,HSTADR ;Find start of NETWORK table ADD T,NETPTR(T) ADD D,1(T) ;2nd word is size of entries ADD D,[1,,0] ;Update the counter JUMPL D,SYSL4A ;Try next match POP P,C POP P,(P) JRST SYMUND ;Else fail. ]; $$ALLNET ;Here to start processing an arg which is not a number. SYML6: MOVE B,E ILDB T,TT ;Check for slash and network name JUMPE T,SYML2 ;None found CAIE T,"/" JRST SYML6 MOVEI T,0 ;Ugh, barf, clobber the argument DPB T,TT PUSH P,TT PUSHJ P,SYMLA ;Go do that JRST [ POP P,TT ? MOVEI T,"/" ? DPB T,TT ? JRST SYMLZ] ;Lost, propagate, fixing arg POP P,TT ;Note, recursive call didn't return anything in T MOVEI T,"/" ; since this wasn't a number DPB T,TT ;Fix argument PUSH P,TT ;Don't barf at / with nothing after it yet ILDB T,TT POP P,TT CAIE T,0 PUSHJ P,SYMSL4 ;Process network-name argument JRST SYMWIN ;And take success return SYML2: HRRZ T,(B) ;Get the next symbol's name from the table. SKIPE HSTNMF ADD T,HSTADR PUSHJ P,SYMCMP ;Does the argument in A abbreviate it? CAIA JRST SYML3 ;Yes, we have found the first match. AOBJN B,SYML2 SYMUND: SETZ B, ;There is no match. Return 0. JRST SYMLZ SYML3: PUSH P,B ;Remember where the first match is, and find the last. SYML4: AOBJP B,SYML5 HRRZ T,(B) ;Get the next symbol's name from the table. SKIPE HSTNMF ADD T,HSTADR PUSHJ P,SYMCMP ;Does the argument in A abbreviate it? JRST SYML5 ;No => we have gone past the last match. JRST SYML4 SYML5: SUB B,[1,,1] ;B points at last match. CAMN B,(P) ;Last and first match are the same table entry? JRST SYMLW ;Then that one is the value. MOVE TT,(P) PUSH P,A HLLZ A,(B) SYML5A: HLLZ T,(TT) CAME T,A JRST SYML5B CAME TT,B AOBJN TT,SYML5A ;If all names have the same value, then just MOVEM B,-1(P) ;return the last name, e.g. for XEROX.ARPA JRST SYMLW1 ;and XEROX.COM, return XEROX.COM SYML5B: MOVE A,-1(P) ;A gets the symbol name of the first match HRRZ A,(A) SKIPE HSTNMF ADD A,HSTADR HRLI A,440700 HRRZ T,(B) SKIPE HSTNMF ;and T gets the name of the last match. ADD T,HSTADR SKIPN NOABRV ;If processing "BBN?", show all names starting with BBN ;even though "BBN" by itself is a valid name. PUSHJ P,SYMCMP ;if the first match is an abbreviation of the last, JRST SYMLL SYMLW1: POP P,A ;then it's no ambiguity; the first wins. SYMLW: POP P,B ANDI B,-1 SYMWIN: POP P,D POP P,C JRST POPJ1 SYMLL: POP P,A ;Here if argument is really ambiguous. HRL B,(P) ;produce 1st match addr,,last match addr. SUB P,[1,,1] SYMLZ: POP P,D POP P,C POPJ P, ;Compare the ASCIZ string <- A with the one <- T. ;Skip if the one in A is an initial segment of the one in T. ;We clobber C, D, T and TT but NOT A. SYMCMP: MOVE C,A ; HRLI C,440700 ;Already a BP now. SYMCM0: HRLI T,440700 SYMCM1: ILDB TT,T ILDB D,C JUMPE D,POPJ1 ;1st string ended and no mismatch => win. CAIL D,140 SUBI D,40 ;Ignore case in the string in A. Assume string in T is all upper. CAME D,TT POPJ P, ;mismatch => lose. JRST SYMCM1 IFE $$HSTMAP,.SCALAR HSTADR ] ;end IFN $$SYMLOOK IFN $$HSTMAP,[ .SCALAR HSTADR ;Address of HOSTS3 file is stored here. .SCALAR HSTABN ; AOBJN page pointer to HOSTS3 ;The format of the compiled HOSTS3 file is: ; NOTE THIS IS NOT COMPLETELY ACCURATE. See the file ; AI:SYSNET;HOSTS3 > for an uptodate description. HSTSID==:0 ; wd 0 SIXBIT /HOSTS3/ HSTFN1==:1 ; wd 1 SIXBIT /HOSTS/ usually HSTVRS==:2 ; wd 2 FN2 of HOSTS file which this was compiled from. HSTDIR==:3 ; wd 3 SIXBIT /SYSENG/ usually, directory name of source file HSTMCH==:4 ; wd 4 SIXBIT /AI/ (e.g.), device name of source file HSTWHO==:5 ; wd 5 UNAME of person who compiled this HSTDAT==:6 ; wd 6 Date of compilation as sixbit YYMMDD HSTTIM==:7 ; wd 7 Time of compilation as sixbit HHMMSS NAMPTR==:10 ; wd 10 Address in file of NAME table. SITPTR==:11 ; wd 11 Address in file of SITE table. NETPTR==:12 ; wd 12 Address in file of NETWORK table. ;....expandable.... ;NETWORK table ; wd 0 Number of entries in table. ; wd 1 Number of words per entry. (2) ;This table contains one entry for each network known about, sorted ;by network number. A network number is bits 4.8-4.1 of a network ;address; these numbers are assigned by Jon Postel. See symbols below. ;The reason for keeping track of different networks is that the user ;program must make different system calls to use each network. ;Each entry contains: NETNUM==:0 ; wd 0 network number NTLNAM==:1 ; wd 1 LH - address in file of name of network NTRTAB==:1 ; wd 1 RH - address in file of network's address table ;ADDRESS table(s) ; wd 0 Number of entries in table. ; wd 1 Number of words per entry. (2) ;There is one of these tables for each network. It contains entries ;for each site attached to that network, sorted by network address. ;These tables are used to convert a numeric address into a host name. ;Also, the list of network addresses for a site is stored ;within these tables. ;Each entry contains: ADDADR==:0 ; wd 0 Network address of this entry (including network number). ADLSIT==:1 ; wd 1 LH - address in file of SITE table entry ADRCDR==:1 ; wd 1 RH - address in file of next ADDRESS entry for this site ; 0 = end of list ADRSVC==:2 ; wd 2 RH - fileaddr of services list for this address ; 0 none, else points to SERVICE node of format SVLCNT==:0 ; <# wds>,, SVRCDR==:0 SVLFLG==:1 ; ,, SVRNAM==:1 SVCARG==:2 ; Possible additional parameters ;SITE table ; wd 0 Number of entries in table. ; wd 1 Number of words per entry. (3) ;This table contains entries for each network site, ;not sorted by anything in particular. A site can have more ;than one network address, usually on different networks. ;This is the main, central table. ;Each entry looks like: STLNAM==:0 ; wd 0 LH - address in file of official host name STRADR==:0 ; wd 0 RH - address in file of first ADDRESS table entry for this ; site. Successive entries are threaded together ; through ADRCDR. STLSYS==:1 ; wd 1 LH - address in file of system name (ITS, TIP, TENEX, etc.) ; May be 0 => not known. STRMCH==:1 ; wd 1 RH - address in file of machine name (PDP10, etc.) ; May be 0 => not known. STLFLG==:2 ; wd 2 LH - flags: STFSRV==:400000 ; 4.9 1 => server site (according to NIC) STFGWY==:200000 ; 4.8 1 => Internet gateway site ; wd 2 RH - not used ;NAMES table: ; wd 0 Number of entries ; wd 1 Number of words per entry. (1) ;This table is used to convert host names into network addresses. ; Followed by entries, sorted by the host name treated as a vector of ; signed integers, looking like: NMLSIT==:0 ; lh address in file of SITE table entry for this host. NMRNAM==:0 ; rh address in file of host name ;This name is official if NMRNAM = STLNAM of NMLSIT. ; All names are ASCIZ strings, all letters upper case. ; The strings are stored before, after and between the tables. ; All strings are word-aligned, and fully zero-filled in the last word. ;Network addresses are defined as follows, for purposes of this table: ; 4.9 0 ; 4.8-4.1 network number ; Chaos net (number 7): ; 3.9-2.8 0 ; 2.7-1.1 address (2.7-1.9 subnet, 1.8-1.1 host) ; Arpa net (number 12): (note, old-format Arpanet addresses ; 3.9-3.8 0 never appear in the host table.) ; 3.7-2.1 Imp ; 1.9 0 ; 1.8-1.1 Host ;Map the host table file SYSBIN;HOSTS3 > into core. ;A should contain the page number to start it at. ;B should contain the channel number to use. ;We skip if we succeed, returning in RH(A) the number of the first page not used up. HSTMAP: IFN ITS,[ SYSCAL OPEN,[ B ? 5000,,.BII ? ['DSK',,] IFN $$HST3, ['HOSTS3'] .ELSE ['HOSTS2'] [SIXBIT />/] ? ['SYSBIN']] POPJ P, SYSCAL FILLEN,[B ? 2000,,T] POPJ P, JUMPLE T,CPOPJ MOVEI T,1777(T) ;(round up) LSH T,-10. PUSH P,A LSH A,10. MOVEM A,HSTADR ;Save in HSTADR the address where we are mapping the file. POP P,A MOVNS T ;form AOBJN page ptr for CORBLK HRL A,T MOVEM A,HSTABN ; save AOBJN for unmapping SYSCAL CORBLK,[ 1000,,%CBNDR ;Read-Only. 1000,,%JSELF ;into self A ;as specified B] ;from file open on channel. POPJ P, SYSCAL CLOSE,B POPJ P, MOVE T,HSTADR ];ITS IFN TNX,[ .SCALAR HSTJFN .SCALAR HSTLEN PUSH P,1 ? PUSH P,2 ? PUSH P,3 PUSH P,A MOVSI 1,(GJ%SHT\GJ%OLD) IFN 20X,[ IFN $$HST3,HRROI 2,[ASCIZ "SYSTEM:HOSTS3.BIN"] .ELSE HRROI 2,[ASCIZ "SYSTEM:HOSTS2.BIN"] ] ;20X IFN 10X,[ IFN $$HST3,HRROI 2,[ASCIZ "HOSTS3.BIN"] .ELSE HRROI 2,[ASCIZ "HOSTS2.BIN"] ] ;10X GTJFN JRST HSTMP7 ; Failed, restore regs. MOVEM 1,HSTJFN MOVE 2,[70000,,OF%RD] OPENF JRST [MOVE 1,HSTJFN RLJFN NOP JRST HSTMP7] MOVE 2,[1,,.FBBYV] MOVEI 3,T GTFDB ;XXX,,#PAGES HRRZM T,HSTLEN HRLZ 1,HSTJFN ;JFN,,FILE PAGE 0 HRRZ 2,(P) ;PAGE NUMBER WITHIN US (saved on stack) HRLI 2,.FHSLF HRRZ 3,T TLO 3,(PM%CNT\PM%RD) PMAP IFN 10X,[ TRNE 3,-1 ; Counted out yet? JRST [ HRRI 3,-1(3) ; Bump count down by 1 TRNE 3,400000 ; and stop if done (count -1) JRST .+1 ADDI 1,1 ; Increment # of file page AOJA 2,.-1] ; and # of process page... then repeat PMAP. ] ;10X POP P,A POP P,3 ? POP P,2 ? POP P,1 MOVE T,A IMULI T,1000 MOVEM T,HSTADR ];TNX MOVE T,HSTSID(T) ;CHECK THAT FIRST WORD OF FILE IS REALLY HOSTS3 IFN $$HST3,CAME T,[SIXBIT /HOSTS3/] .ELSE CAME T,[SIXBIT/HOSTS2/] POPJ P, JRST POPJ1 IFN TNX,[ HSTMP7: POP P,A POP P,3 ? POP P,2 ? POP P,1 POPJ P, ] ;TNX ; UNMAP HOSTS3. HSTUNMAP: SKIPN HSTADR POPJ P, IFN ITS,[ MOVE T,HSTABN ; AOBJN PAGE POINTER TO HOSTS3 SYSCAL CORBLK,[ 1000,,0 ; DELETE 1000,,%JSELF ; FROM SELF T ] JFCL ];ITS IFN TNX,[ PUSH P,1 ? PUSH P,2 ? PUSH P,3 SETO 1, MOVE 2,HSTADR IDIVI 2,1000 ;PAGE# HRLI 2,.FHSLF MOVE 3,HSTLEN TLO 3,(PM%CNT) PMAP IFN 10X,[ TRNE 3,-1 ; Counted out yet? JRST [ HRRI 3,-1(3) ; Bump count down by 1 TRNE 3,400000 ; and stop if done (count -1) JRST .+1 AOJA 2,.-1] ; Bump # of process page... then repeat PMAP. ] ;10X POP P,3 ? POP P,2 ? POP P,1 ];TNX SETZM HSTADR JRST POPJ1 ;Given host number in B, return its host name addr in rh(A) and set sign of A ;if the host is a Tip. Skip if successful. No skip => unknown host. ;We also return in D the address of the SITES table entry for the host. HSTSRC: MOVE A,B PUSHJ P,STDHST MOVE B,A SKIPN HSTADR ;Fail if the HOSTS3 file isn't loaded. POPJ P, PUSH P,C PUSH P,E PUSH P,T GETNET C,B ; Get network number MOVE D,HSTADR ADD D,NETPTR(D) ;get address of NETWORKS table. MOVE TT,0(D) ;get # of entries, MOVE T,1(D) ;and entry size. ADDI D,2 ;point at first entry. HSTSR1: CAMN C,NETNUM(D) ;Find appropriate network JRST HSTSR2 ADD D,T SOJG TT,HSTSR1 ;no => look at next entry. HSTSRX: POP P,T ;unknown network => return non-skipping. POP P,E POP P,C POPJ P, HSTSR2: HRRZ D,NTRTAB(D) ;Get address of ADDRESS table for that network ADD D,HSTADR ;Binary-search it MOVE C,1(D) ;Words per entry MOVE E,0(D) ;Number of entries in table MOVEI D,2(D) ;Base address of table PUSH P,D HSTSR3: CAIG E,1 JRST HSTSR4 ;Search narrowed down to one location MOVE T,E LSH T,-1 MOVE TT,T ;Number of entries in bottom "half" of table IMUL T,C ADD T,D ;Probe point CAMGE B,ADDADR(T) JRST [ MOVE E,TT ;Move down JRST HSTSR3 ] MOVE D,T ;Move up SUB E,TT JRST HSTSR3 HSTSR4: POP P,T ; Recover base addr of table CAME B,ADDADR(D) ; Did we get any match at all? JRST HSTSRX ; Nope, take non-skip return. HSTSR5: SUBI D,(C) ; Found one! Back up to find 1st match CAIGE D,(T) ; Make sure we don't back up past beg JRST HSTSR6 CAMN B,ADDADR(D) ; As long as we still get a match, JRST HSTSR5 ; keep backing up. HSTSR6: ADDI D,(C) ; Recover from backup. MOVEI E,(D) ; Save ptr to ADDRESS table HLRZ D,ADLSIT(D) ; Get address of SITES table entry ADD D,HSTADR MOVE A,STLFLG ; Check flags TLNE A,STFGWY ; to see if this one is a gateway. JRST [ ADDI E,(C) ; Ugh, gateway. Try to skip it. CAME B,ADDADR(E) JRST .+1 ; No good, stuck with this one. JRST HSTSR6] ; Hurray, try next entry! HLRZ A,STLNAM(D) ;found the host => get the addr of its name ADD A,HSTADR ;in our address space. HLRZ C,STLSYS(D) ADD C,HSTADR ;also get addr of its system type name MOVE C,(C) CAME C,[ASCIZ /TAC/] ;If it's a TAC, CAMN C,[ASCIZ /TIP/] ; Or a TIP, TLO A,400000 ; set sign bit of A. AOS -3(P) ;Take skip return JRST HSTSRX ] ;END $$HSTMAP IFN $$NETSRC,[ ;;; NETSRC(B:net#) => A:name_p ;;; Convert a network number to a network name NETSRC: SKIPN HSTADR ;Fail if the HOSTS3 file isn't loaded. POPJ P, PUSH P,C PUSH P,D MOVE D,HSTADR ADD D,NETPTR(D) ;get address of NETWORKS table. MOVE TT,0(D) ;get # of entries, MOVE T,1(D) ;and entry size. ADDI D,2 ;point at first entry. NETSR1: CAMN B,NETNUM(D) ;Find appropriate network JRST NETSR2 ADD D,T SOJG TT,NETSR1 ;no => look at next entry. POP P,D ;unknown network => return non-skipping. POP P,C POPJ P, NETSR2: HLRZ A,NTLNAM(D) ;Get address of name of network ADD A,HSTADR POP P,D ;unknown network => return non-skipping. POP P,C JRST POPJ1 ];END $$NETSRC IFN $$SYMGET*$$HOSTNM,[ ;Read in a host name. Works like SYMGET but searches host database. ;We return in A the number of the host, network# in TT. HOSTNM: ;Host name reader PUSHJ P,HSTTBP ;E gets aobjn ptr to NAMES table, and set HSTNMF,NTSPCF PUSHJ P,HSTNM1 ;Do an interactive symbol table lookup. POPJ P, ;Failed ;TT=0 => A has a number ;else => A has file-relative address of SITE table entry JUMPE TT,HOSTN1 ;JRST HOSTN2 ];$$SYMGET*$$HOSTNM IFN <$$SYMGET*$$HOSTNM>+<$$SYMLOOK*$$HOSTNM>,[ ;Code to process result of Host-name lookup, returning full address in A ;with network number extracted into TT. ;Address was supplied, file-relative pointer to SITES table entry in A. HOSTN2: ADD A,HSTADR SKIPGE TT,NTSPCF ;Explicitly-specified network? JRST HOSTN4 ;No, try all nets we know about HOSTN3: HRRZ E,STRADR(A) ;Find an address for SITE in A on network in TT HSTN3A: ADD E,HSTADR GETNET T,ADDADR(E) CAMN T,TT JRST [ MOVE A,ADDADR(E) ;This is it JRST POPJ1 ] HRRZ E,ADRCDR(E) JUMPN E,HSTN3A ;Try site's next address POPJ P, ;Not found HOSTN4: ;Find a network address for this site IFN $$CHAOS,[ ;Chaos net is preferred, try it first MOVE TT,[NW%CHS] PUSHJ P,HOSTN3 CAIA JRST POPJ1 HOSTN5: ];$$CHAOS IFN $$ARPA,[ MOVE TT,[NW%ARP] PUSHJ P,HOSTN3 CAIA JRST POPJ1 HOSTN6: ];$$ARPA IFE $$ALLNET,[ POPJ P, ;Host exists, but not on any network we know about ]; $$ALLNET IFN $$ALLNET,[ HRRZ E,STRADR(A) JUMPE E,CPOPJ ;No addresses for this site? ADD E,HSTADR ;where ADDRESS entry is in core MOVE A,ADDADR(E) ;A J-random Host Address (some random net) GETNET TT,A ; Extract the network number JRST POPJ1 ;Success ]; $$ALLNET ;Number was supplied, it is in A. Determine what network it is on. HOSTN1: IFE $$ALLNET,[ GETNET TT,A ;Maybe net was specified explicitly as part of number JUMPN TT,[ ;Yes, make sure is on a network we know about IRPS FLAG,,[$$CHAOS $$ARPA]NUM,,[NW%CHS NW%ARP] IFN FLAG,[ CAMN TT,[NUM] JRST POPJ1 ];FLAG TERMIN POPJ P, ] ;Can't find it ]; $$ALLNET SKIPGE TT,NTSPCF ;Maybe network was specified by name JRST [ PUSHJ P,STDHST ; Not specified, return standardized number. JRST POPJ1] IFN $$HST3, IOR A,TT .ELSE DPB TT,[NW$BYT,,A] JRST POPJ1 ];<$$SYMGET*$$HOSTNM>+<$$SYMLOOK*$$HOSTNM> IFN $$SYMLOOK*$$HOSTNM,[ ;HSTLOOK takes args like SYMLOOK and looks in the HOSTS3 NAMES table. ;It returns the same things that HOSTNM returns. It clobbers E, T, TT. ;Also returns in B a pointer like SYMLOOK, or zero if no name lookup won. HSTLOOK: PUSHJ P,HSTTBP ;E gets aobjn ptr to NAMES table, and set HSTNMF,NTSPCF PUSHJ P,SYML1 ;Do a non-interactive symbol table search. POPJ P, MOVE A,T ;If the input was a number AOJE B,HOSTN1 ;go canonicalize it HLRZ A,NMLSIT-1(B) ;Else B points at a NAMES table word, so get SOJA B,HOSTN2 ;the SITE table entry address, go find appropriate net address ];$$SYMLOOK*$$HOSTNM IFN <$$SYMGET\$$SYMLOOK>*$$HOSTNM,[ ;Put in E an aobjn pointer to the HOSTS3 file's NAMES table. Also set HSTNMF. HSTTBP: SKIPN E,HSTADR NWLOSS ADD E,NAMPTR(E) ;Address of NAMES table MOVE T,1(E) ;Make sure words per entry is 1 CAIE T,1 NWLOSS MOVN T,0(E) ;Negative number of entries HRL E,T ADDI E,2 ;E now has an aobjn pointer to the NAMES table. SETOM HSTNMF ;Say that each address needs HSTADR added to it. SETOM NTSPCF ;Say that no network explicitly specified POPJ P, ];<$$SYMGET\$$SYMLOOK>*$$HOSTNM IFN $$SYMGET+$$ANALYZE,[ ;TYPE A CRLF. CLOBBER T. CRLF: MOVEI T,15 PUSHJ P,PUTCHR MOVEI T,12 PUSHJ P,PUTCHR POPJ P, ;TYPE ASCIZ STRING POINTED TO BY TT, CLOBBER T. ZTYPE: IFN ITS,[ HRLI TT,440700 ZTYPE0: ILDB T,TT JUMPE T,CPOPJ PUSHJ P,PUTCHR JRST ZTYPE0 ];ITS IFN TNX,[ PUSH P,1 HRRO 1,TT PSOUT POP P,1 RETURN ];TNX ];$$SYMGET+$$ANALYZE IFN $$HSTSIX,[ ;Given a host number in A, returns a sixbit abbreviation of ;the name of the host, also in A. Clobbers only T and TT. ;You better call HSTMAP before this. ;Always skip returns. HSTSIX: PUSH P,B PUSHJ P,STDHST PUSH P,C PUSH P,D PUSH P,E MOVE B,A PUSHJ P,HSTSRC ;Find the SITES table entry for this host. JRST HSTSX9 ;none => unknown host. Use HSTnnn. SUB D,HSTADR ;D gets addr of SITES table entry relative to file MOVE B,HSTADR ;(for comparison with LH's of NAMES table words). ADD B,NAMPTR(B) ;Get address of NAMES table. MOVE T,1(B) ;Make sure 1 word per entry CAIE T,1 NWLOSS MOVE T,0(B) ;T gets number of entries in the table. SETOB C,E ;E will get the address of the ; longest name shorter than 7 chars, C its length. HRRZ TT,A ;Check out the official name first AOJA B,HSTSX0 HSTSX1: ADDI B,1 ;B points at next untried NAMES table entry. HLRZ TT,NMLSIT(B) CAME TT,D ;Does this name name the host we are serving? JRST HSTSX4 HRRZ TT,NMRNAM(B) ;If so, how long is this name? ADD TT,HSTADR HSTSX0: HRLI TT,440700 PUSH P,TT PUSH P,TT SETZ A, HSTSX2: ILDB TT,(P) JUMPE TT,HSTSX3 AOJA A,HSTSX2 HSTSX3: POP P,TT ;Flush garbage IFN $$MIT,[ MOVE TT,@(P) ;First word of name TRZ TT,377 CAMN TT,[ASCII/MIT-/] CAIG A,6 ;Strip off "MIT-" if longer than 6 characters JRST .+4 SUBI A,4 MOVSI TT,100700 HLLM TT,(P) ];$$MIT POP P,TT ;Restore pointer to name CAIG A,6 ;Fit in 6 characters? CAMG A,C ;and longer than the previous one? JRST HSTSX4 MOVE E,TT ;Yes, save its name's address. MOVE C,A ;and the length of that one HSTSX4: SOJG T,HSTSX1 ;look at all the names in the table. AOJN E,HSTSX5 ;Jump if found a reasonable name ADD D,HSTADR ;No short name, truncate official one MOVEI C,"-" ;Also, will remove hyphens from it HLRZ E,STLNAM(D) ADD E,HSTADR ;Pointer to name IFN $$MIT,[ MOVE A,(E) TRZ A,377 CAMN A,[ASCII/MIT-/] JRST [ HRLI E,100700 AOJA E,HSTSX5 ] ];$$MIT TLOA E,440700 HSTSX5: SUBI E,1 MOVE B,E ;Get BP to name string. ;B has a B.P. to the name string we are going to use. ;C has "- if we should remove all hyphens from it, otherwise C has a number from 1 to 6. ;Convert the name string to SIXBIT in A. MOVE D,[440600,,A] SETZ A, ;Convert name to SIXBIT word in A HSTSX6: ILDB T,B JUMPE T,HSTSX7 ;Stop if name string runs out (nice, it all fits). CAMN T,C ;Remove hyphens if requested to JRST HSTSX6 ;Note C has number from 1 to 6 or "- SUBI T,40 IDPB T,D TLNE D,770000 ;Stop after getting one full word. JRST HSTSX6 HSTSX7: LDB T,D ;If last character is a hyphen, flush it. CAIN T,'-' MOVEI T,0 DPB T,D HSTSX8: POP P,E POP P,D POP P,C POP P,B JRST POPJ1 ;Have to do it numerically. Depends on network. HSTSX9: MOVSI A,'NET' GETNET TT,B CAMN TT,[NW%CHS] MOVSI A,'CHS' CAMN TT,[NW%ARP] JRST [ MOVSI A,'HST' IFN $$HST3, LDB T,[002000,,B] ; IMP .ELSE LDB T,[112000,,B] ;Imp CAIGE T,100 TRNN B,774 JRST .+1 ;Doesn't fit in old-style IFN $$HST3, LSH B,-16. ANDI B,3 LSH B,6 ;Host DPB T,[000600,,B] ;Convert to old-style JRST .+1 ] HRRI A,'000' ;If host number less than 3 digits, pad with zeroes IFE $$HST3, TLZ B,(.BM (NW$BYT)) ;Host number within network SETZB T,TT ;T gets sixbit, TT gets char mask PUSHJ P,HSTS9A ANDCM A,TT ;Clear characters from A to be clobbered from T IOR A,T ;Bring in number JRST HSTSX8 HSTS9A: IDIVI B,8 HRLM C,(P) SKIPE B PUSHJ P,HSTS9A HLRZ C,(P) LSH T,6 IORI T,'0'(C) LSH TT,6 IORI TT,77 POPJ P, ];$$HSTSIX ;;; Standardize host number in A. Clobber T. ;;; No skip-return STDHST: IFN $$HST3, JRST CVH3NA .ELSE [ TLNE A,777000 ;Network number specified? JRST STDHS1 ;Yes, OK IFN $$ARPA, TLO A,NW%ARP_9 ;No, default to some net we know about .ELSE IFN $$CHAOS, TLO A,NW%CHS_9 STDHS1: IFN $$ARPA,[ LDB T,[NW$BYT,,A] ;If Arpanet, standardize to new format CAIN T,NW%ARP TDNE A,[177777000] POPJ P, LDB T,[000600,,A] ;Imp LDB A,[060200,,A] ;Host DPB T,[112000,,A] TLO A,NW%ARP_9 ];$$ARPA POPJ P, ] ;HOSTS2 IFN $$OWNHST+<$$SYMGET*$$HOSTNM>+<$$SYMLOOK*$$HOSTNM>,[ ;;; GIVEN A NETWORK NUMBER IN A (WHICH MUST BE A NETWORK THIS PROGRAM IS ;;; CONDITIONALLY ASSEMBLED TO SUPPORT), RETURN THIS MACHINE'S OWN ;;; ADDRESS ON THAT NETWORK, IN A. CLOBBER T. SKIPS UNLESS HOST NOT ON THAT NET. OWNHST: IFN $$ARPA,[ CAME A,[NW%ARP] JRST OWNHS1 IFN ITS,[ SYSCAL NETHST,[MOVEI -1 ? MOVEM A ? MOVEM A] ;GET OWN ARPANET ADDRESS POPJ P, ;MUST NOT BE ON ARPANET PUSHJ P,STDHST ;SYSTEM DOESN'T RETURN NUMBER IN STANDARD FORMAT JRST POPJ1 ];ITS IFN TNX,[ PUSH P,A PUSH P,1 ? PUSH P,2 ? PUSH P,3 ? PUSH P,4 MOVEI 1,.GTHSZ GTHST CAIA AOS -5(P) ; Take skip return! MOVEM 4,-4(P) ; Store result into what will be put in A POP P,4 ? POP P,3 ? POP P,2 ? POP P,1 POP P,A ;ALREADY IN INTERNET FORMAT ];TNX OWNHS1: ];$$ARPA IFN $$CHAOS,[ CAME A,[NW%CHS] JRST OWNHS2 IFN ITS,[ MOVE A,[SQUOZE 0,MYCHAD] .EVAL A, POPJ P, ;MUST NOT BE ON CHAOS NET ];ITS IFN TNX,[ PUSH P,A PUSH P,1 ? PUSH P,2 MOVE 1,[SIXBIT "CHSTAT"] SYSGT HRR 1,2 ;TABLE# HRLI 1,2 ;WORD#2,,TABLE# GETAB JRST [POP P,2 ? POP P,1 POP P,A ? POPJ P,] MOVEM 1,-2(P) POP P,2 ? POP P,1 POP P,A ];TNX IFN $$HST3, IOR A,[NW%CHS] .ELSE TLO A,NW%CHS_9 JRST POPJ1 OWNHS2: ];$$CHAOS POPJ P, ;Some network I don't know about ];$$OWNHST+<$$SYMGET*$$HOSTNM>+<$$SYMLOOK*$$HOSTNM> ;;; Routine to compare two hosts IFN $$HSTCMP,[ ;; Take host #'s in A and B, and skip if they refer to the same host. ;; Clobber no AC'S ;; ;;CALL: MOVE A,[HOST] ;; MOVE B,[HOST] ;; PUSHJ P,HSTCMP ;; different or error (unknown host or unmapped HOSTS3 table) ;; same HSTCMP: CAMN A,B ;Trivial case JRST POPJ1 PUSH P,A ;Clobber no AC's PUSH P,B PUSH P,T PUSH P,D PUSH P,D ;Get's SITE table entry PUSHJ P,HSTSRC ;Check this one out JRST HSTCM9 ; Non-existant or not mapped MOVEM D,(P) ;Remember this site table entry MOVE B,-4(P) ;Get the other host # PUSHJ P,HSTSRC ;and look up it's SITE table entry JRST HSTCM9 MOVE T,(P) ;Recover the first SITE table entry CAMN T,D ;Compare the two entry pointers AOS -5(P) ; The same! HSTCM9: POP P,D POP P,D POP P,T POP P,B POP P,A POPJ P, ];$$HSTCMP ;;; Arpanet connection routines IFN $$ARPA*ITS,[ IFN $$ICP,[ $$CONNECT==1 ;necessary subroutine ; ARPA NETWORK ICP ROUTINE ; ;Call: MOVEI A,pin ;first of group of 3 channels to use (nonconsecutively numbered) ; ;PIN itself is used only for the ICP. PIN+1 is unused. ; ;PIN+2 and PIN+3 are the in and out sides of the TELNET connection. ; MOVEI B,host ;host number to connect to ; MOVEI C,frnsoc ;foreign socket number to icp through ; MOVE D,[imode,,omode] ;input and output modes as in OPEN on NET device. ; PUSHJ P,NETWRK"ARPICP ;do it. Clobbers A,B,C,D,E,T,TT. ; failed ;A holds the channel which lost. If $$ERRHAN, ANALYZ was called. ; succeeded ARPICP: MOVEI E,0 ;synchronous mode ICPPHS: PUSHJ P,ICP1 ;This is also the phase table PUSHJ P,ICP2 PUSHJ P,ICP3 JRST POPJ1 ICPASN: ;asynchronous mode. Same args except E is phase (initially 1). SKIPL E ;keep calling back with same ACs as returned, until E is zero. HRREI E,-3 ;asynchronous init XCT ICPPHS+3(E) ;call appropriate phase AOJA E,POPJ1 ;and advance to next ;First phase - connect to ICP socket. ICP1: PUSH P,D ;Assume that all sockets were closed, so ITS has deallocated any SETZM SKTBAS ;old set of sockets, and we must ask it for a new set. HRROI D,040044 ;asynchronous, 32-bit read PUSHJ P,ARPCON ;initiate connection JRST POP2J ;lose POP P,D ;win POPJ P, ;Second phase - get server socket number and connect up. ICP2: PUSHJ P,CONFIN ;finish ICP connection JRST POP1J ;lose SYSCAL IOT,[MOVEI (A) ? MOVEM C] ;get foreign socket number IFE $$ERRHAN, JRST POP1J ;Connection opened but nothing came through, lose .ELSE JRST [ POP P,C ? JRST ANALNS ] ;Analyze then take error return ;Due to bug in NCP socket allocation, don't close contact pin yet ADDI A,2 ;connect our read pin ADDI C,1 ;to foreign write pin PUSH P,D HLROS D ;using input mode, asynchronously PUSHJ P,ARPCON JRST POP2J ;lose ADDI A,1 ;connect our write pin SUBI C,1 ;to foreign read pin HRRO D,(P) ;using output mode, asynchronously PUSHJ P,ARPCON JRST POP2J ;lose POP P,D POPJ P, ;Third phase - finish up connections. ICP3: PUSHJ P,CONFIN ;finish write connection JRST POP1J SUBI A,1 PUSHJ P,CONFIN ;finish read connection JRST POP1J SYSCAL CLOSE,[MOVEI -2(A)] ;and now close contact pin .LOSE %LSSYS POPJ P, ] ;END IFN $$ICP IFN $$SERVE,[ ;Call: MOVEI A,pin ;first channel number of three consecutive ones. ; ;the first is the ICP listen channel, ; ;the second is the input channel for the TELNET connection, ; ;the third is the output channel for it. ; MOVEI B,icpsoc ;socket to listen for an ICP on. ; MOVE C,[imode,,omode] ;input and output modes as in OPEN on NET device. ; PUSHJ P,NETWRK"ARPSRV ;Listen for and accept an ICP. ; timed out. ; succeeded. B has number of foreign host. ; ;If $$SYSDBG is 0, then connections from hosts locked out by SYSDBG are ;refused, and SERVE fails to skip. ;If $$SYSDBG is 1, then SERVE accepts all connections but returns in C ;a value which is nonzero if the foreign host ought to be locked out by SYSDBG. ;Clobbers A, D, T and TT. $$CONNECT==1 ;We call ARPCON. ARPSRV: SYSCAL SSTATU,[MOVEM TT ? MOVEM SYSDBG'] .LOSE %LSSYS MOVEI TT,377777 ;If debugging, wait forever. SKIPN DEBUG MOVEI TT,30.*60. ;Otherwise time out after 60 sec. ARPSR1: SYSCAL OPEN,[ A ? 5000,,40065 ? [SIXBIT/NET/] ? B] JRST ARSVLS ;Open a channel to receive the RFC with. SYSCAL WHYINT,[ A ? 2000,,T ? 2000,,T] JRST ARSVLS ARPSR2: CAIN T,%NSRFC ;Have we an RFC to accept? JRST ARPSR3 SKIPN DEBUG ;No => OK only if debugging POPJ P, ;(so you can start your server before starting the user). .CALL CONFIC ;So wait for it to change state and look again. JRST ARSVLS ;[They also serve who hang and wait] JRST ARPSR2 ;TRY AGAIN ARPSR3: HLRZ D,C TLO D,400000 ;D gets mode for our input socket. PUSH P,C SYSCAL RCHST,[ A ? 2000,,C ? 2000,,C ? 2000,,C ? 2000,,B] .LOSE %LSFIL ;C gets foreign socket ICP'd with. ;B now has host number of host that ICP'd to us. TLZ B,777000 ;Make sure network number field is 0 IFE $$SYSDBG,[ SKIPL T,SYSDBG ;If system being debugged, may refuse ICP JRST ARPSR4 ASH T,-9 ;Set to -1000*host# allowed in ADD T,B ;Zero if this guy allowed in JUMPN T,ARSVL2 ARPSR4: ];$$SYSDBG ;remember that TT has the "sleep time" arguments for NETBLKs, including CONFI1. SYSCAL NETAC,A JRST ARSVL1 ADDI A,1 ;Channel to make input connection on. ADDI C,3 ;Foreign socket ICP'd with, plus 3, is target for our input. SETZM SKTBAS' PUSH P,TT ;See comment 6 lines above! PUSHJ P,ARPCON JRST [ POP P,TT ? JRST ARSVL1 ] MOVE TT,SKTBAS ;Get socket number of our input connection ADD TT,A SYSCAL IOT,[1000,,-1(A) ? TT] .LOSE %LSFIL ;Send our lower socket # to the ICPer. SYSCAL CLOSE,[1000,,-1(A)] ;Don't need ICP socket any more. .LOSE %LSFIL HRRZ D,-1(P) ;Saved C HRLI D,400000 ADDI A,1 ;Now open our output connection SUBI C,1 ;to a foreign socket 1 smaller than that used for our input. PUSHJ P,ARPCON JRST [ POP P,TT ? JRST ARSVL1 ] POP P,TT POP P,C PUSHJ P,CONFI1 ;Then wait for the two connections to be finished. JRST ARSVLS ;TT still has the time period (or by now maybe the SUBI A,1 ;time to wait until). PUSHJ P,CONFI1 JRST ARSVLS IFN $$SYSDBG,[ SKIPL C,SYSDBG ;If system being debugged, may disallow JRST [ SETZ C, ? JRST ARPSR5 ] ASH C,-9 ;Set to -1000*host# allowed in TLZ B,777000 ;Clear network number from host number ADD C,B ;Zero if this guy allowed in ARPSR5: ];$$SYSDBG EXCH A,B ;Fix host# returned in B PUSHJ P,STDHST EXCH A,B JRST POPJ1 ARSVL2: SYSCAL CLOSE,A .LOSE %LSFIL ARSVL1: POP P,C ARSVLS: SKIPE DEBUG NWLOSS POPJ P, ] ;END IFN $$SERVE IFN $$CONNECT,[ .SCALAR SKTBAS ; ne 0 => socket number of pin zero ; ARPA NETWORK CONNECT ROUTINE ; ;Call: MOVEI A,pin ;local its chnl and relative socket number to connect ; MOVE B,host ;host number to connect to ; MOVEI C,frnsoc ;foreign socket number to connect to ; MOVEI D,mode ;mode to open in (RH). Bit 4.9=1 => asynchronous ; PUSHJ P,NETWRK"ARPCON ; lossage ;you may call ANALYZE to get an error message. ; ;If $$ERRHAN is nonzero, we call ANALYZE for you. ; ;Clobbers only T and TT. If using asynchronous mode, ;call CONFIN later (with pin number in A) to finish up. ; ; NOTE: AT PRESENT YOU MUST CONNECT THE LOWEST NUMBERED ; PIN FIRST, DUE TO BUGS IN SOCKET-SET ASSIGNMENT IN NCP. ARPCON: MOVE T,A ;Open operand word HRL T,D ;is mode,,channel SKIPN TT,SKTBAS ;get base of local socket group TLO T,10 ;not yet allocated, use gensoc mode ADD TT,A ;get local sock number to be opened ; TLZ B,777000 ;*** TEMPORARILY CLEAR NETWORK NUMBER UNTIL ITS IS FIXED *** MOVEM B,ARPHST ;Save last Arpanet host hacked for ANALYZE .CALL [ SETZ ;open 'er up SIXBIT/OPEN/ T ;mode,,channel ['NET',,] ;arpanet device TT ;local socket C ;foreign socket SETZ B ] ;foreign host IFN $$ERRHAN,JRST ANALNS .ELSE POPJ P, SKIPE SKTBAS JRST CONNE0 SYSCAL RCHST,[A ? MOVEM T ? MOVEM T] ;Get local socket, from first pin .LOSE %LSSYS SUB T,A ;get socket base MOVEM T,SKTBAS CONNE0: JUMPL D,POPJ1 ;asynchronous, return now ;otherwise, drop into CONFIN ;Call: MOVEI A,pin ;pin number of connection ; MOVEI D,flags ;20 if listening, 0 if not. Left over from call to ARPCON. ; PUSHJ P,CONFIN ;finish connection ; lossage - you may call ANALYZE to get an error message ; win - clobbers only T and TT CONFIN: MOVEI TT,30.*60. ;wait at most one minute SKIPE DEBUG ;In debug mode, wait forever MOVSI TT,177777 CONFI1: MOVEI T,%NSRFS ;Which state we started out in depends TRNE D,20 ;on whether we were listening or initiating. MOVEI T,%NSLSN .CALL CONFIC ;Wait up to time in TT to leave state in T. .LOSE %LSSYS CAIE T,%NSOPN ;check good state CAIN T,%NSINP JRST POPJ1 CAIE T,%NSRFC CAIN T,%NSCLI JRST POPJ1 IFN $$ERRHAN,JRST ANALNS ;losing state .ELSE POPJ P, CONFIC: SETZ ;wait for connection to open up 'NETBLK' A T ;wait until not in state in T TT SETZM T ;return state ];$$CONNECT ];$$ARPA*ITS IFN $$ERRHAN,[ ANALNS: PUSH P,B ;ANALYZE AND THEN POPJ PUSH P,C JRST ANALN1 ] ;END IFN $$ERRHAN ;;; Chaos network connection routines IFN $$CHAOS,[ IFN ITS,[ IFN $$SERVE,[ ;Call: MOVEI A,chnl ;Input channel number. That+1 is output channel. ; MOVEI C,contact name ;an ASCIZ string ; MOVEI D,window size ; PUSHJ P,NETWRK"CHASRV ; lossage ;you may call ANALYZE to get an error message. ; ;If $$ERRHAN is nonzero, we call ANALYZE for you. ; ;Returns in B the number of the foreign host. ; ;If $$SYSDBG is 0, then connections from all hosts are ;refused, and SERVE fails to skip. ;If $$SYSDBG is 1, then SERVE accepts all connections but returns in C ;a value which is nonzero if the foreign host ought to be locked out by SYSDBG. ;Clobbers A, D, T and TT. $$CONNECT==1 ;We call CHALSN. CHASRV: SYSCAL SSTATU,[MOVEM TT ? MOVEM SYSDBG'] .LOSE %LSSYS MOVEI TT,%COLSN PUSHJ P,CHACN0 ;Start things up POPJ P, ;Lost ;Listen done. Check host number, return OPN or CLS CAIE TT,%CSRFC ;Have we an RFC to accept? POPJ P, ;No, something went wrong SYSCAL PKTIOT,[MOVEI (A) ? MOVEI PKTBUF] ;Get the RFC packet .LOSE %LSSYS LDB B,[$CPKSA+PKTBUF] ;Get source host IFN $$HST3,IOR B,[NW%CHS] .ELSE TLO B,NW%CHS_9 ;Including network number IFE $$SYSDBG,[ ;Reject rfc if system down SKIPL SYSDBG JRST CHASV1 MOVEI T,%COCLS ;Return CLS DPB T,[$CPKOP+PKTBUF] PUSH P,C MOVEI C,[ASCIZ/System not up/] PUSHJ P,CHSTNG POP P,C SYSCAL PKTIOT,[MOVEI 1(A) ? MOVEI PKTBUF] .LOSE %LSSYS JRST CHASRV ;Try again CHASV1: ];$$SYSDBG MOVEI T,%COOPN ;Return Open DPB T,[$CPKOP+PKTBUF] SYSCAL PKTIOT,[MOVEI 1(A) ? MOVEI PKTBUF] .LOSE %LSSYS IFN $$SYSDBG,[ SKIPL C,SYSDBG ;If system being debugged, may disallow JRST [ SETZ C, ? JRST POPJ1 ] ;Unlike Arpanet, we don't have selective disallow, just disallow everyone ];$$SYSDBG JRST POPJ1 ] ;END IFN $$SERVE ];ITS IFN TNX,[ ];TNX IFN $$CONNECT,[ IFN ITS,[ ;CHAOS NETWORK CONNECT ROUTINE ; ;Call: MOVEI A,chnl ;Input channel number. That+1 is output channel. ; MOVEI B,host ;host number to connect to ; MOVEI C,contact name ;an ASCIZ string ; MOVEI D,window size ; PUSHJ P,NETWRK"CHACON ; lossage ;you may call ANALYZE to get an error message. ; ;If $$ERRHAN is nonzero, we call ANALYZE for you. ; ;Clobbers only T and TT. ; ;CHALSN is the same as CHACON except that it uses LSN instead of RFC. ; B is host number it must be from, or 0 if any host is acceptable. .VECTOR PKTBUF(%CPMXW) ;Buffer used by Open, Close, and Analyze CHACON: $$LOG, LOG CHACON,[B,C] MOVEI TT,%CORFC PUSHJ P,CHACN0 ;Start things up POPJ P, ;Lost CAIE TT,%CSOPN JRST CHACNL ;Started but didn't get open JRST POPJ1 ;CHACON done CHACN0: SETZM PKTBUF MOVE T,[PKTBUF,,PKTBUF+1] BLT T,PKTBUF+%CPMXW-1 ;For extra luck, clear the packet buffer DPB B,[$CPKDA+PKTBUF] ;Destination host DPB TT,[$CPKOP+PKTBUF] PUSHJ P,CHSTNG ;Store string from C SYSCAL CHAOSO,[MOVEI (A) ? MOVEI 1(A) ? D] ;Assign Chaos index JRST CHACNL SYSCAL PKTIOT,[MOVEI 1(A) ? MOVEI PKTBUF] ;Send RFC or LSN .LOSE %LSFIL MOVEI TT,$$CHATO ;15-second timeout SKIPE DEBUG MOVSI TT,177777 ;Or infinite, in debug mode LDB T,[$CPKOP+PKTBUF] CAIE T,%COLSN ;Get the boring state SKIPA T,[%CSRFS] MOVEI T,%CSLSN SYSCAL NETBLK,[MOVEI 1(A) ? T ? TT ? MOVEM TT] ;Await completion of connection JRST CHACNL JRST POPJ1 ;Return to second half CHALSN: MOVEI TT,%COLSN PUSHJ P,CHACN0 ;Start things up POPJ P, ;Lost ;Listen done. Check host number, return OPN or CLS CAIE TT,%CSRFC ;Should be RFC into LSN JRST CHACNL SYSCAL PKTIOT,[MOVEI (A) ? MOVEI PKTBUF] ;Get the RFC packet .LOSE %LSFIL LDB T,[$CPKSA+PKTBUF] ;Check source host CAIE T,(B) ;Not looking at network number JUMPN B,CHALS2 ;Jump if doesn't match MOVEI T,%COOPN ;Matches or we don't care, return open DPB T,[$CPKOP+PKTBUF] SYSCAL PKTIOT,[MOVEI 1(A) ? MOVEI PKTBUF] .LOSE %LSFIL JRST POPJ1 CHALS2: MOVEI T,%COCLS ;Return CLS DPB T,[$CPKOP+PKTBUF] PUSH P,C MOVEI C,[ASCIZ/You are the wrong host./] PUSHJ P,CHSTNG POP P,C SYSCAL PKTIOT,[MOVEI 1(A) ? MOVEI PKTBUF] .LOSE %LSFIL JRST CHALSN ;Try again CHACNL: ;CHACON or CHALSN lost IFN $$ERRHAN, JRST ANALNS .ELSE POPJ P, ;Store string from C into PKTBUF. Bash T, TT CHSTNG: PUSH P,B PUSH P,C MOVE B,[440800,,PKTBUF+%CPKDT] MOVEI TT,0 HRLI C,440700 CHSTG1: ILDB T,C JUMPE T,CHSTG2 IDPB T,B CAIGE TT,%CPMXC-1 AOJA TT,CHSTG1 CHSTG2: DPB TT,[$CPKNB+PKTBUF] POP P,C POP P,B POPJ P, ] ;END IFN $$CONNECT ];ITS IFN TNX,[ ];TNX IFN $$SIMPLE,[ IFN ITS,[ ; CHASMP ; A - channel pair ; B - foreign host ; C - pointer to asciz string of contact name and arguments (if any) ; D - aobjn pointer to buffer in which answer is returned as asciz string ; Returns: ; non-skip failed to get response, or error response (you can call ANALYZE) ; skip once CLS response, asciz string in D's buffer ; skip twice ANS response, asciz string in D's buffer CHASMP: PUSH P,D MOVEI D,5 ;Meaningless window size MOVEI TT,%CORFC PUSHJ P,CHACN0 ;Start things up JRST CHASM9 ;Lose CAIN TT,%CSCLS SYSCAL PKTIOT,[MOVEI (A) ? MOVEI PKTBUF] ;Get the ANS/CLS packet JRST CHASM9 ;Didn't get proper response LDB TT,[$CPKOP+PKTBUF] CAIN TT,%COANS AOSA -1(P) ;Skip twice CAIN TT,%COCLS AOSA -1(P) ;Skip once JRST CHASM9 ;Skip no times (shouldn't get here usually) PUSH P,C HLRE C,-1(P) ;Get minus number of words IMUL C,[-5] SUBI C,1 ;Number of characters not counting terminator MOVE D,-1(P) HRLI D,440700 MOVE TT,[440800,,PKTBUF+%CPKDT] LDB T,[$CPKNB+PKTBUF] CAMGE T,C MOVE C,T CHASM1: ILDB T,TT IDPB T,D SOJG C,CHASM1 IDPB C,D POP P,C CHASM9: POP P,D POPJ P, ] ;END IFN $$SIMPLE ];ITS IFN TNX,[ ];TNX ] ;END IFN $$CHAOS IFN $$TCP,[ IFN $$SERVE,[ ;Call: MOVEI A,chnl ;Input channel number. That+1 is output channel. ; MOVEI B,port# ; PUSHJ P,NETWRK"TCPSRV ; lossage ;you may call ANALYZE to get an error message. ; ;If $$ERRHAN is nonzero, we call ANALYZE for you. ; ;Returns in B the number of the foreign host. ; ;If $$SYSDBG is 0, then connections from all hosts are ;refused, and SERVE fails to skip. ;If $$SYSDBG is 1, then SERVE accepts all connections but returns in C ;a value which is nonzero if the foreign host ought to be locked out by SYSDBG. ;Clobbers A, D, T and TT. $$CONNECT==1 ;just for TCPCNL TCPSRV: SYSCAL SSTATU,[MOVEM TT ? MOVEM SYSDBG'] .LOSE %LSSYS SYSCAL TCPOPN,[MOVEI (A) ? MOVEI 1(A) ? B [-1] ? [-1]] ; Wild fgn port and host. JRST TCPCNL ; Bah, failed for some reason. MOVEI TT,$$TCPTO ;15-second timeout SKIPE DEBUG MOVSI TT,177777 ;Or infinite, in debug mode MOVEI T,%NSLSN ; Initial state to hang on. TCPSV1: SYSCAL NETBLK,[MOVEI 1(A) ? T ? TT ? MOVEM T ? MOVEM TT] .LOSE %LSSYS ; Gack? JUMPLE TT,TCPCNL ; Exit if timed out CAIN T,%NSRFC ; If in SYN-RECEIVED state JRST TCPSV1 ; then it's OK to keep waiting. CAIE T,%NSOPN ; Else should be open now. CAIN T,%NSRFN CAIA JRST TCPCNL ; Aw, phooie. ; TCP connection open now. SYSCAL RFNAME,[MOVEI 1(A) ? MOVEM T MOVEM T ; Local port # (should be = ICPSOC) MOVEM T ; Foreign port # MOVEM B]; Foreign host # .LOSE %LSSYS ; Gack? IFE $$SYSDBG,[ ;Reject rfc if system down SKIPL SYSDBG JRST TCPSV2 ;I don't know how to do this right. Just send string and close MOVE T,[440700,,[ASCIZ/System not up/]] MOVEI TT,13. SYSCAL SIOT,[MOVEI 1(A) ? T ? TT] JFCL SYSCAL CLOSE,[MOVEI (A)] .LOSE %LSSYS SYSCAL CLOSE,[MOVEI 1(A)] .LOSE %LSSYS JRST TCPSRV ;Try again TCPSV2: ];$$SYSDBG IFN $$SYSDBG,[ SKIPL C,SYSDBG ;If system being debugged, may disallow JRST [ SETZ C, ? JRST POPJ1 ] ;Unlike Arpanet, we don't have selective disallow, just disallow everyone ];$$SYSDBG JRST POPJ1 ] ;END IFN $$SERVE IFN $$CONNECT,[ ;TCP CONNECT ROUTINE ; ;Call: MOVEI A,chnl ;Input channel number. That+1 is output channel. ; MOVEI B,host ;host number to connect to ; MOVEI C,foreign port ;you don't get to pick the local port ; PUSHJ P,NETWRK"TCPCON ; lossage ;you may call ANALYZE to get an error message. ; ;If $$ERRHAN is nonzero, we call ANALYZE for you. ; ;Clobbers only T and TT. TCPCON: $$LOG, LOG TCPCON,[B,C] MOVEI T,1(A) ;Output channel .CALL [ SETZ ? 'TCPOPN' ? A ? T ? [-1] ? C ? SETZ B ] JRST TCPCNL ;Didn't even start trying MOVEI TT,$$TCPTO ;15-second timeout SKIPE DEBUG MOVSI TT,177777 ;Or infinite, in debug mode .CALL [ SETZ ? 'NETBLK' ? MOVEI 1(A) ? MOVEI %NSRFS ? TT SETZM T ] ;T gets state it went into .LOSE %LSSYS CAIE T,%NSOPN ;Good state? CAIN T,%NSRFN JRST POPJ1 ;Success TCPCNL: ;Timed out or failed IFN $$ERRHAN, JRST ANALNS .ELSE POPJ P, ];$$CONNECT ];$$TCP IFN $$ANALYZE*ITS,[ ; Network error analysis. ;Call: MOVEI A,pin ;channel number that is losing ; PUSHJ P,ANALYZE ; .VALUE ;always skip-returns ; ;Clobbers only T and TT. Uses the PUTCHR routine to type out its messages. ;Does not type a crlf after the message. .VECTOR WHYINT(5) ;Cruft returned from WHYINT ANALYZE: AOS (P) PUSH P,B PUSH P,C ANALN1: SYSCAL USRVAR,[MOVEI %JSELF ? MOVEI .RIOC(A) ? MOVEM T ] ;Channel open? .LOSE %LSSYS JUMPE T,ANALN2 ;No, don't clobber error code with WHYINT SYSCAL WHYINT,[A ? MOVEM WHYINT ;Get device type MOVEM WHYINT+1 ? MOVEM WHYINT+2 ? MOVEM WHYINT+3 MOVEM WHYINT+4 ] .LOSE %LSFIL MOVE T,WHYINT ; Get device type IFN $$TCP\$$ARPA,[ CAIE T,%WYNET CAIN T,%WYTCP JRST ANAL1 ; Go analyze NCP/TCP channel. ];$$TCP\$$ARPA IFN $$CHAOS,[ CAIN T,%WYCHA JRST ANLCHA ;Chaos net channel open, further info available ];$$CHAOS ANALN2: SYSCAL USRVAR,[MOVEI %JSELF ? MOVEI .RIOS(A) ? MOVEM T] ;Get I/O status wd for channel .LOSE %LSSYS LDB TT,[220600,,T] ;only the open-loss code is available CAIN TT,%EFLDV ;Device full (this one applies to both Arpanet & Chaos net) JRST [ JSP TT,SPEAK ASCIZ \All sockets in use.\ ] CAIN TT,%ENRDV ;Device not ready JRST [ JSP TT,SPEAK ASCIZ \Network down.\ ] IFN $$ARPA,[ CAIE TT,%ENAPP ;Other end of pipeline gone, or CAIN TT,%ENSDR ;No such directory JRST [ ;Host is down, say why. MOVE T,ARPHST ;Go print status for last host hacked, is probably right one JRST ANALC1 ] ;Unfortunately, channel not open, can't get right host CAIN TT,%ESCO ;Self-contradictory open JRST [ JSP TT,SPEAK ASCIZ \Connection cannot be opened because of inconsistent byte sizes.\ ] ];$$ARPA SYSCAL IOPUSH,[A] ;Some other error - get ITS error message .LOSE %LSSYS .CALL [ SETZ SIXBIT/OPEN/ MOVEI (A) ;here we rely on .UAI=0 ['ERR',,] MOVEI 3 ;Status from T SETZ T ] .LOSE %LSFIL MOVEI TT,[ASCIZ\? Internal error - \] PUSHJ P,ZTYPE ANAL0: SYSCAL IOT,[MOVEI (A) ? MOVEM T] ;copy error message to output device .LOSE %LSSYS CAIGE T,40 JRST ANALYX PUSHJ P,PUTCHR JRST ANAL0 ANALYX: SYSCAL IOPOP,[A] .LOSE %LSSYS ANALX: POP P,C POP P,B POPJ P, IFN $$TCP\$$ARPA,[ ; Arpanet channel still open - further information available ANAL1: HRRZ TT,WHYINT+1 ;get socket state JUMPE TT,ANALC .SEE %NSCLS ;connection closed IFN $$TCP,[ CAIN T,%WYTCP JRST ANAL20 ; Report TCP channel state ] ;$$TCP CAIN TT,%NSRFS ;state is %NSRFS => we must have timed out at CONFIN. JRST [ JSP TT,SPEAK ASCIZ /Timed-out while awaiting response to opening of connection./ ] CAIN TT,%NSLSN ;same but listening rather than rfc'ing JRST [ JSP TT,SPEAK ASCIZ/Timed-out while listening for request to open connection./ ] JRST ANAL50 ; Give up, complain about illegal state IFN $$TCP,[ ANAL20: CAILE TT,%NTINP JRST ANAL50 ; State too big PUSH P,TCPSTB(TT) ; Get state message MOVEI TT,[ASCIZ /Connection /] PUSHJ P,ZTYPE POP P,TT JRST SPEAK TCPSTB: OFFSET -. %NTCLS:: [ASCIZ /closed./] %NTLSN:: [ASCIZ /listening./] %NTSYR:: [ASCIZ /wedged, SYN rcvd but not acked./] %NTCLU:: [ASCIZ /being closed by foreign host./] %NTSYN:: [ASCIZ /waiting for response to SYN./] %NTOPN:: [ASCIZ /open./] %NTWRT:: [ASCIZ /open, output buffer full./] %NTCLX:: [ASCIZ /being closed by user./] %NTCLI:: [ASCIZ /closed, input still available./] %NTINP:: [ASCIZ /open, input available./] OFFSET 0 ] ;$$TCP ANAL50: PUSH P,TT MOVEI TT,[ASCIZ\? Socket entered illegal state #\] PUSHJ P,ZTYPE LDB T,[030300,,(P)] SKIPE T PUSHJ P,[ ADDI T,"0" ? JRST PUTCHR ] POP P,T ANDI T,7 ADDI T,"0" PUSHJ P,PUTCHR JRST ANALX ];$$TCP\$$ARPA SPEAK: PUSHJ P,ZTYPE ;send message from TT JRST ANALX ; and return IFN $$TCP\$$ARPA,[ ;Say why connection was closed ANALC: SYSCAL RFNAME,[MOVEI (A) ? MOVEM T MOVEM T ? MOVEM T ; Local port, fgn port MOVEM T ] ; Fgn host (NCP: 1.1-1.9) .LOSE %LSSYS HRRZ TT,WHYINT+3 ; Get close reason CAIL TT,LCLSTB SETO TT, MOVE TT,CLSTAB(TT) ;get asciz close reason PUSH P,T ;save host number PUSH P,TT PUSHJ P,ZTYPE POP P,TT POP P,T JUMPGE TT,ANALX ;return if host is up MOVE TT,WHYINT CAIN TT,%WYTCP ; If TCP, must do further checking JRST [ GETNET TT,T ; Get network number CAME TT,[NW%ARP] ; Can only get status for arpanet sites JRST ANALX ; Sorry, no can do. JRST .+1] ; Aha, try NETHST call. PUSHJ P,CRLF ;CRLF between down message and down reason ANALC1: SYSCAL NETHST,[T ? MOVEM T] ;get information about why host down .LOSE %LSSYS MOVE B,T TRZ T,777760 ;RH gets just reason down TLNE T,2000 ;skip if down SETO T, MOVE TT,DEDTAB(T) ;get asciz string describing situation PUSHJ P,ZTYPE IFE $$UPTM,JRST ANALX IFN $$UPTM,JRST ANALTM IFN $$UPTM,[ ;OPTIONALLY, SAY WHEN THE IMP THINKS THE HOST WILL BE BACK UP. ANALTM: ANDI B,177760 ; get time back JUMPE B,ANALX ; flush if nothing CAIN B,177740 ; -2 means unknown future time JRST ANALX ; There isn't anything useful to say about this. MOVEI TT,[ASCIZ / Host is expected back up /] PUSHJ P,ZTYPE CAIN B,177760 ; -1 means more than a week JRST [ JSP TT,SPEAK ASCIZ /over a week from now./ ] LDB T,[150300,,B] ; get day of week LDB TT,[100500,,B] ; get hours time SUBI TT,5 ; EST/GMT offset PUSH P,B .RYEAR B, ; get time info TLNE B,100000 ; daylight losing time? AOSL TT ; yes, go ahead an hour JUMPGE TT,NODAY ; easy way out ADDI TT,24. ; move up a day SOSGE T ; and days back MOVEI T,6 ; back to Sunday NODAY: MOVE B,TT ; Save real hours MOVE TT,DOWTAB(T) ; Get string describing day of week. PUSHJ P,ZTYPE MOVEI TT,[ASCIZ / at /] PUSHJ P,ZTYPE MOVE T,B ; get hours time PUSHJ P,2DTYPE MOVEI T,":" PUSHJ P,PUTCHR POP P,B ; Restore original time LDB T,[040400,,B] ; get minutes/5 IMULI T,5. ; make into real minutes PUSHJ P,2DTYPE MOVEI TT,[ASCIZ/ EST./] .RYEAR T, TLNE T,100000 MOVEI TT,[ASCIZ/ EDT./] PUSHJ P,ZTYPE JRST ANALX ;TYPE NUMBER IN T AS TWO DECIMAL DIGITS. 2DTYPE: IDIVI T,10. ; split high and low order ADDI T,"0" ; ASCIIify ADDI TT,"0" ; ASCIIify PUSH P,TT PUSHJ P,PUTCHR POP P,T JRST PUTCHR DOWTAB: [ASCIZ/on Monday/] [ASCIZ/on Tuesday/] [ASCIZ/on Wednesday/] [ASCIZ/on Thursday/] [ASCIZ/on Friday/] [ASCIZ/on Saturday/] [ASCIZ/on Sunday/] [ASCIZ/on April Fool's day/] ] ;END IFN $$UPTM ];$$TCP\$$ARPA IFN $$CHAOS,[ ;Analyze on chaos channel, still open ANLCHA: MOVE TT,WHYINT+1 ;Connection state CAIE TT,%CSLOS CAIN TT,%CSCLS JRST ANLCH1 CAIE TT,%CSINC JRST ANLCH0 ;Still open JSP TT,SPEAK ASCIZ /Connection broken -- foreign host not communicating./ ANLCH0: PUSH P,CHSTTB(TT) MOVEI TT,[ASCIZ/Timed-out while connection /] PUSHJ P,ZTYPE POP P,TT JRST SPEAK CHSTTB: [ASCIZ/closed/] [ASCIZ/listening/] [ASCIZ/has received RFC/] [ASCIZ/trying to get connected/] ;has sent RFC [ASCIZ/open/] [ASCIZ/lost/] [ASCIZ/broken/] ANLCH1: PUSH P,CHSTTB(TT) MOVEI TT,[ASCIZ/Connection /] PUSHJ P,ZTYPE POP P,TT PUSHJ P,ZTYPE MOVEI TT,[ASCIZ/ -- /] PUSHJ P,ZTYPE HLRZ TT,WHYINT+2 ;get number of input packets ANLCH2: SOJL TT,ANALX ;scan input looking for CLS, LOS HLRZ T,WHYINT+4 ;Pick up input channel number SYSCAL PKTIOT,[T ? MOVEI PKTBUF] .LOSE %LSFIL LDB T,[$CPKOP+PKTBUF] CAIE T,%COCLS CAIN T,%COLOS SKIPA B,[440800,,PKTBUF+%CPKDT] JRST ANLCH2 LDB C,[$CPKNB+PKTBUF] ANLCH3: SOJL C,ANALX ILDB T,B PUSHJ P,PUTCHR JRST ANLCH3 ];$$CHAOS IFN $$ARPA,[ ; Tables ;Close Reasons [ASCIZ/Illegal close-reason code??/] CLSTAB: OFFSET -. %NCNTO::[ASCIZ/Connection never opened??/] %NCUSR::[ASCIZ/Connection legitimately closed??/] %NCFRN::[ASCIZ/Connection closed by foreign host./] %NCRST::[ASCIZ/Connection reset by foreign host./] %NCDED::400000,,[ASCIZ/Host died./] %NCINC::400000,,[ASCIZ/Incomplete transmission - foreign host or network died./] %NCBYT::[ASCIZ/Byte size mismatch??/] %NCNCP::[ASCIZ/Local Network Control Program reset./] %NCRFS::[ASCIZ/Request for Connection refused by foreign host./] LCLSTB::OFFSET 0 ;Host Dead Reasons [ASCIZ/Illegal host-dead code??/] DEDTAB: [ASCIZ/ Network lossage./] ;0 probably no host-dead-reason returned [ASCIZ/ Destination Host dead./] ;1 WOULDN'T SAY WHY [ASCIZ/ Foreign Network Control Program not in operation./] [ASCIZ/ Destination Host or IMP does not exist./] [ASCIZ/ Destination Host is initializing its NCP software./] [ASCIZ/ Destination Host down for scheduled maintenance./] [ASCIZ/ Destination Host down for scheduled hardware work./] [ASCIZ/ Destination Host down for scheduled software work./] [ASCIZ/ Destination Host is in emergency restart./] [ASCIZ/ Destination Host down due to power failure./] [ASCIZ/ Destination Host is stopped at a breakpoint./] [ASCIZ/ Destination Host down due to hardware failure./] [ASCIZ/ Destination Host is not scheduled to be up./] [ASCIZ/ (Undefined host-down code 13.)/] [ASCIZ/ (Undefined host-down code 14.)/] [ASCIZ/ Destination Host is coming up now./] ];$$ARPA ];END IFN $$ANALYZE*ITS IFN $$CVH,[ ;;;; Utilities - CVH2NA, CVH3NA ; CVH2NA - Convert network host address in A to HOSTS2 format. ; A/ net address (any format) ; Returns A CVH2NA: PUSH P,B LDB B,[301400,,A] ; Get high 12 bits of net address CAIGE B,70 ; If less than lowest HOSTS2-fmt value JUMPN B,CVH2N3 ; then must be HOSTS3, go convert. CAIL B,1000 ; If any of high 3 bits set, JRST CVH2N3 ; then it's a HOSTS3 strange-fmt number. JUMPN B,CVH2N2 CAILE A,377 ; Zero network, so must be ARPA net JRST CVH2N1 ; Not just 8 bits, just add net number. ; Old-style 8-bit Arpanet host number LSHC A,-6. ROT B,6. DPB B,[112000,,A] CVH2N1: TLO A,(12_33) JRST CVH2N9 ; Probably HOSTS2 format number CVH2N2: JRST CVH2N9 ; For now, that's good enough. ; HOSTS3 format number, convert it. CVH2N3: CAIN B,12 ; Arpa net? JRST [ LSHC A,-16. ANDI A,377 ROT B,16. DPB B,[112000,,A] TLO A,(12_33) JRST CVH2N9] CAIN B,7+ ; Chaos net? JRST [ ANDI A,177777 ; Yup, fix it up. TLO A,(7_33) JRST CVH2N9] CAIN B,22 ; LCS net? JRST [ LSHC A,-8. ANDI A,-1 LSH A,2 LSHC A,8. TLO A,(22_33) JRST CVH2N9] ; Not a known net, but try to do something plausible. ANDCM A,[-1_24.] ; Preserve low 24 bits DPB B,[331100,,A] ; put net # into HOSTS2 field. CVH2N9: POP P,B POPJ P, ] ;$$CVH ; CVH3NA - Convert network host address in A to HOSTS3 (Internet) format. ; A/ net address (any format) ; Returns A CVH3NA: PUSH P,B LDB B,[301400,,A] ; Get high 12 bits of net address CAIGE B,70 ; If less than lowest HOSTS2 value, JUMPN B,CVH3N3 ; it's already HOSTS3 format! (unless zero) CAIL B,1000 ; If any of high 3 bits were set, JRST CVH3N3 ; it must be a HOSTS3 strange-fmt addr. JUMPN B,CVH3N2 ; If not zero, then must assume HOSTS2 fmt. ; Old-format 8-bit Arpanet host number, or HOSTS2 with zero net. IFE $$ARPA,IFN $$CHAOS, IOR A,[NW%CHS] ? JRST CVH3N3 CAILE A,377 JRST CVH3N6 ; If greater than 8 bits, assume HOSTS2, zero net. LSHC A,-6 ; Put 10 bits spacing between host/imp #s. LSH B,-<2+8.> LSHC A,<2+8.+6> TLO A,(12_24.) ; and add ARPA network number. JRST CVH3N3 ; HOSTS2 format number CVH3N2: TRZE B,7 ; Zap low 3 bits to ensure correct comparison JRST CVH3N5 ; If any were set, can't be Chaosnet. CAIN B,7_3 ; Chaos net? JRST [ ANDI A,177777 ; Yes, kill all but bottom 16 bits TLO A,(NE%UNT+<7_24.>) ; Add Chaos net # JRST CVH3N3] CVH3N5: CAIN B,12_3 ; Arpa net? CVH3N6: JRST [ LSHC A,-9. ANDI A,177777 ROT B,9. DPB B,[201000,,A] TLO A,(12_24.) JRST CVH3N3] CAIN B,22_3 ; LCS net? JRST [ LSHC A,-8. LSH A,-2 ANDI A,377 LSHC A,-8. TLO A,(22_24.) JRST CVH3N3] ; No match, assume it's HOSTS3. CVH3N3: POP P,B POPJ P, $$LOG,[ ;;; Logging - CStacy, 22 October 1984 ;;; ;;; This facility is (originally) so that I can see which users are using ;;; the TELNET and FTP facilities on our machine and to help discover who ;;; is using us as a base in attacking other sites. Maybe ITS should do ;;; some sort of network logging like Multics, but I'll just put it in ;;; this library for now since it isn't clear how generally useful it is ;;; or what functionality we want. LOGO==1 ;Channel for log file. LOGL==2 ;Channel for log file lock-file. ;;; NOTE: The user could easily become screwed up if we're interrupted. ;;; --We have IOPUSHed channels away from the user without consent. ;;; --We do synchronous file IO behind its back and handle our own errors. ;;; Therefore, LOG processing defers all interrupts. ;;; The LOG stuff is only called before opening and after closing network ;;; channels, and so this should be a first approximation to a safe practice. ;;; Logfile entries are scattered through the file in sequential order. ;;; They are of variable length. They begin with a unique id number; ;;; The log for a particular job can be threaded from the id. ;;; ;;; An transaction entry looks like: ;;; /BEGIN/ ;;; BEGIN-CODE (id) The 36 bit unique id code for this job. ;;; TIMESTAMP The time of the entry. ;;; OPCODE Sixbit name of the transaction type. ;;; CRUFT WORDS Transaction dependant data. ;;; ;;; ;;; The NETLOG program (source in AR2:CSTACY;NETLOG) can be used to ;;; expand a logfile into an ASCII representation of some or all of the ;;; transactions. ;;; ;;; It is possible to have incomplete records of network usage ;;; in the logfile, since if many things go wrong we abort the ;;; logging procedure rather than waste time being too robust ;;; when the entire facility is supposed to be invisible. ;;; NETWRK routines may call LOGACT to log some action. ;;; Callers provide any list of cruft they want, the first word ;;; being SIXBIT name of the operation. ;;; Semantics for entries should be documented here for interested ;;; programmers to find out how to decode the log file. ;;; ;;; OPEN: ;;; ANALYZ: ... ;;; .SCALAR LOGID ;Our id number in the log file. ;;; LOGACT - Log some action ;;; A/ number of crufty words on the stack (P) before the funcall. ;;; Smashes no ACs and never skips. ;;; Caller must pop his args back off himself. LOGACT: MOVE T,P ;Save current SP here for a moment. .SUSET [.RPICLR,,TT] ;Read global interrupt defer word. PUSH P,TT ;Stack it away for restoration. .SUSET [.SPICLR,,[0]] ;Defer all interrupts. .IOPUSH LOGO, ;Push the channels we want, .IOPUSH LOGL, ;hoping the IOPDL doesn't overflow. PUSH P,A ;Do not smash ACs. PUSH P,B PUSH P,C PUSH P,D MOVE B,T ;B gets SP to top of LOGACT frame. LOGA10: PUSHJ P,LOGOPN ;Open log file if needed. JRST LOGCLS SYSCAL ACCESS,[%CLIMM,,LOGO ? C] ;Move to EOF. JRST LOGCLS SUB B,A ;Point to first arg. HRLZ A,A HRR A,B ;A has length,,adr of crufties. LOGA20: SYSCAL RQDATE,[%CLOUT,,B] JRST LOGCLS SKIPE C,LOGID ;If our id has been initialized, JRST LOGA30 ; go make an entry. .SUSET [.RUIND,,C] ;Else find our job number. HRL C,B ;*** This should be more or less unique? ** MOVEM C,LOGID ;Set our id. LOGA30: MOVE T,[444400,,[SIXBIT /BEGIN/]] MOVEI TT,1 SYSCAL SIOT,[%CLIMM,,LOGO ? T ? TT] ;Write entry marker. JRST LOGCLS MOVE T,[444400,,B] MOVEI TT,2 SYSCAL SIOT,[%CLIMM,,LOGO ? T ? TT] ;Write timestamp and id. JRST LOGCLS .SUSET [.RUNAME,,B] .SUSET [.RJNAME,,C] MOVE T,[444400,,B] MOVEI TT,2 SYSCAL SIOT,[%CLIMM,,LOGO ? T ? TT] ;UNAME, JNAME. CAIA LOGA40: HRRZ T,A ;Get ptr to stacked args. HRLI T,444400 ;Make BP. HLRZ TT,A ;Get length. SYSCAL SIOT,[%CLIMM,,LOGO ? T ? TT] ;Write opcode, crufties. JRST LOGCLS LOGCLS: .CLOSE LOGO, .CLOSE LOGL, .IOPOP LOGL, .IOPOP LOGO, POP P,D POP P,C POP P,B POP P,A POP P,T ;Probably -1 (no global deferment). .SUSET [.SPICLR,,T] ;Restore interrupt defer state. POPJ P, ;All done. ;;; LOGOPN - Seize the logfile lock, and open the logfile for writing. ;;; Uses LOGL and LOGO file channels, and skips on success. ;;; Returns length of the database in C, does not smash other ACs. ;;; Notes: ;;; o If the lock file is missing LOGOPN will re-create it. ;;; o If the logfile itself is missing, we just fail. LOGMLT==6 ;Maximum # attempts to make trying to seize the lock. LOGOPN: PUSH P,A PUSH P,B SETZ B, ;Count of locking attempts in B. LOGLOK: SYSCAL OPEN,[%CLBIT,,.BIO\%DOWOV ? %CLIMM,,LOGL [SIXBIT /DSK/] [SIXBIT /NETLOG/] [SIXBIT /LOCK/] [SIXBIT /SPACY/]] CAIA JRST LOGLKD ;Got it! CAIL B,LOGMLT ;Else if we have exceeded the retry maximum JRST LOGLKF ; Fail. .STATUS LOGL,A ;Let's see why the open failed. LDB A,[220600,,A] ;Get error code. CAIN A,%ENAFL ;If someone else has the lock JRST [ MOVEI T,30. ; Sleep for one second. .SLEEP T, ; (They should give it up soon.) AOS B ; Keep count of attempts to seize lock. JRST LOGLOK ] ; Try,try again. CAIE A,%ENSFL ;Hmmm....Maybe the lock file is missing? JRST LOGLKF ; Nope - some random lossage. SYSCAL OPEN,[%CLBIT,,.UAO ? %CLIMM,,LOGL ;Re-create it. [SIXBIT /DSK/] [SIXBIT /NETLOG/] [SIXBIT /LOCK/] [SIXBIT /SPACY/]] JRST LOGLKF ; Fail if could not create lock. .CLOSE LOGL, ;Else close file JRST LOGLOK ;and try to seize it again. LOGLKD: SYSCAL OPEN,[%CLBIT,,.BII ? %CLIMM,,LOGO [SIXBIT /DSK/] [SIXBIT /NETLOG/] [SIXBIT / DATA/] [SIXBIT /SPACY/]] JRST LOGLKF SYSCAL FILLEN,[%CLIMM,,LOGO ? %CLOUT,,C] JRST LOGLKF .CLOSE LOGO, ;Protocol says no lock competition here. SYSCAL OPEN,[%CLBIT,,%DOWOV+.UIO ? %CLIMM,,LOGO [SIXBIT /DSK/] [SIXBIT /NETLOG/] [SIXBIT / DATA/] [SIXBIT /SPACY/]] CAIA ; Huh? We opened it a moment ago??? AOS -2(P) ;Skip return if won. LOGLKF: POP P,B POP P,A POPJ P, ];$$LOG .qmtch=qmtch ;set this back to the value the user gave it .END NETWRK