;XX:RSVCTL.MAC.11, 25-Dec-87 04:38:29, Edit by SRA ; Released. Subttl Table of contents for RSVCTL ; -- Section -- -- Page -- ; ; 1. Edit history.................................................. 1 ; 2. Table of contents............................................. 2 ; 3. Header and copyright information.............................. 3 ; 4. Main program.................................................. 4 ; 5. Commands...................................................... 5 ; 6. Talk to resolver.............................................. 13 ; 7. I/O routines.................................................. 14 ; 8. Support routines.............................................. 15 ; 9. IPCINI........................................................ 16 ; 10. End of program................................................ 17 ; ; (End of table of contents) SUBTTL Header and copyright information TITLE RSVCTL -- Program to send control messages to RESOLV ; Copyright (c) 1987 Massachusetts Institute of Technology. ; ; Note that there is absolutely NO WARRANTY on this software. ; See the file COPYRIGHT.NOTICE for details and restrictions. V%MAJ==1 ; Major version V%MIN==0 ; Minor version V%WHO==0 ; Who last edited (0=SRA@MIT) V%ED==1 ; Edit number SEARCH MACSYM,MONSYM,CMD,DOMSYM .REQUI SYS:MACREL,SYS:CMD .DIREC FLBLST .TEXT "RSVCTL/SAVE" SALL STDAC. ; "Standard" AC definitions MYPID==P1 ; Px ACs for special purposes RSVPID==P2 MSG==P3 ; Location of message page PDLLEN==200 ; Stack size OPDEF JSRET[JRST JSERR0] ; Alternate ways of using OPDEF EJSRET[ERJMP JSERR0] ; MACREL error handlers DEFINE RETBAD(FOO) ; So we can use GTDOM code unchanged ; Size of bytes in word-aligned string data we get from resolver ; Maybe this should be in USRDEF.D? KCCBSZ==9 ; Easiest for KCC to handle KCCBPW==<<^D36/KCCBSZ>*KCCBSZ> ; Formalize assumptions about QNAME length and page size PAGSIZ==1000 ; Size of a page on Twenex (vs. ITS!) IFL <<*KCCBPW>-MAXDNM>,< PRINTX ? QNAME space too small, may fall off data page > SUBTTL Main program EV: JRST START JRST START BYTE (3)V%WHO(9)V%MAJ(6)V%MIN(18)V%ED EVEC==<.-EV,,EV> START: RESET% MOVE P,[-PDLLEN,,PDL-1] CALL CMDINI ; Initialize COMND% parser CALL IPCINI ; Initialize IPCF cruft DO. ; < PROMPT (RSVCTL>) MOVEI T1,[FLDDB. .CMKEY,,KEYTAB] CALL RFIELD HRRZ T2,(T2) CALL (T2) LOOP. ENDDO. ;; Command dispatch table KEYTAB: KEYLEN,,KEYLEN T BOOT ; UC_BUT T EXIT T HELP T INFORMATION ; UC_INF T KILL ; UC_KIL T LOAD ; UC_ZON T PING ; UC_AYT T QUIT T SELECT KEYLEN==.-1-KEYTAB SUBTTL Program commands .HELP: NOISE (with program) CONFRM HRROI T1,HLPMSG PSOUT% RET HLPMSG: ASCIZ | No help available yet. | IFNDEF .PRKIL,<.PRKIL==2> IFNDEF .PRKEP,<.PRKEP==1> .EXIT: NOISE (permanently) MOVSI T4,.PRKIL JRST HALT .QUIT: NOISE (temporarily) MOVSI T4,.PRKEP ; JRST HALT HALT: CONFRM MOVE T1,[.PRAST,,.FHSLF] MOVEI T2,T4 MOVEI T3,1 PRARG% ; MIT EXEC hack (like ITS .BREAK) ERJMP .+1 ; Oh well, we tried HALTF% RET SUBTTL Select command DEFINE DEFPID(NAME) < [ASCIZ NAME],,0 IRPC NAME, > BRINI. KEYB0.,KEYB1.,KEYB2.,KEYB3. PIDTAB: PIDLEN,,PIDLEN DEFPID RESOLVER-DEBUG DEFPID [SYSTEM]RESOLVER PIDLEN==.-1-PIDTAB PIDBRK: EXP W0.,W1.,W2.,W3. PURGE W0.,W1.,W2.,W3. .SELECT:NOISE (which resolver to talk to) MOVEI T1,[FLDDB. .CMCFM,CM%SDH,,,,[ FLDDB. .CMQST,CM%SDH,,,,[ FLDBK. .CMKEY,,PIDTAB,,,PIDBRK]]] CALL RFIELD LOAD T3,CM%FNC,(T3) CAIN T3,.CMCFM JRST SYSRSV ; Get system resolver if confirmed CONFRM ; Otherwise have to handle string STKVAR <,> ; (yuk) HRROI T1,2+PACKET ; Copy to packet buffer CAIE T3,.CMKEY ; Keyword? SKIPA T2,[POINT 7,ATMBUF] ; No, from atom buffer HLRO T2,(T2) ; Yes, from keyword table DMOVE T3,[EXP .IPCIW,0] ; Packet header: DMOVEM T3,PACKET ; get named PID from [SYSTEM]INFO SETZ T3, ; Append name we want SOUT% EJSHLT IBP T1 ; Skip over null byte MOVEI T1,1(T1) ; End of packet SUBI T1,PACKET ; Length of packet HRLI T1,PACKET MOVSM T1,.IPCFP+PDB ; Save packet descriptor SKIPE T1,MYPID ; Do we have a PID? TDZA T2,T2 ; Yes, use it MOVX T2,IP%CPD ; No, create one MOVEM T1,.IPCFS+PDB ; Sender PID MOVEM T2,.IPCFL+PDB ; Flags SETZM .IPCFR+PDB ; Receiver is [SYSTEM]INFO MOVEI T1,.IPCFP+1 ; How much PDB MOVEI T2,PDB ; Where PDB is MSEND% ; Send message to INFO EJSRET ; Lost MOVE T1,.IPCFS+PDB ; Get our PID SKIPN MYPID ; Did we just create it? MOVEM T1,MYPID ; Yeah, save it for posterity MOVEM T1,.IPCFR+PDB ; Is now receiver's PID SETZM .IPCFS+PDB ; Expecting message from INFO SETZM .IPCFL+PDB ; No flags HRLI T1,4 ; How much message we expect HRRI T1,PACKET ; Where to put it MOVEM T1,.IPCFP+PDB ; Save pointer MOVEI T1,.IPCFP+1 ; How much PDB MOVEI T2,PDB ; Where it is MRECV% ; Get answer from INFO EJSRET LOAD T1,IP%CFE,.IPCFL+PDB ; Get error code IFE. T1 ; Did we win? MOVE T1,1+PACKET ; Yes, get resolver's PID MOVEM T1,RSVPID ; Save it ELSE. TMSG <% [SYSTEM]INFO barfed looking for "> HRROI T1,ATMBUF PSOUT% TMSG <" > ENDIF. RET ENDSV. SYSRSV: SAVEAC ; Make argblock in Qx acs MOVX Q1,.MURSP ; Find PID of resolver MOVX Q2,.SPRSV ; System PID table slot number DMOVE T1,[EXP 3,Q1] ; Three word argblock in Qx ACs MUTIL% ; Look up the PID EJSRET ; Fatal error (for now, anyway) MOVEM Q3,RSVPID ; Save the PID RET SUBTTL Resolver commands .PING: NOISE (resolver to see if it is awake) CONFRM MOVX T1,UC.AYT ; Are You There? SETZ T2, ; No QNAME JRST RESOLV ; Join common code .KILL: NOISE (resolver without rebooting it) CONFRM CALL SURE ; Paranoia RET MOVX T1,UC.KIL ; Commit suicide SETZ T2, ; No QNAME JRST RESOLV ; Join common code .BOOT: NOISE (resolver from saved image) CONFRM CALL SURE ; Paranoia RET MOVX T1,UC.BUT ; Reboot the resolver SETZ T2, ; No QNAME JRST RESOLV ; Join common code .INFOR: NOISE (about resolver operation) CONFRM MOVX T1,UC.INF ; Ask resolver to write useful junk SETZ T2, ; No QNAME JRST RESOLV ; Join common code .LOAD: NOISE (new zone file into resolver) MOVEI T1,[FLDDB. .CMTXT,CM%SDH,,] CALL CFIELD ; Get name into ATMBUF MOVX T1,UC.ZON ; Want to reload a zone MOVE T2,[POINT 7,ATMBUF] ; QNAME is name of zone to reload JRST RESOLV ; Join common code ;; Encourage user to think twice about a particular command SURE: PROMPT (Are you sure? ) MOVEI T1,[FLDDB. .CMKEY,,YNTAB,,] CALL CFIELD HRRZ T2,(T2) IFN. T2 TMSG <[Proceeding...] > AOS (P) ELSE. TMSG <[Aborted] > ENDIF. RET YNTAB: YNLEN,,YNLEN T NO,0 T YES,1 YNLEN==.-1-YNTAB SUBTTL Talk to resolver ; This is almost verbatim from GTDOM.MAC. ; Credits: ; This code derived from the RED protocol GTHST% module, ; written by Vince Fuller (Carnegie-Mellon University). ; RESOLV - Send a message to resolver, get a response, tell user ; Called with: ; T1/ Request code (UC_xxx value) ; T2/ Zero or pointer to QNAME ; MSG/ Address of paged IPCF buffer (set up by IPCINI) DEFINE PUNT(MESSAGE) < JRST [HRROI T1,[ASCIZ MESSAGE ] ESOUT% RET ]> PDBLEN==.IPCFC+1 RESOLV: STKVAR <,STAMP> STOR T1,QTYPE,+U.PHSIZ(MSG) ; Request code is QTYPE MOVX T1,QC.CTL ; This is a control message STOR T1,QCLASS,+U.PHSIZ(MSG) ; Save as QCLASS SKIPN T1,T2 ; Have a QNAME? IFSKP. ; Yes, parse it onto message page MOVX T2, MOVX T3,<*KCCBPW> MOVE T4,[ILDB T2,T1] CALL ATOD PUNT MOVX T1,U.PHSIZ+U.DHSIZ ; Page relative address of QNAME ELSE. SETZ T1, ; No QNAME ENDIF. STOR T1,QNAME,+U.PHSIZ(MSG) ; Store QNAME pointer SETZRO FLAGS,+U.PHSIZ(MSG) ; No flags SETZRO RCODE,+U.PHSIZ(MSG) ; No response code SETZRO RNAME,+U.PHSIZ(MSG) ; No canonicalized name SETZRO COUNT,+U.PHSIZ(MSG) ; No RRs in query message MOVX T1,USRVER ; Get user protocol version STOR T1,VERUSR,(MSG) ; send it so resolver can check MOVX T1,RFCVER ; Same for network protocol version STOR T1,VERRFC,(MSG) MOVX T1,US.QRY ; This is a query message STOR T1,STATE,(MSG) ; Tell resolver MOVEI T1,1 ; Set page count fields STOR T1,PAG.COUNT,(MSG) ; page_count STOR T1,PAG.THIS,(MSG) ; page_this TIME% ; Use system uptime and FORKX as STOR T1,STMP1,(MSG) ; check words to be sure resolver MOVEM T1,STAMP ; is answering the right query SKIPE T1,FORKX IFSKP. ; Don't have FORKX yet, try to get it MOVE T1,[SIXBIT 'FORKX'] SYSGT% ERJMP .+1 ; Ignore errors MOVEM T1,FORKX ; Save whatever we got for posterity ENDIF. STOR T1,STMP2,(MSG) MOVX T3,IP%CFV!IP%EPN ; Extended page SKIPN T4,MYPID ; Have a PID yet? TXO T3, ; Request PID creation on send MOVEM T4,.IPCFS+PDB ; Sending PID MOVEM T3,.IPCFL+PDB ; Set flags MOVE T1,RSVPID ; Get resolver PID MOVEM T1,.IPCFR+PDB MOVE T1,MSG ; Get message address LSH T1,-9 ; Make into a page number HRLI T1,1000 ; Size of paged message MOVEM T1,.IPCFP+PDB MOVEI T1,PDBLEN MOVEI T2,PDB ; Point at PDB here MSEND% ; Send message to resolver EJSRET ; Lost, punt SKIPE MYPID ; Had PID already? IFSKP. ; No, we just created one (maybe) MOVE T2,.IPCFS+PDB ; Get sender's PID from message we just sent MOVEM T2,MYPID ; Save it for posterity ENDIF. MOVE T1,MYPID ; Our PID again MOVEM T1,.IPCFR+PDB ; We're the receiver MOVX T1,IP%CFV!IP%EPN ; Extended page MOVEM T1,.IPCFL+PDB MOVE T1,MSG ; Get message address LSH T1,-9 ; Make into a page number HRLI T1,1000 ; Make a page pointer MOVEM T1,.IPCFP+PDB MOVEI T1,PDBLEN MOVEI T2,PDB MRECV% ; Receive a message EJSRET ; Lost, punt LOAD T1,VERUSR,(MSG) ; Make sure we are talking same version LOAD T2,VERRFC,(MSG) ; of the protocols as the resolver is. CAIN T1,USRVER CAIE T2,RFCVER PUNT LOAD T1,STATE,(MSG) ; Check what kind of message this is CAME T1,[US.RSP] ; Better be a response PUNT LOAD T1,PAG.COUNT,(MSG) ; For now we can only handle single LOAD T2,PAG.THIS,(MSG) ; page responses, so make sure that's CAIN T1,1 ; what this is CAIE T2,1 PUNT LOAD T1,STMP1,(MSG) ; Check to see if resolver is suffering LOAD T2,STMP2,(MSG) ; from a nervous breakdown and is sending CAMN T1,STAMP ; us somebody else's responses or is answering CAME T2,FORKX ; an old query of ours PUNT LOAD T1,RCODE,+U.PHSIZ(MSG) MOVSI T2,-ERRLEN ; Look for error/reply code in table DO. HLRZ T3,ERRTAB(T2) ; Get code CAME T3,T1 ; Match? AOBJN T2,TOP. ; Nope ENDDO. SKIPL T2 PUNT HRROI T1,[ASCIZ |Resolver replied "|] PSOUT% HRRO T1,ERRTAB(T2) ; Get message PSOUT% HRROI T1,[ASCIZ |" |] PSOUT% RET ; Done ENDSV. ; Close scope of STKVAR ; Resolver "user" protocol errors, see USRDEF.D for error codes. ; Macro to define an error entry DEFINE DEFERR(CODE,MESS) < XWD CODE,[ASCIZ CODE: MESS] > ERRTAB: ;Response error codes: DEFERR UE.OK, DEFERR UE.NAM, DEFERR UE.NRR, DEFERR UE.SYS, DEFERR UE.NIY, DEFERR UE.TMO, DEFERR UE.RBK, DEFERR UE.TMC, DEFERR UE.ACK, DEFERR UE.ARG, DEFERR UE.DNA, DEFERR UE.NOP, ERRLEN==.-ERRTAB SUBTTL I/O routines ; ATOD -- convert asciz string with dots to domain name format. ; ; Accepts: ; T2/ Destination byte pointer ; T3/ Size of destination buffer in bytes ; T4/ Instruction which will fetch a byte into T2 ; ; Returns: ; +1 on error ; T1/ Error code ; +2 on success ; T2/ Updated pointer ; T3/ Updated count ; T4/ Non-zero if string ended with "." ; ; Does not use T1, P, or Q registers, so fetch instruction can ; reference these. Saves T1 across fetch instruction that reads the ; null terminating the string, so T1 is the right place to put a byte ; pointer if you want it returned in ILDB format. ATOD: STKVAR MOVEM T2,OUTBP ; Save arguments MOVEM T3,CNT MOVEM T4,FETCH SETOM DOT ; Pretend last char was a dot to catch DO. ; bogus strings begining with a dot SOSG CNT ; Check for overflow RETBAD (GTDX9) ; Out of room, punt SETZ T3, ; Count of chars for this label IDPB T3,OUTBP ; Zero count byte and advance over it MOVE T4,OUTBP ; Get pointer to count byte MOVEM T4,SAVEBP ; Save till have something to put there DO. MOVEM T1,HOLDT1 ; Save T1 in case it's caller's source BP XCT FETCH ; Get a byte ERJMP URIOX ; Paranoia JUMPE T2,ENDLP. ; Exit loop if null or dot CAIN T2,"." EXIT. SETZM DOT ; Ok, saw a non-dot character CAIE T2,"\" ; Backslash quoting? IFSKP. ; Yup XCT FETCH ; Get next byte ERJMP URIOX CAIL T2,"0" ; Is it a digit? CAILE T2,"9" ANSKP. ; Yeah, sigh, \DDD character representation MOVEI T4,-"0"(T2) ; Three decimal digits, result is assumed IMULI T4,5+5 ; to be text, thank Ghu XCT FETCH ERJMP URIOX ADDI T4,-"0"(T2) IMULI T4,5+5 XCT FETCH ERJMP URIOX SUBI T2,-"0" ADD T2,T4 ENDIF. ; Done with "\" handling SOSG CNT ; Make sure there's room RETBAD (GTDX9) IDPB T2,OUTBP ; Write the byte AOJA T3,TOP. ; Next ENDDO. MOVE T4,SAVEBP ; Get pointer to count byte DPB T3,T4 ; Put in the count byte. JUMPE T2,ENDLP. ; Done if saw null byte CAIG T3,MAXLAB ; Was dot. Label too long? SKIPE DOT ; Or two dots in a row? RETBAD (GTDX1) ; Loser, punt SETOM DOT ; Remember that this is a dot LOOP. ; Next label ENDDO. ; End of string SOSG CNT ; Terminate with null label RETBAD (GTDX9) IDPB T2,OUTBP ; T2 already contained zero MOVE T1,HOLDT1 ; Get return values MOVE T2,OUTBP MOVE T3,CNT MOVE T4,DOT RETSKP ; Return success ENDSV. ; Close scope of STKVAR SUBTTL Support routines ; ERJMP handlers: ; URIOX, UWIOX -- User Read/Write I/O XCT error (T4 contains instruction) ; URMPV, UWMPV -- XCTU to/from user memory failed URIOX: CAME T4,[BIN%] ; Already have error code if JSYS URMPV: MOVEI T1,ILLX01 ; Else, bad memory operation RETBAD () ; Return error to caller. UWIOX: CAME T4,[BOUT%] ; Already have error code if JSYS UWMPV: MOVEI T1,ILLX02 ; Else, bad memory operation RETBAD () ; Return error to caller. SUBTTL IPCINI ; Initialize IPCF stuff IPCINI: HLRZ MSG,.JBSA## ; Get first free memory location TRZE MSG,777 ; Page aligned? ADDI MSG,1000 ; No, round up JRST SYSRSV ; Go get PID of system resolver SUBTTL End of program ...LIT: LIT ...VAR:!CMDSTG PDL: BLOCK PDLLEN FORKX: 0 END