📄 arp.c
字号:
/*
*****************************************************************************************************
*
* File name: arp.c
*****************************************************************************************************
*/
#include "..\head\includes.h"
#define MaxLenARPtable 10 //ARP表长度
xdata union arp_table_type arp_tab[MaxLenARPtable]; //ARP表,存在外部RAM区里
unsigned char index=0; //ARP table 循环加入点
/*
*****************************************************************************************************
*FUNC: 向指定的IP地址发送一个ARP请求
*NOTE:
*****************************************************************************************************
*/
void ArpRequest(union IP_address ip_address)//ARP请求
{
unsigned char i;
txdnet.etherframe.protocal=0x0806; //arp protocal
for (i=0; i<3; i++) { //复制对方网卡地址或网关地址
txdnet.etherframe.uDestID[i] = 0xffff; //IP广播地址
txdnet.etherframe.uSourceID[i] = my_ethernet_address.words[i]; //指定以太网数据包首部中的源MAC地址
txdnet.arpframe.sourcenodeid[i] = my_ethernet_address.words[i];
txdnet.arpframe.destnodeid[i] = 0x0000; //此时目的MAC未知,填0
}
for (i=0;i<2;i++) {
txdnet.arpframe.sourceip[i] = my_ip_address.words[i]; //我的IP
}
txdnet.arpframe.destip[0]=ip_address.words[0]; //目标IP
txdnet.arpframe.destip[1]=ip_address.words[1];
txdnet.arpframe.harewaretype=0x0001; //1即表示以太网地址
txdnet.arpframe.protocaltype=0x0800;
txdnet.arpframe.halength=0x06;
txdnet.arpframe.palength=0x04;
txdnet.arpframe.operation=0x0001; //ARP请求
for(i=0x2E; i<(0x2E+18); i++) { //不足60补0
txdnet.bytes.bytebuf[i]=0x00;
}
send_packet(&txdnet,60);
}
/*
*****************************************************************************************************
*FUNC: 收到一个ARP应答后,对ARP表进行处理
*NOTE: void ArpRequest(union IP_address ip_address)//ARP请求的应答处理
*****************************************************************************************************
*/
void ArpEcho(void) //ARP应答处理
{
unsigned char i,j;
unsigned char processed=FALSE;
//其中的状态字段表示该ARP记录是否已经被占用.1表示占用,0表示未占用
//当状态为1时,需要对表进行搜索,对表进行更新.显然,当收到一个新的ARP
//包后,首先需要处理的是该ARP记录是否在表中,如果是,则进行更新;否则添
//加该记录
//对表进行搜索,确定是否需要更新
for (i=0; i<MaxLenARPtable; i++) {
if (arp_tab[i].arp.status == 1) {
if ((arp_tab[i].arp.ip_address.words[0] == rxdnet.arpframe.sourceip[0])
&& (arp_tab[i].arp.ip_address.words[1]==rxdnet.arpframe.sourceip[1])) //判断该记录是否已存在
{
arp_tab[i].arp.ttl = 0x80; //已存在,就更新它
for (j=0; j<2; j++) {
arp_tab[i].arp.ip_address.words[j]=rxdnet.arpframe.sourceip[j];
}
for (j=0; j<3; j++) {
arp_tab[i].arp.ethernet_address.words[j]=rxdnet.arpframe.sourcenodeid[j];
}
processed=TRUE; //已处理更新标志
break;
}
}
}
if (!processed) { //未处理
for (i=0; i<MaxLenARPtable; i++) { //添加一条记录
if (arp_tab[i].arp.status == 0) {
arp_tab[i].arp.status = 1;
arp_tab[i].arp.ttl = 0x80;
for (j=0; j<2; j++) {
arp_tab[i].arp.ip_address.words[j]=rxdnet.arpframe.sourceip[j];
}
for(j=0; j<3; j++) {
arp_tab[i].arp.ethernet_address.words[j]=rxdnet.arpframe.sourcenodeid[j];
}
processed=TRUE; //已添加标志
break;
}
}
}
if (!processed) { //未更新,未添加,说明表满
arp_tab[index].arp.status = 1; //表满处理.其中index为全局变量,循环更新ARP表
arp_tab[index].arp.ttl = 0x80;
for (j=0; j<2; j++) {
arp_tab[index].arp.ip_address.words[j]=rxdnet.arpframe.sourceip[j];
}
for (j=0; j<3; j++) {
arp_tab[index].arp.ethernet_address.words[j]=rxdnet.arpframe.sourcenodeid[j];
}
if (++index == MaxLenARPtable) {
index = 0;
}
}
if ((arpwait.wait_arp == TRUE) && (arpwait.ipaddr.words[0] == rxdnet.arpframe.sourceip[0])
&& (arpwait.ipaddr.words[1] == rxdnet.arpframe.sourceip[1])) { //有数据在等待ARP,发送
arpwait.wait_arp = FALSE;
ip_send(arpwait.buf, arpwait.ipaddr, arpwait.proto_id, arpwait.len);
}
}
/*
*****************************************************************************************************
*FUNC: 对ARP请求进行应答
*NOTE:
*****************************************************************************************************
*/
void ArpAnswer(void)
{
unsigned char i;
if (rxdnet.arpframe.destip[0]==my_ip_address.words[0])
if (rxdnet.arpframe.destip[1]==my_ip_address.words[1]) { //表示是向我这个ip地址的请求
for (i=16; i<64; i++) { //复制arp到发送缓冲区
txdnet.bytes.bytebuf[i]=rxdnet.bytes.bytebuf[i];
}
for (i=0; i<3; i++) { //复制对方网卡地址或网关地址
txdnet.etherframe.uDestID[i] = rxdnet.etherframe.uSourceID[i];
txdnet.etherframe.uSourceID[i]=my_ethernet_address.words[i]; //指定以太网数据包首部中的源MAC地址
txdnet.arpframe.sourcenodeid[i]=my_ethernet_address.words[i];
txdnet.arpframe.destnodeid[i]=rxdnet.arpframe.sourcenodeid[i];
}
for (i=0; i<2; i++) {
txdnet.arpframe.destip[i] = rxdnet.arpframe.sourceip[i];
txdnet.arpframe.sourceip[i] = rxdnet.arpframe.destip[i];
}
txdnet.arpframe.operation=0x0002; //ARP响应代码
send_packet(&txdnet,60);
}
}
/*
*****************************************************************************************************
*FUNC: 初始化ARP缓存
*NOTE:
*****************************************************************************************************
*/
void InitArpTable(void)
{
unsigned char i,j;
for (i=0; i<MaxLenARPtable; i++) {
arp_tab[i].arp.status=0;
arp_tab[i].arp.ttl=0;
for (j=0; j<4; j++) {
arp_tab[i].arp.ip_address.bytes[j]=0;
}
for (j=0; j<6; j++) {
arp_tab[i].arp.ethernet_address.bytes[j]=0;
}
}
}
/*
*****************************************************************************************************
*FUNC: 更新ARP缓存
*NOTE: 每1s调用一次
*****************************************************************************************************
*/
void UpdateArpTab()
{
unsigned char i;
for (i=0; i<MaxLenARPtable; i++) {
if (arp_tab[i].arp.status == 1) {
if (arp_tab[i].arp.ttl > 0) { //生存时间
arp_tab[i].arp.ttl--;
} else {
arp_tab[i].arp.status=0;
}
}
}
}
/*
*****************************************************************************************************
*FUNC:在ARP缓存中查找指定IP/MAC映射对
*NOTE: 入参: 指定的IP地址,返回MAC地址的指针
返回值: bit类型.如果找到,则返回1;找不到则返回0.
*****************************************************************************************************
*/
bit FindMac(union IP_address ip,union Ethernet_address xdata *macadr)
{
unsigned char i,j;
for (i=0; i<MaxLenARPtable; i++){
if (arp_tab[i].arp.status == 1) {
if(arp_tab[i].arp.ip_address.dwords == ip.dwords){
for(j=0; j<3; j++) {
macadr->words[j]=arp_tab[i].arp.ethernet_address.words[j];
}
return 1;
}
}
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -