Category : Network Files
Archive   : PDCLK145.ZIP
Filename : ARP.ASM

 
Output of file : ARP.ASM contained in archive : PDCLK145.ZIP
; arp.asm
;========================================================================

; Copyright (C) 1991 by [email protected], see file COPYING.

ArpStruc struc
iArpHtype dw 0 ; 0001 = Ether
iArpProt dw 0008h ; 0800 = IP
iArpHlen db 0 ; Hw addr length
iArpPlen db 4 ; IP addr length
iArpOp dw 0100h ; 0001 = request
iArpMyHwAd db 2*16+2*4 dup (0)
ArpBodyLen = $-iArpHtype
ArpStruc ends

ArpBegLen equ iArpMyHwAd+8-iArpHtype

ArpHandle dw 0

ifndef ARPSLOTS
ARPSLOTS equ 12
endif

; The arp table contains information on hosts on this net.
; Slot 0, 1 and 2 (index 0, 2 and 4) are static and contain:
; this net broadcast, this subnet broadcast and my address, respectively.
;
; If we don't RECEIVE packets for more than a minute from a host or gateway,
; its slot is cleared. If we then DO receive a packet, the slot is restored
; by VerifyIpHdr without sending an ARP. On the other hand, if WE want to
; send the next packet, we will do an ARP and can thus detect dead hosts

; or gateways.
even
ArpTabIp2 dw ARPSLOTS dup (0ffffh) ; IP # (last part)
ArpTabIp1 dw ARPSLOTS dup (0ffffh) ; IP # (first part)
ArpTabTr dw ARPSLOTS dup (0) ; timer
ArpTabFlags dw ARPSLOTS dup (0) ; flags
ArpTabTrSq dw ARPSLOTS dup (0) ; source quench timer
ArpTabSqDelay dw ARPSLOTS dup (0) ; source quench delay
ArpTabHwAdr db ARPSLOTS*16 dup (0ffh) ; hardware addr (max 16 bytes)
ArpTabHw3 dw ARPSLOTS dup (0ffffh) ; hw addr for reverse lookup
ArpTabHw2 dw ARPSLOTS dup (0ffffh) ; hw addr for reverse lookup
ArpTabHw1 dw ARPSLOTS dup (0ffffh) ; hw addr for reverse lookup
USE_SNAP equ 1 ; bit in ArpTabFlags
SQ_UPDATED equ 2 ; bit in ArptabFlags/RouteTabFl

ARPMYIDX equ 4
ArpPutSlot dw ARPMYIDX

ArpType dw 0608h
ArpBuf ArpStruc <>

ArpFixedLen equ $-ArpType
aArpOffsSrcIp equ iArpMyHwAd+2-iArpHtype ; *test*
MyHwAd equ ArpBuf.iArpMyHwAd
ProtType equ ArpBuf.iArpProt
ArpFixedPart equ ArpType

if DEBUG
DbgIntCnt db 1
endif ; DEBUG

;************************************************************************
;* ArpFindIp
;*
;* Input: DX = first word of IP # (saved)
;* AX = second word of IP # (saved)
;* A PushfDI must be done before calling
;* Output: if found: zero and DI = arp table index
;* Destroys: CX, DI, ES, flags
;************************************************************************

ArpFindIp proc near
mov di,offset ArpTabIp2
mov cx,ARPSLOTS
ArpFindIpNext: ; look for matching slot
repne scasw
jnz ArpFindIpRet

cmp dx,2*ARPSLOTS-2[di] ; does IP # first part match?
jne ArpFindIpNext ; - no, look further

sub di,offset ArpTabIp2+2 ; - yes, compute slot index
cmp di,di ; set zero flag
ArpFindIpRet:
ret
ArpFindIp endp



;************************************************************************
;* ArpFindHw
;*
;* Input: SI = first word of HW addr (saved)
;* DX = second word of HW addr (saved)
;* AX = third word of HW addr (saved)
;* A PushfDI must be done before calling
;* Output: if found: zero and DI = arp table index
;* Destroys: CX, DI, ES, flags
;************************************************************************

ArpFindHw proc near
mov di,offset ArpTabHw3
mov cx,ARPSLOTS
ArpFindHwNext: ; look for matching slot
repne scasw
jnz ArpFindHwRet

cmp dx,2*ARPSLOTS-2[di] ; does HW second part match?
jne ArpFindHwNext ; - no, look further

cmp si,4*ARPSLOTS-2[di] ; does HW first part match?
jne ArpFindHwNext ; - no, look further

