1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741 |
- <html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>Npcap Development Tutorial</title><meta name="generator" content="DocBook XSL Stylesheets V1.79.2"><meta name="description" content="A step-by-step guide to writing software that uses Npcap to list network adapters, capture packets, and send network traffic."><link rel="home" href="index.html" title="Npcap Reference Guide"><link rel="up" href="index.html" title="Npcap Reference Guide"><link rel="prev" href="npcap-api.html" title="The Npcap API"><link rel="next" href="npcap-internals.html" title="Npcap internals"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Npcap Development Tutorial</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="npcap-api.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="npcap-internals.html">Next</a></td></tr></table><hr></div><div class="sect1"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="npcap-tutorial"></a>Npcap Development Tutorial</h2></div><div><div class="abstract"><p class="title"><b>Abstract</b></p>
- <p>A step-by-step guide to writing software that uses Npcap to list
- network adapters, capture packets, and send network traffic.</p>
- </div></div></div></div>
-
-
- <p>This section shows how to use the features of the Npcap API. It is
- organized as a tutorial, subdivided into a set of lessons that will
- introduce the reader, in a step-by-step fashion, to program development
- using Npcap, from the basic functions (obtaining the adapter list,
- starting a capture, etc.) to the most advanced ones (handling send queues
- and gathering statistics about network traffic).</p>
-
- <p>The samples are written in plain C, so a basic knowledge of C
- programming is required. Also, since this is a tutorial about a library
- dealing with "raw" networking packets, good knowledge of networks and
- network protocols is assumed.</p>
- <p>The code in this section is copied from the <a class="xref" href="npcap-devguide.html#npcap-examples" title="Examples">the section called “Examples”</a> in the source
- distribution and the SDK. The code is released under a BSD-3-clause license and
- copyright: NetGroup, Politecnico di Torino (Italy); CACE Technologies,
- Davis (California); and Insecure.com, LLC. Full text of the code license
- can be found in each source file.</p>
- <div class="sect2"><div class="titlepage"><div><div><h3 class="title"><a name="npcap-tutorial-devlist"></a>Obtaining the device list</h3></div></div></div>
-
- <p>Typically, the first thing that a Npcap-based application does is
- get a list of attached network adapters. Both libpcap and Npcap provide
- the <a class="ulink" href="wpcap/pcap_findalldevs.html" target="_top">pcap_findalldevs_ex()</a> function for this purpose:
- this function returns a linked list of <code class="literal">pcap_if</code> structures, each of which contains
- comprehensive information about an attached adapter. In particular, the
- fields <code class="literal">name</code> and <code class="literal">description</code> contain the name and a
- human readable description, respectively, of the corresponding
- device.</p>
- <p>The following code retrieves the adapter list and shows it on the
- screen, printing an error if no adapters are found.</p>
- <pre class="programlisting">
- #include "pcap.h"
- main()
- {
- pcap_if_t *alldevs;
- pcap_if_t *d;
- int i=0;
- char errbuf[PCAP_ERRBUF_SIZE];
-
- /* Retrieve the device list from the local machine */
- if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING,
- NULL /* auth is not needed */,
- &alldevs, errbuf) == -1)
- {
- fprintf(stderr,
- "Error in pcap_findalldevs_ex: %s\n",
- errbuf);
- exit(1);
- }
-
- /* Print the list */
- 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 description available)\n");
- }
-
- if (i == 0)
- {
- printf("\nNo interfaces found! Make sure Npcap is installed.\n");
- return;
- }
- /* We don't need any more the device list. Free it */
- pcap_freealldevs(alldevs);
- }
- </pre>
- <p>Some comments about this code.</p>
- <p>First of all, <a class="ulink" href="./wpcap/pcap_findalldevs.html" target="_top">pcap_findalldevs_ex()</a>, like
- other libpcap functions, has an <code class="literal">errbuf</code> parameter. This
- parameter points to a string filled by libpcap with a description of the
- error if something goes wrong.</p>
- <p>Second, remember that not all the OSes supported by libpcap provide a
- description of the network interfaces, therefore if we want to write a
- portable application, we must consider the case in which
- <code class="literal">description</code> is null: we print the string "No
- description available" in that situation.</p>
- <p>Note finally that we free the list with <a class="ulink" href="wpcap/pcap_findalldevs.html" target="_top">pcap_freealldevs()</a> once when
- we have finished with it.</p>
- <p>Assuming we have compiled the program, let's try to run it. On a
- particular Windows workstation, the result we optained is</p>
- <pre class="screen">
- 1. \Device\NPF_{4E273621-5161-46C8-895A-48D0E52A0B83} (Realtek RTL8029(AS) Ethernet Adapter)
- 2. \Device\NPF_{5D24AE04-C486-4A96-83FB-8B5EC6C7F430} (3Com EtherLink PCI)</pre>
-
- <p>As you can see, the name of the network adapters (that will be passed
- to libpcap when opening the devices) under Windows are quite unreadable,
- so the parenthetical descriptions can be very helpful.</p>
- </div>
- <div class="sect2"><div class="titlepage"><div><div><h3 class="title"><a name="npcap-tutorial-devdetails"></a>Obtaining advanced information about installed devices</h3></div></div></div>
-
- <p>Lesson 1 (<a class="xref" href="npcap-tutorial.html#npcap-tutorial-devlist" title="Obtaining the device list">the section called “Obtaining the device list”</a>) demonstrated how
- to get basic information (i.e. device name and description) about
- available adapters. Actually, Npcap provides also other advanced
- information. In particular, every <code class="literal">pcap_if</code> structure
- returned by <a class="ulink" href="wpcap/pcap_findalldevs.html" target="_top">pcap_findalldevs_ex()</a>
- contains also a list of <code class="literal">pcap_addr</code> structures,
- with:</p>
- <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">a list of addresses for that interface.</li><li class="listitem">a list of netmasks (each of which corresponds to an entry in
- the addresses list).</li><li class="listitem">a list of broadcast addresses (each of which corresponds to an
- entry in the addresses list).</li><li class="listitem">a list of destination addresses (each of which corresponds to
- an entry in the addresses list).</li></ul></div>
- <p>Additionally, <code class="literal">pcap_findalldevs_ex()</code> can also
- return remote adapters and a list of pcap files that are located in a
- given local folder.</p>
- <p>The following sample provides an ifprint() function that prints the
- complete contents of a <code class="literal">pcap_if</code> structure. It is
- invoked by the program for every entry returned by
- <code class="literal">pcap_findalldevs_ex()</code>.</p>
- <pre class="programlisting">
- /* Print all the available information on the given interface */
- void ifprint(pcap_if_t *d)
- {
- pcap_addr_t *a;
- char ip6str[128];
- /* Name */
- printf("%s\n",d->name);
- /* Description */
- if (d->description)
- printf("\tDescription: %s\n",d->description);
- /* Loopback Address*/
- printf("\tLoopback: %s\n",(d->flags & PCAP_IF_LOOPBACK)?"yes":"no");
- /* IP addresses */
- for(a=d->addresses;a;a=a->next) {
- printf("\tAddress Family: #%d\n",a->addr->sa_family);
-
- switch(a->addr->sa_family)
- {
- case AF_INET:
- printf("\tAddress Family Name: AF_INET\n");
- if (a->addr)
- printf("\tAddress: %s\n",iptos(((struct sockaddr_in *)a->addr)->sin_addr.s_addr));
- if (a->netmask)
- printf("\tNetmask: %s\n",iptos(((struct sockaddr_in *)a->netmask)->sin_addr.s_addr));
- if (a->broadaddr)
- printf("\tBroadcast Address: %s\n",iptos(((struct sockaddr_in *)a->broadaddr)->sin_addr.s_addr));
- if (a->dstaddr)
- printf("\tDestination Address: %s\n",iptos(((struct sockaddr_in *)a->dstaddr)->sin_addr.s_addr));
- break;
- case AF_INET6:
- printf("\tAddress Family Name: AF_INET6\n");
- if (a->addr)
- printf("\tAddress: %s\n", ip6tos(a->addr, ip6str, sizeof(ip6str)));
- break;
- default:
- printf("\tAddress Family Name: Unknown\n");
- break;
- }
- }
- printf("\n");
- }
- </pre>
- </div>
- <div class="sect2"><div class="titlepage"><div><div><h3 class="title"><a name="npcap-tutorial-openadapter"></a>Opening an adapter and capturing the packets</h3></div></div></div>
-
- <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="ulink" href="wpcap/pcap_open.html" target="_top">pcap_open()</a>. The parameters,
- <code class="literal">snaplen</code>, <code class="literal">flags</code> and
- <code class="literal">to_ms</code> deserve some explanation.</p>
- <p><code class="literal">snaplen</code> 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><code class="literal">flags:</code> 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), Npcap 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><code class="literal">to_ms</code> specifies the read timeout, in milliseconds.
- A read on the adapter (for example, with <a class="ulink" href="wpcap/pcap_loop.html" target="_top">pcap_dispatch()</a> or <a class="ulink" href="wpcap/pcap_next_ex.html" target="_top">pcap_next_ex()</a>) will always
- return after <code class="literal">to_ms</code> milliseconds, even if no packets
- are available from the network. <code class="literal">to_ms</code> 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 <code class="literal">to_ms</code> 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>
- <pre class="programlisting">
- #include <pcap.h>
- #include "misc.h" /* LoadNpcapDlls */
- /* prototype of the packet handler */
- void packet_handler(
- u_char *param,
- const struct pcap_pkthdr *header,
- const u_char *pkt_data);
- int main()
- {
- pcap_if_t *alldevs;
- pcap_if_t *d;
- int inum;
- int i=0;
- pcap_t *adhandle;
- char errbuf[PCAP_ERRBUF_SIZE];
-
- /* Load Npcap and its functions. */
- if (!LoadNpcapDlls())
- {
- fprintf(stderr, "Couldn't load Npcap\n");
- exit(1);
- }
- /* 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 Npcap is installed.\n");
- return -1;
- }
-
- printf("Enter the interface number (1-%d):",i);
- scanf_s("%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
- // 65536 guarantees that the whole packet will
- // be captured on all the link layers
- 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 Npcap\n",
- d->name);
- /* Free the device list */
- pcap_freealldevs(alldevs);
- return -1;
- }
-
- printf("\nlistening on %s...\n", d->description);
-
- /* At this 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;
- /*
- * unused variables
- */
- (VOID)(param);
- (VOID)(pkt_data);
- /* convert the timestamp to readable format */
- local_tv_sec = header->ts.tv_sec;
- localtime_s(&ltime, &local_tv_sec);
- strftime( timestr, sizeof timestr, "%H:%M:%S", &ltime);
-
- printf("%s,%.6d len:%d\n",
- timestr, header->ts.tv_usec, header->len);
- }
- </pre>
- <p>Once the adapter is opened, the capture can be started with <a class="ulink" href="wpcap/pcap_loop.html" target="_top">pcap_dispatch()</a> or <a class="ulink" href="wpcap/pcap_loop.html" target="_top">pcap_loop()</a>. These two functions are
- very similar, the difference is that <code class="literal">pcap_dispatch()</code>
- returns (although not guaranteed) when the timeout expires while
- <code class="literal">pcap_loop()</code> doesn't return until
- <code class="literal">cnt</code> packets have been captured, so it can block for an
- arbitrary period on an under-utilized network.
- <code class="literal">pcap_loop()</code> is enough for the purpose of this sample,
- while <code class="literal">pcap_dispatch()</code> is normally used in a more
- complex program.</p>
- <p>Both of these functions have a <code class="literal">callback</code> parameter,
- <code class="literal">packet_handler</code>, 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 <code class="literal">user</code> parameter of <a class="ulink" href="wpcap/pcap_loop.html" target="_top">pcap_loop()</a> and <a class="ulink" href="wpcap/pcap_loop.html" target="_top">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 Npcap is normally not able
- to capture them.</p>
- <p>The above example extracts the timestamp and the length of every
- packet from the <code class="literal">pcap_pkthdr</code> header and prints them on
- the screen.</p>
- <p>Please note that there may be a drawback using <a class="ulink" href="wpcap/pcap_loop.html" target="_top">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="ulink" href="wpcap/pcap_next_ex.html" target="_top">pcap_next_ex()</a> function, which is
- presented in the next example (<a class="xref" href="npcap-tutorial.html#npcap-tutorial-pcap-next-ex" title="Capturing the packets without the callback">the section called “Capturing the packets without the callback”</a>).</p>
- </div>
- <div class="sect2"><div class="titlepage"><div><div><h3 class="title"><a name="npcap-tutorial-pcap-next-ex"></a>Capturing the packets without the callback</h3></div></div></div>
-
- <p>The example program in this lesson behaves exactly like the previous
- program (<a class="xref" href="npcap-tutorial.html#npcap-tutorial-openadapter" title="Opening an adapter and capturing the packets">the section called “Opening an adapter and capturing the packets”</a>), but it uses
- <a class="ulink" href="wpcap/pcap_next_ex.html" target="_top">pcap_next_ex()</a> instead of
- <a class="ulink" href="wpcap/pcap_loop.html" target="_top">pcap_loop()</a>.</p>
- <p>The callback-based capture mechanism of <a class="ulink" href="wpcap/pcap_loop.html" target="_top">pcap_loop()</a> is elegant and it could
- be a good choice in some situations. However, handling a callback is
- sometimes not practical—it often makes the program more complex
- especially in situations with multithreaded applications or C++
- classes.</p>
- <p>In these cases, <a class="ulink" href="wpcap/pcap_next_ex.html" target="_top">pcap_next_ex()</a> retrievs a packet
- with a direct call—using <code class="literal">pcap_next_ex()</code>,
- packets are received only when the programmer wants them.</p>
- <p>The parameters of this function are the same as a capture callback.
- It takes an adapter descriptor and a couple of pointers that will be
- initialized and returned to the user (one to a
- <code class="literal">pcap_pkthdr</code> structure and another to a buffer with the
- packet data).</p>
- <p>In the following program, we recycle the callback code of the
- previous lesson's example and move it inside main() right after the call
- to <a class="ulink" href="wpcap/pcap_next_ex.html" target="_top">pcap_next_ex()</a>.</p>
- <pre class="programlisting">
- /* Open the device */
- if ( (adhandle= pcap_open(d->name, // name of the device
- 65536, // portion of the packet to capture.
- // 65536 guarantees that the whole packet will
- // be captured on all the link layers
- 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 Npcap\n",
- d->name);
- /* Free the device list */
- pcap_freealldevs(alldevs);
- return -1;
- }
- printf("\nlistening on %s...\n", d->description);
- /* At this point, we don't need any more the device list. Free it */
- pcap_freealldevs(alldevs);
- /* Retrieve the packets */
- while((res = pcap_next_ex( adhandle, &header, &pkt_data)) >= 0){
- if(res == 0)
- /* Timeout elapsed */
- continue;
- /* convert the timestamp to readable format */
- local_tv_sec = header->ts.tv_sec;
- localtime_s(&ltime, &local_tv_sec);
- strftime( timestr, sizeof timestr, "%H:%M:%S", &ltime);
- printf("%s,%.6d len:%d\n", timestr, header->ts.tv_usec, header->len);
- }
- if(res == -1){
- printf("Error reading the packets: %s\n", pcap_geterr(adhandle));
- return -1;
- }
- </pre>
- <p>Why do we use <a class="ulink" href="wpcap/pcap_next_ex.html" target="_top">pcap_next_ex()</a> instead of the old
- <a class="ulink" href="wpcap/pcap_loop.html" target="_top">pcap_next()</a>? Because
- <code class="literal">pcap_next()</code> has some drawbacks. First of all, it is
- inefficient because it hides the callback method but still relies on
- <code class="literal">pcap_dispatch()</code>. Second, it is not able to detect EOF,
- so it's not very useful when gathering packets from a file.</p>
- <p>Notice also that <code class="literal">pcap_next_ex()</code> returns different
- values for success, timeout elapsed, error and EOF conditions.</p>
- </div>
- <div class="sect2"><div class="titlepage"><div><div><h3 class="title"><a name="npcap-tutorial-filtering"></a>Filtering the traffic</h3></div></div></div>
-
- <p>One of the most powerful features offered by Npcap (and by libpcap as
- well) is the filtering engine. It provides a very efficient way to
- receive subsets of the network traffic, and is (usually) integrated with
- the capture mechanism provided by Npcap. The functions used to filter
- packets are <a class="ulink" href="wpcap/pcap_compile.html" target="_top">pcap_compile()</a>
- and <a class="ulink" href="wpcap/pcap_setfilter.html" target="_top">pcap_setfilter()</a>.</p>
- <p><a class="ulink" href="wpcap/pcap_compile.html" target="_top">pcap_compile()</a> takes a
- string containing a high-level Boolean (filter) expression and produces a
- low-level byte code that can be interpreted by the fileter engine in the
- packet driver. The syntax of the boolean expression can be found in the
- <a class="ulink" href="wpcap/pcap-filter.html" target="_top">Filtering expression syntax</a>
- section of this documentation.</p>
- <p><a class="ulink" href="wpcap/pcap_setfilter.html" target="_top">pcap_setfilter()</a>
- associates a filter with a capture session in the kernel driver. Once
- <code class="literal">pcap_setfilter()</code> is called, the associated filter will
- be applied to all the packets coming from the network, and all the
- conformant packets (i.e., packets for which the Boolean expression
- evaluates to true) will be actually copied to the application.</p>
- <p>The following code shows how to compile and set a filter. Note that
- we must retrieve the netmask from the <code class="literal">pcap_if</code>
- structure that describes the adapter, because some filters created by
- <code class="literal">pcap_compile()</code> require it.</p>
- <p>The filter passed to <code class="literal">pcap_compile()</code> in this code
- snippet is "ip and tcp", which means to "keep only the packets that are
- both IPv4 and TCP and deliver them to the application".</p>
-
- <pre class="programlisting">
- if (d->addresses != NULL)
- /* Retrieve the mask of the first address of the interface */
- netmask=((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr;
- else
- /* If the interface is without an address
- * we suppose to be in a C class network */
- netmask=0xffffff;
- //compile the filter
- if (pcap_compile(adhandle, &fcode, "ip and tcp", 1, netmask) < 0)
- {
- fprintf(stderr,
- "\nUnable to compile the packet filter. Check the syntax.\n");
- /* Free the device list */
- pcap_freealldevs(alldevs);
- return -1;
- }
- //set the filter
- if (pcap_setfilter(adhandle, &fcode) < 0)
- {
- fprintf(stderr,"\nError setting the filter.\n");
- /* Free the device list */
- pcap_freealldevs(alldevs);
- return -1;
- }
- </pre>
- <p>If you want to see some code that uses the filtering functions shown
- in this lesson, look at the example presented in the next Lesson, <a class="xref" href="npcap-tutorial.html#npcap-tutorial-interpreting" title="Interpreting the packets">the section called “Interpreting the packets”</a>.</p>
- </div>
- <div class="sect2"><div class="titlepage"><div><div><h3 class="title"><a name="npcap-tutorial-interpreting"></a>Interpreting the packets</h3></div></div></div>
-
- <p>Now that we are able to capture and filter network traffic, we want
- to put our knowledge to work with a simple "real world"
- application.</p>
-
- <p>In this lesson we will take code from the previous lessons and use
- these pieces to build a more useful program. the main purpose of the
- current program is to show how the protocol headers of a captured packet
- can be parsed and interpreted. The resulting application, called UDPdump,
- prints a summary of the UDP traffic on our network.</p>
- <p>We have chosen to parse and display the UDP protocol because it is
- more accessible than other protocols such as TCP and consequently is an
- excellent initial example. Let's look at the code:</p>
- <pre class="programlisting">
- #include <pcap.h>
- #include <Winsock2.h>
- #include <tchar.h>
- BOOL LoadNpcapDlls()
- {
- _TCHAR npcap_dir[512];
- UINT len;
- len = GetSystemDirectory(npcap_dir, 480);
- if (!len) {
- fprintf(stderr, "Error in GetSystemDirectory: %x", GetLastError());
- return FALSE;
- }
- _tcscat_s(npcap_dir, 512, _T("\\Npcap"));
- if (SetDllDirectory(npcap_dir) == 0) {
- fprintf(stderr, "Error in SetDllDirectory: %x", GetLastError());
- return FALSE;
- }
- return TRUE;
- }
- /* 4 bytes IP address */
- typedef struct ip_address{
- u_char byte1;
- u_char byte2;
- u_char byte3;
- u_char byte4;
- }ip_address;
- /* IPv4 header */
- typedef struct ip_header{
- u_char ver_ihl; // Version (4 bits) + IP header length (4 bits)
- u_char tos; // Type of service
- u_short tlen; // Total length
- u_short identification; // Identification
- u_short flags_fo; // Flags (3 bits) + Fragment offset (13 bits)
- u_char ttl; // Time to live
- u_char proto; // Protocol
- u_short crc; // Header checksum
- ip_address saddr; // Source address
- ip_address daddr; // Destination address
- u_int op_pad; // Option + Padding
- }ip_header;
- /* UDP header*/
- typedef struct udp_header{
- u_short sport; // Source port
- u_short dport; // Destination port
- u_short len; // Datagram length
- u_short crc; // Checksum
- }udp_header;
- /* prototype of the packet handler */
- void packet_handler(u_char *param,
- const struct pcap_pkthdr *header,
- const u_char *pkt_data);
- int main()
- {
- pcap_if_t *alldevs;
- pcap_if_t *d;
- int inum;
- int i=0;
- pcap_t *adhandle;
- char errbuf[PCAP_ERRBUF_SIZE];
- u_int netmask;
- char packet_filter[] = "ip and udp";
- struct bpf_program fcode;
- /* Load Npcap and its functions. */
- if (!LoadNpcapDlls())
- {
- fprintf(stderr, "Couldn't load Npcap\n");
- exit(1);
- }
- /* Retrieve the device list */
- 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 Npcap is installed.\n");
- return -1;
- }
-
- printf("Enter the interface number (1-%d):",i);
- scanf_s("%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 adapter */
- if ( (adhandle= pcap_open(d->name, // name of the device
- 65536, // portion of the packet to capture.
- // 65536 grants that the whole packet
- // will be captured on all the MACs.
- PCAP_OPENFLAG_PROMISCUOUS, // promiscuous mode
- 1000, // read timeout
- NULL, // remote authentication
- errbuf // error buffer
- ) ) == NULL)
- {
- fprintf(stderr,
- "\nUnable to open the adapter. %s is not supported by Npcap\n",
- d->name);
- /* Free the device list */
- pcap_freealldevs(alldevs);
- return -1;
- }
-
- /* Check the link layer. We support only Ethernet for simplicity. */
- if(pcap_datalink(adhandle) != DLT_EN10MB)
- {
- fprintf(stderr,"\nThis program works only on Ethernet networks.\n");
- /* Free the device list */
- pcap_freealldevs(alldevs);
- return -1;
- }
-
- if(d->addresses != NULL)
- /* Retrieve the mask of the first address of the interface */
- netmask=((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr;
- else
- /* If the interface is without addresses
- * we suppose to be in a C class network */
- netmask=0xffffff;
- //compile the filter
- if (pcap_compile(adhandle, &fcode, packet_filter, 1, netmask) <0 )
- {
- fprintf(stderr,"\nUnable to compile the packet filter. Check the syntax.\n");
- /* Free the device list */
- pcap_freealldevs(alldevs);
- return -1;
- }
-
- //set the filter
- if (pcap_setfilter(adhandle, &fcode)<0)
- {
- fprintf(stderr,"\nError setting the filter.\n");
- /* Free the device list */
- pcap_freealldevs(alldevs);
- return -1;
- }
-
- printf("\nlistening on %s...\n", d->description);
-
- /* At this 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];
- ip_header *ih;
- udp_header *uh;
- u_int ip_len;
- u_short sport,dport;
- time_t local_tv_sec;
- /*
- * Unused variable
- */
- (VOID)(param);
- /* convert the timestamp to readable format */
- local_tv_sec = header->ts.tv_sec;
- localtime_s(&ltime, &local_tv_sec);
- strftime( timestr, sizeof timestr, "%H:%M:%S", &ltime);
- /* print timestamp and length of the packet */
- printf("%s.%.6d len:%d ", timestr, header->ts.tv_usec, header->len);
- /* retireve the position of the ip header */
- ih = (ip_header *) (pkt_data +
- 14); //length of ethernet header
- /* retireve the position of the udp header */
- ip_len = (ih->ver_ihl & 0xf) * 4;
- uh = (udp_header *) ((u_char*)ih + ip_len);
- /* convert from network byte order to host byte order */
- sport = ntohs( uh->sport );
- dport = ntohs( uh->dport );
- /* print ip addresses and udp ports */
- printf("%d.%d.%d.%d.%d -> %d.%d.%d.%d.%d\n",
- ih->saddr.byte1,
- ih->saddr.byte2,
- ih->saddr.byte3,
- ih->saddr.byte4,
- sport,
- ih->daddr.byte1,
- ih->daddr.byte2,
- ih->daddr.byte3,
- ih->daddr.byte4,
- dport);
- }
- </pre>
- <p>First of all, we set the filter to "ip and udp". In this way we are
- sure that packet_handler() will receive only UDP packets over IPv4: this
- simplifies the parsing and increases the efficiency of the
- program.</p>
- <p>We have also created a couple of structs that describe the IP and UDP
- headers. These structs are used by packet_handler() to properly locate
- the various header fields.</p>
- <p>packet_handler(), although limited to a single protocol dissector
- (UDP over IPv4), shows how complex "sniffers" like tcpdump/WinDump decode
- the network traffic. Since we aren't interested in the MAC header, we
- skip it. For simplicity and before starting the capture, we check the MAC
- layer with <a class="ulink" href="wpcap/pcap_datalink.html" target="_top">pcap_datalink()</a>
- to make sure that we are dealing with an Ethernet network. This way we
- can be sure that the MAC header is exactly 14 bytes.</p>
- <p>The IP header is located just after the MAC header. We will extract
- the IP source and destination addresses from the IP header.</p>
- <p>Reaching the UDP header is a bit more complicated, because the IP
- header doesn't have a fixed length. Therefore, we use the IP header's
- length field to know its size. Once we know the location of the UDP
- header, we extract the source and destination ports.</p>
- <p>The extracted values are printed on the screen, and the result is
- something like:</p>
- <pre class="screen">
- \Device\Packet_{A7FD048A-5D4B-478E-B3C1-34401AC3B72F} (Xircom t 10/100 Adapter)
- Enter the interface number (1-2):1
- listening on Xircom CardBus Ethernet 10/100 Adapter...
- 16:13:15.312784 len:87 130.192.31.67.2682 -> 130.192.3.21.53
- 16:13:15.314796 len:137 130.192.3.21.53 -> 130.192.31.67.2682
- 16:13:15.322101 len:78 130.192.31.67.2683 -> 130.192.3.21.53</pre>
- <p>Each of the final 3 lines represents a different packet.</p>
- </div>
- <div class="sect2"><div class="titlepage"><div><div><h3 class="title"><a name="npcap-tutorial-offline"></a>Handling offline dump files</h3></div></div></div>
-
- <p>In this lession we are going to learn how to handle packet capture to
- a file (dump to file). Npcap offers a wide range of functions to save
- the network traffic to a file and to read the content of
- dumps—this lesson will teach how to use all of these
- functions.</p>
- <p>The format for dump files is the libpcap one. This format contains
- the data of the captured packets in binary form and is a standard used by
- many network tools including WinDump, Wireshark and Snort.</p>
- <div class="sect3"><div class="titlepage"><div><div><h4 class="title"><a name="npcap-tutorial-offline-saving"></a>Saving packets to a dump file</h4></div></div></div>
-
- <p>First of all, let's see how to write packets in libpcap
- format.</p>
- <p>The following example captures the packets from the selected
- interface and saves them on a file whose name is provided by the
- user.</p>
- <pre class="programlisting">
- #include <pcap.h>
- #include "misc.h" /* LoadNpcapDlls */
- /* prototype of the packet handler */
- void packet_handler(u_char *param,
- const struct pcap_pkthdr *header,
- const u_char *pkt_data);
- int main(int argc, char **argv)
- {
- pcap_if_t *alldevs;
- pcap_if_t *d;
- int inum;
- int i=0;
- pcap_t *adhandle;
- char errbuf[PCAP_ERRBUF_SIZE];
- pcap_dumper_t *dumpfile;
- /* Load Npcap and its functions. */
- if (!LoadNpcapDlls())
- {
- fprintf(stderr, "Couldn't load Npcap\n");
- exit(1);
- }
- /* Check command line */
- if(argc != 2)
- {
- printf("usage: %s filename", argv[0]);
- return -1;
- }
-
- /* 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 Npcap is installed.\n");
- return -1;
- }
-
- printf("Enter the interface number (1-%d):",i);
- scanf_s("%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
- // 65536 guarantees that the whole packet
- // will be captured on all the link layers
- 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 Npcap\n",
- d->name);
- /* Free the device list */
- pcap_freealldevs(alldevs);
- return -1;
- }
- /* Open the dump file */
- dumpfile = pcap_dump_open(adhandle, argv[1]);
- if(dumpfile==NULL)
- {
- fprintf(stderr,"\nError opening output file\n");
- return -1;
- }
- printf("\nlistening on %s... Press Ctrl+C to stop...\n", d->description);
- /* At this point, we no longer need the device list. Free it */
- pcap_freealldevs(alldevs);
-
- /* start the capture */
- pcap_loop(adhandle, 0, packet_handler, (unsigned char *)dumpfile);
- return 0;
- }
- /* Callback function invoked by libpcap for every incoming packet */
- void packet_handler(u_char *dumpfile,
- const struct pcap_pkthdr *header,
- const u_char *pkt_data)
- {
- /* save the packet on the dump file */
- pcap_dump(dumpfile, header, pkt_data);
- }
- </pre>
- <p>As you can see, the structure of the program is very similar to the
- ones we have seen in the previous lessons. The differences
- are:</p>
- <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">a call to <a class="ulink" href="wpcap/pcap_dump_open.html" target="_top">pcap_dump_open()</a> is issued
- once the interface is opened. This call opens a dump file and
- associates it with the interface.</li><li class="listitem">the packets are written to this file with a <a class="ulink" href="wpcap/pcap_dump.html" target="_top">pcap_dump()</a> from the
- packet_handler() callback. The parameters of
- <code class="literal">pcap_dump()</code> are in 1-1 correspondence with the
- parameters of <a class="ulink" href="wpcap/pcap_loop.html" target="_top">pcap_handler()</a>.</li></ul></div>
- </div>
- <div class="sect3"><div class="titlepage"><div><div><h4 class="title"><a name="npcap-tutorial-offline-reading"></a>Reading packets from a dump file</h4></div></div></div>
-
- <p>Now that we have a dump file available, we can try to read its
- content. The following code opens a Npcap/libpcap dump file and
- displays every packet contained in the file. The file is opened with
- <a class="ulink" href="wpcap/pcap_open_offline.html" target="_top">pcap_open_offline()</a>,
- then the usual <a class="ulink" href="wpcap/pcap_loop.html" target="_top">pcap_loop()</a> is
- used to sequence through the packets. As you can see, reading packets
- from an offline capture is nearly identical to receiving them from a
- physical interface.</p>
- <p>This example introduces another function:
- <code class="literal">pcap_createsrcstr()</code>. This function is required to
- create a source string that begins with a marker used to tell Npcap the
- type of the source, e.g. "rpcap://" if we are going to open an adapter,
- or "file://" if we are going to open a file. This step is not required
- when <code class="literal">pcap_findalldevs_ex()</code> is used (the returned
- values already contain these strings). However, it is required in this
- example because the name of the file is read from the user
- input.</p>
- <pre class="programlisting">
- #include <stdio.h>
- #include <pcap.h>
- #include "misc.h" /* LoadNpcapDlls */
- #define LINE_LEN 16
- void dispatcher_handler(u_char *,
- const struct pcap_pkthdr *,
- const u_char *);
- int main(int argc, char **argv)
- {
- pcap_t *fp;
- char errbuf[PCAP_ERRBUF_SIZE];
- char source[PCAP_BUF_SIZE];
- /* Load Npcap and its functions. */
- if (!LoadNpcapDlls())
- {
- fprintf(stderr, "Couldn't load Npcap\n");
- exit(1);
- }
- if(argc != 2){
- printf("usage: %s filename", argv[0]);
- return -1;
- }
- /* Create the source string according to the new Npcap syntax */
- if ( pcap_createsrcstr( source, // variable that will keep the source string
- PCAP_SRC_FILE, // we want to open a file
- NULL, // remote host
- NULL, // port on the remote host
- argv[1], // name of the file we want to open
- errbuf // error buffer
- ) != 0)
- {
- fprintf(stderr,"\nError creating a source string\n");
- return -1;
- }
-
- /* Open the capture file */
- if ( (fp= pcap_open(source, // name of the device
- 65536, // portion of the packet to capture
- // 65536 guarantees that the whole packet
- // will be captured on all the link layers
- PCAP_OPENFLAG_PROMISCUOUS, // promiscuous mode
- 1000, // read timeout
- NULL, // authentication on the remote machine
- errbuf // error buffer
- ) ) == NULL)
- {
- fprintf(stderr,"\nUnable to open the file %s.\n", source);
- return -1;
- }
- // read and dispatch packets until EOF is reached
- pcap_loop(fp, 0, dispatcher_handler, NULL);
- return 0;
- }
- void dispatcher_handler(u_char *temp1,
- const struct pcap_pkthdr *header,
- const u_char *pkt_data)
- {
- u_int i=0;
- /*
- * Unused variable
- */
- (VOID)temp1;
- /* print pkt timestamp and pkt len */
- printf("%ld:%ld (%ld)\n", header->ts.tv_sec, header->ts.tv_usec, header->len);
-
- /* Print the packet */
- for (i=1; (i < header->caplen + 1 ) ; i++)
- {
- printf("%.2x ", pkt_data[i-1]);
- if ( (i % LINE_LEN) == 0) printf("\n");
- }
-
- printf("\n\n");
-
- }
- </pre>
- <p>The following example has the same purpose of the last one, but
- <a class="ulink" href="wpcap/pcap_next_ex.html" target="_top">pcap_next_ex()</a> is used
- instead of the <a class="ulink" href="wpcap/pcap_loop.html" target="_top">pcap_loop()</a>
- callback method.</p>
- <pre class="programlisting">
- #include <stdio.h>
- #include <pcap.h>
- #include "misc.h" /* LoadNpcapDlls */
- #define LINE_LEN 16
- int main(int argc, char **argv)
- {
- pcap_t *fp;
- char errbuf[PCAP_ERRBUF_SIZE];
- char source[PCAP_BUF_SIZE];
- struct pcap_pkthdr *header;
- const u_char *pkt_data;
- u_int i=0;
- int res;
- /* Load Npcap and its functions. */
- if (!LoadNpcapDlls())
- {
- fprintf(stderr, "Couldn't load Npcap\n");
- exit(1);
- }
- if(argc != 2)
- {
- printf("usage: %s filename", argv[0]);
- return -1;
- }
-
- /* Create the source string according to the new Npcap syntax */
- if ( pcap_createsrcstr( source, // variable that will keep the source string
- PCAP_SRC_FILE, // we want to open a file
- NULL, // remote host
- NULL, // port on the remote host
- argv[1], // name of the file we want to open
- errbuf // error buffer
- ) != 0)
- {
- fprintf(stderr,"\nError creating a source string\n");
- return -1;
- }
-
- /* Open the capture file */
- if ( (fp= pcap_open(source, // name of the device
- 65536, // portion of the packet to capture
- // 65536 guarantees that the whole packet
- // will be captured on all the link layers
- PCAP_OPENFLAG_PROMISCUOUS, // promiscuous mode
- 1000, // read timeout
- NULL, // authentication on the remote machine
- errbuf // error buffer
- ) ) == NULL)
- {
- fprintf(stderr,"\nUnable to open the file %s.\n", source);
- return -1;
- }
-
- /* Retrieve the packets from the file */
- while((res = pcap_next_ex( fp, &header, &pkt_data)) >= 0)
- {
- /* print pkt timestamp and pkt len */
- printf("%ld:%ld (%ld)\n", header->ts.tv_sec, header->ts.tv_usec, header->len);
-
- /* Print the packet */
- for (i=1; (i < header->caplen + 1 ) ; i++)
- {
- printf("%.2x ", pkt_data[i-1]);
- if ( (i % LINE_LEN) == 0) printf("\n");
- }
-
- printf("\n\n");
- }
-
-
- if (res == -1)
- {
- printf("Error reading the packets: %s\n", pcap_geterr(fp));
- }
-
- return 0;
- }
- </pre>
- </div>
- </div>
- <div class="sect2"><div class="titlepage"><div><div><h3 class="title"><a name="npcap-tutorial-sending"></a>Sending Packets</h3></div></div></div>
-
- <p>Although the name <span class="emphasis"><em>Npcap</em></span> indicates clearly that the purpose
- of the library is packet capture, other useful features for raw
- networking are provided. Among them, the user can find a complete set of
- functions to send packets.</p>
- <div class="sect3"><div class="titlepage"><div><div><h4 class="title"><a name="id582117"></a>Sending a single packet with <code class="literal">pcap_sendpacket()</code></h4></div></div></div>
-
- <p>The simplest way to send a packet is shown in the following code
- snippet. After opening an adapter, <a class="ulink" href="wpcap/pcap_inject.html" target="_top">pcap_sendpacket()</a> is called to
- send a hand-crafted packet. <code class="literal">pcap_sendpacket()</code> takes
- as arguments a buffer containing the data to send, the length of the
- buffer and the adapter that will send it. Notice that the buffer is
- sent to the net as is, without any manipulation. This means that the
- application has to create the correct protocol headers in order to send
- something meaningful.</p>
- <pre class="programlisting">
- #include <stdlib.h>
- #include <stdio.h>
- #include <pcap.h>
- #include "misc.h" /* LoadNpcapDlls */
- void main(int argc, char **argv)
- {
- pcap_t *fp;
- char errbuf[PCAP_ERRBUF_SIZE];
- u_char packet[100];
- int i;
- /* Load Npcap and its functions. */
- if (!LoadNpcapDlls())
- {
- fprintf(stderr, "Couldn't load Npcap\n");
- exit(1);
- }
- /* Check the validity of the command line */
- if (argc != 2)
- {
- printf("usage: %s interface (e.g. 'rpcap://eth0')", argv[0]);
- return;
- }
-
- /* Open the output device */
- if ( (fp= pcap_open(argv[1], // name of the device
- 100, // 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 Npcap\n",
- argv[1]);
- return;
- }
- /* Supposing to be on ethernet, set mac destination to 1:1:1:1:1:1 */
- packet[0]=1;
- packet[1]=1;
- packet[2]=1;
- packet[3]=1;
- packet[4]=1;
- packet[5]=1;
-
- /* set mac source to 2:2:2:2:2:2 */
- packet[6]=2;
- packet[7]=2;
- packet[8]=2;
- packet[9]=2;
- packet[10]=2;
- packet[11]=2;
-
- /* Fill the rest of the packet */
- for(i=12;i<100;i++)
- {
- packet[i]=(u_char)i;
- }
- /* Send down the packet */
- if (pcap_sendpacket(fp, packet, 100 /* size */) != 0)
- {
- fprintf(stderr,"\nError sending the packet: %s\n", pcap_geterr(fp));
- return;
- }
- return;
- }
- </pre>
- </div>
- <div class="sect3"><div class="titlepage"><div><div><h4 class="title"><a name="id582137"></a>Send queues</h4></div></div></div>
-
- <p>While <a class="ulink" href="wpcap/pcap_inject.html" target="_top">pcap_sendpacket()</a>
- offers a simple and immediate way to send a single packet,
- <span class="emphasis"><em>send queues</em></span> provide an advanced, powerful and
- optimized mechanism to send a collection of packets. A send queue is a
- container for a variable number of packets that will be sent to the
- network. It has a size, that represents the maximum amount of bytes it
- can store.</p>
- <p>A send queue is created calling the
- <code class="literal">pcap_sendqueue_alloc()</code> function, specifying the size
- of the new send queue.</p>
- <p>Once the send queue is created,
- <code class="literal">pcap_sendqueue_queue()</code> can be used to add a packet
- to the send queue. This function takes a <code class="literal">pcap_pkthdr</code>
- with the timestamp and the length and a buffer with the data of the
- packet. These parameters are the same as those received by <a class="ulink" href="wpcap/pcap_next_ex.html" target="_top">pcap_next_ex()</a> and
- <code class="literal">pcap_handler()</code>, therefore queuing a packet that was
- just captured or read from a file is a matter of passing these
- parameters to <code class="literal">pcap_sendqueue_queue()</code>.</p>
- <p>To transmit a send queue, Npcap provides the
- <code class="literal">pcap_sendqueue_transmit()</code> function. Note the third
- parameter: if nonzero, the send will be
- <span class="emphasis"><em>synchronized</em></span>, i.e. the relative timestamps of the
- packets will be respected. This operation requires a remarkable amount
- of CPU, because the synchronization takes place in the kernel driver
- using "busy wait" loops. Although this operation is quite CPU
- intensive, it often results in very high precision packet transmissions
- (often around few microseconds or less).</p>
- <p>Note that transmitting a send queue with
- <code class="literal">pcap_sendqueue_transmit()</code> is much more efficient
- than performing a series of <a class="ulink" href="wpcap/pcap_inject.html" target="_top">pcap_sendpacket()</a>, because the
- send queue is buffered at kernel level drastically decreasing the
- number of context switches.</p>
- <p>When a queue is no longer needed, it can be deleted with
- <code class="literal">pcap_sendqueue_destroy()</code> that frees all the buffers
- associated with the send queue.</p>
- <p>The next program shows how to use send queues. It opens a capture
- file with <a class="ulink" href="wpcap/pcap_open_offline.html" target="_top">pcap_open_offline()</a>, then
- it moves the packets from the file to a properly allocated send queue.
- At his point it transmits the queue, synchronizing it if requested by
- the user.</p>
- <p>Note that the link-layer of the dumpfile is compared with the one
- of the interface that will send the packets using <a class="ulink" href="wpcap/pcap_datalink.html" target="_top">pcap_datalink()</a>, and a warning
- is printed if they are different—it is important that the
- capture-file link-layer be the same as the adapter's link layer for
- otherwise the transmission is pointless.</p>
- <pre class="programlisting">
- #include <stdlib.h>
- #include <stdio.h>
- #include <pcap.h>
- #ifdef _WIN32
- #include <tchar.h>
- BOOL LoadNpcapDlls()
- {
- TCHAR npcap_dir[512];
- UINT len;
- len = GetSystemDirectory(npcap_dir, 480);
- if (!len) {
- fprintf(stderr, "Error in GetSystemDirectory: %x", GetLastError());
- return FALSE;
- }
- _tcscat_s(npcap_dir, 512, TEXT("\\Npcap"));
- if (SetDllDirectory(npcap_dir) == 0) {
- fprintf(stderr, "Error in SetDllDirectory: %x", GetLastError());
- return FALSE;
- }
- return TRUE;
- }
- #endif
- void usage();
- void main(int argc, char **argv)
- {
- pcap_t *indesc,*outdesc;
- char errbuf[PCAP_ERRBUF_SIZE];
- char source[PCAP_BUF_SIZE];
- FILE *capfile;
- int caplen, sync;
- u_int res;
- pcap_send_queue *squeue;
- struct pcap_pkthdr *pktheader;
- u_char *pktdata;
- float cpu_time;
- u_int npacks = 0;
- errno_t fopen_error;
- #ifdef _WIN32
- /* Load Npcap and its functions. */
- if (!LoadNpcapDlls())
- {
- fprintf(stderr, "Couldn't load Npcap\n");
- exit(1);
- }
- #endif
- /* Check the validity of the command line */
- if (argc <= 2 || argc >= 5)
- {
- usage();
- return;
- }
-
- /* Retrieve the length of the capture file */
- fopen_error = fopen_s(&capfile, argv[1],"rb");
- if(fopen_error != 0){
- printf("Error opening the file, errno %d.\n", fopen_error);
- return;
- }
-
- fseek(capfile , 0, SEEK_END);
- caplen= ftell(capfile)- sizeof(struct pcap_file_header);
- fclose(capfile);
-
- /* Chek if the timestamps must be respected */
- if(argc == 4 && argv[3][0] == 's')
- sync = TRUE;
- else
- sync = FALSE;
- /* Open the capture */
- /* Create the source string according to the new WinPcap syntax */
- if ( pcap_createsrcstr(
- source, // variable that will keep the source string
- PCAP_SRC_FILE, // we want to open a file
- NULL, // remote host
- NULL, // port on the remote host
- argv[1], // name of the file we want to open
- errbuf // error buffer
- ) != 0)
- {
- fprintf(stderr,"\nError creating a source string\n");
- return;
- }
-
- /* Open the capture file */
- if ( (indesc= pcap_open(source, 65536, PCAP_OPENFLAG_PROMISCUOUS,
- 1000, NULL, errbuf) ) == NULL)
- {
- fprintf(stderr,"\nUnable to open the file %s.\n", source);
- return;
- }
- /* Open the output adapter */
- if ( (outdesc= pcap_open(argv[2], 100, PCAP_OPENFLAG_PROMISCUOUS,
- 1000, NULL, errbuf) ) == NULL)
- {
- fprintf(stderr,"\nUnable to open adapter %s.\n", source);
- return;
- }
- /* Check the MAC type */
- if (pcap_datalink(indesc) != pcap_datalink(outdesc))
- {
- printf("Warning: the datalink of the capture differs"
- " from the one of the selected interface.\n");
- printf("Press a key to continue, or CTRL+C to stop.\n");
- getchar();
- }
- /* Allocate a send queue */
- squeue = pcap_sendqueue_alloc(caplen);
- /* Fill the queue with the packets from the file */
- while ((res = pcap_next_ex( indesc, &pktheader, &pktdata)) == 1)
- {
- if (pcap_sendqueue_queue(squeue, pktheader, pktdata) == -1)
- {
- printf("Warning: packet buffer too small, not all the packets will be sent.\n");
- break;
- }
- npacks++;
- }
- if (res == -1)
- {
- printf("Corrupted input file.\n");
- pcap_sendqueue_destroy(squeue);
- return;
- }
- /* Transmit the queue */
-
- cpu_time = (float)clock ();
- if ((res = pcap_sendqueue_transmit(outdesc, squeue, sync)) < squeue->len)
- {
- printf("An error occurred sending the packets: %s."
- " Only %d bytes were sent\n", pcap_geterr(outdesc), res);
- }
-
- cpu_time = (clock() - cpu_time)/CLK_TCK;
-
- printf ("\n\nElapsed time: %5.3f\n", cpu_time);
- printf ("\nTotal packets generated = %d", npacks);
- printf ("\nAverage packets per second = %d", (int)((double)npacks/cpu_time));
- printf ("\n");
- /* free the send queue */
- pcap_sendqueue_destroy(squeue);
- /* Close the input file */
- pcap_close(indesc);
- /*
- * close the output adapter
- * IMPORTANT: remember to close the adapter, otherwise there will be no
- * guarantee that all the packets will be sent!
- */
- pcap_close(outdesc);
- return;
- }
- void usage()
- {
-
- printf("\nSendcap, sends a libpcap/tcpdump capture file to the net."
- " Copyright (C) 2002 Loris Degioanni.\n");
- printf("\nUsage:\n");
- printf("\t sendcap file_name adapter [s]\n");
- printf("\nParameters:\n");
- printf("\nfile_name: the name of the dump file that will be sent to the network\n");
- printf("\nadapter: the device to use. Use \"WinDump -D\" for a list of valid devices\n");
- printf("\ns: if present, forces the packets to be sent synchronously,"
- " i.e. respecting the timestamps in the dump file.\n\n");
- exit(0);
- }
- </pre>
- </div>
- </div>
- <div class="sect2"><div class="titlepage"><div><div><h3 class="title"><a name="npcap-tutorial-statistics"></a>Gathering Statistics on the network traffic</h3></div></div></div>
-
- <p>This lesson shows another advanced feature of Npcap: the ability to
- collect statistics about network traffic. The statistical engine makes
- use of the kernel-level packet filter to efficiently classify the
- incoming packet.</p>
- <p>In order to use this feature, the programmer must open an adapter and
- put it in <span class="emphasis"><em>statistical mode</em></span>. This can be done with
- <code class="literal">pcap_setmode()</code>. In particular,
- <code class="literal">MODE_STAT</code> must be used as the <code class="literal">mode</code>
- argument of this function.</p>
- <p>With statistical mode, making an application that monitors the TCP
- traffic load is a matter of few lines of code. The following sample shows
- how to do it.</p>
- <pre class="programlisting">
- #include <stdlib.h>
- #include <stdio.h>
- #include <pcap.h>
- #include <tchar.h>
- BOOL LoadNpcapDlls()
- {
- _TCHAR npcap_dir[512];
- UINT len;
- len = GetSystemDirectory(npcap_dir, 480);
- if (!len) {
- fprintf(stderr, "Error in GetSystemDirectory: %x", GetLastError());
- return FALSE;
- }
- _tcscat_s(npcap_dir, 512, _T("\\Npcap"));
- if (SetDllDirectory(npcap_dir) == 0) {
- fprintf(stderr, "Error in SetDllDirectory: %x", GetLastError());
- return FALSE;
- }
- return TRUE;
- }
- void usage();
- void dispatcher_handler(u_char *, const struct pcap_pkthdr *, const u_char *);
- void main(int argc, char **argv)
- {
- pcap_t *fp;
- char errbuf[PCAP_ERRBUF_SIZE];
- struct timeval st_ts;
- u_int netmask;
- struct bpf_program fcode;
-
- /* Load Npcap and its functions. */
- if (!LoadNpcapDlls())
- {
- fprintf(stderr, "Couldn't load Npcap\n");
- exit(1);
- }
- /* Check the validity of the command line */
- if (argc != 2)
- {
- usage();
- return;
- }
-
- /* Open the output adapter */
- if ( (fp= pcap_open(argv[1], 100, PCAP_OPENFLAG_PROMISCUOUS,
- 1000, NULL, errbuf) ) == NULL)
- {
- fprintf(stderr,"\nUnable to open adapter %s.\n", errbuf);
- return;
- }
- /* Don't care about netmask, it won't be used for this filter */
- netmask=0xffffff;
- //compile the filter
- if (pcap_compile(fp, &fcode, "tcp", 1, netmask) <0 )
- {
- fprintf(stderr,"\nUnable to compile the packet filter. Check the syntax.\n");
- /* Free the device list */
- return;
- }
-
- //set the filter
- if (pcap_setfilter(fp, &fcode)<0)
- {
- fprintf(stderr,"\nError setting the filter.\n");
- pcap_close(fp);
- /* Free the device list */
- return;
- }
- /* Put the interface in statstics mode */
- if (pcap_setmode(fp, MODE_STAT)<0)
- {
- fprintf(stderr,"\nError setting the mode.\n");
- pcap_close(fp);
- /* Free the device list */
- return;
- }
- printf("TCP traffic summary:\n");
- /* Start the main loop */
- pcap_loop(fp, 0, dispatcher_handler, (PUCHAR)&st_ts);
- pcap_close(fp);
- return;
- }
- void dispatcher_handler(u_char *state,
- const struct pcap_pkthdr *header,
- const u_char *pkt_data)
- {
- struct timeval *old_ts = (struct timeval *)state;
- u_int delay;
- LARGE_INTEGER Bps,Pps;
- struct tm ltime;
- char timestr[16];
- time_t local_tv_sec;
- /* Calculate the delay in microseconds from the last sample. This value
- * is obtained from the timestamp that the associated with the sample. */
- delay = (header->ts.tv_sec - old_ts->tv_sec) * 1000000
- - old_ts->tv_usec + header->ts.tv_usec;
- /* Get the number of Bits per second */
- Bps.QuadPart=(((*(LONGLONG*)(pkt_data + 8)) * 8 * 1000000) / (delay));
- /* ^ ^
- | |
- | |
- | |
- converts bytes in bits -- |
- |
- delay is expressed in microseconds --
- */
- /* Get the number of Packets per second */
- Pps.QuadPart=(((*(LONGLONG*)(pkt_data)) * 1000000) / (delay));
- /* Convert the timestamp to readable format */
- local_tv_sec = header->ts.tv_sec;
- localtime_s(&ltime, &local_tv_sec);
- strftime( timestr, sizeof timestr, "%H:%M:%S", &ltime);
- /* Print timestamp*/
- printf("%s ", timestr);
- /* Print the samples */
- printf("BPS=%I64u ", Bps.QuadPart);
- printf("PPS=%I64u\n", Pps.QuadPart);
- //store current timestamp
- old_ts->tv_sec=header->ts.tv_sec;
- old_ts->tv_usec=header->ts.tv_usec;
- }
- void usage()
- {
- printf("\nShows the TCP traffic load, in bits per second and packets per second."
- "\nCopyright (C) 2002 Loris Degioanni.\n");
- printf("\nUsage:\n");
- printf("\t tcptop adapter\n");
- printf("\t You can use \"WinDump -D\" if you don't know the name of your adapters.\n");
- exit(0);
- }
- </pre>
- <p>Before enabling statistical mode, the user has the option to set a
- filter that defines the subset of network traffic that will be monitored.
- See the <a class="ulink" href="wpcap/pcap-filter.html" target="_top">Filtering expression
- syntax</a> documentation for details. If no filter has been set,
- all of the traffic will be monitored.</p>
- <p>Once
- </p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">the filter is set</li><li class="listitem"><code class="literal">pcap_setmode()</code> is called</li><li class="listitem">callback invocation is enabled with <a class="ulink" href="wpcap/pcap_loop.html" target="_top">pcap_loop()</a></li></ul></div><p>
- the interface descriptor starts to work in statistical mode. Notice the
- fourth parameter (<code class="literal">to_ms</code>) of <a class="ulink" href="wpcap/pcap_open.html" target="_top">pcap_open()</a>: it defines the interval
- among the statistical samples. The callback function receives the samples
- calculated by the driver every <code class="literal">to_ms</code> milliseconds.
- These samples are encapsulated in the second and third parameters of the
- callback function.
-
- Two 64-bit counters are provided: the number of packets and the amount of
- bytes received during the last interval.</p>
- <p>In the example, the adapter is opened with a timeout of 1000 ms. This
- means that dispatcher_handler() is called once per second. At this point
- a filter that keeps only tcp packets is compiled and set. Then
- <code class="literal">pcap_setmode()</code> and <code class="literal">pcap_loop()</code> are
- called. Note that a struct timeval pointer is passed to
- <code class="literal">pcap_loop()</code> as the <code class="literal">user</code> parameter.
- This structure will be used to store a timestamp in order to calculate
- the interval between two samples. dispatcher_handler()uses this interval
- to obtain the bits per second and the packets per second and then prints
- these values on the screen.</p>
- <p>Note finally that this example is by far more efficient than a
- program that captures the packets in the traditional way and calculates
- statistics at user-level. Statistical mode requires the minumum amount of
- data copies and context switches and therefore the CPU is optimized.
- Moreover, a very small amount of memory is required.</p>
- </div>
- </div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="npcap-api.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="npcap-internals.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">The Npcap API </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Npcap internals</td></tr></table></div></body></html>
|