[BACK]Return to if_tun.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / net

Annotation of src/sys/net/if_tun.c, Revision 1.140

1.140   ! maya        1: /*     $NetBSD: if_tun.c,v 1.139 2017/05/24 06:52:14 pgoyette Exp $    */
1.14      cgd         2:
1.1       cgd         3: /*
1.8       deraadt     4:  * Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk>
                      5:  * Nottingham University 1987.
1.1       cgd         6:  *
                      7:  * This source may be freely distributed, however I would be interested
                      8:  * in any changes that are made.
1.6       deraadt     9:  *
1.1       cgd        10:  * This driver takes packets off the IP i/f and hands them up to a
1.21      scottr     11:  * user process to have its wicked way with. This driver has its
1.1       cgd        12:  * roots in a similar driver written by Phil Cockcroft (formerly) at
1.27      mycroft    13:  * UCL. This driver is based much more on read/write/poll mode of
1.1       cgd        14:  * operation though.
                     15:  */
1.48      lukem      16:
1.136     skrll      17: /*
                     18:  * tun - tunnel software network interface.
                     19:  */
                     20:
1.48      lukem      21: #include <sys/cdefs.h>
1.140   ! maya       22: __KERNEL_RCSID(0, "$NetBSD: if_tun.c,v 1.139 2017/05/24 06:52:14 pgoyette Exp $");
1.33      jonathan   23:
1.123     pooka      24: #ifdef _KERNEL_OPT
1.33      jonathan   25: #include "opt_inet.h"
1.123     pooka      26: #endif
1.8       deraadt    27:
1.6       deraadt    28: #include <sys/param.h>
1.136     skrll      29:
1.6       deraadt    30: #include <sys/buf.h>
1.135     skrll      31: #include <sys/conf.h>
                     32: #include <sys/cpu.h>
                     33: #include <sys/device.h>
1.8       deraadt    34: #include <sys/file.h>
1.135     skrll      35: #include <sys/ioctl.h>
1.89      elad       36: #include <sys/kauth.h>
1.136     skrll      37: #include <sys/kmem.h>
                     38: #include <sys/lwp.h>
1.135     skrll      39: #include <sys/mbuf.h>
                     40: #include <sys/module.h>
1.115     rmind      41: #include <sys/mutex.h>
1.135     skrll      42: #include <sys/poll.h>
                     43: #include <sys/select.h>
                     44: #include <sys/signalvar.h>
                     45: #include <sys/socket.h>
1.6       deraadt    46:
1.135     skrll      47: #include <net/bpf.h>
1.6       deraadt    48: #include <net/if.h>
1.69      tron       49: #include <net/if_types.h>
1.6       deraadt    50: #include <net/route.h>
1.1       cgd        51:
                     52: #ifdef INET
1.6       deraadt    53: #include <netinet/in.h>
                     54: #include <netinet/in_systm.h>
                     55: #include <netinet/in_var.h>
                     56: #include <netinet/ip.h>
1.30      is         57: #include <netinet/if_inarp.h>
1.1       cgd        58: #endif
                     59:
1.8       deraadt    60: #include <net/if_tun.h>
                     61:
1.122     christos   62: #include "ioconf.h"
                     63:
1.29      christos   64: #define TUNDEBUG       if (tundebug) printf
1.6       deraadt    65: int    tundebug = 0;
1.1       cgd        66:
1.6       deraadt    67: extern int ifqmaxlen;
1.78      thorpej    68:
                     69: static LIST_HEAD(, tun_softc) tun_softc_list;
                     70: static LIST_HEAD(, tun_softc) tunz_softc_list;
1.117     skrll      71: static kmutex_t tun_softc_lock;
1.6       deraadt    72:
1.97      christos   73: static int     tun_ioctl(struct ifnet *, u_long, void *);
1.96      dyoung     74: static int     tun_output(struct ifnet *, struct mbuf *,
1.125     ozaki-r    75:                        const struct sockaddr *, const struct rtentry *rt);
1.78      thorpej    76: static int     tun_clone_create(struct if_clone *, int);
                     77: static int     tun_clone_destroy(struct ifnet *);
1.6       deraadt    78:
1.78      thorpej    79: static struct if_clone tun_cloner =
1.46      atatat     80:     IF_CLONE_INITIALIZER("tun", tun_clone_create, tun_clone_destroy);
                     81:
1.78      thorpej    82: static void tunattach0(struct tun_softc *);
1.132     ozaki-r    83: static void tun_enable(struct tun_softc *, const struct ifaddr *);
1.106     ad         84: static void tun_i_softintr(void *);
                     85: static void tun_o_softintr(void *);
1.50      itojun     86: #ifdef ALTQ
1.78      thorpej    87: static void tunstart(struct ifnet *);
1.50      itojun     88: #endif
1.78      thorpej    89: static struct tun_softc *tun_find_unit(dev_t);
                     90: static struct tun_softc *tun_find_zunit(int);
1.53      gehenna    91:
1.78      thorpej    92: static dev_type_open(tunopen);
                     93: static dev_type_close(tunclose);
                     94: static dev_type_read(tunread);
                     95: static dev_type_write(tunwrite);
                     96: static dev_type_ioctl(tunioctl);
                     97: static dev_type_poll(tunpoll);
                     98: static dev_type_kqfilter(tunkqfilter);
1.53      gehenna    99:
                    100: const struct cdevsw tun_cdevsw = {
1.116     dholland  101:        .d_open = tunopen,
                    102:        .d_close = tunclose,
                    103:        .d_read = tunread,
                    104:        .d_write = tunwrite,
                    105:        .d_ioctl = tunioctl,
                    106:        .d_stop = nostop,
                    107:        .d_tty = notty,
                    108:        .d_poll = tunpoll,
                    109:        .d_mmap = nommap,
                    110:        .d_kqfilter = tunkqfilter,
1.120     dholland  111:        .d_discard = nodiscard,
1.136     skrll     112:        .d_flag = D_OTHER | D_MPSAFE
1.53      gehenna   113: };
1.6       deraadt   114:
1.130     ozaki-r   115: #ifdef _MODULE
                    116: devmajor_t tun_bmajor = -1, tun_cmajor = -1;
                    117: #endif
                    118:
1.8       deraadt   119: void
1.94      christos  120: tunattach(int unused)
1.8       deraadt   121: {
1.46      atatat    122:
1.128     christos  123:        /*
                    124:         * Nothing to do here, initialization is handled by the
1.129     ozaki-r   125:         * module initialization code in tuninit() below).
1.128     christos  126:         */
                    127: }
                    128:
                    129: static void
                    130: tuninit(void)
                    131: {
                    132:
1.117     skrll     133:        mutex_init(&tun_softc_lock, MUTEX_DEFAULT, IPL_NET);
1.46      atatat    134:        LIST_INIT(&tun_softc_list);
1.70      pk        135:        LIST_INIT(&tunz_softc_list);
1.46      atatat    136:        if_clone_attach(&tun_cloner);
1.130     ozaki-r   137: #ifdef _MODULE
                    138:        devsw_attach("tun", NULL, &tun_bmajor, &tun_cdevsw, &tun_cmajor);
                    139: #endif
1.46      atatat    140: }
                    141:
