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

1.135   ! skrll       1: /*     $NetBSD: if_tun.c,v 1.134 2017/01/11 13:08:29 ozaki-r 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:
                     17: #include <sys/cdefs.h>
1.135   ! skrll      18: __KERNEL_RCSID(0, "$NetBSD: if_tun.c,v 1.134 2017/01/11 13:08:29 ozaki-r Exp $");
1.33      jonathan   19:
1.123     pooka      20: #ifdef _KERNEL_OPT
1.33      jonathan   21: #include "opt_inet.h"
1.123     pooka      22: #endif
1.8       deraadt    23:
1.6       deraadt    24: #include <sys/param.h>
                     25: #include <sys/buf.h>
1.135   ! skrll      26: #include <sys/conf.h>
        !            27: #include <sys/cpu.h>
        !            28: #include <sys/device.h>
1.6       deraadt    29: #include <sys/errno.h>
1.8       deraadt    30: #include <sys/file.h>
1.135   ! skrll      31: #include <sys/ioctl.h>
1.89      elad       32: #include <sys/kauth.h>
1.135   ! skrll      33: #include <sys/mbuf.h>
        !            34: #include <sys/module.h>
1.115     rmind      35: #include <sys/mutex.h>
1.135   ! skrll      36: #include <sys/poll.h>
        !            37: #include <sys/proc.h>
        !            38: #include <sys/select.h>
        !            39: #include <sys/signalvar.h>
        !            40: #include <sys/socket.h>
        !            41: #include <sys/syslog.h>
        !            42: #include <sys/systm.h>
        !            43: #include <sys/time.h>
1.6       deraadt    44:
1.135   ! skrll      45: #include <net/bpf.h>
1.6       deraadt    46: #include <net/if.h>
1.69      tron       47: #include <net/if_types.h>
1.6       deraadt    48: #include <net/route.h>
1.1       cgd        49:
                     50: #ifdef INET
1.6       deraadt    51: #include <netinet/in.h>
                     52: #include <netinet/in_systm.h>
                     53: #include <netinet/in_var.h>
                     54: #include <netinet/ip.h>
1.30      is         55: #include <netinet/if_inarp.h>
1.1       cgd        56: #endif
                     57:
1.8       deraadt    58: #include <net/if_tun.h>
                     59:
1.122     christos   60: #include "ioconf.h"
                     61:
1.29      christos   62: #define TUNDEBUG       if (tundebug) printf
1.6       deraadt    63: int    tundebug = 0;
1.1       cgd        64:
1.6       deraadt    65: extern int ifqmaxlen;
1.78      thorpej    66:
                     67: static LIST_HEAD(, tun_softc) tun_softc_list;
                     68: static LIST_HEAD(, tun_softc) tunz_softc_list;
1.117     skrll      69: static kmutex_t tun_softc_lock;
1.6       deraadt    70:
1.97      christos   71: static int     tun_ioctl(struct ifnet *, u_long, void *);
1.96      dyoung     72: static int     tun_output(struct ifnet *, struct mbuf *,
1.125     ozaki-r    73:                        const struct sockaddr *, const struct rtentry *rt);
1.78      thorpej    74: static int     tun_clone_create(struct if_clone *, int);
                     75: static int     tun_clone_destroy(struct ifnet *);
1.6       deraadt    76:
1.78      thorpej    77: static struct if_clone tun_cloner =
1.46      atatat     78:     IF_CLONE_INITIALIZER("tun", tun_clone_create, tun_clone_destroy);
                     79:
1.78      thorpej    80: static void tunattach0(struct tun_softc *);
1.132     ozaki-r    81: static void tun_enable(struct tun_softc *, const struct ifaddr *);
1.106     ad         82: static void tun_i_softintr(void *);
                     83: static void tun_o_softintr(void *);
1.50      itojun     84: #ifdef ALTQ
1.78      thorpej    85: static void tunstart(struct ifnet *);
1.50      itojun     86: #endif
1.78      thorpej    87: static struct tun_softc *tun_find_unit(dev_t);
                     88: static struct tun_softc *tun_find_zunit(int);
1.53      gehenna    89:
1.78      thorpej    90: static dev_type_open(tunopen);
                     91: static dev_type_close(tunclose);
                     92: static dev_type_read(tunread);
                     93: static dev_type_write(tunwrite);
                     94: static dev_type_ioctl(tunioctl);
                     95: static dev_type_poll(tunpoll);
                     96: static dev_type_kqfilter(tunkqfilter);
1.53      gehenna    97:
                     98: const struct cdevsw tun_cdevsw = {
1.116     dholland   99:        .d_open = tunopen,
                    100:        .d_close = tunclose,
                    101:        .d_read = tunread,
                    102:        .d_write = tunwrite,
                    103:        .d_ioctl = tunioctl,
                    104:        .d_stop = nostop,
                    105:        .d_tty = notty,
                    106:        .d_poll = tunpoll,
                    107:        .d_mmap = nommap,
                    108:        .d_kqfilter = tunkqfilter,
1.120     dholland  109:        .d_discard = nodiscard,
1.116     dholland  110:        .d_flag = D_OTHER
1.53      gehenna   111: };
1.6       deraadt   112:
1.130     ozaki-r   113: #ifdef _MODULE
                    114: devmajor_t tun_bmajor = -1, tun_cmajor = -1;
                    115: #endif
                    116:
1.8       deraadt   117: void
1.94      christos  118: tunattach(int unused)
1.8       deraadt   119: {
1.46      atatat    120:
1.128     christos  121:        /*
                    122:         * Nothing to do here, initialization is handled by the
1.129     ozaki-r   123:         * module initialization code in tuninit() below).
1.128     christos  124:         */
                    125: }
                    126:
                    127: static void
                    128: tuninit(void)
                    129: {
                    130:
1.117     skrll     131:        mutex_init(&tun_softc_lock, MUTEX_DEFAULT, IPL_NET);
1.46      atatat    132:        LIST_INIT(&tun_softc_list);
1.70      pk        133:        LIST_INIT(&tunz_softc_list);
1.46      atatat    134:        if_clone_attach(&tun_cloner);
1.130     ozaki-r   135: #ifdef _MODULE
                    136:        devsw_attach("tun", NULL, &tun_bmajor, &tun_cdevsw, &tun_cmajor);
                    137: #endif
1.46      atatat    138: }
                    139:
1.128     christos  140: static int
                    141: tundetach(void)
                    142: {
                    143:        int error = 0;
                    144:
                    145:        if (!LIST_EMPTY(&tun_softc_list) || !LIST_EMPTY(&tunz_softc_list))
                    146:                error = EBUSY;
                    147:
1.130     ozaki-r   148: #ifdef _MODULE
                    149:        if (error == 0)
                    150:                error = devsw_detach(NULL, &tun_cdevsw);
                    151: #endif
1.128     christos  152:        if (error == 0) {
                    153:                if_clone_detach(&tun_cloner);
                    154:                mutex_destroy(&tun_softc_lock);
                    155:        }
                    156:
                    157:        return error;
                    158: }
                    159:
1.70      pk        160: /*
                    161:  * Find driver instance from dev_t.
                    162:  * Returns with tp locked (if found).
                    163:  */
                    164: static struct tun_softc *
1.78      thorpej   165: tun_find_unit(dev_t dev)
1.70      pk        166: {
                    167:        struct tun_softc *tp;
                    168:        int unit = minor(dev);
                    169:
1.117     skrll     170:        mutex_enter(&tun_softc_lock);
1.70      pk        171:        LIST_FOREACH(tp, &tun_softc_list, tun_list)
                    172:                if (unit == tp->tun_unit)
                    173:                        break;
                    174:        if (tp)
1.115     rmind     175:                mutex_enter(&tp->tun_lock);
1.117     skrll     176:        mutex_exit(&tun_softc_lock);
1.70      pk        177:
1.135   ! skrll     178:        return tp;
1.70      pk        179: }
                    180:
                    181: /*
                    182:  * Find zombie driver instance by unit number.
                    183:  * Remove tp from list and return it unlocked (if found).
                    184:  */
                    185: static struct tun_softc *
1.78      thorpej   186: tun_find_zunit(int unit)
1.70      pk        187: {
                    188:        struct tun_softc *tp;
                    189:
1.117     skrll     190:        mutex_enter(&tun_softc_lock);
1.70      pk        191:        LIST_FOREACH(tp, &tunz_softc_list, tun_list)
                    192:                if (unit == tp->tun_unit)
                    193:                        break;
                    194:        if (tp)
                    195:                LIST_REMOVE(tp, tun_list);
1.117     skrll     196:        mutex_exit(&tun_softc_lock);
1.70      pk        197: #ifdef DIAGNOSTIC
                    198:        if (tp != NULL && (tp->tun_flags & (TUN_INITED|TUN_OPEN)) != TUN_OPEN)
                    199:                printf("tun%d: inconsistent flags: %x\n", unit, tp->tun_flags);
                    200: #endif
                    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) {
                    211:                /* Allocate a new instance */
1.107     christos  212:                tp = malloc(sizeof(*tp), M_DEVBUF, M_WAITOK|M_ZERO);
1.46      atatat    213:
1.70      pk        214:                tp->tun_unit = unit;
1.115     rmind     215:                mutex_init(&tp->tun_lock, MUTEX_DEFAULT, IPL_NET);
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.117     skrll     270:        int zombie = 0;
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) {
                    279:                /* Hang on to storage until last close */
                    280:                zombie = 1;
                    281:                tp->tun_flags &= ~TUN_INITED;
                    282:                LIST_INSERT_HEAD(&tunz_softc_list, tp, tun_list);
                    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.97      christos  288:                wakeup((void *)tp);
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.70      pk        306:                free(tp, M_DEVBUF);
1.104     rmind     307:        }
1.73      peter     308:
1.135   ! skrll     309:        return 0;
1.8       deraadt   310: }
                    311:
1.6       deraadt   312: /*
                    313:  * tunnel open - must be superuser & the device must be
                    314:  * configured in
                    315:  */