sub di,offset ArpTabHw3+2 ; - yes, compute slot index
cmp di,di ; set zero flag
ArpFindHwRet:
ret ; zero (found) return
ArpFindHw endp



;************************************************************************
;* ArpPutHwAd
;*
;* Input: SI = pointer to physical address (saved)
;* DI = arp table index
;* A PushfDI must be done before calling
;* Destroys: CX, DI, flags
;************************************************************************

ArpPutHwAd proc near
push si

mov cx,[si] ; put reverse search
mov ArpTabHw1[di],cx ; hw addr into slot
mov cx,[si+2]
mov ArpTabHw2[di],cx
mov cx,[si+4]
mov ArpTabHw3[di],cx

call CurrentTicks ; get current ticks value
mov ArpTabTr[di],cx

mov cx,ArpTabFlags[di]
and cl,not USE_SNAP
or cl,[bx].dSnap ; remember if snaps used
mov ArpTabFlags[di],cx ; by that host

mov cl,3 ; put hw addr into slot
shl di,cl
lea di,ArpTabHwAdr[di]
mov cx,Hlen
push cs
pop es
rep movsb
pop si
ret
ArpPutHwAd endp



;************************************************************************
;* ArpPutHwDst
;*
;* Input: DX = first word of IP # (saved)
;* AX = second word of IP # (saved)
;* Output: if found: zero, HW dst addr copied to pkt and CX = 0
;* Destroys: CX, SI, DI, ES, flags
;************************************************************************

ArpPutHwDst proc near
PushfDI

call ArpFindIp ; IP # in arp table?
jnz ArpPutHwRet ; - no, non-zero (not found)

mov cx,ArpTabFlags[di] ; use snap if neeeded
and cl,USE_SNAP
mov [bx].dSnap,cl ; by dst host
if RFCC
push ax
call CurrentTicks
mov ax,ArpTabSqDelay[di] ; move sq delay to descriptor
mov [bx].dSqDelay,ax
dec ax ; any delay?
js ArpNoSqDelay
mov ax,ArpTabTrSq[di] ; - yes
add ax,18 ; has one second has passed
cmp ax,cx ; since we last decremented
jns ArpNoSqDelay ; the delay value?
mov ArpTabTrSq[di],cx
dec ArpTabSqDelay[di] ; - yes, one millisecond off
ArpNoSqDelay:
pop ax
endif ; RFCC
mov cl,3 ; - yes, copy HW addr
shl di,cl
lea si,ArpTabHwAdr[di]
mov di,[bx].dPtrPhys
mov cx,Hlen
push cs
pop es
rep movsb

PopfEI
cmp di,di ; zero (found) return
ret

ArpPutHwRet:
PopfEI
dec cx ; non-zero return
ret
ArpPutHwDst endp



;************************************************************************
;* ArpPutNew
;*
;* Input: DX = first word of IP # (saved)
;* AX = second word of IP # (saved)
;* SI = pointer to physical address (saved)
;* Destroys: CX, DI, ES, flags
;************************************************************************

ArpPutNew proc near
PushfDI

call ArpFindIp ; already have IP # ?
jz ArpPutHere ; - yes, update hw addr
ArpPutWrap: ; - no, find next slot
mov di,ArpPutSlot
add di,2 ; advance index two bytes

cmp di,2*ARPSLOTS ; end of arp table?
jb ArpPut

mov di,ARPMYIDX+2 ; preserve bcast mappings
ArpPut: ; (first slots)
if TBLBUILD
push si
mov si,di
add si,2
cmp si,2*ARPSLOTS
jb ArpPut2
mov si,ARPMYIDX+2
ArpPut2:
mov cx,ArpTabTr[di]
sub cx,ArpTabTr[si]
js ArpPut3
mov di,si ; use elder of next 2 slots
ArpPut3:
pop si
endif ; TBLBUILD
mov ArpPutSlot,di
mov ArpTabIp1[di],dx ; put IP # into slot
mov ArpTabIp2[di],ax
xor cx,cx ; clear other fileds
mov ArpTabFlags[di],cx
mov ArpTabSqDelay[di],cx
ArpPutHere:
call ArpPutHwAd ; put HW addr into slot

PopfEI
ret
ArpPutNew endp



;************************************************************************
;* SendArpReq
;*
;* Input: DX = first word of IP # (saved)
;* AX = second word of IP # (saved)
;* BX = IP description buffer ptr (saved)
;* Output: Zero and CX = 0 if OK
;* non-zero and CX = errorcode if error
;* Destroys: CX, SI, DI, ES, flags
;************************************************************************

SendArpReq proc near
push dx ; dx,ax has IP # to arp for
push ax
push bx ; save IP descr addr

