diff options
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/if_tap.c | 164 | ||||
-rw-r--r-- | sys/net/if_tapvar.h | 1 | ||||
-rw-r--r-- | sys/net/if_tun.c | 163 | ||||
-rw-r--r-- | sys/net/if_tunvar.h | 55 |
4 files changed, 98 insertions, 285 deletions
diff --git a/sys/net/if_tap.c b/sys/net/if_tap.c index 82ae3b9..f83243b 100644 --- a/sys/net/if_tap.c +++ b/sys/net/if_tap.c @@ -54,8 +54,6 @@ #include <sys/ttycom.h> #include <sys/uio.h> #include <sys/vnode.h> -#include <machine/bus.h> /* XXX: Shouldn't really be required! */ -#include <sys/rman.h> #include <sys/queue.h> #include <net/bpf.h> @@ -71,14 +69,12 @@ #define CDEV_NAME "tap" -#define CDEV_MAJOR 149 #define TAPDEBUG if (tapdebug) printf #define TAP "tap" #define VMNET "vmnet" #define TAPMAXUNIT 0x7fff -#define VMNET_DEV_MASK 0x00800000 - /* 0x007f00ff */ +#define VMNET_DEV_MASK CLONE_FLAG0 /* module */ static int tapmodevent(module_t, int, void *); @@ -108,15 +104,12 @@ static struct cdevsw tap_cdevsw = { .d_ioctl = tapioctl, .d_poll = tappoll, .d_name = CDEV_NAME, - .d_maj = CDEV_MAJOR, + .d_flags = D_PSEUDO, }; static int tapdebug = 0; /* debug flag */ static SLIST_HEAD(, tap_softc) taphead; /* first device */ -static udev_t tapbasedev = NOUDEV; /* base device */ -static struct rman tapdevunits[2]; /* device units */ -#define tapunits tapdevunits -#define vmnetunits (tapdevunits + 1) +static struct clonedevs *tapclones; MALLOC_DECLARE(M_TAP); MALLOC_DEFINE(M_TAP, CDEV_NAME, "Ethernet tunnel interface"); @@ -137,63 +130,27 @@ tapmodevent(mod, type, data) static eventhandler_tag eh_tag = NULL; struct tap_softc *tp = NULL; struct ifnet *ifp = NULL; - int error, s; + int s; switch (type) { case MOD_LOAD: - /* initialize resources */ - tapunits->rm_type = RMAN_ARRAY; - tapunits->rm_descr = "open tap units"; - vmnetunits->rm_type = RMAN_ARRAY; - vmnetunits->rm_descr = "open vmnet units"; - - error = rman_init(tapunits); - if (error != 0) - goto bail; - - error = rman_init(vmnetunits); - if (error != 0) - goto bail1; - - error = rman_manage_region(tapunits, 0, TAPMAXUNIT); - if (error != 0) - goto bail2; - - error = rman_manage_region(vmnetunits, 0, TAPMAXUNIT); - if (error != 0) - goto bail2; /* intitialize device */ SLIST_INIT(&taphead); eh_tag = EVENTHANDLER_REGISTER(dev_clone, tapclone, 0, 1000); - if (eh_tag == NULL) { - error = ENOMEM; - goto bail2; - } - - + if (eh_tag == NULL) + return (ENOMEM); return (0); -bail2: - rman_fini(vmnetunits); -bail1: - rman_fini(tapunits); -bail: - return (error); case MOD_UNLOAD: SLIST_FOREACH(tp, &taphead, tap_next) - if (tp->tap_unit != NULL) + if (tp->tap_flags & TAP_OPEN) return (EBUSY); EVENTHANDLER_DEREGISTER(dev_clone, eh_tag); - error = rman_fini(tapunits); - KASSERT((error == 0), ("Could not fini tap units")); - error = rman_fini(vmnetunits); - KASSERT((error == 0), ("Could not fini vmnet units")); - while ((tp = SLIST_FIRST(&taphead)) != NULL) { SLIST_REMOVE_HEAD(&taphead, tap_next); @@ -204,18 +161,14 @@ bail: KASSERT(!(tp->tap_flags & TAP_OPEN), ("%s flags is out of sync", ifp->if_xname)); - /* XXX makedev check? nah.. not right now :) */ - + destroy_dev(tp->tap_dev); s = splimp(); ether_ifdetach(ifp); splx(s); free(tp, M_TAP); } - - if (tapbasedev != NOUDEV) - destroy_dev(udev2dev(tapbasedev, 0)); - + clone_cleanup(&tapclones); break; @@ -239,65 +192,35 @@ tapclone(arg, name, namelen, dev) int namelen; dev_t *dev; { - int unit, minor = 0 /* XXX avoid warning */ , error; + u_int extra; + int i, unit; char *device_name = name; - struct resource *r = NULL; if (*dev != NODEV) return; - if (strcmp(device_name, TAP) == 0) { - /* get first free tap unit */ - r = rman_reserve_resource(tapunits, 0, TAPMAXUNIT, 1, - RF_ALLOCATED | RF_ACTIVE, NULL); - unit = rman_get_start(r); - minor = unit2minor(unit); - } - else if (strcmp(device_name, VMNET) == 0) { - /* get first free vmnet unit */ - r = rman_reserve_resource(vmnetunits, 0, TAPMAXUNIT, 1, - RF_ALLOCATED | RF_ACTIVE, NULL); - unit = rman_get_start(r); - minor = unit2minor(unit) | VMNET_DEV_MASK; + device_name = TAP; + extra = 0; + if (strcmp(name, TAP) == 0) { + unit = -1; + } else if (strcmp(name, VMNET) == 0) { + device_name = VMNET; + extra = VMNET_DEV_MASK; + unit = -1; + } else if (dev_stdclone(name, NULL, device_name, &unit) != 1) { + device_name = VMNET; + extra = VMNET_DEV_MASK; + if (dev_stdclone(name, NULL, device_name, &unit) != 1) + return; } - if (r != NULL) { /* need cloning */ - TAPDEBUG("%s%d is available. minor = %#x\n", - device_name, unit, minor); - - error = rman_release_resource(r); - KASSERT((error == 0), ("Could not release tap/vmnet unit")); - - /* check if device for the unit has been created */ - *dev = makedev(CDEV_MAJOR, minor); - if ((*dev)->si_flags & SI_NAMED) { - TAPDEBUG("%s%d device exists. minor = %#x\n", - device_name, unit, minor); - return; /* device has been created */ - } - } else { /* try to match name/unit, first try tap then vmnet */ - device_name = TAP; - if (dev_stdclone(name, NULL, device_name, &unit) != 1) { - device_name = VMNET; - - if (dev_stdclone(name, NULL, device_name, &unit) != 1) - return; - - minor = unit2minor(unit) | VMNET_DEV_MASK; - } else - minor = unit2minor(unit); - } - - TAPDEBUG("make_dev(%s%d). minor = %#x\n", device_name, unit, minor); - - *dev = make_dev(&tap_cdevsw, minor, UID_ROOT, GID_WHEEL, 0600, "%s%d", - device_name, unit); - - if (tapbasedev == NOUDEV) - tapbasedev = (*dev)->si_udev; - else { - (*dev)->si_flags |= SI_CHEAPCLONE; - dev_depends(udev2dev(tapbasedev, 0), *dev); + /* find any existing device, or allocate new unit number */ + i = clone_create(&tapclones, &tap_cdevsw, &unit, dev, extra); + if (i) { + *dev = make_dev(&tap_cdevsw, unit2minor(unit) | extra, + UID_ROOT, GID_WHEEL, 0600, "%s%d", device_name, unit); + if (*dev != NULL) + (*dev)->si_flags |= SI_CHEAPCLONE; } } /* tapclone */ @@ -317,6 +240,8 @@ tapcreate(dev) int unit, s; char *name = NULL; + dev->si_flags &= ~SI_CHEAPCLONE; + /* allocate driver storage and create device */ MALLOC(tp, struct tap_softc *, sizeof(*tp), M_TAP, M_WAITOK | M_ZERO); SLIST_INSERT_HEAD(&taphead, tp, tap_next); @@ -354,6 +279,7 @@ tapcreate(dev) ifp->if_snd.ifq_maxlen = ifqmaxlen; dev->si_drv1 = tp; + tp->tap_dev = dev; s = splimp(); ether_ifattach(ifp, tp->arpcom.ac_enaddr); @@ -380,24 +306,12 @@ tapopen(dev, flag, mode, td) { struct tap_softc *tp = NULL; int unit, error; - struct resource *r = NULL; if ((error = suser(td)) != 0) return (error); unit = dev2unit(dev) & TAPMAXUNIT; - if (minor(dev) & VMNET_DEV_MASK) - r = rman_reserve_resource(vmnetunits, unit, unit, 1, - RF_ALLOCATED | RF_ACTIVE, NULL); - else - r = rman_reserve_resource(tapunits, unit, unit, 1, - RF_ALLOCATED | RF_ACTIVE, NULL); - - if (r == NULL) - return (EBUSY); - - dev->si_flags &= ~SI_CHEAPCLONE; tp = dev->si_drv1; if (tp == NULL) { @@ -410,7 +324,6 @@ tapopen(dev, flag, mode, td) bcopy(tp->arpcom.ac_enaddr, tp->ether_addr, sizeof(tp->ether_addr)); - tp->tap_unit = r; tp->tap_pid = td->td_proc->p_pid; tp->tap_flags |= TAP_OPEN; @@ -433,12 +346,9 @@ tapclose(dev, foo, bar, td) int bar; struct thread *td; { - int s, error; struct tap_softc *tp = dev->si_drv1; struct ifnet *ifp = &tp->tap_if; - - KASSERT((tp->tap_unit != NULL), - ("%s is not open", ifp->if_xname)); + int s; /* junk all pending output */ IF_DRAIN(&ifp->if_snd); @@ -479,10 +389,6 @@ tapclose(dev, foo, bar, td) tp->tap_flags &= ~TAP_OPEN; tp->tap_pid = 0; - error = rman_release_resource(tp->tap_unit); - KASSERT((error == 0), - ("%s could not release unit", ifp->if_xname)); - tp->tap_unit = NULL; TAPDEBUG("%s is closed. minor = %#x\n", ifp->if_xname, minor(dev)); diff --git a/sys/net/if_tapvar.h b/sys/net/if_tapvar.h index 06e3bbdf..ae6c3cd 100644 --- a/sys/net/if_tapvar.h +++ b/sys/net/if_tapvar.h @@ -61,6 +61,7 @@ struct tap_softc { struct selinfo tap_rsel; /* read select */ SLIST_ENTRY(tap_softc) tap_next; /* next device in chain */ + dev_t tap_dev; }; #endif /* !_NET_IF_TAPVAR_H_ */ diff --git a/sys/net/if_tun.c b/sys/net/if_tun.c index 516d299..4a64da4 100644 --- a/sys/net/if_tun.c +++ b/sys/net/if_tun.c @@ -41,9 +41,7 @@ #include <sys/uio.h> #include <sys/vnode.h> #include <sys/malloc.h> -#include <machine/bus.h> /* XXX Shouldn't really be required ! */ #include <sys/random.h> -#include <sys/rman.h> #include <net/if.h> #include <net/if_types.h> @@ -53,17 +51,40 @@ #include <netinet/in.h> #endif #include <net/bpf.h> -#include <net/if_tunvar.h> #include <net/if_tun.h> +#include <sys/queue.h> + +struct tun_softc { + TAILQ_ENTRY(tun_softc) tun_list; + int tun_unit; + dev_t tun_dev; + u_short tun_flags; /* misc flags */ +#define TUN_OPEN 0x0001 +#define TUN_INITED 0x0002 +#define TUN_RCOLL 0x0004 +#define TUN_IASET 0x0008 +#define TUN_DSTADDR 0x0010 +#define TUN_LMODE 0x0020 +#define TUN_RWAIT 0x0040 +#define TUN_ASYNC 0x0080 +#define TUN_IFHEAD 0x0100 + +#define TUN_READY (TUN_OPEN | TUN_INITED) + + struct proc *tun_proc; /* Owning process */ + struct ifnet tun_if; /* the interface */ + struct sigio *tun_sigio; /* information for async I/O */ + struct selinfo tun_rsel; /* read select */ +}; + #define TUNDEBUG if (tundebug) if_printf #define TUNNAME "tun" static MALLOC_DEFINE(M_TUN, TUNNAME, "Tunnel Interface"); static int tundebug = 0; -static struct tun_softc *tunhead = NULL; -static struct rman tununits; -static udev_t tunbasedev = NOUDEV; +static struct clonedevs *tunclones; +static TAILQ_HEAD(,tun_softc) tunhead = TAILQ_HEAD_INITIALIZER(tunhead); SYSCTL_INT(_debug, OID_AUTO, if_tun_debug, CTLFLAG_RW, &tundebug, 0, ""); static void tunclone(void *arg, char *name, int namelen, dev_t *dev); @@ -82,7 +103,6 @@ static d_write_t tunwrite; static d_ioctl_t tunioctl; static d_poll_t tunpoll; -#define CDEV_MAJOR 52 static struct cdevsw tun_cdevsw = { .d_open = tunopen, .d_close = tunclose, @@ -91,44 +111,32 @@ static struct cdevsw tun_cdevsw = { .d_ioctl = tunioctl, .d_poll = tunpoll, .d_name = TUNNAME, - .d_maj = CDEV_MAJOR, + .d_flags = D_PSEUDO, }; static void tunclone(void *arg, char *name, int namelen, dev_t *dev) { - struct resource *r; - int err; - int u; + int u, i; if (*dev != NODEV) return; if (strcmp(name, TUNNAME) == 0) { - r = rman_reserve_resource(&tununits, 0, IF_MAXUNIT, 1, - RF_ALLOCATED | RF_ACTIVE, NULL); - u = rman_get_start(r); - err = rman_release_resource(r); - KASSERT(err == 0, ("Unexpected failure releasing resource")); - *dev = makedev(CDEV_MAJOR, unit2minor(u)); - if ((*dev)->si_flags & SI_NAMED) - return; /* Already make_dev()d */ + u = -1; } else if (dev_stdclone(name, NULL, TUNNAME, &u) != 1) return; /* Don't recognise the name */ - - *dev = make_dev(&tun_cdevsw, unit2minor(u), - UID_ROOT, GID_WHEEL, 0600, "tun%d", u); - - /* - * All devices depend on tunbasedev so that we can simply - * destroy_dev() this device at module unload time to get - * rid of all our make_dev()d resources. - */ - if (tunbasedev == NOUDEV) - tunbasedev = (*dev)->si_udev; - else { - (*dev)->si_flags |= SI_CHEAPCLONE; - dev_depends(udev2dev(tunbasedev, 0), *dev); + if (u != -1 && u > IF_MAXUNIT) + return; /* Unit number too high */ + + /* find any existing device, or allocate new unit number */ + i = clone_create(&tunclones, &tun_cdevsw, &u, dev, 0); + if (i) { + /* No preexisting dev_t, create one */ + *dev = make_dev(&tun_cdevsw, unit2minor(u), + UID_UUCP, GID_DIALER, 0600, "tun%d", u); + if (*dev != NULL) + (*dev)->si_flags |= SI_CHEAPCLONE; } } @@ -138,57 +146,29 @@ tunmodevent(module_t mod, int type, void *data) static eventhandler_tag tag; struct tun_softc *tp; dev_t dev; - int err; switch (type) { case MOD_LOAD: tag = EVENTHANDLER_REGISTER(dev_clone, tunclone, 0, 1000); if (tag == NULL) return (ENOMEM); - tununits.rm_type = RMAN_ARRAY; - tununits.rm_descr = "open if_tun units"; - err = rman_init(&tununits); - if (err != 0) { - EVENTHANDLER_DEREGISTER(dev_clone, tag); - return (err); - } - err = rman_manage_region(&tununits, 0, IF_MAXUNIT); - if (err != 0) { - printf("%s: tununits: rman_manage_region: Failed %d\n", - TUNNAME, err); - rman_fini(&tununits); - EVENTHANDLER_DEREGISTER(dev_clone, tag); - return (err); - } break; case MOD_UNLOAD: - err = rman_fini(&tununits); - if (err != 0) - return (err); EVENTHANDLER_DEREGISTER(dev_clone, tag); - while (tunhead != NULL) { - KASSERT((tunhead->tun_flags & TUN_OPEN) == 0, + while (!TAILQ_EMPTY(&tunhead)) { + tp = TAILQ_FIRST(&tunhead); + KASSERT((tp->tun_flags & TUN_OPEN) == 0, ("tununits is out of sync - unit %d", - tunhead->tun_if.if_dunit)); - tp = tunhead; - dev = makedev(tun_cdevsw.d_maj, - unit2minor(tp->tun_if.if_dunit)); - KASSERT(dev->si_drv1 == tp, ("Bad makedev result")); - tunhead = tp->next; + tp->tun_if.if_dunit)); + TAILQ_REMOVE(&tunhead, tp, tun_list); + dev = tp->tun_dev; bpfdetach(&tp->tun_if); if_detach(&tp->tun_if); - KASSERT(dev->si_flags & SI_NAMED, ("Missing make_dev")); + destroy_dev(dev); free(tp, M_TUN); } - - /* - * Destroying tunbasedev results in all of our make_dev()s - * conveniently going away. - */ - if (tunbasedev != NOUDEV) - destroy_dev(udev2dev(tunbasedev, 0)); - + clone_cleanup(&tunclones); break; } return 0; @@ -222,14 +202,12 @@ tuncreate(dev_t dev) struct tun_softc *sc; struct ifnet *ifp; - if (!(dev->si_flags & SI_NAMED)) - dev = make_dev(&tun_cdevsw, minor(dev), - UID_UUCP, GID_DIALER, 0600, "tun%d", dev2unit(dev)); + dev->si_flags &= ~SI_CHEAPCLONE; MALLOC(sc, struct tun_softc *, sizeof(*sc), M_TUN, M_WAITOK | M_ZERO); sc->tun_flags = TUN_INITED; - sc->next = tunhead; - tunhead = sc; + sc->tun_dev = dev; + TAILQ_INSERT_TAIL(&tunhead, sc, tun_list); ifp = &sc->tun_if; if_initname(ifp, TUNNAME, dev2unit(dev)); @@ -249,32 +227,21 @@ tuncreate(dev_t dev) static int tunopen(dev_t dev, int flag, int mode, struct thread *td) { - struct resource *r; struct ifnet *ifp; struct tun_softc *tp; - int unit; - - unit = dev2unit(dev); - if (unit > IF_MAXUNIT) - return (ENXIO); - - r = rman_reserve_resource(&tununits, unit, unit, 1, - RF_ALLOCATED | RF_ACTIVE, NULL); - if (r == NULL) - return (EBUSY); - - dev->si_flags &= ~SI_CHEAPCLONE; tp = dev->si_drv1; if (!tp) { tuncreate(dev); tp = dev->si_drv1; } - KASSERT(!(tp->tun_flags & TUN_OPEN), ("Resource & flags out-of-sync")); - tp->tun_unit = r; - tp->tun_pid = td->td_proc->p_pid; - ifp = &tp->tun_if; + + if (tp->tun_proc != NULL && tp->tun_proc != td->td_proc) + return (EBUSY); + tp->tun_proc = td->td_proc; + tp->tun_flags |= TUN_OPEN; + ifp = &tp->tun_if; TUNDEBUG(ifp, "open\n"); return (0); @@ -290,14 +257,12 @@ tunclose(dev_t dev, int foo, int bar, struct thread *td) struct tun_softc *tp; struct ifnet *ifp; int s; - int err; tp = dev->si_drv1; ifp = &tp->tun_if; - KASSERT(tp->tun_unit, ("Unit %d not marked open", tp->tun_if.if_dunit)); tp->tun_flags &= ~TUN_OPEN; - tp->tun_pid = 0; + tp->tun_proc = NULL; /* * junk all pending output @@ -325,11 +290,7 @@ tunclose(dev_t dev, int foo, int bar, struct thread *td) funsetown(&tp->tun_sigio); selwakeuppri(&tp->tun_rsel, PZERO + 1); - TUNDEBUG (ifp, "closed\n"); - err = rman_release_resource(tp->tun_unit); - KASSERT(err == 0, ("Unit %d failed to release", tp->tun_if.if_dunit)); - return (0); } @@ -384,9 +345,9 @@ tunifioctl(struct ifnet *ifp, u_long cmd, caddr_t data) switch(cmd) { case SIOCGIFSTATUS: ifs = (struct ifstat *)data; - if (tp->tun_pid) + if (tp->tun_proc) sprintf(ifs->ascii + strlen(ifs->ascii), - "\tOpened by PID %d\n", tp->tun_pid); + "\tOpened by PID %d\n", tp->tun_proc->p_pid); break; case SIOCSIFADDR: error = tuninit(ifp); @@ -573,7 +534,7 @@ tunioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td) } break; case TUNSIFPID: - tp->tun_pid = curthread->td_proc->p_pid; + tp->tun_proc = curthread->td_proc; break; case FIONBIO: break; diff --git a/sys/net/if_tunvar.h b/sys/net/if_tunvar.h deleted file mode 100644 index cda53f0..0000000 --- a/sys/net/if_tunvar.h +++ /dev/null @@ -1,55 +0,0 @@ -/*- - * Copyright (c) 1998 Brian Somers <brian@Awfulhak.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. - * 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$ - */ - -#ifndef _NET_IF_TUNVAR_H_ -#define _NET_IF_TUNVAR_H_ - -struct tun_softc { - u_short tun_flags; /* misc flags */ -#define TUN_OPEN 0x0001 -#define TUN_INITED 0x0002 -#define TUN_RCOLL 0x0004 -#define TUN_IASET 0x0008 -#define TUN_DSTADDR 0x0010 -#define TUN_LMODE 0x0020 -#define TUN_RWAIT 0x0040 -#define TUN_ASYNC 0x0080 -#define TUN_IFHEAD 0x0100 - -#define TUN_READY (TUN_OPEN | TUN_INITED) - - pid_t tun_pid; /* PID of process to open */ - struct ifnet tun_if; /* the interface */ - struct sigio *tun_sigio; /* information for async I/O */ - struct selinfo tun_rsel; /* read select */ - - struct tun_softc *next; /* Next softc in list */ - struct resource *tun_unit; /* resource allocated for this unit */ -}; - -#endif /* !_NET_IF_TUNVAR_H_ */ |