]> The Tcpdump Group git mirrors - libpcap/commitdiff
From Jon Smirl:
authorguy <guy>
Tue, 23 Dec 2008 18:04:28 +0000 (18:04 +0000)
committerguy <guy>
Tue, 23 Dec 2008 18:04:28 +0000 (18:04 +0000)
try scanning the sysfs USB directory first and, if that
directory doesn't exist, try the procfs USB directory, to handle
newer kernels where the relevant director is in sysfs;

use the data length, not the URB length, as the amount of data
in the packet (the URB length is the amount of space *available*
for the data, not the actual amount of data).

For the memory-mapped interface, include the padding after the URB and
setup header in the packet lengths, and return a different link-layer
type so that code reading the packets knows that padding is there.

gencode.c
pcap-usb-linux.c
pcap.c
pcap/bpf.h
pcap/usb.h [new file with mode: 0644]
savefile.c

index 554240b09fd41b69b1df0d30ca441e46f773a609..a918dd36fb7f6cd4577e192a6b939d6bdcdbf580 100644 (file)
--- a/gencode.c
+++ b/gencode.c
@@ -21,7 +21,7 @@
  */
 #ifndef lint
 static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.290.2.17 2008-12-21 19:29:49 guy Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.290.2.18 2008-12-23 18:04:28 guy Exp $ (LBL)";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -1507,6 +1507,16 @@ init_linktype(p)
                off_nl = -1;
                off_nl_nosnap = -1;
                return;
+
+       case DLT_USB_LINUX_MMAP:
+               /*
+                * Currently, only raw "link[N:M]" filtering is supported.
+                */
+               off_linktype = -1;
+               off_macpl = -1;
+               off_nl = -1;
+               off_nl_nosnap = -1;
+               return;
        }
        bpf_error("unknown data link type %d", linktype);
        /* NOTREACHED */
@@ -3360,6 +3370,7 @@ gen_linktype(proto)
 
        case DLT_USB:
        case DLT_USB_LINUX:
+       case DLT_USB_LINUX_MMAP:
                bpf_error("USB link-layer type filtering not implemented");
 
        case DLT_BLUETOOTH_HCI_H4:
index 649c7d5902ecf9e101521ee78edb848ad731e0ae..c78a8e757cd8f7648399ebb224910c5b6c4f8885 100644 (file)
@@ -34,7 +34,7 @@
  */
 #ifndef lint
 static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/libpcap/pcap-usb-linux.c,v 1.16.2.11 2008-11-24 18:50:20 guy Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/libpcap/pcap-usb-linux.c,v 1.16.2.12 2008-12-23 18:04:29 guy Exp $ (LBL)";
 #endif
  
 #ifdef HAVE_CONFIG_H
@@ -63,7 +63,8 @@ static const char rcsid[] _U_ =
 
 #define USB_IFACE "usb"
 #define USB_TEXT_DIR "/sys/kernel/debug/usbmon"
-#define USB_BUS_DIR "/proc/bus/usb"
+#define SYS_USB_BUS_DIR "/sys/bus/usb/devices"
+#define PROC_USB_BUS_DIR "/proc/bus/usb"
 #define USB_LINE_LEN 4096
 
 #if __BYTE_ORDER == __LITTLE_ENDIAN
@@ -142,27 +143,52 @@ usb_platform_finddevs(pcap_if_t **alldevsp, char *err_str)
        struct dirent* data;
        int ret = 0;
        DIR* dir;
+       int n;
+       char* name;
+       size_t len;
 
-       /* scan procfs usb bus directory */
-       dir = opendir(USB_BUS_DIR);
-       if (!dir) return 0;
-       while ((ret == 0) && ((data = readdir(dir)) != 0)) {
-               int n;
-               char* name = data->d_name;
-               int len = strlen(name);
-
-               /* if this file name does not end with a number it's not of our interest */
-               if ((len < 1) || !isdigit(name[--len]))
-                       continue;
-               while (isdigit(name[--len]));
-               if (sscanf(&name[len+1], "%d", &n) != 1) 
-                       continue;
-
-               ret = usb_dev_add(alldevsp, n, err_str);
+       /* try scanning sysfs usb bus directory */
+       dir = opendir(SYS_USB_BUS_DIR);
+       if (dir != NULL) {
+               while ((ret == 0) && ((data = readdir(dir)) != 0)) {
+                       name = data->d_name;
+
+                       if (strncmp(name, "usb", 3) != 0)
+                               continue;
+
+                       if (sscanf(&name[3], "%d", &n) == 0) 
+                               continue;
+
+                       ret = usb_dev_add(alldevsp, n, err_str);
+               }
+
+               closedir(dir);
+               return ret;
+       }
+
+       /* that didn't work; try scanning procfs usb bus directory */
+       dir = opendir(PROC_USB_BUS_DIR);
+       if (dir != NULL) {
+               while ((ret == 0) && ((data = readdir(dir)) != 0)) {
+                       name = data->d_name;
+                       len = strlen(name);
+
+                       /* if this file name does not end with a number it's not of our interest */
+                       if ((len < 1) || !isdigit(name[--len]))
+                               continue;
+                       while (isdigit(name[--len]));
+                       if (sscanf(&name[len+1], "%d", &n) != 1) 
+                               continue;
+
+                       ret = usb_dev_add(alldevsp, n, err_str);
+               }
+
+               closedir(dir);
+               return ret;
        }
 
-       closedir(dir);
-       return ret;
+       /* neither of them worked */
+       return 0;
 }
 
 static 
