WinPcap文档翻译第三章

本文档翻译自WinPcap开发包,重点介绍了如何打开网络适配器并捕获数据包。讲解了pcap_open()函数的参数含义,如snaplen、flags和to_ms,并提供了一个示例程序,该程序打印每个通过适配器传输的包的信息。程序展示了如何处理捕获的包,包括获取时间戳和长度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

<!-- @page { margin: 2cm } P { margin-bottom: 0.21cm } -->

WinPcap 导引:使用WinPcap 简明指导

WinPcap tutorial:a step by step guide to using WinPcap

翻译自WinPcap 开发包的帮助文档- 俞凌峰

 

第三篇: 打开网络适配器和捕获数据包

Opening an adapter and capturing the pcakets

Now that we've seen how to obtain an adapter to play with,let's start the real job,opening an adapter and capturing some traffic.In this lesson we'll write a program that prints some information about each packet flowing through the adapter.

到现在为止,我们已经知道了如何获得一个网络适配器,那就让我们开始真正的工作吧!开打一个网络适配器并捕获一些网络数据。在本章中,我们将会编写一个能打印通过一个特定网络适配器传输的网络数据包的某些信息的程序。

The function that opens a capture device is pcap_open().The parameters,snaplen,flags and to_ms deserve some explanation.

snaplen specifies the portion of the pcaket to capture.On some Oses(like xBSD and Win32),the packet driver can be configured to capture only the initial part of any packet:this decreases the amount of data to copy to the application and therefore improves the efficiency of the capture.In this case we use the value 65536 which is higher than the greatest MTU that we could encounter.In this manner we ensure that the application will always receive the whole packet.

flags: the most important flag is the one that indicates if the adapter will be put in promiscuous mode.In normal operation,an adapter only captures packets from the network that are destined to it;the pcakets exchanged by other hosts are therefore ignored.Instead,when the adapter is in promiscuous mode it captures all packets whether they are destined to it or not.This means that on shared media(like non-switched Ethernet),WinPcap will be able to capture the packets of other hosts.Promiscuous mode is the default for most capture applications,so we enable it in the following example.

to_ms specifies the read timeout,in millseconds.A read on the adapter(for example,with pcap_dispatch() or pcap_next_ex())will always return after to_ms millseconds,enen if no pcakets are available from the network.to_ms also defines the interval between statistical reports if the adapter is in statistical mode(see the lesson “/ref wpcap_tut9”for information about statistical mode).Setting to_ms to 0 means no timeout,a read on the adapter never returns if no packets arrive.A -1 timeout on the other side causes a read on the adapter to always return immediately.

打开一个捕获设备的函数是pcap_open() 。该函数参数是snaplen,flags,to_ms, 下面分别是各个参数的解释说明。

snaplen 指明了捕获数据包的哪一部分。在有些操作系统中(如xBSD 系统和Win32 系统),包捕获驱动可以配置成只捕获每个数据包的初始化部分:这能减少网络拷贝到应用程序中的数据从而提高了捕获的效率。在本例中我们设置该参数值为65536 ,这个参数值大大超过了链路层MTUMTU 既最大传输单元,为某些链路的最大传输上限值) 。这样做我们可以确保我们的应用程序能接受到一个完整的网络数据包。

flags: 最重要的flags 值是用于设置适配器进入混杂模式( 什么是混杂模式? 查资料!) 的。在普通操作模式下,一个网络适配器只能捕获那些目的地为本地的网络包。和本地主机无关的网络包将会被适配器忽略。与此相反的是,当设配器设置成混杂模式后,其能捕获所有的网络包无论是否和本地主机有关。

这意味着在共享型媒体( 比如非交换型以太网)中,WinPcap 能捕获其他主机的网络包。混杂模式是大多数网络包捕获程序的默认模式,所以在本例中我们也使用该模式。

to_ms 指定了读取的超时时间,以毫秒计。读取网络适配器(比如,函数pcap_dispatch() 或者pcap_next_ex()) 在经过to_ms 毫秒的时间后会马上返回,即使没有任何网络数据包读取到。to_ms 还用于指定当你把适配器设置为统计模式时统计的时间间隔。(参看”ref wpcap_tut9” 可以得到更多关于统计模式的信息) 。将to_ms 设置为0 意味着没有超时设置,读取网络适配器时只有当有数据时才会返回。to_ms 设置成-1 则将使对适配器的读取马上就返回而无论是否读取到数据。

 

