Metropoli BBS
VIEWER: ipasm.asm MODE: TEXT (ASCII)
;
;  TCP/IP support routines
;****************************************************************************
;*                                                                          *
;*                                                                          *
;*      part of NCSA Telnet                                                 *
;*      by Tim Krauskopf, VT100 by Gaige Paulsen, Tek by Aaron Contorer     *
;*                                                                          *
;*      National Center for Supercomputing Applications                     *
;*      152 Computing Applications Building                                 *
;*      605 E. Springfield Ave.                                             *
;*      Champaign, IL  61820                                                *
;*                                                                          *
;****************************************************************************
;
	NAME	IPASM
;Microsoft EQU 1
;Lattice EQU 1
ifndef Microsoft
    ifndef Lattice
        if2
            %out
            %out ERROR: You have to specify "/DMicrosoft" or "/DLattice" on the
            %out        MASM command line to determine the type of assembly.
            %out
        endif
        end
    endif
endif

;******************************************************************
;*
;*	We need to set up a stack for netsleep when we exit to DOS.
;NEWSTACK SEGMENT PARA STACK 'STACK'
;    dw 2048 dup(?)
;STACKEND label far
;NEWSTACK    ends

 X   EQU     6
ifdef Microsoft
.MODEL  LARGE
.DATA
else	
	INCLUDE	DOS.MAC
	SETX
	DSEG
endif

OLDSS dw 1 dup(?)
OLDSP dw 1 dup(?)

ifndef NET14
NEWSTACK dw 2048 dup(?)     ; define a stack for netsleep when we shell to DOS
STACKEND label word
endif

ifdef Microsoft
;_DATA ends
;
;_TEXT	segment public 'CODE'
;	assume CS:_TEXT
.CODE
    PUBLIC  _IPCHECK, _TCPCHECK, _MOVEBYTES, _LONGSWAP, _INTSWAP
    PUBLIC  _COMPAREN
;ifdef Watcom
    PUBLIC  __STK
;endif
;   PUBLIC  _DBG

;was above tinst

ifndef NET14
ifdef Microsoft
;ifdef Watcom
;    EXTRN   netsleep_:FAR   ; C routine which gets called from handler
;else
    EXTRN   _netsleep:FAR   ; C routine which gets called from handler
;endif
	PUBLIC	_TINST,_TDEINST
else	
        EXTRN   netsleep:FAR    ; C routine which gets called from handler
	PUBLIC	TINST,TDEINST
endif
endif ;Net14


else
	ENDDS
	PSEG
    PUBLIC  IPCHECK,TCPCHECK,MOVEBYTES,LONGSWAP,INTSWAP
    PUBLIC  COMPAREN
;   PUBLIC  DBG
endif	
;
;  Routines for general use by the communications programs
;
;
ifdef NOT_USED
;************************************************************************
;  DBG
;  provides a synch point for debugging
;
ifdef Microsoft
_dbg 	proc	far
else
dbg	proc	far
endif
	nop
	nop
	nop
	ret
ifdef Microsoft
_dbg endp
else
dbg endp
endif
endif           ; NOT_USED
;
;*************************************************************************
;  Internet header checksum
;    header checksum is calculated for a higher level program to verify
;
;  USAGE:  ipcheck((IPKT *)ptr,(int)len)
;
;  this proc knows that the IP header length is found in the first byte
;
ifdef Microsoft
_IPCHECK	PROC	FAR
else
IPCHECK	PROC	FAR
endif
	PUSH	BP
	MOV		BP,SP
	PUSH	DS
;    PUSH    ES
	PUSH	SI
;    PUSH    DI

ifdef OLD_WAY
	MOV		AX,[BP+X+2]		; ds for input data
	MOV		DS,AX
	MOV		SI,[BP+X]		; pointer to data
else
    LDS     SI,[BP+X]       ; Get the pointer to the data
endif
    MOV     CX,[BP+X+4]     ; count of words to test
	XOR		BX,BX
	CLC
CHKSUM:
	LODSW					; get next word
	ADC		BX,AX			; keep adding
	LOOP	CHKSUM			; til' done
	ADC		BX,0			; adds the carry bit in
;
	NOT		BX				; take one more 1-complement
	MOV		AX,BX

;    POP     DI
	POP		SI
;    POP     ES
	POP		DS
	POP		BP
	RET
ifdef Microsoft
_IPCHECK	ENDP
else
IPCHECK	ENDP
endif
;
;  TCP checksum, has two parts, including support for a pseudo-header
;
;  usage:   tcpcheck(psptr,tcpptr,tcplen)
;            char *psptr,*tcpptr;  pointers to pseudo header and real header
;            int tcplen            length of tcp packet in checksum
;
ifdef Microsoft
_TCPCHECK	PROC	FAR
else
TCPCHECK	PROC	FAR
endif
	PUSH	BP
	MOV		BP,SP
	PUSH	DS
;    PUSH    ES
	PUSH	SI
;    PUSH    DI

ifdef OLD_WAY
	MOV		AX,[BP+X+2]		; ds for input data for pseudo-hdr
	MOV		DS,AX
	MOV		SI,[BP+X]		; pointer to data
    MOV     CX,6            ; length of p-hdr in words
	XOR		BX,BX           ; clear to begin
	CLC
PCHKSUM:
	LODSW					; get next word
	ADC		BX,AX			; keep adding
	LOOP	PCHKSUM			; til' done
	ADC		BX,0			; adds the carry bit in
else
    LDS     SI,[BP+X]       ; Get the pointer to the data
;    MOV     CX,6            ; length of p-hdr in words
	XOR		BX,BX           ; clear to begin
	CLC
;PCHKSUM:
; Un-roll the loop for faster execution.
	LODSW					; get next word
	ADC		BX,AX			; keep adding
    LODSW                   ; get next word
	ADC		BX,AX			; keep adding
    LODSW                   ; get next word
	ADC		BX,AX			; keep adding
    LODSW                   ; get next word
	ADC		BX,AX			; keep adding
    LODSW                   ; get next word
	ADC		BX,AX			; keep adding
    LODSW                   ; get next word
	ADC		BX,AX			; keep adding
;    LOOP    PCHKSUM         ; til' done
	ADC		BX,0			; adds the carry bit in
endif
;
; NOW THE REAL THING
;
ifdef OLD_WAY
	MOV		AX,[BP+X+6]		; ds of real stuff
	MOV		DS,AX
	MOV		SI,[BP+X+4]		; pointer
else
    LDS     SI,[BP+X+4]     ; Get the pointer to the real stuff
endif
	MOV		CX,[BP+X+8]		; count of bytes to test
	MOV		DX,CX			; keep a copy
	SHR		CX,1			; divide by two, round down
	CLC
RCHKSUM:
	LODSW
	ADC		BX,AX			; add to previous running sum
	LOOP	RCHKSUM	
	ADC		BX,0			; add the last carry in again
	AND		DX,1			; odd # of bytes?
	JZ		NOTODD
	LODSB					; get that last byte
	XOR		AH,AH			; clear the high portion
	ADD		BX,AX			; add the last one in
	ADC		BX,0			; add the carry in, too
NOTODD:
	NOT		BX				; take one more 1-complement
	MOV		AX,BX

;    POP     DI
	POP		SI
;    POP     ES
	POP		DS
	POP		BP
	RET
ifdef Microsoft	
_TCPCHECK	ENDP
else
TCPCHECK	ENDP
endif

;
;********************************************************************
;  New movebytes
;  Move an arbitrary number of bytes from one location to another.
;
;  Usage:
;  movebytes(to,from,count)
;   char *to,*from;
;   int16 count
;   moves < 64K from one 4 byte pointer to another.  Does not handle
;   overlap, but does copy quickly.
;
ifdef Microsoft
_MOVEBYTES	PROC	FAR
else
MOVEBYTES	PROC	FAR
endif
        PUSH    BP
	MOV		BP,SP
	PUSH	DS
	PUSH	ES
	PUSH	SI
	PUSH	DI

	LES		DI,[BP+X]			; WHERE TO PUT IT
	LDS		SI,[BP+X+4]			; WHERE TO GET IT
	MOV		CX,[BP+X+8]			; HOW MANY TO MOVE
	SHR 	CX,1				; MAKE INTO A WORD COUNT
	REP 	MOVSW
	ADC		CX,CX				; GET THE ODD BYTE COUNT BACK
	REP 	MOVSB
	POP		DI
	POP		SI
	POP		ES
	POP		DS
	POP		BP
	RET
