Merge remote-tracking branch 'goog/tcpdump'

* goog/tcpdump: (1872 commits)
  Remove old version. Getting ready for new libpcap 1.5
  Remove commas from clauses in a comma-separated list.
  Fix typo.
  Describe all NFLOG TLV types and define structures for some of them.
  Check caplen in the NFLOG TLV loop.
  Have nflog_tlv_t include only the TLV header.
  Byte-swap the T and L in TLVs as necessary when reading an NFLOG file.
  Don't support D-Bus sniffing on OS X.
  Add post-1.5.2 bug fixes.
  Tag some changes with a bug identifier.
  Add items for 1.5.1 and 1.5.2.
  Formatting tweak.
  Count *ring buffer blocks*, not *packets* to be filtered in userland.
  Add a PACKET_COUNT_IS_UNLIMITED() to test for a packet count <= 0.
  Use HAVE_TPACKET3 rather than TPACKET_V3 to test for TPACKET_V3 support.
  Fix builds on systems without TPACKET_V3.
  tweak manpages formatting
  Fix pcap_loop() with a count of 0 and TPACKET_V3.
  Discourage the use of a zero timeout.
  We can't use TPACKET_V3 in immediate mode, so fall back on TPACKET_V2.
  ...

Change-Id: I2aa9bd87673c56aee439e1154b96a14026ca7985
diff --git a/pcap-dos.c b/pcap-dos.c
index 0700d6b..cecc73c 100644
--- a/pcap-dos.c
+++ b/pcap-dos.c
@@ -1,11 +1,11 @@
 /*
  *  This file is part of DOS-libpcap
- *  Ported to DOS/DOSX by G. Vanem <giva@bgnett.no>
+ *  Ported to DOS/DOSX by G. Vanem <gvanem@broadpark.no>
  *
  *  pcap-dos.c: Interface to PKTDRVR, NDIS2 and 32-bit pmode
  *              network drivers.
  *
- * @(#) $Header: /tcpdump/master/libpcap/pcap-dos.c,v 1.1.2.1 2005/05/03 18:54:35 guy Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/libpcap/pcap-dos.c,v 1.7 2008-04-22 17:16:30 guy Exp $ (LBL)
  */
 
 #include <stdio.h>
@@ -97,9 +97,10 @@
 
 static struct device *handle_to_device [20];
 
+static int  pcap_activate_dos (pcap_t *p);
 static int  pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback,
                            u_char *data);
-static void pcap_close_dos (pcap_t *p);
+static void pcap_cleanup_dos (pcap_t *p);
 static int  pcap_stats_dos (pcap_t *p, struct pcap_stat *ps);
 static int  pcap_sendpacket_dos (pcap_t *p, const void *buf, size_t len);
 static int  pcap_setfilter_dos (pcap_t *p, struct bpf_program *fp);
@@ -143,58 +144,73 @@
 }
 
 /*
+ * Private data for capturing on MS-DOS.
+ */
+struct pcap_dos {
+	void (*wait_proc)(void); /*          call proc while waiting */
+	struct pcap_stat stat;
+};
+
+pcap_t *pcap_create_interface (const char *device, char *ebuf)
+{
+	pcap_t *p;
+
+	p = pcap_create_common(device, ebuf, sizeof (struct pcap_dos));
+	if (p == NULL)
+		return (NULL);
+
+	p->activate_op = pcap_activate_dos;
+	return (p);
+}
+
+/*
  * Open MAC-driver with name 'device_name' for live capture of
  * network packets.
  */
