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, &timestamp, &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