dhcpdump and patch 

I was at work the other day and the whole network went down. DHCP and upstream routers went out and the network went kinda nuts. I tried dhcpdump to get a look at the traffic on the local network segment.

Sadly it doesn’t work with pcap files (from tcpdump or wireshark), it only works with live network interfaces and must be run as rroot. So I decided to add pcap file to dhcpdump 1.8. I tried contacting the author but didn’t hear back, so I decided to put it up here.

pcapfile.patch

  • add option to read from pcap file
  • change to read time from pcap packet header
--- dhcpdump-1.8/dhcpdump.c     2008-06-23 20:26:52.000000000 -0700
+++ dhcpdump.c  2009-09-30 15:22:10.000000000 -0700
@@ -71,7 +71,7 @@
 void   printHexString(u_char *data, int len);

 void usage() {
-       printf("Usage: $0 <-i interface> [-h macaddress]n");
+       printf("Usage: $0 <-i interface|-f pcapfile> [-h macaddress]n");
        exit(0);
 }

@@ -80,6 +80,7 @@
        pcap_t *cap;
        struct bpf_program fp;
        char    *interface = NULL;
+       char    *pcap_file = NULL;

        for (i = 1; i < argc; i++) {
                if (argv[i] == NULL || argv[i][0] != '-') break;
@@ -90,6 +91,9 @@
                case 'i':
                        interface = argv[++i];
                        break;
+               case 'f':
+                       pcap_file = argv[++i];
+                       break;
                default:
                        fprintf(stderr, "%s: %c: uknown optionn",
                            argv[0], argv[i][1]);
@@ -97,13 +101,24 @@
                }
        }

-       if (interface == NULL) usage();
+       if (    //no interface or pcap file specified
+               ((interface == NULL) && (pcap_file == NULL)) ||
+               //both an interface and a pcap file specified
+               ((interface != NULL) && (pcap_file != NULL))
+               )
+               usage();

        if (hmask)
                regcomp(&preg, hmask, REG_EXTENDED | REG_ICASE | REG_NOSUB);

-       if ((cap = pcap_open_live(interface, 1500, 1, 100, errbuf)) == NULL)
-               errx(1, "pcap_open_live(): %s", errbuf);
+       if (interface != NULL) {
+               if ((cap = pcap_open_live(interface, 1500, 1, 100, errbuf)) == NULL)
+                       errx(1, "pcap_open_live(): %s", errbuf);
+       }
+       else {
+               if ((cap = pcap_open_offline(pcap_file,errbuf)) == NULL)
+                       errx(1, "pcap_open_offline(): %s", errbuf);
+       }
        if (pcap_compile(cap, &fp, "udp and (port bootpc or port bootps)", 0, 0) < 0)
                errx(1,"pcap_compile: %s", pcap_geterr(cap));
        if (pcap_setfilter(cap, &fp) < 0)
@@ -148,12 +163,11 @@
        offset += sizeof(struct udphdr);

        {
-               struct timeval tp;
-               gettimeofday(&tp, NULL);
+               //get time from pcap to enable reading from capture file
                strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S.",
-                   localtime(&(tp.tv_sec)));
+                   localtime(&(h->ts.tv_sec)));
                sprintf(timestamp + strlen(timestamp), "%03ld",
-                   tp.tv_usec / 1000);
+                   h->ts.tv_usec / 1000);
        }

        strcpy(mac_origin, ether_ntoa((struct ether_addr *)eh->ether_shost));