⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 arp.c

📁 udp,tcp/ip在智能家居芯片上的代码实现.包括芯片NE64的网络驱动源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	/* Next time start from next entry	*/
	
	aenext = (aenext + 1);	
	if( aenext >= ARP_TSIZE )
		aenext = 1;		

	qstruct = &arp_table[found];
	
	/* Set ARP initial parameters	*/
	
	qstruct->state = ARP_RESERVED;
	qstruct->type = type;
	
	/* Was return(i)!!! <-wrong!!	*/
	
	return((UINT8)found);


}
/** \brief Add given IP address and MAC address to ARP cache
 * 	\author 
 *		\li Jari Lahti (jari.lahti@violasystems.com)
 *	\date 10.07.2002
 *	\param pra - protocol address (assumed IPv4)
 *	\param hwadr - pointer to Ethernet MAC address (6 bytes)
 *	\param type - type of address allocated if not found. Can be one of the
 *		following:
 *		\li #ARP_FIXED_IP
 *		\li #ARP_TEMP_IP
 *	\return
 *		\li 0 - Address already in cache. Refreshed.
 *		\li 1 - New entry in ARP cache created
 *
 *	New IP address is added to ARP cache based on the information
 *	supplied to function as parameters.
 */
INT8 arp_add (UINT32 pra, UINT8* hwadr, UINT8 type)
{
	struct arp_entry *qstruct;
	INT8 i;
	INT8 j;

	for( i=0; i<ARP_TSIZE; i++ ) {
		qstruct = &arp_table[i];
		
		if( qstruct->state == ARP_FREE )
			continue;
			
		if((qstruct->pradr == pra)&&(pra != IP_BROADCAST_ADDRESS)) {
			/* The address is in cache, refresh it	 */
			
			ARP_DEBUGOUT(" Refreshing Existing ARP Entry..\n\r");
		
			for( j=0; j<MAXHWALEN; j++ )		
				qstruct->hwadr[j] = *hwadr++;
				
			qstruct->ttl = ARP_TIMEOUT;
			qstruct->retries = ARP_MAXRETRY;
			qstruct->state = ARP_RESOLVED;
	
			/* All OK	*/
		
			return (0);	
		}
	
	}
	
	if(is_subnet(pra,&localmachine) == FALSE){
		return (-1);
	}
	
	if( localmachine.defgw == pra )	{
		if(localmachine.defgw != 0) {
			type = ARP_FIXED_IP;
		}
	}

	
	/* Address was'nt on cache. Need to allocate new one	*/
	
	ARP_DEBUGOUT("Allocating New ARP Entry..\n\r");
	
	i = arp_alloc(type);
	
	if( i < 0 )				/* No Entries Left?	*/
		return(-1);
			
	/* Fill the fields		*/
		
	qstruct = &arp_table[i];
		
	qstruct->pradr = pra;										/* Fill IP				*/
	
	for(i=0; i<MAXHWALEN; i++)
		qstruct->hwadr[i] = *hwadr++;							/* Fill HW address		*/

	qstruct->retries = ARP_MAXRETRY;
	qstruct->ttl = ARP_TIMEOUT;
	qstruct->state = ARP_RESOLVED;				
	
	ARP_DEBUGOUT("ARP Entry Created!..\n\r");

	return(1);

}
 
/** \brief Find an ARP entry given a protocol address
 * 	\author 
 *		\li Jari Lahti (jari.lahti@violasystems.com)
 *	\date 01.11.2001
 *	\param pra - Protocol address (IPv4)
 *	\param machine - Pointer to configuration of network interface used
 *	\param type - Type of address allocated if not found. Can be one of the
 *		following:
 *		\li #ARP_FIXED_IP
 *		\li #ARP_TEMP_IP
 *	\return
 *		\li 0 - ARP entry not found or not ready yet (waiting for ARP response)
 *		\li struct arp_entry* - pointer to solved entry of ARP cache table
 *
 *	This function tries to resolve IPv4 address by checking the ARP cache
 *	table and sending ARP requested if needed. 
 */
struct arp_entry* arp_find (LWORD pra, struct netif *machine, UINT8 type)
{
	struct arp_entry *qstruct;
	INT8 i;
	
	ARP_DEBUGOUT("Trying to find MAC address from ARP Cache\n\r");
	
	/* Is the address in the cache	*/
	
	for( i=0; i<ARP_TSIZE; i++ ) {
		qstruct = &arp_table[i];
		
		if( qstruct->state == ARP_FREE )
			continue;
		if( qstruct->pradr == pra) {
			/* The address is in cache, is it valid? */
			
			ARP_DEBUGOUT("Address In Cache\n\r");
			
			if( qstruct->state < ARP_RESOLVED ) {
				ARP_DEBUGOUT("Address in cache but unresolved :(\n\r");
				return(0);
			}
			/* All OK	*/
		
			return(qstruct);	
		}
	
	}
	
