Main Page | Modules | Data Structures | File List | Data Fields | Globals | Related Pages

Opening an adapter and capturing the packets
[WinPcap tutorial: a step by step guide to using WinPcap]

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

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

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

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

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

#include "pcap.h" /* prototype of the packet handler */ void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data); main() { pcap_if_t *alldevs; pcap_if_t *d; int inum; int i=0; pcap_t *adhandle; char errbuf[PCAP_ERRBUF_SIZE]; /* Retrieve the device list on the local machine */ if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1) { fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf); exit(1); } /* Print the list */ for(d=alldevs; d; d=d->next) { printf("%d. %s", ++i, d->name); if (d->description) printf(" (%s)\n", d->description); else printf(" (No description available)\n"); } if(i==0) { printf("\nNo interfaces found! Make sure WinPcap is installed.\n"); return -1; } printf("Enter the interface number (1-%d):",i); scanf("%d", &inum); if(inum < 1 || inum > i) { printf("\nInterface number out of range.\n"); /* Free the device list */ pcap_freealldevs(alldevs); return -1; } /* Jump to the selected adapter */ for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++); /* Open the device */ if ( (adhandle= pcap_open(d->name, // name of the device 65536, // portion of the packet to capture // 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 WinPcap\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]; /* convert the timestamp to readable format */ ltime=localtime(&header->ts.tv_sec); strftime( timestr, sizeof timestr, "%H:%M:%S", ltime); printf("%s,%.6d len:%d\n", timestr, header->ts.tv_usec, header->len); }
00001 #include "pcap.h" 00002 00003 /* prototype of the packet handler */ 00004 void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data); 00005 00006 main() 00007 { 00008 pcap_if_t *alldevs; 00009 pcap_if_t *d; 00010 int inum; 00011 int i=0; 00012 pcap_t *adhandle; 00013 char errbuf[PCAP_ERRBUF_SIZE]; 00014 00015 /* Retrieve the device list on the local machine */ 00016 if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1) 00017 { 00018 fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf); 00019 exit(1); 00020 } 00021 00022 /* Print the list */ 00023 for(d=alldevs; d; d=d->next) 00024 { 00025 printf("%d. %s", ++i, d->name); 00026 if (d->description) 00027 printf(" (%s)\n", d->description); 00028 else 00029 printf(" (No description available)\n"); 00030 } 00031 00032 if(i==0) 00033 { 00034 printf("\nNo interfaces found! Make sure WinPcap is installed.\n"); 00035 return -1; 00036 } 00037 00038 printf("Enter the interface number (1-%d):",i); 00039 scanf("%d", &inum); 00040 00041 if(inum < 1 || inum > i) 00042 { 00043 printf("\nInterface number out of range.\n"); 00044 /* Free the device list */ 00045 pcap_freealldevs(alldevs); 00046 return -1; 00047 } 00048 00049 /* Jump to the selected adapter */ 00050 for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++); 00051 00052 /* Open the device */ 00053 if ( (adhandle= pcap_open(d->name, // name of the device 00054 65536, // portion of the packet to capture 00055 // 65536 guarantees that the whole packet will be captured on all the link layers 00056 PCAP_OPENFLAG_PROMISCUOUS, // promiscuous mode 00057 1000, // read timeout 00058 NULL, // authentication on the remote machine 00059 errbuf // error buffer 00060 ) ) == NULL) 00061 { 00062 fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name); 00063 /* Free the device list */ 00064 pcap_freealldevs(alldevs); 00065 return -1; 00066 } 00067 00068 printf("\nlistening on %s...\n", d->description); 00069 00070 /* At this point, we don't need any more the device list. Free it */ 00071 pcap_freealldevs(alldevs); 00072 00073 /* start the capture */ 00074 pcap_loop(adhandle, 0, packet_handler, NULL); 00075 00076 return 0; 00077 } 00078 00079 00080 /* Callback function invoked by libpcap for every incoming packet */ 00081 void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data) 00082 { 00083 struct tm *ltime; 00084 char timestr[16]; 00085 00086 /* convert the timestamp to readable format */ 00087 ltime=localtime(&header->ts.tv_sec); 00088 strftime( timestr, sizeof timestr, "%H:%M:%S", ltime); 00089 00090 printf("%s,%.6d len:%d\n", timestr, header->ts.tv_usec, header->len); 00091 00092 }

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

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

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

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

<<< Previous Next >>>


documentation. Copyright (c) 2002-2005 Politecnico di Torino. Copyright (c) 2005 CACE technologies. All rights reserved.