]>
The Tcpdump Group git mirrors - libpcap/blob - pcap-usb-linux.c
942bb0aab7570fb0af9560ccbb3a1d19c0ddef8c
2 * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
3 * Copyright (c) 2005 - 2006 CACE Technologies, Davis (California)
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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
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.
32 * USB sniffig API implementation for linux platform
33 * By Paolo Abeni <paolo.abeni@email.com>
44 #ifdef NEED_STRERROR_H
54 #include <netinet/in.h>
56 #define USB_IFACE "usb"
57 #define USB_DIR "/sys/kernel/debug/usbmon"
58 #define USB_LINE_LEN 4096
60 /* forward declaration */
61 static int usb_read_linux(pcap_t
*, int , pcap_handler
, u_char
*);
62 static int usb_inject_linux(pcap_t
*, const void *, size_t);
63 static int usb_setfilter_linux(pcap_t
*, struct bpf_program
*);
64 static int usb_setdirection_linux(pcap_t
*, pcap_direction_t
);
65 static int usb_stats_linux(pcap_t
*, struct pcap_stat
*);
66 static void usb_close_linux(pcap_t
*);
69 usb_platform_finddevs(pcap_if_t
**alldevsp
, char *err_str
)
71 pcap_if_t
*devlist
= *alldevsp
;
73 DIR* dir
= opendir(USB_DIR
);
75 /* it's not fatal, but it would be useful to give a message
78 mount -t debugfs none_debugs /sys/kernel/debug
83 /* scan usbmon directory */
85 while ((data
= readdir(dir
)) != 0)
87 char* name
= data
->d_name
;
88 int len
= strlen(name
);
90 if ((len
>= 2) && name
[len
-1]== 't')
92 int n
= name
[0] - '0';
93 char dev_name
[10], dev_descr
[30];
94 snprintf(dev_name
, 10, USB_IFACE
"%d", n
);
95 snprintf(dev_descr
, 30, "usb bus number %d", n
);
97 if (pcap_add_if(&devlist
, dev_name
, 0,
98 dev_descr
, err_str
) < 0)
112 usb_open_live(const char* bus
, int snaplen
, int promisc
, int to_ms
, char* errmsg
)
114 char full_path
[USB_LINE_LEN
];
117 /* Allocate a handle for this session. */
118 handle
= malloc(sizeof(*handle
));
119 if (handle
== NULL
) {
120 snprintf(errmsg
, PCAP_ERRBUF_SIZE
, "malloc: %s",
121 pcap_strerror(errno
));
125 /* Initialize some components of the pcap structure. */
126 memset(handle
, 0, sizeof(*handle
));
127 handle
->snapshot
= snaplen
;
128 handle
->md
.timeout
= to_ms
;
129 handle
->bufsize
= USB_LINE_LEN
;
131 handle
->linktype
= DLT_USB
;
133 /* get usb bus index from device name */
134 if (sscanf(bus
, USB_IFACE
"%d", &handle
->md
.ifindex
) != 1)
136 snprintf(errmsg
, PCAP_ERRBUF_SIZE
,
137 "Can't get usb bus index from %s", bus
);
142 /* open text output file*/
143 snprintf(full_path
, USB_LINE_LEN
, USB_DIR
"/%dt", handle
->md
.ifindex
);
144 handle
->fd
= open(full_path
, O_RDONLY
, 0);
147 snprintf(errmsg
, PCAP_ERRBUF_SIZE
,
148 "Can't open usb bus file %s: %s", full_path
, strerror(errno
));
153 handle
->buffer
= malloc(handle
->bufsize
+ handle
->offset
);
154 if (!handle
->buffer
) {
155 snprintf(errmsg
, PCAP_ERRBUF_SIZE
,
156 "malloc: %s", pcap_strerror(errno
));
157 usb_close_linux(handle
);
162 * "handle->fd" is a real file , so "select()" and "poll()"
165 handle
->selectable_fd
= handle
->fd
;
167 handle
->read_op
= usb_read_linux
;
168 handle
->inject_op
= usb_inject_linux
;
169 handle
->setfilter_op
= usb_setfilter_linux
;
170 handle
->setdirection_op
= usb_setdirection_linux
;
171 handle
->set_datalink_op
= NULL
; /* can't change data link type */
172 handle
->getnonblock_op
= pcap_getnonblock_fd
;
173 handle
->setnonblock_op
= pcap_setnonblock_fd
;
174 handle
->stats_op
= usb_stats_linux
;
175 handle
->close_op
= usb_close_linux
;
184 return c
< 'A' ? c
- '0': ((c
<'a') ? c
- 'A': c
-'a');
188 * see <linux-kernel-source>/Documentation/usb/usbmon.txt and
189 * <linux-kernel-source>/drivers/usb/mon/mon_text.c for urb string
193 usb_read_linux(pcap_t
*handle
, int max_packets
, pcap_handler callback
, u_char
*user
)
196 * /usr/src/linux/Documentation/usb/usbmon.txt
200 int tag
, cnt
, ep_num
, dev_addr
, dummy
, ret
;
201 char etype
, pipeid1
, pipeid2
, status
[16], urb_tag
, line
[4096];
203 u_char
* rawdata
= handle
->buffer
;
204 struct pcap_pkthdr pkth
;
205 pcap_usb_header
* uhdr
= (pcap_usb_header
*)rawdata
;
206 pcap_urb_type_t urb_type
= URB_UNKNOWN
;
208 /* ignore interrupt system call errors */
210 ret
= read(handle
->fd
, line
, USB_LINE_LEN
- 1);
211 if (handle
->break_loop
)
213 handle
->break_loop
= 0;
216 } while ((ret
== -1) && (errno
== EINTR
));
220 return 0; /* no data there */
222 snprintf(handle
->errbuf
, PCAP_ERRBUF_SIZE
,
223 "Can't read from fd %d: %s", handle
->fd
, strerror(errno
));
227 /* read urb header; %n argument may increment return value, but it's
228 * not mandatory, so does not count on it*/
230 ret
= sscanf(string
, "%x %d %c %c%c:%d:%d %s%n", &tag
, ×tamp
, &etype
,
231 &pipeid1
, &pipeid2
, &dev_addr
, &ep_num
, status
,
235 snprintf(handle
->errbuf
, PCAP_ERRBUF_SIZE
,
236 "Can't parse usb bus message '%s', too few token (expected 8 got %d)",
240 uhdr
->endpoint_number
= htonl(ep_num
);
241 uhdr
->device_address
= htonl(dev_addr
);
243 pkth
.ts
.tv_sec
= timestamp
/ 1000000;
244 pkth
.ts
.tv_usec
= timestamp
% 1000000;
246 /* parse endpoint information */
250 urb_type
= URB_CONTROL_INPUT
;
252 urb_type
= URB_CONTROL_OUTPUT
;
254 else if (pipeid1
== 'Z')
257 urb_type
= URB_ISOCHRONOUS_INPUT
;
259 urb_type
= URB_ISOCHRONOUS_OUTPUT
;
261 else if (pipeid1
== 'I')
264 urb_type
= URB_INTERRUPT_INPUT
;
266 urb_type
= URB_INTERRUPT_OUTPUT
;
268 else if (pipeid1
== 'B')
271 urb_type
= URB_BULK_INPUT
;
273 urb_type
= URB_BULK_OUTPUT
;
277 if ((urb_type
== URB_BULK_INPUT
) || (urb_type
== URB_INTERRUPT_INPUT
) ||
278 (urb_type
== URB_ISOCHRONOUS_INPUT
) || (urb_type
== URB_CONTROL_INPUT
))
280 if (handle
->direction
== PCAP_D_OUT
)
284 if (handle
->direction
== PCAP_D_IN
)
287 uhdr
->urb_type
= htonl(urb_type
);
288 pkth
.caplen
= sizeof(pcap_usb_header
);
289 rawdata
+= sizeof(pcap_usb_header
);
291 /* check if this is a setup packet */
292 ret
= sscanf(status
, "%d", &dummy
);
295 /* this a setup packet, setup data can be filled with underscore if
296 * usbmon has not been able to read them, so we must parse this fields as
298 pcap_usb_setup
* shdr
;
299 char str1
[3], str2
[3], str3
[5], str4
[5], str5
[5];
300 ret
= sscanf(string
, "%s %s %s %s %s%n", str1
, str2
, str3
, str4
,
304 snprintf(handle
->errbuf
, PCAP_ERRBUF_SIZE
,
305 "Can't parse usb bus message '%s', too few token (expected 5 got %d)",
311 /* try to convert to corresponding integer */
312 shdr
= (pcap_usb_setup
*)rawdata
;
313 shdr
->bmRequestType
= htonl(strtol(str1
, 0, 16));
314 shdr
->bRequest
= htonl(strtol(str2
, 0, 16));
315 shdr
->wValue
= htonl(strtol(str3
, 0, 16));
316 shdr
->wIndex
= htonl(strtol(str4
, 0, 16));
317 shdr
->wLength
= htonl(strtol(str5
, 0, 16));
319 pkth
.caplen
= sizeof(pcap_usb_setup
);
320 rawdata
+= sizeof(pcap_usb_setup
);
324 ret
= sscanf(string
, " %d%n", &pkth
.len
, &cnt
);
327 snprintf(handle
->errbuf
, PCAP_ERRBUF_SIZE
,
328 "Can't parse urb length from '%s'", string
);
332 handle
->md
.packets_read
++;
334 /* urb tag is not present if urb length is 0 */
335 pkth
.len
+= pkth
.caplen
;
336 if (pkth
.len
== pkth
.caplen
)
339 /* check for data presence */
340 if (sscanf(string
, " %c", &urb_tag
) != 1)
342 snprintf(handle
->errbuf
, PCAP_ERRBUF_SIZE
,
343 "Can't parse urb tag from '%s'", string
);
350 /* read all urb data; if urb length is less then our string we get only
351 * a partial information */
352 while ((string
[0] != 0) && (string
[1] != 0))
354 rawdata
[0] = ascii_to_int(string
[0]) * 16 + ascii_to_int(string
[1]);
357 if (string
[0] == ' ')
363 handle
->md
.packets_read
++;
364 if (pkth
.caplen
> handle
->snapshot
)
365 pkth
.caplen
= handle
->snapshot
;
367 callback(user
, &pkth
, handle
->buffer
);
372 usb_inject_linux(pcap_t
*handle
, const void *buf
, size_t size
)
374 snprintf(handle
->errbuf
, PCAP_ERRBUF_SIZE
, "inject not supported on "
381 usb_close_linux(pcap_t
* handle
)
383 /* handle fill be freed in pcap_close() 'common' code */
385 free(handle
->buffer
);
390 usb_stats_linux(pcap_t
*handle
, struct pcap_stat
*stats
)
393 char string
[USB_LINE_LEN
];
394 snprintf(string
, USB_LINE_LEN
, USB_DIR
"/%ds", handle
->md
.ifindex
);
396 int fd
= open(string
, O_RDONLY
, 0);
399 snprintf(handle
->errbuf
, PCAP_ERRBUF_SIZE
,
400 "Can't open usb stats file %s: %s", string
, strerror(errno
));
404 /* read stats line */
406 ret
= read(fd
, string
, USB_LINE_LEN
-1);
407 } while ((ret
== -1) && (errno
== EINTR
));
412 snprintf(handle
->errbuf
, PCAP_ERRBUF_SIZE
,
413 "Can't read stats from fd %d ", fd
);
418 /* extract info on dropped urbs */
419 ret
= sscanf(string
, "nreaders %d text_lost %d", &dummy
, &stats
->ps_drop
);
422 snprintf(handle
->errbuf
, PCAP_ERRBUF_SIZE
,
423 "Can't parse stat line '%s' expected 2 token got %d", string
, ret
);
427 stats
->ps_recv
= handle
->md
.packets_read
;
428 stats
->ps_ifdrop
= 0;
433 usb_setfilter_linux(pcap_t
*p
, struct bpf_program
*fp
)
440 usb_setdirection_linux(pcap_t
*p
, pcap_direction_t d
)