	/* The address wasn't on the cache. Is it in our Subnet?	*/
	
	if( is_subnet(pra, machine) ) {
		/* Yep, we need to send ARP REQUEST	*/
		
		ARP_DEBUGOUT("Need to send ARP Request to local network..\n\r");
		
		if( machine->defgw == pra ) {
			if(machine->defgw != 0) {
				type = ARP_FIXED_IP;
			}
		}
		i = arp_alloc(type);
		
		if( i < 0 )				/* No Entries Left?	*/
			return(0);
			
		/* Send Request after filling the fields	*/
		
		qstruct = &arp_table[i];
		
		qstruct->pradr = pra;						/* Fill IP				*/
		qstruct->hwadr[0] = 0xFF;					/* Fill Broadcast IP	*/
		qstruct->hwadr[1] = 0xFF;
		qstruct->hwadr[2] = 0xFF;
		qstruct->hwadr[3] = 0xFF;
		qstruct->hwadr[4] = 0xFF;
		qstruct->hwadr[5] = 0xFF;
		qstruct->retries = ARP_MAXRETRY;
		qstruct->ttl = ARP_RESEND;
		arp_send_req( i );
		qstruct->state = ARP_PENDING;				/* Waiting for Reply	*/
		
		return(0);
	
	} 

	/* The Address belongst to the outern world, need to use MAC of			*/
	/* Default Gateway														*/
	
	ARP_DEBUGOUT("Need to use MAC of Default GW\n\r");
	
	/* Check for Broadcast													*/
	
	if(machine->defgw == 0)				/* It's not specified	*/
		return(0);
	
	
	for( i=0; i<ARP_TSIZE; i++ ) {
		qstruct = &arp_table[i];
		
		if( qstruct->state == ARP_FREE )
			continue;
			
		if( qstruct->pradr == machine->defgw ) {
			/* The address is in cache, is it valid? */
		 
			
			if( qstruct->state < ARP_RESOLVED ) {
				ARP_DEBUGOUT("The Address of Def. GW is not Solved!\n\r");
				return(0);
			}
		
			/* All OK	*/
			
			ARP_DEBUGOUT(" >> Default Gateway MAC found!\n\r");
		
			return(qstruct);
				
		}
	
	}
	
	ARP_DEBUGOUT("Need to send ARP Request to default gateway..\n\r");
		
	i = arp_alloc(ARP_FIXED_IP);
		
	if( i < 0 )				/* No Entries Left?	*/
		return(0);
			
	/* Send Request after filling the fields	*/
		
	qstruct = &arp_table[i];
		
	qstruct->pradr = machine->defgw;						/* Fill IP				*/
	qstruct->hwadr[0] = 0xFF;					/* Fill Broadcast IP	*/
	qstruct->hwadr[1] = 0xFF;
	qstruct->hwadr[2] = 0xFF;
	qstruct->hwadr[3] = 0xFF;
	qstruct->hwadr[4] = 0xFF;
	qstruct->hwadr[5] = 0xFF;
	qstruct->retries = ARP_MAXRETRY;
	qstruct->ttl = ARP_RESEND;
	arp_send_req( i );
	qstruct->state = ARP_PENDING;				/* Waiting for Reply	*/
	
	return(0);

	
}


/** \brief Manage ARP cache periodically
 *	\ingroup periodic_functions
 * 	\author 
 *		\li Jari Lahti (jari.lahti@violasystems.com)
 *	\date 04.11.2001
 *	\warning
 *		\li Invoke this function periodically to ensure proper ARP
 *		cache behaviour
 *
 *	Iterate through ARP cache aging entries. If timed-out entry is found,
 *	remove it (dynamic address) or update it (static address). This function
 *	must be called periodically by the system.
 *
 */
