summaryrefslogtreecommitdiffstats
path: root/usr.sbin
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2010-11-22 20:52:18 +0000
committerdim <dim@FreeBSD.org>2010-11-22 20:52:18 +0000
commit71b42433f68a7680bcd07cef6c81b5a9bbe4e948 (patch)
tree09b00ba0fbac964aa5e3af51d7a50e20465b2577 /usr.sbin
parent29458224998b52266f5d890a3d9bff4c1f5d3ccb (diff)
parent11b4830687fabb0a27817feb05bf835db82f3147 (diff)
downloadFreeBSD-src-71b42433f68a7680bcd07cef6c81b5a9bbe4e948.zip
FreeBSD-src-71b42433f68a7680bcd07cef6c81b5a9bbe4e948.tar.gz
Sync: merge r215464 through r215708 from ^/head.
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/apmd/apmdlex.l1
-rw-r--r--usr.sbin/bluetooth/bthidd/lexer.l2
-rw-r--r--usr.sbin/bluetooth/hcsecd/lexer.l2
-rw-r--r--usr.sbin/config/lang.l1
-rw-r--r--usr.sbin/kbdcontrol/lex.l1
-rw-r--r--usr.sbin/mfiutil/mfi_config.c28
-rw-r--r--usr.sbin/mfiutil/mfi_evt.c4
-rw-r--r--usr.sbin/mfiutil/mfi_flash.c4
-rw-r--r--usr.sbin/mptutil/mpt_config.c2
-rw-r--r--usr.sbin/newsyslog/newsyslog.c2
-rw-r--r--usr.sbin/sysinstall/dispatch.c32
-rw-r--r--usr.sbin/usbdump/Makefile8
-rw-r--r--usr.sbin/usbdump/usbdump.877
-rw-r--r--usr.sbin/usbdump/usbdump.c542
14 files changed, 692 insertions, 14 deletions
diff --git a/usr.sbin/apmd/apmdlex.l b/usr.sbin/apmd/apmdlex.l
index 0f95574..dc7664d 100644
--- a/usr.sbin/apmd/apmdlex.l
+++ b/usr.sbin/apmd/apmdlex.l
@@ -38,6 +38,7 @@
/* We don't need it, avoid the warning. */
#define YY_NO_UNPUT
+#define YY_NO_INPUT
int lineno;
int first_time;
diff --git a/usr.sbin/bluetooth/bthidd/lexer.l b/usr.sbin/bluetooth/bthidd/lexer.l
index a25ae92..54821da 100644
--- a/usr.sbin/bluetooth/bthidd/lexer.l
+++ b/usr.sbin/bluetooth/bthidd/lexer.l
@@ -39,7 +39,7 @@
int yylex (void);
%}
-%option yylineno noyywrap nounput
+%option yylineno noyywrap nounput noinput
delim [ \t\n]
ws {delim}+
diff --git a/usr.sbin/bluetooth/hcsecd/lexer.l b/usr.sbin/bluetooth/hcsecd/lexer.l
index 2430d7e..578b42f 100644
--- a/usr.sbin/bluetooth/hcsecd/lexer.l
+++ b/usr.sbin/bluetooth/hcsecd/lexer.l
@@ -34,7 +34,7 @@
#include "parser.h"
%}
-%option yylineno noyywrap nounput
+%option yylineno noyywrap nounput noinput
delim [ \t\n]
ws {delim}+
diff --git a/usr.sbin/config/lang.l b/usr.sbin/config/lang.l
index 4eb94da..81f820f 100644
--- a/usr.sbin/config/lang.l
+++ b/usr.sbin/config/lang.l
@@ -39,6 +39,7 @@
#include "config.h"
#define YY_NO_UNPUT
+#define YY_NO_INPUT
/*
* Data for returning to previous files from include files.
diff --git a/usr.sbin/kbdcontrol/lex.l b/usr.sbin/kbdcontrol/lex.l
index 7d9fd53..e9ca2bc 100644
--- a/usr.sbin/kbdcontrol/lex.l
+++ b/usr.sbin/kbdcontrol/lex.l
@@ -32,6 +32,7 @@
#include "lex.h"
#define YY_NO_UNPUT
+#define YY_NO_INPUT
%}
diff --git a/usr.sbin/mfiutil/mfi_config.c b/usr.sbin/mfiutil/mfi_config.c
index fc03aa7..fdda117 100644
--- a/usr.sbin/mfiutil/mfi_config.c
+++ b/usr.sbin/mfiutil/mfi_config.c
@@ -328,6 +328,10 @@ parse_array(int fd, int raid_type, char *array_str, struct array_info *info)
/* Validate each drive. */
info->drives = calloc(count, sizeof(struct mfi_pd_info));
+ if (info->drives == NULL) {
+ warnx("malloc failed");
+ return (ENOMEM);
+ }
info->drive_count = count;
for (pinfo = info->drives; (cp = strsep(&array_str, ",")) != NULL;
pinfo++) {
@@ -638,6 +642,10 @@ create_volume(int ac, char **av)
break;
}
arrays = calloc(narrays, sizeof(*arrays));
+ if (arrays == NULL) {
+ warnx("malloc failed");
+ return (ENOMEM);
+ }
for (i = 0; i < narrays; i++) {
error = parse_array(fd, raid_type, av[i], &arrays[i]);
if (error)
@@ -673,6 +681,10 @@ create_volume(int ac, char **av)
state.array_count = config->array_count;
if (config->array_count > 0) {
state.arrays = calloc(config->array_count, sizeof(int));
+ if (state.arrays == NULL) {
+ warnx("malloc failed");
+ return (ENOMEM);
+ }
for (i = 0; i < config->array_count; i++) {
ar = (struct mfi_array *)p;
state.arrays[i] = ar->array_ref;
@@ -685,6 +697,10 @@ create_volume(int ac, char **av)
state.log_drv_count = config->log_drv_count;
if (config->log_drv_count) {
state.volumes = calloc(config->log_drv_count, sizeof(int));
+ if (state.volumes == NULL) {
+ warnx("malloc failed");
+ return (ENOMEM);
+ }
for (i = 0; i < config->log_drv_count; i++) {
ld = (struct mfi_ld_config *)p;
state.volumes[i] = ld->properties.ld.v.target_id;
@@ -721,6 +737,10 @@ create_volume(int ac, char **av)
config_size = sizeof(struct mfi_config_data) +
sizeof(struct mfi_ld_config) * nvolumes + MFI_ARRAY_SIZE * narrays;
config = calloc(1, config_size);
+ if (config == NULL) {
+ warnx("malloc failed");
+ return (ENOMEM);
+ }
config->size = config_size;
config->array_count = narrays;
config->array_size = MFI_ARRAY_SIZE; /* XXX: Firmware hardcode */
@@ -902,6 +922,10 @@ add_spare(int ac, char **av)
spare = malloc(sizeof(struct mfi_spare) + sizeof(uint16_t) *
config->array_count);
+ if (spare == NULL) {
+ warnx("malloc failed");
+ return (ENOMEM);
+ }
bzero(spare, sizeof(struct mfi_spare));
spare->ref = info.ref;
@@ -1170,6 +1194,10 @@ dump(int ac, char **av)
}
config = malloc(len);
+ if (config == NULL) {
+ warnx("malloc failed");
+ return (ENOMEM);
+ }
if (sysctlbyname(buf, config, &len, NULL, 0) < 0) {
error = errno;
warn("Failed to read debug command");
diff --git a/usr.sbin/mfiutil/mfi_evt.c b/usr.sbin/mfiutil/mfi_evt.c
index 31c5ec3..b9288d8 100644
--- a/usr.sbin/mfiutil/mfi_evt.c
+++ b/usr.sbin/mfiutil/mfi_evt.c
@@ -624,6 +624,10 @@ show_events(int ac, char **av)
}
list = malloc(size);
+ if (list == NULL) {
+ warnx("malloc failed");
+ return (ENOMEM);
+ }
for (seq = start;;) {
if (mfi_get_events(fd, list, num_events, filter, seq,
&status) < 0) {
diff --git a/usr.sbin/mfiutil/mfi_flash.c b/usr.sbin/mfiutil/mfi_flash.c
index 87bdaca..4039beb 100644
--- a/usr.sbin/mfiutil/mfi_flash.c
+++ b/usr.sbin/mfiutil/mfi_flash.c
@@ -163,6 +163,10 @@ flash_adapter(int ac, char **av)
/* Upload the file 64k at a time. */
buf = malloc(FLASH_BUF_SIZE);
+ if (buf == NULL) {
+ warnx("malloc failed");
+ return (ENOMEM);
+ }
offset = 0;
while (sb.st_size > 0) {
nread = read(flash, buf, FLASH_BUF_SIZE);
diff --git a/usr.sbin/mptutil/mpt_config.c b/usr.sbin/mptutil/mpt_config.c
index 6247bb4..d914d66 100644
--- a/usr.sbin/mptutil/mpt_config.c
+++ b/usr.sbin/mptutil/mpt_config.c
@@ -50,8 +50,6 @@ __RCSID("$FreeBSD$");
static void dump_config(CONFIG_PAGE_RAID_VOL_0 *vol);
#endif
-#define powerof2(x) ((((x)-1)&(x))==0)
-
static long
dehumanize(const char *value)
{
diff --git a/usr.sbin/newsyslog/newsyslog.c b/usr.sbin/newsyslog/newsyslog.c
index 7ba6cb8..46158ef 100644
--- a/usr.sbin/newsyslog/newsyslog.c
+++ b/usr.sbin/newsyslog/newsyslog.c
@@ -163,7 +163,7 @@ struct include_entry {
struct oldlog_entry {
char *fname; /* Filename of the log file */
- time_t t; /* Parses timestamp of the logfile */
+ time_t t; /* Parsed timestamp of the logfile */
};
typedef enum {
diff --git a/usr.sbin/sysinstall/dispatch.c b/usr.sbin/sysinstall/dispatch.c
index 0e4a634..44aa0fa 100644
--- a/usr.sbin/sysinstall/dispatch.c
+++ b/usr.sbin/sysinstall/dispatch.c
@@ -136,8 +136,12 @@ typedef struct command_buffer_ {
static void
dispatch_free_command(command_buffer *item)
{
- REMQUE(item);
- free(item->string);
+ if (item != NULL) {
+ REMQUE(item);
+ free(item->string);
+ item->string = NULL;
+ }
+
free(item);
}
@@ -155,19 +159,29 @@ dispatch_free_all(qelement *head)
static command_buffer *
dispatch_add_command(qelement *head, char *string)
{
- command_buffer *new;
+ command_buffer *new = NULL;
new = malloc(sizeof(command_buffer));
- if (!new)
- return NULL;
+ if (new != NULL) {
- new->string = strdup(string);
- INSQUEUE(new, head->q_back);
+ new->string = strdup(string);
+
+ /*
+ * We failed to copy `string'; clean up the allocated
+ * resources.
+ */
+ if (new->string == NULL) {
+ free(new);
+ new = NULL;
+ } else {
+ INSQUEUE(new, head->q_back);
+ }
+ }
return new;
}
-
+
/*
* Command processing
*/
@@ -280,7 +294,7 @@ dispatchCommand(char *str)
return i;
}
-
+
/*
* File processing
*/
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