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 */ 38void 39fix_linux_usb_mmapped_length(struct pcap_pkthdr *pkth, const u_char *bp) 40{ 41 const pcap_usb_header_mmapped *hdr; 42 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 bytes_left = pkth->caplen; 49 bytes_left -= sizeof (pcap_usb_header_mmapped); 50 51 hdr = (const pcap_usb_header_mmapped *) bp; 52 if (!hdr->data_flag && hdr->transfer_type == URB_ISOCHRONOUS && 53 hdr->event_type == URB_COMPLETE && 54 (hdr->endpoint_number & URB_TRANSFER_IN) && 55 pkth->len == sizeof(pcap_usb_header_mmapped) + 56 (hdr->ndesc * sizeof (usb_isodesc)) + hdr->urb_len) { 57 usb_isodesc *descs; 58 u_int pre_truncation_data_len, pre_truncation_len; 59 60 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 pre_truncation_data_len = 0; 79 for (uint32_t desc = 0; 80 desc < hdr->ndesc && bytes_left >= sizeof (usb_isodesc); 81 desc++, bytes_left -= sizeof (usb_isodesc)) { 82 u_int desc_end; 83 84 if (descs[desc].len != 0) { 85 desc_end = descs[desc].offset + descs[desc].len; 86 if (desc_end > pre_truncation_data_len) 87 pre_truncation_data_len = desc_end; 88 } 89 } 90 91 /* 92 * Now calculate the total length based on that data 93 * length. 94 */ 95 pre_truncation_len = sizeof(pcap_usb_header_mmapped) + 96 (hdr->ndesc * sizeof (usb_isodesc)) + 97 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 if (pre_truncation_len >= pkth->caplen) 104 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 if (pkth->caplen > pkth->len) 128 pkth->len = pkth->caplen; 129 } 130} 131