void arp_manage (void)
{
	struct arp_entry *qstruct;
	UINT8 i,j;
	static UINT8 aenext=0;
	
	/* Check Timer before entering	*/
	
	if( check_timer(arp_timer) )
		return;
		
	init_timer( arp_timer, ARP_MANG_TOUT*TIMERTIC);
	
	/* DEBUGOUT("Managing ARP Cache\n\r"); */
	
	for( i=0; i<ARP_TSIZE; i++ ) {
		/* DEBUGOUT("."); */
	
		qstruct = &arp_table[aenext];
		
		j = aenext;
		
		/* Take next entry next time	*/
				
		aenext++;
		if(aenext >= ARP_TSIZE)
			aenext = 0;	
	
		if( qstruct->state == ARP_FREE )
			continue;
			
		/* TODO: How about ARP_RESERVED?	*/
			
		if( qstruct->ttl > 0 )				/* Aging		*/
			qstruct->ttl --;
		
		if( qstruct->ttl == 0 )	{			/* Timed Out?	*/
			/* Do it for temporay entries	*/
			
			ARP_DEBUGOUT("Found Timed out Entry..\n\r");
		
			if( qstruct->type == ARP_TEMP_IP ) {

				/* Release it?	*/
				if( qstruct->state == ARP_RESOLVED ) {	
					ARP_DEBUGOUT("Releasing ARP Entry..\n\r");
					qstruct->state = ARP_FREE;
					continue;
				}
				
				/* Decrease retries left	*/
				
				if( qstruct->retries > 0 )	
					qstruct->retries--;
				
				if( qstruct->retries == 0 )	{
					ARP_DEBUGOUT("ARP Replies Used up, releasing entry..\n\r");
					qstruct->state = ARP_FREE;
					continue;
				}
				
				/* So we need to resend ARP request	*/
				
				ARP_DEBUGOUT("Trying to Resolve dynamic ARP Entry..\n\r");
			
				qstruct->ttl = ARP_RESEND;
				arp_send_req( j );
				qstruct->state = ARP_PENDING;				/* Waiting for Reply	*/			
				
				return;
			
			}
		
			/* Do it for Static Entries			*/
		
			if( qstruct->type == ARP_FIXED_IP ) {
				
				/* So we need to resend ARP request	*/
				
				/* Do not try to refresh broadcast	*/
				
				if(qstruct->pradr == IP_BROADCAST_ADDRESS) 	{
					qstruct->ttl = ARP_TIMEOUT;
					continue;
				}
				
				ARP_DEBUGOUT("Refreshing Static ARP Entry..\n\r");
				
				if( qstruct->retries > 0 )	
					qstruct->retries--;
				
				if( qstruct->retries == 0 )
					qstruct->state = ARP_PENDING;
				else
					qstruct->state = ARP_REFRESHING;
			
				qstruct->ttl = ARP_RESEND;
				
				arp_send_req( j );
				
				return;
			
			}
		
		}
	
	}


}



/** \brief Initialize data structures for ARP processing
 *	\ingroup core_initializer
 * 	\author 
 *		\li Jari Lahti (jari.lahti@violasystems.com)
 *	\date 01.11.2001
 *	\warning 
 *		\li Invoke this function at start-up to properly initialize
 *		ARP cache subsystem.
 *
 *	Call this function to properly initialize ARP cache table and so that
 *	ARP allocates and initializes a timer for it's use.
 */
void arp_init (void)
{
	struct arp_entry *qstruct;
	INT8 i;
	
	ARP_DEBUGOUT("Initializing ARP");
	
	for( i=0; i<ARP_TSIZE; i++ ) {
		qstruct = &arp_table[i];
		
		qstruct->state = ARP_FREE;
		qstruct->type = ARP_TEMP_IP;
		
		ARP_DEBUGOUT(".");
	}
	
	arp_timer = get_timer();
	init_timer(arp_timer, ARP_MANG_TOUT*TIMERTIC);

	/* set broadcast entry	*/
	
	qstruct = &arp_table[0];
	qstruct->pradr = IP_BROADCAST_ADDRESS;
	qstruct->state = ARP_RESOLVED;
	qstruct->type = ARP_FIXED_IP;
	qstruct->ttl = ARP_TIMEOUT;
	qstruct->retries = ARP_MAXRETRY;	
	
	for(i=0; i<MAXHWALEN; i++)
		qstruct->hwadr[i] = 0xFF;							
	
	ARP_DEBUGOUT("\n\r");
	
}
/** \brief Checks if a given IP address belongs to the subnet of a
 		given machine
 * 	\author 
 *		\li Jari Lahti (jari.lahti@violasystems.com)
 *	\date 05.11.2001
 *	\param ipadr - IP address under check
 *	\param machine - pointer to configuration of network parameters used
 *	\return
 *		\li #TRUE - ipadr belongs to subnet of given machine
 *		\li #FALSE - ipadr is NOT a part of subnet of given machine 
 *
 *	Based on information supplied in ipadr and machine parameters this
 *	function performs basic check if IP address is on the same subnet as
 *	the one defined for the machine. 
 *
 */
BYTE is_subnet (LWORD ipadr, struct netif* machine)
{

	UINT32 ltemp;

	ltemp = ipadr & machine->netmask;						/* Get Subnet part	*/
	
	ltemp ^= (machine->localip & machine->netmask);			/* Compare to my IP	*/
	
	if( ltemp )
		return(FALSE);
	
	return(TRUE);

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -