一 点睛
1 以太网帧头结构定义
#define ETH_ALEN 6 //定义了以太网接口的MAC地址的长度为6个字节
#define ETH_HLAN 14 //定义了以太网帧的头长度为14个字节
#define ETH_ZLEN 60 //定义了以太网帧的最小长度为 ETH_ZLEN + ETH_FCS_LEN = 64个字节
#define ETH_DATA_LEN 1500 //定义了以太网帧的最大负载为1500个字节
#define ETH_FRAME_LEN 1514 //定义了以太网正的最大长度为ETH_DATA_LEN + ETH_FCS_LEN = 1518个字节
#define ETH_FCS_LEN 4 //定义了以太网帧的CRC值占4个字节
struct ethhdr
{
unsigned char h_dest[ETH_ALEN]; //目的MAC地址
unsigned char h_source[ETH_ALEN]; //源MAC地址
__u16 h_proto ; //网络层所使用的协议类型
}__attribute__((packed)) //用于告诉编译器不要对这个结构体中的缝隙部分进行填充操作;
二 实战前准备
1 准备两台虚拟机A和B。
A的IP:192.168.0.110 A的MAC:08:00:27:60:7b:7f
B的IP:192.168.0.120 B的MAC:08:00:27:0c:3b:d3
2 步骤
程序部署在A机上,B给A发送一些ARP包,然后看A是否收到并判断出来。
三 代码
#include
#include
#include
#include
#include
#include
#include
#include //for ethhdr
int main(int argc, char *argv [])
{
int i = 0;
unsigned char buf[1024] = "";
struct ethhdr *eth; //以太网头结构体指针
// 使用ETH_P_ARP协议号,这样这个套接字就只会去接收ARP报文了。
int sock_raw_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ARP));
while (1)
{
recvfrom(sock_raw_fd, buf, sizeof(buf), 0, NULL, NULL); //获取链路层的数据帧
eth = (struct ethhdr*)buf; //指向接收到的数据缓冲区,就能通过结构体字段获得目的、源MAC和协议号
//从eth里提取目的mac、源mac、协议号
printf("proto=0x%04x,dst mac addr:%02x:%02x:%02x:%02x:%02x:%02x\n", ntohs(eth->h_proto), eth->h_dest[0], eth->h_dest[1], eth->h_dest[2], eth->h_dest[3], eth->h_dest[4], eth->h_dest[5]);
printf("proto=0x%04x,src mac addr:%02x:%02x:%02x:%02x:%02x:%02x\n", ntohs(eth->h_proto), eth->h_source[0], eth->h_source[1], eth->h_source[2], eth->h_source[3], eth->h_source[4], eth->h_source[5]);
}
return 0;
}
四 在A机上编译并运行
[root@localhost test]# g++ test.cpp -o test
[root@localhost test]# ./test
五 捕获ARP包
1 在B机上发送2个ARP探测包,输入如下命令
[root@localhost ~]# arping -I enp0s3 192.168.0.110 -c 2
ARPING 192.168.0.110 from 192.168.0.120 enp0s3
Unicast reply from 192.168.0.110 [08:00:27:60:7B:7F] 0.869ms
Unicast reply from 192.168.0.110 [08:00:27:60:7B:7F] 0.813ms
Sent 2 probes (1 broadcast(s))
Received 2 response(s)
2 A端捕获4个ARP包
[root@localhost test]# ./test
proto=0x0806,dst mac addr:ff:ff:ff:ff:ff:ff
proto=0x0806,src mac addr:08:00:27:0c:3b:d3
proto=0x0806,dst mac addr:08:00:27:60:7b:7f
proto=0x0806,src mac addr:08:00:27:0c:3b:d3