arp.c
来自「ARP协议,含ARP」· C语言 代码 · 共 390 行
C
390 行
#include "arp.h"
#include "typedef.h"
#include "tick.h"
#include "string.h"
#include "stdio.h"
#include "mem.h"
#include "eth.h"
#include "cfg.h"
#include "string.h"
#define ARP_ITEM_NUM 3
#define ARP_HARD_TYPE 0x0100 //ARP包硬件类型 以太网0x0100
#define ARP_PROT_TYPE 0x0008 //ARP协议类型
#define ARP_OP_REQ 0x0100
#define ARP_OP_RES 0x0200
#define ARP_NULL 0
#define ARP_WAIT 1
#define ARP_WORK 4
#define ARP_WORK_OUT 7200
#define ARP_WAIT_OUT 60
#define ARP_QEQUEST_COUNT 10
struct _arp_item arp_items[ARP_ITEM_NUM];
void arp_recv_message(uc * msg)
{
struct _eth_arp *p;
p=(struct _eth_arp *)msg;
if(ARP_OP_REQ==p->op)
{
//请求处理
//ARP类型为响应类型
p->op=ARP_OP_RES;
//以太网头部填充
cfg_get_mac_addr(p->src_mac);
memcpy(p->dst_mac,p->src_mac,MAC_ADDR_LEN);
//将接收到的ARP包的源IP、MAC赋给要发送的ARP Response包的目的IP、MAC
memcpy(p->dst_ip_addr,p->src_ip_addr,IP_ADDR_LEN);
memcpy(p->dst_mac_addr,p->src_mac_addr,MAC_ADDR_LEN);
//填充以太网的源IP和源MAC地址
cfg_get_mac_addr(p->src_mac_addr);
cfg_get_src_addr(p->src_ip_addr);
arp_send_response(p);
}
if(ARP_OP_RES==p->op)
{
//响应处理
uc pid;
struct _arp_item *p_temp;
if(arp_find_ip(p->src_ip_addr,&pid))
{
p_temp=&(arp_items[pid]);
if(ARP_WAIT==p_temp->state)
{
p_temp->state=ARP_WORK;
p_temp->timer=ARP_WORK_OUT;
memcpy(p_temp->mac_addr,p->src_mac,MAC_ADDR_LEN);
}
else{}
}
}
}
void arp_send_response(struct _eth_arp * p)
{
struct _mem_block *pm;
struct _eth_arp *p_arp;
if(NULL==(pm=(struct _mem_block *) alloc_mb()))
{
// printf("ARP_request处内存块分配失败");
return;
}
p_arp=(struct _eth_arp *)(pm->content);
//memcpy(p_arp->dst_mac,p->dst_mac,MAC_ADDR_LEN);
cfg_get_mac_addr(p_arp->dst_mac);
//memset(p_arp->dst_mac,0xFF,MAC_ADDR_LEN);
memcpy(p_arp->src_mac,p->src_mac,MAC_ADDR_LEN);
memcpy(p_arp->dst_mac_addr,p->dst_mac_addr,MAC_ADDR_LEN);
memcpy(p_arp->src_mac_addr,p->src_mac_addr,MAC_ADDR_LEN);
memcpy(p_arp->dst_ip_addr,p->dst_ip_addr,IP_ADDR_LEN);
memcpy(p_arp->src_ip_addr,p->src_ip_addr,IP_ADDR_LEN);
p_arp->frame_type=ETH_FRAME_ARP;
//填充ARP头部
p_arp->hard_type=ARP_HARD_TYPE;
p_arp->prot_type=ARP_PROT_TYPE;
p_arp->hard_addr_len=MAC_ADDR_LEN;
p_arp->prot_addr_len=IP_ADDR_LEN;
p_arp->op=ARP_OP_RES;
pm->len=sizeof(struct _eth_arp);
eth_send_msg(pm);
free_msg(pm);
}
void arp_send_request(uc * ip_addr,uc * src_addr)
{
struct _mem_block *pm;
struct _eth_arp *p;
if(NULL==(pm=(struct _mem_block *)alloc_mb()))
{
// printf("ARP_request处内存块分配失败");
return;
}
p=(struct _eth_arp *)(pm->content);
//填充以太网头部
memset(p->dst_mac,0xFF,MAC_ADDR_LEN);//ARP请求目的MAC地址为广播
cfg_get_mac_addr(p->src_mac);
p->frame_type=ETH_FRAME_ARP;
//填充ARP头部
p->hard_type=ARP_HARD_TYPE;
p->prot_type=ARP_PROT_TYPE;
p->hard_addr_len=MAC_ADDR_LEN;
p->prot_addr_len=IP_ADDR_LEN;
p->op=ARP_OP_REQ;
cfg_get_mac_addr(p->src_mac_addr);
memset(p->dst_mac_addr,0,MAC_ADDR_LEN);
//memcpy(p->src_ip_addr,src_addr,
//cfg_get_src_addr(p->src_ip_addr);
memcpy(p->src_ip_addr,src_addr,IP_ADDR_LEN);
memcpy(p->dst_ip_addr,ip_addr,IP_ADDR_LEN);
pm->len=sizeof(struct _eth_arp);
eth_send_msg(pm);
free_msg(pm);
}
void arp_task(void)
{
struct _arp_item *p;
uc i;
// printf("这是ARP任务!\n");
//print_arp_items();
for(i=0;i<ARP_ITEM_NUM;i++)
{
p=&(arp_items[i]);
switch(p->state)
{
case ARP_WAIT:
if(0==p->timer)
{
//状态迁移到初始态
p->state=ARP_NULL;
}
else
{
if(0==p->count)
{
p->count=10;
uc src_ip_temp[4];
uc dst_ip_temp[4];
cfg_get_src_addr(src_ip_temp);
memcpy(dst_ip_temp,p->ip_addr,IP_ADDR_LEN);
arp_send_request(src_ip_temp,dst_ip_temp);
}
else
{
p->count--;
}
p->timer--;
}
case ARP_WORK:
if(0==p->timer)
{
p->state=ARP_NULL;
}
else
{
p->timer--;
}
case ARP_NULL:
default:;
}
}
}
void arp_tick(void)
{
static uc cnt=0;
cnt++;
if(cnt>=50)
{
cnt=0;
arp_task();
}
}
bool arp_find_ip(uc * ip_addr,uc *pidx)
{
struct _arp_item *p;
for(uc i=0;i<ARP_ITEM_NUM;i++)
{
p=&(arp_items[i]);
if(ARP_NULL==p->state)
{
continue;
}
if(cfg_same_ip(ip_addr,p->ip_addr))
{
*pidx=i;
return true;
}
}
return false;
}
us arp_item_age(struct _arp_item *p)
{
us age;
switch ( p->state )
{
case ARP_WAIT:
age=(ARP_WAIT_OUT-p->timer);
break;
case ARP_WORK:
age=(ARP_WORK_OUT-p->timer)+ARP_WAIT_OUT;
break;
case ARP_NULL:
default:
age=0x7FFF;
}
return age;
}
uc arp_find_empty_item(void)
{
struct _arp_item *p;
us max_age,age;
uc i,sel_i;
max_age=0;
sel_i=0;
for(i=0;i<ARP_ITEM_NUM;i++)
{
p=&(arp_items[i]);
if(ARP_NULL==p->state)
{
sel_i=i;
break;
}
age=arp_item_age(p);
if(age>max_age)
{
max_age=age;
sel_i=i;
}
}
memset(&(arp_items[sel_i]),0,sizeof(struct _arp_item));
return sel_i;
}
void arp_put_ip(uc index,uc * des_ip_addr)
{
struct _arp_item *p;
p=&(arp_items[index]);
memcpy(p->ip_addr,des_ip_addr,MAC_ADDR_LEN);
p->state=ARP_WAIT;
p->timer=ARP_WAIT_OUT;
p->count=ARP_QEQUEST_COUNT;
}
void init_arp_items(void)
{
uc ip[4];
uc mac[6];
ip[0]=192;
ip[1]=168;
ip[2]=2;
ip[3]=1;
mac[0]=0x11;
mac[1]=0x22;
mac[2]=0x33;
mac[3]=0x44;
mac[4]=0x55;
mac[5]=0x66;
memcpy(arp_items[0].ip_addr,ip,4);
memcpy(arp_items[0].mac_addr,mac,6);
arp_items[0].state=ARP_NULL;
arp_items[0].timer=0;
memcpy(arp_items[1].ip_addr,ip,4);
memcpy(arp_items[1].mac_addr,mac,6);
arp_items[1].state=ARP_WORK;
arp_items[1].timer=7200;
memcpy(arp_items[2].ip_addr,ip,4);
memcpy(arp_items[2].mac_addr,mac,6);
arp_items[2].state=ARP_WAIT;
arp_items[2].timer=60;
}
void init_arp(void)
{
memset(arp_items,0,sizeof(arp_items));
// init_arp_items();
enroll_tick(arp_tick);
}
void print_arp_items(void)
{
struct _arp_item *p;
uc i=0;
put_char ('\r');
put_char ('\n');
put_char('a');
put_char('r');
put_char('p');
put_char('.');
for(i=0;i<ARP_ITEM_NUM;i++)
{
p=&(arp_items[i]);
put_char ('\r');
put_char ('\n');
put_hex(i+1);
put_char('.');
put_char('i');
put_char('p');
put_char('-');
put_char('>');
put_hex4(p->ip_addr);
put_char ('\r');
put_char ('\n');
put_char('m');
put_char('a');
put_char('c');
put_char('-');
put_char('>');
put_hex_6(p->mac_addr);
put_char ('\r');
put_char ('\n');
put_char('s');
put_char('t');
put_char('a');
put_char('t');
put_char('e');
put_char('-');
put_char('>');
put_hex(p->state);
put_char ('\r');
put_char ('\n');
put_char('t');
put_char('i');
put_char('m');
put_char('e');
put_char('r');
put_char('-');
put_char('>');
put_hex_2(p->timer);
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?