]> The Tcpdump Group git mirrors - libpcap/blob - pcap-usb-linux.c
From Paolo Abeni: add support for the binary USB sniffing interface in
[libpcap] / pcap-usb-linux.c
1 /*
2 * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
3 * Copyright (c) 2005 - 2006 CACE Technologies, Davis (California)
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the Politecnico di Torino, CACE Technologies
16 * nor the names of its contributors may be used to endorse or promote
17 * products derived from this software without specific prior written
18 * permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 * USB sniffing API implementation for Linux platform
33 * By Paolo Abeni <paolo.abeni@email.it>
34 *
35 */
36
37 #ifdef HAVE_CONFIG_H
38 #include "config.h"
39 #endif
40
41 #include "pcap-int.h"
42 #include "pcap-usb-linux.h"
43 #include "pcap/usb.h"
44
45 #ifdef NEED_STRERROR_H
46 #include "strerror.h"
47 #endif
48
49 #include <errno.h>
50 #include <stdlib.h>
51 #include <unistd.h>
52 #include <fcntl.h>
53 #include <string.h>
54 #include <dirent.h>
55 #include <byteswap.h>
56 #include <netinet/in.h>
57 #include <sys/ioctl.h>
58 #include <sys/mman.h>
59
60 #define USB_IFACE "usb"
61 #define USB_DIR "/sys/kernel/debug/usbmon"
62 #define USB_LINE_LEN 4096
63
64
65 #define PIPE_IN 0x80
66 #define PIPE_ISOCHRONOUS 0
67 #define PIPE_INTERRUPT 1
68 #define PIPE_CONTROL 2
69 #define PIPE_BULK 3
70
71 #if __BYTE_ORDER == __LITTLE_ENDIAN
72 #define htols(s) s
73 #define htoll(l) l
74 #else
75 #define htols(s) bswap_16(s)
76 #define htoll(l) bswap_32(l)
77 #endif
78
79 struct mon_bin_stats {
80 u_int32_t queued;
81 u_int32_t dropped;
82 };
83
84 struct mon_bin_get {
85 pcap_usb_header *hdr;
86 void *data;
87 size_t data_len; /* Length of data (can be zero) */
88 };
89
90 struct mon_bin_mfetch {
91 int32_t *offvec; /* Vector of events fetched */
92 int32_t nfetch; /* Number of events to fetch (out: fetched) */
93 int32_t nflush; /* Number of events to flush */
94 };
95
96 #define MON_IOC_MAGIC 0x92
97
98 #define MON_IOCQ_URB_LEN _IO(MON_IOC_MAGIC, 1)
99 #define MON_IOCX_URB _IOWR(MON_IOC_MAGIC, 2, struct mon_bin_hdr)
100 #define MON_IOCG_STATS _IOR(MON_IOC_MAGIC, 3, struct mon_bin_stats)
101 #define MON_IOCT_RING_SIZE _IO(MON_IOC_MAGIC, 4)
102 #define MON_IOCQ_RING_SIZE _IO(MON_IOC_MAGIC, 5)
103 #define MON_IOCX_GET _IOW(MON_IOC_MAGIC, 6, struct mon_bin_get)
104 #define MON_IOCX_MFETCH _IOWR(MON_IOC_MAGIC, 7, struct mon_bin_mfetch)
105 #define MON_IOCH_MFLUSH _IO(MON_IOC_MAGIC, 8)
106
107 #define MON_BIN_SETUP 0x1 /* setup hdr is present*/
108 #define MON_BIN_SETUP_ZERO 0x2 /* setup buffer is not available */
109 #define MON_BIN_DATA_ZERO 0x4 /* data buffer is not available */
110 #define MON_BIN_ERROR 0x8
111
112 /* forward declaration */
113 static int usb_stats_linux(pcap_t *, struct pcap_stat *);
114 static int usb_stats_linux_bin(pcap_t *, struct pcap_stat *);
115 static int usb_read_linux(pcap_t *, int , pcap_handler , u_char *);
116 static int usb_read_linux_bin(pcap_t *, int , pcap_handler , u_char *);
117 static int usb_read_linux_mmap(pcap_t *, int , pcap_handler , u_char *);
118 static int usb_inject_linux(pcap_t *, const void *, size_t);
119 static int usb_setfilter_linux(pcap_t *, struct bpf_program *);
120 static int usb_setdirection_linux(pcap_t *, pcap_direction_t);
121 static void usb_close_linux(pcap_t *);
122 static void usb_close_linux_mmap(pcap_t *);
123
124 int
125 usb_platform_finddevs(pcap_if_t **alldevsp, char *err_str)
126 {
127 pcap_if_t *devlist = *alldevsp;
128 struct dirent* data;
129 DIR* dir = opendir(USB_DIR);
130 if (!dir) {
131 /* it's not fatal, but it would be useful to give a message
132 about debugfs:
133 modprobe usbmon
134 mount -t debugfs none_debugs /sys/kernel/debug
135 */
136 return 0;
137 }
138
139 /* scan usbmon directory */
140 int ret = 0;
141 while ((data = readdir(dir)) != 0)
142 {
143 char* name = data->d_name;
144 int len = strlen(name);
145
146 if ((len >= 2) && name[len -1]== 't')
147 {
148 int n = name[0] - '0';
149 char dev_name[10], dev_descr[30];
150 snprintf(dev_name, 10, USB_IFACE"%d", n);
151 snprintf(dev_descr, 30, "USB bus number %d", n);
152
153 if (pcap_add_if(&devlist, dev_name, 0,
154 dev_descr, err_str) < 0)
155 {
156 ret = -1;
157 break;
158 }
159 }
160 }
161 closedir(dir);
162
163 *alldevsp = devlist;
164 return ret;
165 }
166
167 static
168 int usb_mmap(pcap_t* handle)
169 {
170 int len = ioctl(handle->fd, MON_IOCQ_RING_SIZE);
171 if (len < 0)
172 return 0;
173
174 handle->buffer = mmap(0, len, PROT_READ, MAP_SHARED, handle->fd, 0);
175 return handle->buffer != MAP_FAILED;
176 }
177
178 pcap_t*
179 usb_open_live(const char* bus, int snaplen, int promisc , int to_ms, char* errmsg)
180 {
181 char full_path[USB_LINE_LEN];
182 pcap_t *handle;
183
184 /* Allocate a handle for this session. */
185 handle = malloc(sizeof(*handle));
186 if (handle == NULL) {
187 snprintf(errmsg, PCAP_ERRBUF_SIZE, "malloc: %s",
188 pcap_strerror(errno));
189 return NULL;
190 }
191
192 /* Initialize some components of the pcap structure. */
193 memset(handle, 0, sizeof(*handle));
194 handle->snapshot = snaplen;
195 handle->md.timeout = to_ms;
196 handle->bufsize = snaplen;
197 handle->offset = 0;
198 handle->linktype = DLT_USB;
199
200 /*
201 * "handle->fd" is a real file , so "select()" and "poll()"
202 * work on it.
203 */
204 handle->selectable_fd = handle->fd;
205
206 handle->inject_op = usb_inject_linux;
207 handle->setfilter_op = usb_setfilter_linux;
208 handle->setdirection_op = usb_setdirection_linux;
209 handle->set_datalink_op = NULL; /* can't change data link type */
210 handle->getnonblock_op = pcap_getnonblock_fd;
211 handle->setnonblock_op = pcap_setnonblock_fd;
212 handle->close_op = usb_close_linux;
213
214 /*get usb bus index from device name */
215 if (sscanf(bus, USB_IFACE"%d", &handle->md.ifindex) != 1)
216 {
217 snprintf(errmsg, PCAP_ERRBUF_SIZE,
218 "Can't get USB bus index from %s", bus);
219 free(handle);
220 return NULL;
221 }
222
223 /*now select the read method: try to open binary interface */
224 snprintf(full_path, USB_LINE_LEN, LINUX_USB_MON_DEV"%d", handle->md.ifindex);
225 handle->fd = open(full_path, O_RDONLY, 0);
226 if (handle->fd >= 0)
227 {
228 /* binary api is available, try to use fast mmap access */
229 if (usb_mmap(handle)) {
230 handle->stats_op = usb_stats_linux_bin;
231 handle->read_op = usb_read_linux_mmap;
232 handle->close_op = usb_close_linux_mmap;
233 return handle;
234 }
235
236 /* can't mmap, use plain binary interface access */
237 handle->stats_op = usb_stats_linux_bin;
238 handle->read_op = usb_read_linux_bin;
239 }
240 else {
241 /*Binary interface not available, try open text interface */
242 snprintf(full_path, USB_LINE_LEN, USB_DIR"/%dt", handle->md.ifindex);
243 handle->fd = open(full_path, O_RDONLY, 0);
244 if (handle->fd < 0)
245 {
246 /* no more fallback, give it up*/
247 snprintf(errmsg, PCAP_ERRBUF_SIZE,
248 "Can't open USB bus file %s: %s", full_path, strerror(errno));
249 free(handle);
250 return NULL;
251 }
252 handle->stats_op = usb_stats_linux;
253 handle->read_op = usb_read_linux;
254 }
255
256 /* for plain binary access and text access we need to allocate the read
257 * buffer */
258 handle->buffer = malloc(handle->bufsize);
259 if (!handle->buffer) {
260 snprintf(errmsg, PCAP_ERRBUF_SIZE,
261 "malloc: %s", pcap_strerror(errno));
262 usb_close_linux(handle);
263 return NULL;
264 }
265 return handle;
266 }
267
268 static inline int
269 ascii_to_int(char c)
270 {
271 return c < 'A' ? c- '0': ((c<'a') ? c - 'A' + 10: c-'a'+10);
272 }
273
274 /*
275 * see <linux-kernel-source>/Documentation/usb/usbmon.txt and
276 * <linux-kernel-source>/drivers/usb/mon/mon_text.c for urb string
277 * format description
278 */
279 static int
280 usb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
281 {
282 /* see:
283 * /usr/src/linux/Documentation/usb/usbmon.txt
284 * for message format
285 */
286 unsigned timestamp;
287 int tag, cnt, ep_num, dev_addr, dummy, ret;
288 char etype, pipeid1, pipeid2, status[16], urb_tag, line[USB_LINE_LEN];
289 char *string = line;
290 u_char * rawdata = handle->buffer;
291 struct pcap_pkthdr pkth;
292 pcap_usb_header* uhdr = (pcap_usb_header*)handle->buffer;
293 u_char urb_transfer=0;
294 int incoming=0;
295
296 /* ignore interrupt system call errors */
297 do {
298 ret = read(handle->fd, line, USB_LINE_LEN - 1);
299 if (handle->break_loop)
300 {
301 handle->break_loop = 0;
302 return -2;
303 }
304 } while ((ret == -1) && (errno == EINTR));
305 if (ret < 0)
306 {
307 if (errno == EAGAIN)
308 return 0; /* no data there */
309
310 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
311 "Can't read from fd %d: %s", handle->fd, strerror(errno));
312 return -1;
313 }
314
315 /* read urb header; %n argument may increment return value, but it's
316 * not mandatory, so does not count on it*/
317 string[ret] = 0;
318 ret = sscanf(string, "%x %d %c %c%c:%d:%d %s%n", &tag, &timestamp, &etype,
319 &pipeid1, &pipeid2, &dev_addr, &ep_num, status,
320 &cnt);
321 if (ret < 8)
322 {
323 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
324 "Can't parse USB bus message '%s', too few tokens (expected 8 got %d)",
325 string, ret);
326 return -1;
327 }
328 uhdr->id = tag;
329 uhdr->endpoint_number = ep_num;
330 uhdr->device_address = dev_addr;
331 uhdr->bus_id = htols(handle->md.ifindex);
332 uhdr->status = 0;
333 string += cnt;
334
335 /* don't use usbmon provided timestamp, since it have low precision*/
336 if (gettimeofday(&pkth.ts, NULL) < 0)
337 {
338 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
339 "Can't get timestamp for message '%s' %d:%s",
340 string, errno, strerror(errno));
341 return -1;
342 }
343 uhdr->ts_sec = pkth.ts.tv_sec;
344 uhdr->ts_usec = pkth.ts.tv_usec;
345
346 /* parse endpoint information */
347 if (pipeid1 == 'C')
348 urb_transfer = URB_CONTROL;
349 else if (pipeid1 == 'Z')
350 urb_transfer = URB_ISOCHRONOUS;
351 else if (pipeid1 == 'I')
352 urb_transfer = URB_INTERRUPT;
353 else if (pipeid1 == 'B')
354 urb_transfer = URB_BULK;
355 if (pipeid2 == 'i') {
356 urb_transfer |= URB_TRANSFER_IN;
357 incoming = 1;
358 }
359 if (etype == 'C')
360 incoming = !incoming;
361
362 /* direction check*/
363 if (incoming)
364 {
365 if (handle->direction == PCAP_D_OUT)
366 return 0;
367 }
368 else
369 if (handle->direction == PCAP_D_IN)
370 return 0;
371 uhdr->event_type = etype;
372 uhdr->transfer_type = urb_transfer;
373 pkth.caplen = sizeof(pcap_usb_header);
374 rawdata += sizeof(pcap_usb_header);
375
376 /* check if this is a setup packet */
377 ret = sscanf(status, "%d", &dummy);
378 if (ret != 1)
379 {
380 /* this a setup packet, setup data can be filled with underscore if
381 * usbmon has not been able to read them, so we must parse this fields as
382 * strings */
383 pcap_usb_setup* shdr;
384 char str1[3], str2[3], str3[5], str4[5], str5[5];
385 ret = sscanf(string, "%s %s %s %s %s%n", str1, str2, str3, str4,
386 str5, &cnt);
387 if (ret < 5)
388 {
389 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
390 "Can't parse USB bus message '%s', too few tokens (expected 5 got %d)",
391 string, ret);
392 return -1;
393 }
394 string += cnt;
395
396 /* try to convert to corresponding integer */
397 shdr = &uhdr->setup;
398 shdr->bmRequestType = strtoul(str1, 0, 16);
399 shdr->bRequest = strtoul(str2, 0, 16);
400 shdr->wValue = htols(strtoul(str3, 0, 16));
401 shdr->wIndex = htols(strtoul(str4, 0, 16));
402 shdr->wLength = htols(strtoul(str5, 0, 16));
403
404 uhdr->setup_flag = 0;
405 }
406 else
407 uhdr->setup_flag = 1;
408
409 /* read urb data */
410 ret = sscanf(string, " %d%n", &uhdr->urb_len, &cnt);
411 if (ret < 1)
412 {
413 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
414 "Can't parse urb length from '%s'", string);
415 return -1;
416 }
417 string += cnt;
418
419 /* urb tag is not present if urb length is 0, so we can stop here
420 * text parsing */
421 pkth.len = uhdr->urb_len+pkth.caplen;
422 uhdr->data_flag = 1;
423 uhdr->data_len = 0;
424 if (uhdr->urb_len == pkth.caplen)
425 goto got;
426
427 /* check for data presence; data is present if and only if urb tag is '=' */
428 if (sscanf(string, " %c", &urb_tag) != 1)
429 {
430 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
431 "Can't parse urb tag from '%s'", string);
432 return -1;
433 }
434
435 if (urb_tag != '=')
436 goto got;
437
438 /* skip urb tag and following space */
439 string += 3;
440
441 /* if we reach this point we got some urb data*/
442 uhdr->data_flag = 0;
443
444 /* read all urb data; if urb length is greater then the usbmon internal
445 * buffer length used by the kernel to spool the URB, we get only
446 * a partial information.
447 * At least until linux 2.6.17 there is no way to set usbmon intenal buffer
448 * length and default value is 130. */
449 while ((string[0] != 0) && (string[1] != 0) && (pkth.caplen < handle->snapshot))
450 {
451 rawdata[0] = ascii_to_int(string[0]) * 16 + ascii_to_int(string[1]);
452 rawdata++;
453 string+=2;
454 if (string[0] == ' ')
455 string++;
456 pkth.caplen++;
457 uhdr->data_len++;
458 }
459
460 got:
461 handle->md.packets_read++;
462 if (pkth.caplen > handle->snapshot)
463 pkth.caplen = handle->snapshot;
464
465 callback(user, &pkth, handle->buffer);
466 return 1;
467 }
468
469 static int
470 usb_inject_linux(pcap_t *handle, const void *buf, size_t size)
471 {
472 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on "
473 "USB devices");
474 return (-1);
475 }
476
477 static void
478 usb_close_linux(pcap_t* handle)
479 {
480 /* handle fill be freed in pcap_close() 'common' code */
481 close(handle->fd);
482 if (handle->buffer)
483 free(handle->buffer);
484 }
485
486 static int
487 usb_stats_linux(pcap_t *handle, struct pcap_stat *stats)
488 {
489 int dummy, ret, consumed, cnt;
490 char string[USB_LINE_LEN];
491 char token[USB_LINE_LEN];
492 char * ptr = string;
493 snprintf(string, USB_LINE_LEN, USB_DIR"/%ds", handle->md.ifindex);
494
495 int fd = open(string, O_RDONLY, 0);
496 if (fd < 0)
497 {
498 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
499 "Can't open USB stats file %s: %s",
500 string, strerror(errno));
501 return -1;
502 }
503
504 /* read stats line */
505 do {
506 ret = read(fd, string, USB_LINE_LEN-1);
507 } while ((ret == -1) && (errno == EINTR));
508 close(fd);
509
510 if (ret < 0)
511 {
512 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
513 "Can't read stats from fd %d ", fd);
514 return -1;
515 }
516 string[ret] = 0;
517
518 /* extract info on dropped urbs */
519 for (consumed=0; consumed < ret; ) {
520 int ntok = sscanf(ptr, "%s%n", token, &cnt);
521 if (ntok != 2)
522 break;
523 consumed += cnt;
524 ptr += cnt;
525 if (strcmp(token, "nreaders") == 0)
526 ret = sscanf(ptr, "%d", &stats->ps_drop);
527 else
528 ret = sscanf(ptr, "%d", &dummy);
529 if (ntok != 2)
530 break;
531 consumed += cnt;
532 ptr += cnt;
533 }
534
535 stats->ps_recv = handle->md.packets_read;
536 stats->ps_ifdrop = 0;
537 return 0;
538 }
539
540 static int
541 usb_setfilter_linux(pcap_t *p, struct bpf_program *fp)
542 {
543 return 0;
544 }
545
546 static int
547 usb_setdirection_linux(pcap_t *p, pcap_direction_t d)
548 {
549 p->direction = d;
550 return 0;
551 }
552
553
554 static int
555 usb_stats_linux_bin(pcap_t *handle, struct pcap_stat *stats)
556 {
557 int dummy, ret;
558 struct mon_bin_stats st;
559 ret = ioctl(handle->fd, MON_IOCG_STATS, &st);
560 if (ret < 0)
561 {
562 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
563 "Can't read stats from fd %d:%s ", handle->fd, strerror(errno));
564 return -1;
565 }
566
567 stats->ps_recv = handle->md.packets_read + st.queued;
568 stats->ps_ifdrop = st.dropped;
569 return 0;
570 }
571
572 /*
573 * see <linux-kernel-source>/Documentation/usb/usbmon.txt and
574 * <linux-kernel-source>/drivers/usb/mon/mon_bin.c binary ABI
575 */
576 static int
577 usb_read_linux_bin(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
578 {
579 struct mon_bin_get info;
580 int ret;
581 struct pcap_pkthdr pkth;
582 int hdr_size;
583 u_short flags = 0;
584 int clen = handle->snapshot - sizeof(pcap_usb_header);
585
586 /* the usb header is going to be part of 'packet' data*/
587 info.hdr = (pcap_usb_header*) handle->buffer;
588 info.data = handle->buffer + sizeof(pcap_usb_header);
589 info.data_len = clen;
590 /* ignore interrupt system call errors */
591 do {
592 ret = ioctl(handle->fd, MON_IOCX_GET, &info);
593 if (handle->break_loop)
594 {
595 handle->break_loop = 0;
596 return -2;
597 }
598 } while ((ret == -1) && (errno == EINTR));
599 if (ret < 0)
600 {
601 if (errno == EAGAIN)
602 return 0; /* no data there */
603
604 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
605 "Can't read from fd %d: %s", handle->fd, strerror(errno));
606 return -1;
607 }
608
609 /* we can get less that than really captured from kernel, depending on
610 * snaplen, so adjust header accordingly */
611 if (info.hdr->data_len < clen)
612 clen = info.hdr->data_len;
613 info.hdr->data_len = clen;
614 pkth.caplen = clen + sizeof(pcap_usb_header);
615 pkth.len = info.hdr->urb_len + sizeof(pcap_usb_header);
616 pkth.ts.tv_sec = info.hdr->ts_sec;
617 pkth.ts.tv_usec = info.hdr->ts_usec;
618
619 handle->md.packets_read++;
620 callback(user, &pkth, handle->buffer);
621 return 1;
622 }
623
624 /*
625 * see <linux-kernel-source>/Documentation/usb/usbmon.txt and
626 * <linux-kernel-source>/drivers/usb/mon/mon_bin.c binary ABI
627 */
628 #define VEC_SIZE 32
629 static int
630 usb_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
631 {
632 struct mon_bin_mfetch fetch;
633 uint32_t vec[VEC_SIZE];
634 struct pcap_pkthdr pkth;
635 pcap_usb_header* hdr;
636 int nflush = 0;
637 int packets = 0;
638
639 for (;;) {
640 int i, ret;
641 int limit = max_packets - packets;
642 if (limit < 0)
643 limit = VEC_SIZE;
644 if (limit > VEC_SIZE)
645 limit = VEC_SIZE;
646
647 /* try to fetch as many events as possible*/
648 fetch.offvec = vec;
649 fetch.nfetch = limit;
650 fetch.nflush = nflush;
651 /* ignore interrupt system call errors */
652 do {
653 ret = ioctl(handle->fd, MON_IOCX_MFETCH, &fetch);
654 if (handle->break_loop)
655 {
656 handle->break_loop = 0;
657 return -2;
658 }
659 } while ((ret == -1) && (errno == EINTR));
660 if (ret < 0)
661 {
662 if (errno == EAGAIN)
663 return 0; /* no data there */
664
665 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
666 "Can't mfetch fd %d: %s", handle->fd, strerror(errno));
667 return -1;
668 }
669
670 /* keep track of processed events, we will flush them later */
671 nflush = fetch.nfetch;
672 for (i=0; i<fetch.nfetch; ++i) {
673 /* discard filler */
674 hdr = (pcap_usb_header*) &handle->buffer[vec[i]];
675 if (hdr->event_type == '@')
676 continue;
677
678 /* get packet info from header*/
679 pkth.caplen = hdr->data_len + sizeof(pcap_usb_header);
680 pkth.len = hdr->urb_len + sizeof(pcap_usb_header);
681 pkth.ts.tv_sec = hdr->ts_sec;
682 pkth.ts.tv_usec = hdr->ts_usec;
683
684 handle->md.packets_read++;
685 callback(user, &pkth, (u_char*) hdr);
686 packets++;
687 }
688
689 /* with max_packets == -1 we stop afer the first chunk*/
690 if ((max_packets == -1) || (packets == max_packets))
691 break;
692 }
693
694 /* flush pending events*/
695 ioctl(handle->fd, MON_IOCH_MFLUSH, nflush);
696 return packets;
697 }
698
699 static void
700 usb_close_linux_mmap(pcap_t* handle)
701 {
702 /* handle fill be freed in pcap_close() 'common' code, buffer must not
703 * be freed because it's memory mapped */
704 close(handle->fd);
705 }