]> The Tcpdump Group git mirrors - libpcap/commitdiff
For devices that we have some reason to believe are real live Ethernet
authorguy <guy>
Thu, 18 Dec 2003 23:32:31 +0000 (23:32 +0000)
committerguy <guy>
Thu, 18 Dec 2003 23:32:31 +0000 (23:32 +0000)
devices, offer DLT_DOCSIS as one of the choices of link-layer type, and
support setting that type as meaning just "set libpcap's notion of the
link-layer type to DLT_DOCSIS" without telling the driver to use
DLT_DOCSIS.

pcap-bpf.c
pcap-dag.c
pcap-dlpi.c
pcap-linux.c
pcap-nit.c
pcap-pf.c
pcap-snit.c
pcap-snoop.c
pcap-win32.c
pcap.c

index 8a0cc2f1d6b148d23a18b8c2efb27bfcef3e5801..a40e1610f1c7b9416f8e178b99d4c3262b47444d 100644 (file)
@@ -20,7 +20,7 @@
  */
 #ifndef lint
 static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.71 2003-11-22 00:06:05 guy Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.72 2003-12-18 23:32:31 guy Exp $ (LBL)";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -489,6 +489,14 @@ pcap_close_bpf(pcap_t *p)
                close(p->fd);
 }
 
+/*
+ * We include the OS's <net/bpf.h>, not our "pcap-bpf.h", so we probably
+ * don't get DLT_DOCSIS defined.
+ */
+#ifndef DLT_DOCSIS
+#define DLT_DOCSIS     143
+#endif
+
 /*
  * XXX - on AIX, IBM's tcpdump (and perhaps the incompatible-with-everybody-
  * else's libpcap in AIX 5.1) appears to forcibly load the BPF driver
@@ -653,7 +661,10 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
         * not fatal; we just don't get to use the feature later.
         */
        if (ioctl(fd, BIOCGDLTLIST, (caddr_t)&bdl) == 0) {
-               bdl.bfl_list = (u_int *) malloc(sizeof(u_int) * bdl.bfl_len);
+               u_int i;
+               int is_ethernet;
+
+               bdl.bfl_list = (u_int *) malloc(sizeof(u_int) * bdl.bfl_len + 1);
                if (bdl.bfl_list == NULL) {
                        (void)snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
                            pcap_strerror(errno));
@@ -663,9 +674,44 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
                if (ioctl(fd, BIOCGDLTLIST, (caddr_t)&bdl) < 0) {
                        (void)snprintf(ebuf, PCAP_ERRBUF_SIZE,
                            "BIOCGDLTLIST: %s", pcap_strerror(errno));
+                       free(bdl.bfl_list);
                        goto bad;
                }
 
+               /*
+                * OK, for real Ethernet devices, add DLT_DOCSIS to the
+                * list, so that an application can let you choose it,
+                * in case you're capturing DOCSIS traffic that a Cisco
+                * Cable Modem Termination System is putting out onto
+                * an Ethernet (it doesn't put an Ethernet header onto
+                * the wire, it puts raw DOCSIS frames out on the wire
+                * inside the low-level Ethernet framing).
+                *
+                * A "real Ethernet device" is defined here as a device
+                * that has a link-layer type of DLT_EN10MB and that has
+                * no alternate link-layer types; that's done to exclude
+                * 802.11 interfaces (which might or might not be the
+                * right thing to do, but I suspect it is - Ethernet <->
+                * 802.11 bridges would probably badly mishandle frames
+                * that don't have Ethernet headers).
+                */
+               if (p->linktype == DLT_EN10MB) {
+                       is_ethernet = TRUE;
+                       for (i = 0; i < bdl.bfl_len; i++) {
+                               if (bdl.bfl_list != DLT_EN10MB) {
+                                       is_ethernet = FALSE;
+                                       break;
+                               }
+                       }
+                       if (is_ethernet) {
+                               /*
+                                * We reserved one more slot at the end of
+                                * the list.
+                                */
+                               bdl.bfl_list[bdl.bfl_len] = DLT_DOCSIS;
+                               bdl.bfl_len++;
+                       }
+               }
                p->dlt_count = bdl.bfl_len;
                p->dlt_list = bdl.bfl_list;
        } else {
@@ -677,6 +723,26 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
        }
 #endif
 