1.128     christos  142: static int
                    143: tundetach(void)
                    144: {
                    145:        int error = 0;
                    146:
                    147:        if (!LIST_EMPTY(&tun_softc_list) || !LIST_EMPTY(&tunz_softc_list))
                    148:                error = EBUSY;
                    149:
1.130     ozaki-r   150: #ifdef _MODULE
                    151:        if (error == 0)
                    152:                error = devsw_detach(NULL, &tun_cdevsw);
                    153: #endif
1.128     christos  154:        if (error == 0) {
                    155:                if_clone_detach(&tun_cloner);
                    156:                mutex_destroy(&tun_softc_lock);
                    157:        }
                    158:
                    159:        return error;
                    160: }
                    161:
1.70      pk        162: /*
                    163:  * Find driver instance from dev_t.
                    164:  * Returns with tp locked (if found).
                    165:  */
                    166: static struct tun_softc *
1.78      thorpej   167: tun_find_unit(dev_t dev)
1.70      pk        168: {
                    169:        struct tun_softc *tp;
                    170:        int unit = minor(dev);
                    171:
1.117     skrll     172:        mutex_enter(&tun_softc_lock);
1.70      pk        173:        LIST_FOREACH(tp, &tun_softc_list, tun_list)
                    174:                if (unit == tp->tun_unit)
                    175:                        break;
                    176:        if (tp)
1.115     rmind     177:                mutex_enter(&tp->tun_lock);
1.117     skrll     178:        mutex_exit(&tun_softc_lock);
1.70      pk        179:
1.135     skrll     180:        return tp;
1.70      pk        181: }
                    182:
                    183: /*
                    184:  * Find zombie driver instance by unit number.
                    185:  * Remove tp from list and return it unlocked (if found).
                    186:  */
                    187: static struct tun_softc *
1.78      thorpej   188: tun_find_zunit(int unit)
1.70      pk        189: {
                    190:        struct tun_softc *tp;
                    191:
1.117     skrll     192:        mutex_enter(&tun_softc_lock);
1.70      pk        193:        LIST_FOREACH(tp, &tunz_softc_list, tun_list)
                    194:                if (unit == tp->tun_unit)
                    195:                        break;
                    196:        if (tp)
                    197:                LIST_REMOVE(tp, tun_list);
1.117     skrll     198:        mutex_exit(&tun_softc_lock);
1.137     skrll     199:        KASSERTMSG(!tp || (tp->tun_flags & (TUN_INITED|TUN_OPEN)) == TUN_OPEN,
1.136     skrll     200:            "tun%d: inconsistent flags: %x", unit, tp->tun_flags);
1.70      pk        201:
1.135     skrll     202:        return tp;
1.70      pk        203: }
                    204:
1.78      thorpej   205: static int
                    206: tun_clone_create(struct if_clone *ifc, int unit)
1.46      atatat    207: {
1.70      pk        208:        struct tun_softc *tp;
1.46      atatat    209:
1.70      pk        210:        if ((tp = tun_find_zunit(unit)) == NULL) {
1.136     skrll     211:                tp = kmem_zalloc(sizeof(*tp), KM_SLEEP);
1.46      atatat    212:
1.70      pk        213:                tp->tun_unit = unit;
1.115     rmind     214:                mutex_init(&tp->tun_lock, MUTEX_DEFAULT, IPL_NET);
1.136     skrll     215:                cv_init(&tp->tun_cv, "tunread");
1.104     rmind     216:                selinit(&tp->tun_rsel);
                    217:                selinit(&tp->tun_wsel);
1.70      pk        218:        } else {
                    219:                /* Revive tunnel instance; clear ifp part */
                    220:                (void)memset(&tp->tun_if, 0, sizeof(struct ifnet));
                    221:        }
1.46      atatat    222:
1.107     christos  223:        if_initname(&tp->tun_if, ifc->ifc_name, unit);
1.70      pk        224:        tunattach0(tp);
                    225:        tp->tun_flags |= TUN_INITED;
1.106     ad        226:        tp->tun_osih = softint_establish(SOFTINT_CLOCK, tun_o_softintr, tp);
                    227:        tp->tun_isih = softint_establish(SOFTINT_CLOCK, tun_i_softintr, tp);
1.46      atatat    228:
1.117     skrll     229:        mutex_enter(&tun_softc_lock);
1.70      pk        230:        LIST_INSERT_HEAD(&tun_softc_list, tp, tun_list);
1.117     skrll     231:        mutex_exit(&tun_softc_lock);
1.46      atatat    232:
1.135     skrll     233:        return 0;
1.46      atatat    234: }
                    235:
1.78      thorpej   236: static void
                    237: tunattach0(struct tun_softc *tp)
1.46      atatat    238: {
1.70      pk        239:        struct ifnet *ifp;
1.46      atatat    240:
1.70      pk        241:        ifp = &tp->tun_if;
                    242:        ifp->if_softc = tp;
1.46      atatat    243:        ifp->if_mtu = TUNMTU;
                    244:        ifp->if_ioctl = tun_ioctl;
                    245:        ifp->if_output = tun_output;
1.50      itojun    246: #ifdef ALTQ
                    247:        ifp->if_start = tunstart;
                    248: #endif
1.46      atatat    249:        ifp->if_flags = IFF_POINTOPOINT;
1.69      tron      250:        ifp->if_type = IFT_TUNNEL;
1.46      atatat    251:        ifp->if_snd.ifq_maxlen = ifqmaxlen;
                    252:        ifp->if_collisions = 0;
                    253:        ifp->if_ierrors = 0;
                    254:        ifp->if_oerrors = 0;
                    255:        ifp->if_ipackets = 0;
                    256:        ifp->if_opackets = 0;
1.58      jdolecek  257:        ifp->if_ibytes   = 0;
                    258:        ifp->if_obytes   = 0;
1.46      atatat    259:        ifp->if_dlt = DLT_NULL;
1.50      itojun    260:        IFQ_SET_READY(&ifp->if_snd);
1.46      atatat    261:        if_attach(ifp);
                    262:        if_alloc_sadl(ifp);
1.113     joerg     263:        bpf_attach(ifp, DLT_NULL, sizeof(uint32_t));
1.46      atatat    264: }
                    265:
1.78      thorpej   266: static int
                    267: tun_clone_destroy(struct ifnet *ifp)
