2 * Copyright (c) 2010 Weongyo Jeong <weongyo@freebsd.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer,
10 * without modification.
11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13 * redistribution must be conditioned upon including a substantially
14 * similar Disclaimer requirement for further binary redistribution.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27 * THE POSSIBILITY OF SUCH DAMAGES.
29 * $FreeBSD: head/usr.sbin/usbdump/usbdump.c 260978 2014-01-21 08:24:12Z hselasky $
32 #include <sys/param.h>
33 #include <sys/endian.h>
34 #include <sys/ioctl.h>
35 #include <sys/socket.h>
37 #include <sys/sysctl.h>
38 #include <sys/utsname.h>
39 #include <sys/queue.h>
42 #include <bus/u4b/usb.h>
43 #include <bus/u4b/usb_pf.h>
44 #include <bus/u4b/usbdi.h>
57 #define BPF_STORE_JUMP(x,_c,_k,_jt,_jf) do { \
64 #define BPF_STORE_STMT(x,_c,_k) do { \
72 STAILQ_ENTRY(usb_filt
) entry
;
78 int fd
; /* fd for /dev/usbpf */
90 struct usbcap_filehdr
{
92 #define USBCAP_FILEHDR_MAGIC 0x9a90000e
99 /* capture timestamp */
102 /* data length and alignment information */
109 static int doexit
= 0;
110 static int pkt_captured
= 0;
111 static int verbose
= 0;
113 static const char *i_arg
= "usbus0";
114 static const char *r_arg
= NULL
;
115 static const char *w_arg
= NULL
;
116 static const char *b_arg
= NULL
;
117 static struct usbcap uc
;
118 static const char *errstr_table
[USB_ERR_MAX
] = {
119 [USB_ERR_NORMAL_COMPLETION
] = "0",
120 [USB_ERR_PENDING_REQUESTS
] = "PENDING_REQUESTS",
121 [USB_ERR_NOT_STARTED
] = "NOT_STARTED",
122 [USB_ERR_INVAL
] = "INVAL",
123 [USB_ERR_NOMEM
] = "NOMEM",
124 [USB_ERR_CANCELLED
] = "CANCELLED",
125 [USB_ERR_BAD_ADDRESS
] = "BAD_ADDRESS",
126 [USB_ERR_BAD_BUFSIZE
] = "BAD_BUFSIZE",
127 [USB_ERR_BAD_FLAG
] = "BAD_FLAG",
128 [USB_ERR_NO_CALLBACK
] = "NO_CALLBACK",
129 [USB_ERR_IN_USE
] = "IN_USE",
130 [USB_ERR_NO_ADDR
] = "NO_ADDR",
131 [USB_ERR_NO_PIPE
] = "NO_PIPE",
132 [USB_ERR_ZERO_NFRAMES
] = "ZERO_NFRAMES",
133 [USB_ERR_ZERO_MAXP
] = "ZERO_MAXP",
134 [USB_ERR_SET_ADDR_FAILED
] = "SET_ADDR_FAILED",
135 [USB_ERR_NO_POWER
] = "NO_POWER",
136 [USB_ERR_TOO_DEEP
] = "TOO_DEEP",
137 [USB_ERR_IOERROR
] = "IOERROR",
138 [USB_ERR_NOT_CONFIGURED
] = "NOT_CONFIGURED",
139 [USB_ERR_TIMEOUT
] = "TIMEOUT",
140 [USB_ERR_SHORT_XFER
] = "SHORT_XFER",
141 [USB_ERR_STALLED
] = "STALLED",
142 [USB_ERR_INTERRUPTED
] = "INTERRUPTED",
143 [USB_ERR_DMA_LOAD_FAILED
] = "DMA_LOAD_FAILED",
144 [USB_ERR_BAD_CONTEXT
] = "BAD_CONTEXT",
145 [USB_ERR_NO_ROOT_HUB
] = "NO_ROOT_HUB",
146 [USB_ERR_NO_INTR_THREAD
] = "NO_INTR_THREAD",
147 [USB_ERR_NOT_LOCKED
] = "NOT_LOCKED",
150 static const char *xfertype_table
[4] = {
151 [UE_CONTROL
] = "CTRL",
152 [UE_ISOCHRONOUS
] = "ISOC",
154 [UE_INTERRUPT
] = "INTR"
157 static const char *speed_table
[USB_SPEED_MAX
] = {
158 [USB_SPEED_FULL
] = "FULL",
159 [USB_SPEED_HIGH
] = "HIGH",
160 [USB_SPEED_LOW
] = "LOW",
161 [USB_SPEED_VARIABLE
] = "VARI",
162 [USB_SPEED_SUPER
] = "SUPER",
165 static STAILQ_HEAD(,usb_filt
) usb_filt_head
=
166 STAILQ_HEAD_INITIALIZER(usb_filt_head
);
169 add_filter(int usb_filt_unit
, int usb_filt_ep
)
171 struct usb_filt
*puf
;
173 puf
= malloc(sizeof(struct usb_filt
));
175 errx(EX_SOFTWARE
, "Out of memory.");
177 puf
->unit
= usb_filt_unit
;
178 puf
->endpoint
= usb_filt_ep
;
180 STAILQ_INSERT_TAIL(&usb_filt_head
, puf
, entry
);
184 make_filter(struct bpf_program
*pprog
, int snapshot
)
186 struct usb_filt
*puf
;
187 struct bpf_insn
*dynamic_insn
;
192 STAILQ_FOREACH(puf
, &usb_filt_head
, entry
)
195 dynamic_insn
= malloc(((len
* 5) + 1) * sizeof(struct bpf_insn
));
197 if (dynamic_insn
== NULL
)
198 errx(EX_SOFTWARE
, "Out of memory.");
203 /* accept all packets */
205 BPF_STORE_STMT(dynamic_insn
[0], BPF_RET
| BPF_K
, snapshot
);
212 STAILQ_FOREACH(puf
, &usb_filt_head
, entry
) {
213 const int addr_off
= (uintptr_t)&((struct usbpf_pkthdr
*)0)->up_address
;
214 const int addr_ep
= (uintptr_t)&((struct usbpf_pkthdr
*)0)->up_endpoint
;
216 if (puf
->unit
!= -1) {
217 if (puf
->endpoint
!= -1) {
218 BPF_STORE_STMT(dynamic_insn
[len
],
219 BPF_LD
| BPF_B
| BPF_ABS
, addr_off
);
221 BPF_STORE_JUMP(dynamic_insn
[len
],
222 BPF_JMP
| BPF_JEQ
| BPF_K
, (uint8_t)puf
->unit
, 0, 3);
224 BPF_STORE_STMT(dynamic_insn
[len
],
225 BPF_LD
| BPF_W
| BPF_ABS
, addr_ep
);
227 BPF_STORE_JUMP(dynamic_insn
[len
],
228 BPF_JMP
| BPF_JEQ
| BPF_K
, htobe32(puf
->endpoint
), 0, 1);
231 BPF_STORE_STMT(dynamic_insn
[len
],
232 BPF_LD
| BPF_B
| BPF_ABS
, addr_off
);
234 BPF_STORE_JUMP(dynamic_insn
[len
],
235 BPF_JMP
| BPF_JEQ
| BPF_K
, (uint8_t)puf
->unit
, 0, 1);
239 if (puf
->endpoint
!= -1) {
240 BPF_STORE_STMT(dynamic_insn
[len
],
241 BPF_LD
| BPF_W
| BPF_ABS
, addr_ep
);
243 BPF_STORE_JUMP(dynamic_insn
[len
],
244 BPF_JMP
| BPF_JEQ
| BPF_K
, htobe32(puf
->endpoint
), 0, 1);
248 BPF_STORE_STMT(dynamic_insn
[len
],
249 BPF_RET
| BPF_K
, snapshot
);
253 BPF_STORE_STMT(dynamic_insn
[len
], BPF_RET
| BPF_K
, 0);
258 pprog
->bf_insns
= dynamic_insn
;
262 match_filter(int unit
, int endpoint
)
264 struct usb_filt
*puf
;
266 if (STAILQ_FIRST(&usb_filt_head
) == NULL
)
269 STAILQ_FOREACH(puf
, &usb_filt_head
, entry
) {
270 if ((puf
->unit
== -1 || puf
->unit
== unit
) &&
271 (puf
->endpoint
== -1 || puf
->endpoint
== endpoint
))
278 free_filter(struct bpf_program
*pprog
)
280 struct usb_filt
*puf
;
282 while ((puf
= STAILQ_FIRST(&usb_filt_head
)) != NULL
) {
283 STAILQ_REMOVE_HEAD(&usb_filt_head
, entry
);
286 free(pprog
->bf_insns
);
290 handle_sigint(int sig
)
297 #define FLAGS(x, name) \
298 (((x) & USBPF_FLAG_##name) ? #name "|" : "")
300 #define STATUS(x, name) \
301 (((x) & USBPF_STATUS_##name) ? #name "|" : "")
304 usb_errstr(uint32_t error
)
306 if (error
>= USB_ERR_MAX
|| errstr_table
[error
] == NULL
)
309 return (errstr_table
[error
]);
313 usb_speedstr(uint8_t speed
)
315 if (speed
>= USB_SPEED_MAX
|| speed_table
[speed
] == NULL
)
318 return (speed_table
[speed
]);
322 print_flags(uint32_t flags
)
324 printf(" flags %#x <%s%s%s%s%s%s%s%s%s0>\n",
326 FLAGS(flags
, FORCE_SHORT_XFER
),
327 FLAGS(flags
, SHORT_XFER_OK
),
328 FLAGS(flags
, SHORT_FRAMES_OK
),
329 FLAGS(flags
, PIPE_BOF
),
330 FLAGS(flags
, PROXY_BUFFER
),
331 FLAGS(flags
, EXT_BUFFER
),
332 FLAGS(flags
, MANUAL_STATUS
),
333 FLAGS(flags
, NO_PIPE_OK
),
334 FLAGS(flags
, STALL_PIPE
));
338 print_status(uint32_t status
)
340 printf(" status %#x <%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s0>\n",
342 STATUS(status
, OPEN
),
343 STATUS(status
, TRANSFERRING
),
344 STATUS(status
, DID_DMA_DELAY
),
345 STATUS(status
, DID_CLOSE
),
346 STATUS(status
, DRAINING
),
347 STATUS(status
, STARTED
),
348 STATUS(status
, BW_RECLAIMED
),
349 STATUS(status
, CONTROL_XFR
),
350 STATUS(status
, CONTROL_HDR
),
351 STATUS(status
, CONTROL_ACT
),
352 STATUS(status
, CONTROL_STALL
),
353 STATUS(status
, SHORT_FRAMES_OK
),
354 STATUS(status
, SHORT_XFER_OK
),
355 STATUS(status
, BDMA_ENABLE
),
356 STATUS(status
, BDMA_NO_POST_SYNC
),
357 STATUS(status
, BDMA_SETUP
),
358 STATUS(status
, ISOCHRONOUS_XFR
),
359 STATUS(status
, CURR_DMA_SET
),
360 STATUS(status
, CAN_CANCEL_IMMED
),
361 STATUS(status
, DOING_CALLBACK
));
365 * Dump a byte into hex format.
368 hexbyte(char *buf
, uint8_t temp
)
379 buf
[0] = 'A' + hi
- 10;
384 buf
[1] = 'A' + lo
- 10;
388 * Display a region in traditional hexdump format.
391 hexdump(const uint8_t *region
, uint32_t len
)
399 for (line
= region
; line
< (region
+ len
); line
+= 16) {
404 hexbyte(linebuf
+ i
+ 1, ((line
- region
) >> 8) & 0xFF);
405 hexbyte(linebuf
+ i
+ 3, (line
- region
) & 0xFF);
406 linebuf
[i
+ 5] = ' ';
407 linebuf
[i
+ 6] = ' ';
410 for (x
= 0; x
< 16; x
++) {
411 if ((line
+ x
) < (region
+ len
)) {
413 *(const u_int8_t
*)(line
+ x
));
416 linebuf
[i
+ 1] = '-';
418 linebuf
[i
+ 2] = ' ';
420 linebuf
[i
+ 3] = ' ';
427 linebuf
[i
+ 1] = '|';
429 for (x
= 0; x
< 16; x
++) {
430 if ((line
+ x
) < (region
+ len
)) {
431 c
= *(const u_int8_t
*)(line
+ x
);
433 if ((c
< ' ') || (c
> '~'))
449 print_apacket(const struct header_32
*hdr
, const uint8_t *ptr
, int ptr_len
)
452 struct usbpf_pkthdr up_temp
;
453 struct usbpf_pkthdr
*up
;
459 ptr
+= USBPF_HDR_LEN
;
460 ptr_len
-= USBPF_HDR_LEN
;
464 /* make sure we don't change the source buffer */
465 memcpy(&up_temp
, ptr
- USBPF_HDR_LEN
, sizeof(up_temp
));
469 * A packet from the kernel is based on little endian byte
472 up
->up_totlen
= le32toh(up
->up_totlen
);
473 up
->up_busunit
= le32toh(up
->up_busunit
);
474 up
->up_address
= le32toh(up
->up_address
);
475 up
->up_flags
= le32toh(up
->up_flags
);
476 up
->up_status
= le32toh(up
->up_status
);
477 up
->up_error
= le32toh(up
->up_error
);
478 up
->up_interval
= le32toh(up
->up_interval
);
479 up
->up_frames
= le32toh(up
->up_frames
);
480 up
->up_packet_size
= le32toh(up
->up_packet_size
);
481 up
->up_packet_count
= le32toh(up
->up_packet_count
);
482 up
->up_endpoint
= le32toh(up
->up_endpoint
);
484 if (!match_filter(up
->up_address
, up
->up_endpoint
))
487 tv
.tv_sec
= hdr
->ts_sec
;
488 tv
.tv_usec
= hdr
->ts_usec
;
489 tm
= localtime(&tv
.tv_sec
);
491 len
= strftime(buf
, sizeof(buf
), "%H:%M:%S", tm
);
494 printf("%.*s.%06ld usbus%d.%d %s-%s-EP=%08x,SPD=%s,NFR=%d,SLEN=%d,IVAL=%d%s%s\n",
495 (int)len
, buf
, tv
.tv_usec
,
496 (int)up
->up_busunit
, (int)up
->up_address
,
497 (up
->up_type
== USBPF_XFERTAP_SUBMIT
) ? "SUBM" : "DONE",
498 xfertype_table
[up
->up_xfertype
],
499 (unsigned int)up
->up_endpoint
,
500 usb_speedstr(up
->up_speed
),
502 (int)(up
->up_totlen
- USBPF_HDR_LEN
-
503 (USBPF_FRAME_HDR_LEN
* up
->up_frames
)),
504 (int)up
->up_interval
,
505 (up
->up_type
== USBPF_XFERTAP_DONE
) ? ",ERR=" : "",
506 (up
->up_type
== USBPF_XFERTAP_DONE
) ?
507 usb_errstr(up
->up_error
) : "");
510 if (verbose
>= 1 || b_arg
!= NULL
) {
511 for (x
= 0; x
!= up
->up_frames
; x
++) {
512 const struct usbpf_framehdr
*uf
;
516 uf
= (const struct usbpf_framehdr
*)ptr
;
517 ptr
+= USBPF_FRAME_HDR_LEN
;
518 ptr_len
-= USBPF_FRAME_HDR_LEN
;
522 framelen
= le32toh(uf
->length
);
523 flags
= le32toh(uf
->flags
);
526 printf(" frame[%u] %s %d bytes\n",
528 (flags
& USBPF_FRAMEFLAG_READ
) ? "READ" : "WRITE",
532 if (flags
& USBPF_FRAMEFLAG_DATA_FOLLOWS
) {
536 tot_frame_len
= USBPF_FRAME_ALIGN(framelen
);
538 ptr_len
-= tot_frame_len
;
540 if (tot_frame_len
< 0 ||
541 (int)framelen
< 0 || (int)ptr_len
< 0)
545 struct usbcap
*p
= &uc
;
547 ret
= write(p
->bfd
, ptr
, framelen
);
548 if (ret
!= (int)framelen
)
549 err(EXIT_FAILURE
, "Could not write binary data");
552 hexdump(ptr
, framelen
);
554 ptr
+= tot_frame_len
;
559 print_flags(up
->up_flags
);
561 print_status(up
->up_status
);
565 fix_packets(uint8_t *data
, const int datalen
)
567 struct header_32 temp
;
573 for (ptr
= data
; ptr
< (data
+ datalen
); ptr
= next
) {
575 const struct bpf_hdr
*hdr
;
577 hdr
= (const struct bpf_hdr
*)ptr
;
579 temp
.ts_sec
= htole32(hdr
->bh_tstamp
.tv_sec
);
580 temp
.ts_usec
= htole32(hdr
->bh_tstamp
.tv_usec
);
581 temp
.caplen
= htole32(hdr
->bh_caplen
);
582 temp
.datalen
= htole32(hdr
->bh_datalen
);
583 temp
.hdrlen
= hdr
->bh_hdrlen
;
584 temp
.align
= BPF_WORDALIGN(1);
586 hdrlen
= hdr
->bh_hdrlen
;
587 caplen
= hdr
->bh_caplen
;
589 if ((hdrlen
>= sizeof(temp
)) && (hdrlen
<= 255) &&
590 ((ptr
+ hdrlen
) <= (data
+ datalen
))) {
591 memcpy(ptr
, &temp
, sizeof(temp
));
592 memset(ptr
+ sizeof(temp
), 0, hdrlen
- sizeof(temp
));
594 err(EXIT_FAILURE
, "Invalid header length %d", hdrlen
);
597 next
= ptr
+ BPF_WORDALIGN(hdrlen
+ caplen
);
600 err(EXIT_FAILURE
, "Invalid length");
605 print_packets(uint8_t *data
, const int datalen
)
607 struct header_32 temp
;
611 for (ptr
= data
; ptr
< (data
+ datalen
); ptr
= next
) {
613 const struct header_32
*hdr32
;
615 hdr32
= (const struct header_32
*)ptr
;
617 temp
.ts_sec
= le32toh(hdr32
->ts_sec
);
618 temp
.ts_usec
= le32toh(hdr32
->ts_usec
);
619 temp
.caplen
= le32toh(hdr32
->caplen
);
620 temp
.datalen
= le32toh(hdr32
->datalen
);
621 temp
.hdrlen
= hdr32
->hdrlen
;
622 temp
.align
= hdr32
->align
;
624 next
= ptr
+ roundup2(temp
.hdrlen
+ temp
.caplen
, temp
.align
);
627 err(EXIT_FAILURE
, "Invalid length");
629 if (verbose
>= 0 || r_arg
!= NULL
|| b_arg
!= NULL
) {
630 print_apacket(&temp
, ptr
+
631 temp
.hdrlen
, temp
.caplen
);
638 write_packets(struct usbcap
*p
, const uint8_t *data
, const int datalen
)
640 int len
= htole32(datalen
);
643 ret
= write(p
->wfd
, &len
, sizeof(int));
644 if (ret
!= sizeof(int)) {
645 err(EXIT_FAILURE
, "Could not write length "
646 "field of USB data payload");
648 ret
= write(p
->wfd
, data
, datalen
);
649 if (ret
!= datalen
) {
650 err(EXIT_FAILURE
, "Could not write "
651 "complete USB data payload");
656 read_file(struct usbcap
*p
)
662 while ((ret
= read(p
->rfd
, &datalen
, sizeof(int))) == sizeof(int)) {
663 datalen
= le32toh(datalen
);
664 data
= malloc(datalen
);
666 errx(EX_SOFTWARE
, "Out of memory.");
667 ret
= read(p
->rfd
, data
, datalen
);
668 if (ret
!= datalen
) {
669 err(EXIT_FAILURE
, "Could not read complete "
673 fix_packets(data
, datalen
);
675 print_packets(data
, datalen
);
681 do_loop(struct usbcap
*p
)
685 while (doexit
== 0) {
686 cc
= read(p
->fd
, (uint8_t *)p
->buffer
, p
->bufsize
);
692 fprintf(stderr
, "read: %s\n", strerror(errno
));
700 fix_packets(p
->buffer
, cc
);
703 write_packets(p
, p
->buffer
, cc
);
704 print_packets(p
->buffer
, cc
);
709 init_rfile(struct usbcap
*p
)
711 struct usbcap_filehdr uf
;
714 p
->rfd
= open(r_arg
, O_RDONLY
);
716 err(EXIT_FAILURE
, "Could not open "
717 "'%s' for read", r_arg
);
719 ret
= read(p
->rfd
, &uf
, sizeof(uf
));
720 if (ret
!= sizeof(uf
)) {
721 err(EXIT_FAILURE
, "Could not read USB capture "
724 if (le32toh(uf
.magic
) != USBCAP_FILEHDR_MAGIC
) {
725 errx(EX_SOFTWARE
, "Invalid magic field(0x%08x) "
726 "in USB capture file header.",
727 (unsigned int)le32toh(uf
.magic
));
730 errx(EX_SOFTWARE
, "Invalid major version(%d) "
731 "field in USB capture file header.", (int)uf
.major
);
736 if (uf
.minor
!= 3 && uf
.minor
!= 2) {
737 errx(EX_SOFTWARE
, "Invalid minor version(%d) "
738 "field in USB capture file header.", (int)uf
.minor
);
743 init_wfile(struct usbcap
*p
)
745 struct usbcap_filehdr uf
;
748 p
->wfd
= open(w_arg
, O_CREAT
| O_TRUNC
| O_WRONLY
, S_IRUSR
| S_IWUSR
);
750 err(EXIT_FAILURE
, "Could not open "
751 "'%s' for write", w_arg
);
753 memset(&uf
, 0, sizeof(uf
));
754 uf
.magic
= htole32(USBCAP_FILEHDR_MAGIC
);
757 ret
= write(p
->wfd
, (const void *)&uf
, sizeof(uf
));
758 if (ret
!= sizeof(uf
)) {
759 err(EXIT_FAILURE
, "Could not write "
760 "USB capture header");
768 #define FMT " %-14s %s\n"
769 fprintf(stderr
, "usage: usbdump [options]\n");
770 fprintf(stderr
, FMT
, "-i <usbusX>", "Listen on USB bus interface");
771 fprintf(stderr
, FMT
, "-f <unit[.endpoint]>", "Specify a device and endpoint filter");
772 fprintf(stderr
, FMT
, "-r <file>", "Read the raw packets from file");
773 fprintf(stderr
, FMT
, "-s <snaplen>", "Snapshot bytes from each packet");
774 fprintf(stderr
, FMT
, "-v", "Increase the verbose level");
775 fprintf(stderr
, FMT
, "-b <file>", "Save raw version of all recorded data to file");
776 fprintf(stderr
, FMT
, "-w <file>", "Write the raw packets to file");
777 fprintf(stderr
, FMT
, "-h", "Display summary of command line options");
783 check_usb_pf_sysctl(void)
787 size_t no_pf_len
= sizeof(int);
789 /* check "hw.usb.no_pf" sysctl for 8- and 9- stable */
791 error
= sysctlbyname("hw.usb.no_pf", &no_pf_val
,
792 &no_pf_len
, NULL
, 0);
793 if (error
== 0 && no_pf_val
!= 0) {
794 warnx("The USB packet filter might be disabled.");
795 warnx("See the \"hw.usb.no_pf\" sysctl for more information.");
800 main(int argc
, char *argv
[])
803 struct bpf_program total_prog
;
805 struct bpf_version bv
;
806 struct usbcap
*p
= &uc
;
816 const char *optstring
;
819 optstring
= "b:hi:r:s:vw:f:";
820 while ((o
= getopt(argc
, argv
, optstring
)) != -1) {
830 snapshot
= strtol(optarg
, &pp
, 10);
832 if (pp
!= NULL
&& *pp
!= 0)
834 if (snapshot
== 0 && errno
== EINVAL
)
836 /* snapeshot == 0 is special */
851 filt_unit
= strtol(optarg
, &pp
, 10);
855 filt_ep
= strtol(pp
+ 1, &pp
, 10);
856 if (pp
!= NULL
&& *pp
!= 0)
858 } else if (*pp
!= 0) {
862 add_filter(filt_unit
, filt_ep
);
871 p
->bfd
= open(b_arg
, O_CREAT
| O_TRUNC
|
872 O_WRONLY
, S_IRUSR
| S_IWUSR
);
874 err(EXIT_FAILURE
, "Could not open "
875 "'%s' for write", b_arg
);
880 * Require more verbosity to print anything when -w or -b is
881 * specified on the command line:
883 if (w_arg
!= NULL
|| b_arg
!= NULL
)
891 check_usb_pf_sysctl();
893 p
->fd
= fd
= open("/dev/bpf", O_RDONLY
);
895 err(EXIT_FAILURE
, "Could not open BPF device");
897 if (ioctl(fd
, BIOCVERSION
, (caddr_t
)&bv
) < 0)
898 err(EXIT_FAILURE
, "BIOCVERSION ioctl failed");
900 if (bv
.bv_major
!= BPF_MAJOR_VERSION
||
901 bv
.bv_minor
< BPF_MINOR_VERSION
)
902 errx(EXIT_FAILURE
, "Kernel BPF filter out of date");
904 /* USB transfers can be greater than 64KByte */
907 /* clear ifr structure */
908 memset(&ifr
, 0, sizeof(ifr
));
910 /* Try to create usbusN interface if it is not available. */
911 s
= socket(AF_LOCAL
, SOCK_DGRAM
, 0);
913 errx(EXIT_FAILURE
, "Could not open a socket");
914 ifindex
= if_nametoindex(i_arg
);
916 (void)strlcpy(ifr
.ifr_name
, i_arg
, sizeof(ifr
.ifr_name
));
917 if (ioctl(s
, SIOCIFCREATE2
, &ifr
) < 0)
918 errx(EXIT_FAILURE
, "Invalid bus interface: %s", i_arg
);
921 for ( ; v
>= USBPF_HDR_LEN
; v
>>= 1) {
922 (void)ioctl(fd
, BIOCSBLEN
, (caddr_t
)&v
);
923 (void)strlcpy(ifr
.ifr_name
, i_arg
, sizeof(ifr
.ifr_name
));
924 if (ioctl(fd
, BIOCSETIF
, (caddr_t
)&ifr
) >= 0)
928 errx(EXIT_FAILURE
, "No buffer size worked.");
930 if (ioctl(fd
, BIOCGBLEN
, (caddr_t
)&v
) < 0)
931 err(EXIT_FAILURE
, "BIOCGBLEN ioctl failed");
934 p
->buffer
= (uint8_t *)malloc(p
->bufsize
);
935 if (p
->buffer
== NULL
)
936 errx(EX_SOFTWARE
, "Out of memory.");
938 make_filter(&total_prog
, snapshot
);
940 if (ioctl(p
->fd
, BIOCSETF
, (caddr_t
)&total_prog
) < 0)
941 err(EXIT_FAILURE
, "BIOCSETF ioctl failed");
943 free_filter(&total_prog
);
945 /* 1 second read timeout */
948 if (ioctl(p
->fd
, BIOCSRTIMEOUT
, (caddr_t
)&tv
) < 0)
949 err(EXIT_FAILURE
, "BIOCSRTIMEOUT ioctl failed");
951 (void)signal(SIGINT
, handle_sigint
);
955 if (ioctl(fd
, BIOCGSTATS
, (caddr_t
)&us
) < 0)
956 err(EXIT_FAILURE
, "BIOCGSTATS ioctl failed");
958 /* XXX what's difference between pkt_captured and us.us_recv? */
960 printf("%d packets captured\n", pkt_captured
);
961 printf("%d packets received by filter\n", us
.bs_recv
);
962 printf("%d packets dropped by kernel\n", us
.bs_drop
);
965 * Destroy the usbusN interface only if it was created by
966 * usbdump(8). Ignore when it was already destroyed.
968 if (ifindex
== 0 && if_nametoindex(i_arg
) > 0) {
969 (void)strlcpy(ifr
.ifr_name
, i_arg
, sizeof(ifr
.ifr_name
));
970 if (ioctl(s
, SIOCIFDESTROY
, &ifr
) < 0)
971 warn("SIOCIFDESTROY ioctl failed");
984 return (EXIT_SUCCESS
);