aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2010-01-25 15:12:43 -0800
committerGuy Harris <guy@alum.mit.edu>2010-01-25 15:12:43 -0800
commitecd955e0df1a2471542119c947c351dcd94cb234 (patch)
tree0133d351414e1566853c08cbe0d91dea07628fa0
parentf9c2f9a85200eff7c920dc95fd446aa0236edf5e (diff)
Byte-swap the extra fields in the "version 1" USB monitor header.
-rw-r--r--pcap-common.c28
-rw-r--r--pcap-common.h3
-rw-r--r--pcap/usb.h41
-rw-r--r--sf-pcap-ng.c5
-rw-r--r--sf-pcap.c5
5 files changed, 72 insertions, 10 deletions
diff --git a/pcap-common.c b/pcap-common.c
index 61509e4..18c45cd 100644
--- a/pcap-common.c
+++ b/pcap-common.c
@@ -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);
+ }
}
diff --git a/pcap-common.h b/pcap-common.h
index f198e86..0c80ba3 100644
--- a/pcap-common.h
+++ b/pcap-common.h
@@ -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);
diff --git a/pcap/usb.h b/pcap/usb.h
index d7de2bd..aa35122 100644
--- a/pcap/usb.h
+++ b/pcap/usb.h
@@ -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
diff --git a/sf-pcap-ng.c b/sf-pcap-ng.c
index 54a7363..3535777 100644
--- a/sf-pcap-ng.c
+++ b/sf-pcap-ng.c
@@ -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;
}
}
diff --git a/sf-pcap.c b/sf-pcap.c
index bf0a0ea..6903160 100644
--- 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;
}
}