1.46      atatat    268: {
                    269:        struct tun_softc *tp = (void *)ifp;
1.136     skrll     270:        bool zombie = false;
1.8       deraadt   271:
1.115     rmind     272:        IF_PURGE(&ifp->if_snd);
                    273:        ifp->if_flags &= ~IFF_RUNNING;
                    274:
1.117     skrll     275:        mutex_enter(&tun_softc_lock);
1.115     rmind     276:        mutex_enter(&tp->tun_lock);
1.46      atatat    277:        LIST_REMOVE(tp, tun_list);
1.70      pk        278:        if (tp->tun_flags & TUN_OPEN) {
1.136     skrll     279:                /* Hang on to storage until last close. */
1.70      pk        280:                tp->tun_flags &= ~TUN_INITED;
                    281:                LIST_INSERT_HEAD(&tunz_softc_list, tp, tun_list);
1.136     skrll     282:                zombie = true;
1.70      pk        283:        }
1.117     skrll     284:        mutex_exit(&tun_softc_lock);
1.46      atatat    285:
                    286:        if (tp->tun_flags & TUN_RWAIT) {
                    287:                tp->tun_flags &= ~TUN_RWAIT;
1.136     skrll     288:                cv_broadcast(&tp->tun_cv);
1.46      atatat    289:        }
1.104     rmind     290:        selnotify(&tp->tun_rsel, 0, 0);
1.8       deraadt   291:
1.115     rmind     292:        mutex_exit(&tp->tun_lock);
1.70      pk        293:
1.106     ad        294:        if (tp->tun_flags & TUN_ASYNC && tp->tun_pgid)
                    295:                fownsignal(tp->tun_pgid, SIGIO, POLL_HUP, 0, NULL);
                    296:
1.113     joerg     297:        bpf_detach(ifp);
1.46      atatat    298:        if_detach(ifp);
                    299:
1.104     rmind     300:        if (!zombie) {
                    301:                seldestroy(&tp->tun_rsel);
                    302:                seldestroy(&tp->tun_wsel);
1.106     ad        303:                softint_disestablish(tp->tun_osih);
                    304:                softint_disestablish(tp->tun_isih);
1.115     rmind     305:                mutex_destroy(&tp->tun_lock);
1.139     pgoyette  306:                cv_destroy(&tp->tun_cv);
1.136     skrll     307:                kmem_free(tp, sizeof(*tp));
1.104     rmind     308:        }
1.73      peter     309:
1.135     skrll     310:        return 0;
1.8       deraadt   311: }
                    312:
1.6       deraadt   313: /*
                    314:  * tunnel open - must be superuser & the device must be
                    315:  * configured in
                    316:  */
1.78      thorpej   317: static int
1.94      christos  318: tunopen(dev_t dev, int flag, int mode, struct lwp *l)
1.6       deraadt   319: {
                    320:        struct ifnet    *ifp;
1.8       deraadt   321:        struct tun_softc *tp;
1.117     skrll     322:        int     error;
1.1       cgd       323:
1.111     elad      324:        error = kauth_authorize_network(l->l_cred, KAUTH_NETWORK_INTERFACE_TUN,
                    325:            KAUTH_REQ_NETWORK_INTERFACE_TUN_ADD, NULL, NULL, NULL);
                    326:        if (error)
1.135     skrll     327:                return error;
1.5       deraadt   328:
1.46      atatat    329:        tp = tun_find_unit(dev);
1.52      atatat    330:
1.70      pk        331:        if (tp == NULL) {
1.52      atatat    332:                (void)tun_clone_create(&tun_cloner, minor(dev));
                    333:                tp = tun_find_unit(dev);
1.70      pk        334:                if (tp == NULL) {
1.136     skrll     335:                        return ENXIO;
1.70      pk        336:                }
1.52      atatat    337:        }
1.46      atatat    338:
                    339:        if (tp->tun_flags & TUN_OPEN) {
1.136     skrll     340:                mutex_exit(&tp->tun_lock);
                    341:                return EBUSY;
1.46      atatat    342:        }
                    343:
1.6       deraadt   344:        ifp = &tp->tun_if;
                    345:        tp->tun_flags |= TUN_OPEN;
1.24      thorpej   346:        TUNDEBUG("%s: open\n", ifp->if_xname);
1.136     skrll     347:
1.115     rmind     348:        mutex_exit(&tp->tun_lock);
1.136     skrll     349:
1.135     skrll     350:        return error;
1.1       cgd       351: }
                    352:
1.6       deraadt   353: /*
                    354:  * tunclose - close the device - mark i/f down & delete
                    355:  * routing info
                    356:  */
                    357: int
1.94      christos  358: tunclose(dev_t dev, int flag, int mode,
                    359:     struct lwp *l)
1.6       deraadt   360: {
1.46      atatat    361:        struct tun_softc *tp;
                    362:        struct ifnet    *ifp;
1.6       deraadt   363:
1.70      pk        364:        if ((tp = tun_find_zunit(minor(dev))) != NULL) {
                    365:                /* interface was "destroyed" before the close */
1.104     rmind     366:                seldestroy(&tp->tun_rsel);
                    367:                seldestroy(&tp->tun_wsel);
1.106     ad        368:                softint_disestablish(tp->tun_osih);
                    369:                softint_disestablish(tp->tun_isih);
1.115     rmind     370:                mutex_destroy(&tp->tun_lock);
1.136     skrll     371:                kmem_free(tp, sizeof(*tp));
                    372:                return 0;
1.70      pk        373:        }
1.46      atatat    374:
1.70      pk        375:        if ((tp = tun_find_unit(dev)) == NULL)
                    376:                goto out_nolock;
1.46      atatat    377:
                    378:        ifp = &tp->tun_if;
                    379:
1.10      andrew    380:        tp->tun_flags &= ~TUN_OPEN;
1.6       deraadt   381:
1.115     rmind     382:        tp->tun_pgid = 0;
                    383:        selnotify(&tp->tun_rsel, 0, 0);
                    384:
                    385:        TUNDEBUG ("%s: closed\n", ifp->if_xname);
                    386:        mutex_exit(&tp->tun_lock);
                    387:
1.6       deraadt   388:        /*
                    389:         * junk all pending output
                    390:         */
1.50      itojun    391:        IFQ_PURGE(&ifp->if_snd);
1.6       deraadt   392:
                    393:        if (ifp->if_flags & IFF_UP) {
                    394:                if_down(ifp);
1.8       deraadt   395:                if (ifp->if_flags & IFF_RUNNING) {
1.17      mycroft   396:                        /* find internet addresses and delete routes */
1.39      augustss  397:                        struct ifaddr *ifa;
1.127     ozaki-r   398:                        IFADDR_READER_FOREACH(ifa, ifp) {
1.80      rpaulo    399: #if defined(INET) || defined(INET6)
                    400:                                if (ifa->ifa_addr->sa_family == AF_INET ||
                    401:                                    ifa->ifa_addr->sa_family == AF_INET6) {
1.18      mycroft   402:                                        rtinit(ifa, (int)RTM_DELETE,
1.26      pk        403:                                               tp->tun_flags & TUN_DSTADDR
                    404:                                                        ? RTF_HOST
                    405:                                                        : 0);
1.18      mycroft   406:                                }
1.38      itojun    407: #endif
1.11      deraadt   408:                        }
1.8       deraadt   409:                }
1.6       deraadt   410:        }
1.70      pk        411: out_nolock:
1.135     skrll     412:        return 0;
1.1       cgd       413: }
                    414:
1.26      pk        415: static void
1.132     ozaki-r   416: tun_enable(struct tun_softc *tp, const struct ifaddr *ifa)
1.6       deraadt   417: {
                    418:        struct ifnet    *ifp = &tp->tun_if;
1.8       deraadt   419:
1.128     christos  420:        TUNDEBUG("%s: %s\n", __func__, ifp->if_xname);
1.6       deraadt   421:
1.115     rmind     422:        mutex_enter(&tp->tun_lock);
1.6       deraadt   423:        ifp->if_flags |= IFF_UP | IFF_RUNNING;
1.8       deraadt   424:
1.26      pk        425:        tp->tun_flags &= ~(TUN_IASET|TUN_DSTADDR);
1.132     ozaki-r   426:
                    427:        switch (ifa->ifa_addr->sa_family) {
1.38      itojun    428: #ifdef INET
1.132     ozaki-r   429:        case AF_INET: {
                    430:                struct sockaddr_in *sin;
                    431:
                    432:                sin = satosin(ifa->ifa_addr);
                    433:                if (sin && sin->sin_addr.s_addr)
                    434:                        tp->tun_flags |= TUN_IASET;
1.11      deraadt   435:
1.132     ozaki-r   436:                if (ifp->if_flags & IFF_POINTOPOINT) {
                    437:                        sin = satosin(ifa->ifa_dstaddr);
1.17      mycroft   438:                        if (sin && sin->sin_addr.s_addr)
1.132     ozaki-r   439:                                tp->tun_flags |= TUN_DSTADDR;
1.11      deraadt   440:                }
1.132     ozaki-r   441:                break;
                    442:            }
1.38      itojun    443: #endif
1.80      rpaulo    444: #ifdef INET6
1.132     ozaki-r   445:        case AF_INET6: {
                    446:                struct sockaddr_in6 *sin;
1.80      rpaulo    447:
1.132     ozaki-r   448:                sin = satosin6(ifa->ifa_addr);
                    449:                if (!IN6_IS_ADDR_UNSPECIFIED(&sin->sin6_addr))
                    450:                        tp->tun_flags |= TUN_IASET;
                    451:
                    452:                if (ifp->if_flags & IFF_POINTOPOINT) {
                    453:                        sin = satosin6(ifa->ifa_dstaddr);
                    454:                        if (sin && !IN6_IS_ADDR_UNSPECIFIED(&sin->sin6_addr))
                    455:                                tp->tun_flags |= TUN_DSTADDR;
                    456:                } else
                    457:                        tp->tun_flags &= ~TUN_DSTADDR;
                    458:                break;
                    459:            }
1.80      rpaulo    460: #endif /* INET6 */
1.132     ozaki-r   461:        default:
                    462:                break;
1.18      mycroft   463:        }
1.115     rmind     464:        mutex_exit(&tp->tun_lock);
1.1       cgd       465: }
                    466:
                    467: /*
                    468:  * Process an ioctl request.
                    469:  */
