2、ARP的處理程序
ARP協(xié)議原理很簡單,下面我們來編寫ARP協(xié)議的處理函數(shù)。新建文件命名為arp.c,填寫如下函數(shù)
:
unsigned char mac_addr[6] = {*,*,*,*,*,*};
unsigned char ip_addr[4] = { 192, 168, *, * };
unsigned char host_ip_addr[4] = { 192, 168, *, * };
unsigned char host_mac_addr[6]={ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
unsigned char Buffer[1000];
uint16 packet_len;
#define HON(n) ((((uint16)((n) & 0xff)) << 8) | (((n) & 0xff00) >> 8))
void arp_request(void) //發(fā)送ARP請求數(shù)據(jù)包
{
//以太網(wǎng)首部
memcpy(ARPBUF->ethhdr.d_mac, host_mac_addr, 6);
memcpy(ARPBUF->ethhdr.s_mac, mac_addr, 6);
ARPBUF->ethhdr.type = HON( 0x0806 );
//ARP首部
ARPBUF->hwtype = HON( 1 );
ARPBUF->protocol = HON( 0x0800 );
ARPBUF->hwlen = 6;
ARPBUF->protolen = 4;
ARPBUF->opcode = HON( 0 );
memcpy(ARPBUF->smac, mac_addr, 6);
memcpy(ARPBUF->sipaddr, ip_addr, 4);
memcpy(ARPBUF->dipaddr, host_ip_addr, 4);
packet_len = 42;//14+28=42
sendpacket( Buffer, packet_len );
}
注釋:ARPBUF的宏定義和ARP首部結(jié)構(gòu),在前面已經(jīng)講過。同時注意執(zhí)行該函數(shù)時中斷的處理。這里沒
作處理。
看上去很easy吧,下面函數(shù)實現(xiàn)接收ARP請求或接收ARP應(yīng)答的處理。
unsigned char arp_process(void)//ARP接收函數(shù),成功返回1,否則返回0
{
//簡單判斷ARP數(shù)據(jù)包有無損壞,有損壞則丟棄,不予處理
if( packet_len < 28 )//ARP數(shù)據(jù)長度為28字節(jié)為無效數(shù)據(jù)
{
return 0;
}
switch ( HON( ARPBUF->opcode ) )
{
case 0: //處理ARP請求
if( ARPBUF->dipaddr[0] == ip_addr[0] &&
ARPBUF->dipaddr[1] == ip_addr[1] &&
ARPBUF->dipaddr[2] == ip_addr[2] &&
ARPBUF->dipaddr[3] == ip_addr[3] )//判斷是否是自己的IP,是否向自己詢問MAC地址
。
{
ARPBUF->opcode = HON( 2 );//設(shè)置為ARP應(yīng)答
memcpy(ARPBUF->dmac, ARPBUF->smac, 6);
memcpy(ARPBUF->ethhdr.d_mac, ARPBUF->smac, 6);
memcpy(ARPBUF->smac, mac_addr, 6);
memcpy(ARPBUF->ethhdr.s_mac, mac_addr, 6);
memcpy(ARPBUF->dipaddr, ARPBUF->sipaddr, 4);
memcpy(ARPBUF->sipaddr, ip_addr, 4);
ARPBUF->ethhdr.type = HON( 0x0806 );
packet_len = 42;
sendpacket( Buffer, packet_len );//發(fā)送ARP數(shù)據(jù)包
return 1;
}
else
{
return 0;
}
break;
case 1: //處理ARP應(yīng)答
if( ARPBUF->dipaddr[0] == ip_addr[0] &&
ARPBUF->dipaddr[1] == ip_addr[1] &&
ARPBUF->dipaddr[2] == ip_addr[2] &&
ARPBUF->dipaddr[3] == ip_addr[3] )//再次判斷IP,是否是給自己的應(yīng)答
{
memcpy(host_mac_addr, ARPBUF->smac, 6);//保存服務(wù)器MAC地址
return 1;
}
else
{
return 0;
}
break;
default://不是ARP協(xié)議
return 0;
}
}
根據(jù)ARP協(xié)議格式看這兩個函數(shù)并不困難。于是我們又得到兩個函數(shù):arp_request()和
arp_process()。
3、ARP程序調(diào)試
下面我們修改主函數(shù)和中斷處理函數(shù)。
將mian()函數(shù)中的“sendpacket(60);”語句換成“arp_request();”語句。
void int_issue(void) //中斷處理函數(shù),需要根據(jù)自己的處理器進行設(shè)置
{
unsigned int i;
i = receivepacket(Buffer);//將數(shù)據(jù)讀取到Buffer中。
if(i == 0)
{
return;
}
else
{
i = arp_process();
if(i == 1)//判斷是否是ARP協(xié)議
print_hostmacaddr();//打印目標機的MAC地址,就是用串口打印host_mac_addr[]中的6
個字節(jié)
}
}
保存運行調(diào)試。
圖7 主機MAC地址
至此,關(guān)于DM9000的調(diào)試過程就完成了。之后我還調(diào)試了UDP通訊、TCP通訊等,主要是關(guān)于協(xié)議的
處理了,這里就不介紹了。有興趣的朋友可以參看《TCP/IP協(xié)議》第一卷,將會有很大幫助。希望這些
調(diào)試過程能為讀者或多或少的提供些有用的信息,也歡迎大家和我一起討論
評論