ifdef Microsoft
_MOVEBYTES	ENDP
else
MOVEBYTES	ENDP
endif

;
;********************************************************************
;  New comparen
;  Take n bytes and return identical (true, not zero) or not identical (false=0)
;
;  Usage:
;  comparen(s1,s2,count)
;   char *s1,*s2;
;   int16 count
;
ifdef Microsoft
_COMPAREN  PROC    FAR
else
COMPAREN   PROC    FAR
endif
	PUSH	BP
	MOV		BP,SP
	PUSH	DS
	PUSH	ES
	PUSH	SI
	PUSH	DI

    LES     DI,[BP+X]           ; First string
    LDS     SI,[BP+X+4]         ; Second string
    MOV     CX,[BP+X+8]         ; How many to compare
    REPE    CMPSB               ; Compare the strings
    LAHF                        ; Get the flags
    AND     AX,4000h            ; Mask all the flags except the zero flag

	POP		DI
	POP		SI
	POP		ES
	POP		DS
	POP		BP
	RET
ifdef Microsoft
_COMPAREN   ENDP
else
COMPAREN    ENDP
endif

;
;*************************************************************************
;  longswap
;    swap the bytes of a long integer from PC
;  order (reverse) to in-order.  This will work both ways.
;  returns the new long value
;  usage:
;      l2 = longswap(l)
;	long l;
;
ifdef Microsoft
_LONGSWAP	PROC	FAR
	PUSH	BP
	MOV		BP,SP

	MOV		AX,[BP+X+2]		; HIGH BYTES OF THE LONG INT
	MOV		DX,[BP+X]		; LOW BYTES OF THE LONG INT
;
;  GET THE DATA
;
	XCHG	AH,AL			; SWAP THEM, THESE ARE NOW LOW
	XCHG	DH,DL			; SWAP THE OTHERS
	POP		BP
	RET
_LONGSWAP	ENDP
else
LONGSWAP	PROC	FAR
	PUSH	BP
	MOV		BP,SP
	MOV		BX,[BP+X+2]		; HIGH BYTES OF THE LONG INT
	MOV		AX,[BP+X]		; LOW BYTES OF THE LONG INT
;
;  GET THE DATA
;
	XCHG	AH,AL			; SWAP THEM, THESE ARE NOW LOW
	XCHG	BH,BL			; SWAP THE OTHERS
	POP		BP
	RET
LONGSWAP	ENDP
endif
;
;*************************************************************************
;  INTSWAP
;    swap the bytes of an integer, returns the swapped integer
;
;   usage:      i = intswap(i);
;
ifdef Microsoft
_INTSWAP	PROC	FAR
else
INTSWAP	PROC	FAR
endif
	MOV		BX,SP
	MOV 	AX,SS:[BX+4]
	XCHG	AH,AL
	RET
ifdef Microsoft
_INTSWAP	ENDP
else
INTSWAP	ENDP
endif

ifndef NET14
;
;**************************************************************************
;
;  Routines to install and deinstall a timer routine which calls
;  netsleep(0);
;  The timer is set to go off every 1/2 second to check for packets 
;  in the incoming packet buffer.  We use the user-hook into the system 
;  timer which occurs every 1/18th of a second.
;
;
TIMEINT     EQU 4*1CH       ; User hook to timer int

;*************************************************************************
;
;  Take out the timer interrupt handler, restore previous value
;
ifdef Microsoft
_TDEINST	PROC	FAR
else
TDEINST	PROC	FAR
endif
	MOV		CX,CS:TIP		; GET OLD IP FROM SAVE SPOT
	MOV		DX,CS:TCS		; GET OLD CS FROM SAVE SPOT
	MOV		BX,TIMEINT		; INTERRUPT IN TABLE FOR TIMER
	PUSH	DS
	XOR		AX,AX			; SYSTEM INTERRUPT TABLE
	MOV		DS,AX		
	CLI
	MOV		[BX],CX			; STORE OLD IP INTO THE TABLE
	INC		BX
	INC		BX				; MOVE POINTER IN INTERRUPT TABLE
	MOV		[BX],DX			; STORE OLD CS INTO THE TABLE
	STI
	POP		DS
	RET
