usbdump.c revision 215651
1139738Simp/*- 284996Srobert * Copyright (c) 2010 Weongyo Jeong <weongyo@freebsd.org> 384996Srobert * All rights reserved. 484996Srobert * 584996Srobert * Redistribution and use in source and binary forms, with or without 684996Srobert * modification, are permitted provided that the following conditions 7181398Smarius * are met: 884996Srobert * 1. Redistributions of source code must retain the above copyright 9182916Smarius * notice, this list of conditions and the following disclaimer, 10238851Smarius * without modification. 11182916Smarius * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12182916Smarius * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13182916Smarius * redistribution must be conditioned upon including a substantially 14182916Smarius * similar Disclaimer requirement for further binary redistribution. 15182916Smarius * 16182916Smarius * NO WARRANTY 17182916Smarius * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18182916Smarius * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19182916Smarius * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20182916Smarius * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21182916Smarius * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22182916Smarius * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23182916Smarius * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24182916Smarius * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25182916Smarius * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26182916Smarius * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27182916Smarius * THE POSSIBILITY OF SUCH DAMAGES. 28182916Smarius * 29182916Smarius * $FreeBSD: head/usr.sbin/usbdump/usbdump.c 215651 2010-11-22 01:28:29Z weongyo $ 30182916Smarius */ 31182916Smarius 32182916Smarius#include <sys/param.h> 33182916Smarius#include <sys/endian.h> 34124139Sobrien#include <sys/ioctl.h> 35124139Sobrien#include <sys/stat.h> 36124139Sobrien#include <sys/utsname.h> 37182020Smarius#include <dev/usb/usb.h> 3884996Srobert#include <dev/usb/usb_pf.h> 3984996Srobert#include <dev/usb/usbdi.h> 4084996Srobert#include <assert.h> 4184996Srobert#include <errno.h> 4284996Srobert#include <fcntl.h> 4384996Srobert#include <limits.h> 4484996Srobert#include <stdio.h> 4584996Srobert#include <stdlib.h> 4684996Srobert#include <string.h> 4791139Sjake#include <time.h> 4884996Srobert#include <unistd.h> 49203829Smarius 5084996Srobertstruct usbcap { 51203829Smarius int fd; /* fd for /dev/usbpf */ 52102219Srobert u_int bufsize; 53163145Skmacy char *buffer; 54234898Smarius 55234898Smarius /* for -w option */ 56235364Savg int wfd; 57234898Smarius /* for -r option */ 5884996Srobert int rfd; 59163145Skmacy}; 6084996Srobert 61203829Smariusstruct usbcap_filehdr { 6291139Sjake u_int magic; 6384996Srobert#define USBCAP_FILEHDR_MAGIC 0x9a90000e 64203829Smarius u_char major; 65203829Smarius u_char minor; 6691110Sjake u_char reserved[26]; 6791110Sjake} __packed; 6884996Srobert 69181398Smariusstatic int doexit = 0; 7091139Sjakestatic int pkt_captured = 0; 71182478Smariusstatic int verbose = 0; 72182877Smariusstatic const char *i_arg = "usbus0";; 7384996Srobertstatic const char *r_arg = NULL; 7484996Srobertstatic const char *w_arg = NULL; 7584996Srobertstatic const char *errstr_table[USB_ERR_MAX] = { 7685719Sjake [USB_ERR_NORMAL_COMPLETION] = "NORMAL_COMPLETION", 7784996Srobert [USB_ERR_PENDING_REQUESTS] = "PENDING_REQUESTS", 78170839Smarius [USB_ERR_NOT_STARTED] = "NOT_STARTED", 79170839Smarius [USB_ERR_INVAL] = "INVAL", 8084996Srobert [USB_ERR_NOMEM] = "NOMEM", 8184996Srobert [USB_ERR_CANCELLED] = "CANCELLED", 8284996Srobert [USB_ERR_BAD_ADDRESS] = "BAD_ADDRESS", 8384996Srobert [USB_ERR_BAD_BUFSIZE] = "BAD_BUFSIZE", 8484996Srobert [USB_ERR_BAD_FLAG] = "BAD_FLAG", 8584996Srobert [USB_ERR_NO_CALLBACK] = "NO_CALLBACK", 86203829Smarius [USB_ERR_IN_USE] = "IN_USE", 87203829Smarius [USB_ERR_NO_ADDR] = "NO_ADDR", 88203829Smarius [USB_ERR_NO_PIPE] = "NO_PIPE", 89170839Smarius [USB_ERR_ZERO_NFRAMES] = "ZERO_NFRAMES", 90163145Skmacy [USB_ERR_ZERO_MAXP] = "ZERO_MAXP", 91163145Skmacy [USB_ERR_SET_ADDR_FAILED] = "SET_ADDR_FAILED", 92163145Skmacy [USB_ERR_NO_POWER] = "NO_POWER", 93163145Skmacy [USB_ERR_TOO_DEEP] = "TOO_DEEP", 9485719Sjake [USB_ERR_IOERROR] = "IOERROR", 95170839Smarius [USB_ERR_NOT_CONFIGURED] = "NOT_CONFIGURED", 9685719Sjake [USB_ERR_TIMEOUT] = "TIMEOUT", 97223719Smarius [USB_ERR_SHORT_XFER] = "SHORT_XFER", 98203830Smarius [USB_ERR_STALLED] = "STALLED", 99181398Smarius [USB_ERR_INTERRUPTED] = "INTERRUPTED", 100223719Smarius [USB_ERR_DMA_LOAD_FAILED] = "DMA_LOAD_FAILED", 101203830Smarius [USB_ERR_BAD_CONTEXT] = "BAD_CONTEXT", 102181398Smarius [USB_ERR_NO_ROOT_HUB] = "NO_ROOT_HUB", 103182916Smarius [USB_ERR_NO_INTR_THREAD] = "NO_INTR_THREAD", 10485719Sjake [USB_ERR_NOT_LOCKED] = "NOT_LOCKED", 105170839Smarius}; 106170839Smarius 107170839Smariusstatic const char *xfertype_table[] = { 108170854Smarius [UE_CONTROL] = "CTRL", 109170854Smarius [UE_ISOCHRONOUS] = "ISOC", 110170854Smarius [UE_BULK] = "BULK", 111170854Smarius [UE_INTERRUPT] = "INTR" 112114386Speter}; 113163145Skmacy 114170839Smariusstatic void 115203829Smariushandle_sigint(int sig) 116203829Smarius{ 117203829Smarius 118163145Skmacy (void)sig; 11984996Srobert doexit = 1; 120181398Smarius} 121181398Smarius 122181398Smariusstatic void 123181398Smariusprint_flags(u_int32_t flags) 124181398Smarius{ 125181398Smarius#define PRINTFLAGS(name) \ 126181398Smarius if ((flags & USBPF_FLAG_##name) != 0) \ 127170839Smarius printf("%s ", #name); 128163145Skmacy printf(" flags %#x", flags); 129163145Skmacy printf(" < "); 13097445Sjake PRINTFLAGS(FORCE_SHORT_XFER); 13197445Sjake PRINTFLAGS(SHORT_XFER_OK); 132203829Smarius PRINTFLAGS(SHORT_FRAMES_OK); 133203829Smarius PRINTFLAGS(PIPE_BOF); 134204152Smarius PRINTFLAGS(PROXY_BUFFER); 135203829Smarius PRINTFLAGS(EXT_BUFFER); 136203829Smarius PRINTFLAGS(MANUAL_STATUS); 137223719Smarius PRINTFLAGS(NO_PIPE_OK); 13891139Sjake PRINTFLAGS(STALL_PIPE); 139170839Smarius printf(">\n"); 140170839Smarius#undef PRINTFLAGS 141163145Skmacy} 142236581Smarius 143170854Smariusstatic void 14484996Srobertprint_status(u_int32_t status) 14584996Srobert{ 14684996Srobert#define PRINTSTATUS(name) \ 14784996Srobert if ((status & USBPF_STATUS_##name) != 0) \ 14884996Srobert printf("%s ", #name); 14984996Srobert 15085719Sjake printf(" status %#x", status); 15184996Srobert printf(" < "); 15285719Sjake PRINTSTATUS(OPEN); 15385719Sjake PRINTSTATUS(TRANSFERRING); 15485719Sjake PRINTSTATUS(DID_DMA_DELAY); 15585719Sjake PRINTSTATUS(DID_CLOSE); 156234898Smarius PRINTSTATUS(DRAINING); 157235364Savg PRINTSTATUS(STARTED); 158234898Smarius PRINTSTATUS(BW_RECLAIMED); 15984996Srobert PRINTSTATUS(CONTROL_XFR); 16084996Srobert PRINTSTATUS(CONTROL_HDR); 16184996Srobert PRINTSTATUS(CONTROL_ACT); 16284996Srobert PRINTSTATUS(CONTROL_STALL); 163170839Smarius PRINTSTATUS(SHORT_FRAMES_OK); 164114386Speter PRINTSTATUS(SHORT_XFER_OK); 165114386Speter#if USB_HAVE_BUSDMA 16684996Srobert PRINTSTATUS(BDMA_ENABLE); 16784996Srobert PRINTSTATUS(BDMA_NO_POST_SYNC); 16884996Srobert PRINTSTATUS(BDMA_SETUP); 16984996Srobert#endif 17084996Srobert PRINTSTATUS(ISOCHRONOUS_XFR); 171234898Smarius PRINTSTATUS(CURR_DMA_SET); 17284996Srobert PRINTSTATUS(CAN_CANCEL_IMMED); 17391110Sjake PRINTSTATUS(DOING_CALLBACK); 17484996Srobert printf(">\n"); 17585719Sjake#undef PRINTSTATUS 17693606Stmm} 17793606Stmm 17893606Stmm/* 179234898Smarius * Display a region in traditional hexdump format. 180234898Smarius */ 181234898Smariusstatic void 182108100Sjakehexdump(const char *region, size_t len) 183105065Sjake{ 184105065Sjake const char *line; 185108100Sjake int x, c; 186108100Sjake char lbuf[80]; 187108100Sjake#define EMIT(fmt, args...) do { \ 188105065Sjake sprintf(lbuf, fmt , ## args); \ 189105065Sjake printf("%s", lbuf); \ 190105065Sjake} while (0) 191117448Stmm 19285719Sjake for (line = region; line < (region + len); line += 16) { 19385719Sjake EMIT(" %04lx ", (long) (line - region)); 19491110Sjake for (x = 0; x < 16; x++) { 19591110Sjake if ((line + x) < (region + len)) 19691110Sjake EMIT("%02x ", *(const u_int8_t *)(line + x)); 19784996Srobert else 19884996Srobert EMIT("-- "); 19985719Sjake if (x == 7) 20085719Sjake EMIT(" "); 20185719Sjake } 20285719Sjake EMIT(" |"); 20385719Sjake for (x = 0; x < 16; x++) { 20485719Sjake if ((line + x) < (region + len)) { 20584996Srobert c = *(const u_int8_t *)(line + x); 20684996Srobert /* !isprint(c) */ 20784996Srobert if ((c < ' ') || (c > '~')) 20884996Srobert c = '.'; 20984996Srobert EMIT("%c", c); 21084996Srobert } else 21184996Srobert EMIT(" "); 21291110Sjake } 21391110Sjake EMIT("|\n"); 21491110Sjake } 21591110Sjake#undef EMIT 21691110Sjake} 21791110Sjake 21891110Sjakestatic void 21991110Sjakeprint_apacket(const struct usbpf_xhdr *hdr, struct usbpf_pkthdr *up, 22091110Sjake const char *payload) 22191110Sjake{ 22291110Sjake struct tm *tm; 22391110Sjake struct timeval tv; 22491110Sjake size_t len; 22591110Sjake u_int32_t framelen, x; 22691110Sjake const char *ptr = payload; 22791110Sjake char buf[64]; 22891110Sjake 22991110Sjake /* A packet from the kernel is based on little endian byte order. */ 23091110Sjake up->up_busunit = le32toh(up->up_busunit); 23191110Sjake up->up_flags = le32toh(up->up_flags); 23291110Sjake up->up_status = le32toh(up->up_status); 23391110Sjake up->up_length = le32toh(up->up_length); 23491110Sjake up->up_frames = le32toh(up->up_frames); 23591110Sjake up->up_error = le32toh(up->up_error); 23691110Sjake up->up_interval = le32toh(up->up_interval); 23791110Sjake 23891110Sjake tv.tv_sec = hdr->uh_tstamp.ut_sec; 23991110Sjake tv.tv_usec = hdr->uh_tstamp.ut_frac; 24091110Sjake tm = localtime(&tv.tv_sec); 24191110Sjake 24291110Sjake len = strftime(buf, sizeof(buf), "%H:%M:%S", tm); 24391110Sjake printf("%.*s.%06ju", (int)len, buf, tv.tv_usec); 24491110Sjake printf(" usbus%d.%d 0x%02x %s %s", up->up_busunit, up->up_address, 24591110Sjake up->up_endpoint, 24691110Sjake xfertype_table[up->up_xfertype], 24791110Sjake up->up_type == USBPF_XFERTAP_SUBMIT ? ">" : "<"); 24891110Sjake printf(" (%d/%d)", up->up_frames, up->up_length); 24991110Sjake if (up->up_type == USBPF_XFERTAP_DONE) 25091110Sjake printf(" %s", errstr_table[up->up_error]); 25191110Sjake if (up->up_xfertype == UE_BULK || up->up_xfertype == UE_ISOCHRONOUS) 25291110Sjake printf(" %d", up->up_interval); 25391110Sjake printf("\n"); 25491110Sjake 25591110Sjake if (verbose >= 1) { 25691110Sjake for (x = 0; x < up->up_frames; x++) { 25791110Sjake framelen = le32toh(*((const u_int32_t *)ptr)); 25891110Sjake ptr += sizeof(u_int32_t); 25991110Sjake printf(" frame[%u] len %d\n", x, framelen); 26091110Sjake assert(framelen < (1024 * 4)); 26191110Sjake hexdump(ptr, framelen); 26291110Sjake ptr += framelen; 26391110Sjake } 26491110Sjake } 26584996Srobert if (verbose >= 2) { 26684996Srobert print_flags(up->up_flags); 26784996Srobert print_status(up->up_status); 26884996Srobert } 26984996Srobert} 27084996Srobert 271170839Smarius 272170839Smariusstatic void 27384996Srobertprint_packets(char *data, const int datalen) 27484996Srobert{ 27584996Srobert struct usbpf_pkthdr *up; 27684996Srobert const struct usbpf_xhdr *hdr; 27784996Srobert u_int32_t framelen, x; 278170839Smarius char *ptr, *next; 279163145Skmacy 280170839Smarius for (ptr = data; ptr < (data + datalen); ptr = next) { 28184996Srobert hdr = (const struct usbpf_xhdr *)ptr; 28284996Srobert up = (struct usbpf_pkthdr *)(ptr + hdr->uh_hdrlen); 28384996Srobert next = ptr + USBPF_WORDALIGN(hdr->uh_hdrlen + hdr->uh_caplen); 28484996Srobert 28584996Srobert ptr = ((char *)up) + sizeof(struct usbpf_pkthdr); 286170839Smarius if (w_arg == NULL) 287163145Skmacy print_apacket(hdr, up, ptr); 28884996Srobert pkt_captured++; 289170839Smarius for (x = 0; x < up->up_frames; x++) { 29084996Srobert framelen = le32toh(*((const u_int32_t *)ptr)); 29184996Srobert ptr += sizeof(u_int32_t) + framelen; 29284996Srobert } 29384996Srobert } 29484996Srobert} 295170854Smarius 296170854Smariusstatic void 297170854Smariuswrite_packets(struct usbcap *p, const char *data, const int datalen) 298170854Smarius{ 299170854Smarius int len = htole32(datalen), ret; 300170854Smarius 301170854Smarius ret = write(p->wfd, &len, sizeof(int)); 302170854Smarius assert(ret == sizeof(int)); 303170854Smarius ret = write(p->wfd, data, datalen); 304170854Smarius assert(ret == datalen); 305170854Smarius} 306170854Smarius 307170854Smariusstatic void 308170854Smariusread_file(struct usbcap *p) 309170854Smarius{ 310170854Smarius int datalen, ret; 311170854Smarius char *data; 312170854Smarius 313170854Smarius while ((ret = read(p->rfd, &datalen, sizeof(int))) == sizeof(int)) { 314170854Smarius datalen = le32toh(datalen); 315170854Smarius data = malloc(datalen); 31684996Srobert assert(data != NULL); 317170854Smarius ret = read(p->rfd, data, datalen); 318170854Smarius assert(ret == datalen); 319170854Smarius print_packets(data, datalen); 320170854Smarius free(data); 321170854Smarius } 322170854Smarius if (ret == -1) 323170854Smarius fprintf(stderr, "read: %s\n", strerror(errno)); 324170854Smarius} 325170854Smarius 326170854Smariusstatic void 327170854Smariusdo_loop(struct usbcap *p) 328170854Smarius{ 329170854Smarius int cc; 330170854Smarius 331170854Smarius while (doexit == 0) { 332170854Smarius cc = read(p->fd, (char *)p->buffer, p->bufsize); 333114386Speter if (cc < 0) { 33484996Srobert switch (errno) { 33584996Srobert case EINTR: 33685719Sjake break; 337116415Sjake default: 33891139Sjake fprintf(stderr, "read: %s\n", strerror(errno)); 33985719Sjake return; 34084996Srobert } 341170839Smarius continue; 342170839Smarius } 34391139Sjake if (cc == 0) 34484996Srobert continue; 34585719Sjake if (w_arg != NULL) 346170839Smarius write_packets(p, p->buffer, cc); 34784996Srobert print_packets(p->buffer, cc); 34891139Sjake } 349188455Smarius} 350181398Smarius 35184996Srobertstatic void 35285719Sjakeinit_rfile(struct usbcap *p) 353200946Smarius{ 354200946Smarius struct usbcap_filehdr uf; 355116415Sjake int ret; 356116415Sjake 357165325Skmacy p->rfd = open(r_arg, O_RDONLY); 358116415Sjake if (p->rfd < 0) { 359116415Sjake fprintf(stderr, "open: %s (%s)\n", r_arg, strerror(errno)); 360116415Sjake exit(EXIT_FAILURE); 361170854Smarius } 36284996Srobert ret = read(p->rfd, &uf, sizeof(uf)); 36384996Srobert assert(ret == sizeof(uf)); 364182478Smarius assert(le32toh(uf.magic) == USBCAP_FILEHDR_MAGIC); 365223719Smarius assert(uf.major == 0); 366182478Smarius assert(uf.minor == 1); 367223719Smarius} 368182478Smarius 369223719Smariusstatic void 370182478Smariusinit_wfile(struct usbcap *p) 371223719Smarius{ 372223719Smarius struct usbcap_filehdr uf; 373182478Smarius int ret; 374223719Smarius 375223719Smarius p->wfd = open(w_arg, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR); 376223719Smarius if (p->wfd < 0) { 377223719Smarius fprintf(stderr, "open: %s (%s)\n", w_arg, strerror(errno)); 378223719Smarius exit(EXIT_FAILURE); 379223719Smarius } 380182478Smarius bzero(&uf, sizeof(uf)); 381182478Smarius uf.magic = htole32(USBCAP_FILEHDR_MAGIC); 382182478Smarius uf.major = 0; 383223719Smarius uf.minor = 1; 384182478Smarius ret = write(p->wfd, (const void *)&uf, sizeof(uf)); 385223719Smarius assert(ret == sizeof(uf)); 386182478Smarius} 387223719Smarius 388182478Smariusstatic void 389223719Smariususage(void) 390223719Smarius{ 391182478Smarius 392223719Smarius#define FMT " %-14s %s\n" 393223719Smarius fprintf(stderr, "usage: usbdump [options]\n"); 394223719Smarius fprintf(stderr, FMT, "-i ifname", "Listen on USB bus interface"); 395223719Smarius fprintf(stderr, FMT, "-r file", "Read the raw packets from file"); 396223719Smarius fprintf(stderr, FMT, "-s snaplen", "Snapshot bytes from each packet"); 397223719Smarius fprintf(stderr, FMT, "-v", "Increases the verbose level"); 398182478Smarius fprintf(stderr, FMT, "-w file", "Write the raw packets to file"); 399182478Smarius#undef FMT 400181398Smarius exit(1); 401181398Smarius} 402181398Smarius 403182766Smariusint 404223719Smariusmain(int argc, char *argv[]) 405181398Smarius{ 406182766Smarius struct timeval tv; 407182766Smarius struct usbpf_insn total_insn; 408181398Smarius struct usbpf_program total_prog; 409223719Smarius struct usbpf_stat us; 410223719Smarius struct usbpf_version uv; 411181398Smarius struct usbcap uc, *p = &uc; 412181398Smarius struct usbpf_ifreq ufr; 413223719Smarius long snapshot = 192; 414182766Smarius u_int v; 415191071Smarius int fd, o; 416207537Smarius const char *optstring; 417207537Smarius 418191071Smarius bzero(&uc, sizeof(struct usbcap)); 419191071Smarius 420181398Smarius optstring = "i:r:s:vw:"; 421182766Smarius while ((o = getopt(argc, argv, optstring)) != -1) { 422181398Smarius switch (o) { 423181398Smarius case 'i': 424181398Smarius i_arg = optarg; 425181398Smarius break; 426181398Smarius case 'r': 427181398Smarius r_arg = optarg; 428182766Smarius init_rfile(p); 429181398Smarius break; 430181398Smarius case 's': 431182766Smarius snapshot = strtol(optarg, NULL, 10); 432182766Smarius errno = 0; 433181398Smarius if (snapshot == 0 && errno == EINVAL) 434223719Smarius usage(); 435223719Smarius /* snapeshot == 0 is special */ 436181398Smarius if (snapshot == 0) 437181398Smarius snapshot = -1; 438223719Smarius break; 439182766Smarius case 'v': 440191071Smarius verbose++; 441207537Smarius break; 442207537Smarius case 'w': 443191071Smarius w_arg = optarg; 444191071Smarius init_wfile(p); 445181398Smarius break; 446182766Smarius default: 447181398Smarius usage(); 448181398Smarius /* NOTREACHED */ 449181398Smarius } 450203830Smarius } 451203830Smarius 452181398Smarius if (r_arg != NULL) { 453181398Smarius read_file(p); 454203830Smarius exit(EXIT_SUCCESS); 455203830Smarius } 456181398Smarius 457181398Smarius p->fd = fd = open("/dev/usbpf", O_RDONLY); 458203830Smarius if (p->fd < 0) { 459203830Smarius fprintf(stderr, "(no devices found)\n"); 460181398Smarius return (EXIT_FAILURE); 461181398Smarius } 462203830Smarius 463203830Smarius if (ioctl(fd, UIOCVERSION, (caddr_t)&uv) < 0) { 464203830Smarius fprintf(stderr, "UIOCVERSION: %s\n", strerror(errno)); 465203830Smarius return (EXIT_FAILURE); 466203830Smarius } 467203830Smarius if (uv.uv_major != USBPF_MAJOR_VERSION || 468181398Smarius uv.uv_minor < USBPF_MINOR_VERSION) { 469181398Smarius fprintf(stderr, "kernel bpf filter out of date"); 470182916Smarius return (EXIT_FAILURE); 471182916Smarius } 472182916Smarius 473182916Smarius if ((ioctl(fd, UIOCGBLEN, (caddr_t)&v) < 0) || v < 65536) 474182916Smarius v = 65536; 475182916Smarius for ( ; v != 0; v >>= 1) { 476182916Smarius (void)ioctl(fd, UIOCSBLEN, (caddr_t)&v); 477182916Smarius (void)strncpy(ufr.ufr_name, i_arg, sizeof(ufr.ufr_name)); 478182916Smarius if (ioctl(fd, UIOCSETIF, (caddr_t)&ufr) >= 0) 479182916Smarius break; 480182916Smarius } 481182916Smarius if (v == 0) { 482223719Smarius fprintf(stderr, "UIOCSBLEN: %s: No buffer size worked", i_arg); 483182916Smarius return (EXIT_FAILURE); 484182916Smarius } 485182916Smarius 486182916Smarius if (ioctl(fd, UIOCGBLEN, (caddr_t)&v) < 0) { 487182916Smarius fprintf(stderr, "UIOCGBLEN: %s", strerror(errno)); 488182916Smarius return (EXIT_FAILURE); 489223719Smarius } 490182916Smarius 491182916Smarius p->bufsize = v; 492182916Smarius p->buffer = (u_char *)malloc(p->bufsize); 493182916Smarius if (p->buffer == NULL) { 494182916Smarius fprintf(stderr, "malloc: %s", strerror(errno)); 495182916Smarius return (EXIT_FAILURE); 496182916Smarius } 497182916Smarius 498182916Smarius /* XXX no read filter rules yet so at this moment accept everything */ 499223719Smarius total_insn.code = (u_short)(USBPF_RET | USBPF_K); 500182916Smarius total_insn.jt = 0; 501182916Smarius total_insn.jf = 0; 502182916Smarius total_insn.k = snapshot; 503223719Smarius 504223719Smarius total_prog.uf_len = 1; 505182916Smarius total_prog.uf_insns = &total_insn; 506182916Smarius if (ioctl(p->fd, UIOCSETF, (caddr_t)&total_prog) < 0) { 507182916Smarius fprintf(stderr, "UIOCSETF: %s", strerror(errno)); 508182916Smarius return (EXIT_FAILURE); 509182916Smarius } 510182916Smarius 511182916Smarius /* 1 second read timeout */ 512182916Smarius tv.tv_sec = 1; 51384996Srobert tv.tv_usec = 0; 514163145Skmacy if (ioctl(p->fd, UIOCSRTIMEOUT, (caddr_t)&tv) < 0) { 51584996Srobert fprintf(stderr, "UIOCSRTIMEOUT: %s", strerror(errno)); 51691110Sjake return (EXIT_FAILURE); 51797445Sjake } 518203830Smarius 51984996Srobert (void)signal(SIGINT, handle_sigint); 52084996Srobert 52184996Srobert do_loop(p); 52284996Srobert 52391110Sjake if (ioctl(fd, UIOCGSTATS, (caddr_t)&us) < 0) { 52485719Sjake fprintf(stderr, "UIOCGSTATS: %s", strerror(errno)); 52585719Sjake return (EXIT_FAILURE); 52684996Srobert } 527181398Smarius 528181398Smarius /* XXX what's difference between pkt_captured and us.us_recv? */ 529182020Smarius printf("\n"); 53091110Sjake printf("%d packets captured\n", pkt_captured); 531170854Smarius printf("%d packets received by filter\n", us.us_recv); 53291110Sjake printf("%d packets dropped by kernel\n", us.us_drop); 533170854Smarius 534170854Smarius if (p->fd > 0) 535170839Smarius close(p->fd); 536170854Smarius if (p->rfd > 0) 53791110Sjake close(p->rfd); 538170854Smarius if (p->wfd > 0) 539182020Smarius close(p->wfd); 540182020Smarius 541182020Smarius return (EXIT_SUCCESS); 54291110Sjake} 54391110Sjake