Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src Turn the tun device/network interface into a cloning device.
details: https://anonhg.NetBSD.org/src/rev/5422e8bd539f
branches: trunk
changeset: 516854:5422e8bd539f
user: atatat <atatat%NetBSD.org@localhost>
date: Wed Oct 31 20:08:17 2001 +0000
description:
Turn the tun device/network interface into a cloning device.
diffstat:
share/man/man4/tun.4 | 31 ++++-
sys/net/if_tun.c | 276 ++++++++++++++++++++++++++++++++++++++++++--------
sys/net/if_tun.h | 8 +-
3 files changed, 258 insertions(+), 57 deletions(-)
diffs (truncated from 638 to 300 lines):
diff -r 26da8d2ad56b -r 5422e8bd539f share/man/man4/tun.4
--- a/share/man/man4/tun.4 Wed Oct 31 19:59:43 2001 +0000
+++ b/share/man/man4/tun.4 Wed Oct 31 20:08:17 2001 +0000
@@ -1,4 +1,4 @@
-.\" $NetBSD: tun.4,v 1.10 2001/09/22 16:36:24 wiz Exp $
+.\" $NetBSD: tun.4,v 1.11 2001/10/31 20:08:18 atatat Exp $
.\" Based on PR#2411
.\"
.Dd March 10, 1996
@@ -37,6 +37,21 @@
.Dq control
interface.
.Pp
+To use a
+.Nm tun
+device, the administrator must first create the interface. This can
+be done by using the
+.Xr ifconfig 8
+`create' command, or via the
+.Dv SIOCIFCREATE
+ioctl. Note that an
+.Fn open
+call on
+.Pa /dev/tun Ns Sy N ,
+will indicate that the device is not configured
+.Pq Er ENXIO
+unless the corresponding network interface has been created.
+.Pp
The network interfaces are named
.Sy tun Ns Ar 0 ,
.Sy tun Ns Ar 1 ,
@@ -58,9 +73,8 @@
device, below. When the system chooses to transmit a packet on the
network interface, the packet can be read from the control device
.Po
-it appears as
-.Dq input
-there
+it appears there as
+.Dq output
.Pc ;
writing a packet to the control device generates an input
packet on the network interface, as if the
@@ -73,14 +87,17 @@
.Po
it cannot be opened if it is already open
.Pc
-and is restricted to the super-user. A
+and is restricted to the super-user
+.Po
+regardless of file system permissions
+.Pc . A
.Fn read
call will return an error
.Pq Er EHOSTDOWN
if the interface is not
.Dq ready
-(which means that the control device is open and the interface
-address has been set).
+(which means that the interface
+address has not been set).
Once the interface is ready,
.Fn read
will return a packet if one is available; if not, it will either block
diff -r 26da8d2ad56b -r 5422e8bd539f sys/net/if_tun.c
--- a/sys/net/if_tun.c Wed Oct 31 19:59:43 2001 +0000
+++ b/sys/net/if_tun.c Wed Oct 31 20:08:17 2001 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_tun.c,v 1.45 2001/08/03 21:11:57 itojun Exp $ */
+/* $NetBSD: if_tun.c,v 1.46 2001/10/31 20:08:17 atatat Exp $ */
/*
* Copyright (c) 1988, Julian Onions <jpo%cs.nott.ac.uk@localhost>
@@ -68,46 +68,135 @@
#define TUNDEBUG if (tundebug) printf
int tundebug = 0;
-struct tun_softc tunctl[NTUN];
extern int ifqmaxlen;
void tunattach __P((int));
+LIST_HEAD(, tun_softc) tun_softc_list;
+static struct simplelock tun_softc_lock;
int tun_ioctl __P((struct ifnet *, u_long, caddr_t));
int tun_output __P((struct ifnet *, struct mbuf *, struct sockaddr *,
struct rtentry *rt));
+int tun_clone_create __P((struct if_clone *, int));
+void tun_clone_destroy __P((struct ifnet *));
+struct if_clone tun_cloner =
+ IF_CLONE_INITIALIZER("tun", tun_clone_create, tun_clone_destroy);
+
+static void tunattach0 __P((struct tun_softc *));
static void tuninit __P((struct tun_softc *));
+static struct tun_softc *tun_find_unit __P((dev_t));
void
tunattach(unused)
int unused;
{
- int i;
- struct ifnet *ifp;
+
+ simple_lock_init(&tun_softc_lock);
+ LIST_INIT(&tun_softc_list);
+ if_clone_attach(&tun_cloner);
+}
+
+int
+tun_clone_create(ifc, unit)
+ struct if_clone *ifc;
+ int unit;
+{
+ struct tun_softc *sc;
+
+ sc = malloc(sizeof(struct tun_softc), M_DEVBUF, M_WAITOK);
+ (void)memset(sc, 0, sizeof(struct tun_softc));
- for (i = 0; i < NTUN; i++) {
- tunctl[i].tun_flags = TUN_INITED;
+ (void)snprintf(sc->tun_if.if_xname, sizeof(sc->tun_if.if_xname),
+ "%s%d", ifc->ifc_name, unit);
+ sc->tun_unit = unit;
+ simple_lock_init(&sc->tun_lock);
+
+ tunattach0(sc);
+
+ simple_lock(&tun_softc_lock);
+ LIST_INSERT_HEAD(&tun_softc_list, sc, tun_list);
+ simple_unlock(&tun_softc_lock);
+
+ return (0);
+}
+
+void
+tunattach0(sc)
+ struct tun_softc *sc;
+{
+ struct ifnet *ifp = (void *)sc;
+
+ sc->tun_flags = TUN_INITED;
- ifp = &tunctl[i].tun_if;
- sprintf(ifp->if_xname, "tun%d", i);
- ifp->if_softc = &tunctl[i];
- ifp->if_mtu = TUNMTU;
- ifp->if_ioctl = tun_ioctl;
- ifp->if_output = tun_output;
- ifp->if_flags = IFF_POINTOPOINT;
- ifp->if_snd.ifq_maxlen = ifqmaxlen;
- ifp->if_collisions = 0;
- ifp->if_ierrors = 0;
- ifp->if_oerrors = 0;
- ifp->if_ipackets = 0;
- ifp->if_opackets = 0;
- ifp->if_dlt = DLT_NULL;
- if_attach(ifp);
- if_alloc_sadl(ifp);
+ ifp = &sc->tun_if;
+ ifp->if_softc = sc;
+ ifp->if_mtu = TUNMTU;
+ ifp->if_ioctl = tun_ioctl;
+ ifp->if_output = tun_output;
+ ifp->if_flags = IFF_POINTOPOINT;
+ ifp->if_snd.ifq_maxlen = ifqmaxlen;
+ ifp->if_collisions = 0;
+ ifp->if_ierrors = 0;
+ ifp->if_oerrors = 0;
+ ifp->if_ipackets = 0;
+ ifp->if_opackets = 0;
+ ifp->if_dlt = DLT_NULL;
+ if_attach(ifp);
+ if_alloc_sadl(ifp);
#if NBPFILTER > 0
- bpfattach(ifp, DLT_NULL, sizeof(u_int32_t));
+ bpfattach(ifp, DLT_NULL, sizeof(u_int32_t));
#endif
+}
+
+void
+tun_clone_destroy(ifp)
+ struct ifnet *ifp;
+{
+ struct tun_softc *tp = (void *)ifp;
+ struct proc *p;
+
+ simple_lock(&tun_softc_lock);
+ simple_lock(&tp->tun_lock);
+ LIST_REMOVE(tp, tun_list);
+ simple_unlock(&tp->tun_lock);
+ simple_unlock(&tun_softc_lock);
+
+ if (tp->tun_flags & TUN_RWAIT) {
+ tp->tun_flags &= ~TUN_RWAIT;
+ wakeup((caddr_t)tp);
}
+ if (tp->tun_flags & TUN_ASYNC && tp->tun_pgrp) {
+ if (tp->tun_pgrp > 0)
+ gsignal(tp->tun_pgrp, SIGIO);
+ else if ((p = pfind(-tp->tun_pgrp)) != NULL)
+ psignal(p, SIGIO);
+ }
+ selwakeup(&tp->tun_rsel);
+
+#if NBPFILTER > 0
+ bpfdetach(ifp);
+#endif
+ if_detach(ifp);
+
+ free(tp, M_DEVBUF);
+}
+
+static struct tun_softc *
+tun_find_unit(dev)
+ dev_t dev;
+{
+ struct tun_softc *tp;
+ int unit = minor(dev);
+
+ simple_lock(&tun_softc_lock);
+ LIST_FOREACH(tp, &tun_softc_list, tun_list)
+ if (unit == tp->tun_unit)
+ break;
+ if (tp)
+ simple_lock(&tp->tun_lock);
+ simple_unlock(&tun_softc_lock);
+
+ return (tp);
}
/*
@@ -122,19 +211,28 @@
{
struct ifnet *ifp;
struct tun_softc *tp;
- int unit, error;
+ int error;
if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
return (error);
- if ((unit = minor(dev)) >= NTUN)
+ if (NTUN < 1)
+ return (ENXIO);
+
+ tp = tun_find_unit(dev);
+
+ if (!tp)
return (ENXIO);
- tp = &tunctl[unit];
- if (tp->tun_flags & TUN_OPEN)
- return ENXIO;
+
+ if (tp->tun_flags & TUN_OPEN) {
+ simple_unlock(&tp->tun_lock);
+ return (EBUSY);
+ }
+
ifp = &tp->tun_if;
tp->tun_flags |= TUN_OPEN;
TUNDEBUG("%s: open\n", ifp->if_xname);
+ simple_unlock(&tp->tun_lock);
return (0);
}
@@ -149,11 +247,19 @@
int mode;
struct proc *p;
{
- int unit = minor(dev), s;
- struct tun_softc *tp = &tunctl[unit];
- struct ifnet *ifp = &tp->tun_if;
+ int s;
+ struct tun_softc *tp;
+ struct ifnet *ifp;
struct mbuf *m;
+ tp = tun_find_unit(dev);
+
+ /* interface was "destroyed" before the close */
+ if (tp == NULL)
+ return (0);
+
+ ifp = &tp->tun_if;
+
tp->tun_flags &= ~TUN_OPEN;
/*
@@ -191,6 +297,7 @@
selwakeup(&tp->tun_rsel);
TUNDEBUG ("%s: closed\n", ifp->if_xname);
+ simple_unlock(&tp->tun_lock);
return (0);
}
@@ -199,7 +306,7 @@
struct tun_softc *tp;
{
struct ifnet *ifp = &tp->tun_if;
Home |
Main Index |
Thread Index |
Old Index