+       /*
+        * If this is an Ethernet device, and we don't have a DLT_ list,
+        * give it a list with DLT_EN10MB and DLT_DOCSIS.  (That'd give
+        * 802.11 interfaces DLT_DOCSIS, which isn't the right thing to
+        * do, but there's not much we can do about that without finding
+        * some other way of determining whether it's an Ethernet or 802.11
+        * device.)
+        */
+       if (p->linktype == DLT_EN10MB && p->dlt_count == 0) {
+               p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+               /*
+                * If that fails, just leave the list empty.
+                */
+               if (p->dlt_list != NULL) {
+                       p->dlt_list[0] = DLT_EN10MB;
+                       p->dlt_list[1] = DLT_DOCSIS;
+                       p->dlt_count = 2;
+               }
+       }
+               
        /* set timeout */
        if (to_ms != 0) {
                /*
@@ -842,10 +908,8 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
        return (p);
  bad:
        (void)close(fd);
-#ifdef BIOCGDLTLIST
-       if (bdl.bfl_list != NULL)
-               free(bdl.bfl_list);
-#endif
+       if (p->dlt_list != NULL)
+               free(p->dlt_list);
        free(p);
        return (NULL);
 }
index fa0182493753057d3cc5afea56f6102fe7acecda..f245d1afc13a8120860835c173c8c70e609146ed 100644 (file)
@@ -29,7 +29,7 @@
 
 #ifndef lint
 static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/libpcap/pcap-dag.c,v 1.14 2003-11-21 10:19:33 guy Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/libpcap/pcap-dag.c,v 1.15 2003-12-18 23:32:31 guy Exp $ (LBL)";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -457,16 +457,16 @@ pcap_t *dag_open_live(const char *device, int snaplen, int promisc, int to_ms, c
   handle->snapshot     = snaplen;
   /*handle->md.timeout = to_ms; */
 
-  if ((handle->linktype = dag_get_datalink(handle)) < 0) {
+  if (dag_get_datalink(handle) < 0) {
     snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_get_linktype %s: unknown linktype\n", device);
-       goto fail;
+    goto fail;
   }
   
   handle->bufsize = 0;
 
   if (new_pcap_dag(handle) < 0) {
     snprintf(ebuf, PCAP_ERRBUF_SIZE, "new_pcap_dag %s: %s\n", device, pcap_strerror(errno));
-       goto fail;
+    goto fail;
   }
 
   /*
@@ -496,6 +496,11 @@ fail:
        free((char *)device);
   }
   if (handle != NULL) {
+       /*
+        * Get rid of any link-layer type list we allocated.
+        */
+       if (handle->dlt_list != NULL)
+               free(handle->dlt_list);
        free(handle);
   }
 
@@ -666,8 +671,6 @@ dag_setnonblock(pcap_t *p, int nonblock, char *errbuf)
 static int
 dag_get_datalink(pcap_t *p)
 {
-  int linktype = -1;
-
   /* Check the type through a dagapi call.
   */
   switch(dag_linktype(p->fd)) {
@@ -681,30 +684,48 @@ dag_get_datalink(pcap_t *p)
       record = (dag_record_t *)(p->md.dag_mem_base + p->md.dag_mem_bottom);
 
       if ((ntohl(record->rec.pos.hdlc) & 0xffff0000) == 0xff030000) {
-        linktype = DLT_PPP_SERIAL;
+        p->linktype = DLT_PPP_SERIAL;
         fprintf(stderr, "Set DAG linktype to %d (DLT_PPP_SERIAL)\n", linktype);
       } else {
-        linktype = DLT_CHDLC;
+        p->linktype = DLT_CHDLC;
         fprintf(stderr, "Set DAG linktype to %d (DLT_CHDLC)\n", linktype);
       }
       break;
     }
   case TYPE_ETH:
-    linktype = DLT_EN10MB;
+    p->linktype = DLT_EN10MB;
+    /*
+     * This is (presumably) a real Ethernet capture; give it a
+     * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
+     * that an application can let you choose it, in case you're
+     * capturing DOCSIS traffic that a Cisco Cable Modem
+     * Termination System is putting out onto an Ethernet (it
+     * doesn't put an Ethernet header onto the wire, it puts raw
+     * DOCSIS frames out on the wire inside the low-level
+     * Ethernet framing).
+     */
+    p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+    /*
+     * If that fails, just leave the list empty.
+     */
+    if (p->dlt_list != NULL) {
+      p->dlt_list[0] = DLT_EN10MB;
+      p->dlt_list[1] = DLT_DOCSIS;
+      p->dlt_count = 2;
+    }
     fprintf(stderr, "Set DAG linktype to %d (DLT_EN10MB)\n", linktype);
     break;
   case TYPE_ATM: 
-    linktype = DLT_ATM_RFC1483;
+    p->linktype = DLT_ATM_RFC1483;
     fprintf(stderr, "Set DAG linktype to %d (DLT_ATM_RFC1483)\n", linktype);
     break;
   case TYPE_LEGACY:
-    linktype = DLT_NULL;
+    p->linktype = DLT_NULL;
     fprintf(stderr, "Set DAG linktype to %d (DLT_NULL)\n", linktype);
     break;
   default:
     fprintf(stderr, "Unknown DAG linktype %d\n", dag_linktype(p->fd));
-    break;
+    return -1;;
   }
-
-  return linktype;
+  return 0;
 }
