1/*
2 * Copyright (c) 2006 Paolo Abeni (Italy)
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote
15 * products derived from this software without specific prior written
16 * permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * USB sniffing API implementation for Linux platform
31 * By Paolo Abeni <paolo.abeni@email.it>
32 * Modifications: Kris Katterjohn <katterjohn@gmail.com>
33 *
34 */
35#ifndef lint
36static const char rcsid[] _U_ =
37    "@(#) $Header: /tcpdump/master/libpcap/pcap-usb-linux.c,v 1.33 2008-12-23 21:38:50 guy Exp $ (LBL)";
38#endif
39
40#ifdef HAVE_CONFIG_H
41#include "config.h"
42#endif
43
44#include "pcap-int.h"
45#include "pcap-usb-linux.h"
46#include "pcap/usb.h"
47
48#ifdef NEED_STRERROR_H
49#include "strerror.h"
50#endif
51
52#include <ctype.h>
53#include <errno.h>
54#include <stdlib.h>
55#include <unistd.h>
56#include <fcntl.h>
57#include <string.h>
58#include <dirent.h>
59#include <byteswap.h>
60#include <netinet/in.h>
61#include <sys/ioctl.h>
62#include <sys/mman.h>
63#ifdef HAVE_LINUX_USBDEVICE_FS_H
64/*
65 * We might need <linux/compiler.h> to define __user for
66 * <linux/usbdevice_fs.h>.
67 */
68#ifdef HAVE_LINUX_COMPILER_H
69#include <linux/compiler.h>
70#endif /* HAVE_LINUX_COMPILER_H */
71#include <linux/usbdevice_fs.h>
72#endif /* HAVE_LINUX_USBDEVICE_FS_H */
73
74#define USB_IFACE "usbmon"
75#define USB_TEXT_DIR_OLD "/sys/kernel/debug/usbmon"
76#define USB_TEXT_DIR "/sys/kernel/debug/usb/usbmon"
77#define SYS_USB_BUS_DIR "/sys/bus/usb/devices"
78#define PROC_USB_BUS_DIR "/proc/bus/usb"
79#define USB_LINE_LEN 4096
80
81#if __BYTE_ORDER == __LITTLE_ENDIAN
82#define htols(s) s
83#define htoll(l) l
84#define htol64(ll) ll
85#else
86#define htols(s) bswap_16(s)
87#define htoll(l) bswap_32(l)
88#define htol64(ll) bswap_64(ll)
89#endif
90
91struct mon_bin_stats {
92	u_int32_t queued;
93	u_int32_t dropped;
94};
95
96struct mon_bin_get {
97	pcap_usb_header *hdr;
98	void *data;
99	size_t data_len;   /* Length of data (can be zero) */
100};
101
102struct mon_bin_mfetch {
103	int32_t *offvec;   /* Vector of events fetched */
104	int32_t nfetch;    /* Number of events to fetch (out: fetched) */
105	int32_t nflush;    /* Number of events to flush */
106};
107
108#define MON_IOC_MAGIC 0x92
109
110#define MON_IOCQ_URB_LEN _IO(MON_IOC_MAGIC, 1)
111#define MON_IOCX_URB  _IOWR(MON_IOC_MAGIC, 2, struct mon_bin_hdr)
112#define MON_IOCG_STATS _IOR(MON_IOC_MAGIC, 3, struct mon_bin_stats)
113#define MON_IOCT_RING_SIZE _IO(MON_IOC_MAGIC, 4)
114#define MON_IOCQ_RING_SIZE _IO(MON_IOC_MAGIC, 5)
115#define MON_IOCX_GET   _IOW(MON_IOC_MAGIC, 6, struct mon_bin_get)
116#define MON_IOCX_MFETCH _IOWR(MON_IOC_MAGIC, 7, struct mon_bin_mfetch)
117#define MON_IOCH_MFLUSH _IO(MON_IOC_MAGIC, 8)
118
119#define MON_BIN_SETUP 	0x1 /* setup hdr is present*/
120#define MON_BIN_SETUP_ZERO 	0x2 /* setup buffer is not available */
121#define MON_BIN_DATA_ZERO 	0x4 /* data buffer is not available */
122#define MON_BIN_ERROR 	0x8
123
124/* forward declaration */
125static int usb_activate(pcap_t *);
126static int usb_stats_linux(pcap_t *, struct pcap_stat *);
127static int usb_stats_linux_bin(pcap_t *, struct pcap_stat *);
128static int usb_read_linux(pcap_t *, int , pcap_handler , u_char *);
129static int usb_read_linux_bin(pcap_t *, int , pcap_handler , u_char *);
130static int usb_read_linux_mmap(pcap_t *, int , pcap_handler , u_char *);
131static int usb_inject_linux(pcap_t *, const void *, size_t);
132static int usb_setdirection_linux(pcap_t *, pcap_direction_t);
133static void usb_cleanup_linux_mmap(pcap_t *);
134
135/* facility to add an USB device to the device list*/
136static int
137usb_dev_add(pcap_if_t** alldevsp, int n, char *err_str)
138{
139	char dev_name[10];
140	char dev_descr[30];
141	snprintf(dev_name, 10, USB_IFACE"%d", n);
142	snprintf(dev_descr, 30, "USB bus number %d", n);
143
144	if (pcap_add_if(alldevsp, dev_name, 0,
145	    dev_descr, err_str) < 0)
146		return -1;
147	return 0;
148}
149
150int
151usb_findalldevs(pcap_if_t **alldevsp, char *err_str)
152{
153	struct dirent* data;
154	int ret = 0;
155	DIR* dir;
156	int n;
157	char* name;
158	size_t len;
159
160	/* try scanning sysfs usb bus directory */
161	dir = opendir(SYS_USB_BUS_DIR);
162	if (dir != NULL) {
163		while ((ret == 0) && ((data = readdir(dir)) != 0)) {
164			name = data->d_name;
165
166			if (strncmp(name, "usb", 3) != 0)
167				continue;
168
169			if (sscanf(&name[3], "%d", &n) == 0)
170				continue;
171
172			ret = usb_dev_add(alldevsp, n, err_str);
173		}
174
175		closedir(dir);
176		return ret;
177	}
178
179	/* that didn't work; try scanning procfs usb bus directory */
180	dir = opendir(PROC_USB_BUS_DIR);
181	if (dir != NULL) {
182		while ((ret == 0) && ((data = readdir(dir)) != 0)) {
183			name = data->d_name;
184			len = strlen(name);
185
186			/* if this file name does not end with a number it's not of our interest */
187			if ((len < 1) || !isdigit(name[--len]))
188				continue;
189			while (isdigit(name[--len]));
190			if (sscanf(&name[len+1], "%d", &n) != 1)
191				continue;
192
193			ret = usb_dev_add(alldevsp, n, err_str);
194		}
195
196		closedir(dir);
197		return ret;
198	}
199
200	/* neither of them worked */
201	return 0;
202}
203
204static
205int usb_mmap(pcap_t* handle)
206{
207	int len = ioctl(handle->fd, MON_IOCQ_RING_SIZE);
208	if (len < 0)
209		return 0;
210
211	handle->md.mmapbuflen = len;
212	handle->md.mmapbuf = mmap(0, handle->md.mmapbuflen, PROT_READ,
213	    MAP_SHARED, handle->fd, 0);
214	return handle->md.mmapbuf != MAP_FAILED;
215}
216
217#define CTRL_TIMEOUT    (5*1000)        /* milliseconds */
218
219#define USB_DIR_IN		0x80
220#define USB_TYPE_STANDARD	0x00
221#define USB_RECIP_DEVICE	0x00
222
223#define USB_REQ_GET_DESCRIPTOR	6
224
225#define USB_DT_DEVICE		1
226
227/* probe the descriptors of the devices attached to the bus */
228/* the descriptors will end up in the captured packet stream */
229/* and be decoded by external apps like wireshark */
230/* without these identifying probes packet data can't be fully decoded */
231static void
232probe_devices(int bus)
233{
234	struct usbdevfs_ctrltransfer ctrl;
235	struct dirent* data;
236	int ret = 0;
237	char buf[40];
238	DIR* dir;
239
240	/* scan usb bus directories for device nodes */
241	snprintf(buf, sizeof(buf), "/dev/bus/usb/%03d", bus);
242	dir = opendir(buf);
243	if (!dir)
244		return;
245
246	while ((ret >= 0) && ((data = readdir(dir)) != 0)) {
247		int fd;
248		char* name = data->d_name;
249
250		if (name[0] == '.')
251			continue;
252
253		snprintf(buf, sizeof(buf), "/dev/bus/usb/%03d/%s", bus, data->d_name);
254
255		fd = open(buf, O_RDWR);
256		if (fd == -1)
257			continue;
258
259		/*
260		 * Sigh.  Different kernels have different member names
261		 * for this structure.
262		 */
263#ifdef HAVE_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE
264		ctrl.bRequestType = USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE;
265		ctrl.bRequest = USB_REQ_GET_DESCRIPTOR;
266		ctrl.wValue = USB_DT_DEVICE << 8;
267		ctrl.wIndex = 0;
268 		ctrl.wLength = sizeof(buf);
269#else
270		ctrl.requesttype = USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE;
271		ctrl.request = USB_REQ_GET_DESCRIPTOR;
272		ctrl.value = USB_DT_DEVICE << 8;
273		ctrl.index = 0;
274 		ctrl.length = sizeof(buf);
275#endif
276		ctrl.data = buf;
277		ctrl.timeout = CTRL_TIMEOUT;
278
279		ret = ioctl(fd, USBDEVFS_CONTROL, &ctrl);
280
281		close(fd);
282	}
283	closedir(dir);
284}
285
286pcap_t *
287usb_create(const char *device, char *ebuf, int *is_ours)
288{
289	const char *cp;
290	char *cpend;
291	long devnum;
292	pcap_t *p;
293
294	/* Does this look like a USB monitoring device? */
295	cp = strrchr(device, '/');
296	if (cp == NULL)
297		cp = device;
298	/* Does it begin with USB_IFACE? */
299	if (strncmp(cp, USB_IFACE, sizeof USB_IFACE - 1) != 0) {
300		/* Nope, doesn't begin with USB_IFACE */
301		*is_ours = 0;
302		return NULL;
303	}
304	/* Yes - is USB_IFACE followed by a number? */
305	cp += sizeof USB_IFACE - 1;
306	devnum = strtol(cp, &cpend, 10);
307	if (cpend == cp || *cpend != '\0') {
308		/* Not followed by a number. */
309		*is_ours = 0;
310		return NULL;
311	}
312	if (devnum < 0) {
313		/* Followed by a non-valid number. */
314		*is_ours = 0;
315		return NULL;
316	}
317
318	/* OK, it's probably ours. */
319	*is_ours = 1;
320
321	p = pcap_create_common(device, ebuf);
322	if (p == NULL)
323		return (NULL);
324
325	p->activate_op = usb_activate;
326	return (p);
327}
328
329static int
330usb_activate(pcap_t* handle)
331{
332	char 		full_path[USB_LINE_LEN];
333
334	/* Initialize some components of the pcap structure. */
335	handle->bufsize = handle->snapshot;
336	handle->offset = 0;
337	handle->linktype = DLT_USB_LINUX;
338
339	handle->inject_op = usb_inject_linux;
340	handle->setfilter_op = install_bpf_program; /* no kernel filtering */
341	handle->setdirection_op = usb_setdirection_linux;
342	handle->set_datalink_op = NULL;	/* can't change data link type */
343	handle->getnonblock_op = pcap_getnonblock_fd;
344	handle->setnonblock_op = pcap_setnonblock_fd;
345
346	/*get usb bus index from device name */
347	if (sscanf(handle->opt.source, USB_IFACE"%d", &handle->md.ifindex) != 1)
348	{
349		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
350			"Can't get USB bus index from %s", handle->opt.source);
351		return PCAP_ERROR;
352	}
353
354	/*now select the read method: try to open binary interface */
355	snprintf(full_path, USB_LINE_LEN, LINUX_USB_MON_DEV"%d", handle->md.ifindex);
356	handle->fd = open(full_path, O_RDONLY, 0);
357	if (handle->fd >= 0)
358	{
359		if (handle->opt.rfmon) {
360			/*
361			 * Monitor mode doesn't apply to USB devices.
362			 */
363			close(handle->fd);
364			return PCAP_ERROR_RFMON_NOTSUP;
365		}
366
367		/* binary api is available, try to use fast mmap access */
368		if (usb_mmap(handle)) {
369			handle->linktype = DLT_USB_LINUX_MMAPPED;
370			handle->stats_op = usb_stats_linux_bin;
371			handle->read_op = usb_read_linux_mmap;
372			handle->cleanup_op = usb_cleanup_linux_mmap;
373			probe_devices(handle->md.ifindex);
374
375			/*
376			 * "handle->fd" is a real file, so "select()" and
377			 * "poll()" work on it.
378			 */
379			handle->selectable_fd = handle->fd;
380			return 0;
381		}
382
383		/* can't mmap, use plain binary interface access */
384		handle->stats_op = usb_stats_linux_bin;
385		handle->read_op = usb_read_linux_bin;
386		probe_devices(handle->md.ifindex);
387	}
388	else {
389		/*Binary interface not available, try open text interface */
390		snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR"/%dt", handle->md.ifindex);
391		handle->fd = open(full_path, O_RDONLY, 0);
392		if (handle->fd < 0)
393		{
394			if (errno == ENOENT)
395			{
396				/*
397				 * Not found at the new location; try
398				 * the old location.
399				 */
400				snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%dt", handle->md.ifindex);
401				handle->fd = open(full_path, O_RDONLY, 0);
402			}
403			if (handle->fd < 0) {
404				/* no more fallback, give it up*/
405				snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
406					"Can't open USB bus file %s: %s", full_path, strerror(errno));
407				return PCAP_ERROR;
408			}
409		}
410
411		if (handle->opt.rfmon) {
412			/*
413			 * Monitor mode doesn't apply to USB devices.
414			 */
415			close(handle->fd);
416			return PCAP_ERROR_RFMON_NOTSUP;
417		}
418
419		handle->stats_op = usb_stats_linux;
420		handle->read_op = usb_read_linux;
421	}
422
423	/*
424	 * "handle->fd" is a real file, so "select()" and "poll()"
425	 * work on it.
426	 */
427	handle->selectable_fd = handle->fd;
428
429	/* for plain binary access and text access we need to allocate the read
430	 * buffer */
431	handle->buffer = malloc(handle->bufsize);
432	if (!handle->buffer) {
433		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
434			 "malloc: %s", pcap_strerror(errno));
435		close(handle->fd);
436		return PCAP_ERROR;
437	}
438	return 0;
439}
440
441static inline int
442ascii_to_int(char c)
443{
444	return c < 'A' ? c- '0': ((c<'a') ? c - 'A' + 10: c-'a'+10);
445}
446
447/*
448 * see <linux-kernel-source>/Documentation/usb/usbmon.txt and
449 * <linux-kernel-source>/drivers/usb/mon/mon_text.c for urb string
450 * format description
451 */
452static int
453usb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
454{
455	/* see:
456	* /usr/src/linux/Documentation/usb/usbmon.txt
457	* for message format
458	*/
459	unsigned timestamp;
460	int tag, cnt, ep_num, dev_addr, dummy, ret, urb_len, data_len;
461	char etype, pipeid1, pipeid2, status[16], urb_tag, line[USB_LINE_LEN];
462	char *string = line;
463	u_char * rawdata = handle->buffer;
464	struct pcap_pkthdr pkth;
465	pcap_usb_header* uhdr = (pcap_usb_header*)handle->buffer;
466	u_char urb_transfer=0;
467	int incoming=0;
468
469	/* ignore interrupt system call errors */
470	do {
471		ret = read(handle->fd, line, USB_LINE_LEN - 1);
472		if (handle->break_loop)
473		{
474			handle->break_loop = 0;
475			return -2;
476		}
477	} while ((ret == -1) && (errno == EINTR));
478	if (ret < 0)
479	{
480		if (errno == EAGAIN)
481			return 0;	/* no data there */
482
483		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
484		    "Can't read from fd %d: %s", handle->fd, strerror(errno));
485		return -1;
486	}
487
488	/* read urb header; %n argument may increment return value, but it's
489	* not mandatory, so does not count on it*/
490	string[ret] = 0;
491	ret = sscanf(string, "%x %d %c %c%c:%d:%d %s%n", &tag, &timestamp, &etype,
492		&pipeid1, &pipeid2, &dev_addr, &ep_num, status,
493		&cnt);
494	if (ret < 8)
495	{
496		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
497		    "Can't parse USB bus message '%s', too few tokens (expected 8 got %d)",
498		    string, ret);
499		return -1;
500	}
501	uhdr->id = tag;
502	uhdr->device_address = dev_addr;
503	uhdr->bus_id = handle->md.ifindex;
504	uhdr->status = 0;
505	string += cnt;
506
507	/* don't use usbmon provided timestamp, since it have low precision*/
508	if (gettimeofday(&pkth.ts, NULL) < 0)
509	{
510		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
511			"Can't get timestamp for message '%s' %d:%s",
512			string, errno, strerror(errno));
513		return -1;
514	}
515	uhdr->ts_sec = pkth.ts.tv_sec;
516	uhdr->ts_usec = pkth.ts.tv_usec;
517
518	/* parse endpoint information */
519	if (pipeid1 == 'C')
520		urb_transfer = URB_CONTROL;
521	else if (pipeid1 == 'Z')
522		urb_transfer = URB_ISOCHRONOUS;
523	else if (pipeid1 == 'I')
524		urb_transfer = URB_INTERRUPT;
525	else if (pipeid1 == 'B')
526		urb_transfer = URB_BULK;
527	if (pipeid2 == 'i') {
528		ep_num |= URB_TRANSFER_IN;
529		incoming = 1;
530	}
531	if (etype == 'C')
532		incoming = !incoming;
533
534	/* direction check*/
535	if (incoming)
536	{
537		if (handle->direction == PCAP_D_OUT)
538			return 0;
539	}
540	else
541		if (handle->direction == PCAP_D_IN)
542			return 0;
543	uhdr->event_type = etype;
544	uhdr->transfer_type = urb_transfer;
545	uhdr->endpoint_number = ep_num;
546	pkth.caplen = sizeof(pcap_usb_header);
547	rawdata += sizeof(pcap_usb_header);
548
549	/* check if this is a setup packet */
550	ret = sscanf(status, "%d", &dummy);
551	if (ret != 1)
552	{
553		/* this a setup packet, setup data can be filled with underscore if
554		* usbmon has not been able to read them, so we must parse this fields as
555		* strings */
556		pcap_usb_setup* shdr;
557		char str1[3], str2[3], str3[5], str4[5], str5[5];
558		ret = sscanf(string, "%s %s %s %s %s%n", str1, str2, str3, str4,
559		str5, &cnt);
560		if (ret < 5)
561		{
562			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
563				"Can't parse USB bus message '%s', too few tokens (expected 5 got %d)",
564				string, ret);
565			return -1;
566		}
567		string += cnt;
568
569		/* try to convert to corresponding integer */
570		shdr = &uhdr->setup;
571		shdr->bmRequestType = strtoul(str1, 0, 16);
572		shdr->bRequest = strtoul(str2, 0, 16);
573		shdr->wValue = htols(strtoul(str3, 0, 16));
574		shdr->wIndex = htols(strtoul(str4, 0, 16));
575		shdr->wLength = htols(strtoul(str5, 0, 16));
576
577		uhdr->setup_flag = 0;
578	}
579	else
580		uhdr->setup_flag = 1;
581
582	/* read urb data */
583	ret = sscanf(string, " %d%n", &urb_len, &cnt);
584	if (ret < 1)
585	{
586		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
587		  "Can't parse urb length from '%s'", string);
588		return -1;
589	}
590	string += cnt;
591
592	/* urb tag is not present if urb length is 0, so we can stop here
593	 * text parsing */
594	pkth.len = urb_len+pkth.caplen;
595	uhdr->urb_len = urb_len;
596	uhdr->data_flag = 1;
597	data_len = 0;
598	if (uhdr->urb_len == 0)
599		goto got;
600
601	/* check for data presence; data is present if and only if urb tag is '=' */
602	if (sscanf(string, " %c", &urb_tag) != 1)
603	{
604		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
605			"Can't parse urb tag from '%s'", string);
606		return -1;
607	}
608
609	if (urb_tag != '=')
610		goto got;
611
612	/* skip urb tag and following space */
613	string += 3;
614
615	/* if we reach this point we got some urb data*/
616	uhdr->data_flag = 0;
617
618	/* read all urb data; if urb length is greater then the usbmon internal
619	 * buffer length used by the kernel to spool the URB, we get only
620	 * a partial information.
621	 * At least until linux 2.6.17 there is no way to set usbmon intenal buffer
622	 * length and default value is 130. */
623	while ((string[0] != 0) && (string[1] != 0) && (pkth.caplen < handle->snapshot))
624	{
625		rawdata[0] = ascii_to_int(string[0]) * 16 + ascii_to_int(string[1]);
626		rawdata++;
627		string+=2;
628		if (string[0] == ' ')
629			string++;
630		pkth.caplen++;
631		data_len++;
632	}
633
634got:
635	uhdr->data_len = data_len;
636	if (pkth.caplen > handle->snapshot)
637		pkth.caplen = handle->snapshot;
638
639	if (handle->fcode.bf_insns == NULL ||
640	    bpf_filter(handle->fcode.bf_insns, handle->buffer,
641	      pkth.len, pkth.caplen)) {
642		handle->md.packets_read++;
643		callback(user, &pkth, handle->buffer);
644		return 1;
645	}
646	return 0;	/* didn't pass filter */
647}
648
649static int
650usb_inject_linux(pcap_t *handle, const void *buf, size_t size)
651{
652	snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on "
653		"USB devices");
654	return (-1);
655}
656
657static int
658usb_stats_linux(pcap_t *handle, struct pcap_stat *stats)
659{
660	int dummy, ret, consumed, cnt;
661	char string[USB_LINE_LEN];
662	char token[USB_LINE_LEN];
663	char * ptr = string;
664	int fd;
665
666	snprintf(string, USB_LINE_LEN, USB_TEXT_DIR"/%ds", handle->md.ifindex);
667	fd = open(string, O_RDONLY, 0);
668	if (fd < 0)
669	{
670		if (errno == ENOENT)
671		{
672			/*
673			 * Not found at the new location; try the old
674			 * location.
675			 */
676			snprintf(string, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%ds", handle->md.ifindex);
677			fd = open(string, O_RDONLY, 0);
678		}
679		if (fd < 0) {
680			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
681				"Can't open USB stats file %s: %s",
682				string, strerror(errno));
683			return -1;
684		}
685	}
686
687	/* read stats line */
688	do {
689		ret = read(fd, string, USB_LINE_LEN-1);
690	} while ((ret == -1) && (errno == EINTR));
691	close(fd);
692
693	if (ret < 0)
694	{
695		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
696			"Can't read stats from fd %d ", fd);
697		return -1;
698	}
699	string[ret] = 0;
700
701	/* extract info on dropped urbs */
702	for (consumed=0; consumed < ret; ) {
703		/* from the sscanf man page:
704 		 * The C standard says: "Execution of a %n directive does
705 		 * not increment the assignment count returned at the completion
706		 * of  execution" but the Corrigendum seems to contradict this.
707		 * Do not make any assumptions on the effect of %n conversions
708		 * on the return value and explicitly check for cnt assignmet*/
709		int ntok;
710
711		cnt = -1;
712		ntok = sscanf(ptr, "%s%n", token, &cnt);
713		if ((ntok < 1) || (cnt < 0))
714			break;
715		consumed += cnt;
716		ptr += cnt;
717		if (strcmp(token, "nreaders") == 0)
718			ret = sscanf(ptr, "%d", &stats->ps_drop);
719		else
720			ret = sscanf(ptr, "%d", &dummy);
721		if (ntok != 1)
722			break;
723		consumed += cnt;
724		ptr += cnt;
725	}
726
727	stats->ps_recv = handle->md.packets_read;
728	stats->ps_ifdrop = 0;
729	return 0;
730}
731
732static int
733usb_setdirection_linux(pcap_t *p, pcap_direction_t d)
734{
735	p->direction = d;
736	return 0;
737}
738
739
740static int
741usb_stats_linux_bin(pcap_t *handle, struct pcap_stat *stats)
742{
743	int ret;
744	struct mon_bin_stats st;
745	ret = ioctl(handle->fd, MON_IOCG_STATS, &st);
746	if (ret < 0)
747	{
748		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
749			"Can't read stats from fd %d:%s ", handle->fd, strerror(errno));
750		return -1;
751	}
752
753	stats->ps_recv = handle->md.packets_read + st.queued;
754	stats->ps_drop = st.dropped;
755	stats->ps_ifdrop = 0;
756	return 0;
757}
758
759/*
760 * see <linux-kernel-source>/Documentation/usb/usbmon.txt and
761 * <linux-kernel-source>/drivers/usb/mon/mon_bin.c binary ABI
762 */
763static int
764usb_read_linux_bin(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
765{
766	struct mon_bin_get info;
767	int ret;
768	struct pcap_pkthdr pkth;
769	int clen = handle->snapshot - sizeof(pcap_usb_header);
770
771	/* the usb header is going to be part of 'packet' data*/
772	info.hdr = (pcap_usb_header*) handle->buffer;
773	info.data = handle->buffer + sizeof(pcap_usb_header);
774	info.data_len = clen;
775
776	/* ignore interrupt system call errors */
777	do {
778		ret = ioctl(handle->fd, MON_IOCX_GET, &info);
779		if (handle->break_loop)
780		{
781			handle->break_loop = 0;
782			return -2;
783		}
784	} while ((ret == -1) && (errno == EINTR));
785	if (ret < 0)
786	{
787		if (errno == EAGAIN)
788			return 0;	/* no data there */
789
790		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
791		    "Can't read from fd %d: %s", handle->fd, strerror(errno));
792		return -1;
793	}
794
795	/* we can get less that than really captured from kernel, depending on
796	 * snaplen, so adjust header accordingly */
797	if (info.hdr->data_len < clen)
798		clen = info.hdr->data_len;
799	info.hdr->data_len = clen;
800	pkth.caplen = clen + sizeof(pcap_usb_header);
801	pkth.len = info.hdr->data_len + sizeof(pcap_usb_header);
802	pkth.ts.tv_sec = info.hdr->ts_sec;
803	pkth.ts.tv_usec = info.hdr->ts_usec;
804
805	if (handle->fcode.bf_insns == NULL ||
806	    bpf_filter(handle->fcode.bf_insns, handle->buffer,
807	      pkth.len, pkth.caplen)) {
808		handle->md.packets_read++;
809		callback(user, &pkth, handle->buffer);
810		return 1;
811	}
812
813	return 0;	/* didn't pass filter */
814}
815
816/*
817 * see <linux-kernel-source>/Documentation/usb/usbmon.txt and
818 * <linux-kernel-source>/drivers/usb/mon/mon_bin.c binary ABI
819 */
820#define VEC_SIZE 32
821static int
822usb_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
823{
824	struct mon_bin_mfetch fetch;
825	int32_t vec[VEC_SIZE];
826	struct pcap_pkthdr pkth;
827	pcap_usb_header* hdr;
828	int nflush = 0;
829	int packets = 0;
830	int clen, max_clen;
831
832	max_clen = handle->snapshot - sizeof(pcap_usb_header);
833
834	for (;;) {
835		int i, ret;
836		int limit = max_packets - packets;
837		if (limit <= 0)
838			limit = VEC_SIZE;
839		if (limit > VEC_SIZE)
840			limit = VEC_SIZE;
841
842		/* try to fetch as many events as possible*/
843		fetch.offvec = vec;
844		fetch.nfetch = limit;
845		fetch.nflush = nflush;
846		/* ignore interrupt system call errors */
847		do {
848			ret = ioctl(handle->fd, MON_IOCX_MFETCH, &fetch);
849			if (handle->break_loop)
850			{
851				handle->break_loop = 0;
852				return -2;
853			}
854		} while ((ret == -1) && (errno == EINTR));
855		if (ret < 0)
856		{
857			if (errno == EAGAIN)
858				return 0;	/* no data there */
859
860			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
861			    "Can't mfetch fd %d: %s", handle->fd, strerror(errno));
862			return -1;
863		}
864
865		/* keep track of processed events, we will flush them later */
866		nflush = fetch.nfetch;
867		for (i=0; i<fetch.nfetch; ++i) {
868			/* discard filler */
869			hdr = (pcap_usb_header*) &handle->md.mmapbuf[vec[i]];
870			if (hdr->event_type == '@')
871				continue;
872
873			/* we can get less that than really captured from kernel, depending on
874	 		* snaplen, so adjust header accordingly */
875			clen = max_clen;
876			if (hdr->data_len < clen)
877				clen = hdr->data_len;
878
879			/* get packet info from header*/
880			pkth.caplen = clen + sizeof(pcap_usb_header_mmapped);
881			pkth.len = hdr->data_len + sizeof(pcap_usb_header_mmapped);
882			pkth.ts.tv_sec = hdr->ts_sec;
883			pkth.ts.tv_usec = hdr->ts_usec;
884
885			if (handle->fcode.bf_insns == NULL ||
886			    bpf_filter(handle->fcode.bf_insns, (u_char*) hdr,
887			      pkth.len, pkth.caplen)) {
888				handle->md.packets_read++;
889				callback(user, &pkth, (u_char*) hdr);
890				packets++;
891			}
892		}
893
894		/* with max_packets <= 0 we stop afer the first chunk*/
895		if ((max_packets <= 0) || (packets == max_packets))
896			break;
897	}
898
899	/* flush pending events*/
900	ioctl(handle->fd, MON_IOCH_MFLUSH, nflush);
901	return packets;
902}
903
904static void
905usb_cleanup_linux_mmap(pcap_t* handle)
906{
907	/* if we have a memory-mapped buffer, unmap it */
908	if (handle->md.mmapbuf != NULL) {
909		munmap(handle->md.mmapbuf, handle->md.mmapbuflen);
910		handle->md.mmapbuf = NULL;
911	}
912	pcap_cleanup_live_common(handle);
913}
914