/* * Copyright (c) 1993, 1994, 1995, 1996, 1997 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * pcap-usb-linux-common.c - common code for everything that needs to * deal with Linux USB captures. */ #include "pcap/pcap.h" #include "pcap/usb.h" #include "pcap-usb-linux-common.h" /* * Compute, from the data provided by the Linux USB memory-mapped capture * mechanism, the amount of packet data that would have been provided * had the capture mechanism not chopped off any data at the end, if, in * fact, it did so. * * Set the "unsliced length" field of the packet header to that value. */ void set_linux_usb_mmapped_length(struct pcap_pkthdr *pkth, const u_char *bp) { const pcap_usb_header_mmapped *hdr; u_int bytes_left; bytes_left = pkth->caplen; if (bytes_left < sizeof (pcap_usb_header_mmapped)) { /* * We don't have the full metadata header, so give up. */ return; } bytes_left -= sizeof (pcap_usb_header_mmapped); hdr = (const pcap_usb_header_mmapped *) bp; if (hdr->data_flag) { /* * No data; just base the on-the-bus length on hdr->data_len * (so that it's >= the captured length). */ pkth->len = sizeof(pcap_usb_header_mmapped) + hdr->data_len; } else { /* * We got data; calculate the on-the-bus length based on * the data length prior to the USB monitor device discarding * data due to its buffer being too small. */ usb_isodesc *descs; u_int pre_truncation_data_len; descs = (usb_isodesc *) (bp + sizeof(pcap_usb_header_mmapped)); /* * For most transfers, urb_len is that amount. */ pre_truncation_data_len = hdr->urb_len; if (hdr->transfer_type == URB_ISOCHRONOUS && hdr->event_type == URB_COMPLETE && (hdr->endpoint_number & URB_TRANSFER_IN)) { /* * For "this is complete" incoming isochronous * transfer events, however, the data isn't * contiguous, and the isochronous descriptos * show how it's scattered. * * 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; desc_end = descs[desc].offset + descs[desc].len; if (desc_end > pre_truncation_data_len) pre_truncation_data_len = desc_end; } } pkth->len = sizeof(pcap_usb_header_mmapped) + (hdr->ndesc * sizeof (usb_isodesc)) + pre_truncation_data_len; } }