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