diff options
Diffstat (limited to 'freebsd/sys/net/if_tun.c')
-rw-r--r-- | freebsd/sys/net/if_tun.c | 108 |
1 files changed, 45 insertions, 63 deletions
diff --git a/freebsd/sys/net/if_tun.c b/freebsd/sys/net/if_tun.c index 556a4860..edb30d04 100644 --- a/freebsd/sys/net/if_tun.c +++ b/freebsd/sys/net/if_tun.c @@ -18,10 +18,8 @@ * $FreeBSD$ */ -#include <rtems/bsd/local/opt_atalk.h> #include <rtems/bsd/local/opt_inet.h> #include <rtems/bsd/local/opt_inet6.h> -#include <rtems/bsd/local/opt_ipx.h> #include <rtems/bsd/sys/param.h> #include <sys/priv.h> @@ -47,6 +45,7 @@ #include <sys/random.h> #include <net/if.h> +#include <net/if_var.h> #include <net/if_clone.h> #include <net/if_types.h> #include <net/netisr.h> @@ -101,7 +100,6 @@ struct tun_softc { #define TUN2IFP(sc) ((sc)->tun_ifp) #define TUNDEBUG if (tundebug) if_printf -#define TUNNAME "tun" /* * All mutable global variables in if_tun are locked using tunmtx, with @@ -109,7 +107,8 @@ struct tun_softc { * which is static after setup. */ static struct mtx tunmtx; -static MALLOC_DEFINE(M_TUN, TUNNAME, "Tunnel Interface"); +static const char tunname[] = "tun"; +static MALLOC_DEFINE(M_TUN, tunname, "Tunnel Interface"); static int tundebug = 0; static int tundclone = 1; static struct clonedevs *tunclones; @@ -119,25 +118,22 @@ SYSCTL_INT(_debug, OID_AUTO, if_tun_debug, CTLFLAG_RW, &tundebug, 0, ""); SYSCTL_DECL(_net_link); static SYSCTL_NODE(_net_link, OID_AUTO, tun, CTLFLAG_RW, 0, "IP tunnel software network interface."); -SYSCTL_INT(_net_link_tun, OID_AUTO, devfs_cloning, CTLFLAG_RW, &tundclone, 0, +SYSCTL_INT(_net_link_tun, OID_AUTO, devfs_cloning, CTLFLAG_RWTUN, &tundclone, 0, "Enable legacy devfs interface creation."); -TUNABLE_INT("net.link.tun.devfs_cloning", &tundclone); - static void tunclone(void *arg, struct ucred *cred, char *name, int namelen, struct cdev **dev); static void tuncreate(const char *name, struct cdev *dev); static int tunifioctl(struct ifnet *, u_long, caddr_t); static void tuninit(struct ifnet *); static int tunmodevent(module_t, int, void *); -static int tunoutput(struct ifnet *, struct mbuf *, struct sockaddr *, - struct route *ro); +static int tunoutput(struct ifnet *, struct mbuf *, + const struct sockaddr *, struct route *ro); static void tunstart(struct ifnet *); static int tun_clone_create(struct if_clone *, int, caddr_t); static void tun_clone_destroy(struct ifnet *); - -IFC_SIMPLE_DECLARE(tun, 0); +static struct if_clone *tun_cloner; static d_open_t tunopen; static d_close_t tunclose; @@ -167,7 +163,7 @@ static struct filterops tun_write_filterops = { static struct cdevsw tun_cdevsw = { .d_version = D_VERSION, - .d_flags = D_PSEUDO | D_NEEDMINOR, + .d_flags = D_NEEDMINOR, .d_open = tunopen, .d_close = tunclose, .d_read = tunread, @@ -175,7 +171,7 @@ static struct cdevsw tun_cdevsw = { .d_ioctl = tunioctl, .d_poll = tunpoll, .d_kqfilter = tunkqfilter, - .d_name = TUNNAME, + .d_name = tunname, }; static int @@ -189,9 +185,9 @@ tun_clone_create(struct if_clone *ifc, int unit, caddr_t params) if (i) { /* No preexisting struct cdev *, create one */ dev = make_dev(&tun_cdevsw, unit, - UID_UUCP, GID_DIALER, 0600, "%s%d", ifc->ifc_name, unit); + UID_UUCP, GID_DIALER, 0600, "%s%d", tunname, unit); } - tuncreate(ifc->ifc_name, dev); + tuncreate(tunname, dev); return (0); } @@ -213,9 +209,9 @@ tunclone(void *arg, struct ucred *cred, char *name, int namelen, if (!tundclone || priv_check_cred(cred, PRIV_NET_IFCREATE, 0) != 0) return; - if (strcmp(name, TUNNAME) == 0) { + if (strcmp(name, tunname) == 0) { u = -1; - } else if (dev_stdclone(name, NULL, TUNNAME, &u) != 1) + } else if (dev_stdclone(name, NULL, tunname, &u) != 1) return; /* Don't recognise the name */ if (u != -1 && u > IF_MAXUNIT) return; /* Unit number too high */ @@ -248,7 +244,6 @@ tun_destroy(struct tun_softc *tp) { struct cdev *dev; - /* Unlocked read. */ mtx_lock(&tp->tun_mtx); if ((tp->tun_flags & TUN_OPEN) != 0) cv_wait_unlock(&tp->tun_cv, &tp->tun_mtx); @@ -262,6 +257,7 @@ tun_destroy(struct tun_softc *tp) if_free(TUN2IFP(tp)); destroy_dev(dev); seldrain(&tp->tun_rsel); + knlist_clear(&tp->tun_rsel.si_note, 0); knlist_destroy(&tp->tun_rsel.si_note); mtx_destroy(&tp->tun_mtx); cv_destroy(&tp->tun_cv); @@ -293,10 +289,11 @@ tunmodevent(module_t mod, int type, void *data) tag = EVENTHANDLER_REGISTER(dev_clone, tunclone, 0, 1000); if (tag == NULL) return (ENOMEM); - if_clone_attach(&tun_cloner); + tun_cloner = if_clone_simple(tunname, tun_clone_create, + tun_clone_destroy, 0); break; case MOD_UNLOAD: - if_clone_detach(&tun_cloner); + if_clone_detach(tun_cloner); EVENTHANDLER_DEREGISTER(dev_clone, tag); drain_dev_clone_events(); @@ -364,8 +361,6 @@ tuncreate(const char *name, struct cdev *dev) struct tun_softc *sc; struct ifnet *ifp; - dev->si_flags &= ~SI_CHEAPCLONE; - sc = malloc(sizeof(*sc), M_TUN, M_WAITOK | M_ZERO); mtx_init(&sc->tun_mtx, "tun_mtx", NULL, MTX_DEF); cv_init(&sc->tun_cv, "tun_condvar"); @@ -412,7 +407,7 @@ tunopen(struct cdev *dev, int flag, int mode, struct thread *td) */ tp = dev->si_drv1; if (!tp) { - tuncreate(TUNNAME, dev); + tuncreate(tunname, dev); tp = dev->si_drv1; } @@ -557,18 +552,16 @@ tunifioctl(struct ifnet *ifp, u_long cmd, caddr_t data) ifs = (struct ifstat *)data; mtx_lock(&tp->tun_mtx); if (tp->tun_pid) - sprintf(ifs->ascii + strlen(ifs->ascii), + snprintf(ifs->ascii, sizeof(ifs->ascii), "\tOpened by PID %d\n", tp->tun_pid); + else + ifs->ascii[0] = '\0'; mtx_unlock(&tp->tun_mtx); break; case SIOCSIFADDR: tuninit(ifp); TUNDEBUG(ifp, "address set\n"); break; - case SIOCSIFDSTADDR: - tuninit(ifp); - TUNDEBUG(ifp, "destination address set\n"); - break; case SIOCSIFMTU: ifp->if_mtu = ifr->ifr_mtu; TUNDEBUG(ifp, "mtu set\n"); @@ -587,7 +580,7 @@ tunifioctl(struct ifnet *ifp, u_long cmd, caddr_t data) * tunoutput - queue packets from higher level ready to put out. */ static int -tunoutput(struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst, +tunoutput(struct ifnet *ifp, struct mbuf *m0, const struct sockaddr *dst, struct route *ro) { struct tun_softc *tp = ifp->if_softc; @@ -621,25 +614,23 @@ tunoutput(struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst, } /* BPF writes need to be handled specially. */ - if (dst->sa_family == AF_UNSPEC) { + if (dst->sa_family == AF_UNSPEC) bcopy(dst->sa_data, &af, sizeof(af)); - dst->sa_family = af; - } - - if (bpf_peers_present(ifp->if_bpf)) { + else af = dst->sa_family; + + if (bpf_peers_present(ifp->if_bpf)) bpf_mtap2(ifp->if_bpf, &af, sizeof(af), m0); - } /* prepend sockaddr? this may abort if the mbuf allocation fails */ if (cached_tun_flags & TUN_LMODE) { /* allocate space for sockaddr */ - M_PREPEND(m0, dst->sa_len, M_DONTWAIT); + M_PREPEND(m0, dst->sa_len, M_NOWAIT); /* if allocation failed drop packet */ if (m0 == NULL) { - ifp->if_iqdrops++; - ifp->if_oerrors++; + if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1); + if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); return (ENOBUFS); } else { bcopy(dst, m0->m_data, dst->sa_len); @@ -648,18 +639,18 @@ tunoutput(struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst, if (cached_tun_flags & TUN_IFHEAD) { /* Prepend the address family */ - M_PREPEND(m0, 4, M_DONTWAIT); + M_PREPEND(m0, 4, M_NOWAIT); /* if allocation failed drop packet */ if (m0 == NULL) { - ifp->if_iqdrops++; - ifp->if_oerrors++; + if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1); + if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); return (ENOBUFS); } else - *(u_int32_t *)m0->m_data = htonl(dst->sa_family); + *(u_int32_t *)m0->m_data = htonl(af); } else { #ifdef INET - if (dst->sa_family != AF_INET) + if (af != AF_INET) #endif { m_freem(m0); @@ -670,7 +661,7 @@ tunoutput(struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst, error = (ifp->if_transmit)(ifp, m0); if (error) return (ENOBUFS); - ifp->if_opackets++; + if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); return (0); } @@ -871,7 +862,7 @@ tunwrite(struct cdev *dev, struct uio *uio, int flag) struct tun_softc *tp = dev->si_drv1; struct ifnet *ifp = TUN2IFP(tp); struct mbuf *m; - uint32_t family; + uint32_t family, mru; int isr; TUNDEBUG(ifp, "tunwrite\n"); @@ -883,13 +874,16 @@ tunwrite(struct cdev *dev, struct uio *uio, int flag) if (uio->uio_resid == 0) return (0); - if (uio->uio_resid < 0 || uio->uio_resid > TUNMRU) { + mru = TUNMRU; + if (tp->tun_flags & TUN_IFHEAD) + mru += sizeof(family); + if (uio->uio_resid < 0 || uio->uio_resid > mru) { TUNDEBUG(ifp, "len=%zd!\n", uio->uio_resid); return (EIO); } - if ((m = m_uiotombuf(uio, M_DONTWAIT, 0, 0, M_PKTHDR)) == NULL) { - ifp->if_ierrors++; + if ((m = m_uiotombuf(uio, M_NOWAIT, 0, 0, M_PKTHDR)) == NULL) { + if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); return (ENOBUFS); } @@ -925,25 +919,13 @@ tunwrite(struct cdev *dev, struct uio *uio, int flag) isr = NETISR_IPV6; break; #endif -#ifdef IPX - case AF_IPX: - isr = NETISR_IPX; - break; -#endif -#ifdef NETATALK - case AF_APPLETALK: - isr = NETISR_ATALK2; - break; -#endif default: m_freem(m); return (EAFNOSUPPORT); } - /* First chunk of an mbuf contains good junk */ - if (harvest.point_to_point) - random_harvest(m, 16, 3, 0, RANDOM_NET); - ifp->if_ibytes += m->m_pkthdr.len; - ifp->if_ipackets++; + random_harvest_queue(m, sizeof(*m), 2, RANDOM_NET_TUN); + if_inc_counter(ifp, IFCOUNTER_IBYTES, m->m_pkthdr.len); + if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); CURVNET_SET(ifp->if_vnet); M_SETFIB(m, ifp->if_fib); netisr_dispatch(isr, m); |