1.78      thorpej   470: static int
1.97      christos  471: tun_ioctl(struct ifnet *ifp, u_long cmd, void *data)
1.6       deraadt   472: {
1.46      atatat    473:        struct tun_softc *tp = (struct tun_softc *)(ifp->if_softc);
1.121     roy       474:        struct ifreq *ifr = (struct ifreq *)data;
                    475:        struct ifaddr *ifa = (struct ifaddr *)data;
1.136     skrll     476:        int error = 0;
1.6       deraadt   477:
1.61      itojun    478:        switch (cmd) {
1.108     dyoung    479:        case SIOCINITIFADDR:
1.132     ozaki-r   480:                tun_enable(tp, ifa);
1.121     roy       481:                ifa->ifa_rtrequest = p2p_rtrequest;
1.24      thorpej   482:                TUNDEBUG("%s: address set\n", ifp->if_xname);
1.6       deraadt   483:                break;
1.26      pk        484:        case SIOCSIFBRDADDR:
                    485:                TUNDEBUG("%s: broadcast address set\n", ifp->if_xname);
                    486:                break;
1.102     dyoung    487:        case SIOCSIFMTU:
1.31      matt      488:                if (ifr->ifr_mtu > TUNMTU || ifr->ifr_mtu < 576) {
1.102     dyoung    489:                        error = EINVAL;
                    490:                        break;
1.31      matt      491:                }
                    492:                TUNDEBUG("%s: interface mtu set\n", ifp->if_xname);
1.102     dyoung    493:                if ((error = ifioctl_common(ifp, cmd, data)) == ENETRESET)
                    494:                        error = 0;
1.32      matt      495:                break;
                    496:        case SIOCADDMULTI:
1.102     dyoung    497:        case SIOCDELMULTI:
                    498:                if (ifr == NULL) {
1.32      matt      499:                        error = EAFNOSUPPORT;           /* XXX */
                    500:                        break;
                    501:                }
1.98      dyoung    502:                switch (ifreq_getaddr(cmd, ifr)->sa_family) {
1.32      matt      503: #ifdef INET
                    504:                case AF_INET:
                    505:                        break;
                    506: #endif
1.80      rpaulo    507: #ifdef INET6
                    508:                case AF_INET6:
                    509:                        break;
                    510: #endif
1.32      matt      511:                default:
                    512:                        error = EAFNOSUPPORT;
                    513:                        break;
                    514:                }
1.31      matt      515:                break;
1.6       deraadt   516:        default:
1.108     dyoung    517:                error = ifioctl_common(ifp, cmd, data);
1.6       deraadt   518:        }
1.70      pk        519:
1.135     skrll     520:        return error;
1.1       cgd       521: }
                    522:
                    523: /*
1.22      christos  524:  * tun_output - queue packets from higher level ready to put out.
1.1       cgd       525:  */
1.78      thorpej   526: static int
1.96      dyoung    527: tun_output(struct ifnet *ifp, struct mbuf *m0, const struct sockaddr *dst,
1.125     ozaki-r   528:     const struct rtentry *rt)
1.6       deraadt   529: {
1.24      thorpej   530:        struct tun_softc *tp = ifp->if_softc;
1.51      itojun    531:        int             error;
1.80      rpaulo    532: #if defined(INET) || defined(INET6)
1.75      christos  533:        int             mlen;
1.80      rpaulo    534:        uint32_t        *af;
1.38      itojun    535: #endif
1.6       deraadt   536:
1.115     rmind     537:        mutex_enter(&tp->tun_lock);
1.24      thorpej   538:        TUNDEBUG ("%s: tun_output\n", ifp->if_xname);
1.1       cgd       539:
1.8       deraadt   540:        if ((tp->tun_flags & TUN_READY) != TUN_READY) {
1.24      thorpej   541:                TUNDEBUG ("%s: not ready 0%o\n", ifp->if_xname,
                    542:                          tp->tun_flags);
1.70      pk        543:                error = EHOSTDOWN;
1.138     maya      544:                mutex_exit(&tp->tun_lock);
1.70      pk        545:                goto out;
1.8       deraadt   546:        }
1.136     skrll     547:        // XXXrmind
                    548:        mutex_exit(&tp->tun_lock);
1.8       deraadt   549:
1.50      itojun    550:        /*
                    551:         * if the queueing discipline needs packet classification,
                    552:         * do it before prepending link headers.
                    553:         */
1.124     knakahar  554:        IFQ_CLASSIFY(&ifp->if_snd, m0, dst->sa_family);
1.70      pk        555:
1.113     joerg     556:        bpf_mtap_af(ifp, dst->sa_family, m0);
1.8       deraadt   557:
1.6       deraadt   558:        switch(dst->sa_family) {
1.79      rpaulo    559: #ifdef INET6
                    560:        case AF_INET6:
                    561: #endif
1.1       cgd       562: #ifdef INET
1.6       deraadt   563:        case AF_INET:
1.79      rpaulo    564: #endif
                    565: #if defined(INET) || defined(INET6)
1.26      pk        566:                if (tp->tun_flags & TUN_PREPADDR) {
                    567:                        /* Simple link-layer header */
                    568:                        M_PREPEND(m0, dst->sa_len, M_DONTWAIT);
                    569:                        if (m0 == NULL) {
                    570:                                IF_DROP(&ifp->if_snd);
1.70      pk        571:                                error = ENOBUFS;
                    572:                                goto out;
1.26      pk        573:                        }
1.136     skrll     574:                        memcpy(mtod(m0, char *), dst, dst->sa_len);
1.85      rpaulo    575:                }
                    576:
                    577:                if (tp->tun_flags & TUN_IFHEAD) {
1.81      rpaulo    578:                        /* Prepend the address family */
1.82      rpaulo    579:                        M_PREPEND(m0, sizeof(*af), M_DONTWAIT);
1.80      rpaulo    580:                        if (m0 == NULL) {
                    581:                                IF_DROP(&ifp->if_snd);
                    582:                                error = ENOBUFS;
                    583:                                goto out;
                    584:                        }
                    585:                        af = mtod(m0,uint32_t *);
                    586:                        *af = htonl(dst->sa_family);
1.86      rpaulo    587:                } else {
1.115     rmind     588: #ifdef INET
1.86      rpaulo    589:                        if (dst->sa_family != AF_INET)
                    590: #endif
                    591:                        {
                    592:                                error = EAFNOSUPPORT;
                    593:                                goto out;
                    594:                        }
1.26      pk        595:                }
1.36      sommerfe  596:                /* FALLTHROUGH */
                    597:        case AF_UNSPEC:
1.124     knakahar  598:                IFQ_ENQUEUE(&ifp->if_snd, m0, error);
1.50      itojun    599:                if (error) {
1.6       deraadt   600:                        ifp->if_collisions++;
1.70      pk        601:                        error = EAFNOSUPPORT;
1.115     rmind     602:                        m0 = NULL;
1.70      pk        603:                        goto out;
1.6       deraadt   604:                }
1.58      jdolecek  605:                mlen = m0->m_pkthdr.len;
1.6       deraadt   606:                ifp->if_opackets++;
1.58      jdolecek  607:                ifp->if_obytes += mlen;
1.6       deraadt   608:                break;
1.1       cgd       609: #endif
1.6       deraadt   610:        default:
1.70      pk        611:                error = EAFNOSUPPORT;
                    612:                goto out;
1.6       deraadt   613:        }
                    614:
1.136     skrll     615:        mutex_enter(&tp->tun_lock);
1.6       deraadt   616:        if (tp->tun_flags & TUN_RWAIT) {
                    617:                tp->tun_flags &= ~TUN_RWAIT;
1.136     skrll     618:                cv_broadcast(&tp->tun_cv);
1.6       deraadt   619:        }
1.64      jdolecek  620:        if (tp->tun_flags & TUN_ASYNC && tp->tun_pgid)
1.106     ad        621:                softint_schedule(tp->tun_isih);
1.64      jdolecek  622:
1.104     rmind     623:        selnotify(&tp->tun_rsel, 0, 0);
1.138     maya      624:
                    625:        mutex_exit(&tp->tun_lock);
1.70      pk        626: out:
1.115     rmind     627:        if (error && m0) {
                    628:                m_freem(m0);
                    629:        }
                    630:        return 0;
1.1       cgd       631: }
                    632:
1.106     ad        633: static void
                    634: tun_i_softintr(void *cookie)
                    635: {
                    636:        struct tun_softc *tp = cookie;
                    637:
                    638:        if (tp->tun_flags & TUN_ASYNC && tp->tun_pgid)
                    639:                fownsignal(tp->tun_pgid, SIGIO, POLL_IN, POLLIN|POLLRDNORM,
                    640:                    NULL);
                    641: }
                    642:
                    643: static void
                    644: tun_o_softintr(void *cookie)
                    645: {
                    646:        struct tun_softc *tp = cookie;
                    647:
                    648:        if (tp->tun_flags & TUN_ASYNC && tp->tun_pgid)
                    649:                fownsignal(tp->tun_pgid, SIGIO, POLL_OUT, POLLOUT|POLLWRNORM,
                    650:                    NULL);
                    651: }
                    652:
1.1       cgd       653: /*
                    654:  * the cdevsw interface is now pretty minimal.
                    655:  */
