summaryrefslogtreecommitdiffstats
path: root/usr.sbin
diff options
context:
space:
mode:
authorweongyo <weongyo@FreeBSD.org>2010-11-22 01:28:29 +0000
committerweongyo <weongyo@FreeBSD.org>2010-11-22 01:28:29 +0000
commit08a93ec3b7a224311c5ad5e352f3b55bfb349524 (patch)
tree73a8a725566418172aab6f1237660b6e150a99ed /usr.sbin
parent1dec7bdf779e4fd81bb16a8ae1824b574065d674 (diff)
downloadFreeBSD-src-08a93ec3b7a224311c5ad5e352f3b55bfb349524.zip
FreeBSD-src-08a93ec3b7a224311c5ad5e352f3b55bfb349524.tar.gz
Adds usbdump(8) tool that currently it only supports the very basic
feature set. It's not connected to the build yet. Reviewed by: hps
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/usbdump/Makefile8
-rw-r--r--usr.sbin/usbdump/usbdump.877
-rw-r--r--usr.sbin/usbdump/usbdump.c542
3 files changed, 627 insertions, 0 deletions
diff --git a/usr.sbin/usbdump/Makefile b/usr.sbin/usbdump/Makefile
new file mode 100644
index 0000000..5188901
--- /dev/null
+++ b/usr.sbin/usbdump/Makefile
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+PROG= usbdump
+SRCS= usbdump.c
+MAN= usbdump.8
+WARNS?= 4
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/usbdump/usbdump.8 b/usr.sbin/usbdump/usbdump.8
new file mode 100644
index 0000000..edd883a
--- /dev/null
+++ b/usr.sbin/usbdump/usbdump.8
@@ -0,0 +1,77 @@
+.\"
+.\" Copyright (c) 2010 Weongyo Jeong.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd October 14, 2010
+.Dt usbdump 8
+.Os
+.Sh NAME
+.Nm usbdump
+.Nd "dump traffic on USB host controller"
+.Sh SYNOPSIS
+.Nm
+.Op Fl i Ar ifname
+.Op Fl r Ar file
+.Op Fl s Ar snaplen
+.Op Fl v
+.Op Fl w Ar file
+.Sh DESCRIPTION
+The
+.Nm
+utility provides a way to dump USB packets on each host controller.
+.Pp
+The following options are accepted.
+.Bl -tag -width ".Fl f Ar file"
+.It Fl i Ar ifname
+Listen on USB bus interface.
+.It Fl r Ar file
+Read the raw packets from file.
+.It Fl s Ar snaplen
+Snapshot bytes from each packet.
+.It Fl v
+Enable debugging messages.
+When it defined multiple times the verbose level increases.
+.It Fl w Ar file
+Write the raw packets to file.
+.El
+.Sh EXAMPLES
+Captures the USB raw packets alive on usbus2:
+.Pp
+.Dl "usbdump -i usbus2 -s 256 -v"
+.Pp
+Dumps the USB raw packets of usbus2 into the file without packet
+size limit:
+.Pp
+.Dl "usbdump -i usbus2 -s 0 -w /tmp/dump_pkts"
+.Pp
+Read the USB raw packets from the file:
+.Pp
+.Dl "usbdump -r /tmp/dump_pkts -v"
+.Sh SEE ALSO
+.Xr usbconfig 8
+.Sh AUTHORS
+.An Weongyo Jeong
+.Aq weongyo@FreeBSD.org .
diff --git a/usr.sbin/usbdump/usbdump.c b/usr.sbin/usbdump/usbdump.c
new file mode 100644
index 0000000..6545f1c
--- /dev/null
+++ b/usr.sbin/usbdump/usbdump.c
@@ -0,0 +1,542 @@
+/*-
+ * Copyright (c) 2010 Weongyo Jeong <weongyo@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ * redistribution must be conditioned upon including a substantially
+ * similar Disclaimer requirement for further binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/endian.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/utsname.h>
+#include <dev/usb/usb.h>
+#include <dev/usb/usb_pf.h>
+#include <dev/usb/usbdi.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+struct usbcap {
+ int fd; /* fd for /dev/usbpf */
+ u_int bufsize;
+ char *buffer;
+
+ /* for -w option */
+ int wfd;
+ /* for -r option */
+ int rfd;
+};
+
+struct usbcap_filehdr {
+ u_int magic;
+#define USBCAP_FILEHDR_MAGIC 0x9a90000e
+ u_char major;
+ u_char minor;
+ u_char reserved[26];
+} __packed;
+
+static int doexit = 0;
+static int pkt_captured = 0;
+static int verbose = 0;
+static const char *i_arg = "usbus0";;
+static const char *r_arg = NULL;
+static const char *w_arg = NULL;
+static const char *errstr_table[USB_ERR_MAX] = {
+ [USB_ERR_NORMAL_COMPLETION] = "NORMAL_COMPLETION",
+ [USB_ERR_PENDING_REQUESTS] = "PENDING_REQUESTS",
+ [USB_ERR_NOT_STARTED] = "NOT_STARTED",
+ [USB_ERR_INVAL] = "INVAL",
+ [USB_ERR_NOMEM] = "NOMEM",
+ [USB_ERR_CANCELLED] = "CANCELLED",
+ [USB_ERR_BAD_ADDRESS] = "BAD_ADDRESS",
+ [USB_ERR_BAD_BUFSIZE] = "BAD_BUFSIZE",
+ [USB_ERR_BAD_FLAG] = "BAD_FLAG",
+ [USB_ERR_NO_CALLBACK] = "NO_CALLBACK",
+ [USB_ERR_IN_USE] = "IN_USE",
+ [USB_ERR_NO_ADDR] = "NO_ADDR",
+ [USB_ERR_NO_PIPE] = "NO_PIPE",
+ [USB_ERR_ZERO_NFRAMES] = "ZERO_NFRAMES",
+ [USB_ERR_ZERO_MAXP] = "ZERO_MAXP",
+ [USB_ERR_SET_ADDR_FAILED] = "SET_ADDR_FAILED",
+ [USB_ERR_NO_POWER] = "NO_POWER",
+ [USB_ERR_TOO_DEEP] = "TOO_DEEP",
+ [USB_ERR_IOERROR] = "IOERROR",
+ [USB_ERR_NOT_CONFIGURED] = "NOT_CONFIGURED",
+ [USB_ERR_TIMEOUT] = "TIMEOUT",
+ [USB_ERR_SHORT_XFER] = "SHORT_XFER",
+ [USB_ERR_STALLED] = "STALLED",
+ [USB_ERR_INTERRUPTED] = "INTERRUPTED",
+ [USB_ERR_DMA_LOAD_FAILED] = "DMA_LOAD_FAILED",
+ [USB_ERR_BAD_CONTEXT] = "BAD_CONTEXT",
+ [USB_ERR_NO_ROOT_HUB] = "NO_ROOT_HUB",
+ [USB_ERR_NO_INTR_THREAD] = "NO_INTR_THREAD",
+ [USB_ERR_NOT_LOCKED] = "NOT_LOCKED",
+};
+
+static const char *xfertype_table[] = {
+ [UE_CONTROL] = "CTRL",
+ [UE_ISOCHRONOUS] = "ISOC",
+ [UE_BULK] = "BULK",
+ [UE_INTERRUPT] = "INTR"
+};
+
+static void
+handle_sigint(int sig)
+{
+
+ (void)sig;
+ doexit = 1;
+}
+
+static void
+print_flags(u_int32_t flags)
+{
+#define PRINTFLAGS(name) \
+ if ((flags & USBPF_FLAG_##name) != 0) \
+ printf("%s ", #name);
+ printf(" flags %#x", flags);
+ printf(" < ");
+ PRINTFLAGS(FORCE_SHORT_XFER);
+ PRINTFLAGS(SHORT_XFER_OK);
+ PRINTFLAGS(SHORT_FRAMES_OK);
+ PRINTFLAGS(PIPE_BOF);
+ PRINTFLAGS(PROXY_BUFFER);
+ PRINTFLAGS(EXT_BUFFER);
+ PRINTFLAGS(MANUAL_STATUS);
+ PRINTFLAGS(NO_PIPE_OK);
+ PRINTFLAGS(STALL_PIPE);
+ printf(">\n");
+#undef PRINTFLAGS
+}
+
+static void
+print_status(u_int32_t status)
+{
+#define PRINTSTATUS(name) \
+ if ((status & USBPF_STATUS_##name) != 0) \
+ printf("%s ", #name);
+
+ printf(" status %#x", status);
+ printf(" < ");
+ PRINTSTATUS(OPEN);
+ PRINTSTATUS(TRANSFERRING);
+ PRINTSTATUS(DID_DMA_DELAY);
+ PRINTSTATUS(DID_CLOSE);
+ PRINTSTATUS(DRAINING);
+ PRINTSTATUS(STARTED);
+ PRINTSTATUS(BW_RECLAIMED);
+ PRINTSTATUS(CONTROL_XFR);
+ PRINTSTATUS(CONTROL_HDR);
+ PRINTSTATUS(CONTROL_ACT);
+ PRINTSTATUS(CONTROL_STALL);
+ PRINTSTATUS(SHORT_FRAMES_OK);
+ PRINTSTATUS(SHORT_XFER_OK);
+#if USB_HAVE_BUSDMA
+ PRINTSTATUS(BDMA_ENABLE);
+ PRINTSTATUS(BDMA_NO_POST_SYNC);
+ PRINTSTATUS(BDMA_SETUP);
+#endif
+ PRINTSTATUS(ISOCHRONOUS_XFR);
+ PRINTSTATUS(CURR_DMA_SET);
+ PRINTSTATUS(CAN_CANCEL_IMMED);
+ PRINTSTATUS(DOING_CALLBACK);
+ printf(">\n");
+#undef PRINTSTATUS
+}
+
+/*
+ * Display a region in traditional hexdump format.
+ */
+static void
+hexdump(const char *region, size_t len)
+{
+ const char *line;
+ int x, c;
+ char lbuf[80];
+#define EMIT(fmt, args...) do { \
+ sprintf(lbuf, fmt , ## args); \
+ printf("%s", lbuf); \
+} while (0)
+
+ for (line = region; line < (region + len); line += 16) {
+ EMIT(" %04lx ", (long) (line - region));
+ for (x = 0; x < 16; x++) {
+ if ((line + x) < (region + len))
+ EMIT("%02x ", *(const u_int8_t *)(line + x));
+ else
+ EMIT("-- ");
+ if (x == 7)
+ EMIT(" ");
+ }
+ EMIT(" |");
+ for (x = 0; x < 16; x++) {
+ if ((line + x) < (region + len)) {
+ c = *(const u_int8_t *)(line + x);
+ /* !isprint(c) */
+ if ((c < ' ') || (c > '~'))
+ c = '.';
+ EMIT("%c", c);
+ } else
+ EMIT(" ");
+ }
+ EMIT("|\n");
+ }
+#undef EMIT
+}
+
+static void
+print_apacket(const struct usbpf_xhdr *hdr, struct usbpf_pkthdr *up,
+ const char *payload)
+{
+ struct tm *tm;
+ struct timeval tv;
+ size_t len;
+ u_int32_t framelen, x;
+ const char *ptr = payload;
+ char buf[64];
+
+ /* A packet from the kernel is based on little endian byte order. */
+ up->up_busunit = le32toh(up->up_busunit);
+ up->up_flags = le32toh(up->up_flags);
+ up->up_status = le32toh(up->up_status);
+ up->up_length = le32toh(up->up_length);
+ up->up_frames = le32toh(up->up_frames);
+ up->up_error = le32toh(up->up_error);
+ up->up_interval = le32toh(up->up_interval);
+
+ tv.tv_sec = hdr->uh_tstamp.ut_sec;
+ tv.tv_usec = hdr->uh_tstamp.ut_frac;
+ tm = localtime(&tv.tv_sec);
+
+ len = strftime(buf, sizeof(buf), "%H:%M:%S", tm);
+ printf("%.*s.%06ju", (int)len, buf, tv.tv_usec);
+ printf(" usbus%d.%d 0x%02x %s %s", up->up_busunit, up->up_address,
+ up->up_endpoint,
+ xfertype_table[up->up_xfertype],
+ up->up_type == USBPF_XFERTAP_SUBMIT ? ">" : "<");
+ printf(" (%d/%d)", up->up_frames, up->up_length);
+ if (up->up_type == USBPF_XFERTAP_DONE)
+ printf(" %s", errstr_table[up->up_error]);
+ if (up->up_xfertype == UE_BULK || up->up_xfertype == UE_ISOCHRONOUS)
+ printf(" %d", up->up_interval);
+ printf("\n");
+
+ if (verbose >= 1) {
+ for (x = 0; x < up->up_frames; x++) {
+ framelen = le32toh(*((const u_int32_t *)ptr));
+ ptr += sizeof(u_int32_t);
+ printf(" frame[%u] len %d\n", x, framelen);
+ assert(framelen < (1024 * 4));
+ hexdump(ptr, framelen);
+ ptr += framelen;
+ }
+ }
+ if (verbose >= 2) {
+ print_flags(up->up_flags);
+ print_status(up->up_status);
+ }
+}
+
+
+static void
+print_packets(char *data, const int datalen)
+{
+ struct usbpf_pkthdr *up;
+ const struct usbpf_xhdr *hdr;
+ u_int32_t framelen, x;
+ char *ptr, *next;
+
+ for (ptr = data; ptr < (data + datalen); ptr = next) {
+ hdr = (const struct usbpf_xhdr *)ptr;
+ up = (struct usbpf_pkthdr *)(ptr + hdr->uh_hdrlen);
+ next = ptr + USBPF_WORDALIGN(hdr->uh_hdrlen + hdr->uh_caplen);
+
+ ptr = ((char *)up) + sizeof(struct usbpf_pkthdr);
+ if (w_arg == NULL)
+ print_apacket(hdr, up, ptr);
+ pkt_captured++;
+ for (x = 0; x < up->up_frames; x++) {
+ framelen = le32toh(*((const u_int32_t *)ptr));
+ ptr += sizeof(u_int32_t) + framelen;
+ }
+ }
+}
+
+static void
+write_packets(struct usbcap *p, const char *data, const int datalen)
+{
+ int len = htole32(datalen), ret;
+
+ ret = write(p->wfd, &len, sizeof(int));
+ assert(ret == sizeof(int));
+ ret = write(p->wfd, data, datalen);
+ assert(ret == datalen);
+}
+
+static void
+read_file(struct usbcap *p)
+{
+ int datalen, ret;
+ char *data;
+
+ while ((ret = read(p->rfd, &datalen, sizeof(int))) == sizeof(int)) {
+ datalen = le32toh(datalen);
+ data = malloc(datalen);
+ assert(data != NULL);
+ ret = read(p->rfd, data, datalen);
+ assert(ret == datalen);
+ print_packets(data, datalen);
+ free(data);
+ }
+ if (ret == -1)
+ fprintf(stderr, "read: %s\n", strerror(errno));
+}
+
+static void
+do_loop(struct usbcap *p)
+{
+ int cc;
+
+ while (doexit == 0) {
+ cc = read(p->fd, (char *)p->buffer, p->bufsize);
+ if (cc < 0) {
+ switch (errno) {
+ case EINTR:
+ break;
+ default:
+ fprintf(stderr, "read: %s\n", strerror(errno));
+ return;
+ }
+ continue;
+ }
+ if (cc == 0)
+ continue;
+ if (w_arg != NULL)
+ write_packets(p, p->buffer, cc);
+ print_packets(p->buffer, cc);
+ }
+}
+
+static void
+init_rfile(struct usbcap *p)
+{
+ struct usbcap_filehdr uf;
+ int ret;
+
+ p->rfd = open(r_arg, O_RDONLY);
+ if (p->rfd < 0) {
+ fprintf(stderr, "open: %s (%s)\n", r_arg, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ ret = read(p->rfd, &uf, sizeof(uf));
+ assert(ret == sizeof(uf));
+ assert(le32toh(uf.magic) == USBCAP_FILEHDR_MAGIC);
+ assert(uf.major == 0);
+ assert(uf.minor == 1);
+}
+
+static void
+init_wfile(struct usbcap *p)
+{
+ struct usbcap_filehdr uf;
+ int ret;
+
+ p->wfd = open(w_arg, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR);
+ if (p->wfd < 0) {
+ fprintf(stderr, "open: %s (%s)\n", w_arg, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ bzero(&uf, sizeof(uf));
+ uf.magic = htole32(USBCAP_FILEHDR_MAGIC);
+ uf.major = 0;
+ uf.minor = 1;
+ ret = write(p->wfd, (const void *)&uf, sizeof(uf));
+ assert(ret == sizeof(uf));
+}
+
+static void
+usage(void)
+{
+
+#define FMT " %-14s %s\n"
+ fprintf(stderr, "usage: usbdump [options]\n");
+ fprintf(stderr, FMT, "-i ifname", "Listen on USB bus interface");
+ fprintf(stderr, FMT, "-r file", "Read the raw packets from file");
+ fprintf(stderr, FMT, "-s snaplen", "Snapshot bytes from each packet");
+ fprintf(stderr, FMT, "-v", "Increases the verbose level");
+ fprintf(stderr, FMT, "-w file", "Write the raw packets to file");
+#undef FMT
+ exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct timeval tv;
+ struct usbpf_insn total_insn;
+ struct usbpf_program total_prog;
+ struct usbpf_stat us;
+ struct usbpf_version uv;
+ struct usbcap uc, *p = &uc;
+ struct usbpf_ifreq ufr;
+ long snapshot = 192;
+ u_int v;
+ int fd, o;
+ const char *optstring;
+
+ bzero(&uc, sizeof(struct usbcap));
+
+ optstring = "i:r:s:vw:";
+ while ((o = getopt(argc, argv, optstring)) != -1) {
+ switch (o) {
+ case 'i':
+ i_arg = optarg;
+ break;
+ case 'r':
+ r_arg = optarg;
+ init_rfile(p);
+ break;
+ case 's':
+ snapshot = strtol(optarg, NULL, 10);
+ errno = 0;
+ if (snapshot == 0 && errno == EINVAL)
+ usage();
+ /* snapeshot == 0 is special */
+ if (snapshot == 0)
+ snapshot = -1;
+ break;
+ case 'v':
+ verbose++;
+ break;
+ case 'w':
+ w_arg = optarg;
+ init_wfile(p);
+ break;
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+
+ if (r_arg != NULL) {
+ read_file(p);
+ exit(EXIT_SUCCESS);
+ }
+
+ p->fd = fd = open("/dev/usbpf", O_RDONLY);
+ if (p->fd < 0) {
+ fprintf(stderr, "(no devices found)\n");
+ return (EXIT_FAILURE);
+ }
+
+ if (ioctl(fd, UIOCVERSION, (caddr_t)&uv) < 0) {
+ fprintf(stderr, "UIOCVERSION: %s\n", strerror(errno));
+ return (EXIT_FAILURE);
+ }
+ if (uv.uv_major != USBPF_MAJOR_VERSION ||
+ uv.uv_minor < USBPF_MINOR_VERSION) {
+ fprintf(stderr, "kernel bpf filter out of date");
+ return (EXIT_FAILURE);
+ }
+
+ if ((ioctl(fd, UIOCGBLEN, (caddr_t)&v) < 0) || v < 65536)
+ v = 65536;
+ for ( ; v != 0; v >>= 1) {
+ (void)ioctl(fd, UIOCSBLEN, (caddr_t)&v);
+ (void)strncpy(ufr.ufr_name, i_arg, sizeof(ufr.ufr_name));
+ if (ioctl(fd, UIOCSETIF, (caddr_t)&ufr) >= 0)
+ break;
+ }
+ if (v == 0) {
+ fprintf(stderr, "UIOCSBLEN: %s: No buffer size worked", i_arg);
+ return (EXIT_FAILURE);
+ }
+
+ if (ioctl(fd, UIOCGBLEN, (caddr_t)&v) < 0) {
+ fprintf(stderr, "UIOCGBLEN: %s", strerror(errno));
+ return (EXIT_FAILURE);
+ }
+
+ p->bufsize = v;
+ p->buffer = (u_char *)malloc(p->bufsize);
+ if (p->buffer == NULL) {
+ fprintf(stderr, "malloc: %s", strerror(errno));
+ return (EXIT_FAILURE);
+ }
+
+ /* XXX no read filter rules yet so at this moment accept everything */
+ total_insn.code = (u_short)(USBPF_RET | USBPF_K);
+ total_insn.jt = 0;
+ total_insn.jf = 0;
+ total_insn.k = snapshot;
+
+ total_prog.uf_len = 1;
+ total_prog.uf_insns = &total_insn;
+ if (ioctl(p->fd, UIOCSETF, (caddr_t)&total_prog) < 0) {
+ fprintf(stderr, "UIOCSETF: %s", strerror(errno));
+ return (EXIT_FAILURE);
+ }
+
+ /* 1 second read timeout */
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ if (ioctl(p->fd, UIOCSRTIMEOUT, (caddr_t)&tv) < 0) {
+ fprintf(stderr, "UIOCSRTIMEOUT: %s", strerror(errno));
+ return (EXIT_FAILURE);
+ }
+
+ (void)signal(SIGINT, handle_sigint);
+
+ do_loop(p);
+
+ if (ioctl(fd, UIOCGSTATS, (caddr_t)&us) < 0) {
+ fprintf(stderr, "UIOCGSTATS: %s", strerror(errno));
+ return (EXIT_FAILURE);
+ }
+
+ /* XXX what's difference between pkt_captured and us.us_recv? */
+ printf("\n");
+ printf("%d packets captured\n", pkt_captured);
+ printf("%d packets received by filter\n", us.us_recv);
+ printf("%d packets dropped by kernel\n", us.us_drop);
+
+ if (p->fd > 0)
+ close(p->fd);
+ if (p->rfd > 0)
+ close(p->rfd);
+ if (p->wfd > 0)
+ close(p->wfd);
+
+ return (EXIT_SUCCESS);
+}
OpenPOWER on IntegriCloud