call BufAlloc ; get a buffer
mov cx,SERRNOBUF
jz SendArpRet

mov si,offset ArpTabHwAdr ; put Ether broadcast dst
mov cx,Hlen
push cs
pop es
rep movsb

call MakeSendDescr ; set up descriptor

call PutPhysSrc ; put Ether src addr

push di
mov si,offset ArpFixedPart ; copy in static arp part
mov cx,ArpFixedLen-2*16 ; *test*
add cx,H2len
push cs
pop es
rep movsb

sub di,[bx].dPtrPhys ; calculate packet length
mov [bx].dPktLen,di

pop di ; compute addr to dst IP #
add di,aArpOffsSrcIp
add di,H2Len

mov [di+4],dx ; IP # to arp for
mov [di+4+2],ax

sub di,Hlen ; fill in My IP #
mov dx,MyIpNr
mov ax,MyIpNr+2
mov [di],dx
mov [di+2],ax

pop si ; IP descr addr
push si

mov cx,[si].dTimOutMsg ; use application timeout msg
mov [bx].dTimOutMsg,cx

mov cx,[si].dTickTimeout
cmp cx,3*18 ; limit arp timeout
jbe SendArpOkTim
mov cx,3*18 ; to 3 seconds or less
SendArpOkTim:
mov [bx].dTickTimeout,cx

mov [bx].dWaitEvent,GOT_ARPREPLY

call SendAndWait ; send arp request packet

call BufRelease ; release buffer
SendArpRet:
or cx,cx
pop bx ; restore IP descr addr
pop ax ; restore IP # we ARPed for
pop dx
ret
SendArpReq endp



;************************************************************************
;* InitArp
;************************************************************************

InitArp proc near
push ds
mov ax,1ffh ; driver_info
int_pkt
pop ds

call fatal_error

mov ah,2 ; access all packets.
mov al,ch ; their class from driver_info().
mov byte ptr ArpBuf.iArpHtype+1,al
mov bx,dx ; their type from driver_info().
mov dl,cl ;their number from driver_info().
mov cx,2 ;type length of two.
mov si,offset ArpType
push cs ;es:di -> our receiver.
pop es
mov di,offset ArpRecv

push ds
int_pkt
pop ds

call fatal_error

mov ArpHandle,ax

mov bx,ax
push cs
pop es
mov di,offset MyHwAd
mov cx,15
mov ah,6 ; get my Hw addr

push ds
int_pkt
pop ds

call fatal_error

mov ArpBuf.iArpHlen,cl ; save Hw address length
mov Hlen,cx
shl cx,1
mov H2Len,cx

ret
InitArp endp



;************************************************************************
;* BuildRecDescr
;************************************************************************

BuildRecDescr proc near
mov bx,si
mov ax,si
add ax,cx ; end of packet limit

sub bx,2
mov bx,[bx] ; addr of descriptor

mov [bx].dPktLen,cx ; fill in descriptor info
mov [bx].dPktEnd,ax

add si,H2Len
mov ax,[si] ; type/length field
xchg ah,al

xor dl,dl
cmp ax,GIANT ; if 802.3 pkt
jbe BuildHpOrSnap ; do special handling
BuildNotSnap:
mov [bx].dSnap,dl
lea di,[si+2]
mov [bx].dPtrIp,di ; di must point to IP hdr
ret

BuildHpOrSnap:
BuildSnap:
inc dl ; -no, assumed to be snap
add si,SNAPLEN ; skip over snap bytes
jmp short BuildNotSnap
BuildRecDescr endp



;************************************************************************
;* ARP receiver *
;************************************************************************

ArpRecv:
pushf ; set segment registers
push ds
mov dx,cs
mov ds,dx
mov es,dx
cld

or ax,ax ; first or second call?
jne ArpRecv_1 ; - second, we've got data
; - first, they want a buf
cmp cx,GIANT ; packet too long?
ja ArpRecTooBig
if PINGCLIENT
cmp cx,BUFBODYSML
ja ArpRecBig

call BufAlSml
jz ArpRecBig
pop ds
popf
retf

ArpRecBig:
endif ; PINGCLIENT
call BufAlloc ; get a receive buffer
jz ArpRecNoBuf
ArpRecRet0:
pop ds
popf
retf

if DEBUG
DbgArpRecv:
or GenFlags,DBGINTERR
endif ; DEBUG
ArpRecNoBuf:
ArpRecTooBig:
xor di,di ; no buffer available
mov es,di
jmp short ArpRecRet0


