计算机网络课程设计,使用MFC实现界面化创建ARP发送与接受程序(二)
1.ARP相关知识:
ARP数据报文格式:
硬件类型:0001,表示硬件类型为以太网。
协议类型:0800,表示需映射地址为IP 地址。
硬件长度:6,表示硬件地址长度为6 字节。
协议长度:4,表示协议地址长度为4 字节。
操作码:1,表示此ARP 报文为ARP 请求报文;2,表示此ARP 报文为ARP 应答报文。
源物理地址:6个字节 ,发送方的MAC地址
源 IP 地址: 4个字节,发送方的IP地址
目标物理地址:6个字节,接收方的MAC地址
目标 IP 地址:4个字节,接收方的IP地址
填充内容:18个字节
使用结构体定义我们发送所需的ARP报文和相关常量
struct ArpPacket
{
u_char Des_Mac[6]; //目的MAC地址
u_char Src_Mac[6]; //源MAC地址
u_short EthType; //上一层协议类型
unsigned short HardwareType; //硬件类型
unsigned short ProtocolType; //协议类型
unsigned char HardwareLen; //硬件地址长度
unsigned char ProtocolLen; //协议地址长度
unsigned short OpCode; //操作类型,ARP请求(1),ARP应答(2)
u_char src_mac[6]; //源MAC地址
u_int src_ip; //源IP地址
u_char des_mac[6]; //目的MAC地址
u_int des_ip; //目的IP地址
u_char data[18]; //填充内容,全0
};
#define ETH_ARP 0x0806 //以太网帧类型表示后面数据的类型,对于ARP请求或应答来说,该字段的值为0x0806
#define ARP_HARDWARE 1 //硬件类型字段值为表示以太网地址
#define ETH_IP 0x0800 //协议类型字段表示要映射的协议地址类型值为0x0800表示IP地址
#define ARP_REQUEST 1 //ARP请求
#define ARP_RESPONSE 2 //ARP应答
可能出现的情况
在后面如果我们使用VS2019运行发送ARP报文的程序,可能出现一种情况,这是你发现发送的数据包不是你想构造的数据包,你所填充的内容被捕捉时会有所偏移,这时我们需要在定义结构体之前添加:
#pragma pack(1)
摘自百度百科:编译器中提供了#pragma pack(n)来设定变量以n字节对齐方式。n字节对齐就是说变量存放的起始地址的偏移量有两种情况:第一、如果n大于等于该变量所占用的字节数,那么偏移量必须满足默认的对齐方式,第二、如果n小于该变量的类型所占用的字节数,那么偏移量为n的倍数,不用满足默认的对齐方式。结构的总大小也有个约束条件,分下面两种情况:如果n大于所有成员变量类型所占用的字节数,那么结构的总大小必须为占用空间最大的变量占用的空间数的倍数;否则必须为n的倍数。
简而言之,在定义结构体时需要考虑编译器中数据是否时按照实际情况对齐,否则发送时无法正确发送你所需要的数据报,导致抓包程序无法识别,添加代码后强制使编译器按照1字节对齐,防止出现这种情况
2.WINPCAP中文开发文档相关:
本项目需要使用的有关内容:
(1):获取已连接的网络适配器列表,并打开所需要的设备,这是编写基于Winpcap的应用程序的第一步
pcap_if_t *alldevs;
pcap_if_t *d;
int i=0;
char errbuf[PCAP_ERRBUF_SIZE];
/* 获取本地机器设备列表 */
if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL /* auth is not needed */, &alldevs, errbuf) == -1)
{
fprintf(stderr,"Error in pcap_findalldevs_ex: %s\n", errbuf);
exit(1);
}
/* 打印列表 */
for(d= alldevs; d != NULL; d= d->next)
{
printf("%d. %s", ++i, d->name);
if (d->description)
printf(" (%s)\n", d->description);
else
printf(" (No description available)\n");
}
if (i == 0)
{
printf("\nNo interfaces fo