?? 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 + -