Index: sys/net/bpf.c =================================================================== RCS file: /cvs/src/sys/net/bpf.c,v retrieving revision 1.166 diff -u -p -r1.166 bpf.c --- sys/net/bpf.c 24 Jan 2018 00:25:17 -0000 1.166 +++ sys/net/bpf.c 30 Jan 2018 06:36:50 -0000 @@ -1291,6 +1291,45 @@ _bpf_mtap(caddr_t arg, const struct mbuf } /* + * Incoming linkage from device drivers, where a data buffer should be + * prepended by an arbitrary header. In this situation we already have a + * way of representing a chain of memory buffers, ie, mbufs, so reuse + * the existing functionality by attaching the buffers to mbufs. + * + * Con up a minimal mbuf chain to pacify bpf by allocating (only) a + * struct m_hdr each for the header and data on the stack. + */ +int +bpf_tap_hdr(caddr_t arg, const void *hdr, unsigned int hdrlen, + const void *buf, unsigned int buflen, u_int direction) +{ + struct m_hdr mh, md; + struct mbuf *m0 = NULL; + struct mbuf **mp = &m0; + + if (hdr != NULL) { + mh.mh_flags = 0; + mh.mh_next = NULL; + mh.mh_len = hdrlen; + mh.mh_data = (void *)hdr; + + *mp = (struct mbuf *)&mh; + mp = &mh.mh_next; + } + + if (buf != NULL) { + md.mh_flags = 0; + md.mh_next = NULL; + md.mh_len = buflen; + md.mh_data = (void *)buf; + + *mp = (struct mbuf *)&md; + } + + return _bpf_mtap(arg, m0, direction, bpf_mcopy); +} + +/* * Incoming linkage from device drivers, when packet is in an mbuf chain. */ int Index: sys/net/bpf.h =================================================================== RCS file: /cvs/src/sys/net/bpf.h,v retrieving revision 1.63 diff -u -p -r1.63 bpf.h --- sys/net/bpf.h 24 Jan 2018 00:25:17 -0000 1.63 +++ sys/net/bpf.h 30 Jan 2018 06:36:50 -0000 @@ -201,6 +201,7 @@ struct bpf_hdr { #define DLT_USER13 160 /* Reserved for private use */ #define DLT_USER14 161 /* Reserved for private use */ #define DLT_USER15 162 /* Reserved for private use */ +#define DLT_USBPCAP 249 /* USBPcap */ #define DLT_MPLS 219 /* MPLS Provider Edge header */ #define DLT_OPENFLOW 267 /* in-kernel OpenFlow, by pcap */ @@ -311,6 +312,7 @@ int bpf_mtap_hdr(caddr_t, caddr_t, u_in void (*)(const void *, void *, size_t)); int bpf_mtap_af(caddr_t, u_int32_t, const struct mbuf *, u_int); int bpf_mtap_ether(caddr_t, const struct mbuf *, u_int); +int bpf_tap_hdr(caddr_t, const void *, u_int, const void *, u_int, u_int); void bpfattach(caddr_t *, struct ifnet *, u_int, u_int); void bpfdetach(struct ifnet *); void *bpfsattach(caddr_t *, const char *, u_int, u_int); Index: usr.sbin/tcpdump/Makefile =================================================================== RCS file: /cvs/src/usr.sbin/tcpdump/Makefile,v retrieving revision 1.62 diff -u -p -r1.62 Makefile --- usr.sbin/tcpdump/Makefile 30 Oct 2017 10:07:44 -0000 1.62 +++ usr.sbin/tcpdump/Makefile 30 Jan 2018 06:36:50 -0000 @@ -49,7 +49,7 @@ SRCS= tcpdump.c addrtoname.c privsep.c p print-etherip.c print-lwres.c print-lldp.c print-cdp.c print-pflog.c \ print-pfsync.c pf_print_state.c print-ofp.c ofp_map.c \ print-udpencap.c print-carp.c \ - print-802_11.c print-iapp.c print-mpls.c print-slow.c \ + print-802_11.c print-iapp.c print-mpls.c print-slow.c print-usbpcap.c \ gmt2local.c savestr.c setsignal.c in_cksum.c # TCP OS Fingerprinting Index: usr.sbin/tcpdump/interface.h =================================================================== RCS file: /cvs/src/usr.sbin/tcpdump/interface.h,v retrieving revision 1.69 diff -u -p -r1.69 interface.h --- usr.sbin/tcpdump/interface.h 16 Nov 2016 13:47:27 -0000 1.69 +++ usr.sbin/tcpdump/interface.h 30 Jan 2018 06:36:50 -0000 @@ -276,6 +276,8 @@ extern void slow_print(const u_char *, u extern void gtp_print(const u_char *, u_int, u_short, u_short); extern void ofp_print(const u_char *, u_int); extern void ofp_if_print(u_char *, const struct pcap_pkthdr *, const u_char *); +extern void usbpcap_if_print(u_char *, const struct pcap_pkthdr *, + const u_char *); #ifdef INET6 extern void ip6_print(const u_char *, u_int); Index: usr.sbin/tcpdump/print-usbpcap.c =================================================================== RCS file: usr.sbin/tcpdump/print-usbpcap.c diff -N usr.sbin/tcpdump/print-usbpcap.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ usr.sbin/tcpdump/print-usbpcap.c 30 Jan 2018 06:36:50 -0000 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018 Martin Pieuchot + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include + +#include "interface.h" + +#ifndef nitems +#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) +#endif + +const char *usbpcap_xfer_type[] = {"isoc", "intr", "ctrl", "bulk"}; + +void +usbpcap_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p) +{ + u_int length = h->len; + u_int caplen = h->caplen; + const struct usbpcap_hdr *uph; + + ts_print(&h->ts); + + /* check length */ + if (caplen < sizeof(uint16_t)) { + printf("[|usb]"); + goto out; + } + uph = (struct usbpcap_hdr *)p; + if (uph->hlen < sizeof(*uph)) { + printf("[usb: invalid header length %u!]", uph->hlen); + goto out; + } + + if (caplen < uph->hlen) { + printf("[|usb]"); + goto out; + } + + printf("bus %u %c addr %u: ep%u", + uph->bus, ((uph->info & USBPCAP_INFO_PDO_TO_FDO) ? '<' : '>'), + uph->devaddr, UE_GET_ADDR(uph->epaddr)); + + if (uph->xfertype < nitems(usbpcap_xfer_type)) + printf(" %s", usbpcap_xfer_type[uph->xfertype]); + else + printf(" ??"); + + printf(" %u", uph->dlen); + + if (xflag) + default_print(p + sizeof(*uph), length - sizeof(*uph)); +out: + putchar('\n'); +} Index: usr.sbin/tcpdump/tcpdump.c =================================================================== RCS file: /cvs/src/usr.sbin/tcpdump/tcpdump.c,v retrieving revision 1.81 diff -u -p -r1.81 tcpdump.c --- usr.sbin/tcpdump/tcpdump.c 8 Dec 2017 17:04:15 -0000 1.81 +++ usr.sbin/tcpdump/tcpdump.c 30 Jan 2018 06:36:50 -0000 @@ -127,6 +127,7 @@ static struct printer printers[] = { { ieee802_11_if_print, DLT_IEEE802_11 }, { ieee802_11_radio_if_print, DLT_IEEE802_11_RADIO }, { ofp_if_print, DLT_OPENFLOW }, + { usbpcap_if_print, DLT_USBPCAP }, { NULL, 0 }, }; Index: lib/libpcap/gencode.c =================================================================== RCS file: /cvs/src/lib/libpcap/gencode.c,v retrieving revision 1.46 diff -u -p -r1.46 gencode.c --- lib/libpcap/gencode.c 20 Nov 2016 12:45:26 -0000 1.46 +++ lib/libpcap/gencode.c 30 Jan 2018 06:36:50 -0000 @@ -787,6 +787,8 @@ init_linktype(type) off_nl = 12; return; + case DLT_USBPCAP: + /* FALLTHROUGH */ case DLT_RAW: off_linktype = -1; off_nl = 0; Index: lib/libpcap/pcap.c =================================================================== RCS file: /cvs/src/lib/libpcap/pcap.c,v retrieving revision 1.20 diff -u -p -r1.20 pcap.c --- lib/libpcap/pcap.c 16 Nov 2016 13:47:27 -0000 1.20 +++ lib/libpcap/pcap.c 30 Jan 2018 06:36:50 -0000 @@ -326,6 +326,7 @@ DLT_CHOICE(DLT_IEEE802_11, "IEEE 802.11 DLT_CHOICE(DLT_PFLOG, "Packet filter logging, by pcap people"), DLT_CHOICE(DLT_IEEE802_11_RADIO, "IEEE 802.11 plus WLAN header"), DLT_CHOICE(DLT_OPENFLOW, "OpenFlow"), +DLT_CHOICE(DLT_USBPCAP, "USB"), #undef DLT_CHOICE { NULL, NULL, -1} }; Index: sys/dev/usb/usb.c =================================================================== RCS file: /cvs/src/sys/dev/usb/usb.c,v retrieving revision 1.114 diff -u -p -r1.114 usb.c --- sys/dev/usb/usb.c 29 Jul 2017 18:26:14 -0000 1.114 +++ sys/dev/usb/usb.c 30 Jan 2018 06:36:50 -0000 @@ -63,6 +63,8 @@ #include #include +#include +#include #ifdef USB_DEBUG #define DPRINTF(x) do { if (usbdebug) printf x; } while (0) @@ -183,6 +185,11 @@ usb_attach(struct device *parent, struct } printf("\n"); +#if NBPFILTER > 0 + sc->sc_bus->bpfif = bpfsattach(&sc->sc_bus->bpf, sc->sc_dev.dv_xname, + DLT_USBPCAP, sizeof(struct usbpcap_hdr)); +#endif + /* Make sure not to use tsleep() if we are cold booting. */ if (cold) sc->sc_bus->use_polling++; @@ -973,5 +980,72 @@ usb_detach(struct device *self, int flag sc->sc_bus->soft = NULL; } +#if NBPFILTER > 0 + bpfsdetach(sc->sc_bus->bpfif); +#endif return (0); +} + +void +usb_tap(struct usbd_bus *bus, struct usbd_xfer *xfer, uint8_t dir) +{ +#if NBPFILTER > 0 + struct usb_softc *sc = (struct usb_softc *)bus->usbctl; + usb_endpoint_descriptor_t *ed = xfer->pipe->endpoint->edesc; + struct usbpcap_hdr uph; + unsigned int bpfdir; + void *buf; + unsigned int buflen; + caddr_t bpf; + uint8_t info = 0; + + bpf = bus->bpf; + if (bpf == NULL) + return; + + buf = KERNADDR(&xfer->dmabuf, 0); + buflen = xfer->length; + + if (dir == USBTAP_DIR_OUT) { + bpfdir = BPF_DIRECTION_OUT; + if (usbd_xfer_isread(xfer)) { + buf = NULL; + buflen = 0; + } + } else { /* USBTAP_DIR_IN */ + info = USBPCAP_INFO_PDO_TO_FDO; + bpfdir = BPF_DIRECTION_IN; + if (!usbd_xfer_isread(xfer)) { + buf = NULL; + buflen = 0; + } + } + + uph.hlen = htole16(sizeof(uph)); + uph.id = 0; /* not yet used */ + uph.status = htole32(xfer->status); + uph.function = 0; /* not yet used */ + uph.info = info; + uph.bus = htole32(sc->sc_dev.dv_unit); + uph.devaddr = htole16(xfer->device->address); + uph.epaddr = ed->bEndpointAddress; + uph.dlen = buflen; + + switch (UE_GET_XFERTYPE(ed->bmAttributes)) { + case UE_CONTROL: + uph.xfertype = USBPCAP_TRANSFER_CONTROL; + break; + case UE_ISOCHRONOUS: + uph.xfertype = USBPCAP_TRANSFER_ISOCHRONOUS; + break; + case UE_BULK: + uph.xfertype = USBPCAP_TRANSFER_BULK; + break; + case UE_INTERRUPT: + uph.xfertype = USBPCAP_TRANSFER_INTERRUPT; + break; + } + + bpf_tap_hdr(bpf, &uph, sizeof(uph), buf, buflen, bpfdir); +#endif } Index: sys/dev/usb/usbdi.c =================================================================== RCS file: /cvs/src/sys/dev/usb/usbdi.c,v retrieving revision 1.96 diff -u -p -r1.96 usbdi.c --- sys/dev/usb/usbdi.c 21 Sep 2017 07:44:06 -0000 1.96 +++ sys/dev/usb/usbdi.c 30 Jan 2018 06:36:50 -0000 @@ -320,6 +320,8 @@ usbd_transfer(struct usbd_xfer *xfer) usb_syncmem(&xfer->dmabuf, 0, xfer->length, BUS_DMASYNC_PREREAD); + usb_tap(bus, xfer, USBTAP_DIR_OUT); + err = pipe->methods->transfer(xfer); if (err != USBD_IN_PROGRESS && err != USBD_NORMAL_COMPLETION) { @@ -715,7 +717,8 @@ void usb_transfer_complete(struct usbd_xfer *xfer) { struct usbd_pipe *pipe = xfer->pipe; - int polling = pipe->device->bus->use_polling; + struct usbd_bus *bus = pipe->device->bus; + int polling = bus->use_polling; int status, flags; #if 0 @@ -759,7 +762,7 @@ usb_transfer_complete(struct usbd_xfer * /* if we allocated the buffer in usbd_transfer() we free it here. */ if (xfer->rqflags & URQ_AUTO_DMABUF) { if (!pipe->repeat) { - usb_freemem(pipe->device->bus, &xfer->dmabuf); + usb_freemem(bus, &xfer->dmabuf); xfer->rqflags &= ~URQ_AUTO_DMABUF; } } @@ -778,7 +781,7 @@ usb_transfer_complete(struct usbd_xfer * pipe->repeat, SIMPLEQ_FIRST(&pipe->queue))); /* Count completed transfers. */ - ++pipe->device->bus->stats.uds_requests + ++bus->stats.uds_requests [pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE]; xfer->done = 1; @@ -788,6 +791,8 @@ usb_transfer_complete(struct usbd_xfer * xfer->actlen, xfer->length)); xfer->status = USBD_SHORT_XFER; } + + usb_tap(bus, xfer, USBTAP_DIR_IN); /* * We cannot dereference ``xfer'' after calling the callback as Index: sys/dev/usb/usbdivar.h =================================================================== RCS file: /cvs/src/sys/dev/usb/usbdivar.h,v retrieving revision 1.72 diff -u -p -r1.72 usbdivar.h --- sys/dev/usb/usbdivar.h 8 Apr 2017 02:57:25 -0000 1.72 +++ sys/dev/usb/usbdivar.h 30 Jan 2018 06:36:50 -0000 @@ -35,6 +35,11 @@ #ifndef _USBDIVAR_H_ #define _USBDIVAR_H_ +#include "bpfilter.h" +#if NBPFILTER > 0 +#include +#endif + #include /* From usb_mem.h */ @@ -100,6 +105,10 @@ struct usbd_bus { /* Filled by HC driver */ struct device bdev; /* base device, host adapter */ struct usbd_bus_methods *methods; +#if NBPFILTER > 0 + void *bpfif; + caddr_t bpf; +#endif u_int32_t pipe_size; /* size of a pipe struct */ /* Filled by usb driver */ struct usbd_device *root_hub; @@ -253,6 +262,10 @@ int usbd_detach(struct usbd_device *, s void usb_needs_explore(struct usbd_device *, int); void usb_needs_reattach(struct usbd_device *); void usb_schedsoftintr(struct usbd_bus *); +void usb_tap(struct usbd_bus *, struct usbd_xfer *, uint8_t); + +#define USBTAP_DIR_OUT 0 +#define USBTAP_DIR_IN 1 #define UHUB_UNK_CONFIGURATION -1 #define UHUB_UNK_INTERFACE -1 Index: sys/dev/usb/usbpcap.h =================================================================== RCS file: sys/dev/usb/usbpcap.h diff -N sys/dev/usb/usbpcap.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/dev/usb/usbpcap.h 30 Jan 2018 06:36:50 -0000 @@ -0,0 +1,45 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2018 Martin Pieuchot + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _USBCAP_H_ +#define _USBCAP_H_ + +/* + * DLT_USBPCAP header. + */ +struct usbpcap_hdr { + uint16_t hlen; /* header length */ + uint64_t id; /* request ID */ + uint32_t status; /* USB status code */ + uint16_t function; /* stack function ID */ + uint8_t info; /* info flags */ +#define USBPCAP_INFO_PDO_TO_FDO (1 << 0) + + uint16_t bus; /* bus number */ + uint16_t devaddr; /* device address */ + uint8_t epaddr; /* endpoint's `bEndpointAddress' */ + uint8_t xfertype; /* transfer type */ +#define USBPCAP_TRANSFER_ISOCHRONOUS 0 +#define USBPCAP_TRANSFER_INTERRUPT 1 +#define USBPCAP_TRANSFER_CONTROL 2 +#define USBPCAP_TRANSFER_BULK 3 + + uint32_t dlen; /* data length */ +} __attribute__((packed)); + +#endif /* _USBCAP_H_ */