/*code

 

#include “pcap.h”

 

/*prototype of the packet 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 errbuf[PCAP_ERRBUF_SIZE];

 

/*Retrieve the device list on the local machine*/

if(pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs,errbuf) == -1)

{

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”);

}

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 < 1 || inum > I)

{

printf(“/ninterface number out of range./n”);

/*Free the device list*/

pcap_freealldevs(alldevs);

return -1;

}

 

/*jump to the selected adapter */

for(d=alldevs, i=0; i< inum-1; d=d->next, i++);

 

/*Open the device*/

if((adhandle = pcap_open(d->name, // name of the device

65536, //portion of the packet to capture

PCAP_OPENFLAG_PROMISCUOUS, //promiscuous mode

1000, //read timeout

NULL, //authentication on the remote

// machine

errbuf //error buffer

)) == NULL)

{

fprintf(stderr,”/nUnable to open the adapter.%s is not supported by WinPcap/n”, d->name);

/*Free the device list*/

pcap_freealldevs(alldevs);

return -1;

}

 

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

 

/*At the point,we don't need any more the device list.Free it*/

pcap_freealldevs(alldevs);

 

/*start the capture*/

pcap_loop(adhandle, 0, packet_handler, NULL);

 

return 0;

}

 

/*Callback function invoked by libpcap for every incoming packet*/

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;

 

/*convert the timestamp to readable format*/

local_tv_sec = header->ts.tv_sec;

ltime = localtime(&local_tv_sec);

strftime(timestr, sizeof(timestr), “%H:%M:%S”,ltime);

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

}

 

code*/

 

Once the adapter is opened,the capture can be started with pcap_dispatch() or pcap_loop().These two functions are very similar,the difference is that pcap_dispatch() returns (although not guaranteed)when the timeout expires while pcap_loop() doesn't return until cnt packets have been captured, so it can block for an arbitrary period on an under-utilized network.pcap_loop() is enough for the purpose of this sample,while pcap_dispatch() is normally used in a more complex program.

一旦网络适配器被打开,捕捉网络数据包可以通过函数pcap_dispatch()pcap_loop 开始。这二个函数十分的相似,区别在于当超时时,函数pcap_dispatch() 函数将马上返回( 尽管无法确保) 而函数pcap_loop() 函数只有处理完cnt( 既该函数的第二个参数) 个网络报文后才会返回,所有函数pcap_loop() 在那些利用不足不稳定的网络中容易阻塞。在本例中函数pcap_loop() 已经完全能满足我们的需要了,pcap_dispatch() 函数一般用在复杂的程序中。

Both of these functions have a callback parameter,packet_handler,pointing to a function that will receive the packets.This function is invoked by libpcap for every new packet coming from the network and receives a generic status(corresponding to the user parameter of pcap_loop() and pcap_dispatch()),a header with some information on the packet like the timestamp and the length and the actual data of the packet including all the protocol headers.Note that the frame CRC is normally not present,because it is removed by the network adapter after frame validation. Note also that most adapters discard packets with wrong CRCs,therefore WinPcap is normally not able to capture them.

这二个函数都有一个回调函数参数,packet_handler, 一个指向接收处理函数的函数指针。这个接收处理函数将会在有新数据包来时,由libpcap 库自己去调用并同时会返回对应的数据包状态(对应于函数pcap_loop()pcap_dispatch() 的参数), 参数header 中包含了数据包的通用信息类似于时间戳,

实际上的数据包数据长度等信息。要注意的是,帧的CRC 校验将不存在,因为网络适配器在经过CRC 校验后就会把该字段删除。还要注意的是大部分网络适配器将会丢弃CRC 校验错误的数据包,对于此类数据包,WinPcap 一般也无法捕获。

The above example extracts the timestamp and the length of every packet from the pcap_pkthdr header and prints them on the screen.

上面的代码演示从pcap_pkthdr 结构头中提取出每个数据包的时间信息和长度并打印在屏幕上。

Please note that there may be a drawback using pcap_loop() mainly related to the fact that the handler is called by the packet capture driver;therefore the user application does not have direct control over it.Another approach(and to have more readable programs)is to use the pcap_next_ex() function,which is presented in the next example(Capturing the packets without the callback).

请注意使用pcap_loop() 函数可能有一个缺点,该缺点是由于该函数的回调函数是由驱动层调用的这个事实相关所引起的。因此用户程序无法直接控制它。还有使用pcap_next_ex() 函数的演示将会在下面文档中描述( 不使用回调函数来捕捉数据包)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值