Date: Wed, 18 Apr 2012 18:59:47 +0000 (UTC) From: Hiroki Sato <hrs@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r234435 - in user/hrs/ipv6: sbin/ifconfig sys/dev/usb sys/netinet6 usr.sbin/usbdump Message-ID: <201204181859.q3IIxlu8046266@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: hrs Date: Wed Apr 18 18:59:47 2012 New Revision: 234435 URL: http://svn.freebsd.org/changeset/base/234435 Log: Make usbusN interface clonable and usbdump(8) create the interface dynamically when necessary. This mitigates the problem that the extra pseudo-interfaces enlarge the interface list and confuse the user. The hw.usb.no_pf knob has been removed. Instead of using IFF_CANTCONFIG, the usbusN interfaces reject any ioctls for interface configuration intentionally. Also, set ifp->if_afdata[AF_INET6] to NULL to eliminate INET6-specific handling such as ND6 options. Reviewed by: hselasky Modified: user/hrs/ipv6/sbin/ifconfig/af_nd6.c user/hrs/ipv6/sys/dev/usb/usb_pf.c user/hrs/ipv6/sys/netinet6/in6.c user/hrs/ipv6/sys/netinet6/in6_ifattach.c user/hrs/ipv6/usr.sbin/usbdump/usbdump.c Modified: user/hrs/ipv6/sbin/ifconfig/af_nd6.c ============================================================================== --- user/hrs/ipv6/sbin/ifconfig/af_nd6.c Wed Apr 18 18:59:27 2012 (r234434) +++ user/hrs/ipv6/sbin/ifconfig/af_nd6.c Wed Apr 18 18:59:47 2012 (r234435) @@ -153,7 +153,8 @@ nd6_status(int s) } error = ioctl(s6, SIOCGIFINFO_IN6, &nd); if (error) { - warn("ioctl(SIOCGIFINFO_IN6)"); + if (errno != EPFNOSUPPORT) + warn("ioctl(SIOCGIFINFO_IN6)"); close(s6); return; } Modified: user/hrs/ipv6/sys/dev/usb/usb_pf.c ============================================================================== --- user/hrs/ipv6/sys/dev/usb/usb_pf.c Wed Apr 18 18:59:27 2012 (r234434) +++ user/hrs/ipv6/sys/dev/usb/usb_pf.c Wed Apr 18 18:59:47 2012 (r234435) @@ -44,8 +44,10 @@ __FBSDID("$FreeBSD$"); #include <sys/sockio.h> #include <net/if.h> #include <net/if_types.h> +#include <net/if_clone.h> #include <net/bpf.h> #include <sys/sysctl.h> +#include <net/route.h> #include <dev/usb/usb.h> #include <dev/usb/usbdi.h> @@ -58,35 +60,144 @@ __FBSDID("$FreeBSD$"); #include <dev/usb/usb_pf.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, - &usb_no_pf, 0, "Set to disable USB packet filtering"); +static void usbpf_init(void); +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); + +static struct if_clone usbpf_cloner = IFC_CLONE_INITIALIZER( + USBUSNAME, NULL, IF_MAXUNIT, + NULL, usbpf_clone_match, usbpf_clone_create, usbpf_clone_destroy); -TUNABLE_INT("hw.usb.no_pf", &usb_no_pf); +SYSINIT(usbpf_init, SI_SUB_PSEUDO, SI_ORDER_MIDDLE, usbpf_init, NULL); +SYSUNINIT(usbpf_uninit, SI_SUB_PSEUDO, SI_ORDER_MIDDLE, usbpf_uninit, NULL); -void -usbpf_attach(struct usb_bus *ubus) +static void +usbpf_init(void) { - struct ifnet *ifp; - if (usb_no_pf != 0) { - ubus->ifp = NULL; + if_clone_attach(&usbpf_cloner); +} + +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; + 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); } +} + +static int +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 " + "instance\n"); + return (error); + } ifp = ubus->ifp = if_alloc(IFT_USB); if (ifp == NULL) { + ifc_free_unit(ifc, unit); device_printf(ubus->parent, "usbpf: Could not allocate " "instance\n"); - return; + return (ENOSPC); } - - if_initname(ifp, "usbus", device_get_unit(ubus->bdev)); - ifp->if_flags = IFF_CANTCONFIG; + 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_up(ifp); - + ifp->if_flags |= IFF_UP; + rt_ifmsg(ifp); /* * XXX According to the specification of DLT_USB, it indicates * 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); + 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) device_printf(ubus->parent, "usbpf: Attached\n"); } @@ -101,15 +237,11 @@ usbpf_attach(struct usb_bus *ubus) void usbpf_detach(struct usb_bus *ubus) { - struct ifnet *ifp = ubus->ifp; - if (ifp != NULL) { - bpfdetach(ifp); - if_down(ifp); - if_detach(ifp); - if_free(ifp); - } - ubus->ifp = NULL; + if (ubus->ifp != NULL) + usbpf_clone_destroy(&usbpf_cloner, ubus->ifp); + if (bootverbose) + device_printf(ubus->parent, "usbpf: Detached\n"); } static uint32_t @@ -259,8 +391,6 @@ usbpf_xfertap(struct usb_xfer *xfer, int bus = xfer->xroot->bus; /* sanity checks */ - if (usb_no_pf != 0) - return; if (bus->ifp == NULL) return; if (!bpf_peers_present(bus->ifp->if_bpf)) Modified: user/hrs/ipv6/sys/netinet6/in6.c ============================================================================== --- user/hrs/ipv6/sys/netinet6/in6.c Wed Apr 18 18:59:27 2012 (r234434) +++ user/hrs/ipv6/sys/netinet6/in6.c Wed Apr 18 18:59:47 2012 (r234435) @@ -434,6 +434,9 @@ in6_control(struct socket *so, u_long cm sa6 = NULL; break; } + if (sa6 != NULL && ifp->if_afdata[AF_INET6] == NULL) + return (EPFNOSUPPORT); + if (sa6 && sa6->sin6_family == AF_INET6) { if (sa6->sin6_scope_id != 0) error = sa6_embedscope(sa6, 0); @@ -2698,6 +2701,14 @@ in6_domifattach(struct ifnet *ifp) { struct in6_ifextra *ext; + /* some of the interfaces are inherently not IPv6 capable */ + switch (ifp->if_type) { + case IFT_PFLOG: + case IFT_PFSYNC: + case IFT_USB: + return (NULL); + } + ext = (struct in6_ifextra *)malloc(sizeof(*ext), M_IFADDR, M_WAITOK); bzero(ext, sizeof(*ext)); Modified: user/hrs/ipv6/sys/netinet6/in6_ifattach.c ============================================================================== --- user/hrs/ipv6/sys/netinet6/in6_ifattach.c Wed Apr 18 18:59:27 2012 (r234434) +++ user/hrs/ipv6/sys/netinet6/in6_ifattach.c Wed Apr 18 18:59:47 2012 (r234435) @@ -697,13 +697,6 @@ in6_ifattach(struct ifnet *ifp, struct i struct in6_ifaddr *ia; struct in6_addr in6; - /* some of the interfaces are inherently not IPv6 capable */ - switch (ifp->if_type) { - case IFT_PFLOG: - case IFT_PFSYNC: - return; - } - /* * quirks based on interface type */ @@ -793,6 +786,9 @@ in6_ifdetach(struct ifnet *ifp) struct sockaddr_in6 sin6; struct in6_multi_mship *imm; + if (ifp->if_afdata[AF_INET6] == NULL) + return; + /* remove neighbor management table */ nd6_purge(ifp); Modified: user/hrs/ipv6/usr.sbin/usbdump/usbdump.c ============================================================================== --- user/hrs/ipv6/usr.sbin/usbdump/usbdump.c Wed Apr 18 18:59:27 2012 (r234434) +++ user/hrs/ipv6/usr.sbin/usbdump/usbdump.c Wed Apr 18 18:59:47 2012 (r234435) @@ -758,6 +758,8 @@ main(int argc, char *argv[]) int o; int filt_unit; int filt_ep; + int s; + int ifindex; const char *optstring; char *pp; @@ -833,9 +835,20 @@ main(int argc, char *argv[]) /* clear ifr structure */ 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) { (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) break; } @@ -876,6 +889,17 @@ main(int argc, char *argv[]) printf("%d packets received by filter\n", us.bs_recv); 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) close(p->fd); if (p->rfd > 0)
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201204181859.q3IIxlu8046266>