The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/net/if_tun.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: if_tun.c,v 1.14 1994/06/29 06:36:25 cgd Exp $  */
    2 
    3 /*-
    4  * Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk>
    5  * Nottingham University 1987.
    6  *
    7  * This source may be freely distributed, however I would be interested
    8  * in any changes that are made.
    9  *
   10  * This driver takes packets off the IP i/f and hands them up to a
   11  * user process to have its wicked way with. This driver has it's
   12  * roots in a similar driver written by Phil Cockcroft (formerly) at
   13  * UCL. This driver is based much more on read/write/poll mode of
   14  * operation though.
   15  *
   16  * $FreeBSD: releng/6.2/sys/net/if_tun.c 161441 2006-08-18 14:05:17Z rwatson $
   17  */
   18 
   19 #include "opt_atalk.h"
   20 #include "opt_inet.h"
   21 #include "opt_inet6.h"
   22 #include "opt_ipx.h"
   23 #include "opt_mac.h"
   24 
   25 #include <sys/param.h>
   26 #include <sys/proc.h>
   27 #include <sys/systm.h>
   28 #include <sys/mac.h>
   29 #include <sys/mbuf.h>
   30 #include <sys/module.h>
   31 #include <sys/socket.h>
   32 #include <sys/fcntl.h>
   33 #include <sys/filio.h>
   34 #include <sys/sockio.h>
   35 #include <sys/ttycom.h>
   36 #include <sys/poll.h>
   37 #include <sys/selinfo.h>
   38 #include <sys/signalvar.h>
   39 #include <sys/filedesc.h>
   40 #include <sys/kernel.h>
   41 #include <sys/sysctl.h>
   42 #include <sys/conf.h>
   43 #include <sys/uio.h>
   44 #include <sys/malloc.h>
   45 #include <sys/random.h>
   46 
   47 #include <net/if.h>
   48 #include <net/if_types.h>
   49 #include <net/netisr.h>
   50 #include <net/route.h>
   51 #ifdef INET
   52 #include <netinet/in.h>
   53 #endif
   54 #include <net/bpf.h>
   55 #include <net/if_tun.h>
   56 
   57 #include <sys/queue.h>
   58 
   59 /*
   60  * tun_list is protected by global tunmtx.  Other mutable fields are
   61  * protected by tun->tun_mtx, or by their owning subsystem.  tun_dev is
   62  * static for the duration of a tunnel interface.
   63  */
   64 struct tun_softc {
   65         TAILQ_ENTRY(tun_softc)  tun_list;
   66         struct cdev *tun_dev;
   67         u_short tun_flags;              /* misc flags */
   68 #define TUN_OPEN        0x0001
   69 #define TUN_INITED      0x0002
   70 #define TUN_RCOLL       0x0004
   71 #define TUN_IASET       0x0008
   72 #define TUN_DSTADDR     0x0010
   73 #define TUN_LMODE       0x0020
   74 #define TUN_RWAIT       0x0040
   75 #define TUN_ASYNC       0x0080
   76 #define TUN_IFHEAD      0x0100
   77 
   78 #define TUN_READY       (TUN_OPEN | TUN_INITED)
   79 
   80         /*
   81          * XXXRW: tun_pid is used to exclusively lock /dev/tun.  Is this
   82          * actually needed?  Can we just return EBUSY if already open?
   83          * Problem is that this involved inherent races when a tun device
   84          * is handed off from one process to another, as opposed to just
   85          * being slightly stale informationally.
   86          */
   87         pid_t   tun_pid;                /* owning pid */
   88         struct  ifnet *tun_ifp;         /* the interface */
   89         struct  sigio *tun_sigio;       /* information for async I/O */
   90         struct  selinfo tun_rsel;       /* read select */
   91         struct mtx      tun_mtx;        /* protect mutable softc fields */
   92 };
   93 #define TUN2IFP(sc)     ((sc)->tun_ifp)
   94 
   95 #define TUNDEBUG        if (tundebug) if_printf
   96 #define TUNNAME         "tun"
   97 
   98 /*
   99  * All mutable global variables in if_tun are locked using tunmtx, with
  100  * the exception of tundebug, which is used unlocked, and tunclones,
  101  * which is static after setup.
  102  */
  103 static struct mtx tunmtx;
  104 static MALLOC_DEFINE(M_TUN, TUNNAME, "Tunnel Interface");
  105 static int tundebug = 0;
  106 static struct clonedevs *tunclones;
  107 static TAILQ_HEAD(,tun_softc)   tunhead = TAILQ_HEAD_INITIALIZER(tunhead);
  108 SYSCTL_INT(_debug, OID_AUTO, if_tun_debug, CTLFLAG_RW, &tundebug, 0, "");
  109 
  110 static void     tunclone(void *arg, struct ucred *cred, char *name,
  111                     int namelen, struct cdev **dev);
  112 static void     tuncreate(struct cdev *dev);
  113 static int      tunifioctl(struct ifnet *, u_long, caddr_t);
  114 static int      tuninit(struct ifnet *);
  115 static int      tunmodevent(module_t, int, void *);
  116 static int      tunoutput(struct ifnet *, struct mbuf *, struct sockaddr *,
  117                     struct rtentry *rt);
  118 static void     tunstart(struct ifnet *);
  119 
  120 static d_open_t         tunopen;
  121 static d_close_t        tunclose;
  122 static d_read_t         tunread;
  123 static d_write_t        tunwrite;
  124 static d_ioctl_t        tunioctl;
  125 static d_poll_t         tunpoll;
  126 static d_kqfilter_t     tunkqfilter;
  127 
  128 static int              tunkqread(struct knote *, long);
  129 static int              tunkqwrite(struct knote *, long);
  130 static void             tunkqdetach(struct knote *);
  131 
  132 static struct filterops tun_read_filterops = {
  133         .f_isfd =       1,
  134         .f_attach =     NULL,
  135         .f_detach =     tunkqdetach,
  136         .f_event =      tunkqread,
  137 };
  138 
  139 static struct filterops tun_write_filterops = {
  140         .f_isfd =       1,
  141         .f_attach =     NULL,
  142         .f_detach =     tunkqdetach,
  143         .f_event =      tunkqwrite,
  144 };
  145 
  146 static struct cdevsw tun_cdevsw = {
  147         .d_version =    D_VERSION,
  148         .d_flags =      D_PSEUDO | D_NEEDGIANT,
  149         .d_open =       tunopen,
  150         .d_close =      tunclose,
  151         .d_read =       tunread,
  152         .d_write =      tunwrite,
  153         .d_ioctl =      tunioctl,
  154         .d_poll =       tunpoll,
  155         .d_kqfilter =   tunkqfilter,
  156         .d_name =       TUNNAME,
  157 };
  158 
  159 static void
  160 tunclone(void *arg, struct ucred *cred, char *name, int namelen,
  161     struct cdev **dev)
  162 {
  163         int u, i;
  164 
  165         if (*dev != NULL)
  166                 return;
  167 
  168         if (strcmp(name, TUNNAME) == 0) {
  169                 u = -1;
  170         } else if (dev_stdclone(name, NULL, TUNNAME, &u) != 1)
  171                 return; /* Don't recognise the name */
  172         if (u != -1 && u > IF_MAXUNIT)
  173                 return; /* Unit number too high */
  174 
  175         /* find any existing device, or allocate new unit number */
  176         i = clone_create(&tunclones, &tun_cdevsw, &u, dev, 0);
  177         if (i) {
  178                 /* No preexisting struct cdev *, create one */
  179                 *dev = make_dev(&tun_cdevsw, unit2minor(u),
  180                     UID_UUCP, GID_DIALER, 0600, "tun%d", u);
  181                 if (*dev != NULL) {
  182                         dev_ref(*dev);
  183                         (*dev)->si_flags |= SI_CHEAPCLONE;
  184                 }
  185         }
  186 }
  187 
  188 static void
  189 tun_destroy(struct tun_softc *tp)
  190 {
  191         struct cdev *dev;
  192 
  193         /* Unlocked read. */
  194         KASSERT((tp->tun_flags & TUN_OPEN) == 0,
  195             ("tununits is out of sync - unit %d", TUN2IFP(tp)->if_dunit));
  196 
  197         dev = tp->tun_dev;
  198         bpfdetach(TUN2IFP(tp));
  199         if_detach(TUN2IFP(tp));
  200         if_free(TUN2IFP(tp));
  201         destroy_dev(dev);
  202         knlist_destroy(&tp->tun_rsel.si_note);
  203         mtx_destroy(&tp->tun_mtx);
  204         free(tp, M_TUN);
  205 }
  206 
  207 static int
  208 tunmodevent(module_t mod, int type, void *data)
  209 {
  210         static eventhandler_tag tag;
  211         struct tun_softc *tp;
  212 
  213         switch (type) {
  214         case MOD_LOAD:
  215                 mtx_init(&tunmtx, "tunmtx", NULL, MTX_DEF);
  216                 clone_setup(&tunclones);
  217                 tag = EVENTHANDLER_REGISTER(dev_clone, tunclone, 0, 1000);
  218                 if (tag == NULL)
  219                         return (ENOMEM);
  220                 break;
  221         case MOD_UNLOAD:
  222                 EVENTHANDLER_DEREGISTER(dev_clone, tag);
  223 
  224                 mtx_lock(&tunmtx);
  225                 while ((tp = TAILQ_FIRST(&tunhead)) != NULL) {
  226                         TAILQ_REMOVE(&tunhead, tp, tun_list);
  227                         mtx_unlock(&tunmtx);
  228                         tun_destroy(tp);
  229                         mtx_lock(&tunmtx);
  230                 }
  231                 mtx_unlock(&tunmtx);
  232                 clone_cleanup(&tunclones);
  233                 mtx_destroy(&tunmtx);
  234                 break;
  235         default:
  236                 return EOPNOTSUPP;
  237         }
  238         return 0;
  239 }
  240 
  241 static moduledata_t tun_mod = {
  242         "if_tun",
  243         tunmodevent,
  244         0
  245 };
  246 
  247 DECLARE_MODULE(if_tun, tun_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
  248 
  249 static void
  250 tunstart(struct ifnet *ifp)
  251 {
  252         struct tun_softc *tp = ifp->if_softc;
  253         struct mbuf *m;
  254 
  255         TUNDEBUG(ifp,"%s starting\n", ifp->if_xname);
  256         if (ALTQ_IS_ENABLED(&ifp->if_snd)) {
  257                 IFQ_LOCK(&ifp->if_snd);
  258                 IFQ_POLL_NOLOCK(&ifp->if_snd, m);
  259                 if (m == NULL) {
  260                         IFQ_UNLOCK(&ifp->if_snd);
  261                         return;
  262                 }
  263                 IFQ_UNLOCK(&ifp->if_snd);
  264         }
  265 
  266         mtx_lock(&tp->tun_mtx);
  267         if (tp->tun_flags & TUN_RWAIT) {
  268                 tp->tun_flags &= ~TUN_RWAIT;
  269                 wakeup(tp);
  270         }
  271         if (tp->tun_flags & TUN_ASYNC && tp->tun_sigio) {
  272                 mtx_unlock(&tp->tun_mtx);
  273                 pgsigio(&tp->tun_sigio, SIGIO, 0);
  274         } else
  275                 mtx_unlock(&tp->tun_mtx);
  276         selwakeuppri(&tp->tun_rsel, PZERO + 1);
  277         KNOTE_UNLOCKED(&tp->tun_rsel.si_note, 0);
  278 }
  279 
  280 /* XXX: should return an error code so it can fail. */
  281 static void
  282 tuncreate(struct cdev *dev)
  283 {
  284         struct tun_softc *sc;
  285         struct ifnet *ifp;
  286 
  287         dev->si_flags &= ~SI_CHEAPCLONE;
  288 
  289         MALLOC(sc, struct tun_softc *, sizeof(*sc), M_TUN, M_WAITOK | M_ZERO);
  290         mtx_init(&sc->tun_mtx, "tun_mtx", NULL, MTX_DEF);
  291         sc->tun_flags = TUN_INITED;
  292         sc->tun_dev = dev;
  293         mtx_lock(&tunmtx);
  294         TAILQ_INSERT_TAIL(&tunhead, sc, tun_list);
  295         mtx_unlock(&tunmtx);
  296 
  297         ifp = sc->tun_ifp = if_alloc(IFT_PPP);
  298         if (ifp == NULL)
  299                 panic("%s%d: failed to if_alloc() interface.\n",
  300                     TUNNAME, dev2unit(dev));
  301         if_initname(ifp, TUNNAME, dev2unit(dev));
  302         ifp->if_mtu = TUNMTU;
  303         ifp->if_ioctl = tunifioctl;
  304         ifp->if_output = tunoutput;
  305         ifp->if_start = tunstart;
  306         ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
  307         ifp->if_softc = sc;
  308         IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
  309         ifp->if_snd.ifq_drv_maxlen = 0;
  310         IFQ_SET_READY(&ifp->if_snd);
  311         knlist_init(&sc->tun_rsel.si_note, NULL, NULL, NULL, NULL);
  312 
  313         if_attach(ifp);
  314         bpfattach(ifp, DLT_NULL, sizeof(u_int32_t));
  315         dev->si_drv1 = sc;
  316         TUNDEBUG(ifp, "interface %s is created, minor = %#x\n",
  317             ifp->if_xname, minor(dev));
  318 }
  319 
  320 static int
  321 tunopen(struct cdev *dev, int flag, int mode, struct thread *td)
  322 {
  323         struct ifnet    *ifp;
  324         struct tun_softc *tp;
  325 
  326         /*
  327          * XXXRW: Non-atomic test and set of dev->si_drv1 requires
  328          * synchronization.
  329          */
  330         tp = dev->si_drv1;
  331         if (!tp) {
  332                 tuncreate(dev);
  333                 tp = dev->si_drv1;
  334         }
  335 
  336         /*
  337          * XXXRW: This use of tun_pid is subject to error due to the
  338          * fact that a reference to the tunnel can live beyond the
  339          * death of the process that created it.  Can we replace this
  340          * with a simple busy flag?
  341          */
  342         mtx_lock(&tp->tun_mtx);
  343         if (tp->tun_pid != 0 && tp->tun_pid != td->td_proc->p_pid) {
  344                 mtx_unlock(&tp->tun_mtx);
  345                 return (EBUSY);
  346         }
  347         tp->tun_pid = td->td_proc->p_pid;
  348 
  349         tp->tun_flags |= TUN_OPEN;
  350         mtx_unlock(&tp->tun_mtx);
  351         ifp = TUN2IFP(tp);
  352         TUNDEBUG(ifp, "open\n");
  353 
  354         return (0);
  355 }
  356 
  357 /*
  358  * tunclose - close the device - mark i/f down & delete
  359  * routing info
  360  */
  361 static  int
  362 tunclose(struct cdev *dev, int foo, int bar, struct thread *td)
  363 {
  364         struct tun_softc *tp;
  365         struct ifnet *ifp;
  366         int s;
  367 
  368         tp = dev->si_drv1;
  369         ifp = TUN2IFP(tp);
  370 
  371         mtx_lock(&tp->tun_mtx);
  372         tp->tun_flags &= ~TUN_OPEN;
  373         tp->tun_pid = 0;
  374 
  375         /*
  376          * junk all pending output
  377          */
  378         s = splimp();
  379         IFQ_PURGE(&ifp->if_snd);
  380         splx(s);
  381         mtx_unlock(&tp->tun_mtx);
  382 
  383         if (ifp->if_flags & IFF_UP) {
  384                 s = splimp();
  385                 if_down(ifp);
  386                 splx(s);
  387         }
  388 
  389         if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
  390                 struct ifaddr *ifa;
  391 
  392                 s = splimp();
  393                 /* find internet addresses and delete routes */
  394                 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
  395                         if (ifa->ifa_addr->sa_family == AF_INET)
  396                                 /* Unlocked read. */
  397                                 rtinit(ifa, (int)RTM_DELETE,
  398                                     tp->tun_flags & TUN_DSTADDR ? RTF_HOST : 0);
  399                 ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
  400                 splx(s);
  401         }
  402 
  403         funsetown(&tp->tun_sigio);
  404         selwakeuppri(&tp->tun_rsel, PZERO + 1);
  405         KNOTE_UNLOCKED(&tp->tun_rsel.si_note, 0);
  406         TUNDEBUG (ifp, "closed\n");
  407         return (0);
  408 }
  409 
  410 static int
  411 tuninit(struct ifnet *ifp)
  412 {
  413         struct tun_softc *tp = ifp->if_softc;
  414         struct ifaddr *ifa;
  415         int error = 0;
  416 
  417         TUNDEBUG(ifp, "tuninit\n");
  418 
  419         ifp->if_flags |= IFF_UP;
  420         ifp->if_drv_flags |= IFF_DRV_RUNNING;
  421         getmicrotime(&ifp->if_lastchange);
  422 
  423         for (ifa = TAILQ_FIRST(&ifp->if_addrhead); ifa;
  424              ifa = TAILQ_NEXT(ifa, ifa_link)) {
  425                 if (ifa->ifa_addr == NULL)
  426                         error = EFAULT;
  427                         /* XXX: Should maybe return straight off? */
  428                 else {
  429 #ifdef INET
  430                         if (ifa->ifa_addr->sa_family == AF_INET) {
  431                             struct sockaddr_in *si;
  432 
  433                             si = (struct sockaddr_in *)ifa->ifa_addr;
  434                             mtx_lock(&tp->tun_mtx);
  435                             if (si->sin_addr.s_addr)
  436                                     tp->tun_flags |= TUN_IASET;
  437 
  438                             si = (struct sockaddr_in *)ifa->ifa_dstaddr;
  439                             if (si && si->sin_addr.s_addr)
  440                                     tp->tun_flags |= TUN_DSTADDR;
  441                             mtx_unlock(&tp->tun_mtx);
  442                         }
  443 #endif
  444                 }
  445         }
  446         return (error);
  447 }
  448 
  449 /*
  450  * Process an ioctl request.
  451  */
  452 static int
  453 tunifioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
  454 {
  455         struct ifreq *ifr = (struct ifreq *)data;
  456         struct tun_softc *tp = ifp->if_softc;
  457         struct ifstat *ifs;
  458         int             error = 0, s;
  459 
  460         s = splimp();
  461         switch(cmd) {
  462         case SIOCGIFSTATUS:
  463                 ifs = (struct ifstat *)data;
  464                 mtx_lock(&tp->tun_mtx);
  465                 if (tp->tun_pid)
  466                         sprintf(ifs->ascii + strlen(ifs->ascii),
  467                             "\tOpened by PID %d\n", tp->tun_pid);
  468                 mtx_unlock(&tp->tun_mtx);
  469                 break;
  470         case SIOCSIFADDR:
  471                 error = tuninit(ifp);
  472                 TUNDEBUG(ifp, "address set, error=%d\n", error);
  473                 break;
  474         case SIOCSIFDSTADDR:
  475                 error = tuninit(ifp);
  476                 TUNDEBUG(ifp, "destination address set, error=%d\n", error);
  477                 break;
  478         case SIOCSIFMTU:
  479                 ifp->if_mtu = ifr->ifr_mtu;
  480                 TUNDEBUG(ifp, "mtu set\n");
  481                 break;
  482         case SIOCSIFFLAGS:
  483         case SIOCADDMULTI:
  484         case SIOCDELMULTI:
  485                 break;
  486         default:
  487                 error = EINVAL;
  488         }
  489         splx(s);
  490         return (error);
  491 }
  492 
  493 /*
  494  * tunoutput - queue packets from higher level ready to put out.
  495  */
  496 static int
  497 tunoutput(
  498         struct ifnet *ifp,
  499         struct mbuf *m0,
  500         struct sockaddr *dst,
  501         struct rtentry *rt)
  502 {
  503         struct tun_softc *tp = ifp->if_softc;
  504         u_short cached_tun_flags;
  505         int error;
  506         u_int32_t af;
  507 
  508         TUNDEBUG (ifp, "tunoutput\n");
  509 
  510 #ifdef MAC
  511         error = mac_check_ifnet_transmit(ifp, m0);
  512         if (error) {
  513                 m_freem(m0);
  514                 return (error);
  515         }
  516 #endif
  517 
  518         /* Could be unlocked read? */
  519         mtx_lock(&tp->tun_mtx);
  520         cached_tun_flags = tp->tun_flags;
  521         mtx_unlock(&tp->tun_mtx);
  522         if ((cached_tun_flags & TUN_READY) != TUN_READY) {
  523                 TUNDEBUG (ifp, "not ready 0%o\n", tp->tun_flags);
  524                 m_freem (m0);
  525                 return (EHOSTDOWN);
  526         }
  527 
  528         if ((ifp->if_flags & IFF_UP) != IFF_UP) {
  529                 m_freem (m0);
  530                 return (EHOSTDOWN);
  531         }
  532 
  533         /* BPF writes need to be handled specially. */
  534         if (dst->sa_family == AF_UNSPEC) {
  535                 bcopy(dst->sa_data, &af, sizeof(af));
  536                 dst->sa_family = af; 
  537         }
  538 
  539         if (ifp->if_bpf) {
  540                 af = dst->sa_family;
  541                 bpf_mtap2(ifp->if_bpf, &af, sizeof(af), m0);
  542         }
  543 
  544         /* prepend sockaddr? this may abort if the mbuf allocation fails */
  545         if (cached_tun_flags & TUN_LMODE) {
  546                 /* allocate space for sockaddr */
  547                 M_PREPEND(m0, dst->sa_len, M_DONTWAIT);
  548 
  549                 /* if allocation failed drop packet */
  550                 if (m0 == NULL) {
  551                         ifp->if_iqdrops++;
  552                         ifp->if_oerrors++;
  553                         return (ENOBUFS);
  554                 } else {
  555                         bcopy(dst, m0->m_data, dst->sa_len);
  556                 }
  557         }
  558 
  559         if (cached_tun_flags & TUN_IFHEAD) {
  560                 /* Prepend the address family */
  561                 M_PREPEND(m0, 4, M_DONTWAIT);
  562 
  563                 /* if allocation failed drop packet */
  564                 if (m0 == NULL) {
  565                         ifp->if_iqdrops++;
  566                         ifp->if_oerrors++;
  567                         return (ENOBUFS);
  568                 } else
  569                         *(u_int32_t *)m0->m_data = htonl(dst->sa_family);
  570         } else {
  571 #ifdef INET
  572                 if (dst->sa_family != AF_INET)
  573 #endif
  574                 {
  575                         m_freem(m0);
  576                         return (EAFNOSUPPORT);
  577                 }
  578         }
  579 
  580         IFQ_HANDOFF(ifp, m0, error);
  581         if (error) {
  582                 ifp->if_collisions++;
  583                 return (ENOBUFS);
  584         }
  585         ifp->if_opackets++;
  586         return (0);
  587 }
  588 
  589 /*
  590  * the cdevsw interface is now pretty minimal.
  591  */
  592 static  int
  593 tunioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
  594 {
  595         int             s;
  596         int             error;
  597         struct tun_softc *tp = dev->si_drv1;
  598         struct tuninfo *tunp;
  599 
  600         switch (cmd) {
  601         case TUNSIFINFO:
  602                 tunp = (struct tuninfo *)data;
  603                 if (tunp->mtu < IF_MINMTU)
  604                         return (EINVAL);
  605                 if (TUN2IFP(tp)->if_mtu != tunp->mtu
  606                 && (error = suser(td)) != 0)
  607                         return (error);
  608                 TUN2IFP(tp)->if_mtu = tunp->mtu;
  609                 TUN2IFP(tp)->if_type = tunp->type;
  610                 TUN2IFP(tp)->if_baudrate = tunp->baudrate;
  611                 break;
  612         case TUNGIFINFO:
  613                 tunp = (struct tuninfo *)data;
  614                 tunp->mtu = TUN2IFP(tp)->if_mtu;
  615                 tunp->type = TUN2IFP(tp)->if_type;
  616                 tunp->baudrate = TUN2IFP(tp)->if_baudrate;
  617                 break;
  618         case TUNSDEBUG:
  619                 tundebug = *(int *)data;
  620                 break;
  621         case TUNGDEBUG:
  622                 *(int *)data = tundebug;
  623                 break;
  624         case TUNSLMODE:
  625                 mtx_lock(&tp->tun_mtx);
  626                 if (*(int *)data) {
  627                         tp->tun_flags |= TUN_LMODE;
  628                         tp->tun_flags &= ~TUN_IFHEAD;
  629                 } else
  630                         tp->tun_flags &= ~TUN_LMODE;
  631                 mtx_unlock(&tp->tun_mtx);
  632                 break;
  633         case TUNSIFHEAD:
  634                 mtx_lock(&tp->tun_mtx);
  635                 if (*(int *)data) {
  636                         tp->tun_flags |= TUN_IFHEAD;
  637                         tp->tun_flags &= ~TUN_LMODE;
  638                 } else
  639                         tp->tun_flags &= ~TUN_IFHEAD;
  640                 mtx_unlock(&tp->tun_mtx);
  641                 break;
  642         case TUNGIFHEAD:
  643                 /* Could be unlocked read? */
  644                 mtx_lock(&tp->tun_mtx);
  645                 *(int *)data = (tp->tun_flags & TUN_IFHEAD) ? 1 : 0;
  646                 mtx_unlock(&tp->tun_mtx);
  647                 break;
  648         case TUNSIFMODE:
  649                 /* deny this if UP */
  650                 if (TUN2IFP(tp)->if_flags & IFF_UP)
  651                         return(EBUSY);
  652 
  653                 switch (*(int *)data & ~IFF_MULTICAST) {
  654                 case IFF_POINTOPOINT:
  655                 case IFF_BROADCAST:
  656                         TUN2IFP(tp)->if_flags &=
  657                             ~(IFF_BROADCAST|IFF_POINTOPOINT|IFF_MULTICAST);
  658                         TUN2IFP(tp)->if_flags |= *(int *)data;
  659                         break;
  660                 default:
  661                         return(EINVAL);
  662                 }
  663                 break;
  664         case TUNSIFPID:
  665                 mtx_lock(&tp->tun_mtx);
  666                 tp->tun_pid = curthread->td_proc->p_pid;
  667                 mtx_unlock(&tp->tun_mtx);
  668                 break;
  669         case FIONBIO:
  670                 break;
  671         case FIOASYNC:
  672                 mtx_lock(&tp->tun_mtx);
  673                 if (*(int *)data)
  674                         tp->tun_flags |= TUN_ASYNC;
  675                 else
  676                         tp->tun_flags &= ~TUN_ASYNC;
  677                 mtx_unlock(&tp->tun_mtx);
  678                 break;
  679         case FIONREAD:
  680                 s = splimp();
  681                 if (!IFQ_IS_EMPTY(&TUN2IFP(tp)->if_snd)) {
  682                         struct mbuf *mb;
  683                         IFQ_LOCK(&TUN2IFP(tp)->if_snd);
  684                         IFQ_POLL_NOLOCK(&TUN2IFP(tp)->if_snd, mb);
  685                         for( *(int *)data = 0; mb != 0; mb = mb->m_next)
  686                                 *(int *)data += mb->m_len;
  687                         IFQ_UNLOCK(&TUN2IFP(tp)->if_snd);
  688                 } else
  689                         *(int *)data = 0;
  690                 splx(s);
  691                 break;
  692         case FIOSETOWN:
  693                 return (fsetown(*(int *)data, &tp->tun_sigio));
  694 
  695         case FIOGETOWN:
  696                 *(int *)data = fgetown(&tp->tun_sigio);
  697                 return (0);
  698 
  699         /* This is deprecated, FIOSETOWN should be used instead. */
  700         case TIOCSPGRP:
  701                 return (fsetown(-(*(int *)data), &tp->tun_sigio));
  702 
  703         /* This is deprecated, FIOGETOWN should be used instead. */
  704         case TIOCGPGRP:
  705                 *(int *)data = -fgetown(&tp->tun_sigio);
  706                 return (0);
  707 
  708         default:
  709                 return (ENOTTY);
  710         }
  711         return (0);
  712 }
  713 
  714 /*
  715  * The cdevsw read interface - reads a packet at a time, or at
  716  * least as much of a packet as can be read.
  717  */
  718 static  int
  719 tunread(struct cdev *dev, struct uio *uio, int flag)
  720 {
  721         struct tun_softc *tp = dev->si_drv1;
  722         struct ifnet    *ifp = TUN2IFP(tp);
  723         struct mbuf     *m;
  724         int             error=0, len, s;
  725 
  726         TUNDEBUG (ifp, "read\n");
  727         mtx_lock(&tp->tun_mtx);
  728         if ((tp->tun_flags & TUN_READY) != TUN_READY) {
  729                 mtx_unlock(&tp->tun_mtx);
  730                 TUNDEBUG (ifp, "not ready 0%o\n", tp->tun_flags);
  731                 return (EHOSTDOWN);
  732         }
  733 
  734         tp->tun_flags &= ~TUN_RWAIT;
  735         mtx_unlock(&tp->tun_mtx);
  736 
  737         s = splimp();
  738         do {
  739                 IFQ_DEQUEUE(&ifp->if_snd, m);
  740                 if (m == NULL) {
  741                         if (flag & O_NONBLOCK) {
  742                                 splx(s);
  743                                 return (EWOULDBLOCK);
  744                         }
  745                         mtx_lock(&tp->tun_mtx);
  746                         tp->tun_flags |= TUN_RWAIT;
  747                         mtx_unlock(&tp->tun_mtx);
  748                         if ((error = tsleep(tp, PCATCH | (PZERO + 1),
  749                                         "tunread", 0)) != 0) {
  750                                 splx(s);
  751                                 return (error);
  752                         }
  753                 }
  754         } while (m == NULL);
  755         splx(s);
  756 
  757         while (m && uio->uio_resid > 0 && error == 0) {
  758                 len = min(uio->uio_resid, m->m_len);
  759                 if (len != 0)
  760                         error = uiomove(mtod(m, void *), len, uio);
  761                 m = m_free(m);
  762         }
  763 
  764         if (m) {
  765                 TUNDEBUG(ifp, "Dropping mbuf\n");
  766                 m_freem(m);
  767         }
  768         return (error);
  769 }
  770 
  771 /*
  772  * the cdevsw write interface - an atomic write is a packet - or else!
  773  */
  774 static  int
  775 tunwrite(struct cdev *dev, struct uio *uio, int flag)
  776 {
  777         struct tun_softc *tp = dev->si_drv1;
  778         struct ifnet    *ifp = TUN2IFP(tp);
  779         struct mbuf     *m;
  780         int             error = 0;
  781         uint32_t        family;
  782         int             isr;
  783 
  784         TUNDEBUG(ifp, "tunwrite\n");
  785 
  786         if ((ifp->if_flags & IFF_UP) != IFF_UP)
  787                 /* ignore silently */
  788                 return (0);
  789 
  790         if (uio->uio_resid == 0)
  791                 return (0);
  792 
  793         if (uio->uio_resid < 0 || uio->uio_resid > TUNMRU) {
  794                 TUNDEBUG(ifp, "len=%d!\n", uio->uio_resid);
  795                 return (EIO);
  796         }
  797 
  798         if ((m = m_uiotombuf(uio, M_DONTWAIT, 0, 0)) == NULL) {
  799                 ifp->if_ierrors++;
  800                 return (error);
  801         }
  802 
  803         m->m_pkthdr.rcvif = ifp;
  804 #ifdef MAC
  805         mac_create_mbuf_from_ifnet(ifp, m);
  806 #endif
  807 
  808         /* Could be unlocked read? */
  809         mtx_lock(&tp->tun_mtx);
  810         if (tp->tun_flags & TUN_IFHEAD) {
  811                 mtx_unlock(&tp->tun_mtx);
  812                 if (m->m_len < sizeof(family) &&
  813                     (m = m_pullup(m, sizeof(family))) == NULL)
  814                         return (ENOBUFS);
  815                 family = ntohl(*mtod(m, u_int32_t *));
  816                 m_adj(m, sizeof(family));
  817         } else {
  818                 mtx_unlock(&tp->tun_mtx);
  819                 family = AF_INET;
  820         }
  821 
  822         BPF_MTAP2(ifp, &family, sizeof(family), m);
  823 
  824         switch (family) {
  825 #ifdef INET
  826         case AF_INET:
  827                 isr = NETISR_IP;
  828                 break;
  829 #endif
  830 #ifdef INET6
  831         case AF_INET6:
  832                 isr = NETISR_IPV6;
  833                 break;
  834 #endif
  835 #ifdef IPX
  836         case AF_IPX:
  837                 isr = NETISR_IPX;
  838                 break;
  839 #endif
  840 #ifdef NETATALK
  841         case AF_APPLETALK:
  842                 isr = NETISR_ATALK2;
  843                 break;
  844 #endif
  845         default:
  846                 m_freem(m);
  847                 return (EAFNOSUPPORT);
  848         }
  849         /* First chunk of an mbuf contains good junk */
  850         if (harvest.point_to_point)
  851                 random_harvest(m, 16, 3, 0, RANDOM_NET);
  852         ifp->if_ibytes += m->m_pkthdr.len;
  853         ifp->if_ipackets++;
  854         netisr_dispatch(isr, m);
  855         return (0);
  856 }
  857 
  858 /*
  859  * tunpoll - the poll interface, this is only useful on reads
  860  * really. The write detect always returns true, write never blocks
  861  * anyway, it either accepts the packet or drops it.
  862  */
  863 static  int
  864 tunpoll(struct cdev *dev, int events, struct thread *td)
  865 {
  866         int             s;
  867         struct tun_softc *tp = dev->si_drv1;
  868         struct ifnet    *ifp = TUN2IFP(tp);
  869         int             revents = 0;
  870         struct mbuf     *m;
  871 
  872         s = splimp();
  873         TUNDEBUG(ifp, "tunpoll\n");
  874 
  875         if (events & (POLLIN | POLLRDNORM)) {
  876                 IFQ_LOCK(&ifp->if_snd);
  877                 IFQ_POLL_NOLOCK(&ifp->if_snd, m);
  878                 if (m != NULL) {
  879                         TUNDEBUG(ifp, "tunpoll q=%d\n", ifp->if_snd.ifq_len);
  880                         revents |= events & (POLLIN | POLLRDNORM);
  881                 } else {
  882                         TUNDEBUG(ifp, "tunpoll waiting\n");
  883                         selrecord(td, &tp->tun_rsel);
  884                 }
  885                 IFQ_UNLOCK(&ifp->if_snd);
  886         }
  887         if (events & (POLLOUT | POLLWRNORM))
  888                 revents |= events & (POLLOUT | POLLWRNORM);
  889 
  890         splx(s);
  891         return (revents);
  892 }
  893 
  894 /*
  895  * tunkqfilter - support for the kevent() system call.
  896  */
  897 static int
  898 tunkqfilter(struct cdev *dev, struct knote *kn)
  899 {
  900         int                     s;
  901         struct tun_softc        *tp = dev->si_drv1;
  902         struct ifnet    *ifp = TUN2IFP(tp);
  903 
  904         s = splimp();
  905         switch(kn->kn_filter) {
  906         case EVFILT_READ:
  907                 TUNDEBUG(ifp, "%s kqfilter: EVFILT_READ, minor = %#x\n",
  908                     ifp->if_xname, minor(dev));
  909                 kn->kn_fop = &tun_read_filterops;
  910                 break;
  911 
  912         case EVFILT_WRITE:
  913                 TUNDEBUG(ifp, "%s kqfilter: EVFILT_WRITE, minor = %#x\n",
  914                     ifp->if_xname, minor(dev));
  915                 kn->kn_fop = &tun_write_filterops;
  916                 break;
  917         
  918         default:
  919                 TUNDEBUG(ifp, "%s kqfilter: invalid filter, minor = %#x\n",
  920                     ifp->if_xname, minor(dev));
  921                 splx(s);
  922                 return(EINVAL);
  923         }
  924         splx(s);
  925 
  926         kn->kn_hook = (caddr_t) dev;
  927         knlist_add(&tp->tun_rsel.si_note, kn, 0);
  928 
  929         return (0);
  930 }
  931 
  932 /*
  933  * Return true of there is data in the interface queue.
  934  */
  935 static int
  936 tunkqread(struct knote *kn, long hint)
  937 {
  938         int                     ret, s;
  939         struct cdev             *dev = (struct cdev *)(kn->kn_hook);
  940         struct tun_softc        *tp = dev->si_drv1;
  941         struct ifnet    *ifp = TUN2IFP(tp);
  942 
  943         s = splimp();
  944         if ((kn->kn_data = ifp->if_snd.ifq_len) > 0) {
  945                 TUNDEBUG(ifp,
  946                     "%s have data in the queue.  Len = %d, minor = %#x\n",
  947                     ifp->if_xname, ifp->if_snd.ifq_len, minor(dev));
  948                 ret = 1;
  949         } else {
  950                 TUNDEBUG(ifp,
  951                     "%s waiting for data, minor = %#x\n", ifp->if_xname,
  952                     minor(dev));
  953                 ret = 0;
  954         }
  955         splx(s);
  956 
  957         return (ret);
  958 }
  959 
  960 /*
  961  * Always can write, always return MTU in kn->data.
  962  */
  963 static int
  964 tunkqwrite(struct knote *kn, long hint)
  965 {
  966         int                     s;
  967         struct tun_softc        *tp = ((struct cdev *)kn->kn_hook)->si_drv1;
  968         struct ifnet    *ifp = TUN2IFP(tp);
  969 
  970         s = splimp();
  971         kn->kn_data = ifp->if_mtu;
  972         splx(s);
  973 
  974         return (1);
  975 }
  976 
  977 static void
  978 tunkqdetach(struct knote *kn)
  979 {
  980         struct tun_softc        *tp = ((struct cdev *)kn->kn_hook)->si_drv1;
  981 
  982         knlist_remove(&tp->tun_rsel.si_note, kn, 0);
  983 }

Cache object: a9aaeb5fa88ea3f2e0e49cde3311a187


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.