1.6       deraadt   656: int
1.97      christos  657: tunioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
1.6       deraadt   658: {
1.46      atatat    659:        struct tun_softc *tp;
1.136     skrll     660:        int error = 0;
1.46      atatat    661:
                    662:        tp = tun_find_unit(dev);
                    663:
                    664:        /* interface was "destroyed" already */
1.70      pk        665:        if (tp == NULL) {
1.136     skrll     666:                return ENXIO;
1.70      pk        667:        }
1.6       deraadt   668:
                    669:        switch (cmd) {
                    670:        case TUNSDEBUG:
                    671:                tundebug = *(int *)data;
                    672:                break;
1.26      pk        673:
1.6       deraadt   674:        case TUNGDEBUG:
                    675:                *(int *)data = tundebug;
                    676:                break;
1.26      pk        677:
                    678:        case TUNSIFMODE:
1.31      matt      679:                switch (*(int *)data & (IFF_POINTOPOINT|IFF_BROADCAST)) {
1.26      pk        680:                case IFF_POINTOPOINT:
                    681:                case IFF_BROADCAST:
                    682:                        if (tp->tun_if.if_flags & IFF_UP) {
1.70      pk        683:                                error = EBUSY;
                    684:                                goto out;
1.26      pk        685:                        }
                    686:                        tp->tun_if.if_flags &=
1.31      matt      687:                                ~(IFF_BROADCAST|IFF_POINTOPOINT|IFF_MULTICAST);
1.26      pk        688:                        tp->tun_if.if_flags |= *(int *)data;
                    689:                        break;
                    690:                default:
1.70      pk        691:                        error = EINVAL;
                    692:                        goto out;
1.26      pk        693:                }
                    694:                break;
                    695:
                    696:        case TUNSLMODE:
1.87      rpaulo    697:                if (*(int *)data) {
1.26      pk        698:                        tp->tun_flags |= TUN_PREPADDR;
1.87      rpaulo    699:                        tp->tun_flags &= ~TUN_IFHEAD;
                    700:                } else
1.26      pk        701:                        tp->tun_flags &= ~TUN_PREPADDR;
                    702:                break;
                    703:
1.84      rpaulo    704:        case TUNSIFHEAD:
1.87      rpaulo    705:                if (*(int *)data) {
1.84      rpaulo    706:                        tp->tun_flags |= TUN_IFHEAD;
1.88      rpaulo    707:                        tp->tun_flags &= ~TUN_PREPADDR;
1.87      rpaulo    708:                } else
1.84      rpaulo    709:                        tp->tun_flags &= ~TUN_IFHEAD;
                    710:                break;
                    711:
                    712:        case TUNGIFHEAD:
                    713:                *(int *)data = (tp->tun_flags & TUN_IFHEAD);
                    714:                break;
                    715:
1.6       deraadt   716:        case FIONBIO:
                    717:                if (*(int *)data)
                    718:                        tp->tun_flags |= TUN_NBIO;
                    719:                else
                    720:                        tp->tun_flags &= ~TUN_NBIO;
                    721:                break;
1.26      pk        722:
1.6       deraadt   723:        case FIOASYNC:
                    724:                if (*(int *)data)
                    725:                        tp->tun_flags |= TUN_ASYNC;
                    726:                else
                    727:                        tp->tun_flags &= ~TUN_ASYNC;
                    728:                break;
1.26      pk        729:
1.6       deraadt   730:        case FIONREAD:
                    731:                if (tp->tun_if.if_snd.ifq_head)
1.19      pk        732:                        *(int *)data = tp->tun_if.if_snd.ifq_head->m_pkthdr.len;
1.70      pk        733:                else
1.6       deraadt   734:                        *(int *)data = 0;
                    735:                break;
1.26      pk        736:
1.6       deraadt   737:        case TIOCSPGRP:
1.64      jdolecek  738:        case FIOSETOWN:
1.105     ad        739:                error = fsetown(&tp->tun_pgid, cmd, data);
1.6       deraadt   740:                break;
1.26      pk        741:
1.6       deraadt   742:        case TIOCGPGRP:
1.64      jdolecek  743:        case FIOGETOWN:
1.105     ad        744:                error = fgetown(tp->tun_pgid, cmd, data);
1.6       deraadt   745:                break;
1.26      pk        746:
1.6       deraadt   747:        default:
1.70      pk        748:                error = ENOTTY;
1.6       deraadt   749:        }
1.70      pk        750:
                    751: out:
1.115     rmind     752:        mutex_exit(&tp->tun_lock);
1.136     skrll     753:
1.135     skrll     754:        return error;
1.1       cgd       755: }
                    756:
                    757: /*
1.6       deraadt   758:  * The cdevsw read interface - reads a packet at a time, or at
                    759:  * least as much of a packet as can be read.
1.1       cgd       760:  */
1.6       deraadt   761: int
1.94      christos  762: tunread(dev_t dev, struct uio *uio, int ioflag)
1.6       deraadt   763: {
1.46      atatat    764:        struct tun_softc *tp;
                    765:        struct ifnet    *ifp;
1.6       deraadt   766:        struct mbuf     *m, *m0;
1.136     skrll     767:        int             error = 0, len;
1.46      atatat    768:
                    769:        tp = tun_find_unit(dev);
                    770:
                    771:        /* interface was "destroyed" already */
1.70      pk        772:        if (tp == NULL) {
1.136     skrll     773:                return ENXIO;
1.70      pk        774:        }
1.46      atatat    775:
                    776:        ifp = &tp->tun_if;
1.6       deraadt   777:
1.24      thorpej   778:        TUNDEBUG ("%s: read\n", ifp->if_xname);
1.8       deraadt   779:        if ((tp->tun_flags & TUN_READY) != TUN_READY) {
1.26      pk        780:                TUNDEBUG ("%s: not ready 0%o\n", ifp->if_xname, tp->tun_flags);
1.70      pk        781:                error = EHOSTDOWN;
                    782:                goto out;
1.8       deraadt   783:        }
                    784:
1.6       deraadt   785:        tp->tun_flags &= ~TUN_RWAIT;
                    786:
                    787:        do {
1.50      itojun    788:                IFQ_DEQUEUE(&ifp->if_snd, m0);
1.6       deraadt   789:                if (m0 == 0) {
                    790:                        if (tp->tun_flags & TUN_NBIO) {
1.70      pk        791:                                error = EWOULDBLOCK;
                    792:                                goto out;
1.6       deraadt   793:                        }
                    794:                        tp->tun_flags |= TUN_RWAIT;
1.136     skrll     795:                        if (cv_wait_sig(&tp->tun_cv, &tp->tun_lock)) {
1.70      pk        796:                                error = EINTR;
1.136     skrll     797:                                goto out;
1.26      pk        798:                        }
1.6       deraadt   799:                }
                    800:        } while (m0 == 0);
1.70      pk        801:
1.115     rmind     802:        mutex_exit(&tp->tun_lock);
1.6       deraadt   803:
1.70      pk        804:        /* Copy the mbuf chain */
1.6       deraadt   805:        while (m0 && uio->uio_resid > 0 && error == 0) {
1.13      deraadt   806:                len = min(uio->uio_resid, m0->m_len);
1.45      itojun    807:                if (len != 0)
1.97      christos  808:                        error = uiomove(mtod(m0, void *), len, uio);
1.133     christos  809:                m0 = m = m_free(m0);
1.6       deraadt   810:        }
                    811:
                    812:        if (m0) {
                    813:                TUNDEBUG("Dropping mbuf\n");
                    814:                m_freem(m0);
                    815:        }
1.19      pk        816:        if (error)
                    817:                ifp->if_ierrors++;
1.70      pk        818:
1.135     skrll     819:        return error;
1.70      pk        820:
                    821: out:
1.115     rmind     822:        mutex_exit(&tp->tun_lock);
1.136     skrll     823:
1.135     skrll     824:        return error;
1.1       cgd       825: }
                    826:
                    827: /*
                    828:  * the cdevsw write interface - an atomic write is a packet - or else!
                    829:  */
