]> The Tcpdump Group git mirrors - libpcap/commitdiff
Byte-swap the extra fields in the "version 1" USB monitor header.
authorGuy Harris <[email protected]>
Mon, 25 Jan 2010 23:12:43 +0000 (15:12 -0800)
committerGuy Harris <[email protected]>
Mon, 25 Jan 2010 23:12:43 +0000 (15:12 -0800)
pcap-common.c
pcap-common.h
pcap/usb.h
sf-pcap-ng.c
sf-pcap.c

index 61509e405928680eaad31e44560dfe28788c9a50..18c45cdcab15b9e2520170ed99c8c5565653aca5 100644 (file)
@@ -1123,9 +1123,10 @@ linktype_to_dlt(int linktype)
  * the reading host's byte order.
  */
 void
-swap_linux_usb_header(const struct pcap_pkthdr *hdr, u_char *buf)
+swap_linux_usb_header(const struct pcap_pkthdr *hdr, u_char *buf,
+    int header_len_64_bytes)
 {
-       pcap_usb_header *uhdr = (pcap_usb_header *)buf;
+       pcap_usb_header_mmapped *uhdr = (pcap_usb_header_mmapped *)buf;
 
        /*
         * The URB id is a totally opaque value; do we really need to 
@@ -1152,4 +1153,27 @@ swap_linux_usb_header(const struct pcap_pkthdr *hdr, u_char *buf)
        if (hdr->caplen < 40)
                return;
        uhdr->data_len = SWAPLONG(uhdr->data_len);
+
+       if (header_len_64_bytes) {
+               /*
+                * This is either the "version 1" header, with
+                * 16 bytes of additional fields at the end, or
+                * a "version 0" header from a memory-mapped
+                * capture, with 16 bytes of zeroed-out padding
+                * at the end.  Byte swap them as if this were
+                * a "version 1" header.
+                */
+               if (hdr->caplen < 52)
+                       return;
+               uhdr->interval = SWAPLONG(uhdr->interval);
+               if (hdr->caplen < 56)
+                       return;
+               uhdr->start_frame = SWAPLONG(uhdr->start_frame);
+               if (hdr->caplen < 60)
+                       return;
+               uhdr->xfer_flags = SWAPLONG(uhdr->xfer_flags);
+               if (hdr->caplen < 64)
+                       return;
+               uhdr->ndesc = SWAPLONG(uhdr->ndesc);
+       }       
 }
index f198e8689758114da1c589452c62e0cd120a763a..0c80ba326758f139937c86dd6bfc25862aa1892b 100644 (file)
@@ -21,4 +21,5 @@ extern int dlt_to_linktype(int dlt);
 
 extern int linktype_to_dlt(int linktype);
 
-extern void swap_linux_usb_header(const struct pcap_pkthdr *hdr, u_char *buf);
+extern void swap_linux_usb_header(const struct pcap_pkthdr *hdr, u_char *buf,
+    int header_len_64_bytes);
index d7de2bdc7cfdeb52289ed9d9e56ffbef69141d75..aa35122586cac5ff6d6118b171faeb00eb49c746 100644 (file)
@@ -54,7 +54,7 @@
 
 /*
  * USB setup header as defined in USB specification.
- * Appears at the front of each packet in DLT_USB captures.
+ * Appears at the front of each Control S-type packet in DLT_USB captures.
  */
 typedef struct _usb_setup {
        u_int8_t bmRequestType;
@@ -64,6 +64,13 @@ typedef struct _usb_setup {
        u_int16_t wLength;
 } pcap_usb_setup;
 
+/*
+ * Information from the URB for Isochronous transfers.
+ */
+typedef struct _iso_rec {
+       int32_t error_count;
+       int32_t numdesc;
+} iso_rec;
 
 /*
  * Header prepended by linux kernel to each event.
@@ -87,8 +94,11 @@ typedef struct _usb_header {
 } pcap_usb_header;
 
 /*
- * Header prepended by linux kernel to each event, plus padding in the
- * internal buffer.
+ * Header prepended by linux kernel to each event for the 2.6.31
+ * and later kernels; for the 2.6.21 through 2.6.30 kernels, the
+ * "iso_rec" information, and the fields starting with "interval"
+ * are zeroed-out padding fields.
+ *
  * Appears at the front of each packet in DLT_USB_LINUX_MMAPPED captures.
  */
 typedef struct _usb_header_mmapped {
@@ -105,8 +115,29 @@ typedef struct _usb_header_mmapped {
        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;
-       u_int8_t padding[16];
+       union {
+               pcap_usb_setup setup;
+               iso_rec iso;
+       } s;
+       int32_t interval;       /* for Interrupt and Isochronous events */
+       int32_t start_frame;    /* for Isochronous events */
+       u_int32_t xfer_flags;   /* copy of URB's transfer flags */
+       u_int32_t ndesc;        /* number of isochronous descriptors */
 } pcap_usb_header_mmapped;
 
+/*
+ * Isochronous descriptors; for isochronous transfers there might be
+ * one or more of these at the beginning of the packet data.  The
+ * number of descriptors is given by the "ndesc" field in the header;
+ * as indicated, in older kernels that don't put the descriptors at
+ * the beginning of the packet, that field is zeroed out, so that field
+ * can be trusted even in captures from older kernels.
+ */
+typedef struct _usb_isodesc {
+       int32_t         status;
+       u_int32_t       offset;
+       u_int32_t       len;
+       u_int8_t        pad[4];
+} usb_isodesc;
+
 #endif
index 54a7363a49403ae6a9ab05e4651c78b1f72d9552..3535777ceb3971436a89db4ae386893e1e2373ab 100644 (file)
@@ -1100,8 +1100,11 @@ found:
                switch (p->linktype) {
 
                case DLT_USB_LINUX:
+                       swap_linux_usb_header(hdr, *data, 0);
+                       break;
+
                case DLT_USB_LINUX_MMAPPED:
-                       swap_linux_usb_header(hdr, *data);
+                       swap_linux_usb_header(hdr, *data, 1);
                        break;
                }
        }
index bf0a0eadfea14e1cfdffbd621fff9229b89f61fe..69031608dc806853f3c4440a58c92a9d14956ecc 100644 (file)
--- a/sf-pcap.c
+++ b/sf-pcap.c
@@ -422,8 +422,11 @@ pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
                switch (p->linktype) {
 
                case DLT_USB_LINUX:
+                       swap_linux_usb_header(hdr, *data, 0);
+                       break;
+
                case DLT_USB_LINUX_MMAPPED:
-                       swap_linux_usb_header(hdr, *data);
+                       swap_linux_usb_header(hdr, *data, 1);
                        break;
                }
        }