Winpcap实现arp协议的发送和解析

本文详述了使用Winpcap在VS2019环境下实现ARP协议的全过程,包括环境配置、网络适配器获取、IP及MAC地址提取、ARP包构建与解析等关键步骤,特别强调了IP地址正反转换与MAC地址获取的难点。

计算机网络课程设计中,老师要求用winpcap实现arp协议的发送和解析。我从0开始一点点琢磨最终实现了需要的功能。我中间踩了很多很多的坑,因此在此记录一下,希望也能够帮助更多的人。

环境的配置、头文件和宏定义

我的IDE是vs2019,熟悉的人都知道微软有“不合群”的尿性,它的产品总要与别人不一样,网上的代码粘到vs里就是不能运行。配置环境其实跟网上找的没什么区别,但是需要注意的是需要加上很多额外头文件,因为网上其他关于实现arp的文章中本机mac地址是需要手动输入的,而我是直接通过调用一些函数和API获取对应网卡的mac地址。
winpcap下载地址如下:https://www.winpcap.org/
我的头文件和宏定义如下:

#define WIN32
#define _CRT_SECURE_NO_WARNINGS
#include<pcap.h>
#include<Windows.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<Packet32.h>
#include<ntddndis.h>
#include<time.h>

当然要用到这里的一些头文件你需要按照网上的教程配置好目录。

网络适配器的获取

pcap_if_t* alldevs, * d;		//用于存储网络设备
	//pcap_if是一个结构体,包含了网络适配器的全部信息
	int i = 0;//网络设备号数目
	char errbuf[PCAP_ERRBUF_SIZE];
	if (pcap_findalldevs(&alldevs, errbuf) == -1) {
   
   
		fprintf(stderr, "Error in pcap_findalldevs:%s\n", errbuf);
		exit(1);
	}
	for (d = alldevs; d; d = d->next) {
   
   //alldevs是一个链表!链表!链表!网卡信息的链表,每个网卡信息的结构体就是链表的一个节点
		printf("%d. %s", ++i, d->name);
		if (d->description)
			printf("(%s)\n", d->description);
		else
			printf(" (No description available)\n");
	}
	if (i == 0) {
   
   
		printf("\n找不到指定接口.\n");
	}
	int nnnnn = i;
choose:
	i = nnnnn;
	printf("\n选择适配器号 (1-%d):", i);
	int inum;
	pcap_t* adhandle;
	unsigned char* packet;
	scanf("%d", &inum);//直接选择4号,4号是我的WiFi网卡
	if (inum < 1 || inum > i) {
   
   
		printf("超出范围.\n");
		goto choose;
	}
	for (d = alldevs, i = 0; i < inum - 1; d = d->next, i++);
	pcap_addr_t* a = d->addresses;

这一部分就是获取网卡信息。第一次接触的同学可能不理解输出的到底是什么。我给截一下图:
在这里插入图片描述
在我运行的结果中出现了五个网卡。没错,每台电脑都不止一个网卡,有有线网卡、WiFi网卡、蓝牙设备也算网卡,甚至如果你有Ubuntu虚拟机的话虚拟机也有网卡! 那么我们肯定需要知道到底哪个是我的WiFi网卡呢?毕竟我们发送arp肯定得用WiFi网卡。至少目前我觉得唯一的方法就是得知每个网卡的IP地址,然后看看哪个是我电脑的WiFi网卡。 然而现实是有些网卡没有IP地址!!!也就是不支持ipv4服务,不信的话你到命令行输入ipconfig/all,展现你电脑上所有的网卡,你会发现确实有网卡没有IP地址这个属性。此时你可能发现ipconfig展示出来的网卡数可能比你在程序里输出的网卡多。别问我,我也不知道为什么。。。

IP地址和mac地址的获取

unsigned int ip = 0;
	unsigned char mac[6];
	for (a = d->addresses; a; a = a->next) {
   
   
		switch (a->addr->sa_family) {
   
   
		case AF_INET: {
   
   
			if (a->addr) {
   
   
				ip = (((struct sockaddr_in*)a->addr)->sin_addr.s_addr);//取得ip
				GetAdapterMacAddr(d->name, mac);//取得mac
			}
			break;
		}
		default: break;
		}
	}//获取对应网卡的ipv4的ip地址
	if (ip == 0) {
   
   
		printf("该网卡没有ipv4,请重新选择!\n");
		goto choose;
	}

a是什么呢?a是d->addresses,d是网卡信息,也就是说a是网卡的地址信息。a含有ip地址,子网掩码、p2p地址等若干地址,但就是没有mac地址!!我看起来像是a仅仅含有网络层地址,没有链路层的。这一部分其实非常复杂,我也很不理解。只知道addr的sa_family为AF_INTE的时候才表示这个是IP地址,不是子网掩码什么的,然后ip就可以等于后面一大串了。。后面一大串是啥我也不是很理解,但是一层一层的结构体点进去,会隐隐约约感觉这就是IP地址。。。
ip我定义的是一个无符号整

标 题: 【原创】基于WinPCap网络协议开发 - 炮王(超级打炮机)发送数据包(03) 作 者: 加百力 时 间: 2009-05-18,16:55:36 链 接: http://bbs.pediy.com/showthread.php?t=89175 【文章标题】: 基于WinPCap网络协议开发 - 炮王(超级打炮机)发送数据包(03) 【文章作者】: 加百力 【软件名称】: WinPCap 【下载地址】: http://www.winpcap.org/ 【内部编号】: MASSADA 0029 【编写语言】: C++ 【使用工具】: VS2005 【操作平台】: Windows 2003 -------------------------------------------------------------------------------- 【详细过程】 在第一篇文章中我们提到WinPCap的基本功能之一就是:  1> 在网络上发送原始的数据包。 发送原始数据包难度不大,只需要应用几个简单的函数就可以了。 我编写炮王程序的主要目的是为了测试WinPCap/libpcap的抓包能力,在不同网速数据包大小的条件下libpcap的抓包率有多少。 炮王特点: 01、可以发送任意协议的数据包。TCP/IP等等。 02、针对每次发包,会返回状态,可以检测是否成功。在程序中如果失败会自动退出。 03、可以随机修改数据包的:源、目的MAC地址,IP地址,端口、数据内容等属性信息。 04、使用多线程发包,在XP下最多可以同时开2000个线程发包,发包速度快,流量大。在千兆网卡上可以超过15M/s的速度。 05、自动统计发包时间,计算每秒发包数量,流量。 06、可以设置发包的时间间隔,最少到1毫秒。 炮王使用方法: 首先直接运行pw.exe可以看到程序提示的参数信息显示的当前可用网卡信息。可用网卡信息会保存在CardsInfo.txt文件中。 打开BAT脚本,修改网卡信息,即可。 运行脚本,脚本将数据包文件发送出去。 注意:总的发包数量等于每个线程的发包数量乘以线程总数。 实验的数据包文件都是MSN消息。 具体代码请看附件。 -------------------------------------------------------------------------------- 【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值