1.6       deraadt   830: int
1.94      christos  831: tunwrite(dev_t dev, struct uio *uio, int ioflag)
1.6       deraadt   832: {
1.46      atatat    833:        struct tun_softc *tp;
                    834:        struct ifnet    *ifp;
1.6       deraadt   835:        struct mbuf     *top, **mp, *m;
1.118     rmind     836:        pktqueue_t      *pktq;
1.26      pk        837:        struct sockaddr dst;
1.136     skrll     838:        int             error = 0, tlen, mlen;
1.80      rpaulo    839:        uint32_t        family;
1.6       deraadt   840:
1.46      atatat    841:        tp = tun_find_unit(dev);
1.70      pk        842:        if (tp == NULL) {
1.136     skrll     843:                /* Interface was "destroyed" already. */
                    844:                return ENXIO;
1.70      pk        845:        }
                    846:
                    847:        /* Unlock until we've got the data */
1.115     rmind     848:        mutex_exit(&tp->tun_lock);
1.46      atatat    849:
                    850:        ifp = &tp->tun_if;
                    851:
1.24      thorpej   852:        TUNDEBUG("%s: tunwrite\n", ifp->if_xname);
1.6       deraadt   853:
1.26      pk        854:        if (tp->tun_flags & TUN_PREPADDR) {
1.46      atatat    855:                if (uio->uio_resid < sizeof(dst)) {
1.70      pk        856:                        error = EIO;
                    857:                        goto out0;
1.46      atatat    858:                }
1.97      christos  859:                error = uiomove((void *)&dst, sizeof(dst), uio);
1.26      pk        860:                if (dst.sa_len > sizeof(dst)) {
                    861:                        /* Duh.. */
                    862:                        int n = dst.sa_len - sizeof(dst);
1.136     skrll     863:                        while (n--) {
                    864:                                char discard;
                    865:                                error = uiomove(&discard, 1, uio);
                    866:                                if (error) {
1.70      pk        867:                                        goto out0;
1.46      atatat    868:                                }
1.136     skrll     869:                        }
1.26      pk        870:                }
1.85      rpaulo    871:        } else if (tp->tun_flags & TUN_IFHEAD) {
1.80      rpaulo    872:                if (uio->uio_resid < sizeof(family)){
                    873:                        error = EIO;
                    874:                        goto out0;
                    875:                }
1.97      christos  876:                error = uiomove((void *)&family, sizeof(family), uio);
1.80      rpaulo    877:                dst.sa_family = ntohl(family);
1.85      rpaulo    878:        } else {
                    879: #ifdef INET
                    880:                dst.sa_family = AF_INET;
                    881: #endif
1.26      pk        882:        }
                    883:
1.54      simonb    884:        if (uio->uio_resid > TUNMTU) {
1.37      mjacob    885:                TUNDEBUG("%s: len=%lu!\n", ifp->if_xname,
                    886:                    (unsigned long)uio->uio_resid);
1.70      pk        887:                error = EIO;
                    888:                goto out0;
1.6       deraadt   889:        }
1.26      pk        890:
                    891:        switch (dst.sa_family) {
                    892: #ifdef INET
                    893:        case AF_INET:
1.118     rmind     894:                pktq = ip_pktq;
1.26      pk        895:                break;
                    896: #endif
1.79      rpaulo    897: #ifdef INET6
                    898:        case AF_INET6:
1.118     rmind     899:                pktq = ip6_pktq;
1.83      rpaulo    900:                break;
1.79      rpaulo    901: #endif
1.26      pk        902:        default:
1.70      pk        903:                error = EAFNOSUPPORT;
                    904:                goto out0;
1.26      pk        905:        }
                    906:
1.8       deraadt   907:        tlen = uio->uio_resid;
                    908:
                    909:        /* get a header mbuf */
                    910:        MGETHDR(m, M_DONTWAIT, MT_DATA);
1.46      atatat    911:        if (m == NULL) {
1.136     skrll     912:                return ENOBUFS;
1.46      atatat    913:        }
1.8       deraadt   914:        mlen = MHLEN;
                    915:
1.68      tron      916:        top = NULL;
1.6       deraadt   917:        mp = &top;
                    918:        while (error == 0 && uio->uio_resid > 0) {
1.13      deraadt   919:                m->m_len = min(mlen, uio->uio_resid);
1.97      christos  920:                error = uiomove(mtod(m, void *), m->m_len, uio);
1.6       deraadt   921:                *mp = m;
                    922:                mp = &m->m_next;
1.68      tron      923:                if (error == 0 && uio->uio_resid > 0) {
                    924:                        MGET(m, M_DONTWAIT, MT_DATA);
                    925:                        if (m == NULL) {
1.8       deraadt   926:                                error = ENOBUFS;
                    927:                                break;
                    928:                        }
                    929:                        mlen = MLEN;
                    930:                }
1.6       deraadt   931:        }
                    932:        if (error) {
1.68      tron      933:                if (top != NULL)
1.136     skrll     934:                        m_freem(top);
1.19      pk        935:                ifp->if_ierrors++;
1.70      pk        936:                goto out0;
1.6       deraadt   937:        }
                    938:
1.8       deraadt   939:        top->m_pkthdr.len = tlen;
1.126     ozaki-r   940:        m_set_rcvif(top, ifp);
1.8       deraadt   941:
1.113     joerg     942:        bpf_mtap_af(ifp, dst.sa_family, top);
1.6       deraadt   943:
1.115     rmind     944:        mutex_enter(&tp->tun_lock);
1.70      pk        945:        if ((tp->tun_flags & TUN_INITED) == 0) {
                    946:                /* Interface was destroyed */
                    947:                error = ENXIO;
                    948:                goto out;
                    949:        }
1.119     ws        950:        if (__predict_false(!pktq_enqueue(pktq, top, 0))) {
1.6       deraadt   951:                ifp->if_collisions++;
1.115     rmind     952:                mutex_exit(&tp->tun_lock);
1.70      pk        953:                error = ENOBUFS;
1.119     ws        954:                m_freem(top);
1.136     skrll     955:                goto out0;
1.6       deraadt   956:        }
                    957:        ifp->if_ipackets++;
1.58      jdolecek  958:        ifp->if_ibytes += tlen;
1.70      pk        959: out:
1.115     rmind     960:        mutex_exit(&tp->tun_lock);
1.70      pk        961: out0:
1.135     skrll     962:        return error;
1.1       cgd       963: }
                    964:
1.50      itojun    965: #ifdef ALTQ
                    966: /*
                    967:  * Start packet transmission on the interface.
                    968:  * when the interface queue is rate-limited by ALTQ or TBR,
                    969:  * if_start is needed to drain packets from the queue in order
                    970:  * to notify readers when outgoing packets become ready.
                    971:  */
                    972: static void
