www.pudn.com > TcpIpOn8051.rar > ARP.C


/*------------------------------------------------------------------------------ 
myarp.C   small arp implement 
 
Copyright 1995-1999 Keil Software, Inc. 
------------------------------------------------------------------------------*/ 
#include "public.h" 
#include "ether.h" 
#include "arp.h" 
extern bit user_flag1; 
extern BYTE user_count1; 
 
arp_entry xdata arp_gate;      //默认网关 
arp_entry xdata arp_table[10]; //arp表 
 
void arp_init(); 
BYTE arp_lookup(ip *ipaddr); 
BYTE arp_look_oldest(void); 
void arp_update_index(BYTE index); 
void arp_update_table(BYTE index,ip *ipaddr,WORD *hwaddr); 
void arp_request(ip *destip); 
void arp_reply(arpheader *arpreply); 
void arp_update(ip *ipaddr,WORD *macaddr); 
bit arp_deal_pack(netcard *netbuf); 
 
extern mycomp xdata mypara;				//arp使用情况标志 
extern bit recv_packet(netcard *rxdnet); 
extern void send_packet(netcard *txdnet,WORD length); 
extern void ip_updatebuf(ip destip); 
 
/*---------------------------------- 
 arp初始化函数,主要是初始化地址表 
 ----------------------------------*/ 
void arp_init(void) 
{ 
	register BYTE i; 
        for(i=0;i<10;i++) 
        { 
	        arp_table[i].ip_addr=0; 
            arp_table[i].hw_addr[0]=0; 
            arp_table[i].hw_addr[1]=0; 
            arp_table[i].hw_addr[2]=0; 
            arp_table[i].arp_flag=255; 
        } 
    arp_gate.arp_flag=255; 
} 
/*---------------------------------- 
 arp table update ttl 
 ----------------------------------*/ 
void arp_ttlup(void) 
{ 
	register BYTE i; 
	for(i=0;i<9;i++) 
	{ 
		if(arp_table[i].arp_flag!=255) arp_table[i].arp_flag++; 
		if(arp_gate.arp_flag!=255) arp_gate.arp_flag++; 
	} 
} 
/*------------------------------------------------------------ 
   从表里查找对应ip的mac地址,成功则返回对应的下标;失败返回10 
-------------------------------------------------------------*/ 
 
BYTE arp_lookup(ip *ipaddr) 
{ 
register BYTE i; 
for(i=0;i<10;i++){ 
	if(arp_table[i].ip_addr==*ipaddr && arp_table[i].arp_flag!=255) {return i;} 
        } 
return i; 
} 
/*---------------------------------- 
 查找应该被替换掉的表项,返回下标 
 ----------------------------------*/ 
BYTE arp_look_oldest(void) 
{ 
register BYTE i; 
BYTE max=0; 
for(i=0;i<10;i++){ 
	if(arp_table[i].arp_flag==255) {return i;} 
	else{ 
		if(arp_table[i].arp_flag>arp_table[max].arp_flag){max=i;} 
	} 
} 
return max; 
} 
/*------------------------------------ 
 比对应标号值小的加一,对应标号的置零 
 -----------------------------------*/ 
void arp_update_index(BYTE index){ 
register BYTE i; 
for(i=0;i<10;i++){ 
	if(arp_table[i].arp_flag<=arp_table[index].arp_flag) 
	{ 
		if(arp_table[i].arp_flag<255) 
		arp_table[i].arp_flag++;} 
	} 
arp_table[index].arp_flag=0; 
} 
/*------------------------------------------------------------ 
  将新的对应关系存入arp表,与上面的函数结合使用,不可单独使用 
------------------------------------------------------------ */ 
void arp_update_table(BYTE index,ip *ipaddr,WORD *hwaddr) 
{ 
arp_table[index].ip_addr=*ipaddr; 
arp_table[index].hw_addr[0]=hwaddr[0]; 
arp_table[index].hw_addr[1]=hwaddr[1]; 
arp_table[index].hw_addr[2]=hwaddr[2]; 
} 
/*--------------------------------- 
生成对相应ip的ARP请求包,并发送 
----------------------------------*/ 
void arp_request(ip *destip){ 
arpheader xdata arptemp;//arp数据 
 
netcard *txdnet;//发送的以太网数据指针 
netcard xdata sen; 
WORD txdlength=0x2a; 
register BYTE i; 
arptemp.arpframe.hardwaretype=HWTYPE;								//将arp数据封装 
arptemp.arpframe.ptype=PTYPE; 
arptemp.arpframe.haddrlength=HWADDRLEN; 
arptemp.arpframe.paddrlength=PTADDRLEN; 
arptemp.arpframe.operate=ARP_REQUEST; 
 
arptemp.arpframe.srcaddr[0]=mypara.mynodeid[0].word; 
arptemp.arpframe.srcaddr[1]=mypara.mynodeid[1].word; 
arptemp.arpframe.srcaddr[2]=mypara.mynodeid[2].word; 
arptemp.arpframe.srcip=mypara.myip; 
arptemp.arpframe.destaddr[0]=0x0000; 
arptemp.arpframe.destaddr[1]=0x0000; 
arptemp.arpframe.destaddr[2]=0x0000; 
arptemp.arpframe.destip=*destip; 
//加入以太网帧 
txdnet=&sen; 
txdnet->etherframe.length=txdlength; 
txdnet->etherframe.destnodeid[0]=0xffff; 
txdnet->etherframe.destnodeid[1]=0xffff;//目的地址 
txdnet->etherframe.destnodeid[2]=0xffff; 
txdnet->etherframe.protocal=ARPTYPE;//协议类型 
for(i=0;i<28;i++) 
      txdnet->etherframe.packet[i]=arptemp.bytes.bytebuf[i]; 
//for(i=28;i<46;i++) 
//      txdnet->etherframe.packet[i]=0; 
 
send_packet(txdnet,txdlength);//发送arp包 
} 
 
