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