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
98 #define HEADER_ALIGN(x,a) (((x) + (a) - 1) & ~((a) - 1))
101 /* capture timestamp */
104 /* data length and alignment information */
111 static int doexit
= 0;
112 static int pkt_captured
= 0;
113 static int verbose
= 0;
115 static const char *i_arg
= "usbus0";
116 static const char *r_arg
= NULL
;
117 static const char *w_arg
= NULL
;
118 static const char *b_arg
= NULL
;
119 static struct usbcap uc
;
120 static const char *errstr_table
[USB_ERR_MAX
] = {
121 [USB_ERR_NORMAL_COMPLETION
] = "0",
122 [USB_ERR_PENDING_REQUESTS
] = "PENDING_REQUESTS",
123 [USB_ERR_NOT_STARTED
] = "NOT_STARTED",
124 [USB_ERR_INVAL
] = "INVAL",
125 [USB_ERR_NOMEM
] = "NOMEM",
126 [USB_ERR_CANCELLED
] = "CANCELLED",
127 [USB_ERR_BAD_ADDRESS
] = "BAD_ADDRESS",
128 [USB_ERR_BAD_BUFSIZE
] = "BAD_BUFSIZE",
129 [USB_ERR_BAD_FLAG
] = "BAD_FLAG",
130 [USB_ERR_NO_CALLBACK
] = "NO_CALLBACK",
131 [USB_ERR_IN_USE
] = "IN_USE",
132 [USB_ERR_NO_ADDR
] = "NO_ADDR",
133 [USB_ERR_NO_PIPE
] = "NO_PIPE",
134 [USB_ERR_ZERO_NFRAMES
] = "ZERO_NFRAMES",
135 [USB_ERR_ZERO_MAXP
] = "ZERO_MAXP",
136 [USB_ERR_SET_ADDR_FAILED
] = "SET_ADDR_FAILED",
137 [USB_ERR_NO_POWER
] = "NO_POWER",
138 [USB_ERR_TOO_DEEP
] = "TOO_DEEP",
139 [USB_ERR_IOERROR
] = "IOERROR",
140 [USB_ERR_NOT_CONFIGURED
] = "NOT_CONFIGURED",
141 [USB_ERR_TIMEOUT
] = "TIMEOUT",
142 [USB_ERR_SHORT_XFER
] = "SHORT_XFER",
143 [USB_ERR_STALLED
] = "STALLED",
144 [USB_ERR_INTERRUPTED
] = "INTERRUPTED",
145 [USB_ERR_DMA_LOAD_FAILED
] = "DMA_LOAD_FAILED",
146 [USB_ERR_BAD_CONTEXT
] = "BAD_CONTEXT",
147 [USB_ERR_NO_ROOT_HUB
] = "NO_ROOT_HUB",
148 [USB_ERR_NO_INTR_THREAD
] = "NO_INTR_THREAD",
149 [USB_ERR_NOT_LOCKED
] = "NOT_LOCKED",
152 static const char *xfertype_table
[4] = {
153 [UE_CONTROL
] = "CTRL",
154 [UE_ISOCHRONOUS
] = "ISOC",
156 [UE_INTERRUPT
] = "INTR"
159 static const char *speed_table
[USB_SPEED_MAX
] = {
160 [USB_SPEED_FULL
] = "FULL",
161 [USB_SPEED_HIGH
] = "HIGH",
162 [USB_SPEED_LOW
] = "LOW",
163 [USB_SPEED_VARIABLE
] = "VARI",
164 [USB_SPEED_SUPER
] = "SUPER",
167 static STAILQ_HEAD(,usb_filt
) usb_filt_head
=
168 STAILQ_HEAD_INITIALIZER(usb_filt_head
);
171 add_filter(int usb_filt_unit
, int usb_filt_ep
)
173 struct usb_filt
*puf
;
175 puf
= malloc(sizeof(struct usb_filt
));
177 errx(EX_SOFTWARE
, "Out of memory.");
179 puf
->unit
= usb_filt_unit
;
180 puf
->endpoint
= usb_filt_ep
;
182 STAILQ_INSERT_TAIL(&usb_filt_head
, puf
, entry
);
186 make_filter(struct bpf_program
*pprog
, int snapshot
)
188 struct usb_filt
*puf
;
189 struct bpf_insn
*dynamic_insn
;
194 STAILQ_FOREACH(puf
, &usb_filt_head
, entry
)
197 dynamic_insn
= malloc(((len
* 5) + 1) * sizeof(struct bpf_insn
));
199 if (dynamic_insn
== NULL
)
200 errx(EX_SOFTWARE
, "Out of memory.");
205 /* accept all packets */
207 BPF_STORE_STMT(dynamic_insn
[0], BPF_RET
| BPF_K
, snapshot
);
214 STAILQ_FOREACH(puf
, &usb_filt_head
, entry
) {
215 const int addr_off
= (uintptr_t)&((struct usbpf_pkthdr
*)0)->up_address
;
216 const int addr_ep
= (uintptr_t)&((struct usbpf_pkthdr
*)0)->up_endpoint
;
218 if (puf
->unit
!= -1) {
219 if (puf
->endpoint
!= -1) {
220 BPF_STORE_STMT(dynamic_insn
[len
],
221 BPF_LD
| BPF_B
| BPF_ABS
, addr_off
);
223 BPF_STORE_JUMP(dynamic_insn
[len
],
224 BPF_JMP
| BPF_JEQ
| BPF_K
, (uint8_t)puf
->unit
, 0, 3);
226 BPF_STORE_STMT(dynamic_insn
[len
],
227 BPF_LD
| BPF_W
| BPF_ABS
, addr_ep
);
229 BPF_STORE_JUMP(dynamic_insn
[len
],
230 BPF_JMP
| BPF_JEQ
| BPF_K
, htobe32(puf
->endpoint
), 0, 1);
233 BPF_STORE_STMT(dynamic_insn
[len
],
234 BPF_LD
| BPF_B
| BPF_ABS
, addr_off
);
236 BPF_STORE_JUMP(dynamic_insn
[len
],
237 BPF_JMP
| BPF_JEQ
| BPF_K
, (uint8_t)puf
->unit
, 0, 1);
241 if (puf
->endpoint
!= -1) {
242 BPF_STORE_STMT(dynamic_insn
[len
],
243 BPF_LD
| BPF_W
| BPF_ABS
, addr_ep
);
245 BPF_STORE_JUMP(dynamic_insn
[len
],
246 BPF_JMP
| BPF_JEQ
| BPF_K
, htobe32(puf
->endpoint
), 0, 1);
250 BPF_STORE_STMT(dynamic_insn
[len
],
251 BPF_RET
| BPF_K
, snapshot
);
255 BPF_STORE_STMT(dynamic_insn
[len
], BPF_RET
| BPF_K
, 0);
260 pprog
->bf_insns
= dynamic_insn
;
264 match_filter(int unit
, int endpoint
)
266 struct usb_filt
*puf
;
268 if (STAILQ_FIRST(&usb_filt_head
) == NULL
)
271 STAILQ_FOREACH(puf
, &usb_filt_head
, entry
) {
272 if ((puf
->unit
== -1 || puf
->unit
== unit
) &&
273 (puf
->endpoint
== -1 || puf
->endpoint
== endpoint
))
280 free_filter(struct bpf_program
*pprog
)
282 struct usb_filt
*puf
;
284 while ((puf
= STAILQ_FIRST(&usb_filt_head
)) != NULL
) {
285 STAILQ_REMOVE_HEAD(&usb_filt_head
, entry
);
288 free(pprog
->bf_insns
);
292 handle_sigint(int sig
)
299 #define FLAGS(x, name) \
300 (((x) & USBPF_FLAG_##name) ? #name "|" : "")
302 #define STATUS(x, name) \
303 (((x) & USBPF_STATUS_##name) ? #name "|" : "")
306 usb_errstr(uint32_t error
)
308 if (error
>= USB_ERR_MAX
|| errstr_table
[error
] == NULL
)
311 return (errstr_table
[error
]);
315 usb_speedstr(uint8_t speed
)
317 if (speed
>= USB_SPEED_MAX
|| speed_table
[speed
] == NULL
)
320 return (speed_table
[speed
]);
324 print_flags(uint32_t flags
)
326 printf(" flags %#x <%s%s%s%s%s%s%s%s%s0>\n",
328 FLAGS(flags
, FORCE_SHORT_XFER
),
329 FLAGS(flags
, SHORT_XFER_OK
),
330 FLAGS(flags
, SHORT_FRAMES_OK
),
331 FLAGS(flags
, PIPE_BOF
),
332 FLAGS(flags
, PROXY_BUFFER
),
333 FLAGS(flags
, EXT_BUFFER
),
334 FLAGS(flags
, MANUAL_STATUS
),
335 FLAGS(flags
, NO_PIPE_OK
),
336 FLAGS(flags
, STALL_PIPE
));
340 print_status(uint32_t status
)
342 printf(" status %#x <%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s0>\n",
344 STATUS(status
, OPEN
),
345 STATUS(status
, TRANSFERRING
),
346 STATUS(status
, DID_DMA_DELAY
),
347 STATUS(status
, DID_CLOSE
),
348 STATUS(status
, DRAINING
),
349 STATUS(status
, STARTED
),
350 STATUS(status
, BW_RECLAIMED
),
351 STATUS(status
, CONTROL_XFR
),
352 STATUS(status
, CONTROL_HDR
),
353 STATUS(status
, CONTROL_ACT
),
354 STATUS(status
, CONTROL_STALL
),
355 STATUS(status
, SHORT_FRAMES_OK
),
356 STATUS(status
, SHORT_XFER_OK
),
357 STATUS(status
, BDMA_ENABLE
),
358 STATUS(status
, BDMA_NO_POST_SYNC
),
359 STATUS(status
, BDMA_SETUP
),
360 STATUS(status
, ISOCHRONOUS_XFR
),
361 STATUS(status
, CURR_DMA_SET
),
362 STATUS(status
, CAN_CANCEL_IMMED
),
363 STATUS(status
, DOING_CALLBACK
));
367 * Dump a byte into hex format.
370 hexbyte(char *buf
, uint8_t temp
)
381 buf
[0] = 'A' + hi
- 10;
386 buf
[1] = 'A' + lo
- 10;
390 * Display a region in traditional hexdump format.
393 hexdump(const uint8_t *region
, uint32_t len
)
401 for (line
= region
; line
< (region
+ len
); line
+= 16) {
406 hexbyte(linebuf
+ i
+ 1, ((line
- region
) >> 8) & 0xFF);
407 hexbyte(linebuf
+ i
+ 3, (line
- region
) & 0xFF);
408 linebuf
[i
+ 5] = ' ';
409 linebuf
[i
+ 6] = ' ';
412 for (x
= 0; x
< 16; x
++) {
413 if ((line
+ x
) < (region
+ len
)) {
415 *(const u_int8_t
*)(line
+ x
));
418 linebuf
[i
+ 1] = '-';
420 linebuf
[i
+ 2] = ' ';
422 linebuf
[i
+ 3] = ' ';
429 linebuf
[i
+ 1] = '|';
431 for (x
= 0; x
< 16; x
++) {
432 if ((line
+ x
) < (region
+ len
)) {
433 c
= *(const u_int8_t
*)(line
+ x
);
435 if ((c
< ' ') || (c
> '~'))
451 print_apacket(const struct header_32
*hdr
, const uint8_t *ptr
, int ptr_len
)
454 struct usbpf_pkthdr up_temp
;
455 struct usbpf_pkthdr
*up
;
461 ptr
+= USBPF_HDR_LEN
;
462 ptr_len
-= USBPF_HDR_LEN
;
466 /* make sure we don't change the source buffer */
467 memcpy(&up_temp
, ptr
- USBPF_HDR_LEN
, sizeof(up_temp
));
471 * A packet from the kernel is based on little endian byte
474 up
->up_totlen
= le32toh(up
->up_totlen
);
475 up
->up_busunit
= le32toh(up
->up_busunit
);
476 up
->up_address
= le32toh(up
->up_address
);
477 up
->up_flags
= le32toh(up
->up_flags
);
478 up
->up_status
= le32toh(up
->up_status
);
479 up
->up_error
= le32toh(up
->up_error
);
480 up
->up_interval
= le32toh(up
->up_interval
);
481 up
->up_frames
= le32toh(up
->up_frames
);
482 up
->up_packet_size
= le32toh(up
->up_packet_size
);
483 up
->up_packet_count
= le32toh(up
->up_packet_count
);
484 up
->up_endpoint
= le32toh(up
->up_endpoint
);
486 if (!match_filter(up
->up_address
, up
->up_endpoint
))
489 tv
.tv_sec
= hdr
->ts_sec
;
490 tv
.tv_usec
= hdr
->ts_usec
;
491 tm
= localtime(&tv
.tv_sec
);
493 len
= strftime(buf
, sizeof(buf
), "%H:%M:%S", tm
);
496 printf("%.*s.%06ld usbus%d.%d %s-%s-EP=%08x,SPD=%s,NFR=%d,SLEN=%d,IVAL=%d%s%s\n",
497 (int)len
, buf
, tv
.tv_usec
,
498 (int)up
->up_busunit
, (int)up
->up_address
,
499 (up
->up_type
== USBPF_XFERTAP_SUBMIT
) ? "SUBM" : "DONE",
500 xfertype_table
[up
->up_xfertype
],
501 (unsigned int)up
->up_endpoint
,
502 usb_speedstr(up
->up_speed
),
504 (int)(up
->up_totlen
- USBPF_HDR_LEN
-
505 (USBPF_FRAME_HDR_LEN
* up
->up_frames
)),
506 (int)up
->up_interval
,
507 (up
->up_type
== USBPF_XFERTAP_DONE
) ? ",ERR=" : "",
508 (up
->up_type
== USBPF_XFERTAP_DONE
) ?
509 usb_errstr(up
->up_error
) : "");
512 if (verbose
>= 1 || b_arg
!= NULL
) {
513 for (x
= 0; x
!= up
->up_frames
; x
++) {
514 const struct usbpf_framehdr
*uf
;
518 uf
= (const struct usbpf_framehdr
*)ptr
;
519 ptr
+= USBPF_FRAME_HDR_LEN
;
520 ptr_len
-= USBPF_FRAME_HDR_LEN
;
524 framelen
= le32toh(uf
->length
);
525 flags
= le32toh(uf
->flags
);
528 printf(" frame[%u] %s %d bytes\n",
530 (flags
& USBPF_FRAMEFLAG_READ
) ? "READ" : "WRITE",
534 if (flags
& USBPF_FRAMEFLAG_DATA_FOLLOWS
) {
538 tot_frame_len
= USBPF_FRAME_ALIGN(framelen
);
540 ptr_len
-= tot_frame_len
;
542 if (tot_frame_len
< 0 ||
543 (int)framelen
< 0 || (int)ptr_len
< 0)
547 struct usbcap
*p
= &uc
;
549 ret
= write(p
->bfd
, ptr
, framelen
);
550 if (ret
!= (int)framelen
)
551 err(EXIT_FAILURE
, "Could not write binary data");
554 hexdump(ptr
, framelen
);
556 ptr
+= tot_frame_len
;
561 print_flags(up
->up_flags
);
563 print_status(up
->up_status
);
567 fix_packets(uint8_t *data
, const int datalen
)
569 struct header_32 temp
;
575 for (ptr
= data
; ptr
< (data
+ datalen
); ptr
= next
) {
577 const struct bpf_hdr
*hdr
;
579 hdr
= (const struct bpf_hdr
*)ptr
;
581 temp
.ts_sec
= htole32(hdr
->bh_tstamp
.tv_sec
);
582 temp
.ts_usec
= htole32(hdr
->bh_tstamp
.tv_usec
);
583 temp
.caplen
= htole32(hdr
->bh_caplen
);
584 temp
.datalen
= htole32(hdr
->bh_datalen
);
585 temp
.hdrlen
= hdr
->bh_hdrlen
;
586 temp
.align
= BPF_WORDALIGN(1);
588 hdrlen
= hdr
->bh_hdrlen
;
589 caplen
= hdr
->bh_caplen
;
591 if ((hdrlen
>= sizeof(temp
)) && (hdrlen
<= 255) &&
592 ((ptr
+ hdrlen
) <= (data
+ datalen
))) {
593 memcpy(ptr
, &temp
, sizeof(temp
));
594 memset(ptr
+ sizeof(temp
), 0, hdrlen
- sizeof(temp
));
596 err(EXIT_FAILURE
, "Invalid header length %d", hdrlen
);
599 next
= ptr
+ BPF_WORDALIGN(hdrlen
+ caplen
);
602 err(EXIT_FAILURE
, "Invalid length");
607 print_packets(uint8_t *data
, const int datalen
)
609 struct header_32 temp
;
613 for (ptr
= data
; ptr
< (data
+ datalen
); ptr
= next
) {
615 const struct header_32
*hdr32
;
617 hdr32
= (const struct header_32
*)ptr
;
619 temp
.ts_sec
= le32toh(hdr32
->ts_sec
);
620 temp
.ts_usec
= le32toh(hdr32
->ts_usec
);
621 temp
.caplen
= le32toh(hdr32
->caplen
);
622 temp
.datalen
= le32toh(hdr32
->datalen
);
623 temp
.hdrlen
= hdr32
->hdrlen
;
624 temp
.align
= hdr32
->align
;
626 next
= ptr
+ HEADER_ALIGN(temp
.hdrlen
+ temp
.caplen
, temp
.align
);
629 err(EXIT_FAILURE
, "Invalid length");
631 if (verbose
>= 0 || r_arg
!= NULL
|| b_arg
!= NULL
) {
632 print_apacket(&temp
, ptr
+
633 temp
.hdrlen
, temp
.caplen
);
640 write_packets(struct usbcap
*p
, const uint8_t *data
, const int datalen
)
642 int len
= htole32(datalen
);
645 ret
= write(p
->wfd
, &len
, sizeof(int));
646 if (ret
!= sizeof(int)) {
647 err(EXIT_FAILURE
, "Could not write length "
648 "field of USB data payload");
650 ret
= write(p
->wfd
, data
, datalen
);
651 if (ret
!= datalen
) {
652 err(EXIT_FAILURE
, "Could not write "
653 "complete USB data payload");
658 read_file(struct usbcap
*p
)
664 while ((ret
= read(p
->rfd
, &datalen
, sizeof(int))) == sizeof(int)) {
665 datalen
= le32toh(datalen
);
666 data
= malloc(datalen
);
668 errx(EX_SOFTWARE
, "Out of memory.");
669 ret
= read(p
->rfd
, data
, datalen
);
670 if (ret
!= datalen
) {
671 err(EXIT_FAILURE
, "Could not read complete "
675 fix_packets(data
, datalen
);
677 print_packets(data
, datalen
);
683 do_loop(struct usbcap
*p
)
687 while (doexit
== 0) {
688 cc
= read(p
->fd
, (uint8_t *)p
->buffer
, p
->bufsize
);
694 fprintf(stderr
, "read: %s\n", strerror(errno
));
702 fix_packets(p
->buffer
, cc
);
705 write_packets(p
, p
->buffer
, cc
);
706 print_packets(p
->buffer
, cc
);
711 init_rfile(struct usbcap
*p
)
713 struct usbcap_filehdr uf
;
716 p
->rfd
= open(r_arg
, O_RDONLY
);
718 err(EXIT_FAILURE
, "Could not open "
719 "'%s' for read", r_arg
);
721 ret
= read(p
->rfd
, &uf
, sizeof(uf
));
722 if (ret
!= sizeof(uf
)) {
723 err(EXIT_FAILURE
, "Could not read USB capture "
726 if (le32toh(uf
.magic
) != USBCAP_FILEHDR_MAGIC
) {
727 errx(EX_SOFTWARE
, "Invalid magic field(0x%08x) "
728 "in USB capture file header.",
729 (unsigned int)le32toh(uf
.magic
));
732 errx(EX_SOFTWARE
, "Invalid major version(%d) "
733 "field in USB capture file header.", (int)uf
.major
);
738 if (uf
.minor
!= 3 && uf
.minor
!= 2) {
739 errx(EX_SOFTWARE
, "Invalid minor version(%d) "
740 "field in USB capture file header.", (int)uf
.minor
);
745 init_wfile(struct usbcap
*p
)
747 struct usbcap_filehdr uf
;
750 p
->wfd
= open(w_arg
, O_CREAT
| O_TRUNC
| O_WRONLY
, S_IRUSR
| S_IWUSR
);
752 err(EXIT_FAILURE
, "Could not open "
753 "'%s' for write", w_arg
);
755 memset(&uf
, 0, sizeof(uf
));
756 uf
.magic
= htole32(USBCAP_FILEHDR_MAGIC
);
759 ret
= write(p
->wfd
, (const void *)&uf
, sizeof(uf
));
760 if (ret
!= sizeof(uf
)) {
761 err(EXIT_FAILURE
, "Could not write "
762 "USB capture header");
770 #define FMT " %-14s %s\n"
771 fprintf(stderr
, "usage: usbdump [options]\n");
772 fprintf(stderr
, FMT
, "-i <usbusX>", "Listen on USB bus interface");
773 fprintf(stderr
, FMT
, "-f <unit[.endpoint]>", "Specify a device and endpoint filter");
774 fprintf(stderr
, FMT
, "-r <file>", "Read the raw packets from file");
775 fprintf(stderr
, FMT
, "-s <snaplen>", "Snapshot bytes from each packet");
776 fprintf(stderr
, FMT
, "-v", "Increase the verbose level");
777 fprintf(stderr
, FMT
, "-b <file>", "Save raw version of all recorded data to file");
778 fprintf(stderr
, FMT
, "-w <file>", "Write the raw packets to file");
779 fprintf(stderr
, FMT
, "-h", "Display summary of command line options");
785 check_usb_pf_sysctl(void)
789 size_t no_pf_len
= sizeof(int);
791 /* check "hw.usb.no_pf" sysctl for 8- and 9- stable */
793 error
= sysctlbyname("hw.usb.no_pf", &no_pf_val
,
794 &no_pf_len
, NULL
, 0);
795 if (error
== 0 && no_pf_val
!= 0) {
796 warnx("The USB packet filter might be disabled.");
797 warnx("See the \"hw.usb.no_pf\" sysctl for more information.");
802 main(int argc
, char *argv
[])
805 struct bpf_program total_prog
;
807 struct bpf_version bv
;
808 struct usbcap
*p
= &uc
;
818 const char *optstring
;
821 optstring
= "b:hi:r:s:vw:f:";
822 while ((o
= getopt(argc
, argv
, optstring
)) != -1) {
832 snapshot
= strtol(optarg
, &pp
, 10);
834 if (pp
!= NULL
&& *pp
!= 0)
836 if (snapshot
== 0 && errno
== EINVAL
)
838 /* snapeshot == 0 is special */
853 filt_unit
= strtol(optarg
, &pp
, 10);
857 filt_ep
= strtol(pp
+ 1, &pp
, 10);
858 if (pp
!= NULL
&& *pp
!= 0)
860 } else if (*pp
!= 0) {
864 add_filter(filt_unit
, filt_ep
);
873 p
->bfd
= open(b_arg
, O_CREAT
| O_TRUNC
|
874 O_WRONLY
, S_IRUSR
| S_IWUSR
);
876 err(EXIT_FAILURE
, "Could not open "
877 "'%s' for write", b_arg
);
882 * Require more verbosity to print anything when -w or -b is
883 * specified on the command line:
885 if (w_arg
!= NULL
|| b_arg
!= NULL
)
893 check_usb_pf_sysctl();
895 p
->fd
= fd
= open("/dev/bpf", O_RDONLY
);
897 err(EXIT_FAILURE
, "Could not open BPF device");
899 if (ioctl(fd
, BIOCVERSION
, (caddr_t
)&bv
) < 0)
900 err(EXIT_FAILURE
, "BIOCVERSION ioctl failed");
902 if (bv
.bv_major
!= BPF_MAJOR_VERSION
||
903 bv
.bv_minor
< BPF_MINOR_VERSION
)
904 errx(EXIT_FAILURE
, "Kernel BPF filter out of date");
906 /* USB transfers can be greater than 64KByte */
909 /* clear ifr structure */
910 memset(&ifr
, 0, sizeof(ifr
));
912 /* Try to create usbusN interface if it is not available. */
913 s
= socket(AF_LOCAL
, SOCK_DGRAM
, 0);
915 errx(EXIT_FAILURE
, "Could not open a socket");
916 ifindex
= if_nametoindex(i_arg
);
918 (void)strlcpy(ifr
.ifr_name
, i_arg
, sizeof(ifr
.ifr_name
));
919 if (ioctl(s
, SIOCIFCREATE2
, &ifr
) < 0)
920 errx(EXIT_FAILURE
, "Invalid bus interface: %s", i_arg
);
923 for ( ; v
>= USBPF_HDR_LEN
; v
>>= 1) {
924 (void)ioctl(fd
, BIOCSBLEN
, (caddr_t
)&v
);
925 (void)strlcpy(ifr
.ifr_name
, i_arg
, sizeof(ifr
.ifr_name
));
926 if (ioctl(fd
, BIOCSETIF
, (caddr_t
)&ifr
) >= 0)
930 errx(EXIT_FAILURE
, "No buffer size worked.");
932 if (ioctl(fd
, BIOCGBLEN
, (caddr_t
)&v
) < 0)
933 err(EXIT_FAILURE
, "BIOCGBLEN ioctl failed");
936 p
->buffer
= (uint8_t *)malloc(p
->bufsize
);
937 if (p
->buffer
== NULL
)
938 errx(EX_SOFTWARE
, "Out of memory.");
940 make_filter(&total_prog
, snapshot
);
942 if (ioctl(p
->fd
, BIOCSETF
, (caddr_t
)&total_prog
) < 0)
943 err(EXIT_FAILURE
, "BIOCSETF ioctl failed");
945 free_filter(&total_prog
);
947 /* 1 second read timeout */
950 if (ioctl(p
->fd
, BIOCSRTIMEOUT
, (caddr_t
)&tv
) < 0)
951 err(EXIT_FAILURE
, "BIOCSRTIMEOUT ioctl failed");
953 (void)signal(SIGINT
, handle_sigint
);
957 if (ioctl(fd
, BIOCGSTATS
, (caddr_t
)&us
) < 0)
958 err(EXIT_FAILURE
, "BIOCGSTATS ioctl failed");
960 /* XXX what's difference between pkt_captured and us.us_recv? */
962 printf("%d packets captured\n", pkt_captured
);
963 printf("%d packets received by filter\n", us
.bs_recv
);
964 printf("%d packets dropped by kernel\n", us
.bs_drop
);
967 * Destroy the usbusN interface only if it was created by
968 * usbdump(8). Ignore when it was already destroyed.
970 if (ifindex
== 0 && if_nametoindex(i_arg
) > 0) {
971 (void)strlcpy(ifr
.ifr_name
, i_arg
, sizeof(ifr
.ifr_name
));
972 if (ioctl(s
, SIOCIFDESTROY
, &ifr
) < 0)
973 warn("SIOCIFDESTROY ioctl failed");
986 return (EXIT_SUCCESS
);