arp数据包的发送和解析完整代码
时间: 2023-09-01 09:08:37 浏览: 160
下面是关于ARP数据包的发送和解析的完整代码:
```
#include <winsock2.h>
#include <pcap.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#pragma comment(lib, "wpcap.lib")
#pragma comment(lib, "ws2_32.lib")
#define MAC_LEN 6 // MAC地址长度为6字节
#define IP_LEN 4 // IP地址长度为4字节
#define ETH_P_ARP 0x0806 // ARP协议类型
#define ETH_P_IP 0x0800 // IP协议类型
#define ETH_HDR_LEN 14 // 以太网头部长度为14字节
#define PACKET_LEN 42 // ARP数据包长度为42字节(包括以太网头部和ARP头部)
typedef struct arp_hdr
{
u_short hardware_type; // 硬件类型
u_short protocol_type; // 协议类型
u_char hardware_len; // MAC地址长度
u_char protocol_len; // IP地址长度
u_short operation; // 操作类型
u_char src_mac[6]; // 源MAC地址
u_char src_ip[4]; // 源IP地址
u_char dest_mac[6]; // 目的MAC地址
u_char dest_ip[4]; // 目的IP地址
} arp_hdr;
void send_arp_packet(pcap_t* adhandle, u_char* src_mac, u_char* src_ip, u_char* dest_mac, u_char* dest_ip, int op)
{
arp_hdr arp;
memset(&arp, 0, sizeof(arp));
arp.hardware_type = htons(ARPHRD_ETHER); // 硬件类型为以太网
arp.protocol_type = htons(ETH_P_IP); // 协议类型为IP
arp.hardware_len = MAC_LEN; // MAC地址长度为6
arp.protocol_len = IP_LEN; // IP地址长度为4
arp.operation = htons(op); // 操作类型为请求或响应
memcpy(arp.src_mac, src_mac, MAC_LEN); // 源MAC地址
memcpy(arp.src_ip, src_ip, IP_LEN); // 源IP地址
memcpy(arp.dest_mac, dest_mac, MAC_LEN); // 目的MAC地址
memcpy(arp.dest_ip, dest_ip, IP_LEN); // 目的IP地址
u_char packet[PACKET_LEN];
memset(packet, 0, sizeof(packet));
memcpy(packet, dest_mac, MAC_LEN);
memcpy(packet + MAC_LEN, src_mac, MAC_LEN);
packet[12] = ETH_P_ARP / 256;
packet[13] = ETH_P_ARP % 256;
memcpy(packet + ETH_HDR_LEN, &arp, sizeof(arp));
if (pcap_sendpacket(adhandle, packet, PACKET_LEN) != 0)
{
printf("Error sending ARP packet: %s\n", pcap_geterr(adhandle));
}
}
void parse_arp_packet(const u_char* packet)
{
arp_hdr* arp = (arp_hdr*)(packet + ETH_HDR_LEN); // 获取ARP头部信息
printf("ARP packet:\n");
printf(" Source MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n",
arp->src_mac[0], arp->src_mac[1], arp->src_mac[2], arp->src_mac[3], arp->src_mac[4], arp->src_mac[5]);
printf(" Source IP address: %d.%d.%d.%d\n",
arp->src_ip[0], arp->src_ip[1], arp->src_ip[2], arp->src_ip[3]);
printf(" Destination MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n",
arp->dest_mac[0], arp->dest_mac[1], arp->dest_mac[2], arp->dest_mac[3], arp->dest_mac[4], arp->dest_mac[5]);
printf(" Destination IP address: %d.%d.%d.%d\n",
arp->dest_ip[0], arp->dest_ip[1], arp->dest_ip[2], arp->dest_ip[3]);
}
int main()
{
pcap_if_t* alldevs;
pcap_if_t* d;
int i = 0;
int inum;
pcap_t* adhandle;
char errbuf[PCAP_ERRBUF_SIZE];
struct bpf_program fcode;
bpf_u_int32 netmask;
bpf_u_int32 netaddr;
// 获取本地网卡列表
if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
{
printf("Error in pcap_findalldevs_ex: %s\n", errbuf);
return 1;
}
// 输出网卡列表
for (d = alldevs; d != NULL; d = d->next)
{
printf("%d. %s\n", ++i, d->name);
if (d->description)
printf(" (%s)\n", d->description);
else
printf(" (No description available)\n");
}
// 选择要抓包的网卡
printf("Enter the interface number (1-%d):", i);
scanf_s("%d", &inum);
if (inum < 1 || inum > i)
{
printf("Invalid interface number\n");
pcap_freealldevs(alldevs);
return 1;
}
// 定位到选择的网卡
for (d = alldevs, i = 0; i < inum - 1; d = d->next, i++);
// 打开网卡
if ((adhandle = pcap_open(d->name, 65536, PCAP_OPENFLAG_PROMISCUOUS, 1000, NULL, errbuf)) == NULL)
{
printf("Unable to open the adapter. %s is not supported by WinPcap\n", d->name);
pcap_freealldevs(alldevs);
return 1;
}
// 获取网卡的子网掩码
if (d->addresses != NULL)
{
netmask = ((struct sockaddr_in*)(d->addresses->netmask))->sin_addr.S_un.S_addr;
}
else
{
netmask = 0xffffff;
}
// 编译过滤器
if (pcap_compile(adhandle, &fcode, "arp", 1, netmask) < 0)
{
printf("Unable to compile the packet filter. Check the syntax.\n");
pcap_freealldevs(alldevs);
return 1;
}
// 设置过滤器
if (pcap_setfilter(adhandle, &fcode) < 0)
{
printf("Error setting the filter.\n");
pcap_freealldevs(alldevs);
return 1;
}
// 发送ARP请求
u_char src_mac[6] = { 0x00, 0x0c, 0x29, 0x7b, 0x63, 0x15 }; // 本机MAC地址
u_char src_ip[4] = { 192, 168, 1, 100 }; // 本机IP地址
u_char dest_mac[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; // 广播地址
u_char dest_ip[4] = { 192, 168, 1, 1 }; // 目标IP地址
send_arp_packet(adhandle, src_mac, src_ip, dest_mac, dest_ip, ARPOP_REQUEST);
// 接收ARP响应
struct pcap_pkthdr* header;
const u_char* packet;
int res;
while ((res = pcap_next_ex(adhandle, &header, &packet)) >= 0)
{
if (res == 0)
continue;
parse_arp_packet(packet);
}
pcap_close(adhandle);
pcap_freealldevs(alldevs);
return 0;
}
```
注意:在运行代码时,需要安装WinPcap库,并在项目属性中添加对该库的引用。
阅读全文