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/5.1/sys/net/if_tun.c 111999 2003-03-08 17:32:21Z jlemon $
   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/filio.h>
   33 #include <sys/sockio.h>
   34 #include <sys/ttycom.h>
   35 #include <sys/poll.h>
   36 #include <sys/signalvar.h>
   37 #include <sys/filedesc.h>
   38 #include <sys/kernel.h>
   39 #include <sys/sysctl.h>
   40 #include <sys/conf.h>
   41 #include <sys/uio.h>
   42 #include <sys/vnode.h>
   43 #include <sys/malloc.h>
   44 #include <machine/bus.h>        /* XXX Shouldn't really be required ! */
   45 #include <sys/random.h>
   46 #include <sys/rman.h>
   47 
   48 #include <net/if.h>
   49 #include <net/if_types.h>
   50 #include <net/netisr.h>
   51 #include <net/route.h>
   52 #ifdef INET
   53 #include <netinet/in.h>
   54 #endif
   55 #include <net/bpf.h>
   56 #include <net/if_tunvar.h>
   57 #include <net/if_tun.h>
   58 
   59 #define TUNDEBUG        if (tundebug) printf
   60 #define TUNNAME         "tun"
   61 #define TUN_MAXUNIT     0x7fff  /* ifp->if_unit is only 15 bits */
   62 
   63 static MALLOC_DEFINE(M_TUN, TUNNAME, "Tunnel Interface");
   64 static int tundebug = 0;
   65 static struct tun_softc *tunhead = NULL;
   66 static struct rman tununits;
   67 static udev_t tunbasedev = NOUDEV;
   68 SYSCTL_INT(_debug, OID_AUTO, if_tun_debug, CTLFLAG_RW, &tundebug, 0, "");
   69 
   70 static void     tunclone(void *arg, char *name, int namelen, dev_t *dev);
   71 static void     tuncreate(dev_t dev);
   72 static int      tunifioctl(struct ifnet *, u_long, caddr_t);
   73 static int      tuninit(struct ifnet *);
   74 static int      tunmodevent(module_t, int, void *);
   75 static int      tunoutput(struct ifnet *, struct mbuf *, struct sockaddr *,
   76                     struct rtentry *rt);
   77 static void     tunstart(struct ifnet *);
   78 
   79 static d_open_t         tunopen;
   80 static d_close_t        tunclose;
   81 static d_read_t         tunread;
   82 static d_write_t        tunwrite;
   83 static d_ioctl_t        tunioctl;
   84 static d_poll_t         tunpoll;
   85 
   86 #define CDEV_MAJOR 52
   87 static struct cdevsw tun_cdevsw = {
   88         .d_open =       tunopen,
   89         .d_close =      tunclose,
   90         .d_read =       tunread,
   91         .d_write =      tunwrite,
   92         .d_ioctl =      tunioctl,
   93         .d_poll =       tunpoll,
   94         .d_name =       TUNNAME,
   95         .d_maj =        CDEV_MAJOR,
   96 };
   97 
   98 static void
   99 tunclone(void *arg, char *name, int namelen, dev_t *dev)
  100 {
  101         struct resource *r;
  102         int err;
  103         int u;
  104 
  105         if (*dev != NODEV)
  106                 return;
  107 
  108         if (strcmp(name, TUNNAME) == 0) {
  109                 r = rman_reserve_resource(&tununits, 0, TUN_MAXUNIT, 1,
  110                     RF_ALLOCATED | RF_ACTIVE, NULL);
  111                 u = rman_get_start(r);
  112                 err = rman_release_resource(r);
  113                 KASSERT(err == 0, ("Unexpected failure releasing resource"));
  114                 *dev = makedev(CDEV_MAJOR, unit2minor(u));
  115                 if ((*dev)->si_flags & SI_NAMED)
  116                         return; /* Already make_dev()d */
  117         } else if (dev_stdclone(name, NULL, TUNNAME, &u) != 1)
  118                 return; /* Don't recognise the name */
  119 
  120         *dev = make_dev(&tun_cdevsw, unit2minor(u),
  121             UID_ROOT, GID_WHEEL, 0600, "tun%d", u);
  122 
  123         /*
  124          * All devices depend on tunbasedev so that we can simply
  125          * destroy_dev() this device at module unload time to get
  126          * rid of all our make_dev()d resources.
  127          */
  128         if (tunbasedev == NOUDEV)
  129                 tunbasedev = (*dev)->si_udev;
  130         else {
  131                 (*dev)->si_flags |= SI_CHEAPCLONE;
  132                 dev_depends(udev2dev(tunbasedev, 0), *dev);
  133         }
  134 }
  135 
  136 static int
  137 tunmodevent(module_t mod, int type, void *data)
  138 {
  139         static eventhandler_tag tag;
  140         struct tun_softc *tp;
  141         dev_t dev;
  142         int err;
  143 
  144         switch (type) {
  145         case MOD_LOAD:
  146                 tag = EVENTHANDLER_REGISTER(dev_clone, tunclone, 0, 1000);
  147                 if (tag == NULL)
  148                         return (ENOMEM);
  149                 tununits.rm_type = RMAN_ARRAY;
  150                 tununits.rm_descr = "open if_tun units";
  151                 err = rman_init(&tununits);
  152                 if (err != 0) {
  153                         EVENTHANDLER_DEREGISTER(dev_clone, tag);
  154                         return (err);
  155                 }
  156                 err = rman_manage_region(&tununits, 0, TUN_MAXUNIT);
  157                 if (err != 0) {
  158                         printf("%s: tununits: rman_manage_region: Failed %d\n",
  159                             TUNNAME, err);
  160                         rman_fini(&tununits);
  161                         EVENTHANDLER_DEREGISTER(dev_clone, tag);
  162                         return (err);
  163                 }
  164                 break;
  165         case MOD_UNLOAD:
  166                 err = rman_fini(&tununits);
  167                 if (err != 0)
  168                         return (err);
  169                 EVENTHANDLER_DEREGISTER(dev_clone, tag);
  170 
  171                 while (tunhead != NULL) {
  172                         KASSERT((tunhead->tun_flags & TUN_OPEN) == 0,
  173                             ("tununits is out of sync - unit %d",
  174                             tunhead->tun_if.if_unit));
  175                         tp = tunhead;
  176                         dev = makedev(tun_cdevsw.d_maj,
  177                             unit2minor(tp->tun_if.if_unit));
  178                         KASSERT(dev->si_drv1 == tp, ("Bad makedev result"));
  179                         tunhead = tp->next;
  180                         bpfdetach(&tp->tun_if);
  181                         if_detach(&tp->tun_if);
  182                         KASSERT(dev->si_flags & SI_NAMED, ("Missing make_dev"));
  183                         free(tp, M_TUN);
  184                 }
  185 
  186                 /*
  187                  * Destroying tunbasedev results in all of our make_dev()s
  188                  * conveniently going away.
  189                  */
  190                 if (tunbasedev != NOUDEV)
  191                         destroy_dev(udev2dev(tunbasedev, 0));
  192 
  193                 break;
  194         }
  195         return 0;
  196 }
  197 
  198 static moduledata_t tun_mod = {
  199         "if_tun",
  200         tunmodevent,
  201         0
  202 };
  203 
  204 DECLARE_MODULE(if_tun, tun_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
  205 
  206 static void
  207 tunstart(struct ifnet *ifp)
  208 {
  209         struct tun_softc *tp = ifp->if_softc;
  210 
  211         if (tp->tun_flags & TUN_RWAIT) {
  212                 tp->tun_flags &= ~TUN_RWAIT;
  213                 wakeup(tp);
  214         }
  215         if (tp->tun_flags & TUN_ASYNC && tp->tun_sigio)
  216                 pgsigio(&tp->tun_sigio, SIGIO, 0);
  217         selwakeup(&tp->tun_rsel);
  218 }
  219 
  220 static void
  221 tuncreate(dev_t dev)
  222 {
  223         struct tun_softc *sc;
  224         struct ifnet *ifp;
  225 
  226         if (!(dev->si_flags & SI_NAMED))
  227                 dev = make_dev(&tun_cdevsw, minor(dev),
  228                     UID_UUCP, GID_DIALER, 0600, "tun%d", dev2unit(dev));
  229 
  230         MALLOC(sc, struct tun_softc *, sizeof(*sc), M_TUN, M_WAITOK | M_ZERO);
  231         sc->tun_flags = TUN_INITED;
  232         sc->next = tunhead;
  233         tunhead = sc;
  234 
  235         ifp = &sc->tun_if;
  236         ifp->if_unit = dev2unit(dev);
  237         ifp->if_name = TUNNAME;
  238         ifp->if_mtu = TUNMTU;
  239         ifp->if_ioctl = tunifioctl;
  240         ifp->if_output = tunoutput;
  241         ifp->if_start = tunstart;
  242         ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
  243         ifp->if_type = IFT_PPP;
  244         ifp->if_snd.ifq_maxlen = ifqmaxlen;
  245         ifp->if_softc = sc;
  246         if_attach(ifp);
  247         bpfattach(ifp, DLT_NULL, sizeof(u_int));
  248         dev->si_drv1 = sc;
  249 }
  250 
  251 static int
  252 tunopen(dev_t dev, int flag, int mode, struct thread *td)
  253 {
  254         struct resource *r;
  255         struct ifnet    *ifp;
  256         struct tun_softc *tp;
  257         int unit;
  258 
  259         unit = dev2unit(dev);
  260         if (unit > TUN_MAXUNIT)
  261                 return (ENXIO);
  262 
  263         r = rman_reserve_resource(&tununits, unit, unit, 1,
  264             RF_ALLOCATED | RF_ACTIVE, NULL);
  265         if (r == NULL)
  266                 return (EBUSY);
  267 
  268         dev->si_flags &= ~SI_CHEAPCLONE;
  269 
  270         tp = dev->si_drv1;
  271         if (!tp) {
  272                 tuncreate(dev);
  273                 tp = dev->si_drv1;
  274         }
  275         KASSERT(!(tp->tun_flags & TUN_OPEN), ("Resource & flags out-of-sync"));
  276         tp->r_unit = r;
  277         tp->tun_pid = td->td_proc->p_pid;
  278         ifp = &tp->tun_if;
  279         tp->tun_flags |= TUN_OPEN;
  280         TUNDEBUG("%s%d: open\n", ifp->if_name, ifp->if_unit);
  281 
  282         return (0);
  283 }
  284 
  285 /*
  286  * tunclose - close the device - mark i/f down & delete
  287  * routing info
  288  */
  289 static  int
  290 tunclose(dev_t dev, int foo, int bar, struct thread *td)
  291 {
  292         struct tun_softc *tp;
  293         struct ifnet *ifp;
  294         int s;
  295         int err;
  296 
  297         tp = dev->si_drv1;
  298         ifp = &tp->tun_if;
  299 
  300         KASSERT(tp->r_unit, ("Unit %d not marked open", ifp->if_unit));
  301         tp->tun_flags &= ~TUN_OPEN;
  302         tp->tun_pid = 0;
  303 
  304         /*
  305          * junk all pending output
  306          */
  307         IF_DRAIN(&ifp->if_snd);
  308 
  309         if (ifp->if_flags & IFF_UP) {
  310                 s = splimp();
  311                 if_down(ifp);
  312                 splx(s);
  313         }
  314 
  315         if (ifp->if_flags & IFF_RUNNING) {
  316                 struct ifaddr *ifa;
  317 
  318                 s = splimp();
  319                 /* find internet addresses and delete routes */
  320                 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
  321                         if (ifa->ifa_addr->sa_family == AF_INET)
  322                                 rtinit(ifa, (int)RTM_DELETE,
  323                                     tp->tun_flags & TUN_DSTADDR ? RTF_HOST : 0);
  324                 ifp->if_flags &= ~IFF_RUNNING;
  325                 splx(s);
  326         }
  327 
  328         funsetown(&tp->tun_sigio);
  329         selwakeup(&tp->tun_rsel);
  330 
  331         TUNDEBUG ("%s%d: closed\n", ifp->if_name, ifp->if_unit);
  332         err = rman_release_resource(tp->r_unit);
  333         KASSERT(err == 0, ("Unit %d failed to release", ifp->if_unit));
  334 
  335         return (0);
  336 }
  337 
  338 static int
  339 tuninit(struct ifnet *ifp)
  340 {
  341         struct tun_softc *tp = ifp->if_softc;
  342         struct ifaddr *ifa;
  343         int error = 0;
  344 
  345         TUNDEBUG("%s%d: tuninit\n", ifp->if_name, ifp->if_unit);
  346 
  347         ifp->if_flags |= IFF_UP | IFF_RUNNING;
  348         getmicrotime(&ifp->if_lastchange);
  349 
  350         for (ifa = TAILQ_FIRST(&ifp->if_addrhead); ifa;
  351              ifa = TAILQ_NEXT(ifa, ifa_link)) {
  352                 if (ifa->ifa_addr == NULL)
  353                         error = EFAULT;
  354                         /* XXX: Should maybe return straight off? */
  355                 else {
  356 #ifdef INET
  357                         if (ifa->ifa_addr->sa_family == AF_INET) {
  358                             struct sockaddr_in *si;
  359 
  360                             si = (struct sockaddr_in *)ifa->ifa_addr;
  361                             if (si->sin_addr.s_addr)
  362                                     tp->tun_flags |= TUN_IASET;
  363 
  364                             si = (struct sockaddr_in *)ifa->ifa_dstaddr;
  365                             if (si && si->sin_addr.s_addr)
  366                                     tp->tun_flags |= TUN_DSTADDR;
  367                         }
  368 #endif
  369                 }
  370         }
  371         return (error);
  372 }
  373 
  374 /*
  375  * Process an ioctl request.
  376  */
  377 static int
  378 tunifioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
  379 {
  380         struct ifreq *ifr = (struct ifreq *)data;
  381         struct tun_softc *tp = ifp->if_softc;
  382         struct ifstat *ifs;
  383         int             error = 0, s;
  384 
  385         s = splimp();
  386         switch(cmd) {
  387         case SIOCGIFSTATUS:
  388                 ifs = (struct ifstat *)data;
  389                 if (tp->tun_pid)
  390                         sprintf(ifs->ascii + strlen(ifs->ascii),
  391                             "\tOpened by PID %d\n", tp->tun_pid);
  392                 break;
  393         case SIOCSIFADDR:
  394                 error = tuninit(ifp);
  395                 TUNDEBUG("%s%d: address set, error=%d\n",
  396                          ifp->if_name, ifp->if_unit, error);
  397                 break;
  398         case SIOCSIFDSTADDR:
  399                 error = tuninit(ifp);
  400                 TUNDEBUG("%s%d: destination address set, error=%d\n",
  401                          ifp->if_name, ifp->if_unit, error);
  402                 break;
  403         case SIOCSIFMTU:
  404                 ifp->if_mtu = ifr->ifr_mtu;
  405                 TUNDEBUG("%s%d: mtu set\n", ifp->if_name, ifp->if_unit);
  406                 break;
  407         case SIOCSIFFLAGS:
  408         case SIOCADDMULTI:
  409         case SIOCDELMULTI:
  410                 break;
  411         default:
  412                 error = EINVAL;
  413         }
  414         splx(s);
  415         return (error);
  416 }
  417 
  418 /*
  419  * tunoutput - queue packets from higher level ready to put out.
  420  */
  421 static int
  422 tunoutput(
  423         struct ifnet *ifp,
  424         struct mbuf *m0,
  425         struct sockaddr *dst,
  426         struct rtentry *rt)
  427 {
  428         struct tun_softc *tp = ifp->if_softc;
  429 #ifdef MAC
  430         int error;
  431 #endif
  432 
  433         TUNDEBUG ("%s%d: tunoutput\n", ifp->if_name, ifp->if_unit);
  434 
  435 #ifdef MAC
  436         error = mac_check_ifnet_transmit(ifp, m0);
  437         if (error) {
  438                 m_freem(m0);
  439                 return (error);
  440         }
  441 #endif
  442 
  443         if ((tp->tun_flags & TUN_READY) != TUN_READY) {
  444                 TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name,
  445                           ifp->if_unit, tp->tun_flags);
  446                 m_freem (m0);
  447                 return (EHOSTDOWN);
  448         }
  449 
  450         if ((ifp->if_flags & IFF_UP) != IFF_UP) {
  451                 m_freem (m0);
  452                 return (EHOSTDOWN);
  453         }
  454 
  455         /* BPF write needs to be handled specially */
  456         if (dst->sa_family == AF_UNSPEC) {
  457                 dst->sa_family = *(mtod(m0, int *));
  458                 m0->m_len -= sizeof(int);
  459                 m0->m_pkthdr.len -= sizeof(int);
  460                 m0->m_data += sizeof(int);
  461         }
  462 
  463         if (ifp->if_bpf) {
  464                 /*
  465                  * We need to prepend the address family as
  466                  * a four byte field.  Cons up a dummy header
  467                  * to pacify bpf.  This is safe because bpf
  468                  * will only read from the mbuf (i.e., it won't
  469                  * try to free it or keep a pointer to it).
  470                  */
  471                 struct mbuf m;
  472                 uint32_t af = dst->sa_family;
  473 
  474                 m.m_next = m0;
  475                 m.m_len = 4;
  476                 m.m_data = (char *)&af;
  477 
  478                 BPF_MTAP(ifp, &m);
  479         }
  480 
  481         /* prepend sockaddr? this may abort if the mbuf allocation fails */
  482         if (tp->tun_flags & TUN_LMODE) {
  483                 /* allocate space for sockaddr */
  484                 M_PREPEND(m0, dst->sa_len, M_DONTWAIT);
  485 
  486                 /* if allocation failed drop packet */
  487                 if (m0 == NULL) {
  488                         ifp->if_iqdrops++;
  489                         ifp->if_oerrors++;
  490                         return (ENOBUFS);
  491                 } else {
  492                         bcopy(dst, m0->m_data, dst->sa_len);
  493                 }
  494         }
  495 
  496         if (tp->tun_flags & TUN_IFHEAD) {
  497                 /* Prepend the address family */
  498                 M_PREPEND(m0, 4, M_DONTWAIT);
  499 
  500                 /* if allocation failed drop packet */
  501                 if (m0 == NULL) {
  502                         ifp->if_iqdrops++;
  503                         ifp->if_oerrors++;
  504                         return (ENOBUFS);
  505                 } else
  506                         *(u_int32_t *)m0->m_data = htonl(dst->sa_family);
  507         } else {
  508 #ifdef INET
  509                 if (dst->sa_family != AF_INET)
  510 #endif
  511                 {
  512                         m_freem(m0);
  513                         return (EAFNOSUPPORT);
  514                 }
  515         }
  516 
  517         if (! IF_HANDOFF(&ifp->if_snd, m0, ifp)) {
  518                 ifp->if_collisions++;
  519                 return (ENOBUFS);
  520         }
  521         ifp->if_opackets++;
  522         return (0);
  523 }
  524 
  525 /*
  526  * the cdevsw interface is now pretty minimal.
  527  */
  528 static  int
  529 tunioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
  530 {
  531         int             s;
  532         int             error;
  533         struct tun_softc *tp = dev->si_drv1;
  534         struct tuninfo *tunp;
  535 
  536         switch (cmd) {
  537         case TUNSIFINFO:
  538                 tunp = (struct tuninfo *)data;
  539                 if (tunp->mtu < IF_MINMTU)
  540                         return (EINVAL);
  541                 if (tp->tun_if.if_mtu != tunp->mtu
  542                 && (error = suser(td)) != 0)
  543                         return (error);
  544                 tp->tun_if.if_mtu = tunp->mtu;
  545                 tp->tun_if.if_type = tunp->type;
  546                 tp->tun_if.if_baudrate = tunp->baudrate;
  547                 break;
  548         case TUNGIFINFO:
  549                 tunp = (struct tuninfo *)data;
  550                 tunp->mtu = tp->tun_if.if_mtu;
  551                 tunp->type = tp->tun_if.if_type;
  552                 tunp->baudrate = tp->tun_if.if_baudrate;
  553                 break;
  554         case TUNSDEBUG:
  555                 tundebug = *(int *)data;
  556                 break;
  557         case TUNGDEBUG:
  558                 *(int *)data = tundebug;
  559                 break;
  560         case TUNSLMODE:
  561                 if (*(int *)data) {
  562                         tp->tun_flags |= TUN_LMODE;
  563                         tp->tun_flags &= ~TUN_IFHEAD;
  564                 } else
  565                         tp->tun_flags &= ~TUN_LMODE;
  566                 break;
  567         case TUNSIFHEAD:
  568                 if (*(int *)data) {
  569                         tp->tun_flags |= TUN_IFHEAD;
  570                         tp->tun_flags &= ~TUN_LMODE;
  571                 } else
  572                         tp->tun_flags &= ~TUN_IFHEAD;
  573                 break;
  574         case TUNGIFHEAD:
  575                 *(int *)data = (tp->tun_flags & TUN_IFHEAD) ? 1 : 0;
  576                 break;
  577         case TUNSIFMODE:
  578                 /* deny this if UP */
  579                 if (tp->tun_if.if_flags & IFF_UP)
  580                         return(EBUSY);
  581 
  582                 switch (*(int *)data & ~IFF_MULTICAST) {
  583                 case IFF_POINTOPOINT:
  584                 case IFF_BROADCAST:
  585                         tp->tun_if.if_flags &=
  586                             ~(IFF_BROADCAST|IFF_POINTOPOINT|IFF_MULTICAST);
  587                         tp->tun_if.if_flags |= *(int *)data;
  588                         break;
  589                 default:
  590                         return(EINVAL);
  591                 }
  592                 break;
  593         case TUNSIFPID:
  594                 tp->tun_pid = curthread->td_proc->p_pid;
  595                 break;
  596         case FIONBIO:
  597                 break;
  598         case FIOASYNC:
  599                 if (*(int *)data)
  600                         tp->tun_flags |= TUN_ASYNC;
  601                 else
  602                         tp->tun_flags &= ~TUN_ASYNC;
  603                 break;
  604         case FIONREAD:
  605                 s = splimp();
  606                 if (tp->tun_if.if_snd.ifq_head) {
  607                         struct mbuf *mb = tp->tun_if.if_snd.ifq_head;
  608                         for( *(int *)data = 0; mb != 0; mb = mb->m_next)
  609                                 *(int *)data += mb->m_len;
  610                 } else
  611                         *(int *)data = 0;
  612                 splx(s);
  613                 break;
  614         case FIOSETOWN:
  615                 return (fsetown(*(int *)data, &tp->tun_sigio));
  616 
  617         case FIOGETOWN:
  618                 *(int *)data = fgetown(&tp->tun_sigio);
  619                 return (0);
  620 
  621         /* This is deprecated, FIOSETOWN should be used instead. */
  622         case TIOCSPGRP:
  623                 return (fsetown(-(*(int *)data), &tp->tun_sigio));
  624 
  625         /* This is deprecated, FIOGETOWN should be used instead. */
  626         case TIOCGPGRP:
  627                 *(int *)data = -fgetown(&tp->tun_sigio);
  628                 return (0);
  629 
  630         default:
  631                 return (ENOTTY);
  632         }
  633         return (0);
  634 }
  635 
  636 /*
  637  * The cdevsw read interface - reads a packet at a time, or at
  638  * least as much of a packet as can be read.
  639  */
  640 static  int
  641 tunread(dev_t dev, struct uio *uio, int flag)
  642 {
  643         struct tun_softc *tp = dev->si_drv1;
  644         struct ifnet    *ifp = &tp->tun_if;
  645         struct mbuf     *m;
  646         int             error=0, len, s;
  647 
  648         TUNDEBUG ("%s%d: read\n", ifp->if_name, ifp->if_unit);
  649         if ((tp->tun_flags & TUN_READY) != TUN_READY) {
  650                 TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name,
  651                           ifp->if_unit, tp->tun_flags);
  652                 return (EHOSTDOWN);
  653         }
  654 
  655         tp->tun_flags &= ~TUN_RWAIT;
  656 
  657         s = splimp();
  658         do {
  659                 IF_DEQUEUE(&ifp->if_snd, m);
  660                 if (m == NULL) {
  661                         if (flag & IO_NDELAY) {
  662                                 splx(s);
  663                                 return (EWOULDBLOCK);
  664                         }
  665                         tp->tun_flags |= TUN_RWAIT;
  666                         if((error = tsleep(tp, PCATCH | (PZERO + 1),
  667                                         "tunread", 0)) != 0) {
  668                                 splx(s);
  669                                 return (error);
  670                         }
  671                 }
  672         } while (m == NULL);
  673         splx(s);
  674 
  675         while (m && uio->uio_resid > 0 && error == 0) {
  676                 len = min(uio->uio_resid, m->m_len);
  677                 if (len != 0)
  678                         error = uiomove(mtod(m, void *), len, uio);
  679                 m = m_free(m);
  680         }
  681 
  682         if (m) {
  683                 TUNDEBUG("%s%d: Dropping mbuf\n", ifp->if_name, ifp->if_unit);
  684                 m_freem(m);
  685         }
  686         return (error);
  687 }
  688 
  689 /*
  690  * the cdevsw write interface - an atomic write is a packet - or else!
  691  */
  692 static  int
  693 tunwrite(dev_t dev, struct uio *uio, int flag)
  694 {
  695         struct tun_softc *tp = dev->si_drv1;
  696         struct ifnet    *ifp = &tp->tun_if;
  697         struct mbuf     *top, **mp, *m;
  698         int             error=0, tlen, mlen;
  699         uint32_t        family;
  700         int             isr;
  701 
  702         TUNDEBUG("%s%d: tunwrite\n", ifp->if_name, ifp->if_unit);
  703 
  704         if ((ifp->if_flags & IFF_UP) != IFF_UP)
  705                 /* ignore silently */
  706                 return (0);
  707 
  708         if (uio->uio_resid == 0)
  709                 return (0);
  710 
  711         if (uio->uio_resid < 0 || uio->uio_resid > TUNMRU) {
  712                 TUNDEBUG("%s%d: len=%d!\n", ifp->if_name, ifp->if_unit,
  713                     uio->uio_resid);
  714                 return (EIO);
  715         }
  716         tlen = uio->uio_resid;
  717 
  718         /* get a header mbuf */
  719         MGETHDR(m, M_DONTWAIT, MT_DATA);
  720         if (m == NULL)
  721                 return (ENOBUFS);
  722         mlen = MHLEN;
  723 
  724         top = 0;
  725         mp = &top;
  726         while (error == 0 && uio->uio_resid > 0) {
  727                 m->m_len = min(mlen, uio->uio_resid);
  728                 error = uiomove(mtod(m, void *), m->m_len, uio);
  729                 *mp = m;
  730                 mp = &m->m_next;
  731                 if (uio->uio_resid > 0) {
  732                         MGET (m, M_DONTWAIT, MT_DATA);
  733                         if (m == 0) {
  734                                 error = ENOBUFS;
  735                                 break;
  736                         }
  737                         mlen = MLEN;
  738                 }
  739         }
  740         if (error) {
  741                 if (top)
  742                         m_freem (top);
  743                 ifp->if_ierrors++;
  744                 return (error);
  745         }
  746 
  747         top->m_pkthdr.len = tlen;
  748         top->m_pkthdr.rcvif = ifp;
  749 #ifdef MAC
  750         mac_create_mbuf_from_ifnet(ifp, top);
  751 #endif
  752 
  753         if (ifp->if_bpf) {
  754                 if (tp->tun_flags & TUN_IFHEAD) {
  755                         /*
  756                          * Conveniently, we already have a 4-byte address
  757                          * family prepended to our packet !
  758                          * Inconveniently, it's in the wrong byte order !
  759                          */
  760                         if ((top = m_pullup(top, sizeof(family))) == NULL)
  761                                 return (ENOBUFS);
  762                         *mtod(top, u_int32_t *) =
  763                             ntohl(*mtod(top, u_int32_t *));
  764                         BPF_MTAP(ifp, top);
  765                         *mtod(top, u_int32_t *) =
  766                             htonl(*mtod(top, u_int32_t *));
  767                 } else {
  768                         /*
  769                          * We need to prepend the address family as
  770                          * a four byte field.  Cons up a dummy header
  771                          * to pacify bpf.  This is safe because bpf
  772                          * will only read from the mbuf (i.e., it won't
  773                          * try to free it or keep a pointer to it).
  774                          */
  775                         struct mbuf m;
  776                         uint32_t af = AF_INET;
  777 
  778                         m.m_next = top;
  779                         m.m_len = 4;
  780                         m.m_data = (char *)&af;
  781 
  782                         BPF_MTAP(ifp, &m);
  783                 }
  784         }
  785 
  786         if (tp->tun_flags & TUN_IFHEAD) {
  787                 if (top->m_len < sizeof(family) &&
  788                     (top = m_pullup(top, sizeof(family))) == NULL)
  789                         return (ENOBUFS);
  790                 family = ntohl(*mtod(top, u_int32_t *));
  791                 m_adj(top, sizeof(family));
  792         } else
  793                 family = AF_INET;
  794 
  795         switch (family) {
  796 #ifdef INET
  797         case AF_INET:
  798                 isr = NETISR_IP;
  799                 break;
  800 #endif
  801 #ifdef INET6
  802         case AF_INET6:
  803                 isr = NETISR_IPV6;
  804                 break;
  805 #endif
  806 #ifdef IPX
  807         case AF_IPX:
  808                 isr = NETISR_IPX;
  809                 break;
  810 #endif
  811 #ifdef NETATALK
  812         case AF_APPLETALK:
  813                 isr = NETISR_ATALK2;
  814                 break;
  815 #endif
  816         default:
  817                 m_freem(m);
  818                 return (EAFNOSUPPORT);
  819         }
  820         /* First chunk of an mbuf contains good junk */
  821         if (harvest.point_to_point)
  822                 random_harvest(m, 16, 3, 0, RANDOM_NET);
  823         ifp->if_ibytes += top->m_pkthdr.len;
  824         ifp->if_ipackets++;
  825         netisr_dispatch(isr, top);
  826         return (0);
  827 }
  828 
  829 /*
  830  * tunpoll - the poll interface, this is only useful on reads
  831  * really. The write detect always returns true, write never blocks
  832  * anyway, it either accepts the packet or drops it.
  833  */
  834 static  int
  835 tunpoll(dev_t dev, int events, struct thread *td)
  836 {
  837         int             s;
  838         struct tun_softc *tp = dev->si_drv1;
  839         struct ifnet    *ifp = &tp->tun_if;
  840         int             revents = 0;
  841 
  842         s = splimp();
  843         TUNDEBUG("%s%d: tunpoll\n", ifp->if_name, ifp->if_unit);
  844 
  845         if (events & (POLLIN | POLLRDNORM)) {
  846                 if (ifp->if_snd.ifq_len > 0) {
  847                         TUNDEBUG("%s%d: tunpoll q=%d\n", ifp->if_name,
  848                             ifp->if_unit, ifp->if_snd.ifq_len);
  849                         revents |= events & (POLLIN | POLLRDNORM);
  850                 } else {
  851                         TUNDEBUG("%s%d: tunpoll waiting\n", ifp->if_name,
  852                             ifp->if_unit);
  853                         selrecord(td, &tp->tun_rsel);
  854                 }
  855         }
  856         if (events & (POLLOUT | POLLWRNORM))
  857                 revents |= events & (POLLOUT | POLLWRNORM);
  858 
  859         splx(s);
  860         return (revents);
  861 }

Cache object: b72c649b2326fedcd85d09ba7d31b15d


[ 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.