%( **************************************************************** Copyright (c) 1992, Carnegie Mellon University All Rights Reserved Permission is hereby granted to use, copy, modify, and distribute this software provided that the above copyright notice appears in all copies and that any distribution be for noncommercial purposes. Carnegie Mellon University disclaims all warranties with regard to this software. In no event shall Carnegie Mellon University be liable for any special, indirect, or consequential damages or any damages whatsoever resulting from loss of use, data, or profits arising out of or in connection with the use or performance of this software. **************************************************************** )% %Title 'TCP global Macro definitions' %( Module: TCPMACROS Facility: Provide some macros for convenient usage by the various modules in the TCP/IP network ACP. Author: Original author ? This version by Vince Fuller, CMU-CSD, Summer, 1986 Copyright (c) 1986,1987, Vince Fuller and Carnegie-Mellon University Change log: 6.7 7-Jan-1992 John Clement Rice Added LOG$FLUSH 6.6 17-Jul-1991 Henry W. Miller USBR Added debugging flags for name lookup and memory allocation. 6.4 24-Mar-88, Edit by VAF Enclose X..$FAO macros in BEGIN/END blocks to prevent weird IF/THEN block semantics. 6.3 20-Nov-87, Edit by VAF General cleanup. Create $KCALL macro to isolate all $CMKRNL calls to this macro package. Make logging macros, NOINT/OKINT, etc. check and declare necessary externals so modules don't have to. Add $ACPWAKE macro. Add LOG$IPERR - IP error logging. 6.2 10-Jun-87, Edit by VAF Flush hostname processing from ACP. Change GTHST and OPEN blocks to know about host name length. 6.1 18-Feb-87, Edit by VAF Conditional compilation of a bunch of stuff (logging, GREEN, etc.) Improvements to a bunch of the logging stuff. )% ! Define version-specific debugging flags. REQUIRE 'MACROSWI.REQ'; ! Compile switches COMPILETIME NO_CrLf = 1; ! For message macros FIELD VB$FIELDS = SET VB$LEN = [0,0,16,0], ! Varying string - current length VB$DAT = [0,16,8,0] ! First byte of data TES; MACRO REPEAT = DO%, ! Extend bliss for Repeat until lovers. ! Generate a pointer to a character string descriptor quadword. ASCII_C(S) = uplit(%CharCount(S),uplit(%ascii S))%, ! Generate a carriage-return Line-feed sequence for use in %string lex function. CrLf = %STRING(%Char(13),%Char(10))%, ! String descriptor handling macros VBUF(NCHR) = BLOCK[CH$ALLOCATION(NCHR+2)] FIELD(VB$FIELDS) %, DESC$VSTR = BLOCK[DESC$STR_LEN,BYTE] %, DESC$VSTR_ALLOC(NAME,MAXLEN) = %IF NOT %NULL(MAXLEN) %THEN %NAME(NAME,'_BUF') : VBUF(MAXLEN) PRESET([VB$LEN] = 0), %FI NAME : DESC$VSTR %IF NOT %NULL(MAXLEN) %THEN PRESET([DSC$B_CLASS] = DSC$K_CLASS_VS, [DSC$B_DTYPE] = DSC$K_DTYPE_VT, [DSC$W_MAXSTRLEN] = MAXLEN, [DSC$A_POINTER] = %NAME(NAME,'_BUF')) %FI %, DESC$STR_INIT(DESC,STRLEN,STRPTR) = BEGIN DESC[DSC$B_CLASS] = DSC$K_CLASS_Z; DESC[DSC$B_DTYPE] = DSC$K_DTYPE_Z; DESC[DSC$W_LENGTH] = CH$ALLOCATION(STRLEN); DESC[DSC$A_POINTER] = STRPTR; END %, DESC$VSTR_INIT(DESC,MAXLEN,STRPTR) = BEGIN DESC[DSC$B_CLASS] = DSC$K_CLASS_VS; DESC[DSC$B_DTYPE] = DSC$K_DTYPE_VT; DESC[DSC$W_MAXSTRLEN] = MAXLEN; DESC[DSC$A_POINTER] = STRPTR; END %, ! Handle string descriptor. ! If argument is a quoted string, return created descriptor ! else, just return the argument. $$STR(ARG) = %IF %ISSTRING(ARG) %THEN %ASCID ARG %ELSE ARG %FI %, ! Declare something external if it isn't already declared $QEXT(NAME,MODIF) = %IF NOT %DECLARED(NAME) %THEN EXTERNAL NAME %IF NOT %NULL(MODIF) %THEN : MODIF %FI; %FI %, $QEXTR(NAME,MODIF) = %IF NOT %DECLARED(NAME) %THEN EXTERNAL ROUTINE NAME %IF NOT %NULL(MODIF) %THEN : MODIF %FI; %FI %, ! Write a message to the console operator OPR$FAO(CST) = BEGIN $QEXTR(OPR_FAO,NOVALUE) %IF %NULL(%REMAINING) %THEN OPR_FAO(%ASCID %STRING(CST)); %ELSE OPR_FAO(%ASCID %STRING(CST),%REMAINING); %FI END %, ERROR$FAO(CST) = BEGIN $QEXTR(ERROR_FAO,NOVALUE) %IF %NULL(%REMAINING) %THEN ERROR_FAO(%ASCID %STRING(CST)); %ELSE ERROR_FAO(%ASCID %STRING(CST),%REMAINING); %FI END %, WARN$FAO(CST) = BEGIN $QEXTR(ERROR_FAO,NOVALUE) %IF %NULL(%REMAINING) %THEN ERROR_FAO(%ASCID %STRING(CST)); %ELSE ERROR_FAO(%ASCID %STRING(CST),%REMAINING); %FI END %, FATAL$FAO(CST) = BEGIN $QEXTR(FATAL_FAO,NOVALUE) %IF %NULL(%REMAINING) %THEN FATAL_FAO(%ASCID %STRING(CST)); %ELSE FATAL_FAO(%ASCID %STRING(CST),%REMAINING); %FI END %, ! Obsolete error processing macros - special cases of above. Fatal_Error(S,ERRCODE) = %IF %NULL(ERRCODE) %THEN FATAL$FAO(S) %ELSE FATAL$FAO(%STRING(S,', EC = !XL'),ERRCODE) %FI %, Warn_Error(S,RETVALUE) = %IF %NULL(RETVALUE) %THEN WARN$FAO(S) %ELSE WARN$FAO(%STRING(S,', EC = !XL'),RETVALUE) %FI %, ! Control segment Send macros SEND_SYN$ACK(TCB) = TCP$Send_CTL(Tcb,M$SYN_ACK)%, SEND_SYN(TCB) = TCP$SEND_CTL(TCB,M$SYN)%, SEND_FIN(TCB) = TCP$SEND_CTL(TCB,M$FIN)%, SEND_RST(TCB) = TCP$SEND_CTL(TCB,M$RST)%, ! Queue management macros. Queue_Empty(Queue$Head) = .Queue$Head EQLA Queue$Head%, Queue_NOT_Empty(Queue$Head) = .Queue$Head NEQA Queue$Head%, ! Enable/Disable AST Delivery. ! If AST_IN_Progress then don't bother with AST blocking as AST will block ! delivery of other AST as same access mode. Disable_AST = $SETAST(ENBFLG=0)%, Enable_AST = $SETAST(ENBFLG=1)%, ! Enable/disable interrupts (AST's). These are the macros that should ! really be used, since they restore the AST state to its previous value ! correctly. NOINT = BEGIN $QEXT(AST_IN_PROGRESS) $QEXT(INTDF) IF (NOT .AST_IN_PROGRESS) AND ((INTDF = .INTDF+1) EQL 0) THEN DISABLE_AST END %, OKINT = BEGIN $QEXT(AST_IN_PROGRESS) $QEXT(INTDF) IF (NOT .AST_IN_PROGRESS) AND ((INTDF = .INTDF-1) LSS 0) THEN ENABLE_AST END %, ! Wake sleeping ACP from $HIBER call. This is used when an AST routine wants ! the mainline ACP code to do something at non-AST level. $ACPWAKE = BEGIN $QEXT(SLEEPING) IF .SLEEPING THEN BEGIN SLEEPING = FALSE; $WAKE(); END END %, ! Macros to do word and longword byte swapping. SWAPWORD(ADDR) = BEGIN BIND XX = ADDR : VECTOR[2,BYTE]; REGISTER YY; YY = .XX[0]; XX[0] = .XX[1]; XX[1] = .YY; END %, SWAPLONG(ADDR) = BEGIN REGISTER TEMP; TEMP = .ADDR<0,16>; ! Word swap of TTL ADDR<0,16> = .ADDR<16,16>; ADDR<16,16> = .TEMP; END %, ! Macro to set $CMKRNL argument list $$KARGS(ANAME)[NAME] = ANAME[%COUNT+1] = NAME; %, ! Macro to setup and call routine via $CMKRNL. $$KCALL(RTN)[] = %IF %LENGTH EQL 1 %THEN $CMKRNL(ROUTIN=RTN) %ELSE BEGIN LOCAL CMKARG : VECTOR[%LENGTH]; CMKARG[0] = %LENGTH-1; $$KARGS(CMKARG,%REMAINING) $CMKRNL(ROUTIN=RTN,ARGLST=CMKARG); END %FI %, %IF LOGSWITCH %THEN ! Want the logging macros ! Conditionally do something according to LOG_STATE flags $$LOGF(LOGF) = BEGIN $QEXT(LOG_STATE) ((.LOG_STATE AND (LOGF)) NEQ 0) END %, ! Macros for output to log and opr and the activity log. LOG$OUT(XSTR) = LOG_OUTPUT(%ASCID %STRING(XSTR)) %, XLOG$OUT(LOGF) = BEGIN IF $$LOGF(LOGF) THEN LOG$OUT(%REMAINING) END %, LOG$FAO(CST) = BEGIN %IF NOT %DECLARED(LOG_FAO) %THEN EXTERNAL ROUTINE LOG_FAO : NOVALUE; %FI %IF %NULL(%REMAINING) %THEN LOG_FAO(%ASCID %STRING(CST)) %ELSE LOG_FAO(%ASCID %STRING(CST),%REMAINING) %FI END %, XLOG$FAO(LOGF) = BEGIN IF $$LOGF(LOGF) THEN LOG$FAO(%REMAINING) END %, ACT$OUT(XSTR) = LOG_OUTPUT(%ASCID %STRING(XSTR)) %, ACT$FAO(CST) = BEGIN %IF NOT %DECLARED(ACT_FAO) %THEN EXTERNAL ROUTINE ACT_FAO : NOVALUE; %FI %IF %NULL(%REMAINING) %THEN ACT_FAO(%ASCID %STRING(CST)) %ELSE ACT_FAO(%ASCID %STRING(CST),%REMAINING) %FI END %, QL$FAO(CST) = BEGIN %IF NOT %DECLARED(QL_FAO) %THEN EXTERNAL ROUTINE QL_FAO : NOVALUE; %FI %IF %NULL(%REMAINING) %THEN QL_FAO(%ASCID %STRING(CST)); %ELSE QL_FAO(%ASCID %STRING(CST),%REMAINING); %FI END %, XQL$FAO(LOGF) = BEGIN IF $$LOGF(LOGF) THEN QL$FAO(%REMAINING) END %; %ELSE ! Don't want logging macros - make them null $$LOGF(LOGF) = 0 %, ! $$LOGF always fails LOG$OUT(XSTR) = 0 %, ! LOG$OUT does nothing XLOG$OUT(LOGF) = 0 %, ! XLOG$OUT " LOG$FAO(CST) = 0 %, ! LOG$FAO " ACT$OUT(XSTR) = 0 %, ! ACT$OUT does nothing ACT$FAO(CST) = 0 %, ! ACT$FAO " XLOG$FAO(LOGF) = 0 %, ! XLOG$FAO " QL$FAO(CST) = 0 %, ! QL$FAO " XQL$FAO(LOGF) = 0 %; ! XQL$FAO " %FI ! Network logger flag bits - determine what events to log LITERAL LOG$PHY = %X'01', ! Packet physical headers LOG$ARP = %X'02', ! ARP packet info LOG$IP = %X'04', ! IP packet headers LOG$TCP = %X'08', ! TCP segment info (packet trace) LOG$TCBDUMP = %X'10', ! TCB dump on servicing LOG$USER = %X'20', ! User I/O requests LOG$TCBSTATE= %X'40', ! TCB state changes LOG$TCBCHECK= %X'80', ! TCB servicing timing LOG$TCPERR = %X'100', ! TCP errors (dropped pkts, etc.) LOG$ICMP = %X'200', ! ICMP activity LOG$UDP = %X'400', ! UDP activity LOG$TVT = %X'800', ! TVT (virtual terminal) activity LOG$IPERR = %X'1000', ! IP errors (bad routing, etc.) LOG$DEBUG = %X'2000', ! Temporary statements LOG$MEM = %X'4000', ! Memory Allocation LOG$MSG = %X'8000', ! Name Lookup LOG$Telnet = %x'10000', ! Log Telnet activity LOG$TelNeg = %x'20000', ! Log Telnet negotiations LOG$TelERR = %x'40000', ! Log Telnet errors LOG$Snoop = %x'80000', ! SNOOP activity LOG$Flush = %x'100000'; ! Dump each line ! Define QBLK/Input segment queue flags. LITERAL Q$XERCV = 1, ! XEDRV receive buffer queue Q$SEGIN = 2, ! AST segment input queue Q$TCBNR = 4, ! TCB net receive queue Q$TCBFQ = 8, ! TCB future queue Q$USRCV = 16; ! User receive queue ! Conditional coding for debugging %IF QDEBUG %THEN MACRO XQDEFINE = EXTERNAL ROUTINE MEM_INSQUE, MEM_REMQUE; %, XINSQUE(QH,QB,QRTN,QID,QVAL) = MEM_INSQUE(QH,QB,QRTN,QID,QVAL) %, XREMQUE(QH,QB,QRTN,QID,QVAL) = MEM_REMQUE(QH,QB,QRTN,QID,QVAL) %; %ELSE MACRO XQDEFINE = %, XINSQUE(QH,QB,QRTN,QID,QVAL) = INSQUE(QH,QB) %, XREMQUE(QH,QB,QRTN,QID,QVAL) = REMQUE(QH,QB) %; %FI