mirror of
https://github.com/holub/mame
synced 2025-04-28 11:11:48 +03:00
141 lines
16 KiB
HTML
141 lines
16 KiB
HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
|
<title>WinPcap: Opening an adapter and capturing the packets</title>
|
|
<link href="tabs.css" rel="stylesheet" type="text/css"/>
|
|
<link href="style.css" rel="stylesheet" type="text/css"/>
|
|
</head>
|
|
<body>
|
|
<!-- Generated by Doxygen 1.6.1 -->
|
|
<div class="navigation" id="top">
|
|
<div class="tabs">
|
|
<ul>
|
|
<li><a href="main.html"><span>Main Page</span></a></li>
|
|
<li><a href="pages.html"><span>Related Pages</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>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="contents">
|
|
<h1>Opening an adapter and capturing the packets</h1><table border="0" cellpadding="0" cellspacing="0">
|
|
</table>
|
|
<p>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>
|
|
<p>The function that opens a capture device is <a class="el" href="group__wpcapfunc.html#ga2b64c7b6490090d1d37088794f1f1791" title="Open a generic source in order to capture / send (WinPcap only) traffic.">pcap_open()</a>. The parameters, <em>snaplen</em>, <em>flags</em> and <em>to_ms</em> deserve some explanation.</p>
|
|
<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>
|
|
<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>
|
|
<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#ga60ce104cdf28420d3361cd36d15be44c" title="Collect a group of packets.">pcap_dispatch()</a> or <a class="el" href="group__wpcapfunc.html#ga439439c2eae61161dc1efb1e03a81133" title="Read a packet from an interface or from an offline capture.">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" title="Header of a packet in the dump file.">pcap_pkthdr</a> *header, <span class="keyword">const</span> u_char *pkt_data);
|
|
|
|
<span class="keywordtype">int</span> main()
|
|
{
|
|
<a class="code" href="structpcap__if.html" title="Item in a list of interfaces, used by pcap_findalldevs().">pcap_if_t</a> *alldevs;
|
|
<a class="code" href="structpcap__if.html" title="Item in a list of interfaces, used by pcap_findalldevs().">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#ga4711d025f83503ce692efa5e45ec60a7" title="Descriptor of an open capture instance. This structure is opaque to the user, that...">pcap_t</a> *adhandle;
|
|
<span class="keywordtype">char</span> errbuf[<a class="code" href="group__wpcap__def.html#gacd448353957d92c98fccc29e1fc8d927" title="Size to use when allocating the buffer that contains the libpcap errors.">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#ga98f36e62c95c6ad81eaa8b2bbeb8f16e" title="Create a list of network devices that can be opened with pcap_open().">pcap_findalldevs_ex</a>(<a class="code" href="group__remote__source__string.html#ga6d7103b8a7e1eca8c325bd8f32c361c3" title="String that will be used to determine the type of source in use (file, remote/local...">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#a81508e6e4e41ca4235c8d6b51913c536" title="if not NULL, a pointer to the next element in the list; NULL for the last element...">next</a>)
|
|
{
|
|
printf(<span class="stringliteral">"%d. %s"</span>, ++i, d-><a class="code" href="structpcap__if.html#a5ac083a645d964373f022d03df4849c8" title="a pointer to a string giving a name for the device to pass to pcap_open_live()">name</a>);
|
|
<span class="keywordflow">if</span> (d-><a class="code" href="structpcap__if.html#a8444d6e0dfe2bbab0b5e7b24308f1559" title="if not NULL, a pointer to a string giving a human-readable description of the device...">description</a>)
|
|
printf(<span class="stringliteral">" (%s)\n"</span>, d-><a class="code" href="structpcap__if.html#a8444d6e0dfe2bbab0b5e7b24308f1559" title="if not NULL, a pointer to a string giving a human-readable description of the device...">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_s(<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#ga346b4b0b7fd1cda4abb9a39f767dbeb1" title="Free an interface list returned by pcap_findalldevs().">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#a81508e6e4e41ca4235c8d6b51913c536" title="if not NULL, a pointer to the next element in the list; NULL for the last element...">next</a>, i++);
|
|
|
|
<span class="comment">/* Open the device */</span>
|
|
<span class="keywordflow">if</span> ( (adhandle= <a class="code" href="group__wpcapfunc.html#ga2b64c7b6490090d1d37088794f1f1791" title="Open a generic source in order to capture / send (WinPcap only) traffic.">pcap_open</a>(d-><a class="code" href="structpcap__if.html#a5ac083a645d964373f022d03df4849c8" title="a pointer to a string giving a name for the device to pass to pcap_open_live()">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#ga9134ce51a9a6a7d497c3dee5affdc3b9" title="Defines if the adapter has to go in promiscuous mode.">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#a5ac083a645d964373f022d03df4849c8" title="a pointer to a string giving a name for the device to pass to pcap_open_live()">name</a>);
|
|
<span class="comment">/* Free the device list */</span>
|
|
<a class="code" href="group__wpcapfunc.html#ga346b4b0b7fd1cda4abb9a39f767dbeb1" title="Free an interface list returned by pcap_findalldevs().">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#a8444d6e0dfe2bbab0b5e7b24308f1559" title="if not NULL, a pointer to a string giving a human-readable description of the device...">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#ga346b4b0b7fd1cda4abb9a39f767dbeb1" title="Free an interface list returned by pcap_findalldevs().">pcap_freealldevs</a>(alldevs);
|
|
|
|
<span class="comment">/* start the capture */</span>
|
|
<a class="code" href="group__wpcapfunc.html#ga6bcb7c5c59d76ec16b8a699da136b5de" title="Collect a group of packets.">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" title="Header of a packet in the dump file.">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">/*</span>
|
|
<span class="comment"> * unused variables</span>
|
|
<span class="comment"> */</span>
|
|
(VOID)(param);
|
|
(VOID)(pkt_data);
|
|
|
|
<span class="comment">/* convert the timestamp to readable format */</span>
|
|
local_tv_sec = header-><a class="code" href="structpcap__pkthdr.html#a21be78b2818c91cb205885b8a6f5aed8" title="time stamp">ts</a>.tv_sec;
|
|
localtime_s(&ltime, &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#a21be78b2818c91cb205885b8a6f5aed8" title="time stamp">ts</a>.tv_usec, header-><a class="code" href="structpcap__pkthdr.html#a728f264db4f5cc304742565a2bcdbeea" title="length this packet (off wire)">len</a>);
|
|
|
|
}
|
|
</pre></div><p>Once the adapter is opened, the capture can be started with <a class="el" href="group__wpcapfunc.html#ga60ce104cdf28420d3361cd36d15be44c" title="Collect a group of packets.">pcap_dispatch()</a> or <a class="el" href="group__wpcapfunc.html#ga6bcb7c5c59d76ec16b8a699da136b5de" title="Collect a group of packets.">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#ga6bcb7c5c59d76ec16b8a699da136b5de" title="Collect a group of packets.">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#ga6bcb7c5c59d76ec16b8a699da136b5de" title="Collect a group of packets.">pcap_loop()</a> is enough for the purpose of this sample, while <a class="el" href="group__wpcapfunc.html#ga60ce104cdf28420d3361cd36d15be44c" title="Collect a group of packets.">pcap_dispatch()</a> is normally used in a more complex program.</p>
|
|
<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#ga6bcb7c5c59d76ec16b8a699da136b5de" title="Collect a group of packets.">pcap_loop()</a> and <a class="el" href="group__wpcapfunc.html#ga60ce104cdf28420d3361cd36d15be44c" title="Collect a group of packets.">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>
|
|
<p>The above example extracts the timestamp and the length of every packet from the <a class="el" href="structpcap__pkthdr.html" title="Header of a packet in the dump file.">pcap_pkthdr</a> header and prints them on the screen.</p>
|
|
<p>Please note that there may be a drawback using <a class="el" href="group__wpcapfunc.html#ga6bcb7c5c59d76ec16b8a699da136b5de" title="Collect a group of packets.">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#ga439439c2eae61161dc1efb1e03a81133" title="Read a packet from an interface or from an offline capture.">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>
|
|
<p><a class="el" href="group__wpcap__tut2.html"><<< Previous</a> <a class="el" href="group__wpcap__tut4.html">Next >>></a> </p>
|
|
</div>
|
|
|
|
<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-2009
|
|
CACE Technologies. All rights reserved.</p>
|