Index: usr.sbin/usbdump/usbdump.8 =================================================================== --- usr.sbin/usbdump/usbdump.8 +++ usr.sbin/usbdump/usbdump.8 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd May 14, 2021 +.Dd June 14, 2022 .Dt USBDUMP 8 .Os .Sh NAME @@ -42,6 +42,7 @@ .Op Fl v .Op Fl w Ar file .Op Fl f Ar filter +.Op Fl p .Op Fl b Ar file .Op Fl h .Sh DESCRIPTION @@ -58,16 +59,7 @@ The argument may be prefixed by "ugen". The option may be specified multiple times, but the bus specified must be the same. -.It Fl d Ar [ugen]bus.device -Shortcut for -.Fl i -and -.Fl f -options. -The argument may be prefixed by "ugen". -The option may be specified multiple times, but the bus specified must -be the same. -.It Fl d Ar [ugen]bus.device.endpoint +.It Fl d Ar [ugen]bus.device , Fl d Ar [ugen]bus.device.endpoint Shortcut for .Fl i and @@ -77,16 +69,17 @@ The option may be specified multiple times, but the bus specified must be the same. .It Fl b Ar file -Store data part of the USB trace in binary format to the given +Write the raw packet data without any headers to the given .Ar file . -This option also works with the -r and -f options. +This option does not work with the +.Fl w +option. .It Fl i Ar ifname Listen on USB bus interface .Ar ifname . .It Fl r Ar file Read the raw packets from .Ar file . -This option also works with the -f option. .It Fl s Ar snaplen Snapshot .Ar snaplen @@ -97,7 +90,9 @@ .It Fl w Ar file Write the raw packets to .Ar file . -This option also works with the -s and -v options. +This option does not work with the +.Fl b +option. .It Fl f Ar filter The filter argument consists of either one or two numbers separated by a dot. The first indicates the device unit number which should be traced. @@ -108,6 +103,10 @@ A device unit or endpoint value of -1 means ignore this field. If no filters are specified, all packets are passed through using the default -1,-1 filter. This option can be specified multiple times. +.It Fl p +Do not ignore device unit number filters which overlap device endpoint filters. +Without this option, if a unit filter overlaps any endpoint filters, the unit filter +is ignored and only the endpoint filters are used to limit output. .It Fl h This option displays a summary of the command line options. .El @@ -129,6 +128,23 @@ Read and display the USB raw packets from previous file: .Pp .Dl "usbdump -r /tmp/dump_pkts -v" +.Pp +Display the USB raw packets from usbus2 unit 3, with equivalent combinations of arguments: +.Pp +.Dl "usbdump -i usbus2 -f 3" +.Dl "usbdump -d ugen2 -f 3" +.Dl "usbdump -d ugen2.3" +.Pp +Display the USB raw packets from usbus2 unit 3 endpoint 4, with equivalent combinations of arguments: +.Pp +.Dl "usbdump -i usbus2 -f 3.4" +.Dl "usbdump -d ugen2 -f 3.4" +.Dl "usbdump -d ugen2.3 -f .4" +.Dl "usbdump -d ugen2.3.4" +.Pp +Note: if the +.Fl p +option is specified, the third command will match all packets on endpoint 4. .Sh OUTPUT FORMAT The output format of .Nm @@ -179,6 +195,16 @@ .It <...> Optional field used for printing an error string if the packet is from USB done. .El +.Sh COMPATIBILITY +Originally, unit filters which overlapped endpoint filters would cause the endpoint +filters to have no effect, as the unit filters would accept all packets, including +those which might not match any endpoint filters. +.Pp +This behavior is corrected by automatically removing any unit filters which overlap +any endpoint or unit.endpoint filters. +To disable automatic removal and revert to the old behavior, invoke with the +.Fl p +option. .Sh SEE ALSO .Xr usbconfig 8 .Sh AUTHORS Index: usr.sbin/usbdump/usbdump.c =================================================================== --- usr.sbin/usbdump/usbdump.c +++ usr.sbin/usbdump/usbdump.c @@ -278,6 +278,44 @@ return (0); } +static void +check_filter(int should_remove) +{ + struct usb_filt *puf; + struct usb_filt *puf_temp; + struct usb_filt *puf2; + + STAILQ_FOREACH_SAFE(puf, &usb_filt_head, entry, puf_temp) { + if (puf->unit == -1 || puf->endpoint != -1) + continue; + + int has_more_specific = 0; + + STAILQ_FOREACH(puf2, &usb_filt_head, entry) { + if (puf == puf2) + continue; + + if ((puf2->unit == -1 || puf2->unit == puf->unit) && + (puf2->endpoint != -1)) { + has_more_specific = 1; + + if (!should_remove && verbose >= 1) + printf("Filter %d.%d is overlapped by filter %d.-1, either remove the offending filter or invoke without -p\n", puf2->unit, puf2->endpoint, puf->unit); + + break; + } + } + + if (should_remove && has_more_specific) { + if (verbose >= 1) + printf("Pruned %d.-1 due to at least one or more filters which are more specific than it existing\n", puf->unit); + + STAILQ_REMOVE(&usb_filt_head, puf, usb_filt, entry); + free(puf); + } + } +} + static void free_filter(struct bpf_program *pprog) { @@ -784,6 +822,7 @@ fprintf(stderr, FMT, "-d [ugen]B.D.E", "Listen on bus, B, device, D, and endpoint E"); fprintf(stderr, FMT, "-i ", "Listen on this bus interface"); fprintf(stderr, FMT, "-f ", "Specify a device and endpoint filter"); + fprintf(stderr, FMT, "-p", "Disable ignoring unit filters which overlap endpoint filters"); fprintf(stderr, FMT, "-r ", "Read the raw packets from file"); fprintf(stderr, FMT, "-s ", "Snapshot bytes from each packet"); fprintf(stderr, FMT, "-v", "Increase the verbose level"); @@ -824,6 +863,7 @@ uint32_t v; int fd; int o; + int prune = 1; int filt_unit; int filt_ep; int s; @@ -831,7 +871,7 @@ const char *optstring; char *pp; - optstring = "b:d:hi:r:s:vw:f:"; + optstring = "b:d:hi:r:s:vw:f:p"; while ((o = getopt(argc, argv, optstring)) != -1) { switch (o) { case 'b': @@ -870,12 +910,16 @@ } break; case 'f': - filt_unit = strtol(optarg, &pp, 10); + filt_unit = strtol(optarg, &pp, 0); + if (optarg == pp) + filt_unit = -1; + else if (filt_unit < 0 && filt_unit != -1) + usage(); filt_ep = -1; if (pp != NULL) { if (*pp == '.') { - filt_ep = strtol(pp + 1, &pp, 10); - if (pp != NULL && *pp != 0) + filt_ep = strtol(pp + 1, &pp, 0); + if ((pp != NULL && *pp != 0) || (filt_ep < 0 && filt_unit != -1)) usage(); } else if (*pp != 0) { usage(); @@ -886,6 +930,9 @@ case 'i': i_arg = optarg; break; + case 'p': + prune = 0; + break; case 'r': r_arg = optarg; init_rfile(p); @@ -985,6 +1032,9 @@ if (p->buffer == NULL) errx(EX_SOFTWARE, "Out of memory."); + /* delayed until after all filters are added */ + check_filter(prune); + make_filter(&total_prog, snapshot); if (ioctl(p->fd, BIOCSETF, (caddr_t)&total_prog) < 0)