@@ -229,6 +255,7 @@ usb_activate(pcap_t* handle)
 
                /* binary api is available, try to use fast mmap access */
                if (usb_mmap(handle)) {
+                       handle->linktype = DLT_USB_LINUX_MMAP;
                        handle->stats_op = usb_stats_linux_bin;
                        handle->read_op = usb_read_linux_mmap;
                        handle->cleanup_op = usb_cleanup_linux_mmap;
@@ -632,7 +659,7 @@ usb_read_linux_bin(pcap_t *handle, int max_packets, pcap_handler callback, u_cha
                clen = info.hdr->data_len;
        info.hdr->data_len = clen;
        pkth.caplen = clen + sizeof(pcap_usb_header);
-       pkth.len = info.hdr->urb_len + sizeof(pcap_usb_header);
+       pkth.len = info.hdr->data_len + sizeof(pcap_usb_header);
        pkth.ts.tv_sec = info.hdr->ts_sec;
        pkth.ts.tv_usec = info.hdr->ts_usec;
 
@@ -705,8 +732,8 @@ usb_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, u_ch
                                clen = hdr->data_len;
 
                        /* get packet info from header*/
-                       pkth.caplen = clen + sizeof(pcap_usb_header);
-                       pkth.len = hdr->urb_len + sizeof(pcap_usb_header);
+                       pkth.caplen = clen + MMAPPED_USB_HEADER_SIZE;
+                       pkth.len = hdr->data_len + MMAPPED_USB_HEADER_SIZE;
                        pkth.ts.tv_sec = hdr->ts_sec;
                        pkth.ts.tv_usec = hdr->ts_usec;
 
diff --git a/pcap.c b/pcap.c
index ad4cc3134f621292ef9c3318133666fa9144c65e..e8213212004e3ab8918a3c5f990bdc4d34a3d07e 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.112.2.14 2008-12-21 19:29:49 guy Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.112.2.15 2008-12-23 18:04:29 guy Exp $ (LBL)";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -624,6 +624,7 @@ static struct dlt_choice dlt_choices[] = {
        DLT_CHOICE(DLT_AX25_KISS, "AX.25 with KISS header"),
        DLT_CHOICE(DLT_IEEE802_15_4_NONASK_PHY, "IEEE 802.15.4 with non-ASK PHY data"),
        DLT_CHOICE(DLT_MPLS, "MPLS with label as link-layer header"),
+       DLT_CHOICE(DLT_USB_LINUX_MMAP, "USB with padded Linux header"),
        DLT_CHOICE_SENTINEL
 };
 
index d14e86d2f0307378881f18b7570b2b92a6d6cba1..f744fc96c8a04c8f3d30c07e81edc37722c12c32 100644 (file)
@@ -37,7 +37,7 @@
  *
  *      @(#)bpf.h       7.1 (Berkeley) 5/7/91
  *
- * @(#) $Header: /tcpdump/master/libpcap/pcap/bpf.h,v 1.19.2.11 2008-12-21 19:29:49 guy Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/libpcap/pcap/bpf.h,v 1.19.2.12 2008-12-23 18:04:29 guy Exp $ (LBL)
  */
 
 /*
@@ -844,6 +844,12 @@ struct bpf_version {
  */
 #define DLT_MPLS               219
 
+/*
+ * USB packets, beginning with a Linux USB header, with the USB header
+ * padded to 64 bytes; required for memory-mapped access.
+ */
+#define DLT_USB_LINUX_MMAP     220
+
 
 /*
  * DLT and savefile link type values are split into a class and
diff --git a/pcap/usb.h b/pcap/usb.h
new file mode 100644 (file)
index 0000000..c95ed16
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2006 Paolo Abeni (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote 
+ * products derived from this software without specific prior written 
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Basic USB data struct
+ * By Paolo Abeni <[email protected]>
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap/usb.h,v 1.6.2.1 2008-12-23 18:04:29 guy Exp $
+ */
+#ifndef _PCAP_USB_STRUCTS_H__
+#define _PCAP_USB_STRUCTS_H__
+
+/* 
+ * possible transfer mode
+ */
+#define URB_TRANSFER_IN   0x80
+#define URB_ISOCHRONOUS   0x0
+#define URB_INTERRUPT     0x1
+#define URB_CONTROL       0x2
+#define URB_BULK          0x3
+
+/*
+ * possible event type
+ */
+#define URB_SUBMIT        'S'
+#define URB_COMPLETE      'C'
+#define URB_ERROR         'E'
+
+/*
+ * USB setup header as defined in USB specification.
+ * Appears at the front of each packet in DLT_USB captures.
+ */
+typedef struct _usb_setup {
+       u_int8_t bmRequestType;
+       u_int8_t bRequest;
+       u_int16_t wValue;
+       u_int16_t wIndex;
+       u_int16_t wLength;
+} pcap_usb_setup;
+
+
+/*
+ * Header prepended by linux kernel to each event.
+ * Appears at the front of each packet in DLT_USB_LINUX captures.
+ * Appears at the front of each packet, followed by padding to a multiple
+ * of 64 bytes, in DLT_USB_LINUX_MMAP captures.
+ */
+typedef struct _usb_header {
+       u_int64_t id;
+       u_int8_t event_type;
+       u_int8_t transfer_type;
+       u_int8_t endpoint_number;
+       u_int8_t device_address;
+       u_int16_t bus_id;
+       char setup_flag;/*if !=0 the urb setup header is not present*/
+       char data_flag; /*if !=0 no urb data is present*/
+       int64_t ts_sec;
+       int32_t ts_usec;
+       int32_t status;
+       u_int32_t urb_len;
+       u_int32_t data_len; /* amount of urb data really present in this event*/
+       pcap_usb_setup setup;
+} pcap_usb_header;
+
+/*
+ * In DLT_USB_LINUX_MMAP captures, the header is padded to 64 bytes.
+ */
+#define MMAPPED_USB_HEADER_SIZE        (sizeof (pcap_usb_header) + 63) & ~63)
+
+#endif
index e9eceaf3b7080a5eec4432702b13af1c6bc093b4..a4a7b7928d3337a2c1993608ed9a425f7f234720 100644 (file)
@@ -30,7 +30,7 @@
 
 #ifndef lint
 static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/libpcap/savefile.c,v 1.168.2.13 2008-12-21 19:29:49 guy Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/libpcap/savefile.c,v 1.168.2.14 2008-12-23 18:04:29 guy Exp $ (LBL)";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -483,7 +483,7 @@ static const char rcsid[] _U_ =
  * USB packets, beginning with a Linux USB header; requested by
  * Paolo Abeni <[email protected]>.
  */
-#define LINKTYPE_USB_LINUX     189
+#define LINKTYPE_USB_LINUX             189
 
 /*
  * Controller Area Network (CAN) v. 2.0B packets.
@@ -670,6 +670,12 @@ static const char rcsid[] _U_ =
  */
 #define LINKTYPE_MPLS                          219
 
+/*
+ * USB packets, beginning with a Linux USB header, with the USB header
+ * padded to 64 bytes; required for memory-mapped access.
+ */
+#define LINKTYPE_USB_LINUX_MMAP                        220
+
 
 static struct linktype_map {
        int     dlt;
@@ -985,6 +991,9 @@ static struct linktype_map {
        /* MPLS, with an MPLS label as the link-layer header */
        { DLT_MPLS,             LINKTYPE_MPLS },
 
+       /* USB with padded Linux header */
+       { DLT_USB_LINUX_MMAP,   LINKTYPE_USB_LINUX_MMAP },
+
        { -1,                   -1 }
 };
 
@@ -1555,19 +1564,20 @@ sf_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char *buf, u_int buflen)
        }
 
        /*
-        * The DLT_USB_LINUX header is in host byte order when capturing
-        * (it's supplied directly from a memory-mapped buffer shared
-        * by the kernel).
+        * The DLT_USB_LINUX and DLT_USB_LINUX_MMAP headers are in host
+        * byte order when capturing (it's supplied directly from a
+        * memory-mapped buffer shared by the kernel).
         *
-        * When reading a DLT_USB_LINUX capture file, we need to convert
-        * it from the capturing host's byte order to the reading host's
-        * byte order.
+        * When reading a DLT_USB_LINUX or DLT_USB_LINUX_MMAP capture file,
+        * we need to convert it from the capturing host's byte order to
+        * the reading host's byte order.
         */
-       if (p->sf.swapped && p->linktype == DLT_USB_LINUX) {
+       if (p->sf.swapped &&
+           (p->linktype == DLT_USB_LINUX || p->linktype == DLT_USB_LINUX_MMAP)) {
                pcap_usb_header* uhdr = (pcap_usb_header*) buf;
                /*
                 * The URB id is a totally opaque value; do we really need to 
-                * converte it to the reading host's byte order???
+                * convert it to the reading host's byte order???
                 */
                if (hdr->caplen < 8)
                        return 0;