-pcap_t *pcap_open_live (const char *device_name, int snaplen, int promisc,
-                        int timeout_ms, char *errbuf)
+static int pcap_activate_dos (pcap_t *pcap)
 { 
-  struct pcap *pcap;
+  struct pcap_dos *pcapd = pcap->priv;
 
-  if (snaplen < ETH_MIN)
-      snaplen = ETH_MIN;
-
-  if (snaplen > ETH_MAX)   /* silently accept and truncate large MTUs */
-      snaplen = ETH_MAX;
-
-  pcap = calloc (sizeof(*pcap), 1);
-  if (!pcap)
-  {
-    strcpy (errbuf, "Not enough memory (pcap)");
-    return (NULL);
+  if (pcap->opt.rfmon) {
+    /*
+     * No monitor mode on DOS.
+     */
+    return (PCAP_ERROR_RFMON_NOTSUP);
   }
 
-  pcap->snapshot          = max (ETH_MIN+8, snaplen);
+  if (pcap->snapshot < ETH_MIN+8)
+      pcap->snapshot = ETH_MIN+8;
+
+  if (pcap->snapshot > ETH_MAX)   /* silently accept and truncate large MTUs */
+      pcap->snapshot = ETH_MAX;
+
   pcap->linktype          = DLT_EN10MB;  /* !! */
-  pcap->inter_packet_wait = timeout_ms;
-  pcap->close_op          = pcap_close_dos;
+  pcap->cleanup_op        = pcap_cleanup_dos;
   pcap->read_op           = pcap_read_dos;
   pcap->stats_op          = pcap_stats_dos;
   pcap->inject_op         = pcap_sendpacket_dos;
   pcap->setfilter_op      = pcap_setfilter_dos;
-	pcap->setdirection_op   = NULL; /* Not implemented.*/
+  pcap->setdirection_op   = NULL; /* Not implemented.*/
   pcap->fd                = ++ref_count;
 
   if (pcap->fd == 1)  /* first time we're called */
   {
-    if (!init_watt32(pcap, device_name, errbuf) ||
-        !first_init(device_name, errbuf, promisc))
+    if (!init_watt32(pcap, pcap->opt.source, pcap->errbuf) ||
+        !first_init(pcap->opt.source, pcap->errbuf, pcap->opt.promisc))
     {
-      free (pcap);
-      return (NULL);
+      return (PCAP_ERROR);
     } 
     atexit (close_driver);
   }
-  else if (stricmp(active_dev->name,device_name))
+  else if (stricmp(active_dev->name,pcap->opt.source))
   {
-    snprintf (errbuf, PCAP_ERRBUF_SIZE,
+    snprintf (pcap->errbuf, PCAP_ERRBUF_SIZE,
               "Cannot use different devices simultaneously "
-              "(`%s' vs. `%s')", active_dev->name, device_name);
-    free (pcap);
-    pcap = NULL;
+              "(`%s' vs. `%s')", active_dev->name, pcap->opt.source);
+    return (PCAP_ERROR);
   }
   handle_to_device [pcap->fd-1] = active_dev;
-  return (pcap);
+  return (0);
 }
 
 /*
@@ -204,16 +220,16 @@
 static int
 pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data)
 {
+  struct pcap_dos *pd = p->priv;
   struct pcap_pkthdr pcap;
-  struct bpf_insn   *fcode = p->fcode.bf_insns;
-  struct timeval     now, expiry;
+  struct timeval     now, expiry = { 0,0 };
   BYTE  *rx_buf;
   int    rx_len = 0;
 
-  if (p->inter_packet_wait > 0)
+  if (p->opt.timeout > 0)
   {
     gettimeofday2 (&now, NULL);
-    expiry.tv_usec = now.tv_usec + 1000UL * p->inter_packet_wait;
+    expiry.tv_usec = now.tv_usec + 1000UL * p->opt.timeout;
     expiry.tv_sec  = now.tv_sec;
     while (expiry.tv_usec >= 1000000L)
     {
@@ -258,7 +274,7 @@
       pcap.len    = rx_len;
 
       if (callback &&
-          (!fcode || bpf_filter(fcode, rx_buf, pcap.len, pcap.caplen)))
+          (!p->fcode.bf_insns || bpf_filter(p->fcode.bf_insns, rx_buf, pcap.len, pcap.caplen)))
       {
         filter_count++;
 
@@ -282,10 +298,10 @@
       return (1);
     }
 
-    /* If not to wait for a packet or pcap_close() called from
+    /* If not to wait for a packet or pcap_cleanup_dos() called from
      * e.g. SIGINT handler, exit loop now.
      */
-    if (p->inter_packet_wait <= 0 || (volatile int)p->fd <= 0)
+    if (p->opt.timeout <= 0 || (volatile int)p->fd <= 0)
        break;
 
     gettimeofday2 (&now, NULL);
@@ -303,7 +319,7 @@
 
   if (rx_len < 0)            /* receive error */
   {
-    p->md.stat.ps_drop++;
+    pd->stat.ps_drop++;
 #ifdef USE_32BIT_DRIVERS
     if (pcap_pkt_debug > 1)
        printk ("pkt-err %s\n", pktInfo.error);
@@ -316,9 +332,10 @@
 static int
 pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback, u_char *data)
 {
+  struct pcap_dos *pd = p->priv;
   int rc, num = 0;
 
-  while (num <= cnt || (cnt < 0))
+  while (num <= cnt || PACKET_COUNT_IS_UNLIMITED(cnt))
   {
     if (p->fd <= 0)
        return (-1);
@@ -338,6 +355,7 @@
 static int pcap_stats_dos (pcap_t *p, struct pcap_stat *ps)
 {
   struct net_device_stats *stats;
+  struct pcap_dos         *pd;
   struct device           *dev = p ? get_device(p->fd) : NULL;
 
   if (!dev)
@@ -354,12 +372,13 @@
 
   FLUSHK();
 
-  p->md.stat.ps_recv   = stats->rx_packets;
-  p->md.stat.ps_drop  += stats->rx_missed_errors;
-  p->md.stat.ps_ifdrop = stats->rx_dropped +  /* queue full */
+  pd = p->priv;
+  pd->stat.ps_recv   = stats->rx_packets;
+  pd->stat.ps_drop  += stats->rx_missed_errors;
+  pd->stat.ps_ifdrop = stats->rx_dropped +  /* queue full */
                          stats->rx_errors;    /* HW errors */
   if (ps)
-     *ps = p->md.stat;
+     *ps = pd->stat;
 
   return (0);
 }
@@ -421,12 +440,15 @@
 /*
  * Close pcap device. Not called for offline captures.
  */
-static void pcap_close_dos (pcap_t *p)
+static void pcap_cleanup_dos (pcap_t *p)
 {
+  struct pcap_dos *pd;
+
   if (p && !exc_occured)
   {
+    pd = p->priv;
     if (pcap_stats(p,NULL) < 0)
-       p->md.stat.ps_drop = 0;
+       pd->stat.ps_drop = 0;
     if (!get_device(p->fd))
        return;
 
@@ -477,7 +499,7 @@
 {
   if (!_watt_is_init)
   {
-    strcpy (errbuf, "pcap_open_offline() or pcap_open_live() must be "
+    strcpy (errbuf, "pcap_open_offline() or pcap_activate() must be "
                     "called first");
     return (-1);
   }
@@ -585,10 +607,12 @@
  */
 void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait)
 {
+  struct pcap_dos *pd;
   if (p)
   {
-    p->wait_proc         = yield;
-    p->inter_packet_wait = wait;
+    pd                   = p->priv;
+    pd->wait_proc        = yield;
+    p->opt.timeout        = wait;
   }
 }
 
@@ -734,13 +758,13 @@
          fprintf (stderr, "Catching signal %d.\n", sig);
   }
   exc_occured = 1;
-  pcap_close_dos (NULL);
+  pcap_cleanup_dos (NULL);
 }
 #endif  /* __DJGPP__ */
 
 
 /*
- * Open the pcap device for the first client calling pcap_open_live()
+ * Open the pcap device for the first client calling pcap_activate()
  */
 static int first_init (const char *name, char *ebuf, int promisc)
 {
@@ -991,7 +1015,7 @@
  * Application config hooks to set various driver parameters.
  */
 
-static struct config_table debug_tab[] = {
+static const struct config_table debug_tab[] = {
             { "PKT.DEBUG",       ARG_ATOI,   &pcap_pkt_debug    },
             { "PKT.VECTOR",      ARG_ATOX_W, NULL               },
             { "NDIS.DEBUG",      ARG_ATOI,   NULL               },