1511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
2511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Copyright (c) 2006 Paolo Abeni (Italy)
3511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * All rights reserved.
4511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
5511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Redistribution and use in source and binary forms, with or without
6511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * modification, are permitted provided that the following conditions
7511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * are met:
8511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
9511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * 1. Redistributions of source code must retain the above copyright
10511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * notice, this list of conditions and the following disclaimer.
11511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * 2. Redistributions in binary form must reproduce the above copyright
12511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * notice, this list of conditions and the following disclaimer in the
13511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * documentation and/or other materials provided with the distribution.
14511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * 3. The name of the author may not be used to endorse or promote
15511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * products derived from this software without specific prior written
16511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * permission.
17511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
18511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
30511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * USB sniffing API implementation for Linux platform
31511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * By Paolo Abeni <paolo.abeni@email.it>
32511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Modifications: Kris Katterjohn <katterjohn@gmail.com>
33511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
34511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
35511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifndef lint
36511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic const char rcsid[] _U_ =
37511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall    "@(#) $Header: /tcpdump/master/libpcap/pcap-usb-linux.c,v 1.33 2008-12-23 21:38:50 guy Exp $ (LBL)";
38511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
39511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
40511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_CONFIG_H
41511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include "config.h"
42511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
43511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
44511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include "pcap-int.h"
45511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include "pcap-usb-linux.h"
46511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include "pcap/usb.h"
47511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
48511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef NEED_STRERROR_H
49511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include "strerror.h"
50511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
51511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
52511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <ctype.h>
53511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <errno.h>
54511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <stdlib.h>
55511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <unistd.h>
56511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <fcntl.h>
57511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <string.h>
58511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <dirent.h>
59511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <byteswap.h>
60511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <netinet/in.h>
61511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <sys/ioctl.h>
62511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <sys/mman.h>
63511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_LINUX_USBDEVICE_FS_H
64511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
65511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * We might need <linux/compiler.h> to define __user for
66511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * <linux/usbdevice_fs.h>.
67511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
68511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_LINUX_COMPILER_H
69511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <linux/compiler.h>
70511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* HAVE_LINUX_COMPILER_H */
71511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <linux/usbdevice_fs.h>
72511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* HAVE_LINUX_USBDEVICE_FS_H */
73511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
74511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define USB_IFACE "usbmon"
75511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define USB_TEXT_DIR_OLD "/sys/kernel/debug/usbmon"
76511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define USB_TEXT_DIR "/sys/kernel/debug/usb/usbmon"
77511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define SYS_USB_BUS_DIR "/sys/bus/usb/devices"
78511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define PROC_USB_BUS_DIR "/proc/bus/usb"
79511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define USB_LINE_LEN 4096
80511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
81511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#if __BYTE_ORDER == __LITTLE_ENDIAN
82511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define htols(s) s
83511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define htoll(l) l
84511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define htol64(ll) ll
85511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#else
86511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define htols(s) bswap_16(s)
87511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define htoll(l) bswap_32(l)
88511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define htol64(ll) bswap_64(ll)
89511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
90511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
91511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstruct mon_bin_stats {
92511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	u_int32_t queued;
93511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	u_int32_t dropped;
94511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall};
95511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
96511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstruct mon_bin_get {
97511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	pcap_usb_header *hdr;
98511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	void *data;
99511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	size_t data_len;   /* Length of data (can be zero) */
100511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall};
101511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
102511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstruct mon_bin_mfetch {
103511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int32_t *offvec;   /* Vector of events fetched */
104511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int32_t nfetch;    /* Number of events to fetch (out: fetched) */
105511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int32_t nflush;    /* Number of events to flush */
106511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall};
107511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
108511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define MON_IOC_MAGIC 0x92
109511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
110511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define MON_IOCQ_URB_LEN _IO(MON_IOC_MAGIC, 1)
111511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define MON_IOCX_URB  _IOWR(MON_IOC_MAGIC, 2, struct mon_bin_hdr)
112511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define MON_IOCG_STATS _IOR(MON_IOC_MAGIC, 3, struct mon_bin_stats)
113511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define MON_IOCT_RING_SIZE _IO(MON_IOC_MAGIC, 4)
114511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define MON_IOCQ_RING_SIZE _IO(MON_IOC_MAGIC, 5)
115511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define MON_IOCX_GET   _IOW(MON_IOC_MAGIC, 6, struct mon_bin_get)
116511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define MON_IOCX_MFETCH _IOWR(MON_IOC_MAGIC, 7, struct mon_bin_mfetch)
117511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define MON_IOCH_MFLUSH _IO(MON_IOC_MAGIC, 8)
118511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
119511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define MON_BIN_SETUP 	0x1 /* setup hdr is present*/
120511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define MON_BIN_SETUP_ZERO 	0x2 /* setup buffer is not available */
121511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define MON_BIN_DATA_ZERO 	0x4 /* data buffer is not available */
122511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define MON_BIN_ERROR 	0x8
123511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
124511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
125511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Private data for capturing on Linux USB.
126511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
127511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstruct pcap_usb_linux {
128511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	u_char *mmapbuf;	/* memory-mapped region pointer */
129511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	size_t mmapbuflen;	/* size of region */
130511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int bus_index;
131511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	u_int packets_read;
132511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall};
133511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
134511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/* forward declaration */
135511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int usb_activate(pcap_t *);
136511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int usb_stats_linux(pcap_t *, struct pcap_stat *);
137511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int usb_stats_linux_bin(pcap_t *, struct pcap_stat *);
138511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int usb_read_linux(pcap_t *, int , pcap_handler , u_char *);
139511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int usb_read_linux_bin(pcap_t *, int , pcap_handler , u_char *);
140511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int usb_read_linux_mmap(pcap_t *, int , pcap_handler , u_char *);
141511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int usb_inject_linux(pcap_t *, const void *, size_t);
142511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int usb_setdirection_linux(pcap_t *, pcap_direction_t);
143511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic void usb_cleanup_linux_mmap(pcap_t *);
144511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
145511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/* facility to add an USB device to the device list*/
146511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
147511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallusb_dev_add(pcap_if_t** alldevsp, int n, char *err_str)
148511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
149511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	char dev_name[10];
150511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	char dev_descr[30];
151511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	snprintf(dev_name, 10, USB_IFACE"%d", n);
152511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	snprintf(dev_descr, 30, "USB bus number %d", n);
153511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
154511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (pcap_add_if(alldevsp, dev_name, 0,
155511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	    dev_descr, err_str) < 0)
156511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return -1;
157511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return 0;
158511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
159511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
160511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallint
161511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallusb_findalldevs(pcap_if_t **alldevsp, char *err_str)
162511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
163511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct dirent* data;
164511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int ret = 0;
165511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	DIR* dir;
166511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int n;
167511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	char* name;
168511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	size_t len;
169511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
170511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* try scanning sysfs usb bus directory */
171511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	dir = opendir(SYS_USB_BUS_DIR);
172511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (dir != NULL) {
173511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		while ((ret == 0) && ((data = readdir(dir)) != 0)) {
174511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			name = data->d_name;
175511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
176511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (strncmp(name, "usb", 3) != 0)
177511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				continue;
178511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
179511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (sscanf(&name[3], "%d", &n) == 0)
180511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				continue;
181511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
182511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			ret = usb_dev_add(alldevsp, n, err_str);
183511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
184511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
185511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		closedir(dir);
186511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return ret;
187511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
188511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
189511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* that didn't work; try scanning procfs usb bus directory */
190511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	dir = opendir(PROC_USB_BUS_DIR);
191511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (dir != NULL) {
192511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		while ((ret == 0) && ((data = readdir(dir)) != 0)) {
193511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			name = data->d_name;
194511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			len = strlen(name);
195511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
196511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/* if this file name does not end with a number it's not of our interest */
197511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if ((len < 1) || !isdigit(name[--len]))
198511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				continue;
199511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			while (isdigit(name[--len]));
200511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (sscanf(&name[len+1], "%d", &n) != 1)
201511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				continue;
202511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
203511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			ret = usb_dev_add(alldevsp, n, err_str);
204511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
205511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
206511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		closedir(dir);
207511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return ret;
208511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
209511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
210511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* neither of them worked */
211511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return 0;
212511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
213511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
214511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic
215511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallint usb_mmap(pcap_t* handle)
216511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
217511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_usb_linux *handlep = handle->priv;
218511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int len = ioctl(handle->fd, MON_IOCQ_RING_SIZE);
219511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (len < 0)
220511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return 0;
221511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
222511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handlep->mmapbuflen = len;
223511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handlep->mmapbuf = mmap(0, handlep->mmapbuflen, PROT_READ,
224511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	    MAP_SHARED, handle->fd, 0);
225511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return handlep->mmapbuf != MAP_FAILED;
226511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
227511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
228511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define CTRL_TIMEOUT    (5*1000)        /* milliseconds */
229511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
230511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define USB_DIR_IN		0x80
231511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define USB_TYPE_STANDARD	0x00
232511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define USB_RECIP_DEVICE	0x00
233511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
234511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define USB_REQ_GET_DESCRIPTOR	6
235511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
236511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define USB_DT_DEVICE		1
237511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
238511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/* probe the descriptors of the devices attached to the bus */
239511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/* the descriptors will end up in the captured packet stream */
240511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/* and be decoded by external apps like wireshark */
241511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/* without these identifying probes packet data can't be fully decoded */
242511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic void
243511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallprobe_devices(int bus)
244511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
245511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct usbdevfs_ctrltransfer ctrl;
246511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct dirent* data;
247511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int ret = 0;
248511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	char buf[40];
249511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	DIR* dir;
250511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
251511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* scan usb bus directories for device nodes */
252511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	snprintf(buf, sizeof(buf), "/dev/bus/usb/%03d", bus);
253511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	dir = opendir(buf);
254511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (!dir)
255511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return;
256511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
257511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	while ((ret >= 0) && ((data = readdir(dir)) != 0)) {
258511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		int fd;
259511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		char* name = data->d_name;
260511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
261511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (name[0] == '.')
262511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			continue;
263511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
264511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(buf, sizeof(buf), "/dev/bus/usb/%03d/%s", bus, data->d_name);
265511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
266511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		fd = open(buf, O_RDWR);
267511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (fd == -1)
268511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			continue;
269511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
270511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
271511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Sigh.  Different kernels have different member names
272511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * for this structure.
273511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
274511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE
275511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ctrl.bRequestType = USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE;
276511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ctrl.bRequest = USB_REQ_GET_DESCRIPTOR;
277511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ctrl.wValue = USB_DT_DEVICE << 8;
278511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ctrl.wIndex = 0;
279511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 		ctrl.wLength = sizeof(buf);
280511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#else
281511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ctrl.requesttype = USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE;
282511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ctrl.request = USB_REQ_GET_DESCRIPTOR;
283511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ctrl.value = USB_DT_DEVICE << 8;
284511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ctrl.index = 0;
285511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 		ctrl.length = sizeof(buf);
286511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
287511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ctrl.data = buf;
288511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ctrl.timeout = CTRL_TIMEOUT;
289511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
290511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ret = ioctl(fd, USBDEVFS_CONTROL, &ctrl);
291511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
292511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		close(fd);
293511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
294511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	closedir(dir);
295511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
296511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
297511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallpcap_t *
298511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallusb_create(const char *device, char *ebuf, int *is_ours)
299511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
300511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	const char *cp;
301511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	char *cpend;
302511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	long devnum;
303511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	pcap_t *p;
304511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
305511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* Does this look like a USB monitoring device? */
306511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	cp = strrchr(device, '/');
307511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (cp == NULL)
308511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		cp = device;
309511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* Does it begin with USB_IFACE? */
310511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (strncmp(cp, USB_IFACE, sizeof USB_IFACE - 1) != 0) {
311511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* Nope, doesn't begin with USB_IFACE */
312511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		*is_ours = 0;
313511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return NULL;
314511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
315511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* Yes - is USB_IFACE followed by a number? */
316511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	cp += sizeof USB_IFACE - 1;
317511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	devnum = strtol(cp, &cpend, 10);
318511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (cpend == cp || *cpend != '\0') {
319511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* Not followed by a number. */
320511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		*is_ours = 0;
321511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return NULL;
322511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
323511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (devnum < 0) {
324511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* Followed by a non-valid number. */
325511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		*is_ours = 0;
326511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return NULL;
327511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
328511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
329511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* OK, it's probably ours. */
330511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	*is_ours = 1;
331511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
332511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	p = pcap_create_common(device, ebuf, sizeof (struct pcap_usb_linux));
333511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (p == NULL)
334511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return (NULL);
335511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
336511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	p->activate_op = usb_activate;
337511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return (p);
338511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
339511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
340511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
341511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallusb_activate(pcap_t* handle)
342511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
343511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_usb_linux *handlep = handle->priv;
344511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	char 		full_path[USB_LINE_LEN];
345511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
346511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* Initialize some components of the pcap structure. */
347511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->bufsize = handle->snapshot;
348511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->offset = 0;
349511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->linktype = DLT_USB_LINUX;
350511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
351511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->inject_op = usb_inject_linux;
352511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->setfilter_op = install_bpf_program; /* no kernel filtering */
353511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->setdirection_op = usb_setdirection_linux;
354511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->set_datalink_op = NULL;	/* can't change data link type */
355511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->getnonblock_op = pcap_getnonblock_fd;
356511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->setnonblock_op = pcap_setnonblock_fd;
357511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
358511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*get usb bus index from device name */
359511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (sscanf(handle->opt.source, USB_IFACE"%d", &handlep->bus_index) != 1)
360511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	{
361511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
362511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			"Can't get USB bus index from %s", handle->opt.source);
363511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return PCAP_ERROR;
364511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
365511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
366511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*now select the read method: try to open binary interface */
367511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	snprintf(full_path, USB_LINE_LEN, LINUX_USB_MON_DEV"%d", handlep->bus_index);
368511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->fd = open(full_path, O_RDONLY, 0);
369511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (handle->fd >= 0)
370511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	{
371511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (handle->opt.rfmon) {
372511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
373511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Monitor mode doesn't apply to USB devices.
374511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
375511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			close(handle->fd);
376511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return PCAP_ERROR_RFMON_NOTSUP;
377511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
378511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
379511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* binary api is available, try to use fast mmap access */
380511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (usb_mmap(handle)) {
381511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handle->linktype = DLT_USB_LINUX_MMAPPED;
382511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handle->stats_op = usb_stats_linux_bin;
383511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handle->read_op = usb_read_linux_mmap;
384511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handle->cleanup_op = usb_cleanup_linux_mmap;
385511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			probe_devices(handlep->bus_index);
386511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
387511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
388511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * "handle->fd" is a real file, so "select()" and
389511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * "poll()" work on it.
390511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
391511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handle->selectable_fd = handle->fd;
392511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return 0;
393511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
394511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
395511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* can't mmap, use plain binary interface access */
396511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->stats_op = usb_stats_linux_bin;
397511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->read_op = usb_read_linux_bin;
398511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		probe_devices(handlep->bus_index);
399511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
400511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	else {
401511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*Binary interface not available, try open text interface */
402511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR"/%dt", handlep->bus_index);
403511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->fd = open(full_path, O_RDONLY, 0);
404511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (handle->fd < 0)
405511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		{
406511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (errno == ENOENT)
407511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			{
408511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				/*
409511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * Not found at the new location; try
410511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * the old location.
411511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 */
412511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%dt", handlep->bus_index);
413511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				handle->fd = open(full_path, O_RDONLY, 0);
414511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
415511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (handle->fd < 0) {
416511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				/* no more fallback, give it up*/
417511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
418511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					"Can't open USB bus file %s: %s", full_path, strerror(errno));
419511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				return PCAP_ERROR;
420511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
421511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
422511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
423511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (handle->opt.rfmon) {
424511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
425511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Monitor mode doesn't apply to USB devices.
426511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
427511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			close(handle->fd);
428511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return PCAP_ERROR_RFMON_NOTSUP;
429511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
430511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
431511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->stats_op = usb_stats_linux;
432511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->read_op = usb_read_linux;
433511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
434511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
435511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
436511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * "handle->fd" is a real file, so "select()" and "poll()"
437511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * work on it.
438511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
439511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->selectable_fd = handle->fd;
440511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
441511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* for plain binary access and text access we need to allocate the read
442511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * buffer */
443511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->buffer = malloc(handle->bufsize);
444511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (!handle->buffer) {
445511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
446511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 "malloc: %s", pcap_strerror(errno));
447511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		close(handle->fd);
448511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return PCAP_ERROR;
449511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
450511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return 0;
451511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
452511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
453511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic inline int
454511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallascii_to_int(char c)
455511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
456511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return c < 'A' ? c- '0': ((c<'a') ? c - 'A' + 10: c-'a'+10);
457511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
458511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
459511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
460511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * see <linux-kernel-source>/Documentation/usb/usbmon.txt and
461511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * <linux-kernel-source>/drivers/usb/mon/mon_text.c for urb string
462511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * format description
463511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
464511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
465511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallusb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
466511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
467511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* see:
468511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	* /usr/src/linux/Documentation/usb/usbmon.txt
469511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	* for message format
470511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	*/
471511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_usb_linux *handlep = handle->priv;
472511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	unsigned timestamp;
473511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int tag, cnt, ep_num, dev_addr, dummy, ret, urb_len, data_len;
474511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	char etype, pipeid1, pipeid2, status[16], urb_tag, line[USB_LINE_LEN];
475511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	char *string = line;
476511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	u_char * rawdata = handle->buffer;
477511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_pkthdr pkth;
478511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	pcap_usb_header* uhdr = (pcap_usb_header*)handle->buffer;
479511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	u_char urb_transfer=0;
480511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int incoming=0;
481511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
482511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* ignore interrupt system call errors */
483511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	do {
484511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ret = read(handle->fd, line, USB_LINE_LEN - 1);
485511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (handle->break_loop)
486511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		{
487511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handle->break_loop = 0;
488511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return -2;
489511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
490511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	} while ((ret == -1) && (errno == EINTR));
491511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ret < 0)
492511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	{
493511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (errno == EAGAIN)
494511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return 0;	/* no data there */
495511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
496511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
497511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    "Can't read from fd %d: %s", handle->fd, strerror(errno));
498511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return -1;
499511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
500511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
501511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* read urb header; %n argument may increment return value, but it's
502511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	* not mandatory, so does not count on it*/
503511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	string[ret] = 0;
504511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ret = sscanf(string, "%x %d %c %c%c:%d:%d %s%n", &tag, &timestamp, &etype,
505511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		&pipeid1, &pipeid2, &dev_addr, &ep_num, status,
506511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		&cnt);
507511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ret < 8)
508511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	{
509511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
510511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    "Can't parse USB bus message '%s', too few tokens (expected 8 got %d)",
511511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    string, ret);
512511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return -1;
513511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
514511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	uhdr->id = tag;
515511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	uhdr->device_address = dev_addr;
516511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	uhdr->bus_id = handlep->bus_index;
517511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	uhdr->status = 0;
518511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	string += cnt;
519511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
520511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* don't use usbmon provided timestamp, since it have low precision*/
521511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (gettimeofday(&pkth.ts, NULL) < 0)
522511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	{
523511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
524511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			"Can't get timestamp for message '%s' %d:%s",
525511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			string, errno, strerror(errno));
526511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return -1;
527511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
528511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	uhdr->ts_sec = pkth.ts.tv_sec;
529511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	uhdr->ts_usec = pkth.ts.tv_usec;
530511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
531511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* parse endpoint information */
532511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (pipeid1 == 'C')
533511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		urb_transfer = URB_CONTROL;
534511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	else if (pipeid1 == 'Z')
535511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		urb_transfer = URB_ISOCHRONOUS;
536511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	else if (pipeid1 == 'I')
537511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		urb_transfer = URB_INTERRUPT;
538511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	else if (pipeid1 == 'B')
539511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		urb_transfer = URB_BULK;
540511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (pipeid2 == 'i') {
541511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ep_num |= URB_TRANSFER_IN;
542511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		incoming = 1;
543511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
544511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (etype == 'C')
545511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		incoming = !incoming;
546511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
547511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* direction check*/
548511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (incoming)
549511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	{
550511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (handle->direction == PCAP_D_OUT)
551511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return 0;
552511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
553511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	else
554511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (handle->direction == PCAP_D_IN)
555511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return 0;
556511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	uhdr->event_type = etype;
557511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	uhdr->transfer_type = urb_transfer;
558511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	uhdr->endpoint_number = ep_num;
559511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	pkth.caplen = sizeof(pcap_usb_header);
560511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	rawdata += sizeof(pcap_usb_header);
561511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
562511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* check if this is a setup packet */
563511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ret = sscanf(status, "%d", &dummy);
564511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ret != 1)
565511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	{
566511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* this a setup packet, setup data can be filled with underscore if
567511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		* usbmon has not been able to read them, so we must parse this fields as
568511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		* strings */
569511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		pcap_usb_setup* shdr;
570511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		char str1[3], str2[3], str3[5], str4[5], str5[5];
571511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ret = sscanf(string, "%s %s %s %s %s%n", str1, str2, str3, str4,
572511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		str5, &cnt);
573511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (ret < 5)
574511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		{
575511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
576511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				"Can't parse USB bus message '%s', too few tokens (expected 5 got %d)",
577511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				string, ret);
578511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return -1;
579511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
580511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		string += cnt;
581511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
582511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* try to convert to corresponding integer */
583511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		shdr = &uhdr->setup;
584511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		shdr->bmRequestType = strtoul(str1, 0, 16);
585511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		shdr->bRequest = strtoul(str2, 0, 16);
586511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		shdr->wValue = htols(strtoul(str3, 0, 16));
587511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		shdr->wIndex = htols(strtoul(str4, 0, 16));
588511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		shdr->wLength = htols(strtoul(str5, 0, 16));
589511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
590511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		uhdr->setup_flag = 0;
591511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
592511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	else
593511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		uhdr->setup_flag = 1;
594511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
595511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* read urb data */
596511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ret = sscanf(string, " %d%n", &urb_len, &cnt);
597511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ret < 1)
598511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	{
599511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
600511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		  "Can't parse urb length from '%s'", string);
601511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return -1;
602511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
603511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	string += cnt;
604511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
605511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* urb tag is not present if urb length is 0, so we can stop here
606511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * text parsing */
607511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	pkth.len = urb_len+pkth.caplen;
608511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	uhdr->urb_len = urb_len;
609511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	uhdr->data_flag = 1;
610511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	data_len = 0;
611511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (uhdr->urb_len == 0)
612511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		goto got;
613511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
614511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* check for data presence; data is present if and only if urb tag is '=' */
615511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (sscanf(string, " %c", &urb_tag) != 1)
616511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	{
617511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
618511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			"Can't parse urb tag from '%s'", string);
619511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return -1;
620511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
621511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
622511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (urb_tag != '=')
623511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		goto got;
624511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
625511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* skip urb tag and following space */
626511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	string += 3;
627511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
628511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* if we reach this point we got some urb data*/
629511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	uhdr->data_flag = 0;
630511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
631511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* read all urb data; if urb length is greater then the usbmon internal
632511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * buffer length used by the kernel to spool the URB, we get only
633511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * a partial information.
634511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * At least until linux 2.6.17 there is no way to set usbmon intenal buffer
635511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * length and default value is 130. */
636511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	while ((string[0] != 0) && (string[1] != 0) && (pkth.caplen < handle->snapshot))
637511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	{
638511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		rawdata[0] = ascii_to_int(string[0]) * 16 + ascii_to_int(string[1]);
639511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		rawdata++;
640511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		string+=2;
641511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (string[0] == ' ')
642511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			string++;
643511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		pkth.caplen++;
644511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		data_len++;
645511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
646511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
647511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallgot:
648511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	uhdr->data_len = data_len;
649511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (pkth.caplen > handle->snapshot)
650511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		pkth.caplen = handle->snapshot;
651511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
652511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (handle->fcode.bf_insns == NULL ||
653511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	    bpf_filter(handle->fcode.bf_insns, handle->buffer,
654511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	      pkth.len, pkth.caplen)) {
655511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handlep->packets_read++;
656511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		callback(user, &pkth, handle->buffer);
657511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return 1;
658511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
659511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return 0;	/* didn't pass filter */
660511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
661511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
662511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
663511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallusb_inject_linux(pcap_t *handle, const void *buf, size_t size)
664511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
665511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on "
666511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		"USB devices");
667511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return (-1);
668511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
669511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
670511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
671511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallusb_stats_linux(pcap_t *handle, struct pcap_stat *stats)
672511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
673511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_usb_linux *handlep = handle->priv;
674511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int dummy, ret, consumed, cnt;
675511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	char string[USB_LINE_LEN];
676511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	char token[USB_LINE_LEN];
677511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	char * ptr = string;
678511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int fd;
679511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
680511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	snprintf(string, USB_LINE_LEN, USB_TEXT_DIR"/%ds", handlep->bus_index);
681511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	fd = open(string, O_RDONLY, 0);
682511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (fd < 0)
683511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	{
684511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (errno == ENOENT)
685511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		{
686511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
687511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Not found at the new location; try the old
688511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * location.
689511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
690511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			snprintf(string, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%ds", handlep->bus_index);
691511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			fd = open(string, O_RDONLY, 0);
692511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
693511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (fd < 0) {
694511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
695511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				"Can't open USB stats file %s: %s",
696511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				string, strerror(errno));
697511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return -1;
698511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
699511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
700511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
701511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* read stats line */
702511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	do {
703511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ret = read(fd, string, USB_LINE_LEN-1);
704511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	} while ((ret == -1) && (errno == EINTR));
705511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	close(fd);
706511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
707511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ret < 0)
708511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	{
709511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
710511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			"Can't read stats from fd %d ", fd);
711511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return -1;
712511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
713511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	string[ret] = 0;
714511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
715511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* extract info on dropped urbs */
716511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	for (consumed=0; consumed < ret; ) {
717511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* from the sscanf man page:
718511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 		 * The C standard says: "Execution of a %n directive does
719511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 		 * not increment the assignment count returned at the completion
720511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * of  execution" but the Corrigendum seems to contradict this.
721511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Do not make any assumptions on the effect of %n conversions
722511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * on the return value and explicitly check for cnt assignmet*/
723511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		int ntok;
724511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
725511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		cnt = -1;
726511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ntok = sscanf(ptr, "%s%n", token, &cnt);
727511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if ((ntok < 1) || (cnt < 0))
728511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			break;
729511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		consumed += cnt;
730511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ptr += cnt;
731511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (strcmp(token, "nreaders") == 0)
732511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			ret = sscanf(ptr, "%d", &stats->ps_drop);
733511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		else
734511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			ret = sscanf(ptr, "%d", &dummy);
735511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (ntok != 1)
736511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			break;
737511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		consumed += cnt;
738511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ptr += cnt;
739511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
740511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
741511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	stats->ps_recv = handlep->packets_read;
742511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	stats->ps_ifdrop = 0;
743511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return 0;
744511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
745511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
746511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
747511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallusb_setdirection_linux(pcap_t *p, pcap_direction_t d)
748511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
749511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	p->direction = d;
750511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return 0;
751511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
752511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
753511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
754511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
755511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallusb_stats_linux_bin(pcap_t *handle, struct pcap_stat *stats)
756511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
757511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_usb_linux *handlep = handle->priv;
758511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int ret;
759511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct mon_bin_stats st;
760511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ret = ioctl(handle->fd, MON_IOCG_STATS, &st);
761511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ret < 0)
762511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	{
763511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
764511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			"Can't read stats from fd %d:%s ", handle->fd, strerror(errno));
765511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return -1;
766511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
767511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
768511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	stats->ps_recv = handlep->packets_read + st.queued;
769511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	stats->ps_drop = st.dropped;
770511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	stats->ps_ifdrop = 0;
771511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return 0;
772511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
773511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
774511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
775511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * see <linux-kernel-source>/Documentation/usb/usbmon.txt and
776511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * <linux-kernel-source>/drivers/usb/mon/mon_bin.c binary ABI
777511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
778511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
779511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallusb_read_linux_bin(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
780511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
781511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_usb_linux *handlep = handle->priv;
782511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct mon_bin_get info;
783511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int ret;
784511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_pkthdr pkth;
785511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int clen = handle->snapshot - sizeof(pcap_usb_header);
786511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
787511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* the usb header is going to be part of 'packet' data*/
788511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	info.hdr = (pcap_usb_header*) handle->buffer;
789511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	info.data = handle->buffer + sizeof(pcap_usb_header);
790511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	info.data_len = clen;
791511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
792511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* ignore interrupt system call errors */
793511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	do {
794511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ret = ioctl(handle->fd, MON_IOCX_GET, &info);
795511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (handle->break_loop)
796511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		{
797511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handle->break_loop = 0;
798511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return -2;
799511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
800511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	} while ((ret == -1) && (errno == EINTR));
801511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ret < 0)
802511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	{
803511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (errno == EAGAIN)
804511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return 0;	/* no data there */
805511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
806511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
807511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    "Can't read from fd %d: %s", handle->fd, strerror(errno));
808511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return -1;
809511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
810511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
811511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* we can get less that than really captured from kernel, depending on
812511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * snaplen, so adjust header accordingly */
813511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (info.hdr->data_len < clen)
814511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		clen = info.hdr->data_len;
815511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	info.hdr->data_len = clen;
816511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	pkth.caplen = clen + sizeof(pcap_usb_header);
817511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	pkth.len = info.hdr->data_len + sizeof(pcap_usb_header);
818511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	pkth.ts.tv_sec = info.hdr->ts_sec;
819511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	pkth.ts.tv_usec = info.hdr->ts_usec;
820511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
821511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (handle->fcode.bf_insns == NULL ||
822511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	    bpf_filter(handle->fcode.bf_insns, handle->buffer,
823511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	      pkth.len, pkth.caplen)) {
824511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handlep->packets_read++;
825511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		callback(user, &pkth, handle->buffer);
826511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return 1;
827511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
828511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
829511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return 0;	/* didn't pass filter */
830511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
831511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
832511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
833511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * see <linux-kernel-source>/Documentation/usb/usbmon.txt and
834511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * <linux-kernel-source>/drivers/usb/mon/mon_bin.c binary ABI
835511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
836511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define VEC_SIZE 32
837511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
838511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallusb_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
839511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
840511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_usb_linux *handlep = handle->priv;
841511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct mon_bin_mfetch fetch;
842511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int32_t vec[VEC_SIZE];
843511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_pkthdr pkth;
844511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	pcap_usb_header* hdr;
845511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int nflush = 0;
846511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int packets = 0;
847511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int clen, max_clen;
848511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
849511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	max_clen = handle->snapshot - sizeof(pcap_usb_header);
850511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
851511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	for (;;) {
852511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		int i, ret;
853511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		int limit = max_packets - packets;
854511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (limit <= 0)
855511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			limit = VEC_SIZE;
856511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (limit > VEC_SIZE)
857511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			limit = VEC_SIZE;
858511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
859511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* try to fetch as many events as possible*/
860511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		fetch.offvec = vec;
861511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		fetch.nfetch = limit;
862511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		fetch.nflush = nflush;
863511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* ignore interrupt system call errors */
864511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		do {
865511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			ret = ioctl(handle->fd, MON_IOCX_MFETCH, &fetch);
866511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (handle->break_loop)
867511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			{
868511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				handle->break_loop = 0;
869511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				return -2;
870511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
871511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		} while ((ret == -1) && (errno == EINTR));
872511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (ret < 0)
873511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		{
874511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (errno == EAGAIN)
875511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				return 0;	/* no data there */
876511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
877511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
878511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    "Can't mfetch fd %d: %s", handle->fd, strerror(errno));
879511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return -1;
880511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
881511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
882511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* keep track of processed events, we will flush them later */
883511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		nflush = fetch.nfetch;
884511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		for (i=0; i<fetch.nfetch; ++i) {
885511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/* discard filler */
886511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			hdr = (pcap_usb_header*) &handlep->mmapbuf[vec[i]];
887511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (hdr->event_type == '@')
888511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				continue;
889511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
890511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/* we can get less that than really captured from kernel, depending on
891511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 		* snaplen, so adjust header accordingly */
892511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			clen = max_clen;
893511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (hdr->data_len < clen)
894511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				clen = hdr->data_len;
895511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
896511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/* get packet info from header*/
897511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			pkth.caplen = clen + sizeof(pcap_usb_header_mmapped);
898511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			pkth.len = hdr->data_len + sizeof(pcap_usb_header_mmapped);
899511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			pkth.ts.tv_sec = hdr->ts_sec;
900511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			pkth.ts.tv_usec = hdr->ts_usec;
901511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
902511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (handle->fcode.bf_insns == NULL ||
903511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    bpf_filter(handle->fcode.bf_insns, (u_char*) hdr,
904511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			      pkth.len, pkth.caplen)) {
905511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				handlep->packets_read++;
906511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				callback(user, &pkth, (u_char*) hdr);
907511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				packets++;
908511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
909511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
910511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
911511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* with max_packets specifying "unlimited" we stop afer the first chunk*/
912511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (PACKET_COUNT_IS_UNLIMITED(max_packets) || (packets == max_packets))
913511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			break;
914511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
915511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
916511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* flush pending events*/
917511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ioctl(handle->fd, MON_IOCH_MFLUSH, nflush);
918511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return packets;
919511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
920511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
921511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic void
922511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallusb_cleanup_linux_mmap(pcap_t* handle)
923511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
924511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_usb_linux *handlep = handle->priv;
925511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
926511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* if we have a memory-mapped buffer, unmap it */
927511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (handlep->mmapbuf != NULL) {
928511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		munmap(handlep->mmapbuf, handlep->mmapbuflen);
929511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handlep->mmapbuf = NULL;
930511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
931511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	pcap_cleanup_live_common(handle);
932511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
933