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$
   17  */
   18 
   19 #include "opt_inet.h"
   20 
   21 #include <sys/param.h>
   22 #include <sys/proc.h>
   23 #include <sys/systm.h>
   24 #include <sys/mbuf.h>
   25 #include <sys/socket.h>
   26 #include <sys/filio.h>
   27 #include <sys/sockio.h>
   28 #include <sys/ttycom.h>
   29 #include <sys/poll.h>
   30 #include <sys/signalvar.h>
   31 #include <sys/filedesc.h>
   32 #include <sys/kernel.h>
   33 #include <sys/sysctl.h>
   34 #include <sys/conf.h>
   35 #include <sys/uio.h>
   36 #include <sys/vnode.h>
   37 #include <sys/malloc.h>
   38 
   39 #include <net/if.h>
   40 #include <net/if_types.h>
   41 #include <net/route.h>
   42 #include <net/intrq.h>
   43 
   44 #ifdef INET
   45 #include <netinet/in.h>
   46 #endif
   47 
   48 #include <net/bpf.h>
   49 
   50 #include <net/if_tunvar.h>
   51 #include <net/if_tun.h>
   52 
   53 static MALLOC_DEFINE(M_TUN, "tun", "Tunnel Interface");
   54 
   55 static void tunattach __P((void *));
   56 PSEUDO_SET(tunattach, if_tun);
   57 
   58 static void tuncreate __P((dev_t dev));
   59 
   60 #define TUNDEBUG        if (tundebug) printf
   61 static int tundebug = 0;
   62 SYSCTL_INT(_debug, OID_AUTO, if_tun_debug, CTLFLAG_RW, &tundebug, 0, "");
   63 
   64 static int tunoutput __P((struct ifnet *, struct mbuf *, struct sockaddr *,
   65             struct rtentry *rt));
   66 static int tunifioctl __P((struct ifnet *, u_long, caddr_t));
   67 static int tuninit __P((struct ifnet *));
   68 
   69 static  d_open_t        tunopen;
   70 static  d_close_t       tunclose;
   71 static  d_read_t        tunread;
   72 static  d_write_t       tunwrite;
   73 static  d_ioctl_t       tunioctl;
   74 static  d_poll_t        tunpoll;
   75 
   76 #define CDEV_MAJOR 52
   77 static struct cdevsw tun_cdevsw = {
   78         /* open */      tunopen,
   79         /* close */     tunclose,
   80         /* read */      tunread,
   81         /* write */     tunwrite,
   82         /* ioctl */     tunioctl,
   83         /* poll */      tunpoll,
   84         /* mmap */      nommap,
   85         /* strategy */  nostrategy,
   86         /* name */      "tun",
   87         /* maj */       CDEV_MAJOR,
   88         /* dump */      nodump,
   89         /* psize */     nopsize,
   90         /* flags */     0,
   91         /* bmaj */      -1
   92 };
   93 
   94 static void
   95 tunattach(dummy)
   96         void *dummy;
   97 {
   98 
   99         cdevsw_add(&tun_cdevsw);
  100 }
  101 
  102 static void
  103 tuncreate(dev)
  104         dev_t dev;
  105 {
  106         struct tun_softc *sc;
  107         struct ifnet *ifp;
  108 
  109         dev = make_dev(&tun_cdevsw, minor(dev),
  110             UID_UUCP, GID_DIALER, 0600, "tun%d", lminor(dev));
  111 
  112         MALLOC(sc, struct tun_softc *, sizeof(*sc), M_TUN, M_WAITOK);
  113         bzero(sc, sizeof *sc);
  114         sc->tun_flags = TUN_INITED;
  115 
  116         ifp = &sc->tun_if;
  117         ifp->if_unit = lminor(dev);
  118         ifp->if_name = "tun";
  119         ifp->if_mtu = TUNMTU;
  120         ifp->if_ioctl = tunifioctl;
  121         ifp->if_output = tunoutput;
  122         ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
  123         ifp->if_type = IFT_PPP;
  124         ifp->if_snd.ifq_maxlen = ifqmaxlen;
  125         ifp->if_softc = sc;
  126         if_attach(ifp);
  127         bpfattach(ifp, DLT_NULL, sizeof(u_int));
  128         dev->si_drv1 = sc;
  129 }
  130 
  131 /*
  132  * tunnel open - must be superuser & the device must be
  133  * configured in
  134  */
  135 static  int
  136 tunopen(dev, flag, mode, p)
  137         dev_t   dev;
  138         int     flag, mode;
  139         struct proc *p;
  140 {
  141         struct ifnet    *ifp;
  142         struct tun_softc *tp;
  143         register int    error;
  144 
  145         error = suser(p);
  146         if (error)
  147                 return (error);
  148 
  149         tp = dev->si_drv1;
  150         if (!tp) {
  151                 tuncreate(dev);
  152                 tp = dev->si_drv1;
  153         }
  154         if (tp->tun_flags & TUN_OPEN)
  155                 return EBUSY;
  156         tp->tun_pid = p->p_pid;
  157         ifp = &tp->tun_if;
  158         tp->tun_flags |= TUN_OPEN;
  159         TUNDEBUG("%s%d: open\n", ifp->if_name, ifp->if_unit);
  160         return (0);
  161 }
  162 
  163 /*
  164  * tunclose - close the device - mark i/f down & delete
  165  * routing info
  166  */
  167 static  int
  168 tunclose(dev, foo, bar, p)
  169         dev_t dev;
  170         int foo;
  171         int bar;
  172         struct proc *p;
  173 {
  174         register int    s;
  175         struct tun_softc *tp;
  176         struct ifnet    *ifp;
  177         struct mbuf     *m;
  178 
  179         tp = dev->si_drv1;
  180         ifp = &tp->tun_if;
  181 
  182         tp->tun_flags &= ~TUN_OPEN;
  183         tp->tun_pid = 0;
  184 
  185         /*
  186          * junk all pending output
  187          */
  188         do {
  189                 s = splimp();
  190                 IF_DEQUEUE(&ifp->if_snd, m);
  191                 splx(s);
  192                 if (m)
  193                         m_freem(m);
  194         } while (m);
  195 
  196         if (ifp->if_flags & IFF_UP) {
  197                 s = splimp();
  198                 if_down(ifp);
  199                 splx(s);
  200         }
  201 
  202         if (ifp->if_flags & IFF_RUNNING) {
  203                 register struct ifaddr *ifa;
  204 
  205                 s = splimp();
  206                 /* find internet addresses and delete routes */
  207                 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
  208                         if (ifa->ifa_addr->sa_family == AF_INET)
  209                                 rtinit(ifa, (int)RTM_DELETE,
  210                                     tp->tun_flags & TUN_DSTADDR ? RTF_HOST : 0);
  211                 ifp->if_flags &= ~IFF_RUNNING;
  212                 splx(s);
  213         }
  214 
  215         funsetown(tp->tun_sigio);
  216         selwakeup(&tp->tun_rsel);
  217 
  218         TUNDEBUG ("%s%d: closed\n", ifp->if_name, ifp->if_unit);
  219         return (0);
  220 }
  221 
  222 static int
  223 tuninit(ifp)
  224         struct ifnet *ifp;
  225 {
  226         struct tun_softc *tp = ifp->if_softc;
  227         register struct ifaddr *ifa;
  228         int error = 0;
  229 
  230         TUNDEBUG("%s%d: tuninit\n", ifp->if_name, ifp->if_unit);
  231 
  232         ifp->if_flags |= IFF_UP | IFF_RUNNING;
  233         getmicrotime(&ifp->if_lastchange);
  234 
  235         for (ifa = TAILQ_FIRST(&ifp->if_addrhead); ifa; 
  236              ifa = TAILQ_NEXT(ifa, ifa_link)) {
  237                 if (ifa->ifa_addr == NULL)
  238                         error = EFAULT;
  239                         /* XXX: Should maybe return straight off? */
  240                 else {
  241 #ifdef INET
  242                         if (ifa->ifa_addr->sa_family == AF_INET) {
  243                             struct sockaddr_in *si;
  244 
  245                             si = (struct sockaddr_in *)ifa->ifa_addr;
  246                             if (si->sin_addr.s_addr)
  247                                     tp->tun_flags |= TUN_IASET;
  248 
  249                             si = (struct sockaddr_in *)ifa->ifa_dstaddr;
  250                             if (si && si->sin_addr.s_addr)
  251                                     tp->tun_flags |= TUN_DSTADDR;
  252                         }
  253 #endif
  254                 }
  255         }
  256         return (error);
  257 }
  258 
  259 /*
  260  * Process an ioctl request.
  261  */
  262 int
  263 tunifioctl(ifp, cmd, data)
  264         struct ifnet *ifp;
  265         u_long  cmd;
  266         caddr_t data;
  267 {
  268         struct ifreq *ifr = (struct ifreq *)data;
  269         struct tun_softc *tp = ifp->if_softc;
  270         struct ifstat *ifs;
  271         int             error = 0, s;
  272 
  273         s = splimp();
  274         switch(cmd) {
  275         case SIOCGIFSTATUS:
  276                 ifs = (struct ifstat *)data;
  277                 if (tp->tun_pid)
  278                         sprintf(ifs->ascii + strlen(ifs->ascii),
  279                             "\tOpened by PID %d\n", tp->tun_pid);
  280                 break;
  281         case SIOCSIFADDR:
  282                 error = tuninit(ifp);
  283                 TUNDEBUG("%s%d: address set, error=%d\n",
  284                          ifp->if_name, ifp->if_unit, error);
  285                 break;
  286         case SIOCSIFDSTADDR:
  287                 error = tuninit(ifp);
  288                 TUNDEBUG("%s%d: destination address set, error=%d\n",
  289                          ifp->if_name, ifp->if_unit, error);
  290                 break;
  291         case SIOCSIFMTU:
  292                 ifp->if_mtu = ifr->ifr_mtu;
  293                 TUNDEBUG("%s%d: mtu set\n",
  294                          ifp->if_name, ifp->if_unit);
  295                 break;
  296         case SIOCSIFFLAGS:
  297         case SIOCADDMULTI:
  298         case SIOCDELMULTI:
  299                 break;
  300         default:
  301                 error = EINVAL;
  302         }
  303         splx(s);
  304         return (error);
  305 }
  306 
  307 /*
  308  * tunoutput - queue packets from higher level ready to put out.
  309  */
  310 int
  311 tunoutput(ifp, m0, dst, rt)
  312         struct ifnet   *ifp;
  313         struct mbuf    *m0;
  314         struct sockaddr *dst;
  315         struct rtentry *rt;
  316 {
  317         struct tun_softc *tp = ifp->if_softc;
  318         int             s;
  319 
  320         TUNDEBUG ("%s%d: tunoutput\n", ifp->if_name, ifp->if_unit);
  321 
  322         if ((tp->tun_flags & TUN_READY) != TUN_READY) {
  323                 TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name,
  324                           ifp->if_unit, tp->tun_flags);
  325                 m_freem (m0);
  326                 return EHOSTDOWN;
  327         }
  328 
  329         /* BPF write needs to be handled specially */
  330         if (dst->sa_family == AF_UNSPEC) {
  331                 dst->sa_family = *(mtod(m0, int *));
  332                 m0->m_len -= sizeof(int);
  333                 m0->m_pkthdr.len -= sizeof(int);
  334                 m0->m_data += sizeof(int);
  335         }
  336 
  337         if (ifp->if_bpf) {
  338                 /*
  339                  * We need to prepend the address family as
  340                  * a four byte field.  Cons up a dummy header
  341                  * to pacify bpf.  This is safe because bpf
  342                  * will only read from the mbuf (i.e., it won't
  343                  * try to free it or keep a pointer to it).
  344                  */
  345                 struct mbuf m;
  346                 uint32_t af = dst->sa_family;
  347 
  348                 m.m_next = m0;
  349                 m.m_len = 4;
  350                 m.m_data = (char *)&af;
  351 
  352                 bpf_mtap(ifp, &m);
  353         }
  354 
  355         /* prepend sockaddr? this may abort if the mbuf allocation fails */
  356         if (tp->tun_flags & TUN_LMODE) {
  357                 /* allocate space for sockaddr */
  358                 M_PREPEND(m0, dst->sa_len, M_DONTWAIT);
  359 
  360                 /* if allocation failed drop packet */
  361                 if (m0 == NULL){
  362                         s = splimp();   /* spl on queue manipulation */
  363                         IF_DROP(&ifp->if_snd);
  364                         splx(s);
  365                         ifp->if_oerrors++;
  366                         return (ENOBUFS);
  367                 } else {
  368                         bcopy(dst, m0->m_data, dst->sa_len);
  369                 }
  370         }
  371 
  372         if (tp->tun_flags & TUN_IFHEAD) {
  373                 /* Prepend the address family */
  374                 M_PREPEND(m0, 4, M_DONTWAIT);
  375 
  376                 /* if allocation failed drop packet */
  377                 if (m0 == NULL){
  378                         s = splimp();   /* spl on queue manipulation */
  379                         IF_DROP(&ifp->if_snd);
  380                         splx(s);
  381                         ifp->if_oerrors++;
  382                         return ENOBUFS;
  383                 } else
  384                         *(u_int32_t *)m0->m_data = htonl(dst->sa_family);
  385         } else {
  386 #ifdef INET
  387                 if (dst->sa_family != AF_INET)
  388 #endif
  389                 {
  390                         m_freem(m0);
  391                         return EAFNOSUPPORT;
  392                 }
  393         }
  394 
  395         s = splimp();
  396         if (IF_QFULL(&ifp->if_snd)) {
  397                 IF_DROP(&ifp->if_snd);
  398                 m_freem(m0);
  399                 splx(s);
  400                 ifp->if_collisions++;
  401                 return ENOBUFS;
  402         }
  403         ifp->if_obytes += m0->m_pkthdr.len;
  404         IF_ENQUEUE(&ifp->if_snd, m0);
  405         splx(s);
  406         ifp->if_opackets++;
  407 
  408         if (tp->tun_flags & TUN_RWAIT) {
  409                 tp->tun_flags &= ~TUN_RWAIT;
  410                 wakeup((caddr_t)tp);
  411         }
  412         if (tp->tun_flags & TUN_ASYNC && tp->tun_sigio)
  413                 pgsigio(tp->tun_sigio, SIGIO, 0);
  414         selwakeup(&tp->tun_rsel);
  415         return 0;
  416 }
  417 
  418 /*
  419  * the cdevsw interface is now pretty minimal.
  420  */
  421 static  int
  422 tunioctl(dev, cmd, data, flag, p)
  423         dev_t           dev;
  424         u_long          cmd;
  425         caddr_t         data;
  426         int             flag;
  427         struct proc     *p;
  428 {
  429         int             s;
  430         struct tun_softc *tp = dev->si_drv1;
  431         struct tuninfo *tunp;
  432 
  433         switch (cmd) {
  434         case TUNSIFINFO:
  435                 tunp = (struct tuninfo *)data;
  436                 if (tunp->mtu < IF_MINMTU)
  437                         return (EINVAL);
  438                 tp->tun_if.if_mtu = tunp->mtu;
  439                 tp->tun_if.if_type = tunp->type;
  440                 tp->tun_if.if_baudrate = tunp->baudrate;
  441                 break;
  442         case TUNGIFINFO:
  443                 tunp = (struct tuninfo *)data;
  444                 tunp->mtu = tp->tun_if.if_mtu;
  445                 tunp->type = tp->tun_if.if_type;
  446                 tunp->baudrate = tp->tun_if.if_baudrate;
  447                 break;
  448         case TUNSDEBUG:
  449                 tundebug = *(int *)data;
  450                 break;
  451         case TUNGDEBUG:
  452                 *(int *)data = tundebug;
  453                 break;
  454         case TUNSLMODE:
  455                 if (*(int *)data) {
  456                         tp->tun_flags |= TUN_LMODE;
  457                         tp->tun_flags &= ~TUN_IFHEAD;
  458                 } else
  459                         tp->tun_flags &= ~TUN_LMODE;
  460                 break;
  461         case TUNSIFHEAD:
  462                 if (*(int *)data) {
  463                         tp->tun_flags |= TUN_IFHEAD;
  464                         tp->tun_flags &= ~TUN_LMODE;
  465                 } else 
  466                         tp->tun_flags &= ~TUN_IFHEAD;
  467                 break;
  468         case TUNGIFHEAD:
  469                 *(int *)data = (tp->tun_flags & TUN_IFHEAD) ? 1 : 0;
  470                 break;
  471         case TUNSIFMODE:
  472                 /* deny this if UP */
  473                 if (tp->tun_if.if_flags & IFF_UP)
  474                         return(EBUSY);
  475 
  476                 switch (*(int *)data & ~IFF_MULTICAST) {
  477                 case IFF_POINTOPOINT:
  478                 case IFF_BROADCAST:
  479                         tp->tun_if.if_flags &= ~(IFF_BROADCAST|IFF_POINTOPOINT);
  480                         tp->tun_if.if_flags |= *(int *)data;
  481                         break;
  482                 default:
  483                         return(EINVAL);
  484                 }
  485                 break;
  486         case TUNSIFPID:
  487                 tp->tun_pid = curproc->p_pid;
  488                 break;
  489         case FIONBIO:
  490                 break;
  491         case FIOASYNC:
  492                 if (*(int *)data)
  493                         tp->tun_flags |= TUN_ASYNC;
  494                 else
  495                         tp->tun_flags &= ~TUN_ASYNC;
  496                 break;
  497         case FIONREAD:
  498                 s = splimp();
  499                 if (tp->tun_if.if_snd.ifq_head) {
  500                         struct mbuf *mb = tp->tun_if.if_snd.ifq_head;
  501                         for( *(int *)data = 0; mb != 0; mb = mb->m_next) 
  502                                 *(int *)data += mb->m_len;
  503                 } else
  504                         *(int *)data = 0;
  505                 splx(s);
  506                 break;
  507         case FIOSETOWN:
  508                 return (fsetown(*(int *)data, &tp->tun_sigio));
  509 
  510         case FIOGETOWN:
  511                 *(int *)data = fgetown(tp->tun_sigio);
  512                 return (0);
  513 
  514         /* This is deprecated, FIOSETOWN should be used instead. */
  515         case TIOCSPGRP:
  516                 return (fsetown(-(*(int *)data), &tp->tun_sigio));
  517 
  518         /* This is deprecated, FIOGETOWN should be used instead. */
  519         case TIOCGPGRP:
  520                 *(int *)data = -fgetown(tp->tun_sigio);
  521                 return (0);
  522 
  523         default:
  524                 return (ENOTTY);
  525         }
  526         return (0);
  527 }
  528 
  529 /*
  530  * The cdevsw read interface - reads a packet at a time, or at
  531  * least as much of a packet as can be read.
  532  */
  533 static  int
  534 tunread(dev, uio, flag)
  535         dev_t dev;
  536         struct uio *uio;
  537         int flag;
  538 {
  539         struct tun_softc *tp = dev->si_drv1;
  540         struct ifnet    *ifp = &tp->tun_if;
  541         struct mbuf     *m0;
  542         int             error=0, len, s;
  543 
  544         TUNDEBUG ("%s%d: read\n", ifp->if_name, ifp->if_unit);
  545         if ((tp->tun_flags & TUN_READY) != TUN_READY) {
  546                 TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name,
  547                           ifp->if_unit, tp->tun_flags);
  548                 return EHOSTDOWN;
  549         }
  550 
  551         tp->tun_flags &= ~TUN_RWAIT;
  552 
  553         s = splimp();
  554         do {
  555                 IF_DEQUEUE(&ifp->if_snd, m0);
  556                 if (m0 == 0) {
  557                         if (flag & IO_NDELAY) {
  558                                 splx(s);
  559                                 return EWOULDBLOCK;
  560                         }
  561                         tp->tun_flags |= TUN_RWAIT;
  562                         if((error = tsleep((caddr_t)tp, PCATCH | (PZERO + 1),
  563                                         "tunread", 0)) != 0) {
  564                                 splx(s);
  565                                 return error;
  566                         }
  567                 }
  568         } while (m0 == 0);
  569         splx(s);
  570 
  571         while (m0 && uio->uio_resid > 0 && error == 0) {
  572                 len = min(uio->uio_resid, m0->m_len);
  573                 if (len != 0)
  574                         error = uiomove(mtod(m0, caddr_t), len, uio);
  575                 m0 = m_free(m0);
  576         }
  577 
  578         if (m0) {
  579                 TUNDEBUG("%s%d: Dropping mbuf\n", ifp->if_name, ifp->if_unit);
  580                 m_freem(m0);
  581         }
  582         return error;
  583 }
  584 
  585 /*
  586  * the cdevsw write interface - an atomic write is a packet - or else!
  587  */
  588 static  int
  589 tunwrite(dev, uio, flag)
  590         dev_t dev;
  591         struct uio *uio;
  592         int flag;
  593 {
  594         struct tun_softc *tp = dev->si_drv1;
  595         struct ifnet    *ifp = &tp->tun_if;
  596         struct mbuf     *top, **mp, *m;
  597         int             error=0, tlen, mlen;
  598         uint32_t        family;
  599 
  600         TUNDEBUG("%s%d: tunwrite\n", ifp->if_name, ifp->if_unit);
  601 
  602         if (uio->uio_resid == 0)
  603                 return 0;
  604 
  605         if (uio->uio_resid < 0 || uio->uio_resid > TUNMRU) {
  606                 TUNDEBUG("%s%d: len=%d!\n", ifp->if_name, ifp->if_unit,
  607                     uio->uio_resid);
  608                 return EIO;
  609         }
  610         tlen = uio->uio_resid;
  611 
  612         /* get a header mbuf */
  613         MGETHDR(m, M_DONTWAIT, MT_DATA);
  614         if (m == NULL)
  615                 return ENOBUFS;
  616         mlen = MHLEN;
  617 
  618         top = 0;
  619         mp = &top;
  620         while (error == 0 && uio->uio_resid > 0) {
  621                 m->m_len = min(mlen, uio->uio_resid);
  622                 error = uiomove(mtod (m, caddr_t), m->m_len, uio);
  623                 *mp = m;
  624                 mp = &m->m_next;
  625                 if (uio->uio_resid > 0) {
  626                         MGET (m, M_DONTWAIT, MT_DATA);
  627                         if (m == 0) {
  628                                 error = ENOBUFS;
  629                                 break;
  630                         }
  631                         mlen = MLEN;
  632                 }
  633         }
  634         if (error) {
  635                 if (top)
  636                         m_freem (top);
  637                 ifp->if_ierrors++;
  638                 return error;
  639         }
  640 
  641         top->m_pkthdr.len = tlen;
  642         top->m_pkthdr.rcvif = ifp;
  643 
  644         if (ifp->if_bpf) {
  645                 if (tp->tun_flags & TUN_IFHEAD) {
  646                         /*
  647                          * Conveniently, we already have a 4-byte address
  648                          * family prepended to our packet !
  649                          * Inconveniently, it's in the wrong byte order !
  650                          */
  651                         if ((top = m_pullup(top, sizeof(family))) == NULL)
  652                                 return ENOBUFS;
  653                         *mtod(top, u_int32_t *) =
  654                             ntohl(*mtod(top, u_int32_t *));
  655                         bpf_mtap(ifp, top);
  656                         *mtod(top, u_int32_t *) =
  657                             htonl(*mtod(top, u_int32_t *));
  658                 } else {
  659                         /*
  660                          * We need to prepend the address family as
  661                          * a four byte field.  Cons up a dummy header
  662                          * to pacify bpf.  This is safe because bpf
  663                          * will only read from the mbuf (i.e., it won't
  664                          * try to free it or keep a pointer to it).
  665                          */
  666                         struct mbuf m;
  667                         uint32_t af = AF_INET;
  668 
  669                         m.m_next = top;
  670                         m.m_len = 4;
  671                         m.m_data = (char *)&af;
  672 
  673                         bpf_mtap(ifp, &m);
  674                 }
  675         }
  676 
  677         if (tp->tun_flags & TUN_IFHEAD) {
  678                 if (top->m_len < sizeof(family) &&
  679                     (top = m_pullup(top, sizeof(family))) == NULL)
  680                                 return ENOBUFS;
  681                 family = ntohl(*mtod(top, u_int32_t *));
  682                 m_adj(top, sizeof(family));
  683         } else
  684                 family = AF_INET;
  685 
  686         ifp->if_ibytes += top->m_pkthdr.len;
  687         ifp->if_ipackets++;
  688 
  689         return family_enqueue(family, top);
  690 }
  691 
  692 /*
  693  * tunpoll - the poll interface, this is only useful on reads
  694  * really. The write detect always returns true, write never blocks
  695  * anyway, it either accepts the packet or drops it.
  696  */
  697 static  int
  698 tunpoll(dev, events, p)
  699         dev_t dev;
  700         int events;
  701         struct proc *p;
  702 {
  703         int             s;
  704         struct tun_softc *tp = dev->si_drv1;
  705         struct ifnet    *ifp = &tp->tun_if;
  706         int             revents = 0;
  707 
  708         s = splimp();
  709         TUNDEBUG("%s%d: tunpoll\n", ifp->if_name, ifp->if_unit);
  710 
  711         if (events & (POLLIN | POLLRDNORM)) {
  712                 if (ifp->if_snd.ifq_len > 0) {
  713                         TUNDEBUG("%s%d: tunpoll q=%d\n", ifp->if_name,
  714                             ifp->if_unit, ifp->if_snd.ifq_len);
  715                         revents |= events & (POLLIN | POLLRDNORM);
  716                 } else {
  717                         TUNDEBUG("%s%d: tunpoll waiting\n", ifp->if_name,
  718                             ifp->if_unit);
  719                         selrecord(p, &tp->tun_rsel);
  720                 }
  721         }
  722         if (events & (POLLOUT | POLLWRNORM))
  723                 revents |= events & (POLLOUT | POLLWRNORM);
  724 
  725         splx(s);
  726         return (revents);
  727 }

Cache object: f6e8f061abf73737b3e5cf48a71e5006


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