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