循序渐进学习使用WINPCAP(三)

来源:互联网 发布:2016淘宝流量突然暴跌 编辑:程序博客网 时间:2024/05/26 07:29

打开网卡捕获数据包

现在我门已经知道了如何去获得网卡的信息现在就让我们开始真正的工作:打开网卡并捕获数据流。在这一节,我们将写一个打印流经网络的每个数据包信息的程序。打开网卡的功能是通过pcap_open()来实现的。该函数有三个参数snaplen,flags,to_ms,下面依次解释:

snaplen用于指定所要捕获包的特定部分,在一些系统上(象xBSD and Win32)驱动可以通过配置只捕获数据包的开始一部分而不是全部,这样就减少了拷贝数据的数量从而提高了包捕获的效率。在这个例子中,我们用高过可能遇到的最大传输单元的值65536。用这种方式我们能够保证应用程序总会得到整个包。

flags:用来表明适配器是否处于混杂模式的标识是最重要的标识(flag)。在正常操作下,适配器(网卡)只会接受去往它的包而去往其他主机的数据包则被忽略。相反,当适配器处于混杂模式时他将接收所有的流经它的数据包:这就意味着在共享介质(就像non-switched Ethernet)的情况下,WinPcap可以捕获到其它主机的数据包。大部分的包捕获程序都将混杂模式设为默认,所以我们在下面的例子里也将网卡设为混杂模式。

to_ms 参数指定读数据的超时控制,超时以毫秒计算。当在超时时间内网卡上没有数据到来时对网卡的读操作将返回(如使用pcap_dispatch() 或 pcap_next_ex()等函数)。还有,如果网卡处于统计模式下(请查看“统计和收集网络数据流一节”),to_ms还定义了统计的时间间隔。如果该参数为0,那么意味着没有超时控制。对网卡的读操作在没有数据到来是将永远堵塞。如果为-1那么对网卡的读操作将立即返回,不管有没有数据可读。

 

一旦网卡被打开,就可以调用pcap_dispatch() 或pcap_loop()进行数据的捕获,这两个函数的功能十分相似。不同的是pcap_ dispatch()当超时发生时就会返回(尽管不被保证),可以不被阻塞;而pcap_loop()在没有数据流到达时将阻塞。在这个简单的例子里用pcap_loop()就足够了,而在一些复杂的程序里往往用pcap_dispatch()。

这两个函数都有返回的参数——packet_handler,一个指向接受数据包的函数的指针。当有数据包从网络上到来时,libpcap调用该函数。该函数同时会接受一个一般的状态(与pcap_loop()和pcap_dispatch()函数的用户参数相对应),一个包含关于包的信息(如时间戳、长度)的头,最后一个是含有所有协议头部数据报的实际数据。注意MAC的冗余校验码一般不出现,因为当一个桢到达并被确认后网卡就把它删除了。同样需要注意的是大多数网卡会丢掉冗余码出错的数据包,所以WinPcap一般不能够捕获这些出错的数据报。

上面的例子里从pcap_pkthdr中提取出了每个数据报的时间戳和长度并在显示器上打印出了他们。

请注意使用pcap_loop()可能有个缺点,主要是因为那个指针(packet_handler)是被抓包驱动调用,所以用户应用对它没有直接控制权。另外一个方法(使程序更易读)就是使用pcap_next_ex()函数(在下一个例子中呈现)

附原文:

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 packet 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 packets 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 milliseconds. A read on the adapter (for example, with pcap_dispatch() or pcap_next_ex()) will always return after to_ms milliseconds, even if no packets 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.

/* codes */

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.

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.

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

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).

#end