/src/libpcap/pcap-usb-linux-common.c
Line | Count | Source (jump to first uncovered line) |
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.c - common code for everything that needs to |
22 | | * deal with Linux USB captures. |
23 | | */ |
24 | | |
25 | | #include "pcap/pcap.h" |
26 | | #include "pcap/usb.h" |
27 | | |
28 | | #include "pcap-usb-linux-common.h" |
29 | | |
30 | | /* |
31 | | * Compute, from the data provided by the Linux USB memory-mapped capture |
32 | | * mechanism, the amount of packet data that would have been provided |
33 | | * had the capture mechanism not chopped off any data at the end, if, in |
34 | | * fact, it did so. |
35 | | * |
36 | | * Set the "unsliced length" field of the packet header to that value. |
37 | | */ |
38 | | void |
39 | | fix_linux_usb_mmapped_length(struct pcap_pkthdr *pkth, const u_char *bp) |
40 | 390 | { |
41 | 390 | const pcap_usb_header_mmapped *hdr; |
42 | 390 | u_int bytes_left; |
43 | | |
44 | | /* |
45 | | * All callers of this routine must ensure that pkth->caplen is |
46 | | * >= sizeof (pcap_usb_header_mmapped). |
47 | | */ |
48 | 390 | bytes_left = pkth->caplen; |
49 | 390 | bytes_left -= sizeof (pcap_usb_header_mmapped); |
50 | | |
51 | 390 | hdr = (const pcap_usb_header_mmapped *) bp; |
52 | 390 | if (!hdr->data_flag && hdr->transfer_type == URB_ISOCHRONOUS && |
53 | 390 | hdr->event_type == URB_COMPLETE && |
54 | 390 | (hdr->endpoint_number & URB_TRANSFER_IN) && |
55 | 390 | pkth->len == sizeof(pcap_usb_header_mmapped) + |
56 | 14 | (hdr->ndesc * sizeof (usb_isodesc)) + hdr->urb_len) { |
57 | 14 | usb_isodesc *descs; |
58 | 14 | u_int pre_truncation_data_len, pre_truncation_len; |
59 | | |
60 | 14 | descs = (usb_isodesc *) (bp + sizeof(pcap_usb_header_mmapped)); |
61 | | |
62 | | /* |
63 | | * We have data (yes, data_flag is 0 if we *do* have data), |
64 | | * and this is a "this is complete" incoming isochronous |
65 | | * transfer event, and the length was calculated based |
66 | | * on the URB length. |
67 | | * |
68 | | * That's not correct, because the data isn't contiguous, |
69 | | * and the isochronous descriptos show how it's scattered. |
70 | | * |
71 | | * Find the end of the last chunk of data in the buffer |
72 | | * referred to by the isochronous descriptors; that indicates |
73 | | * how far into the buffer the data would have gone. |
74 | | * |
75 | | * Make sure we don't run past the end of the captured data |
76 | | * while processing the isochronous descriptors. |
77 | | */ |
78 | 14 | pre_truncation_data_len = 0; |
79 | 14 | for (uint32_t desc = 0; |
80 | 14 | desc < hdr->ndesc && bytes_left >= sizeof (usb_isodesc); |
81 | 14 | desc++, bytes_left -= sizeof (usb_isodesc)) { |
82 | 0 | u_int desc_end; |
83 | |
|
84 | 0 | if (descs[desc].len != 0) { |
85 | 0 | desc_end = descs[desc].offset + descs[desc].len; |
86 | 0 | if (desc_end > pre_truncation_data_len) |
87 | 0 | pre_truncation_data_len = desc_end; |
88 | 0 | } |
89 | 0 | } |
90 | | |
91 | | /* |
92 | | * Now calculate the total length based on that data |
93 | | * length. |
94 | | */ |
95 | 14 | pre_truncation_len = sizeof(pcap_usb_header_mmapped) + |
96 | 14 | (hdr->ndesc * sizeof (usb_isodesc)) + |
97 | 14 | pre_truncation_data_len; |
98 | | |
99 | | /* |
100 | | * If that's greater than or equal to the captured length, |
101 | | * use that as the length. |
102 | | */ |
103 | 14 | if (pre_truncation_len >= pkth->caplen) |
104 | 1 | pkth->len = pre_truncation_len; |
105 | | |
106 | | /* |
107 | | * If the captured length is greater than the length, |
108 | | * use the captured length. |
109 | | * |
110 | | * For completion events for incoming isochronous transfers, |
111 | | * it's based on data_len, which is calculated the same way |
112 | | * we calculated pre_truncation_data_len above, except that |
113 | | * it has access to all the isochronous descriptors, not |
114 | | * just the ones that the kernel were able to provide us or, |
115 | | * for a capture file, that weren't sliced off by a snapshot |
116 | | * length. |
117 | | * |
118 | | * However, it might have been reduced by the USB capture |
119 | | * mechanism arbitrarily limiting the amount of data it |
120 | | * provides to userland, or by the libpcap capture code |
121 | | * limiting it to being no more than the snapshot, so |
122 | | * we don't want to just use it all the time; we only |
123 | | * do so to try to get a better estimate of the actual |
124 | | * length - and to make sure the on-the-network length |
125 | | * is always >= the captured length. |
126 | | */ |
127 | 14 | if (pkth->caplen > pkth->len) |
128 | 13 | pkth->len = pkth->caplen; |
129 | 14 | } |
130 | 390 | } |