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*/