📄 group__wpcap__tut3.html
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1"><title>WinPcap: Opening an adapter and capturing the packets</title><link href="style.css" rel="stylesheet" type="text/css"><link href="tabs.css" rel="stylesheet" type="text/css"></head><body><!-- Generated by Doxygen 1.5.1 --><div class="tabs"> <ul> <li><a href="main.html"><span>Main Page</span></a></li> <li><a href="modules.html"><span>Modules</span></a></li> <li><a href="annotated.html"><span>Data Structures</span></a></li> <li><a href="files.html"><span>Files</span></a></li> <li><a href="pages.html"><span>Related Pages</span></a></li> </ul></div><h1>Opening an adapter and capturing the packets</h1><table border="0" cellpadding="0" cellspacing="0"><tr><td></td></tr></table>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.<p>The function that opens a capture device is <a class="el" href="group__wpcapfunc.html#g2b64c7b6490090d1d37088794f1f1791">pcap_open()</a>. The parameters, <em>snaplen</em>, <em>flags</em> and <em>to_ms</em> deserve some explanation.<p><em>snaplen</em> 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.<p><em>flags:</em> 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.<p><em>to_ms</em> specifies the read timeout, in milliseconds. A read on the adapter (for example, with <a class="el" href="group__wpcapfunc.html#g60ce104cdf28420d3361cd36d15be44c">pcap_dispatch()</a> or <a class="el" href="group__wpcapfunc.html#g439439c2eae61161dc1efb1e03a81133">pcap_next_ex()</a>) will always return after <em>to_ms</em> milliseconds, even if no packets are available from the network. <em>to_ms</em> 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 <em>to_ms</em> 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.<p><div class="fragment"><pre class="fragment"><span class="preprocessor">#include "pcap.h"</span><span class="comment">/* prototype of the packet handler */</span><span class="keywordtype">void</span> packet_handler(u_char *param, <span class="keyword">const</span> <span class="keyword">struct</span> <a class="code" href="structpcap__pkthdr.html">pcap_pkthdr</a> *header, <span class="keyword">const</span> u_char *pkt_data);main(){<a class="code" href="structpcap__if.html">pcap_if_t</a> *alldevs;<a class="code" href="structpcap__if.html">pcap_if_t</a> *d;<span class="keywordtype">int</span> inum;<span class="keywordtype">int</span> i=0;<a class="code" href="group__wpcap__def.html#g4711d025f83503ce692efa5e45ec60a7">pcap_t</a> *adhandle;<span class="keywordtype">char</span> errbuf[<a class="code" href="group__wpcap__def.html#gcd448353957d92c98fccc29e1fc8d927">PCAP_ERRBUF_SIZE</a>]; <span class="comment">/* Retrieve the device list on the local machine */</span> <span class="keywordflow">if</span> (<a class="code" href="group__wpcapfunc.html#g98f36e62c95c6ad81eaa8b2bbeb8f16e">pcap_findalldevs_ex</a>(<a class="code" href="group__remote__source__string.html#g6d7103b8a7e1eca8c325bd8f32c361c3">PCAP_SRC_IF_STRING</a>, NULL, &alldevs, errbuf) == -1) { fprintf(stderr,<span class="stringliteral">"Error in pcap_findalldevs: %s\n"</span>, errbuf); exit(1); } <span class="comment">/* Print the list */</span> <span class="keywordflow">for</span>(d=alldevs; d; d=d-><a class="code" href="structpcap__if.html#81508e6e4e41ca4235c8d6b51913c536">next</a>) { printf(<span class="stringliteral">"%d. %s"</span>, ++i, d-><a class="code" href="structpcap__if.html#5ac083a645d964373f022d03df4849c8">name</a>); if (d-><a class="code" href="structpcap__if.html#8444d6e0dfe2bbab0b5e7b24308f1559">description</a>) printf(<span class="stringliteral">" (%s)\n"</span>, d-><a class="code" href="structpcap__if.html#8444d6e0dfe2bbab0b5e7b24308f1559">description</a>); <span class="keywordflow">else</span> printf(<span class="stringliteral">" (No description available)\n"</span>); } <span class="keywordflow">if</span>(i==0) { printf(<span class="stringliteral">"\nNo interfaces found! Make sure WinPcap is installed.\n"</span>); <span class="keywordflow">return</span> -1; } printf(<span class="stringliteral">"Enter the interface number (1-%d):"</span>,i); scanf(<span class="stringliteral">"%d"</span>, &inum); <span class="keywordflow">if</span>(inum < 1 || inum > i) { printf(<span class="stringliteral">"\nInterface number out of range.\n"</span>); <span class="comment">/* Free the device list */</span> <a class="code" href="group__wpcapfunc.html#g346b4b0b7fd1cda4abb9a39f767dbeb1">pcap_freealldevs</a>(alldevs); <span class="keywordflow">return</span> -1; } <span class="comment">/* Jump to the selected adapter */</span> <span class="keywordflow">for</span>(d=alldevs, i=0; i< inum-1 ;d=d-><a class="code" href="structpcap__if.html#81508e6e4e41ca4235c8d6b51913c536">next</a>, i++); <span class="comment">/* Open the device */</span> <span class="keywordflow">if</span> ( (adhandle= <a class="code" href="group__wpcapfunc.html#g2b64c7b6490090d1d37088794f1f1791">pcap_open</a>(d-><a class="code" href="structpcap__if.html#5ac083a645d964373f022d03df4849c8">name</a>, <span class="comment">// name of the device</span> 65536, <span class="comment">// portion of the packet to capture</span> <span class="comment">// 65536 guarantees that the whole packet will be captured on all the link layers</span> <a class="code" href="group__remote__open__flags.html#g9134ce51a9a6a7d497c3dee5affdc3b9">PCAP_OPENFLAG_PROMISCUOUS</a>, <span class="comment">// promiscuous mode</span> 1000, <span class="comment">// read timeout</span> NULL, <span class="comment">// authentication on the remote machine</span> errbuf <span class="comment">// error buffer</span> ) ) == NULL) { fprintf(stderr,<span class="stringliteral">"\nUnable to open the adapter. %s is not supported by WinPcap\n"</span>, d-><a class="code" href="structpcap__if.html#5ac083a645d964373f022d03df4849c8">name</a>); <span class="comment">/* Free the device list */</span> <a class="code" href="group__wpcapfunc.html#g346b4b0b7fd1cda4abb9a39f767dbeb1">pcap_freealldevs</a>(alldevs); <span class="keywordflow">return</span> -1; } printf(<span class="stringliteral">"\nlistening on %s...\n"</span>, d-><a class="code" href="structpcap__if.html#8444d6e0dfe2bbab0b5e7b24308f1559">description</a>); <span class="comment">/* At this point, we don't need any more the device list. Free it */</span> <a class="code" href="group__wpcapfunc.html#g346b4b0b7fd1cda4abb9a39f767dbeb1">pcap_freealldevs</a>(alldevs); <span class="comment">/* start the capture */</span> <a class="code" href="group__wpcapfunc.html#g6bcb7c5c59d76ec16b8a699da136b5de">pcap_loop</a>(adhandle, 0, packet_handler, NULL); <span class="keywordflow">return</span> 0;}<span class="comment">/* Callback function invoked by libpcap for every incoming packet */</span><span class="keywordtype">void</span> packet_handler(u_char *param, <span class="keyword">const</span> <span class="keyword">struct</span> <a class="code" href="structpcap__pkthdr.html">pcap_pkthdr</a> *header, <span class="keyword">const</span> u_char *pkt_data){ <span class="keyword">struct </span>tm *ltime; <span class="keywordtype">char</span> timestr[16]; time_t local_tv_sec; <span class="comment">/* convert the timestamp to readable format */</span> local_tv_sec = header-><a class="code" href="structpcap__pkthdr.html#21be78b2818c91cb205885b8a6f5aed8">ts</a>.tv_sec; ltime=localtime(&local_tv_sec); strftime( timestr, <span class="keyword">sizeof</span> timestr, <span class="stringliteral">"%H:%M:%S"</span>, ltime); printf(<span class="stringliteral">"%s,%.6d len:%d\n"</span>, timestr, header-><a class="code" href="structpcap__pkthdr.html#21be78b2818c91cb205885b8a6f5aed8">ts</a>.tv_usec, header-><a class="code" href="structpcap__pkthdr.html#728f264db4f5cc304742565a2bcdbeea">len</a>); }</pre></div><p>Once the adapter is opened, the capture can be started with <a class="el" href="group__wpcapfunc.html#g60ce104cdf28420d3361cd36d15be44c">pcap_dispatch()</a> or <a class="el" href="group__wpcapfunc.html#g6bcb7c5c59d76ec16b8a699da136b5de">pcap_loop()</a>. These two functions are very similar, the difference is that pcap_ dispatch() returns (although not guaranteed) when the timeout expires while <a class="el" href="group__wpcapfunc.html#g6bcb7c5c59d76ec16b8a699da136b5de">pcap_loop()</a> doesn't return until <em>cnt</em> packets have been captured, so it can block for an arbitrary period on an under-utilized network. <a class="el" href="group__wpcapfunc.html#g6bcb7c5c59d76ec16b8a699da136b5de">pcap_loop()</a> is enough for the purpose of this sample, while <a class="el" href="group__wpcapfunc.html#g60ce104cdf28420d3361cd36d15be44c">pcap_dispatch()</a> is normally used in a more complex program.<p>Both of these functions have a <em>callback</em> parameter, <em>packet_handler</em>, 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 <em>user</em> parameter of <a class="el" href="group__wpcapfunc.html#g6bcb7c5c59d76ec16b8a699da136b5de">pcap_loop()</a> and <a class="el" href="group__wpcapfunc.html#g60ce104cdf28420d3361cd36d15be44c">pcap_dispatch()</a>), 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.<p>The above example extracts the timestamp and the length of every packet from the <a class="el" href="structpcap__pkthdr.html">pcap_pkthdr</a> header and prints them on the screen.<p>Please note that there may be a drawback using <a class="el" href="group__wpcapfunc.html#g6bcb7c5c59d76ec16b8a699da136b5de">pcap_loop()</a> 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 <a class="el" href="group__wpcapfunc.html#g439439c2eae61161dc1efb1e03a81133">pcap_next_ex()</a> function, which is presented in the next example (<a class="el" href="group__wpcap__tut4.html">Capturing the packets without the callback</a>).<p><a class="el" href="group__wpcap__tut2.html"><<< Previous</a> <a class="el" href="group__wpcap__tut4.html">Next >>></a> <hr><p align="right"><img border="0" src="winpcap_small.gif" align="absbottom" width="91" height="27">documentation. Copyright (c) 2002-2005 Politecnico di Torino. Copyright (c) 2005-2007 CACE Technologies. All rights reserved.</p>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -