Make usbusN logging pseudo-interface used by usbdump(8) clonable. One is
now created/destroyed automatically by usbdump(8). Note that "hw.usb.no_pf" loader tunable is now obsolete. Reviewed by: hselasky
This commit is contained in:
parent
d60a0680ba
commit
739047446d
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=238279
@ -44,8 +44,10 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <sys/sockio.h>
|
#include <sys/sockio.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <net/if_types.h>
|
#include <net/if_types.h>
|
||||||
|
#include <net/if_clone.h>
|
||||||
#include <net/bpf.h>
|
#include <net/bpf.h>
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
|
#include <net/route.h>
|
||||||
|
|
||||||
#include <dev/usb/usb.h>
|
#include <dev/usb/usb.h>
|
||||||
#include <dev/usb/usbdi.h>
|
#include <dev/usb/usbdi.h>
|
||||||
@ -58,35 +60,144 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <dev/usb/usb_pf.h>
|
#include <dev/usb/usb_pf.h>
|
||||||
#include <dev/usb/usb_transfer.h>
|
#include <dev/usb/usb_transfer.h>
|
||||||
|
|
||||||
static int usb_no_pf;
|
#define USBUSNAME "usbus"
|
||||||
|
|
||||||
SYSCTL_INT(_hw_usb, OID_AUTO, no_pf, CTLFLAG_RW,
|
static void usbpf_init(void);
|
||||||
&usb_no_pf, 0, "Set to disable USB packet filtering");
|
static void usbpf_uninit(void);
|
||||||
|
static int usbpf_ioctl(struct ifnet *, u_long, caddr_t);
|
||||||
|
static int usbpf_clone_match(struct if_clone *, const char *);
|
||||||
|
static int usbpf_clone_create(struct if_clone *, char *, size_t, caddr_t);
|
||||||
|
static int usbpf_clone_destroy(struct if_clone *, struct ifnet *);
|
||||||
|
static struct usb_bus *usbpf_ifname2ubus(const char *);
|
||||||
|
static uint32_t usbpf_aggregate_xferflags(struct usb_xfer_flags *);
|
||||||
|
static uint32_t usbpf_aggregate_status(struct usb_xfer_flags_int *);
|
||||||
|
static int usbpf_xfer_frame_is_read(struct usb_xfer *, uint32_t);
|
||||||
|
static uint32_t usbpf_xfer_precompute_size(struct usb_xfer *, int);
|
||||||
|
|
||||||
TUNABLE_INT("hw.usb.no_pf", &usb_no_pf);
|
static struct if_clone usbpf_cloner = IFC_CLONE_INITIALIZER(
|
||||||
|
USBUSNAME, NULL, IF_MAXUNIT,
|
||||||
|
NULL, usbpf_clone_match, usbpf_clone_create, usbpf_clone_destroy);
|
||||||
|
|
||||||
void
|
SYSINIT(usbpf_init, SI_SUB_PSEUDO, SI_ORDER_MIDDLE, usbpf_init, NULL);
|
||||||
usbpf_attach(struct usb_bus *ubus)
|
SYSUNINIT(usbpf_uninit, SI_SUB_PSEUDO, SI_ORDER_MIDDLE, usbpf_uninit, NULL);
|
||||||
|
|
||||||
|
static void
|
||||||
|
usbpf_init(void)
|
||||||
{
|
{
|
||||||
struct ifnet *ifp;
|
|
||||||
|
|
||||||
if (usb_no_pf != 0) {
|
if_clone_attach(&usbpf_cloner);
|
||||||
ubus->ifp = NULL;
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
usbpf_uninit(void)
|
||||||
|
{
|
||||||
|
int devlcnt;
|
||||||
|
device_t *devlp;
|
||||||
|
devclass_t dc;
|
||||||
|
struct usb_bus *ubus;
|
||||||
|
int error;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if_clone_detach(&usbpf_cloner);
|
||||||
|
|
||||||
|
dc = devclass_find(USBUSNAME);
|
||||||
|
if (dc == NULL)
|
||||||
return;
|
return;
|
||||||
|
error = devclass_get_devices(dc, &devlp, &devlcnt);
|
||||||
|
if (error)
|
||||||
|
return;
|
||||||
|
for (i = 0; i < devlcnt; i++) {
|
||||||
|
ubus = device_get_softc(devlp[i]);
|
||||||
|
if (ubus != NULL && ubus->ifp != NULL)
|
||||||
|
usbpf_clone_destroy(&usbpf_cloner, ubus->ifp);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ifp = ubus->ifp = if_alloc(IFT_USB);
|
static int
|
||||||
if (ifp == NULL) {
|
usbpf_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* No configuration allowed. */
|
||||||
|
return (EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct usb_bus *
|
||||||
|
usbpf_ifname2ubus(const char *ifname)
|
||||||
|
{
|
||||||
|
device_t dev;
|
||||||
|
devclass_t dc;
|
||||||
|
int unit;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
if (strncmp(ifname, USBUSNAME, sizeof(USBUSNAME)) <= 0)
|
||||||
|
return (NULL);
|
||||||
|
error = ifc_name2unit(ifname, &unit);
|
||||||
|
if (error || unit < 0)
|
||||||
|
return (NULL);
|
||||||
|
dc = devclass_find(USBUSNAME);
|
||||||
|
if (dc == NULL)
|
||||||
|
return (NULL);
|
||||||
|
dev = devclass_get_device(dc, unit);
|
||||||
|
if (dev == NULL)
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
|
return (device_get_softc(dev));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
usbpf_clone_match(struct if_clone *ifc, const char *name)
|
||||||
|
{
|
||||||
|
struct usb_bus *ubus;
|
||||||
|
|
||||||
|
ubus = usbpf_ifname2ubus(name);
|
||||||
|
if (ubus == NULL)
|
||||||
|
return (0);
|
||||||
|
if (ubus->ifp != NULL)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
usbpf_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
int unit;
|
||||||
|
struct ifnet *ifp;
|
||||||
|
struct usb_bus *ubus;
|
||||||
|
|
||||||
|
error = ifc_name2unit(name, &unit);
|
||||||
|
if (error || unit < 0)
|
||||||
|
return (error);
|
||||||
|
|
||||||
|
ubus = usbpf_ifname2ubus(name);
|
||||||
|
if (ubus == NULL)
|
||||||
|
return (1);
|
||||||
|
if (ubus->ifp != NULL)
|
||||||
|
return (1);
|
||||||
|
|
||||||
|
error = ifc_alloc_unit(ifc, &unit);
|
||||||
|
if (error) {
|
||||||
|
ifc_free_unit(ifc, unit);
|
||||||
device_printf(ubus->parent, "usbpf: Could not allocate "
|
device_printf(ubus->parent, "usbpf: Could not allocate "
|
||||||
"instance\n");
|
"instance\n");
|
||||||
return;
|
return (error);
|
||||||
}
|
}
|
||||||
|
ifp = ubus->ifp = if_alloc(IFT_USB);
|
||||||
if_initname(ifp, "usbus", device_get_unit(ubus->bdev));
|
if (ifp == NULL) {
|
||||||
ifp->if_flags = IFF_CANTCONFIG;
|
ifc_free_unit(ifc, unit);
|
||||||
|
device_printf(ubus->parent, "usbpf: Could not allocate "
|
||||||
|
"instance\n");
|
||||||
|
return (ENOSPC);
|
||||||
|
}
|
||||||
|
strlcpy(ifp->if_xname, name, sizeof(ifp->if_xname));
|
||||||
|
ifp->if_softc = ubus;
|
||||||
|
ifp->if_dname = ifc->ifc_name;
|
||||||
|
ifp->if_dunit = unit;
|
||||||
|
ifp->if_ioctl = usbpf_ioctl;
|
||||||
if_attach(ifp);
|
if_attach(ifp);
|
||||||
if_up(ifp);
|
ifp->if_flags |= IFF_UP;
|
||||||
|
rt_ifmsg(ifp);
|
||||||
/*
|
/*
|
||||||
* XXX According to the specification of DLT_USB, it indicates
|
* XXX According to the specification of DLT_USB, it indicates
|
||||||
* packets beginning with USB setup header. But not sure all
|
* packets beginning with USB setup header. But not sure all
|
||||||
@ -94,6 +205,31 @@ usbpf_attach(struct usb_bus *ubus)
|
|||||||
*/
|
*/
|
||||||
bpfattach(ifp, DLT_USB, USBPF_HDR_LEN);
|
bpfattach(ifp, DLT_USB, USBPF_HDR_LEN);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
usbpf_clone_destroy(struct if_clone *ifc, struct ifnet *ifp)
|
||||||
|
{
|
||||||
|
struct usb_bus *ubus;
|
||||||
|
int unit;
|
||||||
|
|
||||||
|
ubus = ifp->if_softc;
|
||||||
|
unit = ifp->if_dunit;
|
||||||
|
|
||||||
|
ubus->ifp = NULL;
|
||||||
|
bpfdetach(ifp);
|
||||||
|
if_detach(ifp);
|
||||||
|
if_free(ifp);
|
||||||
|
ifc_free_unit(ifc, unit);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
usbpf_attach(struct usb_bus *ubus)
|
||||||
|
{
|
||||||
|
|
||||||
if (bootverbose)
|
if (bootverbose)
|
||||||
device_printf(ubus->parent, "usbpf: Attached\n");
|
device_printf(ubus->parent, "usbpf: Attached\n");
|
||||||
}
|
}
|
||||||
@ -101,15 +237,11 @@ usbpf_attach(struct usb_bus *ubus)
|
|||||||
void
|
void
|
||||||
usbpf_detach(struct usb_bus *ubus)
|
usbpf_detach(struct usb_bus *ubus)
|
||||||
{
|
{
|
||||||
struct ifnet *ifp = ubus->ifp;
|
|
||||||
|
|
||||||
if (ifp != NULL) {
|
if (ubus->ifp != NULL)
|
||||||
bpfdetach(ifp);
|
usbpf_clone_destroy(&usbpf_cloner, ubus->ifp);
|
||||||
if_down(ifp);
|
if (bootverbose)
|
||||||
if_detach(ifp);
|
device_printf(ubus->parent, "usbpf: Detached\n");
|
||||||
if_free(ifp);
|
|
||||||
}
|
|
||||||
ubus->ifp = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t
|
static uint32_t
|
||||||
@ -259,8 +391,6 @@ usbpf_xfertap(struct usb_xfer *xfer, int type)
|
|||||||
bus = xfer->xroot->bus;
|
bus = xfer->xroot->bus;
|
||||||
|
|
||||||
/* sanity checks */
|
/* sanity checks */
|
||||||
if (usb_no_pf != 0)
|
|
||||||
return;
|
|
||||||
if (bus->ifp == NULL)
|
if (bus->ifp == NULL)
|
||||||
return;
|
return;
|
||||||
if (!bpf_peers_present(bus->ifp->if_bpf))
|
if (!bpf_peers_present(bus->ifp->if_bpf))
|
||||||
|
@ -795,6 +795,8 @@ main(int argc, char *argv[])
|
|||||||
int o;
|
int o;
|
||||||
int filt_unit;
|
int filt_unit;
|
||||||
int filt_ep;
|
int filt_ep;
|
||||||
|
int s;
|
||||||
|
int ifindex;
|
||||||
const char *optstring;
|
const char *optstring;
|
||||||
char *pp;
|
char *pp;
|
||||||
|
|
||||||
@ -887,9 +889,20 @@ main(int argc, char *argv[])
|
|||||||
/* clear ifr structure */
|
/* clear ifr structure */
|
||||||
memset(&ifr, 0, sizeof(ifr));
|
memset(&ifr, 0, sizeof(ifr));
|
||||||
|
|
||||||
|
/* Try to create usbusN interface if it is not available. */
|
||||||
|
s = socket(AF_LOCAL, SOCK_DGRAM, 0);
|
||||||
|
if (s < 0)
|
||||||
|
errx(EXIT_FAILURE, "Could not open a socket");
|
||||||
|
ifindex = if_nametoindex(i_arg);
|
||||||
|
if (ifindex == 0) {
|
||||||
|
(void)strlcpy(ifr.ifr_name, i_arg, sizeof(ifr.ifr_name));
|
||||||
|
if (ioctl(s, SIOCIFCREATE2, &ifr) < 0)
|
||||||
|
errx(EXIT_FAILURE, "Invalid bus interface: %s", i_arg);
|
||||||
|
}
|
||||||
|
|
||||||
for ( ; v >= USBPF_HDR_LEN; v >>= 1) {
|
for ( ; v >= USBPF_HDR_LEN; v >>= 1) {
|
||||||
(void)ioctl(fd, BIOCSBLEN, (caddr_t)&v);
|
(void)ioctl(fd, BIOCSBLEN, (caddr_t)&v);
|
||||||
(void)strncpy(ifr.ifr_name, i_arg, sizeof(ifr.ifr_name));
|
(void)strlcpy(ifr.ifr_name, i_arg, sizeof(ifr.ifr_name));
|
||||||
if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) >= 0)
|
if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) >= 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -930,6 +943,17 @@ main(int argc, char *argv[])
|
|||||||
printf("%d packets received by filter\n", us.bs_recv);
|
printf("%d packets received by filter\n", us.bs_recv);
|
||||||
printf("%d packets dropped by kernel\n", us.bs_drop);
|
printf("%d packets dropped by kernel\n", us.bs_drop);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Destroy the usbusN interface only if it was created by
|
||||||
|
* usbdump(8). Ignore when it was already destroyed.
|
||||||
|
*/
|
||||||
|
if (ifindex == 0 && if_nametoindex(i_arg) > 0) {
|
||||||
|
(void)strlcpy(ifr.ifr_name, i_arg, sizeof(ifr.ifr_name));
|
||||||
|
if (ioctl(s, SIOCIFDESTROY, &ifr) < 0)
|
||||||
|
warn("SIOCIFDESTROY ioctl failed");
|
||||||
|
}
|
||||||
|
close(s);
|
||||||
|
|
||||||
if (p->fd > 0)
|
if (p->fd > 0)
|
||||||
close(p->fd);
|
close(p->fd);
|
||||||
if (p->rfd > 0)
|
if (p->rfd > 0)
|
||||||
|
Loading…
Reference in New Issue
Block a user