www.pudn.com > tcpipstack.rar > ARP.C


/*  
 * SAR: Simple Address Resolution Protocol Implementation 
 * Written by Geoffrey Cooper, September 27, 1983 
 *  
 * This package implements a very simple version of the Plummer Address 
 * Resolution Protocol (RFC 826). It allows clients to resolve Internet 
 * addresses into Ethernet addresses, and knows how to respond to an 
 * address resolution request (when the transmit buffer is free). 
 *  
 * Routines: 
 *  
 * sar_CheckPacket( pb ) => 1, if ARP packet and processed, 0 otherwise 
 * sar_MapIn2Eth( ina, ethap ) => 1 if did it, 0 if couldn't. 
 * 
 * Copyright (C) 1983, 1986 IMAGEN Corporation 
 * "This code may be duplicated in whole or in part provided that [1] there 
 * is no commercial gain involved in the duplication, and [2] that this 
 * copyright notice is preserved on all copies.  Any other duplication 
 * requires written notice of the author." 
 
|===================================================================| 
|  The author of this code hereby licenses all duplication and/or   |  
|  modification of this code, in whole or in part, consistent with  | 
|  the terms of the GNU Library General Public License.             | 
|              - Geoffrey H. Cooper 10/29/97                        | 
|===================================================================| 
 
|===================================================================| 
|  My changes can be considered public domain.  Geof's statement    | 
|  will cover everything.                                           | 
|              - Rick Rodman 09/02/97                               | 
|===================================================================| 
 
940424	rr	minor changes 
940529	rr	ditto 
 */ 
 
#include "tinytcp.h" 
 
#include  
 
extern	IP_Address		local_IP_address; 
extern	Ethernet_Address	local_ethernet_address; 
extern	Ethernet_Address	broadcast_ethernet_address; 
 
int sar_CheckPacket( ap ) struct arp_Header *ap; { 
	struct arp_Header *op; 
 
	if( ap->hwType != arp_TypeEther ||	/* have ethernet hardware, */ 
		ap->protType != 0x800 ||	/* and internet software, */ 
		ap->opcode != ARP_REQUEST ||	/* and be a resolution req. */ 
		ap->dstIPAddr != local_IP_address ) /* for my addr. */ 
		return ( 0 );			/* .... or we ignore it. */ 
 
	/* format response. */ 
 
	op = ( struct arp_Header * ) sed_FormatPacket( 
		( Byte * ) ap -> srcEthAddr, 0x806 ); 
	op->hwType = arp_TypeEther; 
	op->protType = 0x800; 
	op->hwProtAddrLen = (sizeof( Ethernet_Address ) << 8 ) 
		+ sizeof( IP_Address ); 
	op->opcode = ARP_REPLY; 
	op->srcIPAddr = local_IP_address; 
	Move( ( Byte * ) local_ethernet_address, ( Byte * ) op->srcEthAddr, 
		sizeof( Ethernet_Address )); 
	ap->dstIPAddr = op->srcIPAddr; 
	Move( ( Byte * ) ap->srcEthAddr, ( Byte * ) op->dstEthAddr, 
		sizeof( Ethernet_Address )); 
 
	sed_Send(sizeof(struct arp_Header)); 
	 
	return ( 1 ); 
} 
 
/*  
 * Do an address resolution bit. 
 */ 
 
int sar_MapIn2Eth( ina, ethap ) Longword ina; Ethernet_Address *ethap; { 
	struct arp_Header *	op; 
	Longword		endTime; 
	Longword		rxMitTime; 
 
	sed_Receive( ( Byte * ) 0 ); 
	endTime = MsecClock() + 2000; 
	while ( endTime > MsecClock() ) { 
		op = (struct arp_Header *) sed_FormatPacket( 
			( Byte * ) &broadcast_ethernet_address[ 0 ], 0x806 ); 
 
		op->hwType = arp_TypeEther; 
		op->protType = 0x800; 
		op->hwProtAddrLen = (sizeof(Ethernet_Address) << 8) 
			+ sizeof( IP_Address ); 
		op->opcode = ARP_REQUEST; 
 
		op->srcIPAddr = local_IP_address; 
		Move( ( Byte * ) local_ethernet_address, ( Byte * ) op->srcEthAddr, 
			sizeof(Ethernet_Address)); 
		op->dstIPAddr = ina; 
 
		/* ...and send the packet */ 
 
		sed_Send( sizeof(struct arp_Header) ); 
 
		rxMitTime = MsecClock() + 250; 
		while ( rxMitTime > MsecClock() ) { 
			op = (struct arp_Header *)sed_IsPacket(); 
			if ( op ) { 
				if ( sed_CheckPacket( ( Word * ) op, 0x806 ) 
					== 1 && 
					op->protType == 0x800 && 
					op->srcIPAddr == ina && 
					op->opcode == ARP_REPLY ) { 
					Move( ( Byte * ) op->srcEthAddr, 
						( Byte * ) ethap, 
						sizeof(Ethernet_Address)); 
					return ( 1 ); 
				} 
				sed_Receive( ( Byte * ) op ); 
			} 
		} 
	} 
	return ( 0 ); 
} 
 
/* end of arp.c */