1.WinPcap教程:循序渐进教您使用WinPcap 本节将向您显示如何使用WinPcapAPI的一些特性。本教程被组织成一系列课程,以循序渐进的方式,让读者从最基本的部分(获得设备列表)到最复杂的部分(控制发送队列并收集和统计网络流量)来了解如何使用WinPcap进行程序开
1. WinPcap教程:循序渐进教您使用WinPcap
本节将向您显示如何使用WinPcapAPI的一些特性。本教程被组织成一系列课程,以循序渐进的方式,让读者从最基本的部分(获得设备列表)到最复杂的部分(控制发送队列并收集和统计网络流量)来了解如何使用WinPcap进行程序开发。
我们会提供几个简单但是完整的程序(代码片断)作为参考:所有的源代码中都包含一些指向手册其他地方的链接,这可以让您很方便地通过点击函数和数据结构跳转到相关的文档处。
范例程序都是使用纯C语言编写的, 所以掌握基本的C语言编程知识是必须的,而且这是一个关于处理“原始”网络数据包的教程,所以我们希望读者拥有良好的网络及网络协议的基本知识。
1.1. 获取设备列表
通常,编写基于WinPcap应用程序的第一件事情就是获得已连接的网络适配器列表。libpcap和WinPcap都提供了 pcap_findalldevs_ex() 函数来实现这个功能: 这个函数返回一个pcap_if结构的链表, 每个pcap_if结构都包含一个适配器的详细信息。值得注意的是,数据域name和description分别表示一个适配器名称和一个人们可读的描述。
下列代码用于获取适配器列表,并在屏幕上显示出来,如果没有找到适配器,将打印一个错误信息。
#include"pcap.h"
int main()
{
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 inpcap_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 descriptionavailable)\n");
}
if (i == 0)
{
printf("\nNo interfaces found!Make sure WinPcap is installed.\n");
return;
}
/* 不再需要设备列表了,释放它 */
pcap_freealldevs(alldevs);
}
有关这段代码的一些说明。
首先,与其他libpcap函数一样,pcap_findalldevs_ex()有一个 errbuf 参数。一旦发生错误,由libpcap把错误描述写入到该字符串中。
第二,请记住不是所有的操作系统都支持libpcap提供的网络程序接口,因此,如果我们想编写一个可移植的应用程序,我们就必须考虑在什么情况下,description 是null。本程序中,我们遇到这种情况时,会打印一个提示语句“No description available”。
最后要记住,当我们完成了设备列表的使用,我们要调用 pcap_freealldevs() 函数将其占用的内存资源释放掉。
让我们编译并运行我们的第一个示例程序吧!为了能在Unix或Cygwin平台上编译这段程序,需要简单输入:
gcc -o testprog testprog.c -lpcap
在Windows平台上,您需要创建一个工程,并按照“使用WinPcap编程”里的步骤做。然而,我们建议您使用WinPcap developer's pack (详情请访问WinPcap网站,http://www.winpcap.org ), 因为它提供了很多已经配置好的范例,包括本教程中所有的示例代码,以及在编译运行时需要的包含文件(include) 和动态库文件(libraries)。
假设我们已经完成了对程序的编译,那让我们来运行它吧。在某台WinXP的电脑上,获得的结果是:
1.\Device\NPF_{4E273621-5161-46C8-895A-48D0E52A0B83} (Realtek RTL8029(AS)Ethernet Adapter)
2.\Device\NPF_{5D24AE04-C486-4A96-83FB-8B5EC6C7F430} (3Com EtherLink PCI)
正如您看到的,Windows平台下的网络适配器的名字(当打开设备的时候,把它传递给libpcap库)是相当不可读的,因此解释性的描述是非常有帮助阿!
1.2. 获取已安装设备的高级信息
在第1讲(获取设备列表) 中,我们展示了如何获取适配器的基本信息 (如设备的名称和描述)。事实上,WinPcap提供了其他更高级的信息。特别需要指出的是:由 pcap_findalldevs_ex() 返回的每一个pcap_if结构体,都包含一个pcap_addr的结构体,这个结构体由如下元素组成:
l 一个地址列表
l 一个掩码列表 (eachof which corresponds to an entry in the addresses list).
l 一个广播地址列表(each of which corresponds to an entry in the addresses list).
l 一个目的地址列表(each of which corresponds to an entry in the addresses list).
另外,函数pcap_findalldevs_ex()可以返回远程适配器信息和一个位于给定本地目录下pcap文件列表。
下面的范例使用ifprint()函数打印出 pcap_if结构体中所有的内容。程序对每一个由 pcap_findalldevs_ex()函数返回的pcap_if都调用ifprint()函数来实现打印。
/*
* Copyright (c) 1999 - 2005 NetGroup,Politecnico di Torino (Italy)
* Copyright (c) 2005 - 2006 CACE Technologies,Davis (California)
* All rights reserved.
*
* Redistribution and use in source and binaryforms, with or without
* modification, are permitted provided thatthe following conditions
* are met:
*
* 1. Redistributions of source code mustretain the above copyright
* notice, this list of conditions and thefollowing disclaimer.
* 2. Redistributions in binary form mustreproduce the above copyright
* notice, this list of conditions and thefollowing disclaimer in the
* documentation and/or other materialsprovided with the distribution.
* 3. Neither the name of the Politecnico diTorino, CACE Technologies
* nor the names of its contributors may beused to endorse or promote
* products derived from this software withoutspecific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHTHOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIEDWARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OFMERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NOEVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODSOR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION)HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT,STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISINGIN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF SUCH DAMAGE.
*
*/
#include"pcap.h"
#ifndef WIN32
#include
#include
#else
#include
#endif
// 函数原型
voidifprint(pcap_if_t *d);
char*iptos(u_long in);
char*ip6tos(struct sockaddr *sockaddr, char *address, int addrlen);
int main()
{
pcap_if_t *alldevs;
pcap_if_t *d;
char errbuf[PCAP_ERRBUF_SIZE+1];
char source[PCAP_ERRBUF_SIZE+1];
printf("Enter the device you want tolist:\n"
"rpcap:// ==> lists interfaces in thelocal machine\n"
"rpcap://hostname:port ==>lists interfaces in a remote machine\n"
" (rpcapd daemon mustbe up and running\n"
" and it must accept'null' authentication)\n"
"file://foldername ==> lists all pcap files in the givefolder\n\n"
"Enter your choice: ");
fgets(source, PCAP_ERRBUF_SIZE, stdin);
source[PCAP_ERRBUF_SIZE] = '\0';
/* 获得接口列表 */
if (pcap_findalldevs_ex(source, NULL,&alldevs, errbuf) == -1)
{
fprintf(stderr,"Er