📄 arp.c
字号:
#include <string.h>
#include "arp.h"
#include "eth.h"
//SA:源地址,48位,表明该帧的数据是哪个网卡发的,即发送端的网卡地址,同样是6个字节.
/*DA:目的地址,以太网的地址为48位(6个字节)二进制地址,表明该帧传输给哪个网卡.
如果为FFFFFFFFFFFF,则是广播地址,广播地址的数据可以被任何网卡接收到.*/
/*TYPE:类型字段,表明该帧的数据是什么类型的数据,不同的协议的类型字段不同。如:0800H 表示数据为IP包,
0806H 表示数据为ARP包,814CH是SNMP包,8137H为IPX/SPX包,(小于0600H的值是用于IEEE802的,表示数据包的长度。)*/
/*
__packed struct eth_hdr {
struct eth_addr dest;//6 bytes 目的地址
struct eth_addr src; //6 bytes 源地址
u16_t type; //2 bytes 类型 指定接收数据的高层协议
//data //46 - 1500bytes 数据字段的内容
};
*/
/*__packed struct eth_addr {
u8_t addr[6];
};*/
__packed struct arp_hdr {
struct eth_hdr ethhdr;
u16_t hwtype; //Hardware type 16
u16_t protocol; //Protocol type 16
u8_t hwlen; //Hardware address length 8
u8_t protolen; //Protocol address length 8
u16_t opcode; //Opcode 16
struct eth_addr shwaddr; //Source hardware address 32
u32_t sipaddr; //Source protocol address 32
struct eth_addr dhwaddr; //Destination hardware address 32
u32_t dipaddr; //Destination protocol address 32
};
// entry 记载条目
struct arp_entry {
u32_t ipaddr;
struct eth_addr ethaddr;
u8_t time;
};
//arp高速缓存,存放最近的IP地址到arp地址之间的映射
static struct arp_entry arp_table[ARPTAB_SIZE];
static u8_t arp_time;
//初始化ARP环境
void arp_init(void)
{
memset(arp_table, 0, sizeof(arp_table));
arp_time = 0;
}
//输入ARP包,成功返回0,否则返回-1
u32_t arp_in(u8_t *ethbuf, u16_t len)
{
//u32_t tmp;
struct arp_hdr *pArp = (struct arp_hdr *)ethbuf;
if(pArp->ethhdr.type != HTONS(ETHTYPE_ARP))
return -1;
switch(pArp->opcode)
{
case HTONS(ARP_REQUEST):
dbglog(("\narp request "));
dbglog(("dipaddr %u.%u.%u.%u", IPADDR1(pArp->dipaddr),
IPADDR2(pArp->dipaddr), IPADDR3(pArp->dipaddr),
IPADDR4(pArp->dipaddr)));
if(pArp->dipaddr == getipaddr())
{
dbglog((" sipaddr %u.%u.%u.%u", IPADDR1(pArp->sipaddr),
IPADDR2(pArp->sipaddr), IPADDR3(pArp->sipaddr),
IPADDR4(pArp->sipaddr)));
//#define ARP_REPLY 2
pArp->opcode = HTONS(ARP_REPLY);
//
pArp->dhwaddr = pArp->shwaddr;
pArp->shwaddr = getethaddr();
pArp->ethhdr.dest = pArp->dhwaddr;
pArp->ethhdr.src = pArp->shwaddr;
//
//tmp = pArp->dipaddr;
pArp->dipaddr = pArp->sipaddr;
pArp->sipaddr = getipaddr();//tmp;
//
eth_send(ethbuf, sizeof(struct arp_hdr));
arp_update(pArp->dipaddr, &pArp->dhwaddr);
return 0;
}
break;
//#define ARP_REPLY 2
case HTONS(ARP_REPLY):
arp_update(pArp->sipaddr, &pArp->shwaddr);
return 0;
break;
}
return -1;
}
/*目的地址,以太网的地址为48位(6个字节)二进制地址,表明该帧传输给哪个网卡.
如果为FFFFFFFFFFFF,则是广播地址,广播地址的数据可以被任何网卡接收到.*/
//根据IP地址获取MAC地址,成功返回0,否则返回-1
//ARP的功能:实现从IP地址到对应物理地址的转换
//IP:4*8=32 ARP:6*8=48 //传入u32_t小端的IP地址
u32_t arp_getethaddr(u32_t ipaddr, struct eth_addr *ethaddr)
{
u32_t i;
/*
// entry 记载条目
struct arp_entry {
u32_t ipaddr;
struct eth_addr ethaddr;
u8_t time;
};
//arp高速缓存,存放最近的IP地址到arp地址之间的映射
static struct arp_entry arp_table[ARPTAB_SIZE];
*/
for(i=0; i<ARPTAB_SIZE; i++)
{
if(arp_table[i].ipaddr == ipaddr)
{
*ethaddr = arp_table[i].ethaddr;
return 0;
}
}
/*__packed struct eth_hdr {
struct eth_addr dest;//6 bytes 目的地址
struct eth_addr src; //6 bytes 源地址
u16_t type; //2 bytes 类型 指定接收数据的高层协议
//data //46 - 1500bytes 数据字段的内容
};
*/
/*
__packed struct arp_hdr {
struct eth_hdr ethhdr;
u16_t hwtype; //Hardware type 16
u16_t protocol; //Protocol type 16
u8_t hwlen; //Hardware address length 8
u8_t protolen; //Protocol address length 8
u16_t opcode; //Opcode 16
struct eth_addr shwaddr; //Source hardware address 32
u32_t sipaddr; //Source protocol address 32
struct eth_addr dhwaddr; //Destination hardware address 32
u32_t dipaddr; //Destination protocol address 32
};
*/
{
struct arp_hdr arp;
const static struct eth_addr eth_broadcast_addr = {0xff,0xff,0xff,0xff,0xff,0xff};
const static struct eth_addr eth_zero_addr = {0x00,0x00,0x00,0x00,0x00,0x00};
arp.ethhdr.dest = eth_broadcast_addr;
arp.ethhdr.src = getethaddr();
//#define ETHTYPE_ARP 0x0806
arp.ethhdr.type = HTONS(ETHTYPE_ARP);
arp.hwtype = HTONS(0x0001);
arp.protocol = HTONS(0x0800);
arp.hwlen = 6;
arp.protolen = 4;
//#define ARP_REQUEST 1
arp.opcode = HTONS(ARP_REQUEST);
arp.shwaddr = getethaddr();
arp.sipaddr = getipaddr();
arp.dhwaddr = eth_zero_addr;
arp.dipaddr = ipaddr;
eth_send((u8_t*)&arp, sizeof(struct arp_hdr));
}
return -1;
}
//更新ARP Table ,成功返回0,否则返回-1。
u32_t arp_update(u32_t ipaddr, struct eth_addr *ethaddr)
{
u32_t i;
struct arp_entry *ptr = NULL;
for(i=0; i<ARPTAB_SIZE; i++)
{
if((ptr == NULL && arp_table[i].ipaddr == 0) ||
arp_table[i].ipaddr == ipaddr)
{
ptr = &arp_table[i];
}
}
if(ptr != NULL)
{
ptr->ipaddr = ipaddr;
ptr->ethaddr = *ethaddr;
ptr->time = arp_time;
return 0;
}
return -1;
}
//刷新ARP时间
void arp_timer(void)
{
u32_t i;
arp_time++;
for(i=0; i<ARPTAB_SIZE; i++)
{
if(arp_table[i].ipaddr != 0 &&
(arp_time - arp_table[i].time) > ARP_MAXAGE)
{
memset(&arp_table[i], 0, sizeof(struct arp_entry));
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -