📄 arp.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 + -