]> The Tcpdump Group git mirrors - libpcap/blobdiff - pcap-usb-linux-common.h
CI: Call print_so_deps() on rpcapd in remote enabled build
[libpcap] / pcap-usb-linux-common.h
index 8cff7ba1cf6bc1c15e3ec20ed5204b03b1bd018a..333c6b6e0c627aef37ee527154b4c552b1b66d15 100644 (file)
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
  * pcap-usb-linux-common.h - common code for everything that needs to
- * deal with Linux USB captures.
+ * deal with Linux USB captures, whether live or in a capture file;
+ * the later means that this is *not* Linux-only.
  */
 
-extern void fix_linux_usb_mmapped_length(struct pcap_pkthdr *pkth,
-    const u_char *bp);
+#include <limits.h>
+
+/*
+ * Return the sum of the two u_int arguments if that sum fits in a u_int,
+ * and return UINT_MAX otherwise.
+ */
+static inline u_int
+u_int_sum(u_int a, u_int b)
+{
+       return (((b) <= UINT_MAX - (a)) ? (a) + (b) : UINT_MAX);
+}
+
+/*
+ * Is this a completion event for an isochronous transfer?
+ */
+static inline int
+is_isochronous_transfer_completion(const pcap_usb_header_mmapped *hdr)
+{
+       return (hdr->transfer_type == URB_ISOCHRONOUS &&
+           hdr->event_type == URB_COMPLETE &&
+           (hdr->endpoint_number & URB_TRANSFER_IN));
+}
+
+/*
+ * Total length of the pseudo-header, including the isochronous
+ * descriptors.
+ */
+static inline uint32_t
+iso_pseudo_header_len(const pcap_usb_header_mmapped *usb_hdr)
+{
+       return (sizeof(pcap_usb_header_mmapped) +
+           usb_hdr->ndesc * sizeof (usb_isodesc));
+}
+
+/*
+ * Calculate the packet length for a "this is complete" incoming
+ * isochronous transfer event.
+ *
+ * Calculating that from hdr->urb_len is not correct, because the
+ * data is not contiguous, and the isochroous descriptors show how
+ * it's scattered.
+ */
+static inline u_int
+incoming_isochronous_transfer_completed_len(struct pcap_pkthdr *phdr,
+    const u_char *bp)
+{
+       const pcap_usb_header_mmapped *hdr;
+       u_int bytes_left;
+       const usb_isodesc *descs;
+       u_int pre_truncation_data_len;
+
+       /*
+        * All callers of this routine must ensure that pkth->caplen is
+        * >= sizeof (pcap_usb_header_mmapped).
+        */
+       bytes_left = phdr->caplen;
+       bytes_left -= sizeof (pcap_usb_header_mmapped);
+
+       hdr = (const pcap_usb_header_mmapped *) bp;
+       descs = (const usb_isodesc *) (bp + sizeof(pcap_usb_header_mmapped));
+
+       /*
+        * Find the end of the last chunk of data in the buffer
+        * referred to by the isochronous descriptors; that indicates
+        * how far into the buffer the data would have gone.
+        *
+        * Make sure we don't run past the end of the captured data
+        * while processing the isochronous descriptors.
+        */
+       pre_truncation_data_len = 0;
+       for (uint32_t desc = 0;
+           desc < hdr->ndesc && bytes_left >= sizeof (usb_isodesc);
+           desc++, bytes_left -= sizeof (usb_isodesc)) {
+               u_int desc_end;
+
+               if (descs[desc].len != 0) {
+                       /*
+                        * Compute the end offset of the data
+                        * for this descriptor, i.e. the offset
+                        * of the byte after the data.  Clamp
+                        * the sum at UINT_MAX, so that it fits
+                        * in a u_int.
+                        */
+                       desc_end = u_int_sum(descs[desc].offset,
+                           descs[desc].len);
+                       if (desc_end > pre_truncation_data_len)
+                               pre_truncation_data_len = desc_end;
+               }
+       }
+
+       /*
+        * Return the sum of the total header length (memory-mapped
+        * header and ISO descriptors) and the data length, clamped
+        * to UINT_MAX.
+        *
+        * We've made sure that the number of descriptors is
+        * <= USB_MAXDESC, so we know that the total size,
+        * in bytes, of the descriptors fits in a 32-bit
+        * integer.
+        */
+       return (u_int_sum(iso_pseudo_header_len(hdr), pre_truncation_data_len));
+}