summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/net/if_tun.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/net/if_tun.c')
-rw-r--r--freebsd/sys/net/if_tun.c108
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);