ArpRecv_1:
cli ; switch to our
mov word ptr SaveSP,sp ; interrupt stack
mov word ptr SaveSS,ss
mov sp,offset StackEnd
mov ss,MySegm
sti ; enable interrupts
if DEBUG
dec DbgIntCnt ; double interrupt?
jnz DbgArpRecv
endif ; DEBUG

call BuildRecDescr

cmp [di].iArpProt,0008h ; arp IP protocol?
jne ArpRecRet

push di
mov di,[bx].dPtrPhys
add di,Hlen
mov si,[di]
mov dx,[di+2]
mov ax,[di+4]
call ArpFindHw
pop si
jnz ArpRecNew

cmp di,ARPMYIDX ; ignore pkts from bcast or me
jbe ArpRecRet ; (also helps NDIS)
ArpRecNew:
lea di,[si].iArpMyHwAd
mov cx,[si].iArpOp ; ARP reply?

mov si,di
add di,Hlen
mov dx,word ptr [di] ; get HIS (!) IP # and keep
mov ax,word ptr [di+2] ; it for a long while

add di,4
cmp di,[bx].dPktEnd ; big enough to be arp pkt?
ja ArpRecRet

; The following test is not according to the ARP RFC. The reason for this
; divergence is that if we follow the RFC algorithm, anybody that momentarily
; uses a wrong IP number would disrupt our communication with the original
; owner of that IP number. This would be true even if the program he uses
; is nice (NCSA Telnet for example) and starts by sending an ARP packet for
; itself to see if anybody will answer (a very good thing to do and this
; package does so too).
;
; We do obey an unsolicited arp reply immediately, other cases of changed
; hardware address will be taken care of in a minute automagically by the
; arp table ageing mechanism, so this package should do well even when moving
; hosts in a proxy arp environment.

cmp cx,0200h ; ARP reply?
jne ArpNotReply

PushfDI
call ArpFindIp ; if he is in our ARP table we
jnz ArpNotThere

call ArpPutHwAd ; should update his HW addr
ArpNotThere:
PopfEI
ArpNotReply:
mov di,si
add di,H2Len
mov cx,[di+4]
cmp cx,MyIpNr ; is this arp for me?
jne ArpRecTbl
mov cx,[di+6]
cmp cx,MyIpNr+2
jne ArpRecTbl

add di,8
cmp di,[bx].dPktEnd
ja ArpRecRet

call ArpPutNew ; - yes, put his IP # and HW
; addr into the ARP table
mov di,[bx].dPtrIp
cmp [di].iArpOp,0100h ; arp request?
je ArpRecReq

or Events,GOT_ARPREPLY ; - no, probably a wanted reply
ArpRecTbl:

if TBLBUILD
test ArgFlags,MAKE_TABLE
jnz ArpRecBld
endif ; TBLBUILD

ArpRecRet:
call BufRelease ; release receive buffer
ArpRecKeepBuf:
if DEBUG
inc DbgIntCnt
endif ; DEBUG
cli ; restore previous stack
mov sp, word ptr SaveSP
mov ss, word ptr SaveSS
pop ds
popf
retf
if TBLBUILD
ArpRecBld:
cmp FreeBufs.lBufsAvail,NBUFS/4
jbe ArpRecRet

test GenFlags,TBL_READY
jz ArpRecRet

mov si,offset TblToDo
call AddToList
jmp short ArpRecKeepBuf
endif ; TBLBUILD

ArpRecReq:
mov [di].iArpOp,0200h ; put arp reply code

mov di,si
push di
mov cx,Hlen
add cx,4
add di,cx
push cs
pop es
rep movsb ; mov arp dst to arp src
pop di

mov si,offset MyHwAd
mov cx,Hlen
rep movsb ; put in my HW addr as arp src

mov cx,MyIpNr
mov [di],cx ; put my IP # to arp src
mov si,MyIpNr+2
mov [di+2],si

cmp dx,cx ; is he stealing my IP # ?
jne ArpRecNoSteal
cmp ax,si
jne ArpRecNoSteal

mov dx,ArpTabIp1 ; - yes, tell everybody by
mov ax,dx ; broadcasting my reply
ArpRecNoSteal:
mov [bx].dWaitEvent,0

call ArpPutHwDst ; put dst Ether addr fr DX,AX

call PutPhysSrc ; put src Ether addr

mov word ptr [di],0608h ; arp prot

mov si,offset SendToDo ; put buffer on the send list
call AddToList ; for non-interrupt handling
jmp short ArpRecKeepBuf

;========================================================================
; endinclude


  3 Responses to “Category : Network Files
Archive   : PDCLK145.ZIP
Filename : ARP.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/