home *** CD-ROM | disk | FTP | other *** search
- ; 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
-