summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2015-01-27 16:00:33 -0800
committerGuy Harris <guy@alum.mit.edu>2015-01-27 16:04:01 -0800
commit3b3c4069c56f44ad9b603ceb8bee412d69a6cd9e (patch)
tree611e6161b7555b5ff0df36a335e590f7e7dd9804
parentc6ea8334a341271345b8ca6d0e4c7fd5d3e87418 (diff)
downloadlibpcap-3b3c4069c56f44ad9b603ceb8bee412d69a6cd9e.tar.gz
Fix the swapping of isochronous descriptors.
From looking at the Linux USB monitoring code: With the old header, there are no isochronous descriptors after the header. With the new header, the actual number of descriptors in the header is not s.iso.numdesc, it's ndesc - only the first N descriptors, for some value of N, are put into the header, and ndesc is set to the actual number copied. In addition, if s.iso.numdesc is negative, no descriptors are captured, and ndesc is set to 0.
-rw-r--r--pcap-common.c63
1 files changed, 37 insertions, 26 deletions
diff --git a/pcap-common.c b/pcap-common.c
index 974152f2..282cbfc1 100644
--- a/pcap-common.c
+++ b/pcap-common.c
@@ -1009,8 +1009,6 @@ swap_linux_usb_header(const struct pcap_pkthdr *hdr, u_char *buf,
{
pcap_usb_header_mmapped *uhdr = (pcap_usb_header_mmapped *)buf;
bpf_u_int32 offset = 0;
- usb_isodesc *pisodesc;
- int32_t numdesc, i;
/*
* "offset" is the offset *past* the field we're swapping;
@@ -1074,6 +1072,17 @@ swap_linux_usb_header(const struct pcap_pkthdr *hdr, u_char *buf,
} else
offset += 8; /* skip USB setup header */
+ /*
+ * With the old header, there are no isochronous descriptors
+ * after the header.
+ *
+ * With the new header, the actual number of descriptors in
+ * the header is not s.iso.numdesc, it's ndesc - only the
+ * first N descriptors, for some value of N, are put into
+ * the header, and ndesc is set to the actual number copied.
+ * In addition, if s.iso.numdesc is negative, no descriptors
+ * are captured, and ndesc is set to 0.
+ */
if (header_len_64_bytes) {
/*
* This is either the "version 1" header, with
@@ -1102,31 +1111,33 @@ swap_linux_usb_header(const struct pcap_pkthdr *hdr, u_char *buf,
if (hdr->caplen < offset)
return;
uhdr->ndesc = SWAPLONG(uhdr->ndesc);
- }
- if (uhdr->transfer_type == URB_ISOCHRONOUS) {
- /* swap the values in struct linux_usb_isodesc */
- pisodesc = (usb_isodesc *)(void *)(buf+offset);
- numdesc = uhdr->s.iso.numdesc;
- for (i = 0; i < numdesc; i++) {
- offset += 4; /* skip past status */
- if (hdr->caplen < offset)
- return;
- pisodesc->status = SWAPLONG(pisodesc->status);
-
- offset += 4; /* skip past offset */
- if (hdr->caplen < offset)
- return;
- pisodesc->offset = SWAPLONG(pisodesc->offset);
-
- offset += 4; /* skip past len */
- if (hdr->caplen < offset)
- return;
- pisodesc->len = SWAPLONG(pisodesc->len);
-
- offset += 4; /* skip past padding */
-
- pisodesc++;
+ if (uhdr->transfer_type == URB_ISOCHRONOUS) {
+ /* swap the values in struct linux_usb_isodesc */
+ usb_isodesc *pisodesc;
+ u_int32_t i;
+
+ pisodesc = (usb_isodesc *)(void *)(buf+offset);
+ for (i = 0; i < uhdr->ndesc; i++) {
+ offset += 4; /* skip past status */
+ if (hdr->caplen < offset)
+ return;
+ pisodesc->status = SWAPLONG(pisodesc->status);
+
+ offset += 4; /* skip past offset */
+ if (hdr->caplen < offset)
+ return;
+ pisodesc->offset = SWAPLONG(pisodesc->offset);
+
+ offset += 4; /* skip past len */
+ if (hdr->caplen < offset)
+ return;
+ pisodesc->len = SWAPLONG(pisodesc->len);
+
+ offset += 4; /* skip past padding */
+
+ pisodesc++;
+ }
}
}
}