xref: /freebsd/contrib/libpcap/pcap-usb-linux-common.h (revision afdbf109c6a661a729938f68211054a0a50d38ac)
16f9cba8fSJoseph Mingrone /*
26f9cba8fSJoseph Mingrone  * Copyright (c) 1993, 1994, 1995, 1996, 1997
36f9cba8fSJoseph Mingrone  *	The Regents of the University of California.  All rights reserved.
46f9cba8fSJoseph Mingrone  *
56f9cba8fSJoseph Mingrone  * Redistribution and use in source and binary forms, with or without
66f9cba8fSJoseph Mingrone  * modification, are permitted provided that: (1) source code distributions
76f9cba8fSJoseph Mingrone  * retain the above copyright notice and this paragraph in its entirety, (2)
86f9cba8fSJoseph Mingrone  * distributions including binary code include the above copyright notice and
96f9cba8fSJoseph Mingrone  * this paragraph in its entirety in the documentation or other materials
106f9cba8fSJoseph Mingrone  * provided with the distribution, and (3) all advertising materials mentioning
116f9cba8fSJoseph Mingrone  * features or use of this software display the following acknowledgement:
126f9cba8fSJoseph Mingrone  * ``This product includes software developed by the University of California,
136f9cba8fSJoseph Mingrone  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
146f9cba8fSJoseph Mingrone  * the University nor the names of its contributors may be used to endorse
156f9cba8fSJoseph Mingrone  * or promote products derived from this software without specific prior
166f9cba8fSJoseph Mingrone  * written permission.
176f9cba8fSJoseph Mingrone  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
186f9cba8fSJoseph Mingrone  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
196f9cba8fSJoseph Mingrone  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
206f9cba8fSJoseph Mingrone  *
216f9cba8fSJoseph Mingrone  * pcap-usb-linux-common.h - common code for everything that needs to
22*afdbf109SJoseph Mingrone  * deal with Linux USB captures, whether live or in a capture file;
23*afdbf109SJoseph Mingrone  * the later means that this is *not* Linux-only.
246f9cba8fSJoseph Mingrone  */
256f9cba8fSJoseph Mingrone 
26*afdbf109SJoseph Mingrone #include <limits.h>
27*afdbf109SJoseph Mingrone 
28*afdbf109SJoseph Mingrone /*
29*afdbf109SJoseph Mingrone  * Return the sum of the two u_int arguments if that sum fits in a u_int,
30*afdbf109SJoseph Mingrone  * and return UINT_MAX otherwise.
31*afdbf109SJoseph Mingrone  */
32*afdbf109SJoseph Mingrone static inline u_int
u_int_sum(u_int a,u_int b)33*afdbf109SJoseph Mingrone u_int_sum(u_int a, u_int b)
34*afdbf109SJoseph Mingrone {
35*afdbf109SJoseph Mingrone 	return (((b) <= UINT_MAX - (a)) ? (a) + (b) : UINT_MAX);
36*afdbf109SJoseph Mingrone }
37*afdbf109SJoseph Mingrone 
38*afdbf109SJoseph Mingrone /*
39*afdbf109SJoseph Mingrone  * Is this a completion event for an isochronous transfer?
40*afdbf109SJoseph Mingrone  */
41*afdbf109SJoseph Mingrone static inline int
is_isochronous_transfer_completion(const pcap_usb_header_mmapped * hdr)42*afdbf109SJoseph Mingrone is_isochronous_transfer_completion(const pcap_usb_header_mmapped *hdr)
43*afdbf109SJoseph Mingrone {
44*afdbf109SJoseph Mingrone 	return (hdr->transfer_type == URB_ISOCHRONOUS &&
45*afdbf109SJoseph Mingrone 	    hdr->event_type == URB_COMPLETE &&
46*afdbf109SJoseph Mingrone 	    (hdr->endpoint_number & URB_TRANSFER_IN));
47*afdbf109SJoseph Mingrone }
48*afdbf109SJoseph Mingrone 
49*afdbf109SJoseph Mingrone /*
50*afdbf109SJoseph Mingrone  * Total length of the pseudo-header, including the isochronous
51*afdbf109SJoseph Mingrone  * descriptors.
52*afdbf109SJoseph Mingrone  */
53*afdbf109SJoseph Mingrone static inline uint32_t
iso_pseudo_header_len(const pcap_usb_header_mmapped * usb_hdr)54*afdbf109SJoseph Mingrone iso_pseudo_header_len(const pcap_usb_header_mmapped *usb_hdr)
55*afdbf109SJoseph Mingrone {
56*afdbf109SJoseph Mingrone 	return (sizeof(pcap_usb_header_mmapped) +
57*afdbf109SJoseph Mingrone 	    usb_hdr->ndesc * sizeof (usb_isodesc));
58*afdbf109SJoseph Mingrone }
59*afdbf109SJoseph Mingrone 
60*afdbf109SJoseph Mingrone /*
61*afdbf109SJoseph Mingrone  * Calculate the packet length for a "this is complete" incoming
62*afdbf109SJoseph Mingrone  * isochronous transfer event.
63*afdbf109SJoseph Mingrone  *
64*afdbf109SJoseph Mingrone  * Calculating that from hdr->urb_len is not correct, because the
65*afdbf109SJoseph Mingrone  * data is not contiguous, and the isochroous descriptors show how
66*afdbf109SJoseph Mingrone  * it's scattered.
67*afdbf109SJoseph Mingrone  */
68*afdbf109SJoseph Mingrone static inline u_int
incoming_isochronous_transfer_completed_len(struct pcap_pkthdr * phdr,const u_char * bp)69*afdbf109SJoseph Mingrone incoming_isochronous_transfer_completed_len(struct pcap_pkthdr *phdr,
70*afdbf109SJoseph Mingrone     const u_char *bp)
71*afdbf109SJoseph Mingrone {
72*afdbf109SJoseph Mingrone 	const pcap_usb_header_mmapped *hdr;
73*afdbf109SJoseph Mingrone 	u_int bytes_left;
74*afdbf109SJoseph Mingrone 	const usb_isodesc *descs;
75*afdbf109SJoseph Mingrone 	u_int pre_truncation_data_len;
76*afdbf109SJoseph Mingrone 
77*afdbf109SJoseph Mingrone 	/*
78*afdbf109SJoseph Mingrone 	 * All callers of this routine must ensure that pkth->caplen is
79*afdbf109SJoseph Mingrone 	 * >= sizeof (pcap_usb_header_mmapped).
80*afdbf109SJoseph Mingrone 	 */
81*afdbf109SJoseph Mingrone 	bytes_left = phdr->caplen;
82*afdbf109SJoseph Mingrone 	bytes_left -= sizeof (pcap_usb_header_mmapped);
83*afdbf109SJoseph Mingrone 
84*afdbf109SJoseph Mingrone 	hdr = (const pcap_usb_header_mmapped *) bp;
85*afdbf109SJoseph Mingrone 	descs = (const usb_isodesc *) (bp + sizeof(pcap_usb_header_mmapped));
86*afdbf109SJoseph Mingrone 
87*afdbf109SJoseph Mingrone 	/*
88*afdbf109SJoseph Mingrone 	 * Find the end of the last chunk of data in the buffer
89*afdbf109SJoseph Mingrone 	 * referred to by the isochronous descriptors; that indicates
90*afdbf109SJoseph Mingrone 	 * how far into the buffer the data would have gone.
91*afdbf109SJoseph Mingrone 	 *
92*afdbf109SJoseph Mingrone 	 * Make sure we don't run past the end of the captured data
93*afdbf109SJoseph Mingrone 	 * while processing the isochronous descriptors.
94*afdbf109SJoseph Mingrone 	 */
95*afdbf109SJoseph Mingrone 	pre_truncation_data_len = 0;
96*afdbf109SJoseph Mingrone 	for (uint32_t desc = 0;
97*afdbf109SJoseph Mingrone 	    desc < hdr->ndesc && bytes_left >= sizeof (usb_isodesc);
98*afdbf109SJoseph Mingrone 	    desc++, bytes_left -= sizeof (usb_isodesc)) {
99*afdbf109SJoseph Mingrone 		u_int desc_end;
100*afdbf109SJoseph Mingrone 
101*afdbf109SJoseph Mingrone 		if (descs[desc].len != 0) {
102*afdbf109SJoseph Mingrone 			/*
103*afdbf109SJoseph Mingrone 			 * Compute the end offset of the data
104*afdbf109SJoseph Mingrone 			 * for this descriptor, i.e. the offset
105*afdbf109SJoseph Mingrone 			 * of the byte after the data.  Clamp
106*afdbf109SJoseph Mingrone 			 * the sum at UINT_MAX, so that it fits
107*afdbf109SJoseph Mingrone 			 * in a u_int.
108*afdbf109SJoseph Mingrone 			 */
109*afdbf109SJoseph Mingrone 			desc_end = u_int_sum(descs[desc].offset,
110*afdbf109SJoseph Mingrone 			    descs[desc].len);
111*afdbf109SJoseph Mingrone 			if (desc_end > pre_truncation_data_len)
112*afdbf109SJoseph Mingrone 				pre_truncation_data_len = desc_end;
113*afdbf109SJoseph Mingrone 		}
114*afdbf109SJoseph Mingrone 	}
115*afdbf109SJoseph Mingrone 
116*afdbf109SJoseph Mingrone 	/*
117*afdbf109SJoseph Mingrone 	 * Return the sum of the total header length (memory-mapped
118*afdbf109SJoseph Mingrone 	 * header and ISO descriptors) and the data length, clamped
119*afdbf109SJoseph Mingrone 	 * to UINT_MAX.
120*afdbf109SJoseph Mingrone 	 *
121*afdbf109SJoseph Mingrone 	 * We've made sure that the number of descriptors is
122*afdbf109SJoseph Mingrone 	 * <= USB_MAXDESC, so we know that the total size,
123*afdbf109SJoseph Mingrone 	 * in bytes, of the descriptors fits in a 32-bit
124*afdbf109SJoseph Mingrone 	 * integer.
125*afdbf109SJoseph Mingrone 	 */
126*afdbf109SJoseph Mingrone 	return (u_int_sum(iso_pseudo_header_len(hdr), pre_truncation_data_len));
127*afdbf109SJoseph Mingrone }
128