1.78      thorpej   316: static int
1.94      christos  317: tunopen(dev_t dev, int flag, int mode, struct lwp *l)
1.6       deraadt   318: {
                    319:        struct ifnet    *ifp;
1.8       deraadt   320:        struct tun_softc *tp;
1.117     skrll     321:        int     error;
1.1       cgd       322:
1.111     elad      323:        error = kauth_authorize_network(l->l_cred, KAUTH_NETWORK_INTERFACE_TUN,
                    324:            KAUTH_REQ_NETWORK_INTERFACE_TUN_ADD, NULL, NULL, NULL);
                    325:        if (error)
1.135   ! skrll     326:                return error;
1.5       deraadt   327:
1.46      atatat    328:        tp = tun_find_unit(dev);
1.52      atatat    329:
1.70      pk        330:        if (tp == NULL) {
1.52      atatat    331:                (void)tun_clone_create(&tun_cloner, minor(dev));
                    332:                tp = tun_find_unit(dev);
1.70      pk        333:                if (tp == NULL) {
                    334:                        error = ENXIO;
                    335:                        goto out_nolock;
                    336:                }
1.52      atatat    337:        }
1.46      atatat    338:
                    339:        if (tp->tun_flags & TUN_OPEN) {
1.70      pk        340:                error = EBUSY;
                    341:                goto out;
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.70      pk        347: out:
1.115     rmind     348:        mutex_exit(&tp->tun_lock);
1.70      pk        349: out_nolock:
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.70      pk        371:                free(tp, M_DEVBUF);
                    372:                goto out_nolock;
                    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.70      pk        415: /*
1.110     dyoung    416:  * Call at splnet().
1.70      pk        417:  */
1.26      pk        418: static void
1.132     ozaki-r   419: tun_enable(struct tun_softc *tp, const struct ifaddr *ifa)
1.6       deraadt   420: {
                    421:        struct ifnet    *ifp = &tp->tun_if;
1.8       deraadt   422:
1.128     christos  423:        TUNDEBUG("%s: %s\n", __func__, ifp->if_xname);
1.6       deraadt   424:
1.115     rmind     425:        mutex_enter(&tp->tun_lock);
1.6       deraadt   426:        ifp->if_flags |= IFF_UP | IFF_RUNNING;
1.8       deraadt   427:
1.26      pk        428:        tp->tun_flags &= ~(TUN_IASET|TUN_DSTADDR);
1.132     ozaki-r   429:
                    430:        switch (ifa->ifa_addr->sa_family) {
1.38      itojun    431: #ifdef INET
1.132     ozaki-r   432:        case AF_INET: {
                    433:                struct sockaddr_in *sin;
                    434:
                    435:                sin = satosin(ifa->ifa_addr);
                    436:                if (sin && sin->sin_addr.s_addr)
                    437:                        tp->tun_flags |= TUN_IASET;
1.11      deraadt   438:
1.132     ozaki-r   439:                if (ifp->if_flags & IFF_POINTOPOINT) {
                    440:                        sin = satosin(ifa->ifa_dstaddr);
1.17      mycroft   441:                        if (sin && sin->sin_addr.s_addr)
1.132     ozaki-r   442:                                tp->tun_flags |= TUN_DSTADDR;
1.11      deraadt   443:                }
1.132     ozaki-r   444:                break;
                    445:            }
1.38      itojun    446: #endif
1.80      rpaulo    447: #ifdef INET6
1.132     ozaki-r   448:        case AF_INET6: {
                    449:                struct sockaddr_in6 *sin;
1.80      rpaulo    450:
1.132     ozaki-r   451:                sin = satosin6(ifa->ifa_addr);
                    452:                if (!IN6_IS_ADDR_UNSPECIFIED(&sin->sin6_addr))
                    453:                        tp->tun_flags |= TUN_IASET;
                    454:
                    455:                if (ifp->if_flags & IFF_POINTOPOINT) {
                    456:                        sin = satosin6(ifa->ifa_dstaddr);
                    457:                        if (sin && !IN6_IS_ADDR_UNSPECIFIED(&sin->sin6_addr))
                    458:                                tp->tun_flags |= TUN_DSTADDR;
                    459:                } else
                    460:                        tp->tun_flags &= ~TUN_DSTADDR;
                    461:                break;
                    462:            }
1.80      rpaulo    463: #endif /* INET6 */
1.132     ozaki-r   464:        default:
                    465:                break;
1.18      mycroft   466:        }
1.115     rmind     467:        mutex_exit(&tp->tun_lock);
1.1       cgd       468: }
                    469:
                    470: /*
                    471:  * Process an ioctl request.
                    472:  */
1.78      thorpej   473: static int
1.97      christos  474: tun_ioctl(struct ifnet *ifp, u_long cmd, void *data)
1.6       deraadt   475: {
                    476:        int             error = 0, s;
1.46      atatat    477:        struct tun_softc *tp = (struct tun_softc *)(ifp->if_softc);
1.121     roy       478:        struct ifreq *ifr = (struct ifreq *)data;
                    479:        struct ifaddr *ifa = (struct ifaddr *)data;
1.46      atatat    480:
1.70      pk        481:        s = splnet();
1.6       deraadt   482:
1.61      itojun    483:        switch (cmd) {
1.108     dyoung    484:        case SIOCINITIFADDR:
1.132     ozaki-r   485:                tun_enable(tp, ifa);
1.121     roy       486:                ifa->ifa_rtrequest = p2p_rtrequest;
1.24      thorpej   487:                TUNDEBUG("%s: address set\n", ifp->if_xname);
1.6       deraadt   488:                break;
1.26      pk        489:        case SIOCSIFBRDADDR:
                    490:                TUNDEBUG("%s: broadcast address set\n", ifp->if_xname);
                    491:                break;
1.102     dyoung    492:        case SIOCSIFMTU:
1.31      matt      493:                if (ifr->ifr_mtu > TUNMTU || ifr->ifr_mtu < 576) {
1.102     dyoung    494:                        error = EINVAL;
                    495:                        break;
1.31      matt      496:                }
                    497:                TUNDEBUG("%s: interface mtu set\n", ifp->if_xname);
1.102     dyoung    498:                if ((error = ifioctl_common(ifp, cmd, data)) == ENETRESET)
                    499:                        error = 0;
1.32      matt      500:                break;
                    501:        case SIOCADDMULTI:
1.102     dyoung    502:        case SIOCDELMULTI:
                    503:                if (ifr == NULL) {
1.32      matt      504:                        error = EAFNOSUPPORT;           /* XXX */
                    505:                        break;
                    506:                }
1.98      dyoung    507:                switch (ifreq_getaddr(cmd, ifr)->sa_family) {
1.32      matt      508: #ifdef INET
                    509:                case AF_INET:
                    510:                        break;
                    511: #endif
1.80      rpaulo    512: #ifdef INET6
                    513:                case AF_INET6:
                    514:                        break;
                    515: #endif
1.32      matt      516:                default:
                    517:                        error = EAFNOSUPPORT;
                    518:                        break;
                    519:                }
1.31      matt      520:                break;
1.6       deraadt   521:        default:
1.108     dyoung    522:                error = ifioctl_common(ifp, cmd, data);
1.6       deraadt   523:        }
1.70      pk        524:
1.6       deraadt   525:        splx(s);
1.135   ! skrll     526:        return error;
1.1       cgd       527: }
                    528:
                    529: /*
1.22      christos  530:  * tun_output - queue packets from higher level ready to put out.
1.1       cgd       531:  */
1.78      thorpej   532: static int
1.96      dyoung    533: tun_output(struct ifnet *ifp, struct mbuf *m0, const struct sockaddr *dst,
1.125     ozaki-r   534:     const struct rtentry *rt)
1.6       deraadt   535: {
1.24      thorpej   536:        struct tun_softc *tp = ifp->if_softc;
1.6       deraadt   537:        int             s;
1.51      itojun    538:        int             error;
1.80      rpaulo    539: #if defined(INET) || defined(INET6)
1.75      christos  540:        int             mlen;
1.80      rpaulo    541:        uint32_t        *af;
1.38      itojun    542: #endif
1.6       deraadt   543:
1.70      pk        544:        s = splnet();
1.115     rmind     545:        mutex_enter(&tp->tun_lock);
1.24      thorpej   546:        TUNDEBUG ("%s: tun_output\n", ifp->if_xname);
1.1       cgd       547:
1.8       deraadt   548:        if ((tp->tun_flags & TUN_READY) != TUN_READY) {
1.24      thorpej   549:                TUNDEBUG ("%s: not ready 0%o\n", ifp->if_xname,
                    550:                          tp->tun_flags);
1.70      pk        551:                error = EHOSTDOWN;
                    552:                goto out;
1.8       deraadt   553:        }
                    554:
1.50      itojun    555:        /*
                    556:         * if the queueing discipline needs packet classification,
                    557:         * do it before prepending link headers.
                    558:         */
1.124     knakahar  559:        IFQ_CLASSIFY(&ifp->if_snd, m0, dst->sa_family);
1.70      pk        560:
1.113     joerg     561:        bpf_mtap_af(ifp, dst->sa_family, m0);
1.8       deraadt   562:
1.6       deraadt   563:        switch(dst->sa_family) {
1.79      rpaulo    564: #ifdef INET6
                    565:        case AF_INET6:
                    566: #endif
1.1       cgd       567: #ifdef INET
1.6       deraadt   568:        case AF_INET:
1.79      rpaulo    569: #endif
                    570: #if defined(INET) || defined(INET6)
1.26      pk        571:                if (tp->tun_flags & TUN_PREPADDR) {
                    572:                        /* Simple link-layer header */
                    573:                        M_PREPEND(m0, dst->sa_len, M_DONTWAIT);
                    574:                        if (m0 == NULL) {
                    575:                                IF_DROP(&ifp->if_snd);
1.70      pk        576:                                error = ENOBUFS;
                    577:                                goto out;
1.26      pk        578:                        }
                    579:                        bcopy(dst, mtod(m0, char *), dst->sa_len);
1.85      rpaulo    580:                }
                    581:
                    582:                if (tp->tun_flags & TUN_IFHEAD) {
1.81      rpaulo    583:                        /* Prepend the address family */
1.82      rpaulo    584:                        M_PREPEND(m0, sizeof(*af), M_DONTWAIT);
1.80      rpaulo    585:                        if (m0 == NULL) {
                    586:                                IF_DROP(&ifp->if_snd);
                    587:                                error = ENOBUFS;
                    588:                                goto out;
                    589:                        }
                    590:                        af = mtod(m0,uint32_t *);
                    591:                        *af = htonl(dst->sa_family);
1.86      rpaulo    592:                } else {
1.115     rmind     593: #ifdef INET
1.86      rpaulo    594:                        if (dst->sa_family != AF_INET)
                    595: #endif
                    596:                        {
                    597:                                error = EAFNOSUPPORT;
                    598:                                goto out;
                    599:                        }
1.26      pk        600:                }
1.36      sommerfe  601:                /* FALLTHROUGH */
                    602:        case AF_UNSPEC:
1.124     knakahar  603:                IFQ_ENQUEUE(&ifp->if_snd, m0, error);
1.50      itojun    604:                if (error) {
1.6       deraadt   605:                        ifp->if_collisions++;
1.70      pk        606:                        error = EAFNOSUPPORT;
1.115     rmind     607:                        m0 = NULL;
1.70      pk        608:                        goto out;
1.6       deraadt   609:                }
1.58      jdolecek  610:                mlen = m0->m_pkthdr.len;
1.6       deraadt   611:                ifp->if_opackets++;
1.58      jdolecek  612:                ifp->if_obytes += mlen;
1.6       deraadt   613:                break;
1.1       cgd       614: #endif
1.6       deraadt   615:        default:
1.70      pk        616:                error = EAFNOSUPPORT;
                    617:                goto out;
1.6       deraadt   618:        }
                    619:
                    620:        if (tp->tun_flags & TUN_RWAIT) {
                    621:                tp->tun_flags &= ~TUN_RWAIT;
1.97      christos  622:                wakeup((void *)tp);
1.6       deraadt   623:        }
1.64      jdolecek  624:        if (tp->tun_flags & TUN_ASYNC && tp->tun_pgid)
1.106     ad        625:                softint_schedule(tp->tun_isih);
1.64      jdolecek  626:
1.104     rmind     627:        selnotify(&tp->tun_rsel, 0, 0);
1.70      pk        628: out:
1.115     rmind     629:        mutex_exit(&tp->tun_lock);
1.70      pk        630:        splx(s);
1.115     rmind     631:
                    632:        if (error && m0) {
                    633:                m_freem(m0);
                    634:        }
                    635:        return 0;
1.1       cgd       636: }
                    637:
1.106     ad        638: static void
                    639: tun_i_softintr(void *cookie)
                    640: {
                    641:        struct tun_softc *tp = cookie;
                    642:
                    643:        if (tp->tun_flags & TUN_ASYNC && tp->tun_pgid)
                    644:                fownsignal(tp->tun_pgid, SIGIO, POLL_IN, POLLIN|POLLRDNORM,
                    645:                    NULL);
                    646: }
                    647:
                    648: static void
                    649: tun_o_softintr(void *cookie)
                    650: {
                    651:        struct tun_softc *tp = cookie;
                    652:
                    653:        if (tp->tun_flags & TUN_ASYNC && tp->tun_pgid)
                    654:                fownsignal(tp->tun_pgid, SIGIO, POLL_OUT, POLLOUT|POLLWRNORM,
                    655:                    NULL);
                    656: }
                    657:
1.1       cgd       658: /*
                    659:  * the cdevsw interface is now pretty minimal.
                    660:  */
1.6       deraadt   661: int
1.97      christos  662: tunioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
1.6       deraadt   663: {
1.46      atatat    664:        struct tun_softc *tp;
1.70      pk        665:        int s, error = 0;
1.46      atatat    666:
1.70      pk        667:        s = splnet();
1.46      atatat    668:        tp = tun_find_unit(dev);
                    669:
                    670:        /* interface was "destroyed" already */
1.70      pk        671:        if (tp == NULL) {
                    672:                error = ENXIO;
                    673:                goto out_nolock;
                    674:        }
1.6       deraadt   675:
                    676:        switch (cmd) {
                    677:        case TUNSDEBUG:
                    678:                tundebug = *(int *)data;
                    679:                break;
1.26      pk        680:
1.6       deraadt   681:        case TUNGDEBUG:
                    682:                *(int *)data = tundebug;
                    683:                break;
1.26      pk        684:
                    685:        case TUNSIFMODE:
1.31      matt      686:                switch (*(int *)data & (IFF_POINTOPOINT|IFF_BROADCAST)) {
1.26      pk        687:                case IFF_POINTOPOINT:
                    688:                case IFF_BROADCAST:
                    689:                        if (tp->tun_if.if_flags & IFF_UP) {
1.70      pk        690:                                error = EBUSY;
                    691:                                goto out;
1.26      pk        692:                        }
                    693:                        tp->tun_if.if_flags &=
1.31      matt      694:                                ~(IFF_BROADCAST|IFF_POINTOPOINT|IFF_MULTICAST);
1.26      pk        695:                        tp->tun_if.if_flags |= *(int *)data;
                    696:                        break;
                    697:                default:
1.70      pk        698:                        error = EINVAL;
                    699:                        goto out;
1.26      pk        700:                }
                    701:                break;
                    702:
                    703:        case TUNSLMODE:
1.87      rpaulo    704:                if (*(int *)data) {
1.26      pk        705:                        tp->tun_flags |= TUN_PREPADDR;
1.87      rpaulo    706:                        tp->tun_flags &= ~TUN_IFHEAD;
                    707:                } else
1.26      pk        708:                        tp->tun_flags &= ~TUN_PREPADDR;
                    709:                break;
                    710:
1.84      rpaulo    711:        case TUNSIFHEAD:
1.87      rpaulo    712:                if (*(int *)data) {
1.84      rpaulo    713:                        tp->tun_flags |= TUN_IFHEAD;
1.88      rpaulo    714:                        tp->tun_flags &= ~TUN_PREPADDR;
1.87      rpaulo    715:                } else
1.84      rpaulo    716:                        tp->tun_flags &= ~TUN_IFHEAD;
                    717:                break;
                    718:
                    719:        case TUNGIFHEAD:
                    720:                *(int *)data = (tp->tun_flags & TUN_IFHEAD);
                    721:                break;
                    722:
1.6       deraadt   723:        case FIONBIO:
                    724:                if (*(int *)data)
                    725:                        tp->tun_flags |= TUN_NBIO;
                    726:                else
                    727:                        tp->tun_flags &= ~TUN_NBIO;
                    728:                break;
1.26      pk        729:
1.6       deraadt   730:        case FIOASYNC:
                    731:                if (*(int *)data)
                    732:                        tp->tun_flags |= TUN_ASYNC;
                    733:                else
                    734:                        tp->tun_flags &= ~TUN_ASYNC;
                    735:                break;
1.26      pk        736:
1.6       deraadt   737:        case FIONREAD:
                    738:                if (tp->tun_if.if_snd.ifq_head)
1.19      pk        739:                        *(int *)data = tp->tun_if.if_snd.ifq_head->m_pkthdr.len;
1.70      pk        740:                else
1.6       deraadt   741:                        *(int *)data = 0;
                    742:                break;
1.26      pk        743:
1.6       deraadt   744:        case TIOCSPGRP:
1.64      jdolecek  745:        case FIOSETOWN:
1.105     ad        746:                error = fsetown(&tp->tun_pgid, cmd, data);
1.6       deraadt   747:                break;
1.26      pk        748:
1.6       deraadt   749:        case TIOCGPGRP:
1.64      jdolecek  750:        case FIOGETOWN:
1.105     ad        751:                error = fgetown(tp->tun_pgid, cmd, data);
1.6       deraadt   752:                break;
1.26      pk        753:
1.6       deraadt   754:        default:
1.70      pk        755:                error = ENOTTY;
1.6       deraadt   756:        }
1.70      pk        757:
                    758: out:
1.115     rmind     759:        mutex_exit(&tp->tun_lock);
1.70      pk        760: out_nolock:
                    761:        splx(s);
1.135   ! skrll     762:        return error;
1.1       cgd       763: }
                    764:
                    765: /*
1.6       deraadt   766:  * The cdevsw read interface - reads a packet at a time, or at
                    767:  * least as much of a packet as can be read.
1.1       cgd       768:  */
1.6       deraadt   769: int
1.94      christos  770: tunread(dev_t dev, struct uio *uio, int ioflag)
1.6       deraadt   771: {
1.46      atatat    772:        struct tun_softc *tp;
                    773:        struct ifnet    *ifp;
1.6       deraadt   774:        struct mbuf     *m, *m0;
1.70      pk        775:        int             error = 0, len, s, index;
1.46      atatat    776:
1.70      pk        777:        s = splnet();
1.46      atatat    778:        tp = tun_find_unit(dev);
                    779:
                    780:        /* interface was "destroyed" already */
1.70      pk        781:        if (tp == NULL) {
                    782:                error = ENXIO;
                    783:                goto out_nolock;
                    784:        }
1.46      atatat    785:
                    786:        index = tp->tun_if.if_index;
                    787:        ifp = &tp->tun_if;
1.6       deraadt   788:
1.24      thorpej   789:        TUNDEBUG ("%s: read\n", ifp->if_xname);
1.8       deraadt   790:        if ((tp->tun_flags & TUN_READY) != TUN_READY) {
1.26      pk        791:                TUNDEBUG ("%s: not ready 0%o\n", ifp->if_xname, tp->tun_flags);
1.70      pk        792:                error = EHOSTDOWN;
                    793:                goto out;
1.8       deraadt   794:        }
                    795:
1.6       deraadt   796:        tp->tun_flags &= ~TUN_RWAIT;
                    797:
                    798:        do {
1.50      itojun    799:                IFQ_DEQUEUE(&ifp->if_snd, m0);
1.6       deraadt   800:                if (m0 == 0) {
                    801:                        if (tp->tun_flags & TUN_NBIO) {
1.70      pk        802:                                error = EWOULDBLOCK;
                    803:                                goto out;
1.6       deraadt   804:                        }
                    805:                        tp->tun_flags |= TUN_RWAIT;
1.115     rmind     806:                        if (mtsleep((void *)tp, PZERO|PCATCH|PNORELOCK,
1.70      pk        807:                                        "tunread", 0, &tp->tun_lock) != 0) {
                    808:                                error = EINTR;
                    809:                                goto out_nolock;
1.46      atatat    810:                        } else {
                    811:                                /*
                    812:                                 * Maybe the interface was destroyed while
                    813:                                 * we were sleeping, so let's ensure that
                    814:                                 * we're looking at the same (valid) tun
                    815:                                 * interface before looping.
                    816:                                 */
                    817:                                tp = tun_find_unit(dev);
1.70      pk        818:                                if (tp == NULL) {
                    819:                                        error = ENXIO;
                    820:                                        goto out_nolock;
                    821:                                }
                    822:                                if (tp->tun_if.if_index != index) {
                    823:                                        error = ENXIO;
                    824:                                        goto out;
1.46      atatat    825:                                }
1.26      pk        826:                        }
1.6       deraadt   827:                }
                    828:        } while (m0 == 0);
1.70      pk        829:
1.115     rmind     830:        mutex_exit(&tp->tun_lock);
1.6       deraadt   831:        splx(s);
                    832:
1.70      pk        833:        /* Copy the mbuf chain */
1.6       deraadt   834:        while (m0 && uio->uio_resid > 0 && error == 0) {
1.13      deraadt   835:                len = min(uio->uio_resid, m0->m_len);
1.45      itojun    836:                if (len != 0)
1.97      christos  837:                        error = uiomove(mtod(m0, void *), len, uio);
1.133     christos  838:                m0 = m = m_free(m0);
1.6       deraadt   839:        }
                    840:
                    841:        if (m0) {
                    842:                TUNDEBUG("Dropping mbuf\n");
                    843:                m_freem(m0);
                    844:        }
1.19      pk        845:        if (error)
                    846:                ifp->if_ierrors++;
1.70      pk        847:
1.135   ! skrll     848:        return error;
1.70      pk        849:
                    850: out:
1.115     rmind     851:        mutex_exit(&tp->tun_lock);
1.70      pk        852: out_nolock:
                    853:        splx(s);
1.135   ! skrll     854:        return error;
1.1       cgd       855: }
                    856:
                    857: /*
                    858:  * the cdevsw write interface - an atomic write is a packet - or else!
                    859:  */
1.6       deraadt   860: int
1.94      christos  861: tunwrite(dev_t dev, struct uio *uio, int ioflag)
1.6       deraadt   862: {
1.46      atatat    863:        struct tun_softc *tp;
                    864:        struct ifnet    *ifp;
1.6       deraadt   865:        struct mbuf     *top, **mp, *m;
1.118     rmind     866:        pktqueue_t      *pktq;
1.26      pk        867:        struct sockaddr dst;
1.118     rmind     868:        int             error = 0, s, tlen, mlen;
1.80      rpaulo    869:        uint32_t        family;
1.6       deraadt   870:
1.70      pk        871:        s = splnet();
1.46      atatat    872:        tp = tun_find_unit(dev);
                    873:
                    874:        /* interface was "destroyed" already */
1.70      pk        875:        if (tp == NULL) {
                    876:                error = ENXIO;
                    877:                goto out_nolock;
                    878:        }
                    879:
                    880:        /* Unlock until we've got the data */
1.115     rmind     881:        mutex_exit(&tp->tun_lock);
1.70      pk        882:        splx(s);
1.46      atatat    883:
                    884:        ifp = &tp->tun_if;
                    885:
1.24      thorpej   886:        TUNDEBUG("%s: tunwrite\n", ifp->if_xname);
1.6       deraadt   887:
1.26      pk        888:        if (tp->tun_flags & TUN_PREPADDR) {
1.46      atatat    889:                if (uio->uio_resid < sizeof(dst)) {
1.70      pk        890:                        error = EIO;
                    891:                        goto out0;
1.46      atatat    892:                }
1.97      christos  893:                error = uiomove((void *)&dst, sizeof(dst), uio);
1.26      pk        894:                if (dst.sa_len > sizeof(dst)) {
                    895:                        /* Duh.. */
                    896:                        char discard;
                    897:                        int n = dst.sa_len - sizeof(dst);
                    898:                        while (n--)
1.46      atatat    899:                                if ((error = uiomove(&discard, 1, uio)) != 0) {
1.70      pk        900:                                        goto out0;
1.46      atatat    901:                                }
1.26      pk        902:                }
1.85      rpaulo    903:        } else if (tp->tun_flags & TUN_IFHEAD) {
1.80      rpaulo    904:                if (uio->uio_resid < sizeof(family)){
                    905:                        error = EIO;
                    906:                        goto out0;
                    907:                }
1.97      christos  908:                error = uiomove((void *)&family, sizeof(family), uio);
1.80      rpaulo    909:                dst.sa_family = ntohl(family);
1.85      rpaulo    910:        } else {
                    911: #ifdef INET
                    912:                dst.sa_family = AF_INET;
                    913: #endif
1.26      pk        914:        }
                    915:
1.54      simonb    916:        if (uio->uio_resid > TUNMTU) {
1.37      mjacob    917:                TUNDEBUG("%s: len=%lu!\n", ifp->if_xname,
                    918:                    (unsigned long)uio->uio_resid);
1.70      pk        919:                error = EIO;
                    920:                goto out0;
1.6       deraadt   921:        }
1.26      pk        922:
                    923:        switch (dst.sa_family) {
                    924: #ifdef INET
                    925:        case AF_INET:
1.118     rmind     926:                pktq = ip_pktq;
1.26      pk        927:                break;
                    928: #endif
1.79      rpaulo    929: #ifdef INET6
                    930:        case AF_INET6:
1.118     rmind     931:                pktq = ip6_pktq;
1.83      rpaulo    932:                break;
1.79      rpaulo    933: #endif
1.26      pk        934:        default:
1.70      pk        935:                error = EAFNOSUPPORT;
                    936:                goto out0;
1.26      pk        937:        }
                    938:
1.8       deraadt   939:        tlen = uio->uio_resid;
                    940:
                    941:        /* get a header mbuf */
                    942:        MGETHDR(m, M_DONTWAIT, MT_DATA);
1.46      atatat    943:        if (m == NULL) {
1.70      pk        944:                error = ENOBUFS;
                    945:                goto out0;
1.46      atatat    946:        }
1.8       deraadt   947:        mlen = MHLEN;
                    948:
1.68      tron      949:        top = NULL;
1.6       deraadt   950:        mp = &top;
                    951:        while (error == 0 && uio->uio_resid > 0) {
1.13      deraadt   952:                m->m_len = min(mlen, uio->uio_resid);
1.97      christos  953:                error = uiomove(mtod(m, void *), m->m_len, uio);
1.6       deraadt   954:                *mp = m;
                    955:                mp = &m->m_next;
1.68      tron      956:                if (error == 0 && uio->uio_resid > 0) {
                    957:                        MGET(m, M_DONTWAIT, MT_DATA);
                    958:                        if (m == NULL) {
1.8       deraadt   959:                                error = ENOBUFS;
                    960:                                break;
                    961:                        }
                    962:                        mlen = MLEN;
                    963:                }
1.6       deraadt   964:        }
                    965:        if (error) {
1.68      tron      966:                if (top != NULL)
1.8       deraadt   967:                        m_freem (top);
1.19      pk        968:                ifp->if_ierrors++;
1.70      pk        969:                goto out0;
1.6       deraadt   970:        }
                    971:
1.8       deraadt   972:        top->m_pkthdr.len = tlen;
1.126     ozaki-r   973:        m_set_rcvif(top, ifp);
1.8       deraadt   974:
1.113     joerg     975:        bpf_mtap_af(ifp, dst.sa_family, top);
1.6       deraadt   976:
1.43      thorpej   977:        s = splnet();
1.115     rmind     978:        mutex_enter(&tp->tun_lock);
1.70      pk        979:        if ((tp->tun_flags & TUN_INITED) == 0) {
                    980:                /* Interface was destroyed */
                    981:                error = ENXIO;
                    982:                goto out;
                    983:        }
1.119     ws        984:        if (__predict_false(!pktq_enqueue(pktq, top, 0))) {
1.6       deraadt   985:                ifp->if_collisions++;
1.115     rmind     986:                mutex_exit(&tp->tun_lock);
1.70      pk        987:                error = ENOBUFS;
1.119     ws        988:                m_freem(top);
1.115     rmind     989:                goto out_nolock;
1.6       deraadt   990:        }
                    991:        ifp->if_ipackets++;
1.58      jdolecek  992:        ifp->if_ibytes += tlen;
1.70      pk        993: out:
1.115     rmind     994:        mutex_exit(&tp->tun_lock);
1.70      pk        995: out_nolock:
                    996:        splx(s);
                    997: out0:
1.135   ! skrll     998:        return error;
1.1       cgd       999: }
                   1000:
1.50      itojun   1001: #ifdef ALTQ
                   1002: /*
                   1003:  * Start packet transmission on the interface.
                   1004:  * when the interface queue is rate-limited by ALTQ or TBR,
                   1005:  * if_start is needed to drain packets from the queue in order
                   1006:  * to notify readers when outgoing packets become ready.
1.70      pk       1007:  *
                   1008:  * Should be called at splnet.
1.50      itojun   1009:  */
                   1010: static void
1.78      thorpej  1011: tunstart(struct ifnet *ifp)
1.50      itojun   1012: {
                   1013:        struct tun_softc *tp = ifp->if_softc;
                   1014:
                   1015:        if (!ALTQ_IS_ENABLED(&ifp->if_snd) && !TBR_IS_ENABLED(&ifp->if_snd))
                   1016:                return;
                   1017:
1.115     rmind    1018:        mutex_enter(&tp->tun_lock);
1.70      pk       1019:        if (!IF_IS_EMPTY(&ifp->if_snd)) {
1.50      itojun   1020:                if (tp->tun_flags & TUN_RWAIT) {
                   1021:                        tp->tun_flags &= ~TUN_RWAIT;
1.97      christos 1022:                        wakeup((void *)tp);
1.50      itojun   1023:                }
1.64      jdolecek 1024:                if (tp->tun_flags & TUN_ASYNC && tp->tun_pgid)
1.106     ad       1025:                        softint_schedule(tp->tun_osih);
1.70      pk       1026:
1.104     rmind    1027:                selnotify(&tp->tun_rsel, 0, 0);
1.50      itojun   1028:        }
1.115     rmind    1029:        mutex_exit(&tp->tun_lock);
1.50      itojun   1030: }
                   1031: #endif /* ALTQ */
1.1       cgd      1032: /*
1.27      mycroft  1033:  * tunpoll - the poll interface, this is only useful on reads
1.6       deraadt  1034:  * really. The write detect always returns true, write never blocks
                   1035:  * anyway, it either accepts the packet or drops it.
                   1036:  */
                   1037: int
1.78      thorpej  1038: tunpoll(dev_t dev, int events, struct lwp *l)
1.6       deraadt  1039: {
1.46      atatat   1040:        struct tun_softc *tp;
                   1041:        struct ifnet    *ifp;
                   1042:        int             s, revents = 0;
                   1043:
1.70      pk       1044:        s = splnet();
1.46      atatat   1045:        tp = tun_find_unit(dev);
                   1046:
                   1047:        /* interface was "destroyed" already */
                   1048:        if (tp == NULL)
1.70      pk       1049:                goto out_nolock;
1.46      atatat   1050:
                   1051:        ifp = &tp->tun_if;
1.6       deraadt  1052:
1.27      mycroft  1053:        TUNDEBUG("%s: tunpoll\n", ifp->if_xname);
1.6       deraadt  1054:
1.35      veego    1055:        if (events & (POLLIN | POLLRDNORM)) {
1.70      pk       1056:                if (!IFQ_IS_EMPTY(&ifp->if_snd)) {
1.27      mycroft  1057:                        TUNDEBUG("%s: tunpoll q=%d\n", ifp->if_xname,
1.24      thorpej  1058:                            ifp->if_snd.ifq_len);
1.27      mycroft  1059:                        revents |= events & (POLLIN | POLLRDNORM);
                   1060:                } else {
                   1061:                        TUNDEBUG("%s: tunpoll waiting\n", ifp->if_xname);
1.77      christos 1062:                        selrecord(l, &tp->tun_rsel);
1.6       deraadt  1063:                }
1.35      veego    1064:        }
1.27      mycroft  1065:
                   1066:        if (events & (POLLOUT | POLLWRNORM))
                   1067:                revents |= events & (POLLOUT | POLLWRNORM);
                   1068:
1.115     rmind    1069:        mutex_exit(&tp->tun_lock);
1.70      pk       1070: out_nolock:
1.6       deraadt  1071:        splx(s);
1.135   ! skrll    1072:        return revents;
1.56      jdolecek 1073: }
                   1074:
                   1075: static void
                   1076: filt_tunrdetach(struct knote *kn)
                   1077: {
                   1078:        struct tun_softc *tp = kn->kn_hook;
                   1079:        int s;
                   1080:
                   1081:        s = splnet();
1.57      christos 1082:        SLIST_REMOVE(&tp->tun_rsel.sel_klist, kn, knote, kn_selnext);
1.56      jdolecek 1083:        splx(s);
                   1084: }
                   1085:
                   1086: static int
1.94      christos 1087: filt_tunread(struct knote *kn, long hint)
1.56      jdolecek 1088: {
                   1089:        struct tun_softc *tp = kn->kn_hook;
                   1090:        struct ifnet *ifp = &tp->tun_if;
                   1091:        struct mbuf *m;
                   1092:        int s;
                   1093:
                   1094:        s = splnet();
                   1095:        IF_POLL(&ifp->if_snd, m);
                   1096:        if (m == NULL) {
                   1097:                splx(s);
1.135   ! skrll    1098:                return 0;
1.56      jdolecek 1099:        }
                   1100:
                   1101:        for (kn->kn_data = 0; m != NULL; m = m->m_next)
                   1102:                kn->kn_data += m->m_len;
                   1103:
                   1104:        splx(s);
1.135   ! skrll    1105:        return 1;
1.56      jdolecek 1106: }
                   1107:
                   1108: static const struct filterops tunread_filtops =
                   1109:        { 1, NULL, filt_tunrdetach, filt_tunread };
                   1110:
                   1111: static const struct filterops tun_seltrue_filtops =
                   1112:        { 1, NULL, filt_tunrdetach, filt_seltrue };
                   1113:
                   1114: int
                   1115: tunkqfilter(dev_t dev, struct knote *kn)
                   1116: {
1.70      pk       1117:        struct tun_softc *tp;
1.56      jdolecek 1118:        struct klist *klist;
1.70      pk       1119:        int rv = 0, s;
                   1120:
                   1121:        s = splnet();
                   1122:        tp = tun_find_unit(dev);
                   1123:        if (tp == NULL)
                   1124:                goto out_nolock;
1.56      jdolecek 1125:
                   1126:        switch (kn->kn_filter) {
                   1127:        case EVFILT_READ:
1.57      christos 1128:                klist = &tp->tun_rsel.sel_klist;
1.56      jdolecek 1129:                kn->kn_fop = &tunread_filtops;
                   1130:                break;
                   1131:
                   1132:        case EVFILT_WRITE:
1.57      christos 1133:                klist = &tp->tun_rsel.sel_klist;
1.56      jdolecek 1134:                kn->kn_fop = &tun_seltrue_filtops;
                   1135:                break;
                   1136:
                   1137:        default:
1.100     pooka    1138:                rv = EINVAL;
1.70      pk       1139:                goto out;
1.56      jdolecek 1140:        }
                   1141:
                   1142:        kn->kn_hook = tp;
                   1143:
                   1144:        SLIST_INSERT_HEAD(klist, kn, kn_selnext);
1.70      pk       1145:
                   1146: out:
1.115     rmind    1147:        mutex_exit(&tp->tun_lock);
1.70      pk       1148: out_nolock:
1.56      jdolecek 1149:        splx(s);
1.135   ! skrll    1150:        return rv;
1.1       cgd      1151: }
1.128     christos 1152:
                   1153: /*
                   1154:  * Module infrastructure
                   1155:  */
                   1156: #include "if_module.h"
                   1157:
                   1158: IF_MODULE(MODULE_CLASS_DRIVER, tun, "")

CVSweb <webmaster@jp.NetBSD.org>