root/net/if_tun.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tunattach
  2. tun_clone_create
  3. tun_create
  4. tun_clone_destroy
  5. tun_lookup
  6. tun_switch
  7. tunopen
  8. tunclose
  9. tuninit
  10. tun_ioctl
  11. tun_output
  12. tun_wakeup
  13. tunioctl
  14. tunread
  15. tunwrite
  16. tunpoll
  17. tunkqfilter
  18. filt_tunrdetach
  19. filt_tunread
  20. filt_tunwdetach
  21. filt_tunwrite
  22. tunstart

    1 /*      $OpenBSD: if_tun.c,v 1.89 2007/06/06 10:04:36 henning Exp $     */
    2 /*      $NetBSD: if_tun.c,v 1.24 1996/05/07 02:40:48 thorpej Exp $      */
    3 
    4 /*
    5  * Copyright (c) 1988, Julian Onions <Julian.Onions@nexor.co.uk>
    6  * Nottingham University 1987.
    7  * All rights reserved.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   28  */
   29 
   30 /*
   31  * This driver takes packets off the IP i/f and hands them up to a
   32  * user process to have its wicked way with. This driver has its
   33  * roots in a similar driver written by Phil Cockcroft (formerly) at
   34  * UCL. This driver is based much more on read/write/select mode of
   35  * operation though.
   36  */
   37 
   38 /* #define      TUN_DEBUG       9 */
   39 
   40 #include <sys/param.h>
   41 #include <sys/kernel.h>
   42 #include <sys/proc.h>
   43 #include <sys/systm.h>
   44 #include <sys/mbuf.h>
   45 #include <sys/protosw.h>
   46 #include <sys/socket.h>
   47 #include <sys/ioctl.h>
   48 #include <sys/errno.h>
   49 #include <sys/syslog.h>
   50 #include <sys/selinfo.h>
   51 #include <sys/file.h>
   52 #include <sys/time.h>
   53 #include <sys/device.h>
   54 #include <sys/vnode.h>
   55 #include <sys/signalvar.h>
   56 #include <sys/poll.h>
   57 #include <sys/conf.h>
   58 
   59 #include <machine/cpu.h>
   60 
   61 #include <net/if.h>
   62 #include <net/if_types.h>
   63 #include <net/netisr.h>
   64 #include <net/route.h>
   65 
   66 #ifdef INET
   67 #include <netinet/in.h>
   68 #include <netinet/in_systm.h>
   69 #include <netinet/in_var.h>
   70 #include <netinet/ip.h>
   71 #include <netinet/if_ether.h>
   72 #endif
   73 
   74 #ifdef NETATALK
   75 #include <netatalk/at.h>
   76 #include <netatalk/at_var.h>
   77 #endif
   78 
   79 #include "bpfilter.h"
   80 #if NBPFILTER > 0
   81 #include <net/bpf.h>
   82 #endif
   83 
   84 /* for arc4random() */
   85 #include <dev/rndvar.h>
   86 
   87 #include <net/if_tun.h>
   88 
   89 struct tun_softc {
   90         struct arpcom   arpcom;         /* ethernet common data */
   91         u_short         tun_flags;      /* misc flags */
   92         pid_t           tun_pgid;       /* the process group - if any */
   93         uid_t           tun_siguid;     /* uid for process that set tun_pgid */
   94         uid_t           tun_sigeuid;    /* euid for process that set tun_pgid */
   95         struct selinfo  tun_rsel;       /* read select */
   96         struct selinfo  tun_wsel;       /* write select (not used) */
   97         int             tun_unit;
   98         LIST_ENTRY(tun_softc) tun_list; /* all tunnel interfaces */
   99 #define tun_if  arpcom.ac_if
  100 };
  101 
  102 #ifdef  TUN_DEBUG
  103 int     tundebug = TUN_DEBUG;
  104 #define TUNDEBUG(a)     (tundebug? printf a : 0)
  105 #else
  106 #define TUNDEBUG(a)     /* (tundebug? printf a : 0) */
  107 #endif
  108 
  109 /* Only these IFF flags are changeable by TUNSIFINFO */
  110 #define TUN_IFF_FLAGS (IFF_UP|IFF_POINTOPOINT|IFF_MULTICAST|IFF_BROADCAST)
  111 
  112 void    tunattach(int);
  113 int     tunopen(dev_t, int, int, struct proc *);
  114 int     tunclose(dev_t, int, int, struct proc *);
  115 int     tun_ioctl(struct ifnet *, u_long, caddr_t);
  116 int     tun_output(struct ifnet *, struct mbuf *, struct sockaddr *,
  117             struct rtentry *);
  118 int     tunioctl(dev_t, u_long, caddr_t, int, struct proc *);
  119 int     tunread(dev_t, struct uio *, int);
  120 int     tunwrite(dev_t, struct uio *, int);
  121 int     tunpoll(dev_t, int, struct proc *);
  122 int     tunkqfilter(dev_t, struct knote *);
  123 int     tun_clone_create(struct if_clone *, int);
  124 int     tun_create(struct if_clone *, int, int);
  125 int     tun_clone_destroy(struct ifnet *);
  126 struct  tun_softc *tun_lookup(int);
  127 void    tun_wakeup(struct tun_softc *);
  128 int     tun_switch(struct tun_softc *, int);
  129 
  130 static int tuninit(struct tun_softc *);
  131 static void tunstart(struct ifnet *);
  132 int     filt_tunread(struct knote *, long);
  133 int     filt_tunwrite(struct knote *, long);
  134 void    filt_tunrdetach(struct knote *);
  135 void    filt_tunwdetach(struct knote *);
  136 
  137 struct filterops tunread_filtops =
  138         { 1, NULL, filt_tunrdetach, filt_tunread};
  139 
  140 struct filterops tunwrite_filtops =
  141         { 1, NULL, filt_tunwdetach, filt_tunwrite};
  142 
  143 LIST_HEAD(, tun_softc) tun_softc_list;
  144 
  145 struct if_clone tun_cloner =
  146     IF_CLONE_INITIALIZER("tun", tun_clone_create, tun_clone_destroy);
  147 
  148 void
  149 tunattach(int n)
  150 {
  151         LIST_INIT(&tun_softc_list);
  152         if_clone_attach(&tun_cloner);
  153 }
  154 
  155 int
  156 tun_clone_create(struct if_clone *ifc, int unit)
  157 {
  158         return (tun_create(ifc, unit, 0));
  159 }
  160 
  161 int
  162 tun_create(struct if_clone *ifc, int unit, int flags)
  163 {
  164         struct tun_softc        *tp;
  165         struct ifnet            *ifp;
  166         u_int32_t                macaddr_rnd;
  167         int                      s;
  168 
  169         tp = malloc(sizeof(*tp), M_DEVBUF, M_NOWAIT);
  170         if (!tp)
  171                 return (ENOMEM);
  172         bzero(tp, sizeof(*tp));
  173 
  174         tp->tun_unit = unit;
  175         tp->tun_flags = TUN_INITED|TUN_STAYUP;
  176 
  177         /* generate fake MAC address: 00 bd xx xx xx unit_no */
  178         tp->arpcom.ac_enaddr[0] = 0x00;
  179         tp->arpcom.ac_enaddr[1] = 0xbd;
  180         /*
  181          * This no longer happens pre-scheduler so let's use the real
  182          * random subsystem instead of random().
  183          */
  184         macaddr_rnd = arc4random();
  185         bcopy(&macaddr_rnd, &tp->arpcom.ac_enaddr[2], sizeof(u_int32_t));
  186         tp->arpcom.ac_enaddr[5] = (u_char)unit + 1;
  187 
  188         ifp = &tp->tun_if;
  189         snprintf(ifp->if_xname, sizeof ifp->if_xname, "%s%d", ifc->ifc_name,
  190             unit);
  191         ifp->if_softc = tp;
  192         ifp->if_ioctl = tun_ioctl;
  193         ifp->if_output = tun_output;
  194         ifp->if_start = tunstart;
  195         IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
  196         IFQ_SET_READY(&ifp->if_snd);
  197         if ((flags & TUN_LAYER2) == 0) {
  198                 tp->tun_flags &= ~TUN_LAYER2;
  199                 ifp->if_mtu = ETHERMTU;
  200                 ifp->if_flags = IFF_POINTOPOINT;
  201                 ifp->if_type = IFT_TUNNEL;
  202                 ifp->if_hdrlen = sizeof(u_int32_t);
  203                 if_attach(ifp);
  204                 if_alloc_sadl(ifp);
  205 #if NBPFILTER > 0
  206                 bpfattach(&ifp->if_bpf, ifp, DLT_LOOP, sizeof(u_int32_t));
  207 #endif
  208         } else {
  209                 tp->tun_flags |= TUN_LAYER2;
  210                 ifp->if_flags =
  211                     (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST|IFF_LINK0);
  212                 if_attach(ifp);
  213                 ether_ifattach(ifp);
  214         }
  215         /* force output function to our function */
  216         ifp->if_output = tun_output;
  217 
  218         s = splnet();
  219         LIST_INSERT_HEAD(&tun_softc_list, tp, tun_list);
  220         splx(s);
  221 
  222         return (0);
  223 }
  224 
  225 int
  226 tun_clone_destroy(struct ifnet *ifp)
  227 {
  228         struct tun_softc        *tp = ifp->if_softc;
  229         int                      s;
  230 
  231         tun_wakeup(tp);
  232 
  233         s = splhigh();
  234         klist_invalidate(&tp->tun_rsel.si_note);
  235         klist_invalidate(&tp->tun_wsel.si_note);
  236         splx(s);
  237 
  238         s = splnet();
  239         LIST_REMOVE(tp, tun_list);
  240         splx(s);
  241 
  242         if (tp->tun_flags & TUN_LAYER2)
  243                 ether_ifdetach(ifp);
  244 
  245         if_detach(ifp);
  246 
  247         free(tp, M_DEVBUF);
  248         return (0);
  249 }
  250 
  251 struct tun_softc *
  252 tun_lookup(int unit)
  253 {
  254         struct tun_softc *tp;
  255 
  256         LIST_FOREACH(tp, &tun_softc_list, tun_list)
  257                 if (tp->tun_unit == unit)
  258                         return (tp);
  259         return (NULL);
  260 }
  261 
  262 int
  263 tun_switch(struct tun_softc *tp, int flags)
  264 {
  265         struct ifnet    *ifp = &tp->tun_if;
  266         int              unit, open, r;
  267 
  268         if ((tp->tun_flags & TUN_LAYER2) == (flags & TUN_LAYER2))
  269                 return (0);
  270 
  271         /* tp will be removed so store unit number */
  272         unit = tp->tun_unit;
  273         open = tp->tun_flags & (TUN_OPEN|TUN_NBIO|TUN_ASYNC);
  274         TUNDEBUG(("%s: switching to layer %d\n", ifp->if_xname,
  275                     flags & TUN_LAYER2 ? 2 : 3));
  276 
  277         /* remove old device and ... */
  278         tun_clone_destroy(ifp);
  279         /* attach new interface */
  280         r = tun_create(&tun_cloner, unit, flags);
  281 
  282         if (open && r == 0) {
  283                 /* already opened before ifconfig tunX link0 */
  284                 if ((tp = tun_lookup(unit)) == NULL)
  285                         /* this should never fail */
  286                         return (ENXIO);
  287                 tp->tun_flags |= open;
  288                 TUNDEBUG(("%s: already open\n", tp->tun_if.if_xname));
  289         }
  290         return (r);
  291 }
  292 
  293 /*
  294  * tunnel open - must be superuser & the device must be
  295  * configured in
  296  */
  297 int
  298 tunopen(dev_t dev, int flag, int mode, struct proc *p)
  299 {
  300         struct tun_softc        *tp;
  301         struct ifnet            *ifp;
  302         int                      error, s;
  303 
  304         if ((error = suser(p, 0)) != 0)
  305                 return (error);
  306 
  307         if ((tp = tun_lookup(minor(dev))) == NULL) {    /* create on demand */
  308                 char    xname[IFNAMSIZ];
  309 
  310                 snprintf(xname, sizeof(xname), "%s%d", "tun", minor(dev));
  311                 if ((error = if_clone_create(xname)) != 0)
  312                         return (error);
  313 
  314                 if ((tp = tun_lookup(minor(dev))) == NULL)
  315                         return (ENXIO);
  316                 tp->tun_flags &= ~TUN_STAYUP;
  317         }
  318 
  319         if (tp->tun_flags & TUN_OPEN)
  320                 return (EBUSY);
  321 
  322         ifp = &tp->tun_if;
  323         tp->tun_flags |= TUN_OPEN;
  324 
  325         /* automatically UP the interface on open */
  326         s = splnet();
  327         if_up(ifp);
  328         ifp->if_flags |= IFF_RUNNING;
  329         splx(s);
  330 
  331         TUNDEBUG(("%s: open\n", ifp->if_xname));
  332         return (0);
  333 }
  334 
  335 /*
  336  * tunclose - close the device; if closing the real device, flush pending
  337  *  output and unless STAYUP bring down and destroy the interface.
  338  */
  339 int
  340 tunclose(dev_t dev, int flag, int mode, struct proc *p)
  341 {
  342         int                      s;
  343         struct tun_softc        *tp;
  344         struct ifnet            *ifp;
  345 
  346         if ((tp = tun_lookup(minor(dev))) == NULL)
  347                 return (ENXIO);
  348 
  349         ifp = &tp->tun_if;
  350         tp->tun_flags &= ~(TUN_OPEN|TUN_NBIO|TUN_ASYNC);
  351         ifp->if_flags &= ~IFF_RUNNING;
  352 
  353         /*
  354          * junk all pending output
  355          */
  356         s = splnet();
  357         IFQ_PURGE(&ifp->if_snd);
  358         splx(s);
  359 
  360         TUNDEBUG(("%s: closed\n", ifp->if_xname));
  361 
  362         if (!(tp->tun_flags & TUN_STAYUP))
  363                 return (if_clone_destroy(ifp->if_xname));
  364         else {
  365                 tp->tun_pgid = 0;
  366                 selwakeup(&tp->tun_rsel);
  367                 KNOTE(&tp->tun_rsel.si_note, 0);
  368         }
  369 
  370         return (0);
  371 }
  372 
  373 static int
  374 tuninit(struct tun_softc *tp)
  375 {
  376         struct ifnet    *ifp = &tp->tun_if;
  377         struct ifaddr   *ifa;
  378 
  379         TUNDEBUG(("%s: tuninit\n", ifp->if_xname));
  380 
  381         ifp->if_flags |= IFF_UP | IFF_RUNNING;
  382         ifp->if_flags &= ~IFF_OACTIVE; /* we are never active */
  383 
  384         tp->tun_flags &= ~(TUN_IASET|TUN_DSTADDR|TUN_BRDADDR);
  385         TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
  386 #ifdef INET
  387                 if (ifa->ifa_addr->sa_family == AF_INET) {
  388                         struct sockaddr_in *sin;
  389 
  390                         sin = satosin(ifa->ifa_addr);
  391                         if (sin && sin->sin_addr.s_addr)
  392                                 tp->tun_flags |= TUN_IASET;
  393 
  394                         if (ifp->if_flags & IFF_POINTOPOINT) {
  395                                 sin = satosin(ifa->ifa_dstaddr);
  396                                 if (sin && sin->sin_addr.s_addr)
  397                                         tp->tun_flags |= TUN_DSTADDR;
  398                         } else
  399                                 tp->tun_flags &= ~TUN_DSTADDR;
  400 
  401                         if (ifp->if_flags & IFF_BROADCAST) {
  402                                 sin = satosin(ifa->ifa_broadaddr);
  403                                 if (sin && sin->sin_addr.s_addr)
  404                                         tp->tun_flags |= TUN_BRDADDR;
  405                         } else
  406                                 tp->tun_flags &= ~TUN_BRDADDR;
  407                 }
  408 #endif
  409 #ifdef INET6
  410                 if (ifa->ifa_addr->sa_family == AF_INET6) {
  411                         struct sockaddr_in6 *sin;
  412 
  413                         sin = (struct sockaddr_in6 *)ifa->ifa_addr;
  414                         if (!IN6_IS_ADDR_UNSPECIFIED(&sin->sin6_addr))
  415                                 tp->tun_flags |= TUN_IASET;
  416 
  417                         if (ifp->if_flags & IFF_POINTOPOINT) {
  418                                 sin = (struct sockaddr_in6 *)ifa->ifa_dstaddr;
  419                                 if (sin &&
  420                                     !IN6_IS_ADDR_UNSPECIFIED(&sin->sin6_addr))
  421                                         tp->tun_flags |= TUN_DSTADDR;
  422                         } else
  423                                 tp->tun_flags &= ~TUN_DSTADDR;
  424                 }
  425 #endif /* INET6 */
  426         }
  427 
  428         return (0);
  429 }
  430 
  431 /*
  432  * Process an ioctl request.
  433  */
  434 int
  435 tun_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
  436 {
  437         struct tun_softc        *tp = (struct tun_softc *)(ifp->if_softc);
  438         struct ifreq            *ifr = (struct ifreq *)data;
  439         int                      error = 0, s;
  440 
  441         s = splnet();
  442         if (tp->tun_flags & TUN_LAYER2)
  443                 if ((error = ether_ioctl(ifp, &tp->arpcom, cmd, data)) > 0) {
  444                         splx(s);
  445                         return (error);
  446                 }
  447         switch (cmd) {
  448         case SIOCSIFADDR:
  449                 tuninit(tp);
  450                 TUNDEBUG(("%s: address set\n", ifp->if_xname));
  451                 if (tp->tun_flags & TUN_LAYER2)
  452                         switch (((struct ifaddr *)data)->ifa_addr->sa_family) {
  453 #ifdef INET
  454                         case AF_INET:
  455                                 arp_ifinit(&tp->arpcom, (struct ifaddr *)data);
  456                                 break;
  457 #endif
  458                         default:
  459                                 break;
  460                         }
  461                 break;
  462         case SIOCSIFDSTADDR:
  463                 tuninit(tp);
  464                 TUNDEBUG(("%s: destination address set\n", ifp->if_xname));
  465                 break;
  466         case SIOCSIFBRDADDR:
  467                 tuninit(tp);
  468                 TUNDEBUG(("%s: broadcast address set\n", ifp->if_xname));
  469                 break;
  470         case SIOCSIFMTU:
  471                 if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > TUNMRU)
  472                         error = EINVAL;
  473                 else
  474                         ifp->if_mtu = ifr->ifr_mtu;
  475                 break;
  476         case SIOCADDMULTI:
  477         case SIOCDELMULTI: {
  478                 if (ifr == 0) {
  479                         error = EAFNOSUPPORT;      /* XXX */
  480                         break;
  481                 }
  482 
  483                 if (tp->tun_flags & TUN_LAYER2) {
  484                         error = (cmd == SIOCADDMULTI) ?
  485                             ether_addmulti(ifr, &tp->arpcom) :
  486                             ether_delmulti(ifr, &tp->arpcom);
  487                         if (error == ENETRESET) {
  488                                 /*
  489                                  * Multicast list has changed; set the hardware
  490                                  * filter accordingly. The good thing is we do 
  491                                  * not have a hardware filter (:
  492                                  */
  493                                 error = 0;
  494                         }
  495                         break;
  496                 }
  497 
  498                 switch (ifr->ifr_addr.sa_family) {
  499 #ifdef INET
  500                 case AF_INET:
  501                         break;
  502 #endif
  503 #ifdef INET6
  504                 case AF_INET6:
  505                         break;
  506 #endif
  507                 default:
  508                         error = EAFNOSUPPORT;
  509                         break;
  510                 }
  511                 break;
  512         }
  513 
  514         case SIOCSIFFLAGS:
  515                 error = tun_switch(tp,
  516                     ifp->if_flags & IFF_LINK0 ? TUN_LAYER2 : 0);
  517                 break;
  518         default:
  519                 error = EINVAL;
  520         }
  521         splx(s);
  522         return (error);
  523 }
  524 
  525 /*
  526  * tun_output - queue packets from higher level ready to put out.
  527  */
  528 int
  529 tun_output(struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst,
  530     struct rtentry *rt)
  531 {
  532         struct tun_softc        *tp = ifp->if_softc;
  533         int                      s, len, error;
  534         u_int32_t               *af;
  535 
  536         if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
  537                 m_freem(m0);
  538                 return (EHOSTDOWN);
  539         }
  540 
  541         TUNDEBUG(("%s: tun_output\n", ifp->if_xname));
  542 
  543         if ((tp->tun_flags & TUN_READY) != TUN_READY) {
  544                 TUNDEBUG(("%s: not ready %#x\n", ifp->if_xname,
  545                      tp->tun_flags));
  546                 m_freem(m0);
  547                 return (EHOSTDOWN);
  548         }
  549 
  550         if (tp->tun_flags & TUN_LAYER2)
  551                 /* call ether_output and that will call tunstart at the end */
  552                 return (ether_output(ifp, m0, dst, rt));
  553 
  554         M_PREPEND(m0, sizeof(*af), M_DONTWAIT);
  555         af = mtod(m0, u_int32_t *);
  556         *af = htonl(dst->sa_family);
  557 
  558 #if NBPFILTER > 0
  559         if (ifp->if_bpf)
  560                 bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
  561 #endif
  562 
  563         len = m0->m_pkthdr.len + sizeof(*af);
  564         s = splnet();
  565         IFQ_ENQUEUE(&ifp->if_snd, m0, NULL, error);
  566         if (error) {
  567                 splx(s);
  568                 ifp->if_collisions++;
  569                 return (error);
  570         }
  571         splx(s);
  572         ifp->if_opackets++;
  573         ifp->if_obytes += len;
  574 
  575         tun_wakeup(tp);
  576         return (0);
  577 }
  578 
  579 void
  580 tun_wakeup(struct tun_softc *tp)
  581 {
  582         if (tp->tun_flags & TUN_RWAIT) {
  583                 tp->tun_flags &= ~TUN_RWAIT;
  584                 wakeup((caddr_t)tp);
  585         }
  586         if (tp->tun_flags & TUN_ASYNC && tp->tun_pgid)
  587                 csignal(tp->tun_pgid, SIGIO,
  588                     tp->tun_siguid, tp->tun_sigeuid);
  589         selwakeup(&tp->tun_rsel);
  590         KNOTE(&tp->tun_rsel.si_note, 0);
  591 }
  592 
  593 /*
  594  * the cdevsw interface is now pretty minimal.
  595  */
  596 int
  597 tunioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
  598 {
  599         int                      s;
  600         struct tun_softc        *tp;
  601         struct tuninfo          *tunp;
  602         struct mbuf             *m;
  603 
  604         if ((tp = tun_lookup(minor(dev))) == NULL)
  605                 return (ENXIO);
  606 
  607         s = splnet();
  608         switch (cmd) {
  609         case TUNSIFINFO:
  610                 tunp = (struct tuninfo *)data;
  611                 if (tunp->mtu < ETHERMIN || tunp->mtu > TUNMRU) {
  612                         splx(s);
  613                         return (EINVAL);
  614                 }
  615                 tp->tun_if.if_mtu = tunp->mtu;
  616                 tp->tun_if.if_type = tunp->type;
  617                 tp->tun_if.if_flags = 
  618                     (tunp->flags & TUN_IFF_FLAGS) |
  619                     (tp->tun_if.if_flags & ~TUN_IFF_FLAGS);
  620                 tp->tun_if.if_baudrate = tunp->baudrate;
  621                 break;
  622         case TUNGIFINFO:
  623                 tunp = (struct tuninfo *)data;
  624                 tunp->mtu = tp->tun_if.if_mtu;
  625                 tunp->type = tp->tun_if.if_type;
  626                 tunp->flags = tp->tun_if.if_flags;
  627                 tunp->baudrate = tp->tun_if.if_baudrate;
  628                 break;
  629 #ifdef TUN_DEBUG
  630         case TUNSDEBUG:
  631                 tundebug = *(int *)data;
  632                 break;
  633         case TUNGDEBUG:
  634                 *(int *)data = tundebug;
  635                 break;
  636 #endif
  637         case TUNSIFMODE:
  638                 switch (*(int *)data & (IFF_POINTOPOINT|IFF_BROADCAST)) {
  639                 case IFF_POINTOPOINT:
  640                 case IFF_BROADCAST:
  641                         tp->tun_if.if_flags &= ~TUN_IFF_FLAGS;
  642                         tp->tun_if.if_flags |= *(int *)data & TUN_IFF_FLAGS;
  643                         break;
  644                 default:
  645                         splx(s);
  646                         return (EINVAL);
  647                 }
  648                 break;
  649 
  650         case FIONBIO:
  651                 if (*(int *)data)
  652                         tp->tun_flags |= TUN_NBIO;
  653                 else
  654                         tp->tun_flags &= ~TUN_NBIO;
  655                 break;
  656         case FIOASYNC:
  657                 if (*(int *)data)
  658                         tp->tun_flags |= TUN_ASYNC;
  659                 else
  660                         tp->tun_flags &= ~TUN_ASYNC;
  661                 break;
  662         case FIONREAD:
  663                 IFQ_POLL(&tp->tun_if.if_snd, m);
  664                 if (m != NULL)
  665                         *(int *)data = m->m_pkthdr.len;
  666                 else
  667                         *(int *)data = 0;
  668                 break;
  669         case TIOCSPGRP:
  670                 tp->tun_pgid = *(int *)data;
  671                 tp->tun_siguid = p->p_cred->p_ruid;
  672                 tp->tun_sigeuid = p->p_ucred->cr_uid;
  673                 break;
  674         case TIOCGPGRP:
  675                 *(int *)data = tp->tun_pgid;
  676                 break;
  677         case OSIOCGIFADDR:
  678         case SIOCGIFADDR:
  679                 if (!(tp->tun_flags & TUN_LAYER2)) {
  680                         splx(s);
  681                         return (EINVAL);
  682                 }
  683                 bcopy(tp->arpcom.ac_enaddr, data,
  684                     sizeof(tp->arpcom.ac_enaddr));
  685                 break;
  686 
  687         case SIOCSIFADDR:
  688                 if (!(tp->tun_flags & TUN_LAYER2)) {
  689                         splx(s);
  690                         return (EINVAL);
  691                 }
  692                 bcopy(data, tp->arpcom.ac_enaddr,
  693                     sizeof(tp->arpcom.ac_enaddr));
  694                 break;
  695         default:
  696                 splx(s);
  697                 return (ENOTTY);
  698         }
  699         splx(s);
  700         return (0);
  701 }
  702 
  703 /*
  704  * The cdevsw read interface - reads a packet at a time, or at
  705  * least as much of a packet as can be read.
  706  */
  707 int
  708 tunread(dev_t dev, struct uio *uio, int ioflag)
  709 {
  710         struct tun_softc        *tp;
  711         struct ifnet            *ifp;
  712         struct mbuf             *m, *m0;
  713         int                      error = 0, len, s;
  714 
  715         if ((tp = tun_lookup(minor(dev))) == NULL)
  716                 return (ENXIO);
  717 
  718         ifp = &tp->tun_if;
  719         TUNDEBUG(("%s: read\n", ifp->if_xname));
  720         if ((tp->tun_flags & TUN_READY) != TUN_READY) {
  721                 TUNDEBUG(("%s: not ready %#x\n", ifp->if_xname, tp->tun_flags));
  722                 return (EHOSTDOWN);
  723         }
  724 
  725         tp->tun_flags &= ~TUN_RWAIT;
  726 
  727         s = splnet();
  728         do {
  729                 while ((tp->tun_flags & TUN_READY) != TUN_READY)
  730                         if ((error = tsleep((caddr_t)tp,
  731                             (PZERO + 1)|PCATCH, "tunread", 0)) != 0) {
  732                                 splx(s);
  733                                 return (error);
  734                         }
  735                 IFQ_DEQUEUE(&ifp->if_snd, m0);
  736                 if (m0 == NULL) {
  737                         if (tp->tun_flags & TUN_NBIO && ioflag & IO_NDELAY) {
  738                                 splx(s);
  739                                 return (EWOULDBLOCK);
  740                         }
  741                         tp->tun_flags |= TUN_RWAIT;
  742                         if ((error = tsleep((caddr_t)tp,
  743                             (PZERO + 1)|PCATCH, "tunread", 0)) != 0) {
  744                                 splx(s);
  745                                 return (error);
  746                         }
  747                 }
  748         } while (m0 == NULL);
  749         splx(s);
  750 
  751         while (m0 != NULL && uio->uio_resid > 0 && error == 0) {
  752                 len = min(uio->uio_resid, m0->m_len);
  753                 if (len != 0)
  754                         error = uiomove(mtod(m0, caddr_t), len, uio);
  755                 MFREE(m0, m);
  756                 m0 = m;
  757         }
  758 
  759         if (m0 != NULL) {
  760                 TUNDEBUG(("Dropping mbuf\n"));
  761                 m_freem(m0);
  762         }
  763         if (error)
  764                 ifp->if_ierrors++;
  765 
  766         return (error);
  767 }
  768 
  769 /*
  770  * the cdevsw write interface - an atomic write is a packet - or else!
  771  */
  772 int
  773 tunwrite(dev_t dev, struct uio *uio, int ioflag)
  774 {
  775         struct tun_softc        *tp;
  776         struct ifnet            *ifp;
  777         struct ifqueue          *ifq;
  778         u_int32_t               *th;
  779         struct mbuf             *top, **mp, *m;
  780         int                      isr;
  781         int                      error=0, s, tlen, mlen;
  782 
  783         if ((tp = tun_lookup(minor(dev))) == NULL)
  784                 return (ENXIO);
  785 
  786         ifp = &tp->tun_if;
  787         TUNDEBUG(("%s: tunwrite\n", ifp->if_xname));
  788 
  789         if (uio->uio_resid == 0 || uio->uio_resid > ifp->if_mtu +
  790             (tp->tun_flags & TUN_LAYER2 ? ETHER_HDR_LEN : sizeof(*th))) {
  791                 TUNDEBUG(("%s: len=%d!\n", ifp->if_xname, uio->uio_resid));
  792                 return (EMSGSIZE);
  793         }
  794         tlen = uio->uio_resid;
  795 
  796         /* get a header mbuf */
  797         MGETHDR(m, M_DONTWAIT, MT_DATA);
  798         if (m == NULL)
  799                 return (ENOBUFS);
  800         mlen = MHLEN;
  801         if (uio->uio_resid >= MINCLSIZE) {
  802                 MCLGET(m, M_DONTWAIT);
  803                 if (!(m->m_flags & M_EXT)) {
  804                         m_free(m);
  805                         return (ENOBUFS);
  806                 }
  807                 mlen = MCLBYTES;
  808         }
  809 
  810         top = NULL;
  811         mp = &top;
  812         if (tp->tun_flags & TUN_LAYER2) {
  813                 /*
  814                  * Pad so that IP header is correctly aligned
  815                  * this is necessary for all strict aligned architectures.
  816                  */
  817                 mlen -= ETHER_ALIGN;
  818                 m->m_data += ETHER_ALIGN;
  819         }
  820         while (error == 0 && uio->uio_resid > 0) {
  821                 m->m_len = min(mlen, uio->uio_resid);
  822                 error = uiomove(mtod (m, caddr_t), m->m_len, uio);
  823                 *mp = m;
  824                 mp = &m->m_next;
  825                 if (error == 0 && uio->uio_resid > 0) {
  826                         MGET(m, M_DONTWAIT, MT_DATA);
  827                         if (m == NULL) {
  828                                 error = ENOBUFS;
  829                                 break;
  830                         }
  831                         mlen = MLEN;
  832                         if (uio->uio_resid >= MINCLSIZE) {
  833                                 MCLGET(m, M_DONTWAIT);
  834                                 if (!(m->m_flags & M_EXT)) {
  835                                         error = ENOBUFS;
  836                                         m_free(m);
  837                                         break;
  838                                 }
  839                                 mlen = MCLBYTES;
  840                         }
  841                 }
  842         }
  843         if (error) {
  844                 if (top != NULL)
  845                         m_freem(top);
  846                 ifp->if_ierrors++;
  847                 return (error);
  848         }
  849 
  850         top->m_pkthdr.len = tlen;
  851         top->m_pkthdr.rcvif = ifp;
  852 
  853 #if NBPFILTER > 0
  854         if (ifp->if_bpf)
  855                 bpf_mtap(ifp->if_bpf, top, BPF_DIRECTION_IN);
  856 #endif
  857 
  858         if (tp->tun_flags & TUN_LAYER2) {
  859                 ether_input_mbuf(ifp, top);
  860                 ifp->if_ipackets++; /* ibytes are counted in ether_input */
  861                 return (0);
  862         }
  863 
  864         th = mtod(top, u_int32_t *);
  865         /* strip the tunnel header */
  866         top->m_data += sizeof(*th);
  867         top->m_len  -= sizeof(*th);
  868         top->m_pkthdr.len -= sizeof(*th);
  869 
  870         switch (ntohl(*th)) {
  871 #ifdef INET
  872         case AF_INET:
  873                 ifq = &ipintrq;
  874                 isr = NETISR_IP;
  875                 break;
  876 #endif
  877 #ifdef INET6
  878         case AF_INET6:
  879                 ifq = &ip6intrq;
  880                 isr = NETISR_IPV6;
  881                 break;
  882 #endif
  883 #ifdef NETATALK
  884         case AF_APPLETALK:
  885                 ifq = &atintrq2;
  886                 isr = NETISR_ATALK;
  887                 break;
  888 #endif
  889         default:
  890                 m_freem(top);
  891                 return (EAFNOSUPPORT);
  892         }
  893 
  894         s = splnet();
  895         if (IF_QFULL(ifq)) {
  896                 IF_DROP(ifq);
  897                 splx(s);
  898                 ifp->if_collisions++;
  899                 m_freem(top);
  900                 if (!ifq->ifq_congestion)
  901                         if_congestion(ifq);
  902                 return (ENOBUFS);
  903         }
  904         IF_ENQUEUE(ifq, top);
  905         schednetisr(isr);
  906         ifp->if_ipackets++;
  907         ifp->if_ibytes += top->m_pkthdr.len;
  908         splx(s);
  909         return (error);
  910 }
  911 
  912 /*
  913  * tunpoll - the poll interface, this is only useful on reads
  914  * really. The write detect always returns true, write never blocks
  915  * anyway, it either accepts the packet or drops it.
  916  */
  917 int
  918 tunpoll(dev_t dev, int events, struct proc *p)
  919 {
  920         int                      revents, s;
  921         struct tun_softc        *tp;
  922         struct ifnet            *ifp;
  923         struct mbuf             *m;
  924 
  925         if ((tp = tun_lookup(minor(dev))) == NULL)
  926                 return (POLLERR);
  927 
  928         ifp = &tp->tun_if;
  929         revents = 0;
  930         s = splnet();
  931         TUNDEBUG(("%s: tunpoll\n", ifp->if_xname));
  932 
  933         if (events & (POLLIN | POLLRDNORM)) {
  934                 IFQ_POLL(&ifp->if_snd, m);
  935                 if (m != NULL) {
  936                         TUNDEBUG(("%s: tunselect q=%d\n", ifp->if_xname,
  937                             ifp->if_snd.ifq_len));
  938                         revents |= events & (POLLIN | POLLRDNORM);
  939                 } else {
  940                         TUNDEBUG(("%s: tunpoll waiting\n", ifp->if_xname));
  941                         selrecord(p, &tp->tun_rsel);
  942                 }
  943         }
  944         if (events & (POLLOUT | POLLWRNORM))
  945                 revents |= events & (POLLOUT | POLLWRNORM);
  946         splx(s);
  947         return (revents);
  948 }
  949 
  950 /*
  951  * kqueue(2) support.
  952  *
  953  * The tun driver uses an array of tun_softc's based on the minor number
  954  * of the device.  kn->kn_hook gets set to the specific tun_softc.
  955  *
  956  * filt_tunread() sets kn->kn_data to the iface qsize
  957  * filt_tunwrite() sets kn->kn_data to the MTU size
  958  */
  959 int
  960 tunkqfilter(dev_t dev, struct knote *kn)
  961 {
  962         int                      s;
  963         struct klist            *klist;
  964         struct tun_softc        *tp;
  965         struct ifnet            *ifp;
  966 
  967         if ((tp = tun_lookup(minor(dev))) == NULL)
  968                 return (ENXIO);
  969 
  970         ifp = &tp->tun_if;
  971 
  972         s = splnet();
  973         TUNDEBUG(("%s: tunkqfilter\n", ifp->if_xname));
  974         splx(s);
  975 
  976         switch (kn->kn_filter) {
  977                 case EVFILT_READ:
  978                         klist = &tp->tun_rsel.si_note;
  979                         kn->kn_fop = &tunread_filtops;
  980                         break;
  981                 case EVFILT_WRITE:
  982                         klist = &tp->tun_wsel.si_note;
  983                         kn->kn_fop = &tunwrite_filtops;
  984                         break;
  985                 default:
  986                         return (EPERM); /* 1 */
  987         }
  988 
  989         kn->kn_hook = (caddr_t)tp;
  990 
  991         s = splhigh();
  992         SLIST_INSERT_HEAD(klist, kn, kn_selnext);
  993         splx(s);
  994 
  995         return (0);
  996 }
  997 
  998 void
  999 filt_tunrdetach(struct knote *kn)
 1000 {
 1001         int                      s;
 1002         struct tun_softc        *tp;
 1003 
 1004         tp = (struct tun_softc *)kn->kn_hook;
 1005         s = splhigh();
 1006         if (!(kn->kn_status & KN_DETACHED))
 1007                 SLIST_REMOVE(&tp->tun_rsel.si_note, kn, knote, kn_selnext);
 1008         splx(s);
 1009 }
 1010 
 1011 int
 1012 filt_tunread(struct knote *kn, long hint)
 1013 {
 1014         int                      s;
 1015         struct tun_softc        *tp;
 1016         struct ifnet            *ifp;
 1017         struct mbuf             *m;
 1018 
 1019         if (kn->kn_status & KN_DETACHED) {
 1020                 kn->kn_data = 0;
 1021                 return (1);
 1022         }
 1023 
 1024         tp = (struct tun_softc *)kn->kn_hook;
 1025         ifp = &tp->tun_if;
 1026 
 1027         s = splnet();
 1028         IFQ_POLL(&ifp->if_snd, m);
 1029         if (m != NULL) {
 1030                 splx(s);
 1031                 kn->kn_data = ifp->if_snd.ifq_len;
 1032 
 1033                 TUNDEBUG(("%s: tunkqread q=%d\n", ifp->if_xname,
 1034                     ifp->if_snd.ifq_len));
 1035                 return (1);
 1036         }
 1037         splx(s);
 1038         TUNDEBUG(("%s: tunkqread waiting\n", ifp->if_xname));
 1039         return (0);
 1040 }
 1041 
 1042 void
 1043 filt_tunwdetach(struct knote *kn)
 1044 {
 1045         int                      s;
 1046         struct tun_softc        *tp;
 1047 
 1048         tp = (struct tun_softc *)kn->kn_hook;
 1049         s = splhigh();
 1050         if (!(kn->kn_status & KN_DETACHED))
 1051                 SLIST_REMOVE(&tp->tun_wsel.si_note, kn, knote, kn_selnext);
 1052         splx(s);
 1053 }
 1054 
 1055 int
 1056 filt_tunwrite(struct knote *kn, long hint)
 1057 {
 1058         struct tun_softc        *tp;
 1059         struct ifnet            *ifp;
 1060 
 1061         if (kn->kn_status & KN_DETACHED) {
 1062                 kn->kn_data = 0;
 1063                 return (1);
 1064         }
 1065 
 1066         tp = (struct tun_softc *)kn->kn_hook;
 1067         ifp = &tp->tun_if;
 1068 
 1069         kn->kn_data = ifp->if_mtu;
 1070 
 1071         return (1);
 1072 }
 1073 
 1074 /*
 1075  * Start packet transmission on the interface.
 1076  * when the interface queue is rate-limited by ALTQ or TBR,
 1077  * if_start is needed to drain packets from the queue in order
 1078  * to notify readers when outgoing packets become ready.
 1079  * In layer 2 mode this function is called from ether_output.
 1080  */
 1081 static void
 1082 tunstart(struct ifnet *ifp)
 1083 {
 1084         struct tun_softc        *tp = ifp->if_softc;
 1085         struct mbuf             *m;
 1086 
 1087         if (!(tp->tun_flags & TUN_LAYER2) &&
 1088             !ALTQ_IS_ENABLED(&ifp->if_snd) &&
 1089             !TBR_IS_ENABLED(&ifp->if_snd))
 1090                 return;
 1091 
 1092         IFQ_POLL(&ifp->if_snd, m);
 1093         if (m != NULL) {
 1094                 if (tp->tun_flags & TUN_LAYER2) {
 1095 #if NBPFILTER > 0
 1096                         if (ifp->if_bpf)
 1097                                 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
 1098 #endif
 1099                         ifp->if_opackets++;
 1100                 }
 1101                 tun_wakeup(tp);
 1102         }
 1103 }

/* [<][>][^][v][top][bottom][index][help] */