xref: /dragonfly/usr.sbin/usbdump/usbdump.c (revision df052c2a9588fe12c7a2df4e61e2bfa3f3e16ce0)
1 /*-
2  * Copyright (c) 2010 Weongyo Jeong <weongyo@freebsd.org>
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  * 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.
15  *
16  * NO WARRANTY
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, MERCHANTABILITY
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.
28  *
29  * $FreeBSD: head/usr.sbin/usbdump/usbdump.c 260978 2014-01-21 08:24:12Z hselasky $
30  */
31 
32 #include <sys/param.h>
33 #include <sys/endian.h>
34 #include <sys/ioctl.h>
35 #include <sys/socket.h>
36 #include <sys/stat.h>
37 #include <sys/sysctl.h>
38 #include <sys/utsname.h>
39 #include <sys/queue.h>
40 #include <net/if.h>
41 #include <net/bpf.h>
42 #include <bus/u4b/usb.h>
43 #include <bus/u4b/usb_pf.h>
44 #include <bus/u4b/usbdi.h>
45 #include <errno.h>
46 #include <fcntl.h>
47 #include <limits.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <stdint.h>
51 #include <string.h>
52 #include <time.h>
53 #include <unistd.h>
54 #include <sysexits.h>
55 #include <err.h>
56 
57 #define   BPF_STORE_JUMP(x,_c,_k,_jt,_jf) do {    \
58   (x).code = (_c);                                \
59   (x).k = (_k);                                             \
60   (x).jt = (_jt);                                 \
61   (x).jf = (_jf);                                 \
62 } while (0)
63 
64 #define   BPF_STORE_STMT(x,_c,_k) do {            \
65   (x).code = (_c);                                \
66   (x).k = (_k);                                             \
67   (x).jt = 0;                                               \
68   (x).jf = 0;                                               \
69 } while (0)
70 
71 struct usb_filt {
72           STAILQ_ENTRY(usb_filt) entry;
73           int unit;
74           int endpoint;
75 };
76 
77 struct usbcap {
78           int                 fd;                 /* fd for /dev/usbpf */
79           uint32_t  bufsize;
80           uint8_t             *buffer;
81 
82           /* for -w option */
83           int                 wfd;
84           /* for -r option */
85           int                 rfd;
86           /* for -b option */
87           int                 bfd;
88 };
89 
90 struct usbcap_filehdr {
91           uint32_t  magic;
92 #define   USBCAP_FILEHDR_MAGIC          0x9a90000e
93           uint8_t             major;
94           uint8_t             minor;
95           uint8_t             reserved[26];
96 } __packed;
97 
98 struct header_32 {
99           /* capture timestamp */
100           uint32_t ts_sec;
101           uint32_t ts_usec;
102           /* data length and alignment information */
103           uint32_t caplen;
104           uint32_t datalen;
105           uint8_t hdrlen;
106           uint8_t align;
107 } __packed;
108 
109 static int doexit = 0;
110 static int pkt_captured = 0;
111 static int verbose = 0;
112 static int uf_minor;
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",
148 };
149 
150 static const char *xfertype_table[4] = {
151           [UE_CONTROL]                            = "CTRL",
152           [UE_ISOCHRONOUS]              = "ISOC",
153           [UE_BULK]                     = "BULK",
154           [UE_INTERRUPT]                          = "INTR"
155 };
156 
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",
163 };
164 
165 static STAILQ_HEAD(,usb_filt) usb_filt_head =
166     STAILQ_HEAD_INITIALIZER(usb_filt_head);
167 
168 static void
add_filter(int usb_filt_unit,int usb_filt_ep)169 add_filter(int usb_filt_unit, int usb_filt_ep)
170 {
171           struct usb_filt *puf;
172 
173           puf = malloc(sizeof(struct usb_filt));
174           if (puf == NULL)
175                     errx(EX_SOFTWARE, "Out of memory.");
176 
177           puf->unit = usb_filt_unit;
178           puf->endpoint = usb_filt_ep;
179 
180           STAILQ_INSERT_TAIL(&usb_filt_head, puf, entry);
181 }
182 
183 static void
make_filter(struct bpf_program * pprog,int snapshot)184 make_filter(struct bpf_program *pprog, int snapshot)
185 {
186           struct usb_filt *puf;
187           struct bpf_insn *dynamic_insn;
188           int len;
189 
190           len = 0;
191 
192           STAILQ_FOREACH(puf, &usb_filt_head, entry)
193                     len++;
194 
195           dynamic_insn = malloc(((len * 5) + 1) * sizeof(struct bpf_insn));
196 
197           if (dynamic_insn == NULL)
198                     errx(EX_SOFTWARE, "Out of memory.");
199 
200           len++;
201 
202           if (len == 1) {
203                     /* accept all packets */
204 
205                     BPF_STORE_STMT(dynamic_insn[0], BPF_RET | BPF_K, snapshot);
206 
207                     goto done;
208           }
209 
210           len = 0;
211 
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;
215 
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);
220                                         len++;
221                                         BPF_STORE_JUMP(dynamic_insn[len],
222                                             BPF_JMP | BPF_JEQ | BPF_K, (uint8_t)puf->unit, 0, 3);
223                                         len++;
224                                         BPF_STORE_STMT(dynamic_insn[len],
225                                             BPF_LD | BPF_W | BPF_ABS, addr_ep);
226                                         len++;
227                                         BPF_STORE_JUMP(dynamic_insn[len],
228                                             BPF_JMP | BPF_JEQ | BPF_K, htobe32(puf->endpoint), 0, 1);
229                                         len++;
230                               } else {
231                                         BPF_STORE_STMT(dynamic_insn[len],
232                                             BPF_LD | BPF_B | BPF_ABS, addr_off);
233                                         len++;
234                                         BPF_STORE_JUMP(dynamic_insn[len],
235                                             BPF_JMP | BPF_JEQ | BPF_K, (uint8_t)puf->unit, 0, 1);
236                                         len++;
237                               }
238                     } else {
239                               if (puf->endpoint != -1) {
240                                         BPF_STORE_STMT(dynamic_insn[len],
241                                             BPF_LD | BPF_W | BPF_ABS, addr_ep);
242                                         len++;
243                                         BPF_STORE_JUMP(dynamic_insn[len],
244                                             BPF_JMP | BPF_JEQ | BPF_K, htobe32(puf->endpoint), 0, 1);
245                                         len++;
246                               }
247                     }
248                     BPF_STORE_STMT(dynamic_insn[len],
249                         BPF_RET | BPF_K, snapshot);
250                     len++;
251           }
252 
253           BPF_STORE_STMT(dynamic_insn[len], BPF_RET | BPF_K, 0);
254           len++;
255 
256 done:
257           pprog->bf_len = len;
258           pprog->bf_insns = dynamic_insn;
259 }
260 
261 static int
match_filter(int unit,int endpoint)262 match_filter(int unit, int endpoint)
263 {
264           struct usb_filt *puf;
265 
266           if (STAILQ_FIRST(&usb_filt_head) == NULL)
267                     return (1);
268 
269           STAILQ_FOREACH(puf, &usb_filt_head, entry) {
270                     if ((puf->unit == -1 || puf->unit == unit) &&
271                         (puf->endpoint == -1 || puf->endpoint == endpoint))
272                               return (1);
273           }
274           return (0);
275 }
276 
277 static void
free_filter(struct bpf_program * pprog)278 free_filter(struct bpf_program *pprog)
279 {
280           struct usb_filt *puf;
281 
282           while ((puf = STAILQ_FIRST(&usb_filt_head)) != NULL) {
283                     STAILQ_REMOVE_HEAD(&usb_filt_head, entry);
284                     free(puf);
285           }
286           free(pprog->bf_insns);
287 }
288 
289 static void
handle_sigint(int sig)290 handle_sigint(int sig)
291 {
292 
293           (void)sig;
294           doexit = 1;
295 }
296 
297 #define   FLAGS(x, name)      \
298           (((x) & USBPF_FLAG_##name) ? #name "|" : "")
299 
300 #define   STATUS(x, name) \
301           (((x) & USBPF_STATUS_##name) ? #name "|" : "")
302 
303 static const char *
usb_errstr(uint32_t error)304 usb_errstr(uint32_t error)
305 {
306           if (error >= USB_ERR_MAX || errstr_table[error] == NULL)
307                     return ("UNKNOWN");
308           else
309                     return (errstr_table[error]);
310 }
311 
312 static const char *
usb_speedstr(uint8_t speed)313 usb_speedstr(uint8_t speed)
314 {
315           if (speed >= USB_SPEED_MAX  || speed_table[speed] == NULL)
316                     return ("UNKNOWN");
317           else
318                     return (speed_table[speed]);
319 }
320 
321 static void
print_flags(uint32_t flags)322 print_flags(uint32_t flags)
323 {
324           printf(" flags %#x <%s%s%s%s%s%s%s%s%s0>\n",
325               flags,
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));
335 }
336 
337 static void
print_status(uint32_t status)338 print_status(uint32_t status)
339 {
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",
341               status,
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));
362 }
363 
364 /*
365  * Dump a byte into hex format.
366  */
367 static void
hexbyte(char * buf,uint8_t temp)368 hexbyte(char *buf, uint8_t temp)
369 {
370           uint8_t lo;
371           uint8_t hi;
372 
373           lo = temp & 0xF;
374           hi = temp >> 4;
375 
376           if (hi < 10)
377                     buf[0] = '0' + hi;
378           else
379                     buf[0] = 'A' + hi - 10;
380 
381           if (lo < 10)
382                     buf[1] = '0' + lo;
383           else
384                     buf[1] = 'A' + lo - 10;
385 }
386 
387 /*
388  * Display a region in traditional hexdump format.
389  */
390 static void
hexdump(const uint8_t * region,uint32_t len)391 hexdump(const uint8_t *region, uint32_t len)
392 {
393           const uint8_t *line;
394           char linebuf[128];
395           int i;
396           int x;
397           int c;
398 
399           for (line = region; line < (region + len); line += 16) {
400 
401                     i = 0;
402 
403                     linebuf[i] = ' ';
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] = ' ';
408                     i += 7;
409 
410                     for (x = 0; x < 16; x++) {
411                       if ((line + x) < (region + len)) {
412                               hexbyte(linebuf + i,
413                                   *(const u_int8_t *)(line + x));
414                       } else {
415                                 linebuf[i] = '-';
416                                 linebuf[i + 1] = '-';
417                               }
418                               linebuf[i + 2] = ' ';
419                               if (x == 7) {
420                                 linebuf[i + 3] = ' ';
421                                 i += 4;
422                               } else {
423                                 i += 3;
424                               }
425                     }
426                     linebuf[i] = ' ';
427                     linebuf[i + 1] = '|';
428                     i += 2;
429                     for (x = 0; x < 16; x++) {
430                               if ((line + x) < (region + len)) {
431                                         c = *(const u_int8_t *)(line + x);
432                                         /* !isprint(c) */
433                                         if ((c < ' ') || (c > '~'))
434                                                   c = '.';
435                                         linebuf[i] = c;
436                               } else {
437                                         linebuf[i] = ' ';
438                               }
439                               i++;
440                     }
441                     linebuf[i] = '|';
442                     linebuf[i + 1] = 0;
443                     i += 2;
444                     puts(linebuf);
445           }
446 }
447 
448 static void
print_apacket(const struct header_32 * hdr,const uint8_t * ptr,int ptr_len)449 print_apacket(const struct header_32 *hdr, const uint8_t *ptr, int ptr_len)
450 {
451           struct tm *tm;
452           struct usbpf_pkthdr up_temp;
453           struct usbpf_pkthdr *up;
454           struct timeval tv;
455           size_t len;
456           uint32_t x;
457           char buf[64];
458 
459           ptr += USBPF_HDR_LEN;
460           ptr_len -= USBPF_HDR_LEN;
461           if (ptr_len < 0)
462                     return;
463 
464           /* make sure we don't change the source buffer */
465           memcpy(&up_temp, ptr - USBPF_HDR_LEN, sizeof(up_temp));
466           up = &up_temp;
467 
468           /*
469            * A packet from the kernel is based on little endian byte
470            * order.
471            */
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);
483 
484           if (!match_filter(up->up_address, up->up_endpoint))
485                     return;
486 
487           tv.tv_sec = hdr->ts_sec;
488           tv.tv_usec = hdr->ts_usec;
489           tm = localtime(&tv.tv_sec);
490 
491           len = strftime(buf, sizeof(buf), "%H:%M:%S", tm);
492 
493           if (verbose >= 0) {
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),
501                         (int)up->up_frames,
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) : "");
508           }
509 
510           if (verbose >= 1 || b_arg != NULL) {
511                     for (x = 0; x != up->up_frames; x++) {
512                               const struct usbpf_framehdr *uf;
513                               uint32_t framelen;
514                               uint32_t flags;
515 
516                               uf = (const struct usbpf_framehdr *)ptr;
517                               ptr += USBPF_FRAME_HDR_LEN;
518                               ptr_len -= USBPF_FRAME_HDR_LEN;
519                               if (ptr_len < 0)
520                                         return;
521 
522                               framelen = le32toh(uf->length);
523                               flags = le32toh(uf->flags);
524 
525                               if (verbose >= 1) {
526                                         printf(" frame[%u] %s %d bytes\n",
527                                             (unsigned int)x,
528                                             (flags & USBPF_FRAMEFLAG_READ) ? "READ" : "WRITE",
529                                             (int)framelen);
530                               }
531 
532                               if (flags & USBPF_FRAMEFLAG_DATA_FOLLOWS) {
533 
534                                         int tot_frame_len;
535 
536                                         tot_frame_len = USBPF_FRAME_ALIGN(framelen);
537 
538                                         ptr_len -= tot_frame_len;
539 
540                                         if (tot_frame_len < 0 ||
541                                             (int)framelen < 0 || (int)ptr_len < 0)
542                                                   break;
543 
544                                         if (b_arg != NULL) {
545                                                   struct usbcap *p = &uc;
546                                                   int ret;
547                                                   ret = write(p->bfd, ptr, framelen);
548                                                   if (ret != (int)framelen)
549                                                             err(EXIT_FAILURE, "Could not write binary data");
550                                         }
551                                         if (verbose >= 1)
552                                                   hexdump(ptr, framelen);
553 
554                                         ptr += tot_frame_len;
555                               }
556                     }
557           }
558           if (verbose >= 2)
559                     print_flags(up->up_flags);
560           if (verbose >= 3)
561                     print_status(up->up_status);
562 }
563 
564 static void
fix_packets(uint8_t * data,const int datalen)565 fix_packets(uint8_t *data, const int datalen)
566 {
567           struct header_32 temp;
568           uint8_t *ptr;
569           uint8_t *next;
570           uint32_t hdrlen;
571           uint32_t caplen;
572 
573           for (ptr = data; ptr < (data + datalen); ptr = next) {
574 
575                     const struct bpf_hdr *hdr;
576 
577                     hdr = (const struct bpf_hdr *)ptr;
578 
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);
585 
586                     hdrlen = hdr->bh_hdrlen;
587                     caplen = hdr->bh_caplen;
588 
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));
593                     } else {
594                               err(EXIT_FAILURE, "Invalid header length %d", hdrlen);
595                     }
596 
597                     next = ptr + BPF_WORDALIGN(hdrlen + caplen);
598 
599                     if (next <= ptr)
600                               err(EXIT_FAILURE, "Invalid length");
601           }
602 }
603 
604 static void
print_packets(uint8_t * data,const int datalen)605 print_packets(uint8_t *data, const int datalen)
606 {
607           struct header_32 temp;
608           uint8_t *ptr;
609           uint8_t *next;
610 
611           for (ptr = data; ptr < (data + datalen); ptr = next) {
612 
613                     const struct header_32 *hdr32;
614 
615                     hdr32 = (const struct header_32 *)ptr;
616 
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;
623 
624                     next = ptr + roundup2(temp.hdrlen + temp.caplen, temp.align);
625 
626                     if (next <= ptr)
627                               err(EXIT_FAILURE, "Invalid length");
628 
629                     if (verbose >= 0 || r_arg != NULL || b_arg != NULL) {
630                               print_apacket(&temp, ptr +
631                                   temp.hdrlen, temp.caplen);
632                     }
633                     pkt_captured++;
634           }
635 }
636 
637 static void
write_packets(struct usbcap * p,const uint8_t * data,const int datalen)638 write_packets(struct usbcap *p, const uint8_t *data, const int datalen)
639 {
640           int len = htole32(datalen);
641           int ret;
642 
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");
647           }
648           ret = write(p->wfd, data, datalen);
649           if (ret != datalen) {
650                     err(EXIT_FAILURE, "Could not write "
651                         "complete USB data payload");
652           }
653 }
654 
655 static void
read_file(struct usbcap * p)656 read_file(struct usbcap *p)
657 {
658           int datalen;
659           int ret;
660           uint8_t *data;
661 
662           while ((ret = read(p->rfd, &datalen, sizeof(int))) == sizeof(int)) {
663                     datalen = le32toh(datalen);
664                     data = malloc(datalen);
665                     if (data == NULL)
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 "
670                                   "USB data payload");
671                     }
672                     if (uf_minor == 2)
673                               fix_packets(data, datalen);
674 
675                     print_packets(data, datalen);
676                     free(data);
677           }
678 }
679 
680 static void
do_loop(struct usbcap * p)681 do_loop(struct usbcap *p)
682 {
683           int cc;
684 
685           while (doexit == 0) {
686                     cc = read(p->fd, (uint8_t *)p->buffer, p->bufsize);
687                     if (cc < 0) {
688                               switch (errno) {
689                               case EINTR:
690                                         break;
691                               default:
692                                         fprintf(stderr, "read: %s\n", strerror(errno));
693                                         return;
694                               }
695                               continue;
696                     }
697                     if (cc == 0)
698                               continue;
699 
700                     fix_packets(p->buffer, cc);
701 
702                     if (w_arg != NULL)
703                               write_packets(p, p->buffer, cc);
704                     print_packets(p->buffer, cc);
705           }
706 }
707 
708 static void
init_rfile(struct usbcap * p)709 init_rfile(struct usbcap *p)
710 {
711           struct usbcap_filehdr uf;
712           int ret;
713 
714           p->rfd = open(r_arg, O_RDONLY);
715           if (p->rfd < 0) {
716                     err(EXIT_FAILURE, "Could not open "
717                         "'%s' for read", r_arg);
718           }
719           ret = read(p->rfd, &uf, sizeof(uf));
720           if (ret != sizeof(uf)) {
721                     err(EXIT_FAILURE, "Could not read USB capture "
722                         "file header");
723           }
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));
728           }
729           if (uf.major != 0) {
730                     errx(EX_SOFTWARE, "Invalid major version(%d) "
731                         "field in USB capture file header.", (int)uf.major);
732           }
733 
734           uf_minor = uf.minor;
735 
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);
739           }
740 }
741 
742 static void
init_wfile(struct usbcap * p)743 init_wfile(struct usbcap *p)
744 {
745           struct usbcap_filehdr uf;
746           int ret;
747 
748           p->wfd = open(w_arg, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR);
749           if (p->wfd < 0) {
750                     err(EXIT_FAILURE, "Could not open "
751                         "'%s' for write", w_arg);
752           }
753           memset(&uf, 0, sizeof(uf));
754           uf.magic = htole32(USBCAP_FILEHDR_MAGIC);
755           uf.major = 0;
756           uf.minor = 3;
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");
761           }
762 }
763 
764 static void
usage(void)765 usage(void)
766 {
767 
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");
778 #undef FMT
779           exit(EX_USAGE);
780 }
781 
782 static void
check_usb_pf_sysctl(void)783 check_usb_pf_sysctl(void)
784 {
785           int error;
786           int no_pf_val = 0;
787           size_t no_pf_len = sizeof(int);
788 
789           /* check "hw.usb.no_pf" sysctl for 8- and 9- stable */
790 
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.");
796           }
797 }
798 
799 int
main(int argc,char * argv[])800 main(int argc, char *argv[])
801 {
802           struct timeval tv;
803           struct bpf_program total_prog;
804           struct bpf_stat us;
805           struct bpf_version bv;
806           struct usbcap *p = &uc;
807           struct ifreq ifr;
808           long snapshot = 192;
809           uint32_t v;
810           int fd;
811           int o;
812           int filt_unit;
813           int filt_ep;
814           int s;
815           int ifindex;
816           const char *optstring;
817           char *pp;
818 
819           optstring = "b:hi:r:s:vw:f:";
820           while ((o = getopt(argc, argv, optstring)) != -1) {
821                     switch (o) {
822                     case 'i':
823                               i_arg = optarg;
824                               break;
825                     case 'r':
826                               r_arg = optarg;
827                               init_rfile(p);
828                               break;
829                     case 's':
830                               snapshot = strtol(optarg, &pp, 10);
831                               errno = 0;
832                               if (pp != NULL && *pp != 0)
833                                         usage();
834                               if (snapshot == 0 && errno == EINVAL)
835                                         usage();
836                               /* snapeshot == 0 is special */
837                               if (snapshot == 0)
838                                         snapshot = -1;
839                               break;
840                     case 'b':
841                               b_arg = optarg;
842                               break;
843                     case 'v':
844                               verbose++;
845                               break;
846                     case 'w':
847                               w_arg = optarg;
848                               init_wfile(p);
849                               break;
850                     case 'f':
851                               filt_unit = strtol(optarg, &pp, 10);
852                               filt_ep = -1;
853                               if (pp != NULL) {
854                                         if (*pp == '.') {
855                                                   filt_ep = strtol(pp + 1, &pp, 10);
856                                                   if (pp != NULL && *pp != 0)
857                                                             usage();
858                                         } else if (*pp != 0) {
859                                                   usage();
860                                         }
861                               }
862                               add_filter(filt_unit, filt_ep);
863                               break;
864                     default:
865                               usage();
866                               /* NOTREACHED */
867                     }
868           }
869 
870           if (b_arg != NULL) {
871                     p->bfd = open(b_arg, O_CREAT | O_TRUNC |
872                         O_WRONLY, S_IRUSR | S_IWUSR);
873                     if (p->bfd < 0) {
874                               err(EXIT_FAILURE, "Could not open "
875                                   "'%s' for write", b_arg);
876                     }
877           }
878 
879           /*
880            * Require more verbosity to print anything when -w or -b is
881            * specified on the command line:
882            */
883           if (w_arg != NULL || b_arg != NULL)
884                     verbose--;
885 
886           if (r_arg != NULL) {
887                     read_file(p);
888                     exit(EXIT_SUCCESS);
889           }
890 
891           check_usb_pf_sysctl();
892 
893           p->fd = fd = open("/dev/bpf", O_RDONLY);
894           if (p->fd < 0)
895                     err(EXIT_FAILURE, "Could not open BPF device");
896 
897           if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0)
898                     err(EXIT_FAILURE, "BIOCVERSION ioctl failed");
899 
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");
903 
904           /* USB transfers can be greater than 64KByte */
905           v = 1U << 16;
906 
907           /* clear ifr structure */
908           memset(&ifr, 0, sizeof(ifr));
909 
910           /* Try to create usbusN interface if it is not available. */
911           s = socket(AF_LOCAL, SOCK_DGRAM, 0);
912           if (s < 0)
913                     errx(EXIT_FAILURE, "Could not open a socket");
914           ifindex = if_nametoindex(i_arg);
915           if (ifindex == 0) {
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);
919           }
920 
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)
925                               break;
926           }
927           if (v == 0)
928                     errx(EXIT_FAILURE, "No buffer size worked.");
929 
930           if (ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0)
931                     err(EXIT_FAILURE, "BIOCGBLEN ioctl failed");
932 
933           p->bufsize = v;
934           p->buffer = (uint8_t *)malloc(p->bufsize);
935           if (p->buffer == NULL)
936                     errx(EX_SOFTWARE, "Out of memory.");
937 
938           make_filter(&total_prog, snapshot);
939 
940           if (ioctl(p->fd, BIOCSETF, (caddr_t)&total_prog) < 0)
941                     err(EXIT_FAILURE, "BIOCSETF ioctl failed");
942 
943           free_filter(&total_prog);
944 
945           /* 1 second read timeout */
946           tv.tv_sec = 1;
947           tv.tv_usec = 0;
948           if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&tv) < 0)
949                     err(EXIT_FAILURE, "BIOCSRTIMEOUT ioctl failed");
950 
951           (void)signal(SIGINT, handle_sigint);
952 
953           do_loop(p);
954 
955           if (ioctl(fd, BIOCGSTATS, (caddr_t)&us) < 0)
956                     err(EXIT_FAILURE, "BIOCGSTATS ioctl failed");
957 
958           /* XXX what's difference between pkt_captured and us.us_recv? */
959           printf("\n");
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);
963 
964           /*
965            * Destroy the usbusN interface only if it was created by
966            * usbdump(8).  Ignore when it was already destroyed.
967            */
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");
972           }
973           close(s);
974 
975           if (p->fd > 0)
976                     close(p->fd);
977           if (p->rfd > 0)
978                     close(p->rfd);
979           if (p->wfd > 0)
980                     close(p->wfd);
981           if (p->bfd > 0)
982                     close(p->bfd);
983 
984           return (EXIT_SUCCESS);
985 }
986