1、循序渐进学习使用WINPCAP资料来源:进入WINPCAP的官方网站是http:/www.winpcap.org/不过是英文的一)winpcap驱动简介winpcap(windows packet capture)是windows平台下一个免费,公共的网络访问系统。开发winpcap这个项目的目的在于为win32应用程序提供访问网络底层的能力。它提供了以下的各项功能:1 捕获原始数据报,包括在共享网络上各主机发送/接收的以及相互之间交换的数据报;2 在数据报发往应用程序之前,按照自定义的规则将某些特殊的数据报过滤掉;3 在网络上发送原始的数据报;4 收集网络通信过程中的统计信息。winpcap
2、的主要功能在于独立于主机协议(如TCP-IP)而发送和接收原始数据报。也就是说,winpcap不能阻塞,过滤或控制其他应用程序数据报的发收,它仅仅只是监听共享网络上传送的数据报。因此,它不能用于QoS调度程序或个人防火墙。目前,winpcap开发的主要对象是windows NT/2000/XP,这主要是因为在使用winpcap的用户中只有一小部分是仅使用windows 95/98/Me,并且M$也已经放弃了对win9x的开发。最近正在学习PCAP,所以顺便把原文翻译出来和初学者一起进步。高手勿看。循序渐进学习使用WINPCAP(一)一些需要知道的细节描述(前言):这一部分展示了如何使用WINP
3、CAP-API的不同的功能,它作为一个使用指南被划分为一系列的课时来带领读者循序渐进的体会PCAP的程序设计的魅力:从简单的基本功能(如获取网卡的列表,数据包的捕获等)到统计和收集网络流量等高级功能。在这里将提供一些简单但完整的代码作为参考:所有的这些原代码都有和它相关的详细信息的连接以便单击这些功能和数据结构时能够即使跳转到相关的文献。这些例子是用C语言写的,所以在学习之前首先要有一定的C语言的基础,当然PCAP作为一个网络底层的驱动,要想学好它也必须具备一定的网络方面的知识。(一)得到网络驱动列表用PCAP写应用程序的第一件事往往就是要获得本地的网卡列表。PCAP提供了pcap_finda
4、lldevs()这个函数来实现此功能,这个API返回一个pcap_if结构的连表,连表的每项内容都含有全面的网卡信息:尤其是字段名字和含有名字的描述以及有关驱动器的易读信息。得到网络驱动列表的程序如下:#include pcap.hmain()pcap_if_t *alldevs;pcap_if_t *d;int i=0;char errbufPCAP_ERRBUF_SIZE;/* 这个API用来获得网卡 的列表 */if (pcap_findalldevs(&alldevs, errbuf) = -1)fprintf(stderr,Error in pcap_findalldevs: %sn
5、, errbuf);exit(1);/* 显示列表的响应字段的内容 */for(d=alldevs;d;d=d-next)printf(%d. %s, +i, d-name);if (d-description)printf( (%s)n, d-description);elseprintf( (No description available)n);if(i=0)printf(nNo interfaces found! Make sure WinPcap is installed.n);return;/* We dont need any more the device list. Free
6、 it */pcap_freealldevs(alldevs);有关这段程序的一些说明:首先pcap_findalldevs()同其他的libpca函数一样有一个errbuf参数,当有异常情况发生时,这个参数会被PCAP填充为某个特定的错误字串。再次,UNIX也同样提供pcap_findalldevs()这个函数,但是请注意并非所有的系统都支持libpcap提供的网络程序接口。所以我门要想写出合适的程序就必须考虑到这些情况(系统不能够返回一些字段的描述信息),在这种情况下我门应该给出类似No description available这样的提示。最后结束时别忘了用pcap_freealldev
7、s()释放掉内存资源。原文如下:Obtaining the device listThe first thing that usually a WinPcap based application needs is a list of suitable network adapters. Libpcap provides the pcap_findalldevs() function for this purpose: this function returns a linked list of pcap_if structures, each of which contains compreh
8、ensive information about an adapter. In particular the fields name and description contain the name and a human readable description of the device.The following code retrieves the adapter list and shows it on the screen, printing an error if no adapters are found.#include pcap.hmain()pcap_if_t *alld
9、evs;pcap_if_t *d;int i=0;char errbufPCAP_ERRBUF_SIZE;/* Retrieve the device list */if (pcap_findalldevs(&alldevs, errbuf) = -1)fprintf(stderr,Error in pcap_findalldevs: %sn, 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-des
10、cription);elseprintf( (No description available)n);if(i=0)printf(nNo interfaces found! Make sure WinPcap is installed.n);return;/* We dont need any more the device list. Free it */pcap_freealldevs(alldevs);Some comments about this code.First of all, pcap_findalldevs(), like other libpcap functions,
11、has an errbuf parameter. This parameter points to a string filled by libpcap with a description of the error if something goes wrong.Second, note that pcap_findalldevs() is provided by libpcap under Unix as well, but remember that not all the OSes supported by libpcap provide a description of the ne
12、twork interfaces, therefore if we want to write a portable application, we must consider the case in which description is null: we print the string No description available in that situation.Note finally that we free the list with pcap_freealldevs() once when we have finished with it.Lets try to com
13、pile and run the code of this first sample. In order to compile it under Unix or Cygwin, simply issue a:gcc -o testaprog testprog.c -lpcapOn Windows, you will need to create a project, following the instructions in the Using WinPcap in your programs section of this manual. However, I suggest you to
14、use the WinPcap developers pack (available at the WinPcap website, http:/winpcap.polito.it ), that provides a lot of properly configured example apps, all the code presented in this tutorial and all the projects, includes and libraries needed to compile and run the samples.Assuming we have compiled
15、the program, lets try to run it. On my WinXP workstation, the result is1. 4E273621-5161-46C8-895A-48D0E52A0B83 (Realtek RTL8029(AS) Ethernet Adapter) 2. 5D24AE04-C486-4A96-83FB-8B5EC6C7F430 (3Com EtherLink PCI) As you can see, the name of the network adapters (that will be passed to libpcap when ope
16、ning the devices) under Windows are quite unreadable, so the description near them can be very useful to the user.循序渐进学习使用WINPCAP(二) 获得已安装网络驱动器的高级信息在第一章中演示了如何获得已存在适配器的静态信息。实际上WinPcap同样也提供其他的高级信息,特别是 pcap_findalldevs()这个函数返回的每个 pcap_if结构体都同样包含一个pcap_addr结构的列表,他包含:一个地址列表,一个掩码列表,一个广播地址列表和一个目的地址列表。下面的例子
17、通过一个ifprint()函数打印出了pcap_if结构的的所有字段信息,该程序对每一个pcap_findalldevs()所返回的pcap_if结构循环调用ifprint()来显示详细的字段信息。#include pcap.h#ifndef WIN32#include #include #else#include #endifvoid ifprint(pcap_if_t *d);char *iptos(u_long in);int main()pcap_if_t *alldevs;pcap_if_t *d;char errbufPCAP_ERRBUF_SIZE+1;/* 获得网卡的列表 */
18、if (pcap_findalldevs(&alldevs, errbuf) = -1)fprintf(stderr,Error in pcap_findalldevs: %sn,errbuf);exit(1);/* 循环调用ifprint() 来显示pcap_if结构的信息*/for(d=alldevs;d;d=d-next)ifprint(d);return 1;/* Print all the available information on the given interface */void ifprint(pcap_if_t *d)pcap_addr_t *a;/* Name */
19、printf(%sn,d-name);/* Description */if (d-description)printf(tDescription: %sn,d-description);/* Loopback Address*/printf(tLoopback: %sn,(d-flags & PCAP_IF_LOOPBACK)?yes:no);/* IP addresses */for(a=d-addresses;a;a=a-next) printf(tAddress Family: #%dn,a-addr-sa_family);/*关于 sockaddr_in 结构请参考其他的网络编程书*
20、/switch(a-addr-sa_family)case AF_INET:printf(tAddress Family Name: AF_INETn);/打印网络地址类型if (a-addr)/打印IP地址printf(tAddress: %sn,iptos(struct sockaddr_in *)a-addr)-sin_addr.s_addr);if (a-netmask)/打印掩码printf(tNetmask: %sn,iptos(struct sockaddr_in *)a-netmask)-sin_addr.s_addr);if (a-broadaddr)/打印广播地址print
21、f(tBroadcast Address: %sn,iptos(struct sockaddr_in *)a-broadaddr)-sin_addr.s_addr);if (a-dstaddr)/目的地址printf(tDestination Address: %sn,iptos(struct sockaddr_in *)a-dstaddr)-sin_addr.s_addr);break;default:printf(tAddress Family Name: Unknownn);break;printf(n);/*将一个unsigned long 型的IP转换为字符串类型的IP */#def
22、ine IPTOSBUFFERS12char *iptos(u_long in)static char outputIPTOSBUFFERS3*4+3+1;static short which;u_char *p;p = (u_char *)∈which = (which + 1 = IPTOSBUFFERS ? 0 : which + 1);sprintf(outputwhich, %d.%d.%d.%d, p0, p1, p2, p3);return outputwhich; 循序渐进学习使用WINPCAP(三) -打开网卡捕获数据包现在我门已经知道了如何去获得网卡的信息现在就让我们
23、开始真正的工作:打开网卡并捕获数据流。在这一节里我们将写一个打印流经网络的每个数据包信息的程序。打开网卡的功能是通过pcap_open_live()来实现的它有三个参数snaplenpromiscto_ms。 snaplen用于指定所捕获包的特定部分,在一些系统上(象xBSD and Win32等)驱动只给出所捕获数据包的一部分而不是全部,这样就减少了拷贝数据的数量从而提高了包捕获的效率。promisc指明网卡处于混杂模式,在正常情况下网卡只接受去往它的包而去往其他主机的数据包则被忽略。相反当网卡处于混杂 模式时他将接收所有的流经它的数据包:这就意味着在共享介质的情况下我门可以捕获到其它主机的
24、数据包。大部分的包捕获程序都将混杂模式设为默认,所有我们在下面的例子里也将网卡设为混杂模式。to_ms 参数指定读数据的超时控制,超时以毫秒计算。当在超时时间内网卡上没有数据到来时对网卡的读操作将返回(如pcap_dispatch() or pcap_next_ex()等函数)。还有,如果网卡处于统计模式下(请查看“统计和收集网络数据流一节”)to_ms还定义了统计的时间间隔。如果该参数为0那么意味着没有超时控制,对网卡的读操作在没有数据到来是将永远堵塞。如果为-1那么对网卡的读操作将立即返回不管有没有数据可读。#include pcap.h/* prototype of the packet
25、 handler */void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data);main()pcap_if_t *alldevs;pcap_if_t *d;int inum;int i=0;pcap_t *adhandle;char errbufPCAP_ERRBUF_SIZE;/* 获得网卡的列表 */if (pcap_findalldevs(&alldevs, errbuf) = -1)fprintf(stderr,Error in pcap_findalldev
26、s: %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);elseprintf( (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);/* Free the device list */pcap_freealldevs(alldevs);return -1;/* 找到要选择的网卡结构 */for(d=alldevs, i=0;
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1