diff options
Diffstat (limited to 'contrib/libpcap/pcap-usb-linux-common.h')
| -rw-r--r-- | contrib/libpcap/pcap-usb-linux-common.h | 127 | 
1 files changed, 127 insertions, 0 deletions
diff --git a/contrib/libpcap/pcap-usb-linux-common.h b/contrib/libpcap/pcap-usb-linux-common.h new file mode 100644 index 000000000000..333c6b6e0c62 --- /dev/null +++ b/contrib/libpcap/pcap-usb-linux-common.h @@ -0,0 +1,127 @@ +/* + * 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.h - common code for everything that needs to + * deal with Linux USB captures, whether live or in a capture file; + * the later means that this is *not* Linux-only. + */ + +#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)); +}  | 
