[ Previous | Next | Table of Contents | Index | Library Home | Legal | Search ]

Communications Programming Concepts


Sample 1: Capturing Packet Data and Printing It in Binary Form to the Screen

The following code sample demonstrates capturing packet data and printing it in binary form to the screen. This sample is only for illustrating the use of the Packet Capture Library APIs. It is recommended that you write your own application for optimal function in a production environment.

/*
 * Use pcap_open_live() to open a packet capture device and use pcap_dump()
 * to output the packet capture data in binary format to standard out. The
 * output can be piped to another program, such as the one in Sample 3, 
 * for formatting and readability.
 */
 
#include <stdio.h>
#include <pcap.h>
#include <netinet/in.h>
#include <sys/socket.h>
 
#include <string.h>
 
#define FLTRSZ 120
#define MAXHOSTSZ 256
#define ADDR_STRSZ 16
 
extern char *inet_ntoa();
 
int
main(int argc, char **argv)
{
        pcap_t *p;               /* packet capture descriptor */
        pcap_dumper_t *pd;       /* pointer to the dump file */
        char *ifname;            /* interface name (such as "en0") */
        char errbuf[PCAP_ERRBUF_SIZE];  /* buffer to hold error text */
        char lhost[MAXHOSTSZ];   /* local host name */
        char fltstr[FLTRSZ];     /* bpf filter string */
        char prestr[80];         /* prefix string for errors from pcap_perror */
        struct bpf_program prog; /* compiled bpf filter program */
        int optimize = 1;        /* passed to pcap_compile to do optimization */
        int snaplen = 80;        /* amount of data per packet */
        int promisc = 0;         /* do not change mode; if in promiscuous */
                                 /* mode, stay in it, otherwise, do not */
        int to_ms = 1000;        /* timeout, in milliseconds */
        int count = 20;          /* number of packets to capture */
        u_int32 net = 0;         /* network IP address */
        u_int32 mask = 0;        /* network address mask */
        char netstr[INET_ADDRSTRLEN];   /* dotted decimal form of address */
        char maskstr[INET_ADDRSTRLEN];  /* dotted decimal form of net mask */
 
        /*
         * Find a network device on the system.
         */
        if (!(ifname = pcap_lookupdev(errbuf))) {
                fprintf(stderr, "Error getting device on system: %s\n", errbuf);
                exit(1);
        }
 
        /*
         * Open the network device for packet capture. This must be called
         * before any packets can be captured on the network device.
         */
        if (!(p = pcap_open_live(ifname, snaplen, promisc, to_ms, errbuf))) {
                fprintf(stderr,
                        "Error opening interface %s: %s\n", ifname, errbuf);
                exit(2);
        }
 
        /*
         * Look up the network address and subnet mask for the network device 
         * returned by pcap_lookupdev(). The network mask will be used later
         * in the call to pcap_compile().
         */
        if (pcap_lookupnet(ifname, &net, &mask, errbuf) < 0) {
                fprintf(stderr, "Error looking up network: %s\n", errbuf);
                exit(3);
        }
 
        /*
         * Create the filter and store it in the string called 'fltstr.'
         * Here, you want only incoming packets (destined for this host),
         * which use port 23 (telnet), and originate from a host on the 
         * local network.
         */
 
        /* First, get the hostname of the local system */
        if (gethostname(lhost,sizeof(lhost)) < 0) {
                fprintf(stderr, "Error getting hostname.\n");
                exit(4);
        }
 
        /*
         * Second, get the dotted decimal representation of the network address
         * and netmask. These will be used as part of the filter string.
         */
        inet_ntop(AF_INET, (char*) &net, netstr, sizeof netstr);
        inet_ntop(AF_INET, (char*) &mask, maskstr, sizeof maskstr);
 
        /* Next, put the filter expression into the fltstr string. */
        sprintf(fltstr,"dst host %s and src net %s mask %s and tcp port 23",
                lhost, netstr, maskstr);
 
        /*
         * Compile the filter. The filter will be converted from a text
         * string to a bpf program that can be used by the Berkely Packet
         * Filtering mechanism. The fourth argument, optimize, is set to 1 so
         * the resulting bpf program, prog, is compiled for better performance.
         */
        if (pcap_compile(p,&prog,fltstr,optimize,mask) < 0) {
                /*
                 * Print out appropriate text, followed by the error message
                 * generated by the packet capture library.
                 */
                fprintf(stderr, "Error compiling bpf filter on %s: %s\n",
                        ifname, pcap_geterr(p));
                exit(5);
        }
 
        /*
         * Load the compiled filter program into the packet capture device.
         * This causes the capture of the packets defined by the filter
         * program, prog, to begin.
         */
        if (pcap_setfilter(p, &prog) < 0) {
                /* Copy appropriate error text to prefix string, prestr */
                sprintf(prestr, "Error installing bpf filter on interface %s",
                        ifname);
                /*
                 * Print out error. The format will be the prefix string,
                 * created above, followed by the error message that the packet 
                 * capture library generates.
                 */
                pcap_perror(p,prestr);
                exit(6);
        }
 
        /*
         * Open dump device for writing packet capture data. Passing in "-"
         * indicates that packets are to be written to standard output.
         * pcap_dump() will be called to write the packet capture data in
         * binary format, so the output from this program can be piped into
         * another application for further processing or formatting before
         * reading.
         */
        if ((pd = pcap_dump_open(p,"-")) == NULL) {
                /*
                 * Print out error message if pcap_dump_open failed. This will
                 * be the below message followed by the pcap library error text,
                 * obtained by pcap_geterr().
                 */
                fprintf(stderr, "Error opening dump device stdout: %s\n",
                        pcap_geterr(p));
                exit(7);
        }
 
        /*
         * Call pcap_loop() to read and process a maximum of count (20)
         * packets. For each captured packet (a packet that matches the filter
         * specified to pcap_compile()), pcap_dump() will be called to write
         * the packet capture data (in binary format) to the savefile specified
         * to pcap_dump_open(). Note that the packet in this case may not be a
         * complete packet. The amount of data captured per packet is
         * determined by the snaplen variable which is passed to
         * pcap_open_live().
         */
        if (pcap_loop(p, count, &pcap_dump, (char *)pd) < 0) {
                /*
                 * Print out appropriate text, followed by the error message
                 * generated by the packet capture library.
                 */
                sprintf(prestr,"Error reading packets from interface %s",
                        ifname);
                pcap_perror(p,prestr);
                exit(8);
        }
 
        /*
         * Close the packet capture device and free the memory used by the
         * packet capture descriptor.
         */
        pcap_close(p);
}


[ Previous | Next | Table of Contents | Index | Library Home | Legal | Search ]