index 1e7055b6e603ec7a69a566294a99c6d2ea90cfb4..20c1fbb0dae3ccc3369b55064f7652e4ca4cffcc 100644 (file)
@@ -38,7 +38,7 @@
 
 #ifndef lint
 static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.94 2003-11-21 10:19:34 guy Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.95 2003-12-18 23:32:32 guy Exp $ (LBL)";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -585,6 +585,25 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
        case DL_ETHER:
                p->linktype = DLT_EN10MB;
                p->offset = 2;
+               /*
+                * This is (presumably) a real Ethernet capture; give it a
+                * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
+                * that an application can let you choose it, in case you're
+                * capturing DOCSIS traffic that a Cisco Cable Modem
+                * Termination System is putting out onto an Ethernet (it
+                * doesn't put an Ethernet header onto the wire, it puts raw
+                * DOCSIS frames out on the wire inside the low-level
+                * Ethernet framing).
+                */
+               p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+               /*
+                * If that fails, just leave the list empty.
+                */
+               if (p->dlt_list != NULL) {
+                       p->dlt_list[0] = DLT_EN10MB;
+                       p->dlt_list[1] = DLT_DOCSIS;
+                       p->dlt_count = 2;
+               }
                break;
 
        case DL_FDDI:
@@ -722,6 +741,11 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
 bad:
        if (p->fd >= 0)
                close(p->fd);
+       /*
+        * Get rid of any link-layer type list we allocated.
+        */
+       if (p->dlt_list != NULL)
+               free(p->dlt_list);
        free(p);
        return (NULL);
 }
index 50883b66738e068345cd4b26d8aea063a173077f..61d1c37bab326b9e355a9cea7f0c8e516249def1 100644 (file)
@@ -27,7 +27,7 @@
 
 #ifndef lint
 static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.102 2003-11-21 10:19:34 guy Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.103 2003-12-18 23:32:32 guy Exp $ (LBL)";
 #endif
 
 /*
@@ -948,6 +948,34 @@ static void map_arphrd_to_dlt(pcap_t *handle, int arptype, int cooked_ok)
        switch (arptype) {
 
        case ARPHRD_ETHER:
+               /*
+                * This is (presumably) a real Ethernet capture; give it a
+                * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
+                * that an application can let you choose it, in case you're
+                * capturing DOCSIS traffic that a Cisco Cable Modem
+                * Termination System is putting out onto an Ethernet (it
+                * doesn't put an Ethernet header onto the wire, it puts raw
+                * DOCSIS frames out on the wire inside the low-level
+                * Ethernet framing).
+                *
+                * XXX - are there any sorts of "fake Ethernet" that have
+                * ARPHRD_ETHER but that *shouldn't offer DLT_DOCSIS as
+                * a Cisco CMTS won't put traffic onto it or get traffic
+                * bridged onto it?  ISDN is handled in "live_open_new()",
+                * as we fall back on cooked mode there; are there any
+                * others?
+                */
+               handle->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+               /*
+                * If that fails, just leave the list empty.
+                */
+               if (handle->dlt_list != NULL) {
+                       handle->dlt_list[0] = DLT_EN10MB;
+                       handle->dlt_list[1] = DLT_DOCSIS;
+                       handle->dlt_count = 2;
+               }
+               /* FALLTHROUGH */
+
        case ARPHRD_METRICOM:
        case ARPHRD_LOOPBACK:
                handle->linktype = DLT_EN10MB;
