Add port 3799 to the default filter to capture CoA and Disconnect
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Fri, 9 Nov 2012 12:51:34 +0000 (12:51 +0000)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Fri, 9 Nov 2012 14:47:29 +0000 (14:47 +0000)
Support reading from stdin writing to *

Support writing to stdout reading from  *

Add -v which prints out our version and the libpcap library version

Remove -m and add -q to reduce debugging level

Cleanup of code in main()

src/main/radsniff.c

index 5da57c5..cade9f6 100644 (file)
@@ -35,19 +35,32 @@ RCSID("$Id$")
 
 static const char *radius_secret = "testing123";
 static VALUE_PAIR *filter_vps = NULL;
-#undef DEBUG
-#define DEBUG if (fr_debug_flag) printf
 
-static int minimal = 0;
 static int do_sort = 0;
+static int to_stdout = 0;
+static FILE *log_dst;
+
+#undef DEBUG1
+#define DEBUG1 if (fr_debug_flag > 2) fprintf
+#undef DEBUG
+#define DEBUG if (fr_debug_flag > 1) fprintf
+#undef INFO
+#define INFO if (fr_debug_flag > 0) fprintf
+
 struct timeval start_pcap = {0, 0};
 static rbtree_t *filter_tree = NULL;
 static rbtree_t *request_tree = NULL;
-static pcap_dumper_t *pcap_dumper = NULL;
+static pcap_dumper_t *out = NULL;
 static RADIUS_PACKET *nullpacket = NULL;
 
 typedef int (*rbcmp)(const void *, const void *);
 
+static const char *radsniff_version = "radsniff version " RADIUSD_VERSION_STRING
+#ifdef RADIUSD_VERSION_COMMIT
+" (git #" RADIUSD_VERSION_COMMIT ")"
+#endif
+;
+
 static int filter_packet(RADIUS_PACKET *packet)
 {
        VALUE_PAIR *check_item;
@@ -70,7 +83,6 @@ static int filter_packet(RADIUS_PACKET *packet)
                        }
        }
 
