Annotation of XNU/bsd/net/if_tun.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /*     $NetBSD: if_tun.c,v 1.14 1994/06/29 06:36:25 cgd Exp $  */
                     23: 
                     24: /*
                     25:  * Copyright (c) 1988, Julian Onions <[email protected]>
                     26:  * Nottingham University 1987.
                     27:  *
                     28:  * This source may be freely distributed, however I would be interested
                     29:  * in any changes that are made.
                     30:  *
                     31:  * This driver takes packets off the IP i/f and hands them up to a
                     32:  * user process to have its wicked way with. This driver has it's
                     33:  * roots in a similar driver written by Phil Cockcroft (formerly) at
                     34:  * UCL. This driver is based much more on read/write/poll mode of
                     35:  * operation though.
                     36:  */
                     37: 
                     38: #include "tun.h"
                     39: #if NTUN > 0
                     40: 
                     41: #include "opt_devfs.h"
                     42: #include "opt_inet.h"
                     43: 
                     44: #include <sys/param.h>
                     45: #include <sys/proc.h>
                     46: #include <sys/systm.h>
                     47: #include <sys/mbuf.h>
                     48: #include <sys/socket.h>
                     49: #include <sys/filio.h>
                     50: #include <sys/sockio.h>
                     51: #include <sys/ttycom.h>
                     52: #include <sys/poll.h>
                     53: #include <sys/signalvar.h>
                     54: #include <sys/filedesc.h>
                     55: #include <sys/kernel.h>
                     56: #include <sys/sysctl.h>
                     57: #if DEVFS
                     58: #include <sys/devfsext.h>
                     59: #endif /*DEVFS*/
                     60: #include <sys/conf.h>
                     61: #include <sys/uio.h>
                     62: #include <sys/vnode.h>
                     63: 
                     64: #include <net/if.h>
                     65: #include <net/netisr.h>
                     66: #include <net/route.h>
                     67: 
                     68: #if INET
                     69: #include <netinet/in.h>
                     70: #include <netinet/in_var.h>
                     71: #endif
                     72: 
                     73: #if NS
                     74: #include <netns/ns.h>
                     75: #include <netns/ns_if.h>
                     76: #endif
                     77: 
                     78: #include "bpfilter.h"
                     79: #if NBPFILTER > 0
                     80: #include <net/bpf.h>
                     81: #endif
                     82: 
                     83: #include <net/if_tunvar.h>
                     84: #include <net/if_tun.h>
                     85: 
                     86: static void tunattach __P((void *));
                     87: PSEUDO_SET(tunattach, if_tun);
                     88: 
                     89: #define TUNDEBUG       if (tundebug) printf
                     90: static int tundebug = 0;
                     91: SYSCTL_INT(_debug, OID_AUTO, if_tun_debug, CTLFLAG_RW, &tundebug, 0, "");
                     92: 
                     93: static struct tun_softc tunctl[NTUN];
                     94: 
                     95: static int tunoutput __P((struct ifnet *, struct mbuf *, struct sockaddr *,
                     96:            struct rtentry *rt));
                     97: static int tunifioctl __P((struct ifnet *, u_long, caddr_t));
                     98: static int tuninit __P((int));
                     99: 
                    100: static d_open_t        tunopen;
                    101: static d_close_t       tunclose;
                    102: static d_read_t        tunread;
                    103: static d_write_t       tunwrite;
                    104: static d_ioctl_t       tunioctl;
                    105: static d_poll_t        tunpoll;
                    106: 
                    107: #define CDEV_MAJOR 52
                    108: static struct cdevsw tun_cdevsw = {
                    109:        tunopen,        tunclose,       tunread,        tunwrite,
                    110:        tunioctl,       nullstop,       noreset,        nodevtotty,
                    111:        tunpoll,        nommap,         nostrategy,     "tun",  NULL,   -1
                    112: };
                    113: 
                    114: 
                    115: static int     tun_devsw_installed;
                    116: #if    DEVFS
                    117: static void    *tun_devfs_token[NTUN];
                    118: #endif
                    119: 
                    120: #define minor_val(n) ((((n) & ~0xff) << 8) | ((n) & 0xff))
                    121: #define dev_val(n) (((n) >> 8) | ((n) & 0xff))
                    122: 
                    123: static void
                    124: tunattach(dummy)
                    125:        void *dummy;
                    126: {
                    127:        register int i;
                    128:        struct ifnet *ifp;
                    129:        dev_t dev;
                    130: 
                    131:        if ( tun_devsw_installed )
                    132:                return;
                    133:        dev = makedev(CDEV_MAJOR, 0);
                    134:        cdevsw_add(&dev, &tun_cdevsw, NULL);
                    135:        tun_devsw_installed = 1;
                    136:        for ( i = 0; i < NTUN; i++ ) {
                    137: #if DEVFS
                    138:                tun_devfs_token[i] = devfs_add_devswf(&tun_cdevsw, minor_val(i),
                    139:                                                      DV_CHR, UID_UUCP,
                    140:                                                      GID_DIALER, 0600,
                    141:                                                      "tun%d", i);
                    142: #endif
                    143:                tunctl[i].tun_flags = TUN_INITED;
                    144: 
                    145:                ifp = &tunctl[i].tun_if;
                    146:                ifp->if_unit = i;
                    147:                ifp->if_name = "tun";
                    148:                ifp->if_family = APPLE_IF_FAM_TUN;
                    149:                ifp->if_mtu = TUNMTU;
                    150:                ifp->if_ioctl = tunifioctl;
                    151:                ifp->if_output = tunoutput;
                    152:                ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
                    153:                ifp->if_snd.ifq_maxlen = ifqmaxlen;
                    154:                if_attach(ifp);
                    155: #if NBPFILTER > 0
                    156:                bpfattach(ifp, DLT_NULL, sizeof(u_int));
                    157: #endif
                    158:        }
                    159: }
                    160: 
                    161: /*
                    162:  * tunnel open - must be superuser & the device must be
                    163:  * configured in
                    164:  */
                    165: static int
                    166: tunopen(dev, flag, mode, p)
                    167:        dev_t   dev;
                    168:        int     flag, mode;
                    169:        struct proc *p;
                    170: {
                    171:        struct ifnet    *ifp;
                    172:        struct tun_softc *tp;
                    173:        register int    unit, error;
                    174: 
                    175:        error = suser(p->p_ucred, &p->p_acflag);
                    176:        if (error)
                    177:                return (error);
                    178: 
                    179:        if ((unit = dev_val(minor(dev))) >= NTUN)
                    180:                return (ENXIO);
                    181:        tp = &tunctl[unit];
                    182:        if (tp->tun_flags & TUN_OPEN)
                    183:                return EBUSY;
                    184:        ifp = &tp->tun_if;
                    185:        tp->tun_flags |= TUN_OPEN;
                    186:        TUNDEBUG("%s%d: open\n", ifp->if_name, ifp->if_unit);
                    187:        return (0);
                    188: }
                    189: 
                    190: /*
                    191:  * tunclose - close the device - mark i/f down & delete
                    192:  * routing info
                    193:  */
                    194: static int
                    195: tunclose(dev, foo, bar, p)
                    196:        dev_t dev;
                    197:        int foo;
                    198:        int bar;
                    199:        struct proc *p;
                    200: {
                    201:        register int    unit = dev_val(minor(dev)), s;
                    202:        struct tun_softc *tp = &tunctl[unit];
                    203:        struct ifnet    *ifp = &tp->tun_if;
                    204:        struct mbuf     *m;
                    205: 
                    206:        tp->tun_flags &= ~TUN_OPEN;
                    207: 
                    208:        /*
                    209:         * junk all pending output
                    210:         */
                    211:        do {
                    212:                s = splimp();
                    213:                IF_DEQUEUE(&ifp->if_snd, m);
                    214:                splx(s);
                    215:                if (m)
                    216:                        m_freem(m);
                    217:        } while (m);
                    218: 
                    219:        if (ifp->if_flags & IFF_UP) {
                    220:                s = splimp();
                    221:                if_down(ifp);
                    222:                if (ifp->if_flags & IFF_RUNNING) {
                    223:                    /* find internet addresses and delete routes */
                    224:                    register struct ifaddr *ifa;
                    225:                    for (ifa = ifp->if_addrhead.tqh_first; ifa;
                    226:                         ifa = ifa->ifa_link.tqe_next) {
                    227:                        if (ifa->ifa_addr->sa_family == AF_INET) {
                    228:                            rtinit(ifa, (int)RTM_DELETE,
                    229:                                   tp->tun_flags & TUN_DSTADDR ? RTF_HOST : 0);
                    230:                        }
                    231:                    }
                    232:                }
                    233:                splx(s);
                    234:        }
                    235:        funsetown(tp->tun_sigio);
                    236:        selwakeup(&tp->tun_rsel);
                    237: 
                    238:        TUNDEBUG ("%s%d: closed\n", ifp->if_name, ifp->if_unit);
                    239:        return (0);
                    240: }
                    241: 
                    242: static int
                    243: tuninit(unit)
                    244:        int     unit;
                    245: {
                    246:        struct tun_softc *tp = &tunctl[unit];
                    247:        struct ifnet    *ifp = &tp->tun_if;
                    248:        register struct ifaddr *ifa;
                    249: 
                    250:        TUNDEBUG("%s%d: tuninit\n", ifp->if_name, ifp->if_unit);
                    251: 
                    252:        ifp->if_flags |= IFF_UP | IFF_RUNNING;
                    253:        getmicrotime(&ifp->if_lastchange);
                    254: 
                    255:        for (ifa = ifp->if_addrhead.tqh_first; ifa; 
                    256:             ifa = ifa->ifa_link.tqe_next) {
                    257: #if INET
                    258:                if (ifa->ifa_addr->sa_family == AF_INET) {
                    259:                    struct sockaddr_in *si;
                    260: 
                    261:                    si = (struct sockaddr_in *)ifa->ifa_addr;
                    262:                    if (si && si->sin_addr.s_addr)
                    263:                            tp->tun_flags |= TUN_IASET;
                    264: 
                    265:                    si = (struct sockaddr_in *)ifa->ifa_dstaddr;
                    266:                    if (si && si->sin_addr.s_addr)
                    267:                            tp->tun_flags |= TUN_DSTADDR;
                    268:                }
                    269: #endif
                    270:        }
                    271:        return 0;
                    272: }
                    273: 
                    274: /*
                    275:  * Process an ioctl request.
                    276:  */
                    277: int
                    278: tunifioctl(ifp, cmd, data)
                    279:        struct ifnet *ifp;
                    280:        u_long  cmd;
                    281:        caddr_t data;
                    282: {
                    283:        register struct ifreq *ifr = (struct ifreq *)data;
                    284:        int             error = 0, s;
                    285: 
                    286:        s = splimp();
                    287:        switch(cmd) {
                    288:        case SIOCSIFADDR:
                    289:                tuninit(ifp->if_unit);
                    290:                TUNDEBUG("%s%d: address set\n",
                    291:                         ifp->if_name, ifp->if_unit);
                    292:                break;
                    293:        case SIOCSIFDSTADDR:
                    294:                tuninit(ifp->if_unit);
                    295:                TUNDEBUG("%s%d: destination address set\n",
                    296:                         ifp->if_name, ifp->if_unit);
                    297:                break;
                    298:        case SIOCSIFMTU:
                    299:                ifp->if_mtu = ifr->ifr_mtu;
                    300:                TUNDEBUG("%s%d: mtu set\n",
                    301:                         ifp->if_name, ifp->if_unit);
                    302:                break;
                    303:        case SIOCADDMULTI:
                    304:        case SIOCDELMULTI:
                    305:                break;
                    306: 
                    307: 
                    308:        default:
                    309:                error = EINVAL;
                    310:        }
                    311:        splx(s);
                    312:        return (error);
                    313: }
                    314: 
                    315: /*
                    316:  * tunoutput - queue packets from higher level ready to put out.
                    317:  */
                    318: int
                    319: tunoutput(ifp, m0, dst, rt)
                    320:        struct ifnet   *ifp;
                    321:        struct mbuf    *m0;
                    322:        struct sockaddr *dst;
                    323:        struct rtentry *rt;
                    324: {
                    325:        struct tun_softc *tp = &tunctl[ifp->if_unit];
                    326:        int             s;
                    327: 
                    328:        TUNDEBUG ("%s%d: tunoutput\n", ifp->if_name, ifp->if_unit);
                    329: 
                    330:        if ((tp->tun_flags & TUN_READY) != TUN_READY) {
                    331:                TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name,
                    332:                          ifp->if_unit, tp->tun_flags);
                    333:                m_freem (m0);
                    334:                return EHOSTDOWN;
                    335:        }
                    336: 
                    337: #if NBPFILTER > 0
                    338:        /* BPF write needs to be handled specially */
                    339:        if (dst->sa_family == AF_UNSPEC) {
                    340:                dst->sa_family = *(mtod(m0, int *));
                    341:                m0->m_len -= sizeof(int);
                    342:                m0->m_pkthdr.len -= sizeof(int);
                    343:                m0->m_data += sizeof(int);
                    344:        }
                    345: 
                    346:        if (ifp->if_bpf) {
                    347:                /*
                    348:                 * We need to prepend the address family as
                    349:                 * a four byte field.  Cons up a dummy header
                    350:                 * to pacify bpf.  This is safe because bpf
                    351:                 * will only read from the mbuf (i.e., it won't
                    352:                 * try to free it or keep a pointer to it).
                    353:                 */
                    354:                struct mbuf m;
                    355:                u_int af = dst->sa_family;
                    356: 
                    357:                m.m_next = m0;
                    358:                m.m_len = 4;
                    359:                m.m_data = (char *)&af;
                    360: 
                    361:                bpf_mtap(ifp, &m);
                    362:        }
                    363: #endif
                    364: 
                    365:        switch(dst->sa_family) {
                    366: #if INET
                    367:        case AF_INET:
                    368:                s = splimp();
                    369:                if (IF_QFULL(&ifp->if_snd)) {
                    370:                        IF_DROP(&ifp->if_snd);
                    371:                        m_freem(m0);
                    372:                        splx(s);
                    373:                        ifp->if_collisions++;
                    374:                        return (ENOBUFS);
                    375:                }
                    376:                ifp->if_obytes += m0->m_pkthdr.len;
                    377:                IF_ENQUEUE(&ifp->if_snd, m0);
                    378:                splx(s);
                    379:                ifp->if_opackets++;
                    380:                break;
                    381: #endif
                    382:        default:
                    383:                m_freem(m0);
                    384:                return EAFNOSUPPORT;
                    385:        }
                    386: 
                    387:        if (tp->tun_flags & TUN_RWAIT) {
                    388:                tp->tun_flags &= ~TUN_RWAIT;
                    389:                wakeup((caddr_t)tp);
                    390:        }
                    391:        if (tp->tun_flags & TUN_ASYNC && tp->tun_sigio)
                    392:                pgsigio(tp->tun_sigio, SIGIO, 0);
                    393:        selwakeup(&tp->tun_rsel);
                    394:        return 0;
                    395: }
                    396: 
                    397: /*
                    398:  * the cdevsw interface is now pretty minimal.
                    399:  */
                    400: static int
                    401: tunioctl(dev, cmd, data, flag, p)
                    402:        dev_t           dev;
                    403:        u_long          cmd;
                    404:        caddr_t         data;
                    405:        int             flag;
                    406:        struct proc     *p;
                    407: {
                    408:        int             unit = dev_val(minor(dev)), s;
                    409:        struct tun_softc *tp = &tunctl[unit];
                    410:        struct tuninfo *tunp;
                    411: 
                    412:        switch (cmd) {
                    413:        case TUNSIFINFO:
                    414:                tunp = (struct tuninfo *)data;
                    415:                tp->tun_if.if_mtu = tunp->mtu;
                    416:                tp->tun_if.if_type = tunp->type;
                    417:                tp->tun_if.if_baudrate = tunp->baudrate;
                    418:                break;
                    419:        case TUNGIFINFO:
                    420:                tunp = (struct tuninfo *)data;
                    421:                tunp->mtu = tp->tun_if.if_mtu;
                    422:                tunp->type = tp->tun_if.if_type;
                    423:                tunp->baudrate = tp->tun_if.if_baudrate;
                    424:                break;
                    425:        case TUNSDEBUG:
                    426:                tundebug = *(int *)data;
                    427:                break;
                    428:        case TUNGDEBUG:
                    429:                *(int *)data = tundebug;
                    430:                break;
                    431:        case FIONBIO:
                    432:                break;
                    433:        case FIOASYNC:
                    434:                if (*(int *)data)
                    435:                        tp->tun_flags |= TUN_ASYNC;
                    436:                else
                    437:                        tp->tun_flags &= ~TUN_ASYNC;
                    438:                break;
                    439:        case FIONREAD:
                    440:                s = splimp();
                    441:                if (tp->tun_if.if_snd.ifq_head) {
                    442:                        struct mbuf *mb = tp->tun_if.if_snd.ifq_head;
                    443:                        for( *(int *)data = 0; mb != 0; mb = mb->m_next) 
                    444:                                *(int *)data += mb->m_len;
                    445:                } else
                    446:                        *(int *)data = 0;
                    447:                splx(s);
                    448:                break;
                    449:        case FIOSETOWN:
                    450:                return (fsetown(*(int *)data, &tp->tun_sigio));
                    451: 
                    452:        case FIOGETOWN:
                    453:                *(int *)data = fgetown(tp->tun_sigio);
                    454:                return (0);
                    455: 
                    456:        /* This is deprecated, FIOSETOWN should be used instead. */
                    457:        case TIOCSPGRP:
                    458:                return (fsetown(-(*(int *)data), &tp->tun_sigio));
                    459: 
                    460:        /* This is deprecated, FIOGETOWN should be used instead. */
                    461:        case TIOCGPGRP:
                    462:                *(int *)data = -fgetown(tp->tun_sigio);
                    463:                return (0);
                    464: 
                    465:        default:
                    466:                return (ENOTTY);
                    467:        }
                    468:        return (0);
                    469: }
                    470: 
                    471: /*
                    472:  * The cdevsw read interface - reads a packet at a time, or at
                    473:  * least as much of a packet as can be read.
                    474:  */
                    475: static int
                    476: tunread(dev, uio, flag)
                    477:        dev_t dev;
                    478:        struct uio *uio;
                    479:        int flag;
                    480: {
                    481:        int             unit = dev_val(minor(dev));
                    482:        struct tun_softc *tp = &tunctl[unit];
                    483:        struct ifnet    *ifp = &tp->tun_if;
                    484:        struct mbuf     *m, *m0;
                    485:        int             error=0, len, s;
                    486: 
                    487:        TUNDEBUG ("%s%d: read\n", ifp->if_name, ifp->if_unit);
                    488:        if ((tp->tun_flags & TUN_READY) != TUN_READY) {
                    489:                TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name,
                    490:                          ifp->if_unit, tp->tun_flags);
                    491:                return EHOSTDOWN;
                    492:        }
                    493: 
                    494:        tp->tun_flags &= ~TUN_RWAIT;
                    495: 
                    496:        s = splimp();
                    497:        do {
                    498:                IF_DEQUEUE(&ifp->if_snd, m0);
                    499:                if (m0 == 0) {
                    500:                        if (flag & IO_NDELAY) {
                    501:                                splx(s);
                    502:                                return EWOULDBLOCK;
                    503:                        }
                    504:                        tp->tun_flags |= TUN_RWAIT;
                    505:                        if( error = tsleep((caddr_t)tp, PCATCH | (PZERO + 1),
                    506:                                        "tunread", 0)) {
                    507:                                splx(s);
                    508:                                return error;
                    509:                        }
                    510:                }
                    511:        } while (m0 == 0);
                    512:        splx(s);
                    513: 
                    514:        while (m0 && uio->uio_resid > 0 && error == 0) {
                    515:                len = min(uio->uio_resid, m0->m_len);
                    516:                if (len == 0)
                    517:                        break;
                    518:                error = uiomove(mtod(m0, caddr_t), len, uio);
                    519:                MFREE(m0, m);
                    520:                m0 = m;
                    521:        }
                    522: 
                    523:        if (m0) {
                    524:                TUNDEBUG("Dropping mbuf\n");
                    525:                m_freem(m0);
                    526:        }
                    527:        return error;
                    528: }
                    529: 
                    530: /*
                    531:  * the cdevsw write interface - an atomic write is a packet - or else!
                    532:  */
                    533: static int
                    534: tunwrite(dev, uio, flag)
                    535:        dev_t dev;
                    536:        struct uio *uio;
                    537:        int flag;
                    538: {
                    539:        int             unit = dev_val(minor(dev));
                    540:        struct ifnet    *ifp = &tunctl[unit].tun_if;
                    541:        struct mbuf     *top, **mp, *m;
                    542:        int             error=0, s, tlen, mlen;
                    543: 
                    544:        TUNDEBUG("%s%d: tunwrite\n", ifp->if_name, ifp->if_unit);
                    545: 
                    546:        if (uio->uio_resid < 0 || uio->uio_resid > TUNMRU) {
                    547:                TUNDEBUG("%s%d: len=%d!\n", ifp->if_name, ifp->if_unit,
                    548:                    uio->uio_resid);
                    549:                return EIO;
                    550:        }
                    551:        tlen = uio->uio_resid;
                    552: 
                    553:        /* get a header mbuf */
                    554:        MGETHDR(m, M_DONTWAIT, MT_DATA);
                    555:        if (m == NULL)
                    556:                return ENOBUFS;
                    557:        mlen = MHLEN;
                    558: 
                    559:        top = 0;
                    560:        mp = &top;
                    561:        while (error == 0 && uio->uio_resid > 0) {
                    562:                m->m_len = min(mlen, uio->uio_resid);
                    563:                error = uiomove(mtod (m, caddr_t), m->m_len, uio);
                    564:                *mp = m;
                    565:                mp = &m->m_next;
                    566:                if (uio->uio_resid > 0) {
                    567:                        MGET (m, M_DONTWAIT, MT_DATA);
                    568:                        if (m == 0) {
                    569:                                error = ENOBUFS;
                    570:                                break;
                    571:                        }
                    572:                        mlen = MLEN;
                    573:                }
                    574:        }
                    575:        if (error) {
                    576:                if (top)
                    577:                        m_freem (top);
                    578:                return error;
                    579:        }
                    580: 
                    581:        top->m_pkthdr.len = tlen;
                    582:        top->m_pkthdr.rcvif = ifp;
                    583: 
                    584: #if NBPFILTER > 0
                    585:        if (ifp->if_bpf) {
                    586:                /*
                    587:                 * We need to prepend the address family as
                    588:                 * a four byte field.  Cons up a dummy header
                    589:                 * to pacify bpf.  This is safe because bpf
                    590:                 * will only read from the mbuf (i.e., it won't
                    591:                 * try to free it or keep a pointer to it).
                    592:                 */
                    593:                struct mbuf m;
                    594:                u_int af = AF_INET;
                    595: 
                    596:                m.m_next = top;
                    597:                m.m_len = 4;
                    598:                m.m_data = (char *)&af;
                    599: 
                    600:                bpf_mtap(ifp, &m);
                    601:        }
                    602: #endif
                    603: 
                    604: #if INET
                    605:        s = splimp();
                    606:        if (IF_QFULL (&ipintrq)) {
                    607:                IF_DROP(&ipintrq);
                    608:                splx(s);
                    609:                ifp->if_collisions++;
                    610:                m_freem(top);
                    611:                return ENOBUFS;
                    612:        }
                    613:        IF_ENQUEUE(&ipintrq, top);
                    614:        splx(s);
                    615:        ifp->if_ibytes += tlen;
                    616:        ifp->if_ipackets++;
                    617:        schednetisr(NETISR_IP);
                    618: #endif
                    619:        return error;
                    620: }
                    621: 
                    622: /*
                    623:  * tunpoll - the poll interface, this is only useful on reads
                    624:  * really. The write detect always returns true, write never blocks
                    625:  * anyway, it either accepts the packet or drops it.
                    626:  */
                    627: static int
                    628: tunpoll(dev, events, p)
                    629:        dev_t dev;
                    630:        int events;
                    631:        struct proc *p;
                    632: {
                    633:        int             unit = dev_val(minor(dev)), s;
                    634:        struct tun_softc *tp = &tunctl[unit];
                    635:        struct ifnet    *ifp = &tp->tun_if;
                    636:        int             revents = 0;
                    637: 
                    638:        s = splimp();
                    639:        TUNDEBUG("%s%d: tunpoll\n", ifp->if_name, ifp->if_unit);
                    640: 
                    641:        if (events & (POLLIN | POLLRDNORM))
                    642:                if (ifp->if_snd.ifq_len > 0) {
                    643:                        TUNDEBUG("%s%d: tunpoll q=%d\n", ifp->if_name,
                    644:                            ifp->if_unit, ifp->if_snd.ifq_len);
                    645:                        revents |= events & (POLLIN | POLLRDNORM);
                    646:                } else {
                    647:                        TUNDEBUG("%s%d: tunpoll waiting\n", ifp->if_name,
                    648:                            ifp->if_unit);
                    649:                        selrecord(p, &tp->tun_rsel);
                    650:                }
                    651: 
                    652:        if (events & (POLLOUT | POLLWRNORM))
                    653:                revents |= events & (POLLOUT | POLLWRNORM);
                    654: 
                    655:        splx(s);
                    656:        return (revents);
                    657: }
                    658: 
                    659: 
                    660: #endif  /* NTUN */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.