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, 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. 28 * 29 * $FreeBSD: stable/10/usr.sbin/usbdump/usbdump.c 349666 2019-07-03 18:19:29Z 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/utsname.h> 38#include <sys/queue.h> 39#include <net/if.h> 40#include <net/bpf.h> 41#include <dev/usb/usb.h> 42#include <dev/usb/usb_pf.h> 43#include <dev/usb/usbdi.h> 44#include <errno.h> 45#include <fcntl.h> 46#include <limits.h> 47#include <stdio.h> 48#include <stdlib.h> 49#include <stdint.h> 50#include <string.h> 51#include <time.h> 52#include <unistd.h> 53#include <sysexits.h> 54#include <err.h> 55 56#define BPF_STORE_JUMP(x,_c,_k,_jt,_jf) do { \ 57 (x).code = (_c); \ 58 (x).k = (_k); \ 59 (x).jt = (_jt); \ 60 (x).jf = (_jf); \ 61} while (0) 62 63#define BPF_STORE_STMT(x,_c,_k) do { \ 64 (x).code = (_c); \ 65 (x).k = (_k); \ 66 (x).jt = 0; \ 67 (x).jf = 0; \ 68} while (0) 69 70struct usb_filt { 71 STAILQ_ENTRY(usb_filt) entry; 72 int unit; 73 int endpoint; 74}; 75 76struct usbcap { 77 int fd; /* fd for /dev/usbpf */ 78 uint32_t bufsize; 79 uint8_t *buffer; 80 81 /* for -w option */ 82 int wfd; 83 /* for -r option */ 84 int rfd; 85 /* for -b option */ 86 int bfd; 87}; 88 89struct usbcap_filehdr { 90 uint32_t magic; 91#define USBCAP_FILEHDR_MAGIC 0x9a90000e 92 uint8_t major; 93 uint8_t minor; 94 uint8_t reserved[26]; 95} __packed; 96 97#define HEADER_ALIGN(x,a) (((x) + (a) - 1) & ~((a) - 1)) 98 99struct header_32 { 100 /* capture timestamp */ 101 uint32_t ts_sec; 102 uint32_t ts_usec; 103 /* data length and alignment information */ 104 uint32_t caplen; 105 uint32_t datalen; 106 uint8_t hdrlen; 107 uint8_t align; 108} __packed; 109 110static int doexit = 0; 111static int pkt_captured = 0; 112static int verbose = 0; 113static int uf_minor; 114static const char *i_arg = "usbus0"; 115static const char *r_arg = NULL; 116static const char *w_arg = NULL; 117static const char *b_arg = NULL; 118static struct usbcap uc; 119static const char *errstr_table[USB_ERR_MAX] = { 120 [USB_ERR_NORMAL_COMPLETION] = "0", 121 [USB_ERR_PENDING_REQUESTS] = "PENDING_REQUESTS", 122 [USB_ERR_NOT_STARTED] = "NOT_STARTED", 123 [USB_ERR_INVAL] = "INVAL", 124 [USB_ERR_NOMEM] = "NOMEM", 125 [USB_ERR_CANCELLED] = "CANCELLED", 126 [USB_ERR_BAD_ADDRESS] = "BAD_ADDRESS", 127 [USB_ERR_BAD_BUFSIZE] = "BAD_BUFSIZE", 128 [USB_ERR_BAD_FLAG] = "BAD_FLAG", 129 [USB_ERR_NO_CALLBACK] = "NO_CALLBACK", 130 [USB_ERR_IN_USE] = "IN_USE", 131 [USB_ERR_NO_ADDR] = "NO_ADDR", 132 [USB_ERR_NO_PIPE] = "NO_PIPE", 133 [USB_ERR_ZERO_NFRAMES] = "ZERO_NFRAMES", 134 [USB_ERR_ZERO_MAXP] = "ZERO_MAXP", 135 [USB_ERR_SET_ADDR_FAILED] = "SET_ADDR_FAILED", 136 [USB_ERR_NO_POWER] = "NO_POWER", 137 [USB_ERR_TOO_DEEP] = "TOO_DEEP", 138 [USB_ERR_IOERROR] = "IOERROR", 139 [USB_ERR_NOT_CONFIGURED] = "NOT_CONFIGURED", 140 [USB_ERR_TIMEOUT] = "TIMEOUT", 141 [USB_ERR_SHORT_XFER] = "SHORT_XFER", 142 [USB_ERR_STALLED] = "STALLED", 143 [USB_ERR_INTERRUPTED] = "INTERRUPTED", 144 [USB_ERR_DMA_LOAD_FAILED] = "DMA_LOAD_FAILED", 145 [USB_ERR_BAD_CONTEXT] = "BAD_CONTEXT", 146 [USB_ERR_NO_ROOT_HUB] = "NO_ROOT_HUB", 147 [USB_ERR_NO_INTR_THREAD] = "NO_INTR_THREAD", 148 [USB_ERR_NOT_LOCKED] = "NOT_LOCKED", 149}; 150 151#define USB_XFERTYPE_MAX 4 152 153static const char *xfertype_table[USB_XFERTYPE_MAX] = { 154 [UE_CONTROL] = "CTRL", 155 [UE_ISOCHRONOUS] = "ISOC", 156 [UE_BULK] = "BULK", 157 [UE_INTERRUPT] = "INTR" 158}; 159 160static const char *speed_table[USB_SPEED_MAX] = { 161 [USB_SPEED_FULL] = "FULL", 162 [USB_SPEED_HIGH] = "HIGH", 163 [USB_SPEED_LOW] = "LOW", 164 [USB_SPEED_VARIABLE] = "VARI", 165 [USB_SPEED_SUPER] = "SUPER", 166}; 167 168static STAILQ_HEAD(,usb_filt) usb_filt_head = 169 STAILQ_HEAD_INITIALIZER(usb_filt_head); 170 171static void 172add_filter(int usb_filt_unit, int usb_filt_ep) 173{ 174 struct usb_filt *puf; 175 176 puf = malloc(sizeof(struct usb_filt)); 177 if (puf == NULL) 178 errx(EX_SOFTWARE, "Out of memory."); 179 180 puf->unit = usb_filt_unit; 181 puf->endpoint = usb_filt_ep; 182 183 STAILQ_INSERT_TAIL(&usb_filt_head, puf, entry); 184} 185 186static void 187make_filter(struct bpf_program *pprog, int snapshot) 188{ 189 struct usb_filt *puf; 190 struct bpf_insn *dynamic_insn; 191 int len; 192 193 len = 0; 194 195 STAILQ_FOREACH(puf, &usb_filt_head, entry) 196 len++; 197 198 dynamic_insn = malloc(((len * 5) + 1) * sizeof(struct bpf_insn)); 199 200 if (dynamic_insn == NULL) 201 errx(EX_SOFTWARE, "Out of memory."); 202 203 len++; 204 205 if (len == 1) { 206 /* accept all packets */ 207 208 BPF_STORE_STMT(dynamic_insn[0], BPF_RET | BPF_K, snapshot); 209 210 goto done; 211 } 212 213 len = 0; 214 215 STAILQ_FOREACH(puf, &usb_filt_head, entry) { 216 const int addr_off = (uintptr_t)&((struct usbpf_pkthdr *)0)->up_address; 217 const int addr_ep = (uintptr_t)&((struct usbpf_pkthdr *)0)->up_endpoint; 218 219 if (puf->unit != -1) { 220 if (puf->endpoint != -1) { 221 BPF_STORE_STMT(dynamic_insn[len], 222 BPF_LD | BPF_B | BPF_ABS, addr_off); 223 len++; 224 BPF_STORE_JUMP(dynamic_insn[len], 225 BPF_JMP | BPF_JEQ | BPF_K, (uint8_t)puf->unit, 0, 3); 226 len++; 227 BPF_STORE_STMT(dynamic_insn[len], 228 BPF_LD | BPF_W | BPF_ABS, addr_ep); 229 len++; 230 BPF_STORE_JUMP(dynamic_insn[len], 231 BPF_JMP | BPF_JEQ | BPF_K, htobe32(puf->endpoint), 0, 1); 232 len++; 233 } else { 234 BPF_STORE_STMT(dynamic_insn[len], 235 BPF_LD | BPF_B | BPF_ABS, addr_off); 236 len++; 237 BPF_STORE_JUMP(dynamic_insn[len], 238 BPF_JMP | BPF_JEQ | BPF_K, (uint8_t)puf->unit, 0, 1); 239 len++; 240 } 241 } else { 242 if (puf->endpoint != -1) { 243 BPF_STORE_STMT(dynamic_insn[len], 244 BPF_LD | BPF_W | BPF_ABS, addr_ep); 245 len++; 246 BPF_STORE_JUMP(dynamic_insn[len], 247 BPF_JMP | BPF_JEQ | BPF_K, htobe32(puf->endpoint), 0, 1); 248 len++; 249 } 250 } 251 BPF_STORE_STMT(dynamic_insn[len], 252 BPF_RET | BPF_K, snapshot); 253 len++; 254 } 255 256 BPF_STORE_STMT(dynamic_insn[len], BPF_RET | BPF_K, 0); 257 len++; 258 259done: 260 pprog->bf_len = len; 261 pprog->bf_insns = dynamic_insn; 262} 263 264static int 265match_filter(int unit, int endpoint) 266{ 267 struct usb_filt *puf; 268 269 if (STAILQ_FIRST(&usb_filt_head) == NULL) 270 return (1); 271 272 STAILQ_FOREACH(puf, &usb_filt_head, entry) { 273 if ((puf->unit == -1 || puf->unit == unit) && 274 (puf->endpoint == -1 || puf->endpoint == endpoint)) 275 return (1); 276 } 277 return (0); 278} 279 280static void 281free_filter(struct bpf_program *pprog) 282{ 283 struct usb_filt *puf; 284 285 while ((puf = STAILQ_FIRST(&usb_filt_head)) != NULL) { 286 STAILQ_REMOVE_HEAD(&usb_filt_head, entry); 287 free(puf); 288 } 289 free(pprog->bf_insns); 290} 291 292static void 293handle_sigint(int sig) 294{ 295 296 (void)sig; 297 doexit = 1; 298} 299 300#define FLAGS(x, name) \ 301 (((x) & USBPF_FLAG_##name) ? #name "|" : "") 302 303#define STATUS(x, name) \ 304 (((x) & USBPF_STATUS_##name) ? #name "|" : "") 305 306static const char * 307usb_errstr(uint32_t error) 308{ 309 if (error >= USB_ERR_MAX || errstr_table[error] == NULL) 310 return ("UNKNOWN"); 311 else 312 return (errstr_table[error]); 313} 314 315static const char * 316usb_speedstr(uint8_t speed) 317{ 318 if (speed >= USB_SPEED_MAX || speed_table[speed] == NULL) 319 return ("UNKNOWN"); 320 else 321 return (speed_table[speed]); 322} 323 324static const char * 325usb_xferstr(uint8_t type) 326{ 327 if (type >= USB_XFERTYPE_MAX || xfertype_table[type] == NULL) 328 return ("UNKN"); 329 else 330 return (xfertype_table[type]); 331} 332 333static void 334print_flags(uint32_t flags) 335{ 336 printf(" flags %#x <%s%s%s%s%s%s%s%s%s0>\n", 337 flags, 338 FLAGS(flags, FORCE_SHORT_XFER), 339 FLAGS(flags, SHORT_XFER_OK), 340 FLAGS(flags, SHORT_FRAMES_OK), 341 FLAGS(flags, PIPE_BOF), 342 FLAGS(flags, PROXY_BUFFER), 343 FLAGS(flags, EXT_BUFFER), 344 FLAGS(flags, MANUAL_STATUS), 345 FLAGS(flags, NO_PIPE_OK), 346 FLAGS(flags, STALL_PIPE)); 347} 348 349static void 350print_status(uint32_t status) 351{ 352 printf(" status %#x <%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s0>\n", 353 status, 354 STATUS(status, OPEN), 355 STATUS(status, TRANSFERRING), 356 STATUS(status, DID_DMA_DELAY), 357 STATUS(status, DID_CLOSE), 358 STATUS(status, DRAINING), 359 STATUS(status, STARTED), 360 STATUS(status, BW_RECLAIMED), 361 STATUS(status, CONTROL_XFR), 362 STATUS(status, CONTROL_HDR), 363 STATUS(status, CONTROL_ACT), 364 STATUS(status, CONTROL_STALL), 365 STATUS(status, SHORT_FRAMES_OK), 366 STATUS(status, SHORT_XFER_OK), 367 STATUS(status, BDMA_ENABLE), 368 STATUS(status, BDMA_NO_POST_SYNC), 369 STATUS(status, BDMA_SETUP), 370 STATUS(status, ISOCHRONOUS_XFR), 371 STATUS(status, CURR_DMA_SET), 372 STATUS(status, CAN_CANCEL_IMMED), 373 STATUS(status, DOING_CALLBACK)); 374} 375 376/* 377 * Dump a byte into hex format. 378 */ 379static void 380hexbyte(char *buf, uint8_t temp) 381{ 382 uint8_t lo; 383 uint8_t hi; 384 385 lo = temp & 0xF; 386 hi = temp >> 4; 387 388 if (hi < 10) 389 buf[0] = '0' + hi; 390 else 391 buf[0] = 'A' + hi - 10; 392 393 if (lo < 10) 394 buf[1] = '0' + lo; 395 else 396 buf[1] = 'A' + lo - 10; 397} 398 399/* 400 * Display a region in traditional hexdump format. 401 */ 402static void 403hexdump(const uint8_t *region, uint32_t len) 404{ 405 const uint8_t *line; 406 char linebuf[128]; 407 int i; 408 int x; 409 int c; 410 411 for (line = region; line < (region + len); line += 16) { 412 413 i = 0; 414 415 linebuf[i] = ' '; 416 hexbyte(linebuf + i + 1, ((line - region) >> 8) & 0xFF); 417 hexbyte(linebuf + i + 3, (line - region) & 0xFF); 418 linebuf[i + 5] = ' '; 419 linebuf[i + 6] = ' '; 420 i += 7; 421 422 for (x = 0; x < 16; x++) { 423 if ((line + x) < (region + len)) { 424 hexbyte(linebuf + i, 425 *(const u_int8_t *)(line + x)); 426 } else { 427 linebuf[i] = '-'; 428 linebuf[i + 1] = '-'; 429 } 430 linebuf[i + 2] = ' '; 431 if (x == 7) { 432 linebuf[i + 3] = ' '; 433 i += 4; 434 } else { 435 i += 3; 436 } 437 } 438 linebuf[i] = ' '; 439 linebuf[i + 1] = '|'; 440 i += 2; 441 for (x = 0; x < 16; x++) { 442 if ((line + x) < (region + len)) { 443 c = *(const u_int8_t *)(line + x); 444 /* !isprint(c) */ 445 if ((c < ' ') || (c > '~')) 446 c = '.'; 447 linebuf[i] = c; 448 } else { 449 linebuf[i] = ' '; 450 } 451 i++; 452 } 453 linebuf[i] = '|'; 454 linebuf[i + 1] = 0; 455 i += 2; 456 puts(linebuf); 457 } 458} 459 460static void 461print_apacket(const struct header_32 *hdr, const uint8_t *ptr, int ptr_len) 462{ 463 struct tm *tm; 464 struct usbpf_pkthdr up_temp; 465 struct usbpf_pkthdr *up; 466 struct timeval tv; 467 size_t len; 468 uint32_t x; 469 char buf[64]; 470 471 ptr += USBPF_HDR_LEN; 472 ptr_len -= USBPF_HDR_LEN; 473 if (ptr_len < 0) 474 return; 475 476 /* make sure we don't change the source buffer */ 477 memcpy(&up_temp, ptr - USBPF_HDR_LEN, sizeof(up_temp)); 478 up = &up_temp; 479 480 /* 481 * A packet from the kernel is based on little endian byte 482 * order. 483 */ 484 up->up_totlen = le32toh(up->up_totlen); 485 up->up_busunit = le32toh(up->up_busunit); 486 up->up_flags = le32toh(up->up_flags); 487 up->up_status = le32toh(up->up_status); 488 up->up_error = le32toh(up->up_error); 489 up->up_interval = le32toh(up->up_interval); 490 up->up_frames = le32toh(up->up_frames); 491 up->up_packet_size = le32toh(up->up_packet_size); 492 up->up_packet_count = le32toh(up->up_packet_count); 493 up->up_endpoint = le32toh(up->up_endpoint); 494 495 if (!match_filter(up->up_address, up->up_endpoint)) 496 return; 497 498 tv.tv_sec = hdr->ts_sec; 499 tv.tv_usec = hdr->ts_usec; 500 tm = localtime(&tv.tv_sec); 501 502 len = strftime(buf, sizeof(buf), "%H:%M:%S", tm); 503 504 if (verbose >= 0) { 505 printf("%.*s.%06ld usbus%d.%d %s-%s-EP=%08x,SPD=%s,NFR=%d,SLEN=%d,IVAL=%d%s%s\n", 506 (int)len, buf, tv.tv_usec, 507 (int)up->up_busunit, (int)up->up_address, 508 (up->up_type == USBPF_XFERTAP_SUBMIT) ? "SUBM" : "DONE", 509 usb_xferstr(up->up_xfertype), 510 (unsigned int)up->up_endpoint, 511 usb_speedstr(up->up_speed), 512 (int)up->up_frames, 513 (int)(up->up_totlen - USBPF_HDR_LEN - 514 (USBPF_FRAME_HDR_LEN * up->up_frames)), 515 (int)up->up_interval, 516 (up->up_type == USBPF_XFERTAP_DONE) ? ",ERR=" : "", 517 (up->up_type == USBPF_XFERTAP_DONE) ? 518 usb_errstr(up->up_error) : ""); 519 } 520 521 if (verbose >= 1 || b_arg != NULL) { 522 for (x = 0; x != up->up_frames; x++) { 523 const struct usbpf_framehdr *uf; 524 uint32_t framelen; 525 uint32_t flags; 526 527 uf = (const struct usbpf_framehdr *)ptr; 528 ptr += USBPF_FRAME_HDR_LEN; 529 ptr_len -= USBPF_FRAME_HDR_LEN; 530 if (ptr_len < 0) 531 return; 532 533 framelen = le32toh(uf->length); 534 flags = le32toh(uf->flags); 535 536 if (verbose >= 1) { 537 printf(" frame[%u] %s %d bytes\n", 538 (unsigned int)x, 539 (flags & USBPF_FRAMEFLAG_READ) ? "READ" : "WRITE", 540 (int)framelen); 541 } 542 543 if (flags & USBPF_FRAMEFLAG_DATA_FOLLOWS) { 544 545 int tot_frame_len; 546 547 tot_frame_len = USBPF_FRAME_ALIGN(framelen); 548 549 ptr_len -= tot_frame_len; 550 551 if (tot_frame_len < 0 || 552 (int)framelen < 0 || (int)ptr_len < 0) 553 break; 554 555 if (b_arg != NULL) { 556 struct usbcap *p = &uc; 557 int ret; 558 ret = write(p->bfd, ptr, framelen); 559 if (ret != (int)framelen) 560 err(EXIT_FAILURE, "Could not write binary data"); 561 } 562 if (verbose >= 1) 563 hexdump(ptr, framelen); 564 565 ptr += tot_frame_len; 566 } 567 } 568 } 569 if (verbose >= 2) 570 print_flags(up->up_flags); 571 if (verbose >= 3) 572 print_status(up->up_status); 573} 574 575static void 576fix_packets(uint8_t *data, const int datalen) 577{ 578 struct header_32 temp; 579 uint8_t *ptr; 580 uint8_t *next; 581 uint32_t hdrlen; 582 uint32_t caplen; 583 584 for (ptr = data; ptr < (data + datalen); ptr = next) { 585 586 const struct bpf_hdr *hdr; 587 588 hdr = (const struct bpf_hdr *)ptr; 589 590 temp.ts_sec = htole32(hdr->bh_tstamp.tv_sec); 591 temp.ts_usec = htole32(hdr->bh_tstamp.tv_usec); 592 temp.caplen = htole32(hdr->bh_caplen); 593 temp.datalen = htole32(hdr->bh_datalen); 594 temp.hdrlen = hdr->bh_hdrlen; 595 temp.align = BPF_WORDALIGN(1); 596 597 hdrlen = hdr->bh_hdrlen; 598 caplen = hdr->bh_caplen; 599 600 if ((hdrlen >= sizeof(temp)) && (hdrlen <= 255) && 601 ((ptr + hdrlen) <= (data + datalen))) { 602 memcpy(ptr, &temp, sizeof(temp)); 603 memset(ptr + sizeof(temp), 0, hdrlen - sizeof(temp)); 604 } else { 605 err(EXIT_FAILURE, "Invalid header length %d", hdrlen); 606 } 607 608 next = ptr + BPF_WORDALIGN(hdrlen + caplen); 609 610 if (next <= ptr) 611 err(EXIT_FAILURE, "Invalid length"); 612 } 613} 614 615static void 616print_packets(uint8_t *data, const int datalen) 617{ 618 struct header_32 temp; 619 uint8_t *ptr; 620 uint8_t *next; 621 622 for (ptr = data; ptr < (data + datalen); ptr = next) { 623 624 const struct header_32 *hdr32; 625 626 hdr32 = (const struct header_32 *)ptr; 627 628 temp.ts_sec = le32toh(hdr32->ts_sec); 629 temp.ts_usec = le32toh(hdr32->ts_usec); 630 temp.caplen = le32toh(hdr32->caplen); 631 temp.datalen = le32toh(hdr32->datalen); 632 temp.hdrlen = hdr32->hdrlen; 633 temp.align = hdr32->align; 634 635 next = ptr + HEADER_ALIGN(temp.hdrlen + temp.caplen, temp.align); 636 637 if (next <= ptr) 638 err(EXIT_FAILURE, "Invalid length"); 639 640 if (verbose >= 0 || r_arg != NULL || b_arg != NULL) { 641 print_apacket(&temp, ptr + 642 temp.hdrlen, temp.caplen); 643 } 644 pkt_captured++; 645 } 646} 647 648static void 649write_packets(struct usbcap *p, const uint8_t *data, const int datalen) 650{ 651 int len = htole32(datalen); 652 int ret; 653 654 ret = write(p->wfd, &len, sizeof(int)); 655 if (ret != sizeof(int)) { 656 err(EXIT_FAILURE, "Could not write length " 657 "field of USB data payload"); 658 } 659 ret = write(p->wfd, data, datalen); 660 if (ret != datalen) { 661 err(EXIT_FAILURE, "Could not write " 662 "complete USB data payload"); 663 } 664} 665 666static void 667read_file(struct usbcap *p) 668{ 669 int datalen; 670 int ret; 671 uint8_t *data; 672 673 while ((ret = read(p->rfd, &datalen, sizeof(int))) == sizeof(int)) { 674 datalen = le32toh(datalen); 675 data = malloc(datalen); 676 if (data == NULL) 677 errx(EX_SOFTWARE, "Out of memory."); 678 ret = read(p->rfd, data, datalen); 679 if (ret != datalen) { 680 err(EXIT_FAILURE, "Could not read complete " 681 "USB data payload"); 682 } 683 if (uf_minor == 2) 684 fix_packets(data, datalen); 685 686 print_packets(data, datalen); 687 free(data); 688 } 689} 690 691static void 692do_loop(struct usbcap *p) 693{ 694 int cc; 695 696 while (doexit == 0) { 697 cc = read(p->fd, (uint8_t *)p->buffer, p->bufsize); 698 if (cc < 0) { 699 switch (errno) { 700 case EINTR: 701 break; 702 default: 703 fprintf(stderr, "read: %s\n", strerror(errno)); 704 return; 705 } 706 continue; 707 } 708 if (cc == 0) 709 continue; 710 711 fix_packets(p->buffer, cc); 712 713 if (w_arg != NULL) 714 write_packets(p, p->buffer, cc); 715 print_packets(p->buffer, cc); 716 } 717} 718 719static void 720init_rfile(struct usbcap *p) 721{ 722 struct usbcap_filehdr uf; 723 int ret; 724 725 p->rfd = open(r_arg, O_RDONLY); 726 if (p->rfd < 0) { 727 err(EXIT_FAILURE, "Could not open " 728 "'%s' for read", r_arg); 729 } 730 ret = read(p->rfd, &uf, sizeof(uf)); 731 if (ret != sizeof(uf)) { 732 err(EXIT_FAILURE, "Could not read USB capture " 733 "file header"); 734 } 735 if (le32toh(uf.magic) != USBCAP_FILEHDR_MAGIC) { 736 errx(EX_SOFTWARE, "Invalid magic field(0x%08x) " 737 "in USB capture file header.", 738 (unsigned int)le32toh(uf.magic)); 739 } 740 if (uf.major != 0) { 741 errx(EX_SOFTWARE, "Invalid major version(%d) " 742 "field in USB capture file header.", (int)uf.major); 743 } 744 745 uf_minor = uf.minor; 746 747 if (uf.minor != 3 && uf.minor != 2) { 748 errx(EX_SOFTWARE, "Invalid minor version(%d) " 749 "field in USB capture file header.", (int)uf.minor); 750 } 751} 752 753static void 754init_wfile(struct usbcap *p) 755{ 756 struct usbcap_filehdr uf; 757 int ret; 758 759 p->wfd = open(w_arg, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR); 760 if (p->wfd < 0) { 761 err(EXIT_FAILURE, "Could not open " 762 "'%s' for write", w_arg); 763 } 764 memset(&uf, 0, sizeof(uf)); 765 uf.magic = htole32(USBCAP_FILEHDR_MAGIC); 766 uf.major = 0; 767 uf.minor = 3; 768 ret = write(p->wfd, (const void *)&uf, sizeof(uf)); 769 if (ret != sizeof(uf)) { 770 err(EXIT_FAILURE, "Could not write " 771 "USB capture header"); 772 } 773} 774 775static void 776usage(void) 777{ 778 779#define FMT " %-14s %s\n" 780 fprintf(stderr, "usage: usbdump [options]\n"); 781 fprintf(stderr, FMT, "-i <usbusX>", "Listen on USB bus interface"); 782 fprintf(stderr, FMT, "-f <unit[.endpoint]>", "Specify a device and endpoint filter"); 783 fprintf(stderr, FMT, "-r <file>", "Read the raw packets from file"); 784 fprintf(stderr, FMT, "-s <snaplen>", "Snapshot bytes from each packet"); 785 fprintf(stderr, FMT, "-v", "Increase the verbose level"); 786 fprintf(stderr, FMT, "-b <file>", "Save raw version of all recorded data to file"); 787 fprintf(stderr, FMT, "-w <file>", "Write the raw packets to file"); 788 fprintf(stderr, FMT, "-h", "Display summary of command line options"); 789#undef FMT 790 exit(EX_USAGE); 791} 792 793int 794main(int argc, char *argv[]) 795{ 796 struct timeval tv; 797 struct bpf_program total_prog; 798 struct bpf_stat us; 799 struct bpf_version bv; 800 struct usbcap *p = &uc; 801 struct ifreq ifr; 802 long snapshot = 192; 803 uint32_t v; 804 int fd; 805 int o; 806 int filt_unit; 807 int filt_ep; 808 int s; 809 int ifindex; 810 const char *optstring; 811 char *pp; 812 813 optstring = "b:hi:r:s:vw:f:"; 814 while ((o = getopt(argc, argv, optstring)) != -1) { 815 switch (o) { 816 case 'i': 817 i_arg = optarg; 818 break; 819 case 'r': 820 r_arg = optarg; 821 init_rfile(p); 822 break; 823 case 's': 824 snapshot = strtol(optarg, &pp, 10); 825 errno = 0; 826 if (pp != NULL && *pp != 0) 827 usage(); 828 if (snapshot == 0 && errno == EINVAL) 829 usage(); 830 /* snapeshot == 0 is special */ 831 if (snapshot == 0) 832 snapshot = -1; 833 break; 834 case 'b': 835 b_arg = optarg; 836 break; 837 case 'v': 838 verbose++; 839 break; 840 case 'w': 841 w_arg = optarg; 842 init_wfile(p); 843 break; 844 case 'f': 845 filt_unit = strtol(optarg, &pp, 10); 846 filt_ep = -1; 847 if (pp != NULL) { 848 if (*pp == '.') { 849 filt_ep = strtol(pp + 1, &pp, 10); 850 if (pp != NULL && *pp != 0) 851 usage(); 852 } else if (*pp != 0) { 853 usage(); 854 } 855 } 856 add_filter(filt_unit, filt_ep); 857 break; 858 default: 859 usage(); 860 /* NOTREACHED */ 861 } 862 } 863 864 if (b_arg != NULL) { 865 p->bfd = open(b_arg, O_CREAT | O_TRUNC | 866 O_WRONLY, S_IRUSR | S_IWUSR); 867 if (p->bfd < 0) { 868 err(EXIT_FAILURE, "Could not open " 869 "'%s' for write", b_arg); 870 } 871 } 872 873 /* 874 * Require more verbosity to print anything when -w or -b is 875 * specified on the command line: 876 */ 877 if (w_arg != NULL || b_arg != NULL) 878 verbose--; 879 880 if (r_arg != NULL) { 881 read_file(p); 882 exit(EXIT_SUCCESS); 883 } 884 885 p->fd = fd = open("/dev/bpf", O_RDONLY); 886 if (p->fd < 0) 887 err(EXIT_FAILURE, "Could not open BPF device"); 888 889 if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0) 890 err(EXIT_FAILURE, "BIOCVERSION ioctl failed"); 891 892 if (bv.bv_major != BPF_MAJOR_VERSION || 893 bv.bv_minor < BPF_MINOR_VERSION) 894 errx(EXIT_FAILURE, "Kernel BPF filter out of date"); 895 896 /* USB transfers can be greater than 64KByte */ 897 v = 1U << 16; 898 899 /* clear ifr structure */ 900 memset(&ifr, 0, sizeof(ifr)); 901 902 /* Try to create usbusN interface if it is not available. */ 903 s = socket(AF_LOCAL, SOCK_DGRAM, 0); 904 if (s < 0) 905 errx(EXIT_FAILURE, "Could not open a socket"); 906 ifindex = if_nametoindex(i_arg); 907 if (ifindex == 0) { 908 (void)strlcpy(ifr.ifr_name, i_arg, sizeof(ifr.ifr_name)); 909 if (ioctl(s, SIOCIFCREATE2, &ifr) < 0) 910 errx(EXIT_FAILURE, "Invalid bus interface: %s", i_arg); 911 } 912 913 for ( ; v >= USBPF_HDR_LEN; v >>= 1) { 914 (void)ioctl(fd, BIOCSBLEN, (caddr_t)&v); 915 (void)strlcpy(ifr.ifr_name, i_arg, sizeof(ifr.ifr_name)); 916 if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) >= 0) 917 break; 918 } 919 if (v == 0) 920 errx(EXIT_FAILURE, "No buffer size worked."); 921 922 if (ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) 923 err(EXIT_FAILURE, "BIOCGBLEN ioctl failed"); 924 925 p->bufsize = v; 926 p->buffer = (uint8_t *)malloc(p->bufsize); 927 if (p->buffer == NULL) 928 errx(EX_SOFTWARE, "Out of memory."); 929 930 make_filter(&total_prog, snapshot); 931 932 if (ioctl(p->fd, BIOCSETF, (caddr_t)&total_prog) < 0) 933 err(EXIT_FAILURE, "BIOCSETF ioctl failed"); 934 935 free_filter(&total_prog); 936 937 /* 1 second read timeout */ 938 tv.tv_sec = 1; 939 tv.tv_usec = 0; 940 if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&tv) < 0) 941 err(EXIT_FAILURE, "BIOCSRTIMEOUT ioctl failed"); 942 943 (void)signal(SIGINT, handle_sigint); 944 945 do_loop(p); 946 947 if (ioctl(fd, BIOCGSTATS, (caddr_t)&us) < 0) 948 err(EXIT_FAILURE, "BIOCGSTATS ioctl failed"); 949 950 /* XXX what's difference between pkt_captured and us.us_recv? */ 951 printf("\n"); 952 printf("%d packets captured\n", pkt_captured); 953 printf("%d packets received by filter\n", us.bs_recv); 954 printf("%d packets dropped by kernel\n", us.bs_drop); 955 956 /* 957 * Destroy the usbusN interface only if it was created by 958 * usbdump(8). Ignore when it was already destroyed. 959 */ 960 if (ifindex == 0 && if_nametoindex(i_arg) > 0) { 961 (void)strlcpy(ifr.ifr_name, i_arg, sizeof(ifr.ifr_name)); 962 if (ioctl(s, SIOCIFDESTROY, &ifr) < 0) 963 warn("SIOCIFDESTROY ioctl failed"); 964 } 965 close(s); 966 967 if (p->fd > 0) 968 close(p->fd); 969 if (p->rfd > 0) 970 close(p->rfd); 971 if (p->wfd > 0) 972 close(p->wfd); 973 if (p->bfd > 0) 974 close(p->bfd); 975 976 return (EXIT_SUCCESS); 977} 978