-
        if (fail == 0 && pass != 0) {
                /*
                 *      Cache authentication requests, as the replies
@@ -184,26 +196,35 @@ static void tv_sub(const struct timeval *end, const struct timeval *start,
        }
 }
 
-static void got_packet(uint8_t *args, const struct pcap_pkthdr *header, const uint8_t *data)
+static void got_packet(UNUSED uint8_t *args, const struct pcap_pkthdr *header, const uint8_t *data)
 {
-       /* Just a counter of how many packets we've had */
-       static int count = 1;
-       /* Define pointers for packet's attributes */
-       const struct ethernet_header *ethernet;  /* The ethernet header */
-       const struct ip_header *ip;              /* The IP header */
-       const struct udp_header *udp;            /* The UDP header */
-       const uint8_t *payload;                     /* Packet payload */
-       /* And define the size of the structures we're using */
+
+       static int count = 1;                   /* Packets seen */
+       
+       /*
+        *  Define pointers for packet's attributes
+        */
+       const struct ethernet_header *ethernet; /* The ethernet header */
+       const struct ip_header *ip;             /* The IP header */
+       const struct udp_header *udp;           /* The UDP header */
+       const uint8_t *payload;                 /* Packet payload */
+       
+       /*
+        *  And define the size of the structures we're using
+        */
        int size_ethernet = sizeof(struct ethernet_header);
        int size_ip = sizeof(struct ip_header);
        int size_udp = sizeof(struct udp_header);
-       /* For FreeRADIUS */
+       
+       /*
+        *  For FreeRADIUS
+        */
        RADIUS_PACKET *packet, *original;
        struct timeval elapsed;
 
-       args = args;            /* -Wunused */
-
-       /* Define our packet's attributes */
+       /*
+        * Define our packet's attributes
+        */
 
        if ((data[0] == 2) && (data[1] == 0) &&
            (data[2] == 0) && (data[3] == 0)) {
@@ -213,6 +234,7 @@ static void got_packet(uint8_t *args, const struct pcap_pkthdr *header, const ui
                ethernet = (const struct ethernet_header*)(data);
                ip = (const struct ip_header*)(data + size_ethernet);
        }
+       
        udp = (const struct udp_header*)(((const uint8_t *) ip) + size_ip);
        payload = (const uint8_t *)(((const uint8_t *) udp) + size_udp);
 
@@ -230,15 +252,15 @@ static void got_packet(uint8_t *args, const struct pcap_pkthdr *header, const ui
        packet->dst_ipaddr.ipaddr.ip4addr.s_addr = ip->ip_dst.s_addr;
        packet->dst_port = ntohs(udp->udp_dport);
 
-       packet->data = payload;
+       memcpy(&packet->data, &payload, sizeof(packet->data));
        packet->data_len = header->len - (payload - data);
 
        if (!rad_packet_ok(packet, 0)) {
-               printf("Packet: %s\n", fr_strerror());
+               DEBUG(log_dst, "Packet: %s\n", fr_strerror());
                
-               printf("\tFrom:    %s:%d\n", inet_ntoa(ip->ip_src), ntohs(udp->udp_sport));
-               printf("\tTo:      %s:%d\n", inet_ntoa(ip->ip_dst), ntohs(udp->udp_dport));
-               printf("\tType:    %s\n", fr_packet_codes[packet->code]);
+               DEBUG(log_dst, "  From     %s:%d\n", inet_ntoa(ip->ip_src), ntohs(udp->udp_sport));
+               DEBUG(log_dst, "  To:      %s:%d\n", inet_ntoa(ip->ip_dst), ntohs(udp->udp_dport));
+               DEBUG(log_dst, "  Type:    %s\n", fr_packet_codes[packet->code]);
 
                free(packet);
                return;
@@ -267,7 +289,7 @@ static void got_packet(uint8_t *args, const struct pcap_pkthdr *header, const ui
        }
 
        /*
-        *      Decode the data without bothering to check the signatures.
+        *  Decode the data without bothering to check the signatures.
         */
        if (rad_decode(packet, original, radius_secret) != 0) {
                free(packet);
@@ -275,51 +297,64 @@ static void got_packet(uint8_t *args, const struct pcap_pkthdr *header, const ui
                return;
        }
 
-       /* we've seen a successfull reply to this, so delete it now */
+       /*
+        *  We've seen a successfull reply to this, so delete it now
+        */
        if (original)
                rbtree_deletebydata(request_tree, original);
 
        if (filter_vps && filter_packet(packet)) {
                free(packet);
-               DEBUG("Packet number %d doesn't match\n", count++);
+               DEBUG(log_dst, "Packet number %d doesn't match\n", count++);
                return;
        }
 
-       if (pcap_dumper) {
-               pcap_dump((void *) pcap_dumper, header, data);
+       if (out) {
+               pcap_dump((void *) out, header, data);
                goto check_filter;
        }
 
-       printf("%s Id %d\t", fr_packet_codes[packet->code], packet->id);
-
-       /* Print the RADIUS packet */
-       printf("%s:%d -> ", inet_ntoa(ip->ip_src), ntohs(udp->udp_sport));
-       printf("%s:%d", inet_ntoa(ip->ip_dst), ntohs(udp->udp_dport));
-       if (fr_debug_flag) printf("\t(%d packets)", count++);
+       INFO(log_dst, "%s Id %d\t", fr_packet_codes[packet->code], packet->id);
 
+       /*
+        *  Print the RADIUS packet
+        */
+       INFO(log_dst, "%s:%d -> ", inet_ntoa(ip->ip_src), ntohs(udp->udp_sport));
+       INFO(log_dst, "%s:%d", inet_ntoa(ip->ip_dst), ntohs(udp->udp_dport));
+       
+       DEBUG1(log_dst, "\t(%d packets)", count++);
+       
        if (!start_pcap.tv_sec) {
                start_pcap = header->ts;
        }
 
        tv_sub(&header->ts, &start_pcap, &elapsed);
 
-       printf("\t+%u.%03u", (unsigned int) elapsed.tv_sec,
+       INFO(log_dst, "\t+%u.%03u", (unsigned int) elapsed.tv_sec,
               (unsigned int) elapsed.tv_usec / 1000);
-       if (!minimal) printf("\n");
-       if (!minimal && packet->vps) {
-               if (do_sort) sort(packet);
-
-               vp_printlist(stdout, packet->vps);
-               pairfree(&packet->vps);
+              
+       if (fr_debug_flag > 1) {
+               DEBUG(log_dst, "\n");
+               if (packet->vps) {
+                       if (do_sort) sort(packet);
+       
+                       vp_printlist(log_dst, packet->vps);
+                       pairfree(&packet->vps);
+               }
+       }
+       
+       INFO(log_dst, "\n");
+       
+       if (!to_stdout && (fr_debug_flag > 4)) {
+               rad_print_hex(packet);
        }
-       printf("\n");
-       if (fr_debug_flag > 2) rad_print_hex(packet);
-       fflush(stdout);
+       
+       fflush(log_dst);
 
  check_filter:
        /*
-        *      If we're doing filtering, Access-Requests are cached
-        *      in the filter tree.
+        *  If we're doing filtering, Access-Requests are cached in the
+        *  filter tree.
         */
        if (!filter_vps ||
            ((packet->code != PW_AUTHENTICATION_REQUEST) &&
@@ -331,58 +366,66 @@ static void got_packet(uint8_t *args, const struct pcap_pkthdr *header, const ui
 static void NEVER_RETURNS usage(int status)
 {
        FILE *output = status ? stderr : stdout;
-       fprintf(output, "usage: radsniff [options]\n");
+       fprintf(output, "Usage: radsniff [options]\n");
        fprintf(output, "options:\n");
-       fprintf(output, "\t-c count\tNumber of packets to capture.\n");
-       fprintf(output, "\t-d directory\tDirectory where the dictionaries are found\n");
-       fprintf(output, "\t-F\t\tFilter PCAP file from stdin to stdout.\n");
-       fprintf(output, "\t\t\tOutput file will contain RADIUS packets.\n");
-       fprintf(output, "\t-f filter\tPCAP filter. (default is udp port 1812 or 1813)\n");
-       fprintf(output, "\t-h\t\tPrint this help message.\n");
-       fprintf(output, "\t-i interface\tInterface to capture.\n");
-       fprintf(output, "\t-I filename\tRead packets from filename.\n");
-       fprintf(output, "\t-m\t\tPrint packet headers only, not contents.\n");
-       fprintf(output, "\t-p port\t\tListen for packets on port.\n");
-       fprintf(output, "\t-r filter\tRADIUS attribute filter.\n");
-       fprintf(output, "\t-s secret\tRADIUS secret.\n");
-       fprintf(output, "\t-S\t\tSort attributes in the packet.\n");
-       fprintf(output, "\t\t\tUsed to compare server results.\n");
-       fprintf(output, "\t-w file\tWrite output packets to file.\n");
-       fprintf(output, "\t-x\t\tPrint out debugging information.\n");
+       fprintf(output, "  -c <count>      Number of packets to capture.\n");
+       fprintf(output, "  -d <directory>  Set dictionary directory.\n");
+       fprintf(output, "  -F              Filter PCAP file from stdin to stdout.\n");
+       fprintf(output, "  -f <filter>     PCAP filter (default is 'udp port <port> or <port + 1> or 3799')\n");
+       fprintf(output, "  -h              This help message.\n");
+       fprintf(output, "  -i <interface>  Capture packets from interface (defaults to any if supported).\n");
+       fprintf(output, "  -I <file>       Read packets from file (overrides input of -F).\n");
+       fprintf(output, "  -p <port>       Filter packets by port (default is 1812).\n");
+       fprintf(output, "  -q              Print less debugging information.\n");
+       fprintf(output, "  -r <filter>     RADIUS attribute filter.\n");
+       fprintf(output, "  -s <secret>     RADIUS secret.\n");
+       fprintf(output, "  -S              Sort attributes in the packet (useful for diffing responses).\n");
+       fprintf(output, "  -v              Show program version information.\n");
+       fprintf(output, "  -w <file>       Write output packets to file (overrides output of -F).\n");
+       fprintf(output, "  -x              Print more debugging information (defaults to -xx).\n");
        exit(status);
 }
 
 int main(int argc, char *argv[])
 {
-       char *dev;                      /* sniffing device */
-       char errbuf[PCAP_ERRBUF_SIZE];  /* error buffer */
-       pcap_t *descr;                  /* sniff handler */
-       struct bpf_program fp;          /* hold compiled program */
-       bpf_u_int32 maskp;              /* subnet mask */
-       bpf_u_int32 netp;               /* ip */
-       char buffer[1024];
-       char *pcap_filter = NULL;
+       const char *from_dev = NULL;                    /* Capture from device */
+       const char *from_file = NULL;                   /* Read from pcap file */
+       int from_stdin = 0;                             /* Read from stdin */
+       
+       pcap_t *in;                                     /* PCAP input handle */
+       
+       int limit = -1;                                 /* How many packets to sniff */
+       
+       char errbuf[PCAP_ERRBUF_SIZE];                  /* Error buffer */
+
+       char *to_file = NULL;                           /* PCAP output file */
+       
+       char *pcap_filter = NULL;                       /* PCAP filter string */
        char *radius_filter = NULL;
-       char *filename = NULL;
-       int printable_output = 1;
-       char *dump_file = NULL;
-       int packet_count = -1;          /* how many packets to sniff */
+       int port = 1812;
+       
+       struct bpf_program fp;                          /* Holds compiled filter */
+       bpf_u_int32 ip_mask = PCAP_NETMASK_UNKNOWN;     /* Device Subnet mask */
+       bpf_u_int32 ip_addr = 0;                        /* Device IP */
+       
+       char buffer[1024];
+
        int opt;
        FR_TOKEN parsecode;
        const char *radius_dir = RADIUS_DIR;
-       int port = 1812;
-       int filter_stdin = 0;
-
-       /* Default device */
-       dev = pcap_lookupdev(errbuf);
+       
+       fr_debug_flag = 2;
+       log_dst = stdout;
 
-       /* Get options */
-       while ((opt = getopt(argc, argv, "c:d:Ff:hi:I:mp:r:s:Sw:xX")) != EOF) {
+       /*
+        *  Get options
+        */
+       while ((opt = getopt(argc, argv, "c:d:Ff:hi:I:p:qr:s:Svw:xX")) != EOF) {
                switch (opt)
                {
                case 'c':
-                       packet_count = atoi(optarg);
-                       if (packet_count <= 0) {
+                       limit = atoi(optarg);
+                       if (limit <= 0) {
                                fprintf(stderr, "radsniff: Invalid number of packets \"%s\"\n", optarg);
                                exit(1);
                        }
@@ -391,8 +434,8 @@ int main(int argc, char *argv[])
                        radius_dir = optarg;
                        break;
                case 'F':
-                       filter_stdin = 1;
-                       printable_output = 0;
+                       from_stdin = 1;
+                       to_stdout = 1;
                        break;
                case 'f':
                        pcap_filter = optarg;
@@ -401,17 +444,19 @@ int main(int argc, char *argv[])
                        usage(0);
                        break;
                case 'i':
-                       dev = optarg;
+                       from_dev = optarg;
                        break;
                case 'I':
-                       filename = optarg;
-                       break;
-               case 'm':
-                       minimal = 1;
+                       from_file = optarg;
                        break;
                case 'p':
                        port = atoi(optarg);
                        break;
+               case 'q':
+                       if (fr_debug_flag > 0) {
+                               fr_debug_flag--;
+                       }
+                       break;
                case 'r':
                        radius_filter = optarg;
                        break;
@@ -421,156 +466,204 @@ int main(int argc, char *argv[])
                case 'S':
                        do_sort = 1;
                        break;
+               case 'v':
+                       INFO(log_dst, "%s %s\n", radsniff_version, pcap_lib_version());
+                       exit(0);
+                       break;
                case 'w':
-                       dump_file = optarg;
-                       printable_output = 0;
+                       to_file = optarg;
                        break;
                case 'x':
-               case 'X':       /* for backwards compatibility */
+               case 'X':
                        fr_debug_flag++;
                        break;
                default:
-                       usage(1);
+                       usage(64);
                }
        }
-
+       
+       /* What's the point in specifying -F ?! */
+       if (from_stdin && from_file && to_file) {
+               usage(64);
+       }
+       
+       /* Can't read from both... */
+       if (from_file && from_dev) {
+               usage(64);
+       }
+       
+       /* Reading from file overrides stdin */
+       if (from_stdin && (from_file || from_dev)) {
+               from_stdin = 0;
+       }
+       
+       /* Writing to file overrides stdout */
+       if (to_file && to_stdout) {
+               to_stdout = 0;
+       }
+       
        /*
-        *      Cross-check command-line arguments.
+        *  If were writing pcap data stdout we *really* don't want to send
+        *  logging there as well.
         */
-       if (filter_stdin && (filename || dump_file)) usage(1);
+       log_dst = to_stdout ? stderr : stdout;
 
-#ifndef HAVE_PCAP_FOPEN_OFFLINE
-       if (filter_stdin) {
-               fr_perror("-F is unsupported on this platform.");
-               return 1;
+#if !defined(HAVE_PCAP_FOPEN_OFFLINE) || !defined(HAVE_PCAP_DUMP_FOPEN)
+       if (from_stdin || to_stdout) {
+               fprintf(stderr, "radsniff: PCAP streams not supported.\n");
+               exit(64);
        }
 #endif
 
        if (!pcap_filter) {
                pcap_filter = buffer;
-               snprintf(buffer, sizeof(buffer), "udp port %d or %d",
-                        port, port + 1);
+               snprintf(buffer, sizeof(buffer), "udp port %d or %d or %d",
+                        port, port + 1, 3799);
        }
        
        /*
-        *      There are times when we don't need the dictionaries.
+        *  There are times when we don't need the dictionaries.
         */
-       if (printable_output) {
+       if (!to_stdout) {
                if (dict_init(radius_dir, RADIUS_DICTIONARY) < 0) {
                        fr_perror("radsniff");
-                       return 1;
+                       exit(64);
                }
        }
 
        if (radius_filter) {
                parsecode = userparse(radius_filter, &filter_vps);
                if (parsecode == T_OP_INVALID) {
-                       fprintf(stderr, "radsniff: Invalid RADIUS filter \"%s\": %s\n", radius_filter, fr_strerror());
-                       exit(1);
+                       fprintf(stderr, "radsniff: Invalid RADIUS filter \"%s\" (%s)\n", radius_filter, fr_strerror());
+                       exit(64);
                }
+               
                if (!filter_vps) {
                        fprintf(stderr, "radsniff: Empty RADIUS filter \"%s\"\n", radius_filter);
-                       exit(1);
+                       exit(64);
                }
 
-               filter_tree = rbtree_create((rbcmp) fr_packet_cmp,
-                                           free, 0);
+               filter_tree = rbtree_create((rbcmp) fr_packet_cmp, free, 0);
                if (!filter_tree) {
                        fprintf(stderr, "radsniff: Failed creating filter tree\n");
                        exit(1);
                }
        }
 
-       /* setup the request tree */
+       /*
+        *  Setup the request tree
+        */
        request_tree = rbtree_create((rbcmp) fr_packet_cmp, free, 0);
        if (!request_tree) {
                fprintf(stderr, "radsniff: Failed creating request tree\n");
                exit(1);
        }
 
-       /* allocate a null packet for decrypting attributes in CoA requests */
+       /*
+        *  Allocate a null packet for decrypting attributes in CoA requests
+        */
        nullpacket = rad_alloc(0);
        if (!nullpacket) {
                fprintf(stderr, "radsniff: Out of memory\n");
                exit(1);
        }
 
-       /* Set our device */
-       pcap_lookupnet(dev, &netp, &maskp, errbuf);
-
-       /* Print device to the user */
-       if (fr_debug_flag) {
-               if (dev) printf("Device: [%s]\n", dev);
-               if (packet_count > 0) {
-                       printf("Num of packets: [%d]\n",
-                              packet_count);
+       /*
+        *  Get the default capture device
+        */
+       if (!from_stdin && !from_file && !from_dev) {
+               from_dev = pcap_lookupdev(errbuf);
+               if (!from_dev) {
+                       fprintf(stderr, "radsniff: Failed discovering default interface (%s)\n", errbuf);
+                       exit(1);
                }
-               printf("PCAP filter: [%s]\n", pcap_filter);
-               if (filter_vps) {
-                       printf("RADIUS filter:\n");
-                       vp_printlist(stdout, filter_vps);
+
+               INFO(log_dst, "Capturing from interface \"%s\"\n", from_dev);
+       }
+       
+       /*
+        *  Print captures values which will be used
+        */
+       if (fr_debug_flag > 2) {
+                               DEBUG1(log_dst, "Sniffing with options:\n");
+               if (from_dev)   DEBUG1(log_dst, "  Device                   : [%s]\n", from_dev);
+               if (limit > 0)  DEBUG1(log_dst, "  Capture limit (packets)  : [%d]\n", limit);
+                               DEBUG1(log_dst, "  PCAP filter              : [%s]\n", pcap_filter);
+                               DEBUG1(log_dst, "  RADIUS secret            : [%s]\n", radius_secret);
+               if (filter_vps){DEBUG1(log_dst, "  RADIUS filter            :\n");
+                       vp_printlist(log_dst, filter_vps);
                }
-               printf("RADIUS secret: [%s]\n", radius_secret);
        }
 
-       /* Open the device so we can spy */
-       if (filename) {
-               descr = pcap_open_offline(filename, errbuf);
-
+       /*
+        *  Figure out whether were doing a reading from a file, doing a live
+        *  capture or reading from stdin.
+        */
+       if (from_file) {
+               in = pcap_open_offline(from_file, errbuf);
 #ifdef HAVE_PCAP_FOPEN_OFFLINE
-       } else if (filter_stdin) {
-               descr = pcap_fopen_offline(stdin, errbuf);
+       } else if (from_stdin) {
+               in = pcap_fopen_offline(stdin, errbuf);
 #endif
-
-       } else if (!dev) {
-               fprintf(stderr, "radsniff: No filename or device was specified.\n");
-               exit(1);
-
+       } else if (from_dev) {
+               pcap_lookupnet(from_dev, &ip_addr, &ip_mask, errbuf);
+               in = pcap_open_live(from_dev, 65536, 1, 1, errbuf);
        } else {
-               descr = pcap_open_live(dev, 65536, 1, 1, errbuf);
+               fprintf(stderr, "radsniff: No capture devices available\n");
        }
-       if (descr == NULL)
-       {
-               fprintf(stderr, "radsniff: pcap_open_live failed (%s)\n", errbuf);
+       
+       if (!in) {
+               fprintf(stderr, "radsniff: Failed opening input (%s)\n", errbuf);
                exit(1);
        }
 
-       if (dump_file) {
-               pcap_dumper = pcap_dump_open(descr, dump_file);
-               if (!pcap_dumper) {
-                       fprintf(stderr, "radsniff: Failed opening output file (%s)\n", pcap_geterr(descr));
+       if (to_file) {
+               out = pcap_dump_open(in, to_file);
+               if (!out) {
+                       fprintf(stderr, "radsniff: Failed opening output file (%s)\n", pcap_geterr(in));
                        exit(1);
                }
-
 #ifdef HAVE_PCAP_DUMP_FOPEN
-       } else if (filter_stdin) {
-               pcap_dumper = pcap_dump_fopen(descr, stdout);
-               if (!pcap_dumper) {
-                       fprintf(stderr, "radsniff: Failed opening stdout: %s\n", pcap_geterr(descr));
+       } else if (to_stdout) {
+               out = pcap_dump_fopen(in, stdout);
+               if (!out) {
+                       fprintf(stderr, "radsniff: Failed opening stdout (%s)\n", pcap_geterr(in));
                        exit(1);
                }
-
 #endif
        }
 
-       /* Apply the rules */
-       if( pcap_compile(descr, &fp, pcap_filter, 0, netp) == -1)
-       {
-               fprintf(stderr, "radsniff: pcap_compile failed\n");
+       /*
+        *  Apply the rules
+        */
+       if (pcap_compile(in, &fp, pcap_filter, 0, ip_mask) < 0) {
+               fprintf(stderr, "radsniff: Failed compiling PCAP filter (%s)\n", pcap_geterr(in));
                exit(1);
        }
-       if (pcap_setfilter(descr, &fp) == -1)
-       {
-               fprintf(stderr, "radsniff: pcap_setfilter failed\n");
+       
+       if (pcap_setfilter(in, &fp) < 0) {
+               fprintf(stderr, "radsniff: Failed applying PCAP filter (%s)\n", pcap_geterr(in));
                exit(1);
        }
 
-       /* Now we can set our callback function */
-       pcap_loop(descr, packet_count, got_packet, NULL);
-       pcap_close(descr);
-
-       if (filter_tree) rbtree_free(filter_tree);
-
-       DEBUG("Done sniffing\n");
+       /*
+        *  Enter the main capture loop...
+        */
+       pcap_loop(in, limit, got_packet, NULL);
+       
+       /*
+        *  ...were done capturing.
+        */
+       pcap_close(in);
+       if (out) {
+               pcap_dump_close(out);
+       }
+       
+       if (filter_tree) {
+               rbtree_free(filter_tree);
+       }
+       
+       INFO(log_dst, "Done sniffing\n");
+       
        return 0;
 }