winpcap:捕获数据包


因为已经知道如何获取适配器的信息,所以可以打开适配器并捕获数据包。将每一个通过适配器的数据包打印出来。
打开设备的函数是pcap_open()。 在一些操作系统中 (比如 xBSD 和 Win32), 驱动可以被配置成只捕获数据包的初始化部分: 这样可以减少应用程序间复制数据的量,从而提高捕获效率。将值定为65535,它比我们能遇到的最大的MTU还要大。因此,总能收到完整的数据包。flags:最最重要的flag是用来指示适配器是否要被设置成混杂模式。 一般情况下,适配器只接收发给它自己的数据包, 而那些在其他机器之间通讯的数据包,将会被丢弃。 相反,如果适配器是混杂模式,那么不管这个数据包是不是发给我的,我都会去捕获。也就是说,我会去捕获所有的数据包。 这意味着在一个共享媒介(比如总线型以太网),WinPcap能捕获其他主机的所有的数据包。 大多数用于数据捕获的应用程序都会将适配器设置成混杂模式,所以,我们也会在下面的范例中,使用混杂模式。to_ms指定读取数据的超时时间,以毫秒计(1s=1000ms)。在适配器上进行读取操作(比如用pcap_dispatch()或pcap_next_ex()) 都会在to_ms毫秒时间内响应,即使在网络上没有可用的数据包。 在统计模式下,to_ms还可以用来定义统计的时间间隔。 将to_ms设置为0意味着没有超时,那么如果没有数据包到达的话,读操作将永远不会返回。 如果设置成-1,则情况恰好相反,无论有没有数据包到达,读操作都会立即返回。// 4002.cpp : 定义控制台应用程序的入口点。
//

#include “stdafx.h”
#include “pcap.h”

/* packet handler 函数原型 */
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data);

int _tmain(int argc, _TCHAR* argv[])
{
pcap_if_t *alldevs;
pcap_if_t *d;
int inum;
int i=0;
pcap_t *adhandle;
char errbuf[PCAP_ERRBUF_SIZE];

/* 获取本机设备列表 */
if (pcap_findalldevs_ex(P免费云主机域名CAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
{
fprintf(stderr,”Error in pcap_findalldevs: %sn”, errbuf);
exit(1);
}

/* 打印列表 */
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”);
}

if(i==0)
{
printf(“nNo interfaces found! Make sure WinPcap is installed.n”);
return -1;
}

printf(“Enter the interface number (1-%d):”,i);
scanf(“%d”, &inum);

if(inum i)
{
printf(“nInterface number out of range.n”);
/* 释放设备列表 */
pcap_freealldevs(alldevs);
return -1;
}

/* 跳转到选中的适配器 */
for(d=alldevs, i=0; inext, i++);

/* 打开设备 */
if ( (adhandle= pcap_open(d->name, // 设备名
65536, // 65535保证能捕获到不同数据链路层上的每个数据包的全部内容
PCAP_OPENFLAG_PROMISCUOUS, // 混杂模式
1000, // 读取超时时间
NULL, // 远程机器验证
errbuf // 错误缓冲池
) ) == NULL)
{
fprintf(stderr,”nUnable to open the adapter. %s is not supported by WinPcapn”, d->name);
/* 释放设备列表 */
pcap_freealldevs(alldevs);
return -1;
}

printf(“nlistening on %s…n”, d->description);

/* 释放设备列表 */
pcap_freealldevs(alldevs);

/* 开始捕获 */
pcap_loop(adhandle, 0, packet_handler, NULL);

return 0;

}

/* 每次捕获到数据包时,libpcap都会自动调用这个回调函数 */
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
{
struct tm *ltime;
char timestr[16];
time_t local_tv_sec;

/* 将时间戳转换成可识别的格式 */
local_tv_sec = header->ts.tv_sec;
ltime=localtime(&local_tv_sec);
strftime( timestr, sizeof timestr, “%H:%M:%S”, ltime);

printf(“%s,%.6d len:%dn”, timestr, header->ts.tv_usec, header->len);

}
当适配器被打开,捕获工作就可以用pcap_dispatch()或pcap_loop()进行。 这两个函数非常的相似,区别就是 pcap_ dispatch() 当超时时间到了(timeout expires)就返回 (尽管不能保证) ,而pcap_loop()不会因此而返回,只有当cnt数据包被捕获,所以,pcap_loop()会在一小段时间内,阻塞网络的利用。pcap_loop()对于我们这个简单的范例来说,可以满足需求,不过,pcap_dispatch()函数一般用于比较复杂的程序中。这两个函数都有一个回调参数,packet_handler指向一个可以接收数据包的函数。 这个函数会在收到每个新的数据包并收到一个通用状态时被libpcap所调用 ( 与函数pcap_loop()和pcap_dispatch()中的user参数相似),数据包的首部一般有一些诸如时间戳,数据包长度的信息,还有包含了协议首部的实际数据。 注意:冗余校验码CRC不再支持,因为帧到达适配器,并经过校验确认以后,适配器就会将CRC删除,与此同时,大部分适配器会直接丢弃CRC错误的数据包,所以,WinPcap没法捕获到它们。上面的程序将每一个数据包的时间戳和长度从pcap_pkthdr的首部解析出来,并打印在屏幕上。注意事项:
项目–>**属性(alt+F7)
配置属性–>清单工具–>输入和输出–>嵌入清单–>否

项目–>**属性(alt+F7)
配置属性–>C/C++–>常规–>附加包含目录–>(include)

项目–>**属性(alt+F7)
配置属性–>链接器–>常规–>附加库目录–>(lib)

项目–>**属性(alt+F7)
配置属性–>链接器–>输入–>附加依赖项–>补充“;Packet.lib;wpcap.lib”

项目–>**属性(alt+F7)
配置属性–>C/C++–>预处理器–>预处理器定义–>补充“;HAVE_REMOTE”

相关推荐: 网站故障-排查步骤

作为一家中型网站的运维工程师,真实遇到网站故障了,寻求理想排查步骤,自己心得,附加网友观点网站挂了:1、ping我的网站主站IP,可能是禁ping,不通,可能是机房网络问题,那么就去ping机房的网关!2、机房网络如果没问题的话,那我会去看访问是什么情况,服务…

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。

(0)
打赏 微信扫一扫 微信扫一扫
上一篇 02/01 19:53
下一篇 02/01 19:53