home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware 1 2 the Maxx
/
sw_1.zip
/
sw_1
/
LAN
/
PDCLK139.ZIP
/
ARP.ASM
next >
Wrap
Assembly Source File
|
1992-05-17
|
16KB
|
653 lines
; arp.asm
;========================================================================
; Copyright (C) 1991 by Jan.Engvald@ldc.lu.se, 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