1190214Srpaulo/* 2190214Srpaulo * Copyright (c) 2006 Paolo Abeni (Italy) 3190214Srpaulo * All rights reserved. 4190214Srpaulo * 5190214Srpaulo * Redistribution and use in source and binary forms, with or without 6190214Srpaulo * modification, are permitted provided that the following conditions 7190214Srpaulo * are met: 8190214Srpaulo * 9190214Srpaulo * 1. Redistributions of source code must retain the above copyright 10190214Srpaulo * notice, this list of conditions and the following disclaimer. 11190214Srpaulo * 2. Redistributions in binary form must reproduce the above copyright 12190214Srpaulo * notice, this list of conditions and the following disclaimer in the 13190214Srpaulo * documentation and/or other materials provided with the distribution. 14190214Srpaulo * 3. The name of the author may not be used to endorse or promote 15190214Srpaulo * products derived from this software without specific prior written 16190214Srpaulo * permission. 17190214Srpaulo * 18190214Srpaulo * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19190214Srpaulo * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20190214Srpaulo * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21190214Srpaulo * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22190214Srpaulo * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23190214Srpaulo * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24190214Srpaulo * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25190214Srpaulo * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26190214Srpaulo * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27190214Srpaulo * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28190214Srpaulo * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29190214Srpaulo * 30190214Srpaulo * USB sniffing API implementation for Linux platform 31190214Srpaulo * By Paolo Abeni <paolo.abeni@email.it> 32190214Srpaulo * Modifications: Kris Katterjohn <katterjohn@gmail.com> 33190214Srpaulo * 34190214Srpaulo */ 35190214Srpaulo 36190214Srpaulo#ifdef HAVE_CONFIG_H 37190214Srpaulo#include "config.h" 38190214Srpaulo#endif 39190214Srpaulo 40190214Srpaulo#include "pcap-int.h" 41190214Srpaulo#include "pcap-usb-linux.h" 42190214Srpaulo#include "pcap/usb.h" 43190214Srpaulo 44190214Srpaulo#ifdef NEED_STRERROR_H 45190214Srpaulo#include "strerror.h" 46190214Srpaulo#endif 47190214Srpaulo 48190214Srpaulo#include <ctype.h> 49190214Srpaulo#include <errno.h> 50190214Srpaulo#include <stdlib.h> 51190214Srpaulo#include <unistd.h> 52190214Srpaulo#include <fcntl.h> 53190214Srpaulo#include <string.h> 54190214Srpaulo#include <dirent.h> 55190214Srpaulo#include <byteswap.h> 56190214Srpaulo#include <netinet/in.h> 57190214Srpaulo#include <sys/ioctl.h> 58190214Srpaulo#include <sys/mman.h> 59214518Srpaulo#ifdef HAVE_LINUX_USBDEVICE_FS_H 60235426Sdelphij/* 61235426Sdelphij * We might need <linux/compiler.h> to define __user for 62235426Sdelphij * <linux/usbdevice_fs.h>. 63235426Sdelphij */ 64235426Sdelphij#ifdef HAVE_LINUX_COMPILER_H 65235426Sdelphij#include <linux/compiler.h> 66235426Sdelphij#endif /* HAVE_LINUX_COMPILER_H */ 67214518Srpaulo#include <linux/usbdevice_fs.h> 68235426Sdelphij#endif /* HAVE_LINUX_USBDEVICE_FS_H */ 69190214Srpaulo 70214518Srpaulo#define USB_IFACE "usbmon" 71214518Srpaulo#define USB_TEXT_DIR_OLD "/sys/kernel/debug/usbmon" 72214518Srpaulo#define USB_TEXT_DIR "/sys/kernel/debug/usb/usbmon" 73214518Srpaulo#define SYS_USB_BUS_DIR "/sys/bus/usb/devices" 74214518Srpaulo#define PROC_USB_BUS_DIR "/proc/bus/usb" 75190214Srpaulo#define USB_LINE_LEN 4096 76190214Srpaulo 77190214Srpaulo#if __BYTE_ORDER == __LITTLE_ENDIAN 78190214Srpaulo#define htols(s) s 79190214Srpaulo#define htoll(l) l 80190214Srpaulo#define htol64(ll) ll 81190214Srpaulo#else 82190214Srpaulo#define htols(s) bswap_16(s) 83190214Srpaulo#define htoll(l) bswap_32(l) 84190214Srpaulo#define htol64(ll) bswap_64(ll) 85190214Srpaulo#endif 86190214Srpaulo 87190214Srpaulostruct mon_bin_stats { 88190214Srpaulo u_int32_t queued; 89190214Srpaulo u_int32_t dropped; 90190214Srpaulo}; 91190214Srpaulo 92190214Srpaulostruct mon_bin_get { 93190214Srpaulo pcap_usb_header *hdr; 94190214Srpaulo void *data; 95190214Srpaulo size_t data_len; /* Length of data (can be zero) */ 96190214Srpaulo}; 97190214Srpaulo 98190214Srpaulostruct mon_bin_mfetch { 99190214Srpaulo int32_t *offvec; /* Vector of events fetched */ 100190214Srpaulo int32_t nfetch; /* Number of events to fetch (out: fetched) */ 101190214Srpaulo int32_t nflush; /* Number of events to flush */ 102190214Srpaulo}; 103190214Srpaulo 104190214Srpaulo#define MON_IOC_MAGIC 0x92 105190214Srpaulo 106190214Srpaulo#define MON_IOCQ_URB_LEN _IO(MON_IOC_MAGIC, 1) 107190214Srpaulo#define MON_IOCX_URB _IOWR(MON_IOC_MAGIC, 2, struct mon_bin_hdr) 108190214Srpaulo#define MON_IOCG_STATS _IOR(MON_IOC_MAGIC, 3, struct mon_bin_stats) 109190214Srpaulo#define MON_IOCT_RING_SIZE _IO(MON_IOC_MAGIC, 4) 110190214Srpaulo#define MON_IOCQ_RING_SIZE _IO(MON_IOC_MAGIC, 5) 111190214Srpaulo#define MON_IOCX_GET _IOW(MON_IOC_MAGIC, 6, struct mon_bin_get) 112190214Srpaulo#define MON_IOCX_MFETCH _IOWR(MON_IOC_MAGIC, 7, struct mon_bin_mfetch) 113190214Srpaulo#define MON_IOCH_MFLUSH _IO(MON_IOC_MAGIC, 8) 114190214Srpaulo 115190214Srpaulo#define MON_BIN_SETUP 0x1 /* setup hdr is present*/ 116190214Srpaulo#define MON_BIN_SETUP_ZERO 0x2 /* setup buffer is not available */ 117190214Srpaulo#define MON_BIN_DATA_ZERO 0x4 /* data buffer is not available */ 118190214Srpaulo#define MON_BIN_ERROR 0x8 119190214Srpaulo 120276768Sdelphij/* 121276768Sdelphij * Private data for capturing on Linux USB. 122276768Sdelphij */ 123276768Sdelphijstruct pcap_usb_linux { 124276768Sdelphij u_char *mmapbuf; /* memory-mapped region pointer */ 125276768Sdelphij size_t mmapbuflen; /* size of region */ 126276768Sdelphij int bus_index; 127276768Sdelphij u_int packets_read; 128276768Sdelphij}; 129276768Sdelphij 130190214Srpaulo/* forward declaration */ 131190214Srpaulostatic int usb_activate(pcap_t *); 132190214Srpaulostatic int usb_stats_linux(pcap_t *, struct pcap_stat *); 133190214Srpaulostatic int usb_stats_linux_bin(pcap_t *, struct pcap_stat *); 134190214Srpaulostatic int usb_read_linux(pcap_t *, int , pcap_handler , u_char *); 135190214Srpaulostatic int usb_read_linux_bin(pcap_t *, int , pcap_handler , u_char *); 136190214Srpaulostatic int usb_read_linux_mmap(pcap_t *, int , pcap_handler , u_char *); 137190214Srpaulostatic int usb_inject_linux(pcap_t *, const void *, size_t); 138190214Srpaulostatic int usb_setdirection_linux(pcap_t *, pcap_direction_t); 139190214Srpaulostatic void usb_cleanup_linux_mmap(pcap_t *); 140190214Srpaulo 141190214Srpaulo/* facility to add an USB device to the device list*/ 142190214Srpaulostatic int 143190214Srpaulousb_dev_add(pcap_if_t** alldevsp, int n, char *err_str) 144190214Srpaulo{ 145190214Srpaulo char dev_name[10]; 146190214Srpaulo char dev_descr[30]; 147190214Srpaulo snprintf(dev_name, 10, USB_IFACE"%d", n); 148190214Srpaulo snprintf(dev_descr, 30, "USB bus number %d", n); 149190214Srpaulo 150190214Srpaulo if (pcap_add_if(alldevsp, dev_name, 0, 151190214Srpaulo dev_descr, err_str) < 0) 152190214Srpaulo return -1; 153190214Srpaulo return 0; 154190214Srpaulo} 155190214Srpaulo 156190214Srpauloint 157251129Sdelphijusb_findalldevs(pcap_if_t **alldevsp, char *err_str) 158190214Srpaulo{ 159190214Srpaulo struct dirent* data; 160190214Srpaulo int ret = 0; 161190214Srpaulo DIR* dir; 162214518Srpaulo int n; 163214518Srpaulo char* name; 164214518Srpaulo size_t len; 165190214Srpaulo 166214518Srpaulo /* try scanning sysfs usb bus directory */ 167214518Srpaulo dir = opendir(SYS_USB_BUS_DIR); 168214518Srpaulo if (dir != NULL) { 169214518Srpaulo while ((ret == 0) && ((data = readdir(dir)) != 0)) { 170214518Srpaulo name = data->d_name; 171190214Srpaulo 172214518Srpaulo if (strncmp(name, "usb", 3) != 0) 173214518Srpaulo continue; 174190214Srpaulo 175214518Srpaulo if (sscanf(&name[3], "%d", &n) == 0) 176214518Srpaulo continue; 177214518Srpaulo 178214518Srpaulo ret = usb_dev_add(alldevsp, n, err_str); 179214518Srpaulo } 180214518Srpaulo 181214518Srpaulo closedir(dir); 182214518Srpaulo return ret; 183190214Srpaulo } 184190214Srpaulo 185214518Srpaulo /* that didn't work; try scanning procfs usb bus directory */ 186214518Srpaulo dir = opendir(PROC_USB_BUS_DIR); 187214518Srpaulo if (dir != NULL) { 188214518Srpaulo while ((ret == 0) && ((data = readdir(dir)) != 0)) { 189214518Srpaulo name = data->d_name; 190214518Srpaulo len = strlen(name); 191214518Srpaulo 192214518Srpaulo /* if this file name does not end with a number it's not of our interest */ 193214518Srpaulo if ((len < 1) || !isdigit(name[--len])) 194214518Srpaulo continue; 195214518Srpaulo while (isdigit(name[--len])); 196214518Srpaulo if (sscanf(&name[len+1], "%d", &n) != 1) 197214518Srpaulo continue; 198214518Srpaulo 199214518Srpaulo ret = usb_dev_add(alldevsp, n, err_str); 200214518Srpaulo } 201214518Srpaulo 202214518Srpaulo closedir(dir); 203214518Srpaulo return ret; 204214518Srpaulo } 205214518Srpaulo 206214518Srpaulo /* neither of them worked */ 207214518Srpaulo return 0; 208190214Srpaulo} 209190214Srpaulo 210190214Srpaulostatic 211190214Srpauloint usb_mmap(pcap_t* handle) 212190214Srpaulo{ 213276768Sdelphij struct pcap_usb_linux *handlep = handle->priv; 214190214Srpaulo int len = ioctl(handle->fd, MON_IOCQ_RING_SIZE); 215190214Srpaulo if (len < 0) 216190214Srpaulo return 0; 217190214Srpaulo 218276768Sdelphij handlep->mmapbuflen = len; 219276768Sdelphij handlep->mmapbuf = mmap(0, handlep->mmapbuflen, PROT_READ, 220214518Srpaulo MAP_SHARED, handle->fd, 0); 221276768Sdelphij return handlep->mmapbuf != MAP_FAILED; 222190214Srpaulo} 223190214Srpaulo 224276768Sdelphij#ifdef HAVE_LINUX_USBDEVICE_FS_H 225276768Sdelphij 226214518Srpaulo#define CTRL_TIMEOUT (5*1000) /* milliseconds */ 227214518Srpaulo 228214518Srpaulo#define USB_DIR_IN 0x80 229214518Srpaulo#define USB_TYPE_STANDARD 0x00 230214518Srpaulo#define USB_RECIP_DEVICE 0x00 231214518Srpaulo 232214518Srpaulo#define USB_REQ_GET_DESCRIPTOR 6 233214518Srpaulo 234214518Srpaulo#define USB_DT_DEVICE 1 235214518Srpaulo 236214518Srpaulo/* probe the descriptors of the devices attached to the bus */ 237214518Srpaulo/* the descriptors will end up in the captured packet stream */ 238214518Srpaulo/* and be decoded by external apps like wireshark */ 239214518Srpaulo/* without these identifying probes packet data can't be fully decoded */ 240214518Srpaulostatic void 241214518Srpauloprobe_devices(int bus) 242214518Srpaulo{ 243214518Srpaulo struct usbdevfs_ctrltransfer ctrl; 244214518Srpaulo struct dirent* data; 245214518Srpaulo int ret = 0; 246214518Srpaulo char buf[40]; 247214518Srpaulo DIR* dir; 248214518Srpaulo 249214518Srpaulo /* scan usb bus directories for device nodes */ 250214518Srpaulo snprintf(buf, sizeof(buf), "/dev/bus/usb/%03d", bus); 251214518Srpaulo dir = opendir(buf); 252214518Srpaulo if (!dir) 253214518Srpaulo return; 254214518Srpaulo 255214518Srpaulo while ((ret >= 0) && ((data = readdir(dir)) != 0)) { 256214518Srpaulo int fd; 257214518Srpaulo char* name = data->d_name; 258214518Srpaulo 259214518Srpaulo if (name[0] == '.') 260214518Srpaulo continue; 261214518Srpaulo 262214518Srpaulo snprintf(buf, sizeof(buf), "/dev/bus/usb/%03d/%s", bus, data->d_name); 263214518Srpaulo 264214518Srpaulo fd = open(buf, O_RDWR); 265214518Srpaulo if (fd == -1) 266214518Srpaulo continue; 267214518Srpaulo 268214518Srpaulo /* 269214518Srpaulo * Sigh. Different kernels have different member names 270214518Srpaulo * for this structure. 271214518Srpaulo */ 272214518Srpaulo#ifdef HAVE_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE 273214518Srpaulo ctrl.bRequestType = USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE; 274214518Srpaulo ctrl.bRequest = USB_REQ_GET_DESCRIPTOR; 275214518Srpaulo ctrl.wValue = USB_DT_DEVICE << 8; 276214518Srpaulo ctrl.wIndex = 0; 277214518Srpaulo ctrl.wLength = sizeof(buf); 278214518Srpaulo#else 279214518Srpaulo ctrl.requesttype = USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE; 280214518Srpaulo ctrl.request = USB_REQ_GET_DESCRIPTOR; 281214518Srpaulo ctrl.value = USB_DT_DEVICE << 8; 282214518Srpaulo ctrl.index = 0; 283214518Srpaulo ctrl.length = sizeof(buf); 284214518Srpaulo#endif 285214518Srpaulo ctrl.data = buf; 286214518Srpaulo ctrl.timeout = CTRL_TIMEOUT; 287214518Srpaulo 288214518Srpaulo ret = ioctl(fd, USBDEVFS_CONTROL, &ctrl); 289214518Srpaulo 290214518Srpaulo close(fd); 291214518Srpaulo } 292214518Srpaulo closedir(dir); 293214518Srpaulo} 294276768Sdelphij#endif /* HAVE_LINUX_USBDEVICE_FS_H */ 295214518Srpaulo 296190214Srpaulopcap_t * 297251129Sdelphijusb_create(const char *device, char *ebuf, int *is_ours) 298190214Srpaulo{ 299251129Sdelphij const char *cp; 300251129Sdelphij char *cpend; 301251129Sdelphij long devnum; 302190214Srpaulo pcap_t *p; 303190214Srpaulo 304251129Sdelphij /* Does this look like a USB monitoring device? */ 305251129Sdelphij cp = strrchr(device, '/'); 306251129Sdelphij if (cp == NULL) 307251129Sdelphij cp = device; 308251129Sdelphij /* Does it begin with USB_IFACE? */ 309251129Sdelphij if (strncmp(cp, USB_IFACE, sizeof USB_IFACE - 1) != 0) { 310251129Sdelphij /* Nope, doesn't begin with USB_IFACE */ 311251129Sdelphij *is_ours = 0; 312251129Sdelphij return NULL; 313251129Sdelphij } 314251129Sdelphij /* Yes - is USB_IFACE followed by a number? */ 315251129Sdelphij cp += sizeof USB_IFACE - 1; 316251129Sdelphij devnum = strtol(cp, &cpend, 10); 317251129Sdelphij if (cpend == cp || *cpend != '\0') { 318251129Sdelphij /* Not followed by a number. */ 319251129Sdelphij *is_ours = 0; 320251129Sdelphij return NULL; 321251129Sdelphij } 322251129Sdelphij if (devnum < 0) { 323251129Sdelphij /* Followed by a non-valid number. */ 324251129Sdelphij *is_ours = 0; 325251129Sdelphij return NULL; 326251129Sdelphij } 327251129Sdelphij 328251129Sdelphij /* OK, it's probably ours. */ 329251129Sdelphij *is_ours = 1; 330251129Sdelphij 331276768Sdelphij p = pcap_create_common(device, ebuf, sizeof (struct pcap_usb_linux)); 332190214Srpaulo if (p == NULL) 333190214Srpaulo return (NULL); 334190214Srpaulo 335190214Srpaulo p->activate_op = usb_activate; 336190214Srpaulo return (p); 337190214Srpaulo} 338190214Srpaulo 339190214Srpaulostatic int 340190214Srpaulousb_activate(pcap_t* handle) 341190214Srpaulo{ 342276768Sdelphij struct pcap_usb_linux *handlep = handle->priv; 343190214Srpaulo char full_path[USB_LINE_LEN]; 344190214Srpaulo 345190214Srpaulo /* Initialize some components of the pcap structure. */ 346190214Srpaulo handle->bufsize = handle->snapshot; 347190214Srpaulo handle->offset = 0; 348190214Srpaulo handle->linktype = DLT_USB_LINUX; 349190214Srpaulo 350190214Srpaulo handle->inject_op = usb_inject_linux; 351235426Sdelphij handle->setfilter_op = install_bpf_program; /* no kernel filtering */ 352190214Srpaulo handle->setdirection_op = usb_setdirection_linux; 353190214Srpaulo handle->set_datalink_op = NULL; /* can't change data link type */ 354190214Srpaulo handle->getnonblock_op = pcap_getnonblock_fd; 355190214Srpaulo handle->setnonblock_op = pcap_setnonblock_fd; 356190214Srpaulo 357190214Srpaulo /*get usb bus index from device name */ 358276768Sdelphij if (sscanf(handle->opt.source, USB_IFACE"%d", &handlep->bus_index) != 1) 359190214Srpaulo { 360190214Srpaulo snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 361190214Srpaulo "Can't get USB bus index from %s", handle->opt.source); 362190214Srpaulo return PCAP_ERROR; 363190214Srpaulo } 364190214Srpaulo 365190214Srpaulo /*now select the read method: try to open binary interface */ 366276768Sdelphij snprintf(full_path, USB_LINE_LEN, LINUX_USB_MON_DEV"%d", handlep->bus_index); 367190214Srpaulo handle->fd = open(full_path, O_RDONLY, 0); 368190214Srpaulo if (handle->fd >= 0) 369190214Srpaulo { 370190214Srpaulo if (handle->opt.rfmon) { 371190214Srpaulo /* 372190214Srpaulo * Monitor mode doesn't apply to USB devices. 373190214Srpaulo */ 374214518Srpaulo close(handle->fd); 375190214Srpaulo return PCAP_ERROR_RFMON_NOTSUP; 376190214Srpaulo } 377190214Srpaulo 378190214Srpaulo /* binary api is available, try to use fast mmap access */ 379190214Srpaulo if (usb_mmap(handle)) { 380214518Srpaulo handle->linktype = DLT_USB_LINUX_MMAPPED; 381190214Srpaulo handle->stats_op = usb_stats_linux_bin; 382190214Srpaulo handle->read_op = usb_read_linux_mmap; 383190214Srpaulo handle->cleanup_op = usb_cleanup_linux_mmap; 384276768Sdelphij#ifdef HAVE_LINUX_USBDEVICE_FS_H 385276768Sdelphij probe_devices(handlep->bus_index); 386276768Sdelphij#endif 387190214Srpaulo 388190214Srpaulo /* 389190214Srpaulo * "handle->fd" is a real file, so "select()" and 390190214Srpaulo * "poll()" work on it. 391190214Srpaulo */ 392190214Srpaulo handle->selectable_fd = handle->fd; 393190214Srpaulo return 0; 394190214Srpaulo } 395190214Srpaulo 396190214Srpaulo /* can't mmap, use plain binary interface access */ 397190214Srpaulo handle->stats_op = usb_stats_linux_bin; 398190214Srpaulo handle->read_op = usb_read_linux_bin; 399276768Sdelphij#ifdef HAVE_LINUX_USBDEVICE_FS_H 400276768Sdelphij probe_devices(handlep->bus_index); 401276768Sdelphij#endif 402190214Srpaulo } 403190214Srpaulo else { 404190214Srpaulo /*Binary interface not available, try open text interface */ 405276768Sdelphij snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR"/%dt", handlep->bus_index); 406190214Srpaulo handle->fd = open(full_path, O_RDONLY, 0); 407190214Srpaulo if (handle->fd < 0) 408190214Srpaulo { 409214518Srpaulo if (errno == ENOENT) 410214518Srpaulo { 411214518Srpaulo /* 412214518Srpaulo * Not found at the new location; try 413214518Srpaulo * the old location. 414214518Srpaulo */ 415276768Sdelphij snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%dt", handlep->bus_index); 416214518Srpaulo handle->fd = open(full_path, O_RDONLY, 0); 417214518Srpaulo } 418214518Srpaulo if (handle->fd < 0) { 419214518Srpaulo /* no more fallback, give it up*/ 420214518Srpaulo snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 421214518Srpaulo "Can't open USB bus file %s: %s", full_path, strerror(errno)); 422214518Srpaulo return PCAP_ERROR; 423214518Srpaulo } 424190214Srpaulo } 425214518Srpaulo 426214518Srpaulo if (handle->opt.rfmon) { 427214518Srpaulo /* 428214518Srpaulo * Monitor mode doesn't apply to USB devices. 429214518Srpaulo */ 430214518Srpaulo close(handle->fd); 431214518Srpaulo return PCAP_ERROR_RFMON_NOTSUP; 432214518Srpaulo } 433214518Srpaulo 434190214Srpaulo handle->stats_op = usb_stats_linux; 435190214Srpaulo handle->read_op = usb_read_linux; 436190214Srpaulo } 437190214Srpaulo 438190214Srpaulo /* 439190214Srpaulo * "handle->fd" is a real file, so "select()" and "poll()" 440190214Srpaulo * work on it. 441190214Srpaulo */ 442190214Srpaulo handle->selectable_fd = handle->fd; 443190214Srpaulo 444190214Srpaulo /* for plain binary access and text access we need to allocate the read 445190214Srpaulo * buffer */ 446190214Srpaulo handle->buffer = malloc(handle->bufsize); 447190214Srpaulo if (!handle->buffer) { 448190214Srpaulo snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 449190214Srpaulo "malloc: %s", pcap_strerror(errno)); 450214518Srpaulo close(handle->fd); 451190214Srpaulo return PCAP_ERROR; 452190214Srpaulo } 453190214Srpaulo return 0; 454190214Srpaulo} 455190214Srpaulo 456190214Srpaulostatic inline int 457190214Srpauloascii_to_int(char c) 458190214Srpaulo{ 459190214Srpaulo return c < 'A' ? c- '0': ((c<'a') ? c - 'A' + 10: c-'a'+10); 460190214Srpaulo} 461190214Srpaulo 462190214Srpaulo/* 463190214Srpaulo * see <linux-kernel-source>/Documentation/usb/usbmon.txt and 464190214Srpaulo * <linux-kernel-source>/drivers/usb/mon/mon_text.c for urb string 465190214Srpaulo * format description 466190214Srpaulo */ 467190214Srpaulostatic int 468190214Srpaulousb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) 469190214Srpaulo{ 470190214Srpaulo /* see: 471190214Srpaulo * /usr/src/linux/Documentation/usb/usbmon.txt 472190214Srpaulo * for message format 473190214Srpaulo */ 474276768Sdelphij struct pcap_usb_linux *handlep = handle->priv; 475190214Srpaulo unsigned timestamp; 476190214Srpaulo int tag, cnt, ep_num, dev_addr, dummy, ret, urb_len, data_len; 477190214Srpaulo char etype, pipeid1, pipeid2, status[16], urb_tag, line[USB_LINE_LEN]; 478190214Srpaulo char *string = line; 479190214Srpaulo u_char * rawdata = handle->buffer; 480190214Srpaulo struct pcap_pkthdr pkth; 481190214Srpaulo pcap_usb_header* uhdr = (pcap_usb_header*)handle->buffer; 482190214Srpaulo u_char urb_transfer=0; 483190214Srpaulo int incoming=0; 484190214Srpaulo 485190214Srpaulo /* ignore interrupt system call errors */ 486190214Srpaulo do { 487190214Srpaulo ret = read(handle->fd, line, USB_LINE_LEN - 1); 488190214Srpaulo if (handle->break_loop) 489190214Srpaulo { 490190214Srpaulo handle->break_loop = 0; 491190214Srpaulo return -2; 492190214Srpaulo } 493190214Srpaulo } while ((ret == -1) && (errno == EINTR)); 494190214Srpaulo if (ret < 0) 495190214Srpaulo { 496190214Srpaulo if (errno == EAGAIN) 497190214Srpaulo return 0; /* no data there */ 498190214Srpaulo 499190214Srpaulo snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 500190214Srpaulo "Can't read from fd %d: %s", handle->fd, strerror(errno)); 501190214Srpaulo return -1; 502190214Srpaulo } 503190214Srpaulo 504190214Srpaulo /* read urb header; %n argument may increment return value, but it's 505190214Srpaulo * not mandatory, so does not count on it*/ 506190214Srpaulo string[ret] = 0; 507190214Srpaulo ret = sscanf(string, "%x %d %c %c%c:%d:%d %s%n", &tag, ×tamp, &etype, 508190214Srpaulo &pipeid1, &pipeid2, &dev_addr, &ep_num, status, 509190214Srpaulo &cnt); 510190214Srpaulo if (ret < 8) 511190214Srpaulo { 512190214Srpaulo snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 513190214Srpaulo "Can't parse USB bus message '%s', too few tokens (expected 8 got %d)", 514190214Srpaulo string, ret); 515190214Srpaulo return -1; 516190214Srpaulo } 517190214Srpaulo uhdr->id = tag; 518190214Srpaulo uhdr->device_address = dev_addr; 519276768Sdelphij uhdr->bus_id = handlep->bus_index; 520190214Srpaulo uhdr->status = 0; 521190214Srpaulo string += cnt; 522190214Srpaulo 523190214Srpaulo /* don't use usbmon provided timestamp, since it have low precision*/ 524190214Srpaulo if (gettimeofday(&pkth.ts, NULL) < 0) 525190214Srpaulo { 526190214Srpaulo snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 527190214Srpaulo "Can't get timestamp for message '%s' %d:%s", 528190214Srpaulo string, errno, strerror(errno)); 529190214Srpaulo return -1; 530190214Srpaulo } 531190214Srpaulo uhdr->ts_sec = pkth.ts.tv_sec; 532190214Srpaulo uhdr->ts_usec = pkth.ts.tv_usec; 533190214Srpaulo 534190214Srpaulo /* parse endpoint information */ 535190214Srpaulo if (pipeid1 == 'C') 536190214Srpaulo urb_transfer = URB_CONTROL; 537190214Srpaulo else if (pipeid1 == 'Z') 538190214Srpaulo urb_transfer = URB_ISOCHRONOUS; 539190214Srpaulo else if (pipeid1 == 'I') 540190214Srpaulo urb_transfer = URB_INTERRUPT; 541190214Srpaulo else if (pipeid1 == 'B') 542190214Srpaulo urb_transfer = URB_BULK; 543190214Srpaulo if (pipeid2 == 'i') { 544214518Srpaulo ep_num |= URB_TRANSFER_IN; 545190214Srpaulo incoming = 1; 546190214Srpaulo } 547190214Srpaulo if (etype == 'C') 548190214Srpaulo incoming = !incoming; 549190214Srpaulo 550190214Srpaulo /* direction check*/ 551190214Srpaulo if (incoming) 552190214Srpaulo { 553190214Srpaulo if (handle->direction == PCAP_D_OUT) 554190214Srpaulo return 0; 555190214Srpaulo } 556190214Srpaulo else 557190214Srpaulo if (handle->direction == PCAP_D_IN) 558190214Srpaulo return 0; 559190214Srpaulo uhdr->event_type = etype; 560190214Srpaulo uhdr->transfer_type = urb_transfer; 561214518Srpaulo uhdr->endpoint_number = ep_num; 562190214Srpaulo pkth.caplen = sizeof(pcap_usb_header); 563190214Srpaulo rawdata += sizeof(pcap_usb_header); 564190214Srpaulo 565190214Srpaulo /* check if this is a setup packet */ 566190214Srpaulo ret = sscanf(status, "%d", &dummy); 567190214Srpaulo if (ret != 1) 568190214Srpaulo { 569190214Srpaulo /* this a setup packet, setup data can be filled with underscore if 570190214Srpaulo * usbmon has not been able to read them, so we must parse this fields as 571190214Srpaulo * strings */ 572190214Srpaulo pcap_usb_setup* shdr; 573190214Srpaulo char str1[3], str2[3], str3[5], str4[5], str5[5]; 574190214Srpaulo ret = sscanf(string, "%s %s %s %s %s%n", str1, str2, str3, str4, 575190214Srpaulo str5, &cnt); 576190214Srpaulo if (ret < 5) 577190214Srpaulo { 578190214Srpaulo snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 579190214Srpaulo "Can't parse USB bus message '%s', too few tokens (expected 5 got %d)", 580190214Srpaulo string, ret); 581190214Srpaulo return -1; 582190214Srpaulo } 583190214Srpaulo string += cnt; 584190214Srpaulo 585190214Srpaulo /* try to convert to corresponding integer */ 586190214Srpaulo shdr = &uhdr->setup; 587190214Srpaulo shdr->bmRequestType = strtoul(str1, 0, 16); 588190214Srpaulo shdr->bRequest = strtoul(str2, 0, 16); 589190214Srpaulo shdr->wValue = htols(strtoul(str3, 0, 16)); 590190214Srpaulo shdr->wIndex = htols(strtoul(str4, 0, 16)); 591190214Srpaulo shdr->wLength = htols(strtoul(str5, 0, 16)); 592190214Srpaulo 593190214Srpaulo uhdr->setup_flag = 0; 594190214Srpaulo } 595190214Srpaulo else 596190214Srpaulo uhdr->setup_flag = 1; 597190214Srpaulo 598190214Srpaulo /* read urb data */ 599190214Srpaulo ret = sscanf(string, " %d%n", &urb_len, &cnt); 600190214Srpaulo if (ret < 1) 601190214Srpaulo { 602190214Srpaulo snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 603190214Srpaulo "Can't parse urb length from '%s'", string); 604190214Srpaulo return -1; 605190214Srpaulo } 606190214Srpaulo string += cnt; 607190214Srpaulo 608190214Srpaulo /* urb tag is not present if urb length is 0, so we can stop here 609190214Srpaulo * text parsing */ 610190214Srpaulo pkth.len = urb_len+pkth.caplen; 611190214Srpaulo uhdr->urb_len = urb_len; 612190214Srpaulo uhdr->data_flag = 1; 613190214Srpaulo data_len = 0; 614214518Srpaulo if (uhdr->urb_len == 0) 615190214Srpaulo goto got; 616190214Srpaulo 617190214Srpaulo /* check for data presence; data is present if and only if urb tag is '=' */ 618190214Srpaulo if (sscanf(string, " %c", &urb_tag) != 1) 619190214Srpaulo { 620190214Srpaulo snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 621190214Srpaulo "Can't parse urb tag from '%s'", string); 622190214Srpaulo return -1; 623190214Srpaulo } 624190214Srpaulo 625190214Srpaulo if (urb_tag != '=') 626190214Srpaulo goto got; 627190214Srpaulo 628190214Srpaulo /* skip urb tag and following space */ 629190214Srpaulo string += 3; 630190214Srpaulo 631190214Srpaulo /* if we reach this point we got some urb data*/ 632190214Srpaulo uhdr->data_flag = 0; 633190214Srpaulo 634190214Srpaulo /* read all urb data; if urb length is greater then the usbmon internal 635190214Srpaulo * buffer length used by the kernel to spool the URB, we get only 636190214Srpaulo * a partial information. 637190214Srpaulo * At least until linux 2.6.17 there is no way to set usbmon intenal buffer 638190214Srpaulo * length and default value is 130. */ 639190214Srpaulo while ((string[0] != 0) && (string[1] != 0) && (pkth.caplen < handle->snapshot)) 640190214Srpaulo { 641190214Srpaulo rawdata[0] = ascii_to_int(string[0]) * 16 + ascii_to_int(string[1]); 642190214Srpaulo rawdata++; 643190214Srpaulo string+=2; 644190214Srpaulo if (string[0] == ' ') 645190214Srpaulo string++; 646190214Srpaulo pkth.caplen++; 647190214Srpaulo data_len++; 648190214Srpaulo } 649190214Srpaulo 650190214Srpaulogot: 651190214Srpaulo uhdr->data_len = data_len; 652190214Srpaulo if (pkth.caplen > handle->snapshot) 653190214Srpaulo pkth.caplen = handle->snapshot; 654190214Srpaulo 655235426Sdelphij if (handle->fcode.bf_insns == NULL || 656235426Sdelphij bpf_filter(handle->fcode.bf_insns, handle->buffer, 657235426Sdelphij pkth.len, pkth.caplen)) { 658276768Sdelphij handlep->packets_read++; 659235426Sdelphij callback(user, &pkth, handle->buffer); 660235426Sdelphij return 1; 661235426Sdelphij } 662235426Sdelphij return 0; /* didn't pass filter */ 663190214Srpaulo} 664190214Srpaulo 665190214Srpaulostatic int 666190214Srpaulousb_inject_linux(pcap_t *handle, const void *buf, size_t size) 667190214Srpaulo{ 668190214Srpaulo snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on " 669190214Srpaulo "USB devices"); 670190214Srpaulo return (-1); 671190214Srpaulo} 672190214Srpaulo 673190214Srpaulostatic int 674190214Srpaulousb_stats_linux(pcap_t *handle, struct pcap_stat *stats) 675190214Srpaulo{ 676276768Sdelphij struct pcap_usb_linux *handlep = handle->priv; 677190214Srpaulo int dummy, ret, consumed, cnt; 678190214Srpaulo char string[USB_LINE_LEN]; 679190214Srpaulo char token[USB_LINE_LEN]; 680190214Srpaulo char * ptr = string; 681214518Srpaulo int fd; 682214518Srpaulo 683276768Sdelphij snprintf(string, USB_LINE_LEN, USB_TEXT_DIR"/%ds", handlep->bus_index); 684214518Srpaulo fd = open(string, O_RDONLY, 0); 685190214Srpaulo if (fd < 0) 686190214Srpaulo { 687214518Srpaulo if (errno == ENOENT) 688214518Srpaulo { 689214518Srpaulo /* 690214518Srpaulo * Not found at the new location; try the old 691214518Srpaulo * location. 692214518Srpaulo */ 693276768Sdelphij snprintf(string, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%ds", handlep->bus_index); 694214518Srpaulo fd = open(string, O_RDONLY, 0); 695214518Srpaulo } 696214518Srpaulo if (fd < 0) { 697214518Srpaulo snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 698214518Srpaulo "Can't open USB stats file %s: %s", 699214518Srpaulo string, strerror(errno)); 700214518Srpaulo return -1; 701214518Srpaulo } 702190214Srpaulo } 703190214Srpaulo 704190214Srpaulo /* read stats line */ 705190214Srpaulo do { 706190214Srpaulo ret = read(fd, string, USB_LINE_LEN-1); 707190214Srpaulo } while ((ret == -1) && (errno == EINTR)); 708190214Srpaulo close(fd); 709190214Srpaulo 710190214Srpaulo if (ret < 0) 711190214Srpaulo { 712190214Srpaulo snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 713190214Srpaulo "Can't read stats from fd %d ", fd); 714190214Srpaulo return -1; 715190214Srpaulo } 716190214Srpaulo string[ret] = 0; 717190214Srpaulo 718190214Srpaulo /* extract info on dropped urbs */ 719190214Srpaulo for (consumed=0; consumed < ret; ) { 720190214Srpaulo /* from the sscanf man page: 721190214Srpaulo * The C standard says: "Execution of a %n directive does 722190214Srpaulo * not increment the assignment count returned at the completion 723190214Srpaulo * of execution" but the Corrigendum seems to contradict this. 724190214Srpaulo * Do not make any assumptions on the effect of %n conversions 725190214Srpaulo * on the return value and explicitly check for cnt assignmet*/ 726214518Srpaulo int ntok; 727214518Srpaulo 728190214Srpaulo cnt = -1; 729214518Srpaulo ntok = sscanf(ptr, "%s%n", token, &cnt); 730190214Srpaulo if ((ntok < 1) || (cnt < 0)) 731190214Srpaulo break; 732190214Srpaulo consumed += cnt; 733190214Srpaulo ptr += cnt; 734190214Srpaulo if (strcmp(token, "nreaders") == 0) 735190214Srpaulo ret = sscanf(ptr, "%d", &stats->ps_drop); 736190214Srpaulo else 737190214Srpaulo ret = sscanf(ptr, "%d", &dummy); 738190214Srpaulo if (ntok != 1) 739190214Srpaulo break; 740190214Srpaulo consumed += cnt; 741190214Srpaulo ptr += cnt; 742190214Srpaulo } 743190214Srpaulo 744276768Sdelphij stats->ps_recv = handlep->packets_read; 745190214Srpaulo stats->ps_ifdrop = 0; 746190214Srpaulo return 0; 747190214Srpaulo} 748190214Srpaulo 749190214Srpaulostatic int 750190214Srpaulousb_setdirection_linux(pcap_t *p, pcap_direction_t d) 751190214Srpaulo{ 752190214Srpaulo p->direction = d; 753190214Srpaulo return 0; 754190214Srpaulo} 755190214Srpaulo 756190214Srpaulo 757190214Srpaulostatic int 758190214Srpaulousb_stats_linux_bin(pcap_t *handle, struct pcap_stat *stats) 759190214Srpaulo{ 760276768Sdelphij struct pcap_usb_linux *handlep = handle->priv; 761190214Srpaulo int ret; 762190214Srpaulo struct mon_bin_stats st; 763190214Srpaulo ret = ioctl(handle->fd, MON_IOCG_STATS, &st); 764190214Srpaulo if (ret < 0) 765190214Srpaulo { 766190214Srpaulo snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 767190214Srpaulo "Can't read stats from fd %d:%s ", handle->fd, strerror(errno)); 768190214Srpaulo return -1; 769190214Srpaulo } 770190214Srpaulo 771276768Sdelphij stats->ps_recv = handlep->packets_read + st.queued; 772214518Srpaulo stats->ps_drop = st.dropped; 773214518Srpaulo stats->ps_ifdrop = 0; 774190214Srpaulo return 0; 775190214Srpaulo} 776190214Srpaulo 777190214Srpaulo/* 778190214Srpaulo * see <linux-kernel-source>/Documentation/usb/usbmon.txt and 779190214Srpaulo * <linux-kernel-source>/drivers/usb/mon/mon_bin.c binary ABI 780190214Srpaulo */ 781190214Srpaulostatic int 782190214Srpaulousb_read_linux_bin(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) 783190214Srpaulo{ 784276768Sdelphij struct pcap_usb_linux *handlep = handle->priv; 785190214Srpaulo struct mon_bin_get info; 786190214Srpaulo int ret; 787190214Srpaulo struct pcap_pkthdr pkth; 788190214Srpaulo int clen = handle->snapshot - sizeof(pcap_usb_header); 789190214Srpaulo 790190214Srpaulo /* the usb header is going to be part of 'packet' data*/ 791190214Srpaulo info.hdr = (pcap_usb_header*) handle->buffer; 792190214Srpaulo info.data = handle->buffer + sizeof(pcap_usb_header); 793190214Srpaulo info.data_len = clen; 794190214Srpaulo 795190214Srpaulo /* ignore interrupt system call errors */ 796190214Srpaulo do { 797190214Srpaulo ret = ioctl(handle->fd, MON_IOCX_GET, &info); 798190214Srpaulo if (handle->break_loop) 799190214Srpaulo { 800190214Srpaulo handle->break_loop = 0; 801190214Srpaulo return -2; 802190214Srpaulo } 803190214Srpaulo } while ((ret == -1) && (errno == EINTR)); 804190214Srpaulo if (ret < 0) 805190214Srpaulo { 806190214Srpaulo if (errno == EAGAIN) 807190214Srpaulo return 0; /* no data there */ 808190214Srpaulo 809190214Srpaulo snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 810190214Srpaulo "Can't read from fd %d: %s", handle->fd, strerror(errno)); 811190214Srpaulo return -1; 812190214Srpaulo } 813190214Srpaulo 814190214Srpaulo /* we can get less that than really captured from kernel, depending on 815190214Srpaulo * snaplen, so adjust header accordingly */ 816190214Srpaulo if (info.hdr->data_len < clen) 817190214Srpaulo clen = info.hdr->data_len; 818190214Srpaulo info.hdr->data_len = clen; 819190214Srpaulo pkth.caplen = clen + sizeof(pcap_usb_header); 820214518Srpaulo pkth.len = info.hdr->data_len + sizeof(pcap_usb_header); 821190214Srpaulo pkth.ts.tv_sec = info.hdr->ts_sec; 822190214Srpaulo pkth.ts.tv_usec = info.hdr->ts_usec; 823190214Srpaulo 824235426Sdelphij if (handle->fcode.bf_insns == NULL || 825235426Sdelphij bpf_filter(handle->fcode.bf_insns, handle->buffer, 826235426Sdelphij pkth.len, pkth.caplen)) { 827276768Sdelphij handlep->packets_read++; 828235426Sdelphij callback(user, &pkth, handle->buffer); 829235426Sdelphij return 1; 830235426Sdelphij } 831235426Sdelphij 832235426Sdelphij return 0; /* didn't pass filter */ 833190214Srpaulo} 834190214Srpaulo 835190214Srpaulo/* 836190214Srpaulo * see <linux-kernel-source>/Documentation/usb/usbmon.txt and 837190214Srpaulo * <linux-kernel-source>/drivers/usb/mon/mon_bin.c binary ABI 838190214Srpaulo */ 839190214Srpaulo#define VEC_SIZE 32 840190214Srpaulostatic int 841190214Srpaulousb_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) 842190214Srpaulo{ 843276768Sdelphij struct pcap_usb_linux *handlep = handle->priv; 844190214Srpaulo struct mon_bin_mfetch fetch; 845190214Srpaulo int32_t vec[VEC_SIZE]; 846190214Srpaulo struct pcap_pkthdr pkth; 847190214Srpaulo pcap_usb_header* hdr; 848190214Srpaulo int nflush = 0; 849190214Srpaulo int packets = 0; 850214518Srpaulo int clen, max_clen; 851190214Srpaulo 852214518Srpaulo max_clen = handle->snapshot - sizeof(pcap_usb_header); 853214518Srpaulo 854190214Srpaulo for (;;) { 855190214Srpaulo int i, ret; 856190214Srpaulo int limit = max_packets - packets; 857190214Srpaulo if (limit <= 0) 858190214Srpaulo limit = VEC_SIZE; 859190214Srpaulo if (limit > VEC_SIZE) 860190214Srpaulo limit = VEC_SIZE; 861190214Srpaulo 862190214Srpaulo /* try to fetch as many events as possible*/ 863190214Srpaulo fetch.offvec = vec; 864190214Srpaulo fetch.nfetch = limit; 865190214Srpaulo fetch.nflush = nflush; 866190214Srpaulo /* ignore interrupt system call errors */ 867190214Srpaulo do { 868190214Srpaulo ret = ioctl(handle->fd, MON_IOCX_MFETCH, &fetch); 869190214Srpaulo if (handle->break_loop) 870190214Srpaulo { 871190214Srpaulo handle->break_loop = 0; 872190214Srpaulo return -2; 873190214Srpaulo } 874190214Srpaulo } while ((ret == -1) && (errno == EINTR)); 875190214Srpaulo if (ret < 0) 876190214Srpaulo { 877190214Srpaulo if (errno == EAGAIN) 878190214Srpaulo return 0; /* no data there */ 879190214Srpaulo 880190214Srpaulo snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 881190214Srpaulo "Can't mfetch fd %d: %s", handle->fd, strerror(errno)); 882190214Srpaulo return -1; 883190214Srpaulo } 884190214Srpaulo 885190214Srpaulo /* keep track of processed events, we will flush them later */ 886190214Srpaulo nflush = fetch.nfetch; 887190214Srpaulo for (i=0; i<fetch.nfetch; ++i) { 888190214Srpaulo /* discard filler */ 889276768Sdelphij hdr = (pcap_usb_header*) &handlep->mmapbuf[vec[i]]; 890190214Srpaulo if (hdr->event_type == '@') 891190214Srpaulo continue; 892190214Srpaulo 893214518Srpaulo /* we can get less that than really captured from kernel, depending on 894214518Srpaulo * snaplen, so adjust header accordingly */ 895214518Srpaulo clen = max_clen; 896214518Srpaulo if (hdr->data_len < clen) 897214518Srpaulo clen = hdr->data_len; 898214518Srpaulo 899190214Srpaulo /* get packet info from header*/ 900214518Srpaulo pkth.caplen = clen + sizeof(pcap_usb_header_mmapped); 901214518Srpaulo pkth.len = hdr->data_len + sizeof(pcap_usb_header_mmapped); 902190214Srpaulo pkth.ts.tv_sec = hdr->ts_sec; 903190214Srpaulo pkth.ts.tv_usec = hdr->ts_usec; 904190214Srpaulo 905235426Sdelphij if (handle->fcode.bf_insns == NULL || 906235426Sdelphij bpf_filter(handle->fcode.bf_insns, (u_char*) hdr, 907235426Sdelphij pkth.len, pkth.caplen)) { 908276768Sdelphij handlep->packets_read++; 909235426Sdelphij callback(user, &pkth, (u_char*) hdr); 910235426Sdelphij packets++; 911235426Sdelphij } 912190214Srpaulo } 913190214Srpaulo 914276768Sdelphij /* with max_packets specifying "unlimited" we stop afer the first chunk*/ 915276768Sdelphij if (PACKET_COUNT_IS_UNLIMITED(max_packets) || (packets == max_packets)) 916190214Srpaulo break; 917190214Srpaulo } 918190214Srpaulo 919190214Srpaulo /* flush pending events*/ 920190214Srpaulo ioctl(handle->fd, MON_IOCH_MFLUSH, nflush); 921190214Srpaulo return packets; 922190214Srpaulo} 923190214Srpaulo 924190214Srpaulostatic void 925190214Srpaulousb_cleanup_linux_mmap(pcap_t* handle) 926190214Srpaulo{ 927276768Sdelphij struct pcap_usb_linux *handlep = handle->priv; 928276768Sdelphij 929214518Srpaulo /* if we have a memory-mapped buffer, unmap it */ 930276768Sdelphij if (handlep->mmapbuf != NULL) { 931276768Sdelphij munmap(handlep->mmapbuf, handlep->mmapbuflen); 932276768Sdelphij handlep->mmapbuf = NULL; 933214518Srpaulo } 934190214Srpaulo pcap_cleanup_live_common(handle); 935190214Srpaulo} 936