home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-385-Vol-1of3.iso
/
p
/
pcrte224.zip
/
SOURCE.ZIP
/
ARP.INC
< prev
next >
Wrap
Text File
|
1992-06-09
|
16KB
|
437 lines
;;*****************************************************************************
;; arp.inc arp.inc
;;*****************************************************************************
;;
;; Copyright (C) 1989 Northwestern University, Vance Morrison
;;
;;
;; Permission to view, compile, and modify for LOCAL (intra-organization)
;; USE ONLY is hereby granted, provided that this copyright and permission
;; notice appear on all copies. Any other use by permission only.
;;
;; Northwestern University makes no representations about the suitability
;; of this software for any purpose. It is provided "as is" without expressed
;; or implied warranty. See the copywrite notice file for complete details.
;;
;;*****************************************************************************
;;
;; arp.inc constains the DL_IP interface for ethernet. This is the module
;; that handles the arp lookup need to support the DL_IP interface
;; (see dl_ip.inc for a description of the DL_IP interface)
;;
;; The functions provided by this file are
;;
;; ARP_DECLARE name, ether
;; ARP_DEFINE name, ip_address, ip_mask
;; ARP_DL_IP_R_READ name, code_label
;; ARP_DL_IP_R_CONT_in_BX_CX_ES_const_BX_CX_DX_BP_SI_DI_ES name, ok
;; ARP_DL_IP_RETURN name
;; ARP_DL_IP_W_ACCESS_in_CX_out_DI_ES_const_CX_BP name, fail
;; ARP_DL_IP_W_WRITE_in_AX_CX_const_BP name, broadcast
;; ARP_DL_IP_IS_BROADCAST_in_BX_ES_const_AX_BX_CX_DX_BP_DI_ES name
;; ARP_DL_IP_COPY_in_CX_SI_DI_ES_out_SI_DI_const_BX_BP_ES name
;;
;; Variables Provided by this module (READ ONLY!!!!)
;;
;; arp_&name&_declared 1 if this data structure is declared
;; dl_ip_&name&_ip the IP address
;; dl_ip_&name&_mask the network mask
;; dl_ip_&name&_net the network (IP addr bitwize AND ip_mask)
;; dl_ip_&name&_broad the network broadcast address
;; dl_ip_&name&_flags A word exclusively for IP use
;; dl_ip_&name&_mtu The maximum transmition unit
;; dl_ip_&name&_metric The interface metric
;; dl_ip_&name&_haddr The hardware address
;;
;;*****************************************************************************
;;*****************************************************************************
;; data storage needed by this module
arp_data STRUC
arp_broadcast DW 3 dup (0)
arp_write_off DW 0 ;; offset and seg for
arp_write_seg DW 0 ;; the write buffer
arp_data ENDS
;;*****************************************************************************
;; ARP_DECLARE name, ether
;; creates a new data link object. 'name' is the name of this new
;; object. 'ether' is the name of the ethernet to that will provide
;; the low level services this module will need.
;;
ARP_DECLARE MACRO name, ether
.errb <name>
.errb <ether>
.DATA
arp_&name&_declared = 1
arp_&name&_ether = ether
arp_&name&_arptab = (100*name+1)
dl_ip_&name&_mtu = 1500
dl_ip_&name&_haddr = eth_ðer&_address
global dl_ip_&name&_ip:dword
global dl_ip_&name&_mask:dword
global dl_ip_&name&_net:dword
global dl_ip_&name&_broad:dword
global dl_ip_&name&_flags:word
global dl_ip_&name&_metric:word
global arp_&name&_data:arp_data
.CODE
ARP_TAB_DECLARE %arp_&name&_arptab
ENDM
;;*****************************************************************************
;; ARP_DEFINE name, ip_address, ip_mask
;; ARP_DEFINE declare all the things that have to be defined in
;; every independantly assembled module. DL_IP declares those
;; things that need be be done only once (in particular memory allocation
;; and initialzation code). Every module including the one ARP_DEFINE
;; is in) must have a DL_IP_DELCARE. 'ip_address' holds the address of
;; the IP address for this ethernet and 'ip_mask' is the subnet mask.
;;
ARP_DEFINE MACRO name, ip_address, ip_mask
local around, arp_read_packet, zero_broad
.errb <ip_mask>
ifdef arp_&name&_declared
.DATA
dl_ip_&name&_ip DD ?
dl_ip_&name&_mask DD ?
dl_ip_&name&_net DD ?
dl_ip_&name&_broad DD ?
dl_ip_&name&_flags DW ?
dl_ip_&name&_metric DW ?
arp_&name&_data arp_data <> ;; create storage needed
.CODE
jmp around
arp_read_packet:
ARP_PROCESS_PACKET_in_AX_BX_ES name
ETH_R_RETURN %arp_&name&_ether
;; this does NOT fall through
around:
mov AX, word ptr ip_address ;; copy over params
mov BX, 0FFFFH ;; Force our assumtion
mov word ptr dl_ip_&name&_ip, AX
mov word ptr dl_ip_&name&_net, AX
mov word ptr dl_ip_&name&_broad, AX
mov word ptr dl_ip_&name&_mask, BX
mov AX, word ptr ip_address+2
mov BX, word ptr ip_mask+2
mov word ptr dl_ip_&name&_ip+2, AX
mov word ptr dl_ip_&name&_mask+2, BX
and AX, BX
mov word ptr dl_ip_&name&_net+2, AX
test word ptr dl_ip_&name&_flags, ZERO_BROADCAST
jnz zero_broad
not BX
or AX, BX
zero_broad:
mov word ptr dl_ip_&name&_broad+2, AX
ARP_TAB_DEFINE %arp_&name&_arptab
mov AX, DS ;; initialize the broadcast addr
mov ES, AX
mov DI, offset arp_&name&_data.arp_broadcast
mov AX, 0FFFFh
stosw
stosw
stosw
mov AX, word ptr dl_ip_&name&_broad+2
mov BX, offset arp_&name&_data.arp_broadcast
ARP_TAB_ADD_in_AX_BX_ES_out_SI_const_BX_DX_BP_DI_ES %arp_&name&_arptab
;; start up the arp task
ETH_R_READ %arp_&name&_ether, ARP_TYPE, arp_read_packet
endif
ENDM
;;******************************************************************************
;; DL_IP_R_READ name, code_label
;; DL_IP_R_READ declares that the code starting at 'code_label'
;; should be called whenever a IP packet is read. BX:ES is initilized
;; to the begining of the IP packet before 'macro_code' is called
;; The code at 'code_label' should call ARP_DL_IP_R_RETURN when it
;; is done processing the packet.
;; This procedure can only be called once per 'name'
;;
ARP_DL_IP_R_READ MACRO name, code_label
.errb <code_label>
ETH_R_READ %arp_&name&_ether, IP_TYPE, code_label
ENDM
;;******************************************************************************
;; DL_IP_R_CONT_in_BX_CX_ES name, ok
;; DL_IP_R_CONT determines if the packet returned by R_READ in BX:ES
;; of length CX is continuous. If it is it jumps to 'ok' otherwise
;; it just returns
;;
ARP_DL_IP_R_CONT_in_BX_CX_ES_const_BX_CX_DX_BP_SI_DI_ES MACRO name, ok
.errb <ok>
ETH_R_CONT_in_BX_CX_ES_const_BX_CX_DX_BP_SI_DI_ES %arp_&name&_ether, ok
ENDM
;;******************************************************************************
;; DL_IP_R_RETURN name
;; DL_IP_R_RETURN should be executed by the READ routine to signal
;; that it is done processing the packet.
;;
ARP_DL_IP_R_RETURN MACRO name
.errb <name>
ETH_R_RETURN %arp_&name&_ether
ENDM
;;******************************************************************************
;; DL_IP_W_ACCESS_in_CX_out_DI_ES name, fail
;; DL_IP_W_ACCESS returns a pointer to an output buffer for a IP
;; packet. The pointer is returned in DI:ES. This routine may
;; busy wait for a time, and after a reasonable attempt a buffer
;; could not be had, it will jump to 'fail'
;;
ARP_DL_IP_W_ACCESS_in_CX_out_DI_ES_const_CX_BP MACRO name, fail
.errb <name>
.errb <fail>
ETH_W_ACCESS_in_CX_out_DI_ES_const_BX_CX_BP %arp_&name&_ether, fail
mov arp_&name&_data.arp_write_off, DI
mov arp_&name&_data.arp_write_seg, ES
ENDM
;;******************************************************************************
;; DL_IP_W_WRITE_in_AX_CX name, broadcast
;; DL_IP_W_WRITE actually signals the link layer to write a packet to the
;; network. The packet is assumed to be in the buffer returned by
;; DL_IP_W_ACCESS. CX is the length of the packet to send. AX holds the
;; last two bytes of the IP address to send the packet to. (notice we
;; are assuming a host portion of less that 16 bits)
;; if 'broadcast' is not blank, then the packet is written to the
;; broadcast address. AX is ignored in this case
;;
ARP_DL_IP_W_WRITE_in_AX_CX_const_BP MACRO name, broadcast
local send_packet
.errb <name>
les DI, dword ptr arp_&name&_data.arp_write_off
mov BX, SWAPPED_IP_TYPE
ifb <broadcast>
ARP_TAB_GET_in_AX_out_SI_const_AX_BX_CX_BP_DI_ES %arp_&name&_arptab
jz send_packet
ARP_BUILD_REQUEST_in_AX_DI_ES_const_CX_DX_BP_ES name
mov CX, size arp
mov DI, word ptr arp_&name&_data.arp_write_off
mov SI, offset arp_&name&_data.arp_broadcast
mov BX, SWAPPED_ARP_TYPE
send_packet:
else
mov SI, offset arp_&name&_data.arp_broadcast
endif
mov AX, BX
ETH_W_WRITE_in_AX_CX_SI_DI_ES_const_BX_BP_ES %arp_&name&_ether
ENDM
;;******************************************************************************
;; DL_IP_IS_BROADCAST_in_BX_ES name
;; DL_IP_IS_BROADCAST_in_BX_ES determines if the packet pointed to
;; by BX:ES is a broadcast and sets the zero flag if it is NOT a
;; broadcast
;;
ARP_DL_IP_IS_BROADCAST_in_BX_ES_const_AX_BX_CX_DX_BP_DI_ES MACRO name
.errb <name>
ETH_IS_BROADCAST_in_BX_ES_const_AX_BX_CX_DX_BP_DI_ES %arp_&name&_ether
ENDM
;;******************************************************************************
;; DL_IP_COPY_in_CX_SI_DI_ES_out_SI_DI_const_BX_BP_ES name
;; DL_IP_COPY_in_CX_SI_DI_ES copys a packet from the input buffer (pointed
;; to by SI and the segement register given in IF_DECLARE) to an output
;; buffer (pointed to by DI and dest_reg) of length CX. It assumes the
;; output buffer is contiguous. (and the caller shouldn't care if the
;; input buffer is contiguous) COPY updates the pointers SI and DI
;; to the end of the packet, and COPY could be called again if CX is not
;; the total packet length (Note that CX MUST be even if you care about
;; SI, and DI being updated properly)
;;
;;
ARP_DL_IP_COPY_in_CX_SI_DI_ES_out_SI_DI_const_BX_BP_ES MACRO name
.errb <name>
ETH_COPY_in_CX_SI_DI_ES_out_SI_DI_const_BX_BP_ES %arp_&name&_ether
ENDM
;;******************************************************************************
;; ARP_PROCESS_PACKET_in_AX_BX_ES MACRO name
;; ARP_PROCESS_PACKET is called when an ARP packet is received. AX holds
;; the ethernet type (SWAPPED_ARP_TYPE) and BX:ES points to the begining
;; of the ARP packet
;;
ARP_PROCESS_PACKET_in_AX_BX_ES MACRO name
local notarp, forme, notme
.errb <name>
cmp word ptr AX, SWAPPED_ARP_TYPE ;; is it an arp packet
jne notarp
mov AX, word ptr ES:[BX+arp_proto] ;; is it my IP address
cmp word ptr AX, SWAPPED_IP_TYPE ;; is it an arp packet
jne notarp
mov AX, word ptr ES:[BX+arp_spa+2]
add BX, arp_sha
ARP_TAB_ADD_in_AX_BX_ES_out_SI_const_BX_DX_BP_DI_ES %arp_&name&_arptab
sub BX, arp_sha
cmp byte ptr ES:[BX+arp_op+1], ARP_REQUEST
jnz notme
mov AX, word ptr ES:[BX+arp_tpa+2] ;; is it my IP address
cmp AX, word ptr dl_ip_&name&_ip+2
jz forme
;; should I PROXY
test word ptr dl_ip_&name&_flags, ARP_PROXY_ARP
jz notme
and AX, word ptr dl_ip_&name&_mask+2
cmp AX, word ptr dl_ip_&name&_net+2
jz notme
forme:
mov BP, SI ;; save SI
mov SI, BX
ARP_BUILD_REPLY_in_SI_ES_const_DX_BP_SI_ES name
mov CX, size arp
mov BX, SI ;; save SI
ETH_W_ACCESS_in_CX_out_DI_ES_const_BX_CX_BP %arp_&name&_ether, notme
mov SI, BX ;; restore SI
mov BX, DI ;; save DI
mov CX, size arp
ETH_COPY_in_CX_SI_DI_ES_out_SI_DI_const_BX_BP_ES %arp_&name&_ether
mov CX, size arp
mov DI, BX ;; restore DI
mov SI, BP ;; restore SI
mov AX, SWAPPED_ARP_TYPE
ETH_W_WRITE_in_AX_CX_SI_DI_ES_const_BX_BP_ES %arp_&name&_ether
notme:
notarp:
ENDM
;;******************************************************************************
;; arp related stuff. these are for internal use only
ARP_REQUEST = 1
ARP_REPLY = 2
SWAPPED_ARP_REQUEST = 100h
SWAPPED_ARP_REPLY = 200h
ARP_ETHER_TYPE = 1
SWAPPED_ARP_ETHER_TYPE = 100h
arp STRUC
arp_hdr DW 1 ;; header type 1 = ETHERNET
arp_proto DW 0
arp_hln DB 6 ;; length of ethernet address
arp_pln DB 4 ;; length of IP address
arp_op DW ARP_REPLY ;; operation
arp_sha DB 6 DUP (0) ;; source hardware address
arp_spa DB 4 DUP (0) ;; source protocol address
arp_tha DB 6 DUP (0) ;; target hardware address
arp_tpa DB 4 DUP (0) ;; target protocol address
arp ENDS
;;******************************************************************************
;; ARP_BUILD_REQUEST_in_AX_DI_ES builds an arp request in the buffer
;; pointed to by DI:ES for the ip address that ends in AX
ARP_BUILD_REQUEST_in_AX_DI_ES_const_CX_DX_BP_ES MACRO name
.errb <name>
mov BX, AX ;; save AX
mov AX, SWAPPED_ARP_ETHER_TYPE
stosw
mov AX, SWAPPED_IP_TYPE
stosw
mov AX, 0406h ;; byte swapped hardware address len, ip address len
stosw
mov AX, SWAPPED_ARP_REQUEST
stosw
mov SI, offset dl_ip_&name&_haddr ;; copy me as source hardware address
movsw
movsw
movsw
mov SI, OFFSET dl_ip_&name&_ip ;; and protocol address
movsw
movsw
mov AX, 0
stosw ;; target harware address
stosw
stosw
mov SI, OFFSET dl_ip_&name&_ip ;; target ip address
movsw
mov AX, BX
stosw
ENDM
;;******************************************************************************
;; ARP_BUILD_REPLY_in_SI_ES converts the ARP request in SI:ES to a reply
;; that has indicates that this node is the target of the request. Note
;; that this routine just copies the target IP address from the request,
;; so that proxy arp is easy.
ARP_BUILD_REPLY_in_SI_ES_const_DX_BP_SI_ES MACRO name
.errb <name>
mov CX, SI ;; save the pointer
mov word ptr ES:[SI+arp_op], SWAPPED_ARP_REPLY
mov AX, word ptr ES:[SI+arp_tpa]
mov BX, word ptr ES:[SI+arp_tpa+2]
add SI, offset arp_sha
mov DI, CX
add DI, offset arp_tha
seges ;; copy source hardware and proto addr
movsw
seges
movsw
seges
movsw
seges
movsw
seges
movsw
mov DI, CX
add DI, offset arp_sha
mov SI, offset dl_ip_&name&_haddr
movsw ;; put in me as source hardware addr
movsw
movsw
stosw ;; put in TPA as source hardware addr
mov AX, BX
stosw
mov SI, CX ;; restore SI
ENDM