; UPD ID= 2195, SNARK:<6.1.MONITOR>TCPCRC.MAC.5, 5-Jun-85 11:20:59 by MCCOLLUM ;TCO 6.1.1406 - Update copyright notice. ; UPD ID= 1041, SNARK:<6.1.MONITOR>TCPCRC.MAC.4, 12-Nov-84 15:26:43 by PAETZOLD ;TCO 6.1041 - Move ARPANET to XCDSEC ; UPD ID= 289, SNARK:TCPCRC.MAC.2, 24-Sep-84 13:55:39 by PURRETTA ;Update copyright notice. ; UPD ID= 3822, SNARK:<6.MONITOR>TCPCRC.MAC.3, 29-Feb-84 18:13:01 by PAETZOLD ;TCO 6.1733 - ANBSEC and MNTSEC removal. Bug Fixes. Cleanup. ;TCPCRC.MAC.4, 6-Dec-83 23:58:55, Edit by PAETZOLD ;TCPCRC.MAC.5, 5-Jul-83 08:29:52, Edit by PAETZOLD ;TCP Changes for 5.1 ;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED ;OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE. ; ;COPYRIGHT (C) DIGITAL EQUIPMENT CORPORATION 1976, 1985. ;ALL RIGHTS RESERVED. SEARCH ANAUNV,PROLOG TTITLE (TCPCRC,TCPCRC,< - Cyclic Redundancy Check Routines>) IFNDEF REL6, ;DEFAULT IS RELEASE 6 IFE REL6, ; THIS CODE IS SWAPPABLE IFN REL6, ; THIS CODE IS SWAPPABLE COMMENT ! These routines implement the checksumming function for the Internet header and for the TCP. Two versions are provided: a "one's complement sum" and a CRC. The runtime cell CRCF may be used to select CRC if it is set non-zero. The prototype CRC routines were supplied by Dave Reed at MIT-ML. N.B. ACs PTR, CNT, and SUM are used globally within this file. They are assigned from the local ACs area so the will be saved by called routines. They are preserved for callers. SUM must be T4+1 . These routines are highly dependent on the PACKET definitions in ANAUNV.MAC. ! %CRC==0 ; Set non-zero to assemble in the CRC code IFN %CRC, ; Set non-zero to use CRC IF1 < ; AC redefinitions: SUM=1+T4 ; Holds CRC or ordinary sum PTR=1+NTEMPS+NLOCLS-1 ; Holds byte pointer into packet during CRC CNT=1+NTEMPS+NLOCLS-2 ; Holds byte count during CRC NTEMPS==NTEMPS+1 ; Start assigning \ocals one higher due to SUM NLOCLS==NLOCLS-3 ; Reduce number of local ACs available > ; Macro to contruct a byte pointer to a structure field: DEFINE .POINT(STR,Y)< ..STR0(...PT,,STR,Y)> DEFINE ...PT(AC,LOC,MSK)< POINTR(LOC,MSK) > ; Symbol which is all ones in a right justified field which is the ; width of the checksum field CKSMSK==PICKS_-<^D35-POS(PICKS)> IFN WID(PTCKS)-WID(PICKS), IFN WID(CMCKS)-WID(PICKS), SUBTTL INTCKS - Compute Value for Internet Checksum Field ;PKT/ (Extended) Pointer to Internet Packet ; CALL INTCKS ;Ret+1: Always. ;T1 has the checksum for the Internet header INTCKS::SAVEAC ; Save ACs we will use as globals IFN %CRC,< SKIPN CRCF ; Use CRC or Old 1's comp? JRST INTADD ; Use additive function ; Compute CRC for Internet header INTCRC: MOVX SUM,-1B ; Init sum to all 1's MOVE PTR,[POINT 32,PKTELI(PKT)] ; Start at beginning of IN part LOAD CNT,PIDO,(PKT) ; Number of 32-bit words to do CALL CRC32 ; Process that many 32-bit bytes MOVE T1,SUM ; Get left-justified result LSH T1,-<^D36-WID(PICKS)>; Right justify it JRST INTCKX> ; END OF IFN %CRC ; 1's complement additive checksum calculation for Internet header INTADD: MOVEI SUM,0 ; Init the sum MOVE PTR,[POINT 32,PKTELI(PKT)] ; Point to IN hdr LOAD CNT,PIDO,(PKT) ; Number of 32-bit words to do CALL ADDSUM ; Add those in CALL FIXSUM ; Handle extra carries CAIE SUM,0 ; Avoid complementing a +0 XORI SUM,CKSMSK ; Return complement of the sum INTCKX: MOVE T1,SUM ; Return value RET SUBTTL ICMCKS - Compute Value for ICMP Checksum Field ;PKT/ (Extended) Pointer to Internet Packet ; CALL ICMCKS ;Ret+1: Always. ;T1 has the checksum for the ICMP packet ;Can be used to checksum the data protion of any internet packet. ICMCKS:: DATCKS::SAVEAC ; Save ACs we will use as globals IFN %CRC,< SKIPN CRCF ; Use CRC or Old 1's comp? JRST ICMADD ; Use additive function ; Compute CRC for ICMP packet ICMCRC: MOVX SUM,-1B ; Init sum to all 1's TCPCRC: MOVX SUM,-1B ; Init CRC to all one's MOVX PTR, ; Point to IP header LOAD T1,PIPL,(PKT) ; Get total length LOAD T2,PIDO,(PKT) ; Get data offset ADD PTR,T2 ; Locate ICMP header ASH T2,2 ; Convert to byte count SUB T1,T2 ; Get length of ICMP portion IDIVI T1,^D<36/8> ; Number of full words and extra bytes PUSH P,T2 ; Save number of bytes in partial word MOVSI PTR,( ; Skip over internet options SKIPN CNT,T1 CALL CRC32 TLC PTR,(^!) ; Back to 8-bit mode POP P,CNT ; Recover number of bytes in last word SKIPE CNT CALL CRC8 ; Do them MOVE T1,SUM ; Get left-justified result LSH T1,-<^D36-WID(PCCKS)>; Right justify it JRST ICMCKX> ;END OF IFN %CRC ; 1's complement additive checksum calculation for Internet header ICMADD: MOVEI SUM,0 ; Init the sum MOVE PTR,[POINT 32,PKTELI(PKT)] ; Pointer IP portion LOAD T1,PIPL,(PKT) ; Packet length in bytes LOAD T2,PIDO,(PKT) ; Internet data offset ADD PTR,T2 ; Point to ICMP portion ASH T2,2 ; Convert to bytes SUB T1,T2 ; Compute length of ICMP portion IDIVI T1,^D<36/8> ; Number of full words PUSH P,T2 ; Number of bytes in last word SKIPE CNT,T1 ; Set count of 32-bit words CALL ADDSUM ; Add in the data POP P,CNT ; Recover number of bytes at end TLC PTR,(^!) ; Back to 8-bit mode SKIPLE CNT ; Get out if none CALL ADD8 CALL FIXSUM ; Handle extra carries CAIE SUM,0 ; Avoid complementing a +0 XORI SUM,CKSMSK ; Return complement of the sum ICMCKX: MOVE T1,SUM ; Return value RET SUBTTL TCPCKS - Returns number for TCP checksum. ;PKT/ (Extended) pointer to packet ;TPKT/ (Extended) pointer to TCP portion of packet ; CALL TCPCKS ;Ret+1: Always. Number for TCP header checksum field in T1 TCPCKS::SAVEAC ; Save ACs which will be used globally IFN %CRC,< SKIPN CRCF ; Supposed to use CRC? JRST TCPADD ; No. 1's comp. TCPCRC: MOVX SUM,-1B ; Init CRC to all one's MOVX PTR,[<.POINT PIDST,(PKT)>-B5] ; Destination MOVEI CNT,2 ; and source CALL CRC32 ; Do those. MOVE PTR,[POINT 8,[0]] ; Pseudo header has a 0 byte next MOVEI CNT,1 CALL CRC8 ; Do it MOVX PTR,[<.POINT PIPRO,(PKT)>-B5]; Ptr to Protocol MOVEI CNT,1 ; One byte CALL CRC8 ; Do it. LOAD T1,PIPL,(PKT) ; Get total length PUSH P,T1 ; Save so it can be restored LOAD T2,PIDO,(PKT) ; Get data offset ASH T2,2 ; Convert to byte count SUB T1,T2 ; Get length of TCP portion STOR T1,PIPL,(PKT) ; Smash into packet for CRC calculation MOVX PTR,[<.POINT PIPL,(PKT)>-B5] ; Get ptr to it MOVEI CNT,1 ; Do one 16-bit byte CALL CRC16 ; TCP packet length POP P,T1 STOR T1,PIPL,(PKT) ; Restore the packet LOAD T2,PIDO,(PKT) ; Number of words in Internet part ASH T2,2 ; Number of bytes there SUB T1,T2 ; Number of bytes in TCP portion IDIVI T1,^D<36/8> ; Number of full words and extra bytes PUSH P,T2 ; Save number of bytes in partial word MOVSI PTR,( ; Skip over internet options SKIPN CNT,T1 CALL CRC32 MOVSI PTR,() ; Switch to 8-bits for tail POP P,CNT ; Recover number of bytes in last word SKIPE CNT CALL CRC8 ; Do them MOVE T1,SUM ; Get the result LSH T1,-<^D36-WID(PTCKS)>; Right-justify JRST TCPCKX> ;END OF IFN %CRC ; 1's complement function for TCP packet TCPADD: LOAD SUM,PISH,(PKT) ; Start with "pseudo header" LOAD T1,PIDH,(PKT) ; Source and destination hosts, and protocol ADD SUM,T1 ; Are constants and part of "addr info" LOAD T1,PIPRO,(PKT) ; Internet protocol (TCP, XNET, etc) ADD SUM,T1 LOAD T1,PIPL,(PKT) ; Packet length in bytes LOAD T2,PIDO,(PKT) ; Internet data offset ASH T2,2 ; Convert to bytes SUB T1,T2 ; Compute length of TCP portion ADD SUM,T1 ; Add in to checksum IDIVI T1,^D<36/8> ; Number of full words PUSH P,T2 ; Number of bytes in last word MOVE PTR,[POINT 32,0(TPKT)] ; Pointer to TCP portion SKIPE CNT,T1 ; Set count of 32-bit words CALL ADDSUM ; Add in the data POP P,CNT ; Recover number of bytes at end TLC PTR,(^!) ; Back to 8-bit mode SKIPLE CNT ; Get out if none CALL ADD8 CALL FIXSUM ; Fold into 16 bits CAIE SUM,0 ; Avoid complementing plus zero XORI SUM,CKSMSK ; Do one's complement TCPCKX: MOVE T1,SUM RET SUBTTL CRC One Byte Routines IFN %CRC,< ;CRC32 Add 32-bit bytes into the SUM. ;PKT/ (Extended) pointer to packet ;TPKT/ (Extended) pointer to TCP part of packet ;PTR/ Pointer into packet where to begin (may index by PKT or TPKT) ;CNT/ Number of 32-bit bytes to do ;SUM/ Current sum ; CALL CRC32 ;Ret+1: Always. PTR, CNT, SUM updated to reflect processing done. CRC32: ILDB T1,PTR ; Get next 32-bit byte LSH T1,^D<36-32> ; Left justify XOR T1,SUM ; Start CRCing SETZ SUM, LSHC T1,-^D<36-8> ; Get left most 8-bit byte XOR T2,CRCTAB(T1) LSHC T2,-^D<36-8> ; Get next 8-bit byte XOR T3,CRCTAB(T2) LSHC T3,-^D<36-8> XOR T4,CRCTAB(T3) LSHC T4,-^D<36-8> ; N.B. some bits go into SUM XOR SUM,CRCTAB(T4) SOJG CNT,CRC32 RET ;CRC24 Add one 24-bit byte into the SUM. ;PKT/ (Extended) pointer to packet ;TPKT/ (Extended) pointer to TCP part of packet ;PTR/ Pointer into packet where to begin (may index by PKT or TPKT) ;SUM/ Current sum ; CALL CRC24 ;Ret+1: Always. PTR, SUM updated to reflect processing done. CRC24: ILDB T2,PTR LSH T2,^D<36-24> XOR R2,SUM SETZ SUM, LSHC T2,-^D<36-8> XOR T3,CRCTAB(T2) LSHC T3,-^D<36-8> XOR T4,CRCTAB(T3) LSHC T4,-^D<36-8> ; N.B. some bits go into SUM XOR SUM,CRCTAB(T4) RET ;CRC16 Add 16-bit bytes into the SUM. ;PKT/ (Extended) pointer to packet ;TPKT/ (Extended) pointer to TCP part of packet ;PTR/ Pointer into packet where to begin (may index by PKT or TPKT) ;CNT/ Number of 16-bit bytes to do ;SUM/ Current sum ; CALL CRC16 ;Ret+1: Always. PTR, CNT, SUM updated to reflect processing done. CRC16: ILDB T3,PTR LSH T3,^D<36-16> XOR T3,SUM SETZ SUM, LSHC T3,-^D<36-8> XOR T4,CRCTAB(T3) LSHC T4,-^D<36-8> ; N.B. some bits go into SUM XOR SUM,CRCTAB(T4) SOJG CNT,CRC16 RET ;CRC8 Add 8-bit bytes into the SUM. ;PKT/ (Extended) pointer to packet ;TPKT/ (Extended) pointer to TCP part of packet ;PTR/ Pointer into packet where to begin (may index by PKT or TPKT) ;CNT/ Number of 8-bit bytes to do ;SUM/ Current sum ; CALL CRC8 ;Ret+1: Always. PTR, CNT, SUM updated to reflect processing done. CRC8: ILDB T4,PTR LSH T4,^D<36-8> XOR T4,SUM SETZ SUM, LSHC T4,-^D<36-8> ; N.B. some bits go into SUM XOR SUM,CRCTAB(T4) SOJG CNT,CRC8 RET SUBTTL CRC Calculation Tables ; Macros to build the table used in the CRC calculations DEFINE BLDTAB(COEFS)< $WORD==0 IRP COEFS,<$WORD==$WORD!1B<^D35-COEFS>> POLY==$WORD_^L<$WORD> ;; High order coefficient to sign bit CRCA==^D255 REPEAT ^D256,< CRCB==CRCA_^D24 REPEAT 8,< IFL CRCB, CRCB==CRCB_1> .NCONC (\CRCB) CRCA==CRCA-1>> DEFINE .TAB(X,Y) ; Init the table macro DEFINE .NCONC(Z)<.TAB()> ; Macro to add to the table BLDTAB(<16,15,2,0>) ; Build the table in .TAB ; for X**16+X**15+X**2+1 CRCTAB: .TAB ; Assemble the table >; end of IFN %CRC several pages back SUBTTL CRC Multiple Word Routines ;ADDSUM Adds N 32 or 16 bit bytes into the SUM ;PKT/ (Extended) pointer to packet ;TPKT/ (Extended) pointer to TCP part of packet ;PTR/ Pointer into packet where to begin (may index by PKT or TPKT) ;CNT/ Number of bytes to do ;SUM/ Current sum ; CALL ADDSUM ;Ret+1: Always. PTR, CNT, SUM updated to reflect processing done. ADDSUM: ILDB T1,PTR ; Get a byte ADD SUM,T1 ; Add it in SKIPGE SUM ; Too many carries? CALL FIXSUM ; Yes. Worry about that SOJG CNT,ADDSUM ; Loop over all RET ;ADD8 Adds in 8-bit bytes. ;PKT/ (Extended) pointer to packet ;TPKT/ (Extended) pointer to TCP part of packet ;PTR/ Pointer into packet where to begin (may index by PKT or TPKT) ;CNT/ Number of bytes to do ;SUM/ Current sum ; CALL ADDSUM ;Ret+1: Always. PTR, CNT, SUM updated to reflect processing done. ADD8: ILDB T1,PTR TLNE PTR,(1B2) ; See if left/right of 16 bit word LSH T1,8 ; Left half ADD SUM,T1 ; Add into sum SKIPGE SUM ; Too many carries? CALL FIXSUM ; Yes. Fold them into low bits SOJG CNT,ADD8 ; Do more RET ;FIXSUM Folds SUM so it fits in one 16-bit field ;SUM/ current checksum, computed using 32-bit arithmetic ; CALL FIXSUM ;Ret+1: Always. All carries added in (1's complement) to low 16 FIXSUM: TXNN SUM,<^-CKSMSK> ; Any bits outside the mask? RET ; No. We're done LDB T1,[POINTR SUM,<^-CKSMSK>] ; Get carries ANDX SUM,CKSMSK ; Remove them from sum ADD SUM,T1 ; Add in to low end JRST FIXSUM ; Must stop soon. TNXEND END