@@ -1278,6 +1306,17 @@ live_open_new(pcap_t *handle, const char *device, int promisc,
                                }
                                handle->md.cooked = 1;
 
+                               /*
+                                * Get rid of any link-layer type list
+                                * we allocated - this only supports cooked
+                                * capture.
+                                */
+                               if (handle->dlt_list != NULL) {
+                                       free(handle->dlt_list);
+                                       handle->dlt_list = NULL;
+                                       handle->dlt_count = 0;
+                               }
+
                                if (handle->linktype == -1) {
                                        /*
                                         * Warn that we're falling back on
@@ -1294,7 +1333,7 @@ live_open_new(pcap_t *handle, const char *device, int promisc,
                                }
                                /* IrDA capture is not a real "cooked" capture,
                                 * it's IrLAP frames, not IP packets. */
-                               if(handle->linktype != DLT_LINUX_IRDA)
+                               if (handle->linktype != DLT_LINUX_IRDA)
                                        handle->linktype = DLT_LINUX_SLL;
                        }
 
@@ -1368,9 +1407,14 @@ live_open_new(pcap_t *handle, const char *device, int promisc,
        if (sock_fd != -1)
                close(sock_fd);
 
-       if (fatal_err)
+       if (fatal_err) {
+               /*
+                * Get rid of any link-layer type list we allocated.
+                */
+               if (handle->dlt_list != NULL)
+                       free(handle->dlt_list);
                return -2;
-       else
+       else
                return 0;
 #else
        strncpy(ebuf,
index 6aebc90f2d49741786986ca33df11f61e6f0e912..e89f9ba21dd47121ddce4b7f7c62ce6a574e2239 100644 (file)
@@ -20,7 +20,7 @@
  */
 #ifndef lint
 static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/libpcap/pcap-nit.c,v 1.53 2003-11-21 10:19:35 guy Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/libpcap/pcap-nit.c,v 1.54 2003-12-18 23:32:32 guy Exp $ (LBL)";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -285,6 +285,26 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
         */
        p->selectable_fd = p->fd;
 
+       /*
+        * This is (presumably) a real Ethernet capture; give it a
+        * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
+        * that an application can let you choose it, in case you're
+        * capturing DOCSIS traffic that a Cisco Cable Modem
+        * Termination System is putting out onto an Ethernet (it
+        * doesn't put an Ethernet header onto the wire, it puts raw
+        * DOCSIS frames out on the wire inside the low-level
+        * Ethernet framing).
+        */
+       p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+       /*
+        * If that fails, just leave the list empty.
+        */
+       if (p->dlt_list != NULL) {
+               p->dlt_list[0] = DLT_EN10MB;
+               p->dlt_list[1] = DLT_DOCSIS;
+               p->dlt_count = 2;
+       }
+
        p->read_op = pcap_read_nit;
        p->setfilter_op = install_bpf_program;  /* no kernel filtering */
        p->set_datalink_op = NULL;      /* can't change data link type */
index 22512932087efd72fbbdeb6570e6adc26ec43519..a8ad1424e876510a818b755d7bef6bf7a1bf217f 100644 (file)
--- a/pcap-pf.c
+++ b/pcap-pf.c
@@ -24,7 +24,7 @@
 
 #ifndef lint
 static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/libpcap/pcap-pf.c,v 1.84 2003-11-22 00:32:25 guy Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/libpcap/pcap-pf.c,v 1.85 2003-12-18 23:32:33 guy Exp $ (LBL)";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -340,6 +340,25 @@ your system may not be properly configured; see the packetfilter(4) man page\n",
        case ENDT_10MB:
                p->linktype = DLT_EN10MB;
                p->offset = 2;
+               /*
+                * This is (presumably) a real Ethernet capture; give it a
+                * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
+                * that an application can let you choose it, in case you're
+                * capturing DOCSIS traffic that a Cisco Cable Modem
+                * Termination System is putting out onto an Ethernet (it
+                * doesn't put an Ethernet header onto the wire, it puts raw
+                * DOCSIS frames out on the wire inside the low-level
+                * Ethernet framing).
+                */
+               p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+               /*
+                * If that fails, just leave the list empty.
+                */
+               if (p->dlt_list != NULL) {
+                       p->dlt_list[0] = DLT_EN10MB;
+                       p->dlt_list[1] = DLT_DOCSIS;
+                       p->dlt_count = 2;
+               }
                break;
 
        case ENDT_FDDI:
@@ -451,6 +470,11 @@ your system may not be properly configured; see the packetfilter(4) man page\n",
  bad:
        if (p->fd >= 0)
                close(p->fd);
+       /*
+        * Get rid of any link-layer type list we allocated.
+        */
+       if (p->dlt_list != NULL)
+               free(p->dlt_list);
        free(p);
        return (NULL);
 }
index 20a688937fc1c7dcaed2a37c95147ec28d8f411f..209878b57494289706b1e398a4688a094f2c6c52 100644 (file)
@@ -25,7 +25,7 @@
 
 #ifndef lint
 static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/libpcap/pcap-snit.c,v 1.69 2003-11-21 10:19:35 guy Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/libpcap/pcap-snit.c,v 1.70 2003-12-18 23:32:33 guy Exp $ (LBL)";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -344,6 +344,26 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
         */
        p->selectable_fd = p->fd;
 
+       /*
+        * This is (presumably) a real Ethernet capture; give it a
+        * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
+        * that an application can let you choose it, in case you're
+        * capturing DOCSIS traffic that a Cisco Cable Modem
+        * Termination System is putting out onto an Ethernet (it
+        * doesn't put an Ethernet header onto the wire, it puts raw
+        * DOCSIS frames out on the wire inside the low-level
+        * Ethernet framing).
+        */
+       p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+       /*
+        * If that fails, just leave the list empty.
+        */
+       if (p->dlt_list != NULL) {
+               p->dlt_list[0] = DLT_EN10MB;
+               p->dlt_list[1] = DLT_DOCSIS;
+               p->dlt_count = 2;
+       }
+
        p->read_op = pcap_read_snit;
        p->setfilter_op = install_bpf_program;  /* no kernel filtering */
        p->set_datalink_op = NULL;      /* can't change data link type */
index d216ba9b1a988162057045d90b6167cb8629e5f4..7ea8394efaf798c5ba1d10b7b3475fa5cf7dcaae 100644 (file)
@@ -20,7 +20,7 @@
  */
 #ifndef lint
 static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/libpcap/pcap-snoop.c,v 1.49 2003-11-21 10:19:35 guy Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/libpcap/pcap-snoop.c,v 1.50 2003-12-18 23:32:33 guy Exp $ (LBL)";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -237,6 +237,35 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
                p->linktype = DLT_EN10MB;
                p->offset = RAW_HDRPAD(sizeof(struct ether_header));
                ll_hdrlen = sizeof(struct ether_header);
+               /*
+                * This is (presumably) a real Ethernet capture; give it a
+                * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
+                * that an application can let you choose it, in case you're
+                * capturing DOCSIS traffic that a Cisco Cable Modem
+                * Termination System is putting out onto an Ethernet (it
+                * doesn't put an Ethernet header onto the wire, it puts raw
+                * DOCSIS frames out on the wire inside the low-level
+                * Ethernet framing).
+                *
+                * XXX - are there any sorts of "fake Ethernet" that have
+                * Ethernet link-layer headers but that *shouldn't offer
+                * DLT_DOCSIS as a Cisco CMTS won't put traffic onto it
+                * or get traffic bridged onto it?  "el" is for ATM LANE
+                * Ethernet devices, so that might be the case for them;
+                * the same applies for "qaa" classical IP devices.  If
+                * "fa" devices are for FORE SPANS, that'd apply to them
+                * as well; what are "cip" devices - some other ATM
+                * Classical IP devices?
+                */
+               handle->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+               /*
+                * If that fails, just leave the list empty.
+                */
+               if (handle->dlt_list != NULL) {
+                       handle->dlt_list[0] = DLT_EN10MB;
+                       handle->dlt_list[1] = DLT_DOCSIS;
+                       handle->dlt_count = 2;
+               }
        } else if (strncmp("ipg", device, 3) == 0 ||
                   strncmp("rns", device, 3) == 0 ||    /* O2/200/2000 FDDI */
                   strncmp("xpi", device, 3) == 0) {
@@ -339,6 +368,11 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
        return (p);
  bad:
        (void)close(fd);
+       /*
+        * Get rid of any link-layer type list we allocated.
+        */
+       if (p->dlt_list != NULL)
+               free(p->dlt_list);
        free(p);
        return (NULL);
 }
index ad53a1b8bfe3be69fafaedc80b5f8b0242e7490c..f16da44eaee5c61fdededc4189853b4a3e6e09f1 100644 (file)
@@ -32,7 +32,7 @@
 
 #ifndef lint
 static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/libpcap/pcap-win32.c,v 1.18 2003-11-30 02:31:04 guy Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/libpcap/pcap-win32.c,v 1.19 2003-12-18 23:32:33 guy Exp $ (LBL)";
 #endif
 
 #include <pcap-int.h>
@@ -231,6 +231,25 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
                
        case NdisMedium802_3:
                p->linktype = DLT_EN10MB;
+               /*
+                * This is (presumably) a real Ethernet capture; give it a
+                * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
+                * that an application can let you choose it, in case you're
+                * capturing DOCSIS traffic that a Cisco Cable Modem
+                * Termination System is putting out onto an Ethernet (it
+                * doesn't put an Ethernet header onto the wire, it puts raw
+                * DOCSIS frames out on the wire inside the low-level
+                * Ethernet framing).
+                */
+               p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+               /*
+                * If that fails, just leave the list empty.
+                */
+               if (p->dlt_list != NULL) {
+                       p->dlt_list[0] = DLT_EN10MB;
+                       p->dlt_list[1] = DLT_DOCSIS;
+                       p->dlt_count = 2;
+               }
                break;
                
        case NdisMediumFddi:
@@ -313,6 +332,11 @@ bad:
            PacketCloseAdapter(p->adapter);
        if (p->buffer != NULL)
                free(p->buffer);
+       /*
+        * Get rid of any link-layer type list we allocated.
+        */
+       if (p->dlt_list != NULL)
+               free(p->dlt_list);
        free(p);
        return (NULL);
 }