1.78      thorpej   973: tunstart(struct ifnet *ifp)
1.50      itojun    974: {
                    975:        struct tun_softc *tp = ifp->if_softc;
                    976:
                    977:        if (!ALTQ_IS_ENABLED(&ifp->if_snd) && !TBR_IS_ENABLED(&ifp->if_snd))
                    978:                return;
                    979:
1.115     rmind     980:        mutex_enter(&tp->tun_lock);
1.70      pk        981:        if (!IF_IS_EMPTY(&ifp->if_snd)) {
1.50      itojun    982:                if (tp->tun_flags & TUN_RWAIT) {
                    983:                        tp->tun_flags &= ~TUN_RWAIT;
1.136     skrll     984:                        cv_broadcast(&tp->tun_cv);
1.50      itojun    985:                }
1.64      jdolecek  986:                if (tp->tun_flags & TUN_ASYNC && tp->tun_pgid)
1.106     ad        987:                        softint_schedule(tp->tun_osih);
1.70      pk        988:
1.104     rmind     989:                selnotify(&tp->tun_rsel, 0, 0);
1.50      itojun    990:        }
1.115     rmind     991:        mutex_exit(&tp->tun_lock);
1.50      itojun    992: }
                    993: #endif /* ALTQ */
1.1       cgd       994: /*
1.27      mycroft   995:  * tunpoll - the poll interface, this is only useful on reads
1.6       deraadt   996:  * really. The write detect always returns true, write never blocks
                    997:  * anyway, it either accepts the packet or drops it.
                    998:  */
                    999: int
1.78      thorpej  1000: tunpoll(dev_t dev, int events, struct lwp *l)
1.6       deraadt  1001: {
1.46      atatat   1002:        struct tun_softc *tp;
                   1003:        struct ifnet    *ifp;
1.136     skrll    1004:        int revents = 0;
1.46      atatat   1005:
                   1006:        tp = tun_find_unit(dev);
1.136     skrll    1007:        if (tp == NULL) {
                   1008:                /* Interface was "destroyed" already. */
                   1009:                return 0;
                   1010:        }
1.46      atatat   1011:        ifp = &tp->tun_if;
1.6       deraadt  1012:
1.27      mycroft  1013:        TUNDEBUG("%s: tunpoll\n", ifp->if_xname);
1.6       deraadt  1014:
1.35      veego    1015:        if (events & (POLLIN | POLLRDNORM)) {
1.70      pk       1016:                if (!IFQ_IS_EMPTY(&ifp->if_snd)) {
1.27      mycroft  1017:                        TUNDEBUG("%s: tunpoll q=%d\n", ifp->if_xname,
1.24      thorpej  1018:                            ifp->if_snd.ifq_len);
1.27      mycroft  1019:                        revents |= events & (POLLIN | POLLRDNORM);
                   1020:                } else {
                   1021:                        TUNDEBUG("%s: tunpoll waiting\n", ifp->if_xname);
1.77      christos 1022:                        selrecord(l, &tp->tun_rsel);
1.6       deraadt  1023:                }
1.35      veego    1024:        }
1.27      mycroft  1025:
                   1026:        if (events & (POLLOUT | POLLWRNORM))
                   1027:                revents |= events & (POLLOUT | POLLWRNORM);
                   1028:
1.115     rmind    1029:        mutex_exit(&tp->tun_lock);
1.136     skrll    1030:
1.135     skrll    1031:        return revents;
1.56      jdolecek 1032: }
                   1033:
                   1034: static void
                   1035: filt_tunrdetach(struct knote *kn)
                   1036: {
                   1037:        struct tun_softc *tp = kn->kn_hook;
                   1038:
1.136     skrll    1039:        mutex_enter(&tp->tun_lock);
1.57      christos 1040:        SLIST_REMOVE(&tp->tun_rsel.sel_klist, kn, knote, kn_selnext);
1.136     skrll    1041:        mutex_exit(&tp->tun_lock);
1.56      jdolecek 1042: }
                   1043:
                   1044: static int
1.94      christos 1045: filt_tunread(struct knote *kn, long hint)
1.56      jdolecek 1046: {
                   1047:        struct tun_softc *tp = kn->kn_hook;
                   1048:        struct ifnet *ifp = &tp->tun_if;
                   1049:        struct mbuf *m;
                   1050:
1.136     skrll    1051:        mutex_enter(&tp->tun_lock);
1.56      jdolecek 1052:        IF_POLL(&ifp->if_snd, m);
                   1053:        if (m == NULL) {
1.136     skrll    1054:                mutex_exit(&tp->tun_lock);
1.135     skrll    1055:                return 0;
1.56      jdolecek 1056:        }
                   1057:
                   1058:        for (kn->kn_data = 0; m != NULL; m = m->m_next)
                   1059:                kn->kn_data += m->m_len;
                   1060:
1.136     skrll    1061:        mutex_exit(&tp->tun_lock);
                   1062:
1.135     skrll    1063:        return 1;
1.56      jdolecek 1064: }
                   1065:
1.140   ! maya     1066: static const struct filterops tunread_filtops = {
        !          1067:        .f_isfd = 1,
        !          1068:        .f_attach = NULL,
        !          1069:        .f_detach = filt_tunrdetach,
        !          1070:        .f_event = filt_tunread,
        !          1071: };
1.56      jdolecek 1072:
1.140   ! maya     1073: static const struct filterops tun_seltrue_filtops = {
        !          1074:        .f_isfd = 1,
        !          1075:        .f_attach = NULL,
        !          1076:        .f_detach = filt_tunrdetach,
        !          1077:        .f_event = filt_seltrue,
        !          1078: };
1.56      jdolecek 1079:
                   1080: int
                   1081: tunkqfilter(dev_t dev, struct knote *kn)
                   1082: {
1.70      pk       1083:        struct tun_softc *tp;
1.56      jdolecek 1084:        struct klist *klist;
1.136     skrll    1085:        int rv = 0;
1.70      pk       1086:
                   1087:        tp = tun_find_unit(dev);
                   1088:        if (tp == NULL)
                   1089:                goto out_nolock;
1.56      jdolecek 1090:
                   1091:        switch (kn->kn_filter) {
                   1092:        case EVFILT_READ:
1.57      christos 1093:                klist = &tp->tun_rsel.sel_klist;
1.56      jdolecek 1094:                kn->kn_fop = &tunread_filtops;
                   1095:                break;
                   1096:
                   1097:        case EVFILT_WRITE:
1.57      christos 1098:                klist = &tp->tun_rsel.sel_klist;
1.56      jdolecek 1099:                kn->kn_fop = &tun_seltrue_filtops;
                   1100:                break;
                   1101:
                   1102:        default:
1.100     pooka    1103:                rv = EINVAL;
1.70      pk       1104:                goto out;
1.56      jdolecek 1105:        }
                   1106:
                   1107:        kn->kn_hook = tp;
                   1108:
                   1109:        SLIST_INSERT_HEAD(klist, kn, kn_selnext);
1.70      pk       1110:
                   1111: out:
1.115     rmind    1112:        mutex_exit(&tp->tun_lock);
1.70      pk       1113: out_nolock:
1.135     skrll    1114:        return rv;
1.1       cgd      1115: }
1.128     christos 1116:
                   1117: /*
                   1118:  * Module infrastructure
                   1119:  */
                   1120: #include "if_module.h"
                   1121:
                   1122: IF_MODULE(MODULE_CLASS_DRIVER, tun, "")

CVSweb <webmaster@jp.NetBSD.org>