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

📄 arp.c

📁 51单片机加rt8019硬件平台,上web方案及详细代码
💻 C
字号:
//--------------------------arp.c-------------------
//#define DEBUG          

#include<string.h>
#include "includes.h" 

uchar code broadcast_macaddr[6]={0xff,0xff,0xff,0xff,0xff,0xff,};
/*****************************************
ARP初始化
*****************************************/
void init_arp(void)
{
	memset(arp_cache, 0, sizeof(arp_cache)); 
	memset(&wait, 0, sizeof(wait));
	waiting_for_arp = FALSE;

//	myipaddr  =  0xc0a800f3;//192.168.0.243
//	mygateway =  0xc0a80065;//192.168.0.101
	myipaddr  =  0xc0a801f3;//192.168.1.243
	mysubnet  =  0xffffff00;
	mygateway =  0xc0a80101;//192.168.1.1
	mymac[0]  =  0x00;
	mymac[1]  =  0x00;
	mymac[2]  =  0x00;
	mymac[3]  =  0x00;
	mymac[4]  =  0x12;
	mymac[5]  =  0x34; 
}
/*****************************************
老化ARP缓存
*****************************************/
void age_arp_cache(void)
{
 	uchar data i;
    	
   for (i=0; i < CACHESIZE; i++)
   {
      if ((arp_cache[i].ipaddr != 0) && (arp_cache[i].timer) && (arp_cache[i].type == 0))
      {
         arp_cache[i].timer--; 		
		 if (arp_cache[i].timer == 0)			
			arp_cache[i].ipaddr = 0; 			
	  }
   }
}
/*****************************************
更新ARP缓存
*****************************************/
uchar arp_updata(ulong ipaddr, uchar * macaddr)
{
	uchar i;

	for (i=0; i < CACHESIZE; i++) // 更新ARP缓存
	{
      if (arp_cache[i].ipaddr == ipaddr)
      {
         memcpy(&arp_cache[i].macaddr[0], macaddr, 6);
         arp_cache[i].timer = CACHETIME;         		                   
         return(1);  
       }
    }
	return(0);
}
/*****************************************
ARP学习
*****************************************/
void arp_study(ulong ipaddr, uchar * macaddr)
{
	uchar i,minitime,oldest;

	minitime = 0xff;
	for (i=0; i < CACHESIZE; i++)
	{
		if (arp_cache[i].ipaddr == 0) 
		{
			arp_cache[i].ipaddr = ipaddr;
            memcpy(&arp_cache[i].macaddr[0], macaddr, 6);   
            arp_cache[i].timer = CACHETIME;
         	return;
		}
	}
	
	if(i >= CACHESIZE)
	{
		for (i=0; i < CACHESIZE; i++)
      	{
			if (arp_cache[i].timer < minitime) 
			{
				minitime = arp_cache[i].timer;
				oldest = i;
			}
		}			
		arp_cache[oldest].ipaddr = ipaddr;
        memcpy(&arp_cache[oldest].macaddr[0], macaddr, 6);   
        arp_cache[oldest].timer = CACHETIME; 
	}
			
}
/*****************************************
重发ARP请求,超时后放弃
*****************************************/
void arp_resend(void)
{
	static uchar idata retries = 0; 
	
	if ((waiting_for_arp) && (wait.timer))
	{
		wait.timer--;
		if (wait.timer == 0)
		{
			retries++;
			if (retries <= 2) //重发两次
			{
	 			arp_send(outbuf,NULL, wait.ipaddr, ARP_REQUEST);  //重发ARP请求
            TRACE("ARP TIMEOUT RESEND",NULL,0,0);
				wait.timer = ARP_TIMEOUT;
			}
			else
			{
	 			retries=0;
				wait.timer = 0;
				KillTimer(ARP_RESEND);
				waiting_for_arp = FALSE;
				clean_buf(outbuf,MAXBUF);
			}
		}
	}
}
/*****************************************
发送28byteARP请求/应答
*****************************************/
void arp_send(uchar xdata * outbuf,uchar * macaddr, ulong ipaddr, uchar msg_type)
{ 
	Arp_Header xdata * arp;      
   
	arp = (Arp_Header xdata *)(outbuf + 14);

	arp->hardware_type = 1; 
	arp->protocol_type = IP_PACKET;
	arp->macaddr_len = 6;
	arp->ipaddr_len = 4;               
	arp->message_type = (uint)msg_type;   
	//源MAC和IP
	memcpy(arp->source_macaddr, mymac, 6);
	arp->source_ipaddr = myipaddr;  
	// 目的MAC和IP
	if (msg_type == ARP_REQUEST) 
	{
		memset(arp->dest_macaddr, 0, 6); //arp请求目的MAC清零
	}
	else
	{
		memcpy(arp->dest_macaddr, macaddr, 6); //arp应答要填充MAC
	}   
    arp->dest_ipaddr = ipaddr;     
 
	if (msg_type == ARP_REQUEST)
	{ 
		eth_send(outbuf, broadcast_macaddr, ARP_PACKET, 28); //arp请求目的MAC为广播		 
	}
	else 
	{
		eth_send(outbuf, macaddr, ARP_PACKET, 28); 
		TRACE("T: ARP_RESPONSE TO ",CP &ipaddr,4,0);  
	}
}

/*****************************************
根据IP地址搜索MAC地址,若非本地网则发向网关
若缓存里没有目的IP或网关的IP则发送ARP请求
*****************************************/
uchar * arp_search(ulong dest_ipaddr)
{
   uchar data i;     
   
	if ((dest_ipaddr ^ myipaddr) & mysubnet)//非同一网段
	{
		if (mygateway == 0)		
			return (NULL);	 	
	 	else dest_ipaddr = mygateway;
	} 	   
   
	for (i=0; i < CACHESIZE; i++)
	{
		if (arp_cache[i].ipaddr == dest_ipaddr)
		{
			return (&arp_cache[i].macaddr[0]);
		}
	}
	TRACE("ARP SEARCH FAIL SEND ARP_REQUEST",NULL,0,0);  	

	return (NULL); 
}
/*****************************************
ARP包处理
*****************************************/
void arp_receive(uchar xdata * inbuf)
{
	uchar  cached;
	Arp_Header xdata * arp;     
 
	arp = (Arp_Header xdata *)(inbuf + 14);
	cached = FALSE;         
   
	if ((arp->hardware_type != 1) || (arp->protocol_type != IP_PACKET)) // 判断是否为有效帧
		return;	      
  
	cached	= arp_updata(arp->source_ipaddr, &arp->source_macaddr[0]);//判断是否更新过
   
	if (arp->dest_ipaddr != myipaddr) 
	{
		TRACE("arp->dest_ipaddr",CP &arp->dest_ipaddr,4,0);
		TRACE("myipaddr = ",CP &myipaddr,4,0);
		return;    
	}

	if (cached == FALSE)	      
		arp_study(arp->source_ipaddr, &arp->source_macaddr[0]);//学习	   

	if (arp->message_type == ARP_RESPONSE) //收到ARP应答
	{  
		TRACE("R: ARP_RESPONSE FROM ",CP &arp->source_ipaddr,4,0);
        
		if ((waiting_for_arp) && (wait.ipaddr == arp->source_ipaddr)) //收到所请求的ARP数据
		{
  			KillTimer(ARP_RESEND);
			waiting_for_arp = FALSE;
		  	ip_send(wait.buf, wait.ipaddr, wait.proto_id, wait.len); //发送因没有MAC未发出去的IP包         
			clean_buf( (uchar * )&wait,sizeof(Arp_Wait));
		}
	}
	
	else if (arp->message_type == ARP_REQUEST)//收到ARP请求
	{
		TRACE("R: ARP_REQUEST BY ",CP &arp->source_ipaddr,4,0);
		arp_send(outbuf,arp->source_macaddr, arp->source_ipaddr, ARP_RESPONSE);	//发送应答 	
	}
}

⌨️ 快捷键说明

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