LCOV - code coverage report
Current view: top level - net - if_tun.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 514 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 38 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: if_tun.c,v 1.181 2018/02/24 07:20:04 dlg 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/fcntl.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             : 
      60             : #include <net/if.h>
      61             : #include <net/if_types.h>
      62             : #include <net/netisr.h>
      63             : #include <net/rtable.h>
      64             : 
      65             : #include <netinet/in.h>
      66             : #include <netinet/if_ether.h>
      67             : 
      68             : #ifdef PIPEX
      69             : #include <net/pipex.h>
      70             : #endif
      71             : 
      72             : #include "bpfilter.h"
      73             : #if NBPFILTER > 0
      74             : #include <net/bpf.h>
      75             : #endif
      76             : 
      77             : #include <net/if_tun.h>
      78             : 
      79             : struct tun_softc {
      80             :         struct arpcom   arpcom;         /* ethernet common data */
      81             :         struct selinfo  tun_rsel;       /* read select */
      82             :         struct selinfo  tun_wsel;       /* write select (not used) */
      83             :         LIST_ENTRY(tun_softc) entry;    /* all tunnel interfaces */
      84             :         int             tun_unit;
      85             :         uid_t           tun_siguid;     /* uid for process that set tun_pgid */
      86             :         uid_t           tun_sigeuid;    /* euid for process that set tun_pgid */
      87             :         pid_t           tun_pgid;       /* the process group - if any */
      88             :         u_short         tun_flags;      /* misc flags */
      89             : #define tun_if  arpcom.ac_if
      90             : #ifdef PIPEX
      91             :         struct pipex_iface_context pipex_iface; /* pipex context */
      92             : #endif
      93             : };
      94             : 
      95             : #ifdef  TUN_DEBUG
      96             : int     tundebug = TUN_DEBUG;
      97             : #define TUNDEBUG(a)     (tundebug? printf a : 0)
      98             : #else
      99             : #define TUNDEBUG(a)     /* (tundebug? printf a : 0) */
     100             : #endif
     101             : 
     102             : /* Only these IFF flags are changeable by TUNSIFINFO */
     103             : #define TUN_IFF_FLAGS (IFF_UP|IFF_POINTOPOINT|IFF_MULTICAST|IFF_BROADCAST)
     104             : 
     105             : void    tunattach(int);
     106             : 
     107             : /* cdev functions */
     108             : int     tunopen(dev_t, int, int, struct proc *);
     109             : int     tunclose(dev_t, int, int, struct proc *);
     110             : int     tunioctl(dev_t, u_long, caddr_t, int, struct proc *);
     111             : int     tunread(dev_t, struct uio *, int);
     112             : int     tunwrite(dev_t, struct uio *, int);
     113             : int     tunpoll(dev_t, int, struct proc *);
     114             : int     tunkqfilter(dev_t, struct knote *);
     115             : 
     116             : int     tapopen(dev_t, int, int, struct proc *);
     117             : int     tapclose(dev_t, int, int, struct proc *);
     118             : int     tapioctl(dev_t, u_long, caddr_t, int, struct proc *);
     119             : int     tapread(dev_t, struct uio *, int);
     120             : int     tapwrite(dev_t, struct uio *, int);
     121             : int     tappoll(dev_t, int, struct proc *);
     122             : int     tapkqfilter(dev_t, struct knote *);
     123             : 
     124             : int     tun_dev_open(struct tun_softc *, int, int, struct proc *);
     125             : int     tun_dev_close(struct tun_softc *, int, int, struct proc *);
     126             : int     tun_dev_ioctl(struct tun_softc *, u_long, caddr_t, int, struct proc *);
     127             : int     tun_dev_read(struct tun_softc *, struct uio *, int);
     128             : int     tun_dev_write(struct tun_softc *, struct uio *, int);
     129             : int     tun_dev_poll(struct tun_softc *, int, struct proc *);
     130             : int     tun_dev_kqfilter(struct tun_softc *, struct knote *);
     131             : 
     132             : 
     133             : int     tun_ioctl(struct ifnet *, u_long, caddr_t);
     134             : int     tun_output(struct ifnet *, struct mbuf *, struct sockaddr *,
     135             :             struct rtentry *);
     136             : int     tun_clone_create(struct if_clone *, int);
     137             : int     tap_clone_create(struct if_clone *, int);
     138             : int     tun_create(struct if_clone *, int, int);
     139             : int     tun_clone_destroy(struct ifnet *);
     140             : static inline struct    tun_softc *tun_lookup(int);
     141             : static inline struct    tun_softc *tap_lookup(int);
     142             : void    tun_wakeup(struct tun_softc *);
     143             : int     tun_init(struct tun_softc *);
     144             : void    tun_start(struct ifnet *);
     145             : int     filt_tunread(struct knote *, long);
     146             : int     filt_tunwrite(struct knote *, long);
     147             : void    filt_tunrdetach(struct knote *);
     148             : void    filt_tunwdetach(struct knote *);
     149             : void    tun_link_state(struct tun_softc *);
     150             : 
     151             : struct filterops tunread_filtops =
     152             :         { 1, NULL, filt_tunrdetach, filt_tunread};
     153             : 
     154             : struct filterops tunwrite_filtops =
     155             :         { 1, NULL, filt_tunwdetach, filt_tunwrite};
     156             : 
     157             : LIST_HEAD(, tun_softc) tun_softc_list;
     158             : LIST_HEAD(, tun_softc) tap_softc_list;
     159             : 
     160             : struct if_clone tun_cloner =
     161             :     IF_CLONE_INITIALIZER("tun", tun_clone_create, tun_clone_destroy);
     162             : 
     163             : struct if_clone tap_cloner =
     164             :     IF_CLONE_INITIALIZER("tap", tap_clone_create, tun_clone_destroy);
     165             : 
     166             : void
     167           0 : tunattach(int n)
     168             : {
     169           0 :         LIST_INIT(&tun_softc_list);
     170           0 :         LIST_INIT(&tap_softc_list);
     171           0 :         if_clone_attach(&tun_cloner);
     172           0 :         if_clone_attach(&tap_cloner);
     173             : #ifdef PIPEX
     174           0 :         pipex_init();
     175             : #endif
     176           0 : }
     177             : 
     178             : int
     179           0 : tun_clone_create(struct if_clone *ifc, int unit)
     180             : {
     181           0 :         return (tun_create(ifc, unit, 0));
     182             : }
     183             : 
     184             : int
     185           0 : tap_clone_create(struct if_clone *ifc, int unit)
     186             : {
     187           0 :         return (tun_create(ifc, unit, TUN_LAYER2));
     188             : }
     189             : 
     190             : int
     191           0 : tun_create(struct if_clone *ifc, int unit, int flags)
     192             : {
     193             :         struct tun_softc        *tp;
     194             :         struct ifnet            *ifp;
     195             : 
     196           0 :         tp = malloc(sizeof(*tp), M_DEVBUF, M_WAITOK|M_ZERO);
     197           0 :         tp->tun_unit = unit;
     198           0 :         tp->tun_flags = TUN_INITED|TUN_STAYUP;
     199             : 
     200           0 :         ifp = &tp->tun_if;
     201           0 :         snprintf(ifp->if_xname, sizeof(ifp->if_xname), "%s%d", ifc->ifc_name,
     202             :             unit);
     203           0 :         ifp->if_softc = tp;
     204             : 
     205           0 :         ifp->if_ioctl = tun_ioctl;
     206           0 :         ifp->if_output = tun_output;
     207           0 :         ifp->if_start = tun_start;
     208           0 :         ifp->if_hardmtu = TUNMRU;
     209           0 :         ifp->if_link_state = LINK_STATE_DOWN;
     210           0 :         IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
     211             : 
     212           0 :         if ((flags & TUN_LAYER2) == 0) {
     213           0 :                 tp->tun_flags &= ~TUN_LAYER2;
     214           0 :                 ifp->if_mtu = ETHERMTU;
     215           0 :                 ifp->if_flags = (IFF_POINTOPOINT|IFF_MULTICAST);
     216           0 :                 ifp->if_type = IFT_TUNNEL;
     217           0 :                 ifp->if_hdrlen = sizeof(u_int32_t);
     218           0 :                 ifp->if_rtrequest = p2p_rtrequest;
     219             : 
     220           0 :                 if_attach(ifp);
     221           0 :                 if_alloc_sadl(ifp);
     222             : #if NBPFILTER > 0
     223           0 :                 bpfattach(&ifp->if_bpf, ifp, DLT_LOOP, sizeof(u_int32_t));
     224             : #endif
     225           0 :                 LIST_INSERT_HEAD(&tun_softc_list, tp, entry);
     226           0 :         } else {
     227           0 :                 tp->tun_flags |= TUN_LAYER2;
     228           0 :                 ether_fakeaddr(ifp);
     229           0 :                 ifp->if_flags =
     230             :                     (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST);
     231           0 :                 ifp->if_capabilities = IFCAP_VLAN_MTU;
     232             : 
     233           0 :                 if_attach(ifp);
     234           0 :                 ether_ifattach(ifp);
     235             : 
     236           0 :                 LIST_INSERT_HEAD(&tap_softc_list, tp, entry);
     237             :         }
     238             : 
     239             : #ifdef PIPEX
     240           0 :         if ((tp->tun_flags & TUN_LAYER2) == 0)
     241           0 :                 pipex_iface_init(&tp->pipex_iface, ifp);
     242             : #endif
     243             : 
     244           0 :         return (0);
     245             : }
     246             : 
     247             : int
     248           0 : tun_clone_destroy(struct ifnet *ifp)
     249             : {
     250           0 :         struct tun_softc        *tp = ifp->if_softc;
     251             :         int                      s;
     252             : 
     253             : #ifdef PIPEX
     254           0 :         if ((tp->tun_flags & TUN_LAYER2) == 0)
     255           0 :                 pipex_iface_fini(&tp->pipex_iface);
     256             : #endif
     257           0 :         tun_wakeup(tp);
     258             : 
     259           0 :         s = splhigh();
     260           0 :         klist_invalidate(&tp->tun_rsel.si_note);
     261           0 :         klist_invalidate(&tp->tun_wsel.si_note);
     262           0 :         splx(s);
     263             : 
     264           0 :         LIST_REMOVE(tp, entry);
     265             : 
     266           0 :         if (tp->tun_flags & TUN_LAYER2)
     267           0 :                 ether_ifdetach(ifp);
     268             : 
     269           0 :         if_detach(ifp);
     270             : 
     271           0 :         free(tp, M_DEVBUF, sizeof *tp);
     272           0 :         return (0);
     273             : }
     274             : 
     275             : static inline struct tun_softc *
     276           0 : tun_lookup(int unit)
     277             : {
     278             :         struct tun_softc *tp;
     279             : 
     280           0 :         LIST_FOREACH(tp, &tun_softc_list, entry)
     281           0 :                 if (tp->tun_unit == unit)
     282           0 :                         return (tp);
     283           0 :         return (NULL);
     284           0 : }
     285             : 
     286             : static inline struct tun_softc *
     287           0 : tap_lookup(int unit)
     288             : {
     289             :         struct tun_softc *tp;
     290             : 
     291           0 :         LIST_FOREACH(tp, &tap_softc_list, entry)
     292           0 :                 if (tp->tun_unit == unit)
     293           0 :                         return (tp);
     294           0 :         return (NULL);
     295           0 : }
     296             : 
     297             : /*
     298             :  * tunnel open - must be superuser & the device must be
     299             :  * configured in
     300             :  */
     301             : int
     302           0 : tunopen(dev_t dev, int flag, int mode, struct proc *p)
     303             : {
     304             :         struct tun_softc *tp;
     305           0 :         unsigned int rdomain = rtable_l2(p->p_p->ps_rtableid);
     306             : 
     307           0 :         if ((tp = tun_lookup(minor(dev))) == NULL) {    /* create on demand */
     308           0 :                 char    xname[IFNAMSIZ];
     309             :                 int     error;
     310             : 
     311           0 :                 snprintf(xname, sizeof(xname), "%s%d", "tun", minor(dev));
     312           0 :                 NET_LOCK();
     313           0 :                 error = if_clone_create(xname, rdomain);
     314           0 :                 NET_UNLOCK();
     315           0 :                 if (error != 0)
     316           0 :                         return (error);
     317             : 
     318           0 :                 if ((tp = tun_lookup(minor(dev))) == NULL)
     319           0 :                         return (ENXIO);
     320           0 :                 tp->tun_flags &= ~TUN_STAYUP;
     321           0 :         }
     322             : 
     323           0 :         return (tun_dev_open(tp, flag, mode, p));
     324           0 : }
     325             : 
     326             : int
     327           0 : tapopen(dev_t dev, int flag, int mode, struct proc *p)
     328             : {
     329             :         struct tun_softc *tp;
     330           0 :         unsigned int rdomain = rtable_l2(p->p_p->ps_rtableid);
     331             : 
     332           0 :         if ((tp = tap_lookup(minor(dev))) == NULL) {    /* create on demand */
     333           0 :                 char    xname[IFNAMSIZ];
     334             :                 int     error;
     335             : 
     336           0 :                 snprintf(xname, sizeof(xname), "%s%d", "tap", minor(dev));
     337           0 :                 NET_LOCK();
     338           0 :                 error = if_clone_create(xname, rdomain);
     339           0 :                 NET_UNLOCK();
     340           0 :                 if (error != 0)
     341           0 :                         return (error);
     342             : 
     343           0 :                 if ((tp = tap_lookup(minor(dev))) == NULL)
     344           0 :                         return (ENXIO);
     345           0 :                 tp->tun_flags &= ~TUN_STAYUP;
     346           0 :         }
     347             : 
     348           0 :         return (tun_dev_open(tp, flag, mode, p));
     349           0 : }
     350             : 
     351             : int
     352           0 : tun_dev_open(struct tun_softc *tp, int flag, int mode, struct proc *p)
     353             : {
     354             :         struct ifnet *ifp;
     355             : 
     356           0 :         if (tp->tun_flags & TUN_OPEN)
     357           0 :                 return (EBUSY);
     358             : 
     359           0 :         ifp = &tp->tun_if;
     360           0 :         tp->tun_flags |= TUN_OPEN;
     361           0 :         if (flag & FNONBLOCK)
     362           0 :                 tp->tun_flags |= TUN_NBIO;
     363             : 
     364             :         /* automatically mark the interface running on open */
     365           0 :         ifp->if_flags |= IFF_RUNNING;
     366           0 :         tun_link_state(tp);
     367             : 
     368             :         TUNDEBUG(("%s: open\n", ifp->if_xname));
     369           0 :         return (0);
     370           0 : }
     371             : 
     372             : /*
     373             :  * tunclose - close the device; if closing the real device, flush pending
     374             :  *  output and unless STAYUP bring down and destroy the interface.
     375             :  */
     376             : int
     377           0 : tunclose(dev_t dev, int flag, int mode, struct proc *p)
     378             : {
     379             :         struct tun_softc        *tp;
     380             : 
     381           0 :         if ((tp = tun_lookup(minor(dev))) == NULL)
     382           0 :                 return (ENXIO);
     383           0 :         return (tun_dev_close(tp, flag, mode, p));
     384           0 : }
     385             : 
     386             : int
     387           0 : tapclose(dev_t dev, int flag, int mode, struct proc *p)
     388             : {
     389             :         struct tun_softc        *tp;
     390             : 
     391           0 :         if ((tp = tap_lookup(minor(dev))) == NULL)
     392           0 :                 return (ENXIO);
     393           0 :         return (tun_dev_close(tp, flag, mode, p));
     394           0 : }
     395             : 
     396             : int
     397           0 : tun_dev_close(struct tun_softc *tp, int flag, int mode, struct proc *p)
     398             : {
     399             :         int                      error = 0;
     400             :         struct ifnet            *ifp;
     401             : 
     402           0 :         ifp = &tp->tun_if;
     403           0 :         tp->tun_flags &= ~(TUN_OPEN|TUN_NBIO|TUN_ASYNC);
     404             : 
     405             :         /*
     406             :          * junk all pending output
     407             :          */
     408           0 :         ifp->if_flags &= ~IFF_RUNNING;
     409           0 :         tun_link_state(tp);
     410           0 :         IFQ_PURGE(&ifp->if_snd);
     411             : 
     412             :         TUNDEBUG(("%s: closed\n", ifp->if_xname));
     413             : 
     414           0 :         if (!(tp->tun_flags & TUN_STAYUP)) {
     415           0 :                 NET_LOCK();
     416           0 :                 error = if_clone_destroy(ifp->if_xname);
     417           0 :                 NET_UNLOCK();
     418           0 :         } else {
     419           0 :                 tp->tun_pgid = 0;
     420           0 :                 selwakeup(&tp->tun_rsel);
     421             :         }
     422             : 
     423           0 :         return (error);
     424             : }
     425             : 
     426             : int
     427           0 : tun_init(struct tun_softc *tp)
     428             : {
     429           0 :         struct ifnet    *ifp = &tp->tun_if;
     430             :         struct ifaddr   *ifa;
     431             : 
     432             :         TUNDEBUG(("%s: tun_init\n", ifp->if_xname));
     433             : 
     434           0 :         ifp->if_flags |= IFF_UP | IFF_RUNNING;
     435             : 
     436           0 :         tp->tun_flags &= ~(TUN_IASET|TUN_DSTADDR|TUN_BRDADDR);
     437           0 :         TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
     438           0 :                 if (ifa->ifa_addr->sa_family == AF_INET) {
     439             :                         struct sockaddr_in *sin;
     440             : 
     441           0 :                         sin = satosin(ifa->ifa_addr);
     442           0 :                         if (sin && sin->sin_addr.s_addr)
     443           0 :                                 tp->tun_flags |= TUN_IASET;
     444             : 
     445           0 :                         if (ifp->if_flags & IFF_POINTOPOINT) {
     446           0 :                                 sin = satosin(ifa->ifa_dstaddr);
     447           0 :                                 if (sin && sin->sin_addr.s_addr)
     448           0 :                                         tp->tun_flags |= TUN_DSTADDR;
     449             :                         } else
     450           0 :                                 tp->tun_flags &= ~TUN_DSTADDR;
     451             : 
     452           0 :                         if (ifp->if_flags & IFF_BROADCAST) {
     453           0 :                                 sin = satosin(ifa->ifa_broadaddr);
     454           0 :                                 if (sin && sin->sin_addr.s_addr)
     455           0 :                                         tp->tun_flags |= TUN_BRDADDR;
     456             :                         } else
     457           0 :                                 tp->tun_flags &= ~TUN_BRDADDR;
     458           0 :                 }
     459             : #ifdef INET6
     460           0 :                 if (ifa->ifa_addr->sa_family == AF_INET6) {
     461             :                         struct sockaddr_in6 *sin6;
     462             : 
     463           0 :                         sin6 = satosin6(ifa->ifa_addr);
     464           0 :                         if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
     465           0 :                                 tp->tun_flags |= TUN_IASET;
     466             : 
     467           0 :                         if (ifp->if_flags & IFF_POINTOPOINT) {
     468           0 :                                 sin6 = satosin6(ifa->ifa_dstaddr);
     469           0 :                                 if (sin6 &&
     470           0 :                                     !IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
     471           0 :                                         tp->tun_flags |= TUN_DSTADDR;
     472             :                         } else
     473           0 :                                 tp->tun_flags &= ~TUN_DSTADDR;
     474           0 :                 }
     475             : #endif /* INET6 */
     476             :         }
     477             : 
     478           0 :         return (0);
     479             : }
     480             : 
     481             : /*
     482             :  * Process an ioctl request.
     483             :  */
     484             : int
     485           0 : tun_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
     486             : {
     487           0 :         struct tun_softc        *tp = (struct tun_softc *)(ifp->if_softc);
     488           0 :         struct ifreq            *ifr = (struct ifreq *)data;
     489             :         int                      error = 0;
     490             : 
     491           0 :         switch (cmd) {
     492             :         case SIOCSIFADDR:
     493           0 :                 tun_init(tp);
     494           0 :                 break;
     495             :         case SIOCSIFDSTADDR:
     496           0 :                 tun_init(tp);
     497             :                 TUNDEBUG(("%s: destination address set\n", ifp->if_xname));
     498           0 :                 break;
     499             :         case SIOCSIFMTU:
     500           0 :                 if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > TUNMRU)
     501           0 :                         error = EINVAL;
     502             :                 else
     503           0 :                         ifp->if_mtu = ifr->ifr_mtu;
     504             :                 break;
     505             :         case SIOCADDMULTI:
     506             :         case SIOCDELMULTI:
     507             :                 break;
     508             :         case SIOCSIFFLAGS:
     509             :                 break;
     510             :         default:
     511           0 :                 if (tp->tun_flags & TUN_LAYER2)
     512           0 :                         error = ether_ioctl(ifp, &tp->arpcom, cmd, data);
     513             :                 else
     514             :                         error = ENOTTY;
     515             :         }
     516             : 
     517           0 :         return (error);
     518             : }
     519             : 
     520             : /*
     521             :  * tun_output - queue packets from higher level ready to put out.
     522             :  */
     523             : int
     524           0 : tun_output(struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst,
     525             :     struct rtentry *rt)
     526             : {
     527           0 :         struct tun_softc        *tp = ifp->if_softc;
     528             :         int                      error;
     529             :         u_int32_t               *af;
     530             : 
     531           0 :         if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
     532           0 :                 m_freem(m0);
     533           0 :                 return (EHOSTDOWN);
     534             :         }
     535             : 
     536             :         TUNDEBUG(("%s: tun_output\n", ifp->if_xname));
     537             : 
     538           0 :         if ((tp->tun_flags & TUN_READY) != TUN_READY) {
     539             :                 TUNDEBUG(("%s: not ready %#x\n", ifp->if_xname,
     540             :                      tp->tun_flags));
     541           0 :                 m_freem(m0);
     542           0 :                 return (EHOSTDOWN);
     543             :         }
     544             : 
     545           0 :         if (tp->tun_flags & TUN_LAYER2)
     546           0 :                 return (ether_output(ifp, m0, dst, rt));
     547             : 
     548           0 :         M_PREPEND(m0, sizeof(*af), M_DONTWAIT);
     549           0 :         if (m0 == NULL)
     550           0 :                 return (ENOBUFS);
     551           0 :         af = mtod(m0, u_int32_t *);
     552           0 :         *af = htonl(dst->sa_family);
     553             : 
     554             : #if NBPFILTER > 0
     555           0 :         if (ifp->if_bpf)
     556           0 :                 bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
     557             : #endif
     558             : #ifdef PIPEX
     559           0 :         if (pipex_enable && (m0 = pipex_output(m0, dst->sa_family,
     560           0 :             sizeof(u_int32_t), &tp->pipex_iface)) == NULL) {
     561           0 :                 return (0);
     562             :         }
     563             : #endif
     564             : 
     565           0 :         error = if_enqueue(ifp, m0);
     566             : 
     567           0 :         if (error) {
     568           0 :                 ifp->if_collisions++;
     569           0 :                 return (error);
     570             :         }
     571             : 
     572           0 :         tun_wakeup(tp);
     573           0 :         return (0);
     574           0 : }
     575             : 
     576             : void
     577           0 : tun_wakeup(struct tun_softc *tp)
     578             : {
     579           0 :         if (tp->tun_flags & TUN_RWAIT) {
     580           0 :                 tp->tun_flags &= ~TUN_RWAIT;
     581           0 :                 wakeup((caddr_t)tp);
     582           0 :         }
     583           0 :         if (tp->tun_flags & TUN_ASYNC && tp->tun_pgid)
     584           0 :                 csignal(tp->tun_pgid, SIGIO,
     585           0 :                     tp->tun_siguid, tp->tun_sigeuid);
     586           0 :         selwakeup(&tp->tun_rsel);
     587           0 : }
     588             : 
     589             : /*
     590             :  * the cdevsw interface is now pretty minimal.
     591             :  */
     592             : int
     593           0 : tunioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
     594             : {
     595             :         struct tun_softc *tp;
     596             : 
     597           0 :         if ((tp = tun_lookup(minor(dev))) == NULL)
     598           0 :                 return (ENXIO);
     599           0 :         return (tun_dev_ioctl(tp, cmd, data, flag, p));
     600           0 : }
     601             : 
     602             : int
     603           0 : tapioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
     604             : {
     605             :         struct tun_softc *tp;
     606             : 
     607           0 :         if ((tp = tap_lookup(minor(dev))) == NULL)
     608           0 :                 return (ENXIO);
     609           0 :         return (tun_dev_ioctl(tp, cmd, data, flag, p));
     610           0 : }
     611             : 
     612             : int
     613           0 : tun_dev_ioctl(struct tun_softc *tp, u_long cmd, caddr_t data, int flag,
     614             :     struct proc *p)
     615             : {
     616             :         struct tuninfo          *tunp;
     617             : 
     618           0 :         switch (cmd) {
     619             :         case TUNSIFINFO:
     620           0 :                 tunp = (struct tuninfo *)data;
     621           0 :                 if (tunp->mtu < ETHERMIN || tunp->mtu > TUNMRU)
     622           0 :                         return (EINVAL);
     623           0 :                 tp->tun_if.if_mtu = tunp->mtu;
     624           0 :                 tp->tun_if.if_type = tunp->type;
     625           0 :                 tp->tun_if.if_flags =
     626           0 :                     (tunp->flags & TUN_IFF_FLAGS) |
     627           0 :                     (tp->tun_if.if_flags & ~TUN_IFF_FLAGS);
     628           0 :                 tp->tun_if.if_baudrate = tunp->baudrate;
     629           0 :                 break;
     630             :         case TUNGIFINFO:
     631           0 :                 tunp = (struct tuninfo *)data;
     632           0 :                 tunp->mtu = tp->tun_if.if_mtu;
     633           0 :                 tunp->type = tp->tun_if.if_type;
     634           0 :                 tunp->flags = tp->tun_if.if_flags;
     635           0 :                 tunp->baudrate = tp->tun_if.if_baudrate;
     636           0 :                 break;
     637             : #ifdef TUN_DEBUG
     638             :         case TUNSDEBUG:
     639             :                 tundebug = *(int *)data;
     640             :                 break;
     641             :         case TUNGDEBUG:
     642             :                 *(int *)data = tundebug;
     643             :                 break;
     644             : #endif
     645             :         case TUNSIFMODE:
     646           0 :                 switch (*(int *)data & (IFF_POINTOPOINT|IFF_BROADCAST)) {
     647             :                 case IFF_POINTOPOINT:
     648             :                 case IFF_BROADCAST:
     649           0 :                         tp->tun_if.if_flags &= ~TUN_IFF_FLAGS;
     650           0 :                         tp->tun_if.if_flags |= *(int *)data & TUN_IFF_FLAGS;
     651             :                         break;
     652             :                 default:
     653           0 :                         return (EINVAL);
     654             :                 }
     655           0 :                 break;
     656             : 
     657             :         case FIONBIO:
     658           0 :                 if (*(int *)data)
     659           0 :                         tp->tun_flags |= TUN_NBIO;
     660             :                 else
     661           0 :                         tp->tun_flags &= ~TUN_NBIO;
     662             :                 break;
     663             :         case FIOASYNC:
     664           0 :                 if (*(int *)data)
     665           0 :                         tp->tun_flags |= TUN_ASYNC;
     666             :                 else
     667           0 :                         tp->tun_flags &= ~TUN_ASYNC;
     668             :                 break;
     669             :         case FIONREAD:
     670           0 :                 *(int *)data = ifq_empty(&tp->tun_if.if_snd) ?
     671           0 :                     0 : tp->tun_if.if_mtu;
     672           0 :                 break;
     673             :         case TIOCSPGRP:
     674           0 :                 tp->tun_pgid = *(int *)data;
     675           0 :                 tp->tun_siguid = p->p_ucred->cr_ruid;
     676           0 :                 tp->tun_sigeuid = p->p_ucred->cr_uid;
     677           0 :                 break;
     678             :         case TIOCGPGRP:
     679           0 :                 *(int *)data = tp->tun_pgid;
     680           0 :                 break;
     681             :         case SIOCGIFADDR:
     682           0 :                 if (!(tp->tun_flags & TUN_LAYER2))
     683           0 :                         return (EINVAL);
     684           0 :                 bcopy(tp->arpcom.ac_enaddr, data,
     685             :                     sizeof(tp->arpcom.ac_enaddr));
     686           0 :                 break;
     687             : 
     688             :         case SIOCSIFADDR:
     689           0 :                 if (!(tp->tun_flags & TUN_LAYER2))
     690           0 :                         return (EINVAL);
     691           0 :                 bcopy(data, tp->arpcom.ac_enaddr,
     692             :                     sizeof(tp->arpcom.ac_enaddr));
     693           0 :                 break;
     694             :         default:
     695             : #ifdef PIPEX
     696           0 :                 if (!(tp->tun_flags & TUN_LAYER2)) {
     697             :                         int ret;
     698           0 :                         ret = pipex_ioctl(&tp->pipex_iface, cmd, data);
     699             :                         return (ret);
     700             :                 }
     701             : #endif
     702           0 :                 return (ENOTTY);
     703             :         }
     704           0 :         return (0);
     705           0 : }
     706             : 
     707             : /*
     708             :  * The cdevsw read interface - reads a packet at a time, or at
     709             :  * least as much of a packet as can be read.
     710             :  */
     711             : int
     712           0 : tunread(dev_t dev, struct uio *uio, int ioflag)
     713             : {
     714             :         struct tun_softc *tp;
     715             : 
     716           0 :         if ((tp = tun_lookup(minor(dev))) == NULL)
     717           0 :                 return (ENXIO);
     718           0 :         return (tun_dev_read(tp, uio, ioflag));
     719           0 : }
     720             : 
     721             : int
     722           0 : tapread(dev_t dev, struct uio *uio, int ioflag)
     723             : {
     724             :         struct tun_softc *tp;
     725             : 
     726           0 :         if ((tp = tap_lookup(minor(dev))) == NULL)
     727           0 :                 return (ENXIO);
     728           0 :         return (tun_dev_read(tp, uio, ioflag));
     729           0 : }
     730             : 
     731             : int
     732           0 : tun_dev_read(struct tun_softc *tp, struct uio *uio, int ioflag)
     733             : {
     734           0 :         struct ifnet            *ifp = &tp->tun_if;
     735             :         struct mbuf             *m, *m0;
     736             :         unsigned int             ifidx;
     737             :         int                      error = 0;
     738             :         size_t                   len;
     739             : 
     740           0 :         if ((tp->tun_flags & TUN_READY) != TUN_READY)
     741           0 :                 return (EHOSTDOWN);
     742             : 
     743           0 :         ifidx = ifp->if_index;
     744           0 :         tp->tun_flags &= ~TUN_RWAIT;
     745             : 
     746           0 :         do {
     747             :                 struct ifnet *ifp1;
     748             :                 int destroyed;
     749             : 
     750           0 :                 while ((tp->tun_flags & TUN_READY) != TUN_READY) {
     751           0 :                         if ((error = tsleep((caddr_t)tp,
     752           0 :                             (PZERO + 1)|PCATCH, "tunread", 0)) != 0)
     753           0 :                                 return (error);
     754             :                         /* Make sure the interface still exists. */
     755           0 :                         ifp1 = if_get(ifidx);
     756           0 :                         destroyed = (ifp1 == NULL);
     757           0 :                         if_put(ifp1);
     758           0 :                         if (destroyed)
     759           0 :                                 return (ENXIO);
     760             :                 }
     761           0 :                 IFQ_DEQUEUE(&ifp->if_snd, m0);
     762           0 :                 if (m0 == NULL) {
     763           0 :                         if (tp->tun_flags & TUN_NBIO && ioflag & IO_NDELAY)
     764           0 :                                 return (EWOULDBLOCK);
     765           0 :                         tp->tun_flags |= TUN_RWAIT;
     766           0 :                         if ((error = tsleep((caddr_t)tp,
     767           0 :                             (PZERO + 1)|PCATCH, "tunread", 0)) != 0)
     768           0 :                                 return (error);
     769             :                         /* Make sure the interface still exists. */
     770           0 :                         ifp1 = if_get(ifidx);
     771           0 :                         destroyed = (ifp1 == NULL);
     772           0 :                         if_put(ifp1);
     773           0 :                         if (destroyed)
     774           0 :                                 return (ENXIO);
     775             :                 }
     776           0 :         } while (m0 == NULL);
     777             : 
     778           0 :         if (tp->tun_flags & TUN_LAYER2) {
     779             : #if NBPFILTER > 0
     780           0 :                 if (ifp->if_bpf)
     781           0 :                         bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
     782             : #endif
     783             :         }
     784             : 
     785           0 :         while (m0 != NULL && uio->uio_resid > 0 && error == 0) {
     786           0 :                 len = ulmin(uio->uio_resid, m0->m_len);
     787           0 :                 if (len != 0)
     788           0 :                         error = uiomove(mtod(m0, caddr_t), len, uio);
     789           0 :                 m = m_free(m0);
     790             :                 m0 = m;
     791             :         }
     792             : 
     793           0 :         if (m0 != NULL) {
     794             :                 TUNDEBUG(("Dropping mbuf\n"));
     795           0 :                 m_freem(m0);
     796           0 :         }
     797           0 :         if (error)
     798           0 :                 ifp->if_oerrors++;
     799             : 
     800           0 :         return (error);
     801           0 : }
     802             : 
     803             : /*
     804             :  * the cdevsw write interface - an atomic write is a packet - or else!
     805             :  */
     806             : int
     807           0 : tunwrite(dev_t dev, struct uio *uio, int ioflag)
     808             : {
     809             :         struct tun_softc *tp;
     810             : 
     811           0 :         if ((tp = tun_lookup(minor(dev))) == NULL)
     812           0 :                 return (ENXIO);
     813           0 :         return (tun_dev_write(tp, uio, ioflag));
     814           0 : }
     815             : 
     816             : int
     817           0 : tapwrite(dev_t dev, struct uio *uio, int ioflag)
     818             : {
     819             :         struct tun_softc *tp;
     820             : 
     821           0 :         if ((tp = tap_lookup(minor(dev))) == NULL)
     822           0 :                 return (ENXIO);
     823           0 :         return (tun_dev_write(tp, uio, ioflag));
     824           0 : }
     825             : 
     826             : int
     827           0 : tun_dev_write(struct tun_softc *tp, struct uio *uio, int ioflag)
     828             : {
     829             :         struct ifnet            *ifp;
     830             :         u_int32_t               *th;
     831           0 :         struct mbuf             *top, **mp, *m;
     832             :         int                     error = 0, tlen;
     833             :         size_t                  mlen;
     834             : 
     835           0 :         ifp = &tp->tun_if;
     836             :         TUNDEBUG(("%s: tunwrite\n", ifp->if_xname));
     837             : 
     838           0 :         if (uio->uio_resid == 0 || uio->uio_resid > ifp->if_mtu +
     839           0 :             (tp->tun_flags & TUN_LAYER2 ? ETHER_HDR_LEN : sizeof(*th))) {
     840             :                 TUNDEBUG(("%s: len=%d!\n", ifp->if_xname, uio->uio_resid));
     841           0 :                 return (EMSGSIZE);
     842             :         }
     843           0 :         tlen = uio->uio_resid;
     844             : 
     845             :         /* get a header mbuf */
     846           0 :         MGETHDR(m, M_DONTWAIT, MT_DATA);
     847           0 :         if (m == NULL)
     848           0 :                 return (ENOBUFS);
     849             :         mlen = MHLEN;
     850           0 :         if (uio->uio_resid >= MINCLSIZE) {
     851           0 :                 MCLGET(m, M_DONTWAIT);
     852           0 :                 if (!(m->m_flags & M_EXT)) {
     853           0 :                         m_free(m);
     854           0 :                         return (ENOBUFS);
     855             :                 }
     856             :                 mlen = MCLBYTES;
     857           0 :         }
     858             : 
     859           0 :         top = NULL;
     860             :         mp = &top;
     861           0 :         if (tp->tun_flags & TUN_LAYER2) {
     862             :                 /*
     863             :                  * Pad so that IP header is correctly aligned
     864             :                  * this is necessary for all strict aligned architectures.
     865             :                  */
     866           0 :                 mlen -= ETHER_ALIGN;
     867           0 :                 m->m_data += ETHER_ALIGN;
     868           0 :         }
     869           0 :         while (error == 0 && uio->uio_resid > 0) {
     870           0 :                 m->m_len = ulmin(mlen, uio->uio_resid);
     871           0 :                 error = uiomove(mtod (m, caddr_t), m->m_len, uio);
     872           0 :                 *mp = m;
     873           0 :                 mp = &m->m_next;
     874           0 :                 if (error == 0 && uio->uio_resid > 0) {
     875           0 :                         MGET(m, M_DONTWAIT, MT_DATA);
     876           0 :                         if (m == NULL) {
     877             :                                 error = ENOBUFS;
     878           0 :                                 break;
     879             :                         }
     880             :                         mlen = MLEN;
     881           0 :                         if (uio->uio_resid >= MINCLSIZE) {
     882           0 :                                 MCLGET(m, M_DONTWAIT);
     883           0 :                                 if (!(m->m_flags & M_EXT)) {
     884             :                                         error = ENOBUFS;
     885           0 :                                         m_free(m);
     886           0 :                                         break;
     887             :                                 }
     888             :                                 mlen = MCLBYTES;
     889           0 :                         }
     890             :                 }
     891             :         }
     892           0 :         if (error) {
     893           0 :                 m_freem(top);
     894           0 :                 ifp->if_ierrors++;
     895           0 :                 return (error);
     896             :         }
     897             : 
     898           0 :         top->m_pkthdr.len = tlen;
     899             : 
     900           0 :         if (tp->tun_flags & TUN_LAYER2) {
     901           0 :                 struct mbuf_list ml = MBUF_LIST_INITIALIZER();
     902             : 
     903           0 :                 ml_enqueue(&ml, top);
     904           0 :                 if_input(ifp, &ml);
     905             :                 return (0);
     906           0 :         }
     907             : 
     908             : #if NBPFILTER > 0
     909           0 :         if (ifp->if_bpf) {
     910           0 :                 bpf_mtap(ifp->if_bpf, top, BPF_DIRECTION_IN);
     911           0 :         }
     912             : #endif
     913             : 
     914           0 :         th = mtod(top, u_int32_t *);
     915             :         /* strip the tunnel header */
     916           0 :         top->m_data += sizeof(*th);
     917           0 :         top->m_len  -= sizeof(*th);
     918           0 :         top->m_pkthdr.len -= sizeof(*th);
     919           0 :         top->m_pkthdr.ph_rtableid = ifp->if_rdomain;
     920           0 :         top->m_pkthdr.ph_ifidx = ifp->if_index;
     921             : 
     922           0 :         ifp->if_ipackets++;
     923           0 :         ifp->if_ibytes += top->m_pkthdr.len;
     924             : 
     925           0 :         NET_LOCK();
     926             : 
     927           0 :         switch (ntohl(*th)) {
     928             :         case AF_INET:
     929           0 :                 ipv4_input(ifp, top);
     930           0 :                 break;
     931             : #ifdef INET6
     932             :         case AF_INET6:
     933           0 :                 ipv6_input(ifp, top);
     934           0 :                 break;
     935             : #endif
     936             :         default:
     937           0 :                 m_freem(top);
     938             :                 error = EAFNOSUPPORT;
     939           0 :                 break;
     940             :         }
     941             : 
     942           0 :         NET_UNLOCK();
     943             : 
     944           0 :         return (error);
     945           0 : }
     946             : 
     947             : /*
     948             :  * tunpoll - the poll interface, this is only useful on reads
     949             :  * really. The write detect always returns true, write never blocks
     950             :  * anyway, it either accepts the packet or drops it.
     951             :  */
     952             : int
     953           0 : tunpoll(dev_t dev, int events, struct proc *p)
     954             : {
     955             :         struct tun_softc *tp;
     956             : 
     957           0 :         if ((tp = tun_lookup(minor(dev))) == NULL)
     958           0 :                 return (POLLERR);
     959           0 :         return (tun_dev_poll(tp, events, p));
     960           0 : }
     961             : 
     962             : int
     963           0 : tappoll(dev_t dev, int events, struct proc *p)
     964             : {
     965             :         struct tun_softc *tp;
     966             : 
     967           0 :         if ((tp = tap_lookup(minor(dev))) == NULL)
     968           0 :                 return (POLLERR);
     969           0 :         return (tun_dev_poll(tp, events, p));
     970           0 : }
     971             : 
     972             : int
     973           0 : tun_dev_poll(struct tun_softc *tp, int events, struct proc *p)
     974             : {
     975             :         int                      revents;
     976             :         struct ifnet            *ifp;
     977             :         unsigned int             len;
     978             : 
     979           0 :         ifp = &tp->tun_if;
     980             :         revents = 0;
     981             :         TUNDEBUG(("%s: tunpoll\n", ifp->if_xname));
     982             : 
     983           0 :         if (events & (POLLIN | POLLRDNORM)) {
     984           0 :                 len = IFQ_LEN(&ifp->if_snd);
     985           0 :                 if (len > 0) {
     986             :                         TUNDEBUG(("%s: tunselect q=%d\n", ifp->if_xname, len));
     987             :                         revents |= events & (POLLIN | POLLRDNORM);
     988           0 :                 } else {
     989             :                         TUNDEBUG(("%s: tunpoll waiting\n", ifp->if_xname));
     990           0 :                         selrecord(p, &tp->tun_rsel);
     991             :                 }
     992             :         }
     993           0 :         if (events & (POLLOUT | POLLWRNORM))
     994           0 :                 revents |= events & (POLLOUT | POLLWRNORM);
     995           0 :         return (revents);
     996             : }
     997             : 
     998             : /*
     999             :  * kqueue(2) support.
    1000             :  *
    1001             :  * The tun driver uses an array of tun_softc's based on the minor number
    1002             :  * of the device.  kn->kn_hook gets set to the specific tun_softc.
    1003             :  *
    1004             :  * filt_tunread() sets kn->kn_data to the iface qsize
    1005             :  * filt_tunwrite() sets kn->kn_data to the MTU size
    1006             :  */
    1007             : int
    1008           0 : tunkqfilter(dev_t dev, struct knote *kn)
    1009             : {
    1010             :         struct tun_softc *tp;
    1011             : 
    1012           0 :         if ((tp = tun_lookup(minor(dev))) == NULL)
    1013           0 :                 return (ENXIO);
    1014           0 :         return (tun_dev_kqfilter(tp, kn));
    1015           0 : }
    1016             : 
    1017             : int
    1018           0 : tapkqfilter(dev_t dev, struct knote *kn)
    1019             : {
    1020             :         struct tun_softc *tp;
    1021             : 
    1022           0 :         if ((tp = tap_lookup(minor(dev))) == NULL)
    1023           0 :                 return (ENXIO);
    1024           0 :         return (tun_dev_kqfilter(tp, kn));
    1025           0 : }
    1026             : 
    1027             : int
    1028           0 : tun_dev_kqfilter(struct tun_softc *tp, struct knote *kn)
    1029             : {
    1030             :         int                      s;
    1031             :         struct klist            *klist;
    1032             :         struct ifnet            *ifp;
    1033             : 
    1034           0 :         ifp = &tp->tun_if;
    1035             :         TUNDEBUG(("%s: tunkqfilter\n", ifp->if_xname));
    1036             : 
    1037           0 :         switch (kn->kn_filter) {
    1038             :                 case EVFILT_READ:
    1039           0 :                         klist = &tp->tun_rsel.si_note;
    1040           0 :                         kn->kn_fop = &tunread_filtops;
    1041           0 :                         break;
    1042             :                 case EVFILT_WRITE:
    1043           0 :                         klist = &tp->tun_wsel.si_note;
    1044           0 :                         kn->kn_fop = &tunwrite_filtops;
    1045           0 :                         break;
    1046             :                 default:
    1047           0 :                         return (EINVAL);
    1048             :         }
    1049             : 
    1050           0 :         kn->kn_hook = (caddr_t)tp;
    1051             : 
    1052           0 :         s = splhigh();
    1053           0 :         SLIST_INSERT_HEAD(klist, kn, kn_selnext);
    1054           0 :         splx(s);
    1055             : 
    1056           0 :         return (0);
    1057           0 : }
    1058             : 
    1059             : void
    1060           0 : filt_tunrdetach(struct knote *kn)
    1061             : {
    1062             :         int                      s;
    1063             :         struct tun_softc        *tp;
    1064             : 
    1065           0 :         tp = (struct tun_softc *)kn->kn_hook;
    1066           0 :         s = splhigh();
    1067           0 :         if (!(kn->kn_status & KN_DETACHED))
    1068           0 :                 SLIST_REMOVE(&tp->tun_rsel.si_note, kn, knote, kn_selnext);
    1069           0 :         splx(s);
    1070           0 : }
    1071             : 
    1072             : int
    1073           0 : filt_tunread(struct knote *kn, long hint)
    1074             : {
    1075             :         struct tun_softc        *tp;
    1076             :         struct ifnet            *ifp;
    1077             :         unsigned int             len;
    1078             : 
    1079           0 :         if (kn->kn_status & KN_DETACHED) {
    1080           0 :                 kn->kn_data = 0;
    1081           0 :                 return (1);
    1082             :         }
    1083             : 
    1084           0 :         tp = (struct tun_softc *)kn->kn_hook;
    1085           0 :         ifp = &tp->tun_if;
    1086             : 
    1087           0 :         len = IFQ_LEN(&ifp->if_snd);
    1088           0 :         if (len > 0) {
    1089           0 :                 kn->kn_data = len;
    1090             : 
    1091             :                 TUNDEBUG(("%s: tunkqread q=%d\n", ifp->if_xname,
    1092             :                     IFQ_LEN(&ifp->if_snd)));
    1093           0 :                 return (1);
    1094             :         }
    1095             :         TUNDEBUG(("%s: tunkqread waiting\n", ifp->if_xname));
    1096           0 :         return (0);
    1097           0 : }
    1098             : 
    1099             : void
    1100           0 : filt_tunwdetach(struct knote *kn)
    1101             : {
    1102             :         int                      s;
    1103             :         struct tun_softc        *tp;
    1104             : 
    1105           0 :         tp = (struct tun_softc *)kn->kn_hook;
    1106           0 :         s = splhigh();
    1107           0 :         if (!(kn->kn_status & KN_DETACHED))
    1108           0 :                 SLIST_REMOVE(&tp->tun_wsel.si_note, kn, knote, kn_selnext);
    1109           0 :         splx(s);
    1110           0 : }
    1111             : 
    1112             : int
    1113           0 : filt_tunwrite(struct knote *kn, long hint)
    1114             : {
    1115             :         struct tun_softc        *tp;
    1116             :         struct ifnet            *ifp;
    1117             : 
    1118           0 :         if (kn->kn_status & KN_DETACHED) {
    1119           0 :                 kn->kn_data = 0;
    1120           0 :                 return (1);
    1121             :         }
    1122             : 
    1123           0 :         tp = (struct tun_softc *)kn->kn_hook;
    1124           0 :         ifp = &tp->tun_if;
    1125             : 
    1126           0 :         kn->kn_data = ifp->if_mtu;
    1127             : 
    1128           0 :         return (1);
    1129           0 : }
    1130             : 
    1131             : void
    1132           0 : tun_start(struct ifnet *ifp)
    1133             : {
    1134           0 :         struct tun_softc        *tp = ifp->if_softc;
    1135             : 
    1136           0 :         splassert(IPL_NET);
    1137             : 
    1138           0 :         if (IFQ_LEN(&ifp->if_snd))
    1139           0 :                 tun_wakeup(tp);
    1140           0 : }
    1141             : 
    1142             : void
    1143           0 : tun_link_state(struct tun_softc *tp)
    1144             : {
    1145           0 :         struct ifnet *ifp = &tp->tun_if;
    1146             :         int link_state = LINK_STATE_DOWN;
    1147             : 
    1148           0 :         if (tp->tun_flags & TUN_OPEN) {
    1149           0 :                 if (tp->tun_flags & TUN_LAYER2)
    1150           0 :                         link_state = LINK_STATE_FULL_DUPLEX;
    1151             :                 else
    1152             :                         link_state = LINK_STATE_UP;
    1153             :         }
    1154           0 :         if (ifp->if_link_state != link_state) {
    1155           0 :                 ifp->if_link_state = link_state;
    1156           0 :                 if_link_state_change(ifp);
    1157           0 :         }
    1158           0 : }

Generated by: LCOV version 1.13