diff --git a/pcap.c b/pcap.c
index 8dd34b911fa70ca40d7192e8431275c57d5d7812..8af22261a999bbb8b83b0b1a293385607f606538 100644 (file)
--- a/pcap.c
+++ b/pcap.c
@@ -33,7 +33,7 @@
 
 #ifndef lint
 static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.69 2003-11-21 10:19:36 guy Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.70 2003-12-18 23:32:34 guy Exp $ (LBL)";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -275,6 +275,22 @@ pcap_set_datalink(pcap_t *p, int dlt)
                        break;
        if (i >= p->dlt_count)
                goto unsupported;
+       if (p->dlt_count == 2 && p->dlt_list[0] == DLT_EN10MB &&
+           dlt == DLT_DOCSIS) {
+               /*
+                * This is presumably an Ethernet device, as the first
+                * link-layer type it offers is DLT_EN10MB, and the only
+                * other type it offers is DLT_DOCSIS.  That means that
+                * we can't tell the driver to supply DOCSIS link-layer
+                * headers - we're just pretending that's what we're
+                * getting, as, presumably, we're capturing on a dedicated
+                * link to a Cisco Cable Modem Termination System, and
+                * it's putting raw DOCSIS frames on the wire inside low-level
+                * Ethernet framing.
+                */
+               p->linktype = dlt;
+               return (0);
+       }
        if (p->set_datalink_op(p, dlt) == -1)
                return (-1);
        p->linktype = dlt;
@@ -331,6 +347,7 @@ static struct dlt_choice dlt_choices[] = {
        DLT_CHOICE(DLT_SUNATM, "Sun raw ATM"),
        DLT_CHOICE(DLT_IEEE802_11_RADIO, "802.11 plus radio information header"),
        DLT_CHOICE(DLT_ARCNET_LINUX, "Linux ARCNET"),
+       DLT_CHOICE(DLT_DOCSIS, "DOCSIS"),
        DLT_CHOICE(DLT_LINUX_IRDA, "Linux IrDA"),
        DLT_CHOICE_SENTINEL
 };