File: pcap-usb-linux-common.h

package info (click to toggle)
libpcap 1.10.5-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 4,892 kB
  • sloc: ansic: 47,969; sh: 3,761; makefile: 1,078; lex: 690; python: 254; asm: 227
file content (127 lines) | stat: -rw-r--r-- 4,256 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
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));
}