ifdef Microsoft
_TDEINST	ENDP
else
TDEINST	ENDP
endif
;
;
;  install the timer interrupt handler, the handler is technically
;  part of this procedure.
;
ifdef Microsoft
_TINST	PROC	FAR
else
TINST	PROC	FAR
endif
    XOR     AX,AX
    MOV     CS:TENTER,AL    ; CLEAR THIS FLAG
	MOV		CS:TMYDS,DS		; STORE FOR USE BY HANDLER
	MOV		BX,TIMEINT		; INTERRUPT IN TABLE FOR TIMER (1c)
	PUSH	DS
	XOR		AX,AX			; SYSTEM INTERRUPT TABLE
	MOV		DS,AX		
	MOV		AX,OFFSET THAND	; WHERE THE HANDLER IS
	CLI
	MOV		DX,[BX]			; KEEP COPY OF THE IP
	MOV		[BX],AX			; STORE IP INTO THE TABLE
	INC		BX
	INC		BX				; MOVE POINTER IN INTERRUPT TABLE
	MOV		CX,[BX]			; KEEP COPY OF THE CS, TOO
	MOV		AX,CS
	MOV		[BX],AX			; STORE NEW CS INTO THE TABLE
	STI
	POP	DS
	MOV	CS:TIP,DX			; STORE THEM AWAY
	MOV	CS:TCS,CX
	RET
;
;  Code segment addressable data for keeping track of the interrupt handler
;  stuff
;
TMYDS		DW	00H			; THE DATA SEGMENT FOR THIS ASSEMBLY CODE
TICNT       DB  00          ; COUNTER OF 1/18THS SEC
TENTER      DB  00
TIP  		DW  00
TCS  		DW  00

;
;   The handler itself.
;
THAND:                      ; not a public name, only handles ints
    STI
    PUSH    DS
	PUSH 	ES
	PUSH	AX
	PUSH	BX
	PUSH	CX
	PUSH	DX
	PUSH	DI
	PUSH	SI

    CLD                     ; ALL MOVES WILL BE FORWARD
    MOV     AL,CS:TENTER
    OR      AL,AL
    JNZ     TIME2
	MOV		AL,1
    MOV     CS:TENTER,AL    ; SET FLAG TO INDICATE BUSY
	INC		CS:TICNT
    MOV     AL,CS:TICNT     ; COUNTER FOR US
    AND     AL,7            ; SEE IF # MOD 8 = 0
    JNZ     TSKIP           ; SKIP 7 OUT OF 8 TIMES

;    MOV     AL,60H          ; EOI FOR TIMER INT
;    OUT     20H,AL          ; LET LOWER INTERRUPTS IN

;  SET UP CORRECT DS
    MOV     DS,CS:TMYDS     ; GET CORRECT DS

;  do we have to set up our own stack here?
ifdef HellWhyNot
    CLI
    MOV     AX,SS
	MOV		OLDSS,AX
    MOV     OLDSP,SP
;    MOV     AX,seg NEWSTACK
    MOV     AX,seg STACKEND
	MOV		SS,AX
    MOV     SP,OFFSET DGROUP:STACKEND
    STI
endif   ;HellWhyNot
    XOR     AX,AX
	PUSH 	AX

ifdef Microsoft
    CALL _netsleep
else
    CALL netsleep
endif

    POP     AX
ifdef HellWhyNot
    CLI
    MOV     AX,OLDSS
	MOV		SS,AX
    MOV     SP,OLDSP
    STI
endif

TSKIP:
	XOR		AL,AL
	MOV		CS:TENTER,AL	; REENTER FLAG, DONE NOW
TIME2:
    POP     SI
	POP		DI
	POP		DX
	POP		CX
	POP		BX
	POP		AX
	POP		ES
	POP		DS

; Pass through to other routines
	JMP 	DWORD PTR CS:TIP

ifdef Microsoft
_TINST		ENDP
else
TINST		ENDP
endif

endif       ; NET14

;************************************************************************
;  __STK
;  Routine stub to avoid stack overflow errors in Watcom
;
;ifdef Watcom
__STK    proc    far
	ret
__STK endp
;endif

ifdef Microsoft
;_TEXT ends
else
	ENDPS
endif
	END
[ RETURN TO DIRECTORY ]