之前有一个任务需要在windows上监听IEEE1905的报文,但是1905协议本身处于物理层(Physical Layer)与网络层(Network Layer)之间,翻了以下微软的msdn查看开发手册,然而发现windows没有直接提供网络层以下的API可以用。所以网上找资料,发现一个第三方开发的开源的库winpcap,提供了比较丰富的功能可以使用。
winpcap(windows packet capture)是windows平台下一个免费,公共的网络访问系统。开发winpcap这个项目的目的在于为win32应用程序提供访问网络底层的能力。它用于windows系统下的直接的网络编程。
- 特性
Winpcap特别适用于下面这几个经典领域:
-
网络及协议分析
-
网络监控
-
通信日志记录
-
traffic generators
-
用户级别的桥路和路由
-
网络入侵检测系统(NIDS)
-
网络扫描
-
安全工具
Winpcap有些方面不能做。它不依靠主机的诸如TCP/IP协议去收发数据包。这意味着它不能阻塞,不能处理同一台主机中各程序之间的通信数据。它只能“嗅探”到物理线路上的数据包。因此它不适用于 traffic shapers,QoS调度,以及个人防火墙。
- 组成部分
winpcap由两部分组成,首先是运行在内核态的网络数据包过滤器(Netgroup Packet Filter,NPF),它可以绕过操作系统的协议栈来访问在网络上传输的原始数据包。另外一部分是一个底层的DLL(packet.dll)和一个高级的独立于系统的DLL(Wpcap.dll),用于与用户程序的链接。因此使用winpcap,首先需要在windows下安装winpcap驱动,然后在开发的win32程序中链接两个动态库即可使用winpcap提供的捕获数据包功能。
![](https://img.haomeiwen.com/i11132662/97fa4129be72cfc8.png)
- 配置环境
地址:http://www.winpcap.org/install/default.htm 下载winpcap驱动
地址:http://www.winpcap.org/archive 下载package开发包
-
a) 执行安装包,在主机上安装winpcap驱动
-
b) 解压开发包,在VC15.0的Tools-->Option-->Directories的Include fils 和library files加入winpcap的include和lib目录
-
c) 在项目属性页中:配置属性->C/C++->预处理器->预处理器定义,增加;WPCAP;HAVE_REMOTE;
-
d) 在项目属性页中:配置属性->链接器->命令行->附加选项对应的文本框中增加:wpcap.lib ws2_32.lib Packet.lib
- 实例
监听IEEE 1905广播报文
//include 其他头文件
#include "pcap.h"
struct ether_header
{
u_int8_t ether_dhost[6]; //目的Mac地址
u_int8_t ether_shost[6]; //源Mac地址
u_int16_t ether_type; //协议类型
};
static void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
{
ether_header *Eheader = NULL;
u_short protocol;
//判断是否为1905广播报文
Eheader = (struct ether_header*)pkt_data;
protocol = ntohs(Eheader->ether_type);
//1905报文的以太网报文协议类型是 0x893a
if (protocol == 0x893a)
{
printf("it's a 1905 packet\n");
//do something
return;
}
}
void main()
{
pcap_if_t *alldevs;
pcap_if_t *d;
int i=0;
char errbuf[PCAP_ERRBUF_SIZE];
/* Retrieve the device list */
if (pcap_findalldevs(&alldevs, errbuf) == -1)//返回网卡列表,alldevs指向表头
{
fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
exit(1);
}
/* Print the list */
for(d=alldevs;d;d=d->next)
{
printf("%d. %s", ++i, d->name);
if (d->description)
printf(" (%s)\n", d->description);
else printf(" (No description available)\n");
/*print ip address*/
pcap_addr_t *a = NULL;
in_addr saddr;
CString buf;
for (a = p->addresses; a; a = a->next)
{
char ipStr[16] = { 0 };
saddr = ((sockaddr_in *)a->addr)->sin_addr;
buf.Format(_T("%s"), inet_ntop(AF_INET, (void *)&saddr, ipStr, 16));
printf("%s\n", buf.GetBuffer());
}
/*catch 100 packets*/
pcap_t *dhandle;
if ((dhandle = pcap_open_live(p->name,
65536,
true,
2000,
errbuf)) == NULL)
{
printf("[winpcap] pcap_open_live:%s", errbuf);
}
pcap_loop(dhandle, 100, packet_handler, NULL);
pcap_close(dhandle);
}
if(i==0)
{
printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
return;
}
/* We don't need any more the device list. Free it */
pcap_freealldevs(alldevs);
}
-
参考文档
winpcap用户指南 [http://www.ferrisxu.com/WinPcap/html/group__wpcapsamps.html
]
winpcap安装使用教程 [https://blog.csdn.net/qq_29350467/article/details/46663953
]
网友评论