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