/*--------------------------------- 
生成对相应ip的ARP应答包,并发送 
----------------------------------*/ 
void arp_reply(arpheader *arpreply){								//生成对相应ARP应答包,并发送 
netcard *txdnet;//发送的以太网数据指针 
netcard xdata sen; 
WORD txdlength=60; 
register BYTE i; 
ip  iptemp;          //临时变量,用于目的和发送端地址对调 
arpreply->arpframe.operate=ARP_REPLY;//应答包类型 
 
arpreply->arpframe.destaddr[0]=arpreply->arpframe.srcaddr[0]; 
arpreply->arpframe.destaddr[1]=arpreply->arpframe.srcaddr[1]; 
arpreply->arpframe.destaddr[2]=arpreply->arpframe.srcaddr[2]; 
arpreply->arpframe.srcaddr[0]=mypara.mynodeid[0].word; 
arpreply->arpframe.srcaddr[1]=mypara.mynodeid[1].word; 
arpreply->arpframe.srcaddr[2]=mypara.mynodeid[2].word; 
//交换目和发送端ip 
iptemp=arpreply->arpframe.srcip; 
arpreply->arpframe.srcip=arpreply->arpframe.destip; 
arpreply->arpframe.destip=iptemp; 
 
//加入以太网帧 
txdnet=&sen; 
txdnet->etherframe.length=txdlength; 
txdnet->etherframe.destnodeid[0]=arpreply->arpframe.destaddr[0]; 
txdnet->etherframe.destnodeid[1]=arpreply->arpframe.destaddr[1];  //目的地址 
txdnet->etherframe.destnodeid[2]=arpreply->arpframe.destaddr[2]; 
txdnet->etherframe.protocal=ARPTYPE;//协议类型 
for(i=0;i<28;i++) 
      txdnet->etherframe.packet[i]=arpreply->bytes.bytebuf[i]; 
for(i=28;i<46;i++) 
      txdnet->etherframe.packet[i]=0; 
 
send_packet(txdnet,txdlength);//发送arp包 
} 
/*------------------------------------------------- 
ip包查表或插入最新对应关系,表里有数据返回对应下标,没有返回0xff 
输入参数:ip地址,mac地址,若为查询,则mac地址对应为0,flag=0 
更新flag=1 
--------------------------------------------------*/ 
void arp_update(ip *ipaddr,WORD *macaddr) 
{ 
        BYTE arp_flag=10; 
        //register BYTE i; 
        //bit revb; 
        bit revsec=0; 
        //ip xdata tempip; 
        //netcard xdata revbuf; 
 
        arp_flag=arp_lookup(ipaddr); 
        if(arp_flag>9){ 
              arp_flag=arp_look_oldest(); 
        } 
        arp_update_table(arp_flag,ipaddr,macaddr);//更新表(有重复ip) 
        arp_update_index(arp_flag);               //更新标志 
} 
/*--------------------------------- 
arp包处理 
----------------------------------*/ 
bit arp_deal_pack(netcard *netbuf){ 
	bit update_flag; 
	BYTE pcol; 
	arpheader *arp_sev; 
 
	arp_sev=(arpheader *)&netbuf->etherframe.packet; 
	update_flag=0; 
    //WORD xdata macaddrt; 
	if(arp_sev->arpframe.hardwaretype!=HWTYPE|| 
                arp_sev->arpframe.ptype!=PTYPE|| 
                arp_sev->arpframe.destip!=mypara.myip) 
                return update_flag;  //包错误返回 
	else{ 
		pcol=arp_sev->arpframe.operate; 
		if(pcol==ARP_REQUEST && 
                arp_sev->arpframe.destip==mypara.myip) //若为arp请求包 
        { 
              	arp_reply(arp_sev); 
		}                       //发送arp应答 
 
		if(pcol==ARP_REPLY){//对应答包进行处理 
                if(arp_sev->arpframe.destip==mypara.myip) 
                { 
                             //网关物理地址 
                            if(arp_sev->arpframe.srcip==mypara.mygate) 
                            { 
                                    arp_gate.hw_addr[0]=arp_sev->arpframe.srcaddr[0]; 
                                    arp_gate.hw_addr[1]=arp_sev->arpframe.srcaddr[1]; 
                                    arp_gate.hw_addr[2]=arp_sev->arpframe.srcaddr[2]; 
									arp_gate.arp_flag=1; 
                       		} 
                             //更新arp表(只有发给自己的arp应答包才更新) 
		             		else { 
								arp_update(&(arp_sev->arpframe.srcip),&arp_sev->arpframe.srcaddr[0]); 
							} 
							update_flag=1; 
							ip_updatebuf(arp_sev->arpframe.srcip); 
							//look souce ip,look ip send buffer 
         		} 
		} 
		return update_flag; 
	} 
} 
 
/*EOF*/