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

1.72    ! christos    1: /*     $NetBSD: if_tun.c,v 1.71 2004/06/06 04:36:29 dyoung 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.72    ! christos   18: __KERNEL_RCSID(0, "$NetBSD: if_tun.c,v 1.71 2004/06/06 04:36:29 dyoung Exp $");
1.1       cgd        19:
1.8       deraadt    20: #include "tun.h"
1.33      jonathan   21:
                     22: #include "opt_inet.h"
1.34      jonathan   23: #include "opt_ns.h"
1.8       deraadt    24:
1.6       deraadt    25: #include <sys/param.h>
1.8       deraadt    26: #include <sys/proc.h>
1.6       deraadt    27: #include <sys/systm.h>
                     28: #include <sys/mbuf.h>
                     29: #include <sys/buf.h>
                     30: #include <sys/protosw.h>
                     31: #include <sys/socket.h>
                     32: #include <sys/ioctl.h>
                     33: #include <sys/errno.h>
                     34: #include <sys/syslog.h>
                     35: #include <sys/select.h>
1.27      mycroft    36: #include <sys/poll.h>
1.8       deraadt    37: #include <sys/file.h>
1.22      christos   38: #include <sys/signalvar.h>
1.23      christos   39: #include <sys/conf.h>
1.9       deraadt    40:
                     41: #include <machine/cpu.h>
1.6       deraadt    42:
                     43: #include <net/if.h>
1.69      tron       44: #include <net/if_types.h>
1.6       deraadt    45: #include <net/netisr.h>
                     46: #include <net/route.h>
1.1       cgd        47:
1.30      is         48:
1.1       cgd        49: #ifdef INET
1.6       deraadt    50: #include <netinet/in.h>
                     51: #include <netinet/in_systm.h>
                     52: #include <netinet/in_var.h>
                     53: #include <netinet/ip.h>
1.30      is         54: #include <netinet/if_inarp.h>
1.1       cgd        55: #endif
                     56:
                     57: #ifdef NS
1.6       deraadt    58: #include <netns/ns.h>
                     59: #include <netns/ns_if.h>
1.1       cgd        60: #endif
                     61:
1.8       deraadt    62: #include "bpfilter.h"
                     63: #if NBPFILTER > 0
                     64: #include <sys/time.h>
                     65: #include <net/bpf.h>
                     66: #endif
                     67:
                     68: #include <net/if_tun.h>
                     69:
1.29      christos   70: #define TUNDEBUG       if (tundebug) printf
1.6       deraadt    71: int    tundebug = 0;
1.1       cgd        72:
1.6       deraadt    73: extern int ifqmaxlen;
1.22      christos   74: void   tunattach __P((int));
1.46      atatat     75: LIST_HEAD(, tun_softc) tun_softc_list;
1.70      pk         76: LIST_HEAD(, tun_softc) tunz_softc_list;
1.46      atatat     77: static struct simplelock tun_softc_lock;
1.6       deraadt    78:
1.22      christos   79: int    tun_ioctl __P((struct ifnet *, u_long, caddr_t));
                     80: int    tun_output __P((struct ifnet *, struct mbuf *, struct sockaddr *,
                     81:                       struct rtentry *rt));
1.46      atatat     82: int    tun_clone_create __P((struct if_clone *, int));
                     83: void   tun_clone_destroy __P((struct ifnet *));
1.6       deraadt    84:
1.46      atatat     85: struct if_clone tun_cloner =
                     86:     IF_CLONE_INITIALIZER("tun", tun_clone_create, tun_clone_destroy);
                     87:
                     88: static void tunattach0 __P((struct tun_softc *));
1.26      pk         89: static void tuninit __P((struct tun_softc *));
1.50      itojun     90: #ifdef ALTQ
                     91: static void tunstart __P((struct ifnet *));
                     92: #endif
1.46      atatat     93: static struct tun_softc *tun_find_unit __P((dev_t));
1.70      pk         94: static struct tun_softc *tun_find_zunit __P((int));
1.53      gehenna    95:
                     96: dev_type_open(tunopen);
                     97: dev_type_close(tunclose);
                     98: dev_type_read(tunread);
                     99: dev_type_write(tunwrite);
                    100: dev_type_ioctl(tunioctl);
                    101: dev_type_poll(tunpoll);
1.56      jdolecek  102: dev_type_kqfilter(tunkqfilter);
1.53      gehenna   103:
                    104: const struct cdevsw tun_cdevsw = {
                    105:        tunopen, tunclose, tunread, tunwrite, tunioctl,
1.56      jdolecek  106:        nostop, notty, tunpoll, nommap, tunkqfilter,
1.53      gehenna   107: };
1.6       deraadt   108:
1.8       deraadt   109: void
                    110: tunattach(unused)
                    111:        int unused;
                    112: {
1.46      atatat    113:
                    114:        simple_lock_init(&tun_softc_lock);
                    115:        LIST_INIT(&tun_softc_list);
1.70      pk        116:        LIST_INIT(&tunz_softc_list);
1.46      atatat    117:        if_clone_attach(&tun_cloner);
                    118: }
                    119:
1.70      pk        120: /*
                    121:  * Find driver instance from dev_t.
                    122:  * Call at splnet().
                    123:  * Returns with tp locked (if found).
                    124:  */
                    125: static struct tun_softc *
                    126: tun_find_unit(dev)
                    127:        dev_t dev;
                    128: {
                    129:        struct tun_softc *tp;
                    130:        int unit = minor(dev);
                    131:
                    132:        simple_lock(&tun_softc_lock);
                    133:        LIST_FOREACH(tp, &tun_softc_list, tun_list)
                    134:                if (unit == tp->tun_unit)
                    135:                        break;
                    136:        if (tp)
                    137:                simple_lock(&tp->tun_lock);
                    138:        simple_unlock(&tun_softc_lock);
                    139:
                    140:        return (tp);
                    141: }
                    142:
                    143: /*
                    144:  * Find zombie driver instance by unit number.
                    145:  * Call at splnet().
                    146:  * Remove tp from list and return it unlocked (if found).
                    147:  */
                    148: static struct tun_softc *
                    149: tun_find_zunit(unit)
                    150:        int unit;
                    151: {
                    152:        struct tun_softc *tp;
                    153:
                    154:        simple_lock(&tun_softc_lock);
                    155:        LIST_FOREACH(tp, &tunz_softc_list, tun_list)
                    156:                if (unit == tp->tun_unit)
                    157:                        break;
                    158:        if (tp)
                    159:                LIST_REMOVE(tp, tun_list);
                    160:        simple_unlock(&tun_softc_lock);
                    161: #ifdef DIAGNOSTIC
                    162:        if (tp != NULL && (tp->tun_flags & (TUN_INITED|TUN_OPEN)) != TUN_OPEN)
                    163:                printf("tun%d: inconsistent flags: %x\n", unit, tp->tun_flags);
                    164: #endif
                    165:
                    166:        return (tp);
                    167: }
                    168:
1.46      atatat    169: int
                    170: tun_clone_create(ifc, unit)
                    171:        struct if_clone *ifc;
                    172:        int unit;
                    173: {
1.70      pk        174:        struct tun_softc *tp;
1.46      atatat    175:
1.70      pk        176:        if ((tp = tun_find_zunit(unit)) == NULL) {
                    177:                /* Allocate a new instance */
                    178:                tp = malloc(sizeof(struct tun_softc), M_DEVBUF, M_WAITOK);
                    179:                (void)memset(tp, 0, sizeof(struct tun_softc));
1.46      atatat    180:
1.70      pk        181:                tp->tun_unit = unit;
                    182:                simple_lock_init(&tp->tun_lock);
                    183:        } else {
                    184:                /* Revive tunnel instance; clear ifp part */
                    185:                (void)memset(&tp->tun_if, 0, sizeof(struct ifnet));
                    186:        }
1.46      atatat    187:
1.70      pk        188:        (void)snprintf(tp->tun_if.if_xname, sizeof(tp->tun_if.if_xname),
                    189:                        "%s%d", ifc->ifc_name, unit);
                    190:        tunattach0(tp);
                    191:        tp->tun_flags |= TUN_INITED;
1.46      atatat    192:
                    193:        simple_lock(&tun_softc_lock);
1.70      pk        194:        LIST_INSERT_HEAD(&tun_softc_list, tp, tun_list);
1.46      atatat    195:        simple_unlock(&tun_softc_lock);
                    196:
                    197:        return (0);
                    198: }
                    199:
                    200: void
1.70      pk        201: tunattach0(tp)
                    202:        struct tun_softc *tp;
1.46      atatat    203: {
1.70      pk        204:        struct ifnet *ifp;
1.46      atatat    205:
1.70      pk        206:        ifp = &tp->tun_if;
                    207:        ifp->if_softc = tp;
1.46      atatat    208:        ifp->if_mtu = TUNMTU;
                    209:        ifp->if_ioctl = tun_ioctl;
                    210:        ifp->if_output = tun_output;
1.50      itojun    211: #ifdef ALTQ
                    212:        ifp->if_start = tunstart;
                    213: #endif
1.46      atatat    214:        ifp->if_flags = IFF_POINTOPOINT;
1.69      tron      215:        ifp->if_type = IFT_TUNNEL;
1.46      atatat    216:        ifp->if_snd.ifq_maxlen = ifqmaxlen;
                    217:        ifp->if_collisions = 0;
                    218:        ifp->if_ierrors = 0;
                    219:        ifp->if_oerrors = 0;
                    220:        ifp->if_ipackets = 0;
                    221:        ifp->if_opackets = 0;
1.58      jdolecek  222:        ifp->if_ibytes   = 0;
                    223:        ifp->if_obytes   = 0;
1.46      atatat    224:        ifp->if_dlt = DLT_NULL;
1.50      itojun    225:        IFQ_SET_READY(&ifp->if_snd);
1.46      atatat    226:        if_attach(ifp);
                    227:        if_alloc_sadl(ifp);
                    228: #if NBPFILTER > 0
                    229:        bpfattach(ifp, DLT_NULL, sizeof(u_int32_t));
                    230: #endif
                    231: }
                    232:
                    233: void
                    234: tun_clone_destroy(ifp)
1.8       deraadt   235:        struct ifnet *ifp;
1.46      atatat    236: {
                    237:        struct tun_softc *tp = (void *)ifp;
1.70      pk        238:        int s, zombie = 0;
1.8       deraadt   239:
1.70      pk        240:        s = splnet();
1.46      atatat    241:        simple_lock(&tun_softc_lock);
                    242:        simple_lock(&tp->tun_lock);
                    243:        LIST_REMOVE(tp, tun_list);
1.70      pk        244:        if (tp->tun_flags & TUN_OPEN) {
                    245:                /* Hang on to storage until last close */
                    246:                zombie = 1;
                    247:                tp->tun_flags &= ~TUN_INITED;
                    248:                LIST_INSERT_HEAD(&tunz_softc_list, tp, tun_list);
                    249:        }
1.46      atatat    250:        simple_unlock(&tun_softc_lock);
                    251:
1.70      pk        252:        IF_PURGE(&ifp->if_snd);
                    253:        ifp->if_flags &= ~IFF_RUNNING;
                    254:
1.46      atatat    255:        if (tp->tun_flags & TUN_RWAIT) {
                    256:                tp->tun_flags &= ~TUN_RWAIT;
                    257:                wakeup((caddr_t)tp);
                    258:        }
1.64      jdolecek  259:        if (tp->tun_flags & TUN_ASYNC && tp->tun_pgid)
1.66      christos  260:                fownsignal(tp->tun_pgid, SIGIO, POLL_HUP, 0, NULL);
1.64      jdolecek  261:
1.46      atatat    262:        selwakeup(&tp->tun_rsel);
1.8       deraadt   263:
1.70      pk        264:        simple_unlock(&tp->tun_lock);
                    265:        splx(s);
                    266:
1.8       deraadt   267: #if NBPFILTER > 0
1.46      atatat    268:        bpfdetach(ifp);
1.8       deraadt   269: #endif
1.46      atatat    270:        if_detach(ifp);
                    271:
1.70      pk        272:        if (!zombie)
                    273:                free(tp, M_DEVBUF);
1.8       deraadt   274: }
                    275:
1.6       deraadt   276: /*
                    277:  * tunnel open - must be superuser & the device must be
                    278:  * configured in
                    279:  */
                    280: int
1.63      fvdl      281: tunopen(dev, flag, mode, p)
1.6       deraadt   282:        dev_t   dev;
                    283:        int     flag, mode;
1.63      fvdl      284:        struct proc *p;
1.6       deraadt   285: {
                    286:        struct ifnet    *ifp;
1.8       deraadt   287:        struct tun_softc *tp;
1.70      pk        288:        int     s, error;
1.1       cgd       289:
1.22      christos  290:        if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
1.5       deraadt   291:                return (error);
                    292:
1.46      atatat    293:        if (NTUN < 1)
1.6       deraadt   294:                return (ENXIO);
1.46      atatat    295:
1.70      pk        296:        s = splnet();
1.46      atatat    297:        tp = tun_find_unit(dev);
1.52      atatat    298:
1.70      pk        299:        if (tp == NULL) {
1.52      atatat    300:                (void)tun_clone_create(&tun_cloner, minor(dev));
                    301:                tp = tun_find_unit(dev);
1.70      pk        302:                if (tp == NULL) {
                    303:                        error = ENXIO;
                    304:                        goto out_nolock;
                    305:                }
1.52      atatat    306:        }
1.46      atatat    307:
                    308:        if (tp->tun_flags & TUN_OPEN) {
1.70      pk        309:                error = EBUSY;
                    310:                goto out;
1.46      atatat    311:        }
                    312:
1.6       deraadt   313:        ifp = &tp->tun_if;
                    314:        tp->tun_flags |= TUN_OPEN;
1.24      thorpej   315:        TUNDEBUG("%s: open\n", ifp->if_xname);
1.70      pk        316: out:
1.46      atatat    317:        simple_unlock(&tp->tun_lock);
1.70      pk        318: out_nolock:
                    319:        splx(s);
                    320:        return (error);
1.1       cgd       321: }
                    322:
1.6       deraadt   323: /*
                    324:  * tunclose - close the device - mark i/f down & delete
                    325:  * routing info
                    326:  */
                    327: int
1.63      fvdl      328: tunclose(dev, flag, mode, p)
1.6       deraadt   329:        dev_t   dev;
                    330:        int     flag;
1.22      christos  331:        int     mode;
1.63      fvdl      332:        struct proc *p;
1.6       deraadt   333: {
1.46      atatat    334:        int     s;
                    335:        struct tun_softc *tp;
                    336:        struct ifnet    *ifp;
1.6       deraadt   337:
1.70      pk        338:        s = splnet();
                    339:        if ((tp = tun_find_zunit(minor(dev))) != NULL) {
                    340:                /* interface was "destroyed" before the close */
                    341:                free(tp, M_DEVBUF);
                    342:                goto out_nolock;
                    343:        }
1.46      atatat    344:
1.70      pk        345:        if ((tp = tun_find_unit(dev)) == NULL)
                    346:                goto out_nolock;
1.46      atatat    347:
                    348:        ifp = &tp->tun_if;
                    349:
1.10      andrew    350:        tp->tun_flags &= ~TUN_OPEN;
1.6       deraadt   351:
                    352:        /*
                    353:         * junk all pending output
                    354:         */
1.50      itojun    355:        IFQ_PURGE(&ifp->if_snd);
1.6       deraadt   356:
                    357:        if (ifp->if_flags & IFF_UP) {
                    358:                if_down(ifp);
1.8       deraadt   359:                if (ifp->if_flags & IFF_RUNNING) {
1.17      mycroft   360:                        /* find internet addresses and delete routes */
1.39      augustss  361:                        struct ifaddr *ifa;
1.47      matt      362:                        TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
1.38      itojun    363: #ifdef INET
1.18      mycroft   364:                                if (ifa->ifa_addr->sa_family == AF_INET) {
                    365:                                        rtinit(ifa, (int)RTM_DELETE,
1.26      pk        366:                                               tp->tun_flags & TUN_DSTADDR
                    367:                                                        ? RTF_HOST
                    368:                                                        : 0);
1.18      mycroft   369:                                }
1.38      itojun    370: #endif
1.11      deraadt   371:                        }
1.8       deraadt   372:                }
1.6       deraadt   373:        }
1.64      jdolecek  374:        tp->tun_pgid = 0;
1.56      jdolecek  375:        selnotify(&tp->tun_rsel, 0);
1.70      pk        376:
1.24      thorpej   377:        TUNDEBUG ("%s: closed\n", ifp->if_xname);
1.46      atatat    378:        simple_unlock(&tp->tun_lock);
1.70      pk        379: out_nolock:
                    380:        splx(s);
1.6       deraadt   381:        return (0);
1.1       cgd       382: }
                    383:
1.70      pk        384: /*
                    385:  * Call at splnet() with tp locked.
                    386:  */
1.26      pk        387: static void
1.24      thorpej   388: tuninit(tp)
                    389:        struct tun_softc *tp;
1.6       deraadt   390: {
                    391:        struct ifnet    *ifp = &tp->tun_if;
1.46      atatat    392:        struct ifaddr   *ifa;
1.8       deraadt   393:
1.24      thorpej   394:        TUNDEBUG("%s: tuninit\n", ifp->if_xname);
1.6       deraadt   395:
                    396:        ifp->if_flags |= IFF_UP | IFF_RUNNING;
1.8       deraadt   397:
1.26      pk        398:        tp->tun_flags &= ~(TUN_IASET|TUN_DSTADDR);
1.47      matt      399:        TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
1.38      itojun    400: #ifdef INET
1.11      deraadt   401:                if (ifa->ifa_addr->sa_family == AF_INET) {
1.17      mycroft   402:                        struct sockaddr_in *sin;
1.11      deraadt   403:
1.17      mycroft   404:                        sin = satosin(ifa->ifa_addr);
                    405:                        if (sin && sin->sin_addr.s_addr)
                    406:                                tp->tun_flags |= TUN_IASET;
                    407:
1.26      pk        408:                        if (ifp->if_flags & IFF_POINTOPOINT) {
                    409:                                sin = satosin(ifa->ifa_dstaddr);
                    410:                                if (sin && sin->sin_addr.s_addr)
                    411:                                        tp->tun_flags |= TUN_DSTADDR;
                    412:                        }
1.11      deraadt   413:                }
1.38      itojun    414: #endif
1.18      mycroft   415:        }
1.8       deraadt   416:
1.26      pk        417:        return;
1.1       cgd       418: }
                    419:
                    420: /*
                    421:  * Process an ioctl request.
                    422:  */
                    423: int
1.22      christos  424: tun_ioctl(ifp, cmd, data)
1.6       deraadt   425:        struct ifnet *ifp;
1.25      mycroft   426:        u_long cmd;
1.6       deraadt   427:        caddr_t data;
                    428: {
                    429:        int             error = 0, s;
1.46      atatat    430:        struct tun_softc *tp = (struct tun_softc *)(ifp->if_softc);
                    431:
1.70      pk        432:        s = splnet();
1.46      atatat    433:        simple_lock(&tp->tun_lock);
1.6       deraadt   434:
1.61      itojun    435:        switch (cmd) {
1.6       deraadt   436:        case SIOCSIFADDR:
1.70      pk        437:                tuninit(tp);
1.24      thorpej   438:                TUNDEBUG("%s: address set\n", ifp->if_xname);
1.6       deraadt   439:                break;
                    440:        case SIOCSIFDSTADDR:
1.70      pk        441:                tuninit(tp);
1.24      thorpej   442:                TUNDEBUG("%s: destination address set\n", ifp->if_xname);
1.6       deraadt   443:                break;
1.26      pk        444:        case SIOCSIFBRDADDR:
                    445:                TUNDEBUG("%s: broadcast address set\n", ifp->if_xname);
                    446:                break;
1.31      matt      447:        case SIOCSIFMTU: {
                    448:                struct ifreq *ifr = (struct ifreq *) data;
                    449:                if (ifr->ifr_mtu > TUNMTU || ifr->ifr_mtu < 576) {
                    450:                    error = EINVAL;
                    451:                    break;
                    452:                }
                    453:                TUNDEBUG("%s: interface mtu set\n", ifp->if_xname);
                    454:                ifp->if_mtu = ifr->ifr_mtu;
1.32      matt      455:                break;
                    456:        }
                    457:        case SIOCADDMULTI:
                    458:        case SIOCDELMULTI: {
                    459:                struct ifreq *ifr = (struct ifreq *) data;
                    460:                if (ifr == 0) {
                    461:                        error = EAFNOSUPPORT;           /* XXX */
                    462:                        break;
                    463:                }
                    464:                switch (ifr->ifr_addr.sa_family) {
                    465: #ifdef INET
                    466:                case AF_INET:
                    467:                        break;
                    468: #endif
                    469:                default:
                    470:                        error = EAFNOSUPPORT;
                    471:                        break;
                    472:                }
1.31      matt      473:                break;
                    474:        }
1.38      itojun    475:        case SIOCSIFFLAGS:
                    476:                break;
1.6       deraadt   477:        default:
                    478:                error = EINVAL;
                    479:        }
1.70      pk        480:
                    481:        simple_unlock(&tp->tun_lock);
1.6       deraadt   482:        splx(s);
                    483:        return (error);
1.1       cgd       484: }
                    485:
                    486: /*
1.22      christos  487:  * tun_output - queue packets from higher level ready to put out.
1.1       cgd       488:  */
1.6       deraadt   489: int
1.22      christos  490: tun_output(ifp, m0, dst, rt)
1.6       deraadt   491:        struct ifnet   *ifp;
                    492:        struct mbuf    *m0;
                    493:        struct sockaddr *dst;
1.12      deraadt   494:        struct rtentry *rt;
1.6       deraadt   495: {
1.24      thorpej   496:        struct tun_softc *tp = ifp->if_softc;
1.38      itojun    497: #ifdef INET
1.6       deraadt   498:        int             s;
1.51      itojun    499:        int             error;
1.38      itojun    500: #endif
1.58      jdolecek  501:        int             mlen;
1.50      itojun    502:        ALTQ_DECL(struct altq_pktattr pktattr;)
1.6       deraadt   503:
1.70      pk        504:        s = splnet();
1.46      atatat    505:        simple_lock(&tp->tun_lock);
1.24      thorpej   506:        TUNDEBUG ("%s: tun_output\n", ifp->if_xname);
1.1       cgd       507:
1.8       deraadt   508:        if ((tp->tun_flags & TUN_READY) != TUN_READY) {
1.24      thorpej   509:                TUNDEBUG ("%s: not ready 0%o\n", ifp->if_xname,
                    510:                          tp->tun_flags);
1.8       deraadt   511:                m_freem (m0);
1.70      pk        512:                error = EHOSTDOWN;
                    513:                goto out;
1.8       deraadt   514:        }
                    515:
1.50      itojun    516:        /*
                    517:         * if the queueing discipline needs packet classification,
                    518:         * do it before prepending link headers.
                    519:         */
                    520:        IFQ_CLASSIFY(&ifp->if_snd, m0, dst->sa_family, &pktattr);
1.70      pk        521:
1.8       deraadt   522: #if NBPFILTER > 0
1.72    ! christos  523:        if (ifp->if_bpf)
        !           524:                bpf_mtap_af(ifp->if_bpf, dst->sa_family, m0);
1.8       deraadt   525: #endif
                    526:
1.6       deraadt   527:        switch(dst->sa_family) {
1.1       cgd       528: #ifdef INET
1.6       deraadt   529:        case AF_INET:
1.26      pk        530:                if (tp->tun_flags & TUN_PREPADDR) {
                    531:                        /* Simple link-layer header */
                    532:                        M_PREPEND(m0, dst->sa_len, M_DONTWAIT);
                    533:                        if (m0 == NULL) {
                    534:                                IF_DROP(&ifp->if_snd);
1.70      pk        535:                                error = ENOBUFS;
                    536:                                goto out;
1.26      pk        537:                        }
                    538:                        bcopy(dst, mtod(m0, char *), dst->sa_len);
                    539:                }
1.36      sommerfe  540:                /* FALLTHROUGH */
                    541:        case AF_UNSPEC:
1.50      itojun    542:                IFQ_ENQUEUE(&ifp->if_snd, m0, &pktattr, error);
                    543:                if (error) {
1.6       deraadt   544:                        ifp->if_collisions++;
1.70      pk        545:                        error = EAFNOSUPPORT;
                    546:                        goto out;
1.6       deraadt   547:                }
1.58      jdolecek  548:                mlen = m0->m_pkthdr.len;
1.6       deraadt   549:                ifp->if_opackets++;
1.58      jdolecek  550:                ifp->if_obytes += mlen;
1.6       deraadt   551:                break;
1.1       cgd       552: #endif
1.6       deraadt   553:        default:
                    554:                m_freem(m0);
1.70      pk        555:                error = EAFNOSUPPORT;
                    556:                goto out;
1.6       deraadt   557:        }
                    558:
                    559:        if (tp->tun_flags & TUN_RWAIT) {
                    560:                tp->tun_flags &= ~TUN_RWAIT;
                    561:                wakeup((caddr_t)tp);
                    562:        }
1.64      jdolecek  563:        if (tp->tun_flags & TUN_ASYNC && tp->tun_pgid)
1.66      christos  564:                fownsignal(tp->tun_pgid, SIGIO, POLL_IN, POLLIN|POLLRDNORM,
                    565:                    NULL);
1.64      jdolecek  566:
1.56      jdolecek  567:        selnotify(&tp->tun_rsel, 0);
1.70      pk        568: out:
1.46      atatat    569:        simple_unlock(&tp->tun_lock);
1.70      pk        570:        splx(s);
1.26      pk        571:        return (0);
1.1       cgd       572: }
                    573:
                    574: /*
                    575:  * the cdevsw interface is now pretty minimal.
                    576:  */
1.6       deraadt   577: int
1.63      fvdl      578: tunioctl(dev, cmd, data, flag, p)
1.6       deraadt   579:        dev_t           dev;
1.15      cgd       580:        u_long          cmd;
1.6       deraadt   581:        caddr_t         data;
                    582:        int             flag;
1.63      fvdl      583:        struct proc     *p;
1.6       deraadt   584: {
1.46      atatat    585:        struct tun_softc *tp;
1.70      pk        586:        int s, error = 0;
1.46      atatat    587:
1.70      pk        588:        s = splnet();
1.46      atatat    589:        tp = tun_find_unit(dev);
                    590:
                    591:        /* interface was "destroyed" already */
1.70      pk        592:        if (tp == NULL) {
                    593:                error = ENXIO;
                    594:                goto out_nolock;
                    595:        }
1.6       deraadt   596:
                    597:        switch (cmd) {
                    598:        case TUNSDEBUG:
                    599:                tundebug = *(int *)data;
                    600:                break;
1.26      pk        601:
1.6       deraadt   602:        case TUNGDEBUG:
                    603:                *(int *)data = tundebug;
                    604:                break;
1.26      pk        605:
                    606:        case TUNSIFMODE:
1.31      matt      607:                switch (*(int *)data & (IFF_POINTOPOINT|IFF_BROADCAST)) {
1.26      pk        608:                case IFF_POINTOPOINT:
                    609:                case IFF_BROADCAST:
                    610:                        if (tp->tun_if.if_flags & IFF_UP) {
1.70      pk        611:                                error = EBUSY;
                    612:                                goto out;
1.26      pk        613:                        }
                    614:                        tp->tun_if.if_flags &=
1.31      matt      615:                                ~(IFF_BROADCAST|IFF_POINTOPOINT|IFF_MULTICAST);
1.26      pk        616:                        tp->tun_if.if_flags |= *(int *)data;
                    617:                        break;
                    618:                default:
1.70      pk        619:                        error = EINVAL;
                    620:                        goto out;
1.26      pk        621:                }
                    622:                break;
                    623:
                    624:        case TUNSLMODE:
                    625:                if (*(int *)data)
                    626:                        tp->tun_flags |= TUN_PREPADDR;
                    627:                else
                    628:                        tp->tun_flags &= ~TUN_PREPADDR;
                    629:                break;
                    630:
1.6       deraadt   631:        case FIONBIO:
                    632:                if (*(int *)data)
                    633:                        tp->tun_flags |= TUN_NBIO;
                    634:                else
                    635:                        tp->tun_flags &= ~TUN_NBIO;
                    636:                break;
1.26      pk        637:
1.6       deraadt   638:        case FIOASYNC:
                    639:                if (*(int *)data)
                    640:                        tp->tun_flags |= TUN_ASYNC;
                    641:                else
                    642:                        tp->tun_flags &= ~TUN_ASYNC;
                    643:                break;
1.26      pk        644:
1.6       deraadt   645:        case FIONREAD:
                    646:                if (tp->tun_if.if_snd.ifq_head)
1.19      pk        647:                        *(int *)data = tp->tun_if.if_snd.ifq_head->m_pkthdr.len;
1.70      pk        648:                else
1.6       deraadt   649:                        *(int *)data = 0;
                    650:                break;
1.26      pk        651:
1.6       deraadt   652:        case TIOCSPGRP:
1.64      jdolecek  653:        case FIOSETOWN:
                    654:                error = fsetown(p, &tp->tun_pgid, cmd, data);
1.6       deraadt   655:                break;
1.26      pk        656:
1.6       deraadt   657:        case TIOCGPGRP:
1.64      jdolecek  658:        case FIOGETOWN:
                    659:                error = fgetown(p, tp->tun_pgid, cmd, data);
1.6       deraadt   660:                break;
1.26      pk        661:
1.6       deraadt   662:        default:
1.70      pk        663:                error = ENOTTY;
1.6       deraadt   664:        }
1.70      pk        665:
                    666: out:
1.46      atatat    667:        simple_unlock(&tp->tun_lock);
1.70      pk        668: out_nolock:
                    669:        splx(s);
1.64      jdolecek  670:        return (error);
1.1       cgd       671: }
                    672:
                    673: /*
1.6       deraadt   674:  * The cdevsw read interface - reads a packet at a time, or at
                    675:  * least as much of a packet as can be read.
1.1       cgd       676:  */
1.6       deraadt   677: int
1.22      christos  678: tunread(dev, uio, ioflag)
1.6       deraadt   679:        dev_t           dev;
                    680:        struct uio      *uio;
1.22      christos  681:        int             ioflag;
1.6       deraadt   682: {
1.46      atatat    683:        struct tun_softc *tp;
                    684:        struct ifnet    *ifp;
1.6       deraadt   685:        struct mbuf     *m, *m0;
1.70      pk        686:        int             error = 0, len, s, index;
1.46      atatat    687:
1.70      pk        688:        s = splnet();
1.46      atatat    689:        tp = tun_find_unit(dev);
                    690:
                    691:        /* interface was "destroyed" already */
1.70      pk        692:        if (tp == NULL) {
                    693:                error = ENXIO;
                    694:                goto out_nolock;
                    695:        }
1.46      atatat    696:
                    697:        index = tp->tun_if.if_index;
                    698:        ifp = &tp->tun_if;
1.6       deraadt   699:
1.24      thorpej   700:        TUNDEBUG ("%s: read\n", ifp->if_xname);
1.8       deraadt   701:        if ((tp->tun_flags & TUN_READY) != TUN_READY) {
1.26      pk        702:                TUNDEBUG ("%s: not ready 0%o\n", ifp->if_xname, tp->tun_flags);
1.70      pk        703:                error = EHOSTDOWN;
                    704:                goto out;
1.8       deraadt   705:        }
                    706:
1.6       deraadt   707:        tp->tun_flags &= ~TUN_RWAIT;
                    708:
                    709:        do {
1.50      itojun    710:                IFQ_DEQUEUE(&ifp->if_snd, m0);
1.6       deraadt   711:                if (m0 == 0) {
                    712:                        if (tp->tun_flags & TUN_NBIO) {
1.70      pk        713:                                error = EWOULDBLOCK;
                    714:                                goto out;
1.6       deraadt   715:                        }
                    716:                        tp->tun_flags |= TUN_RWAIT;
1.70      pk        717:                        if (ltsleep((caddr_t)tp, PZERO|PCATCH|PNORELOCK,
                    718:                                        "tunread", 0, &tp->tun_lock) != 0) {
                    719:                                error = EINTR;
                    720:                                goto out_nolock;
1.46      atatat    721:                        } else {
                    722:                                /*
                    723:                                 * Maybe the interface was destroyed while
                    724:                                 * we were sleeping, so let's ensure that
                    725:                                 * we're looking at the same (valid) tun
                    726:                                 * interface before looping.
                    727:                                 */
                    728:                                tp = tun_find_unit(dev);
1.70      pk        729:                                if (tp == NULL) {
                    730:                                        error = ENXIO;
                    731:                                        goto out_nolock;
                    732:                                }
                    733:                                if (tp->tun_if.if_index != index) {
                    734:                                        error = ENXIO;
                    735:                                        goto out;
1.46      atatat    736:                                }
1.26      pk        737:                        }
1.6       deraadt   738:                }
                    739:        } while (m0 == 0);
1.70      pk        740:
                    741:        simple_unlock(&tp->tun_lock);
1.6       deraadt   742:        splx(s);
                    743:
1.70      pk        744:        /* Copy the mbuf chain */
1.6       deraadt   745:        while (m0 && uio->uio_resid > 0 && error == 0) {
1.13      deraadt   746:                len = min(uio->uio_resid, m0->m_len);
1.45      itojun    747:                if (len != 0)
                    748:                        error = uiomove(mtod(m0, caddr_t), len, uio);
1.6       deraadt   749:                MFREE(m0, m);
                    750:                m0 = m;
                    751:        }
                    752:
                    753:        if (m0) {
                    754:                TUNDEBUG("Dropping mbuf\n");
                    755:                m_freem(m0);
                    756:        }
1.19      pk        757:        if (error)
                    758:                ifp->if_ierrors++;
1.70      pk        759:
                    760:        return (error);
                    761:
                    762: out:
1.46      atatat    763:        simple_unlock(&tp->tun_lock);
1.70      pk        764: out_nolock:
                    765:        splx(s);
1.26      pk        766:        return (error);
1.1       cgd       767: }
                    768:
                    769: /*
                    770:  * the cdevsw write interface - an atomic write is a packet - or else!
                    771:  */
1.6       deraadt   772: int
1.22      christos  773: tunwrite(dev, uio, ioflag)
1.8       deraadt   774:        dev_t           dev;
1.6       deraadt   775:        struct uio      *uio;
1.22      christos  776:        int             ioflag;
1.6       deraadt   777: {
1.46      atatat    778:        struct tun_softc *tp;
                    779:        struct ifnet    *ifp;
1.6       deraadt   780:        struct mbuf     *top, **mp, *m;
1.26      pk        781:        struct ifqueue  *ifq;
                    782:        struct sockaddr dst;
1.70      pk        783:        int             isr, error = 0, s, tlen, mlen;
1.6       deraadt   784:
1.70      pk        785:        s = splnet();
1.46      atatat    786:        tp = tun_find_unit(dev);
                    787:
                    788:        /* interface was "destroyed" already */
1.70      pk        789:        if (tp == NULL) {
                    790:                error = ENXIO;
                    791:                goto out_nolock;
                    792:        }
                    793:
                    794:        /* Unlock until we've got the data */
                    795:        simple_unlock(&tp->tun_lock);
                    796:        splx(s);
1.46      atatat    797:
                    798:        ifp = &tp->tun_if;
                    799:
1.24      thorpej   800:        TUNDEBUG("%s: tunwrite\n", ifp->if_xname);
1.6       deraadt   801:
1.26      pk        802:        if (tp->tun_flags & TUN_PREPADDR) {
1.46      atatat    803:                if (uio->uio_resid < sizeof(dst)) {
1.70      pk        804:                        error = EIO;
                    805:                        goto out0;
1.46      atatat    806:                }
1.26      pk        807:                error = uiomove((caddr_t)&dst, sizeof(dst), uio);
                    808:                if (dst.sa_len > sizeof(dst)) {
                    809:                        /* Duh.. */
                    810:                        char discard;
                    811:                        int n = dst.sa_len - sizeof(dst);
                    812:                        while (n--)
1.46      atatat    813:                                if ((error = uiomove(&discard, 1, uio)) != 0) {
1.70      pk        814:                                        goto out0;
1.46      atatat    815:                                }
1.26      pk        816:                }
                    817:        } else {
                    818: #ifdef INET
                    819:                dst.sa_family = AF_INET;
                    820: #endif
                    821:        }
                    822:
1.54      simonb    823:        if (uio->uio_resid > TUNMTU) {
1.37      mjacob    824:                TUNDEBUG("%s: len=%lu!\n", ifp->if_xname,
                    825:                    (unsigned long)uio->uio_resid);
1.70      pk        826:                error = EIO;
                    827:                goto out0;
1.6       deraadt   828:        }
1.26      pk        829:
                    830:        switch (dst.sa_family) {
                    831: #ifdef INET
                    832:        case AF_INET:
                    833:                ifq = &ipintrq;
                    834:                isr = NETISR_IP;
                    835:                break;
                    836: #endif
                    837:        default:
1.70      pk        838:                error = EAFNOSUPPORT;
                    839:                goto out0;
1.26      pk        840:        }
                    841:
1.8       deraadt   842:        tlen = uio->uio_resid;
                    843:
                    844:        /* get a header mbuf */
                    845:        MGETHDR(m, M_DONTWAIT, MT_DATA);
1.46      atatat    846:        if (m == NULL) {
1.70      pk        847:                error = ENOBUFS;
                    848:                goto out0;
1.46      atatat    849:        }
1.8       deraadt   850:        mlen = MHLEN;
                    851:
1.68      tron      852:        top = NULL;
1.6       deraadt   853:        mp = &top;
                    854:        while (error == 0 && uio->uio_resid > 0) {
1.13      deraadt   855:                m->m_len = min(mlen, uio->uio_resid);
1.68      tron      856:                error = uiomove(mtod(m, caddr_t), m->m_len, uio);
1.6       deraadt   857:                *mp = m;
                    858:                mp = &m->m_next;
1.68      tron      859:                if (error == 0 && uio->uio_resid > 0) {
                    860:                        MGET(m, M_DONTWAIT, MT_DATA);
                    861:                        if (m == NULL) {
1.8       deraadt   862:                                error = ENOBUFS;
                    863:                                break;
                    864:                        }
                    865:                        mlen = MLEN;
                    866:                }
1.6       deraadt   867:        }
                    868:        if (error) {
1.68      tron      869:                if (top != NULL)
1.8       deraadt   870:                        m_freem (top);
1.19      pk        871:                ifp->if_ierrors++;
1.70      pk        872:                goto out0;
1.6       deraadt   873:        }
                    874:
1.8       deraadt   875:        top->m_pkthdr.len = tlen;
                    876:        top->m_pkthdr.rcvif = ifp;
                    877:
                    878: #if NBPFILTER > 0
1.72    ! christos  879:        if (ifp->if_bpf)
        !           880:                bpf_mtap_af(ifp->if_bpf, AF_INET, top);
1.8       deraadt   881: #endif
1.6       deraadt   882:
1.43      thorpej   883:        s = splnet();
1.70      pk        884:        simple_lock(&tp->tun_lock);
                    885:        if ((tp->tun_flags & TUN_INITED) == 0) {
                    886:                /* Interface was destroyed */
                    887:                error = ENXIO;
                    888:                goto out;
                    889:        }
1.26      pk        890:        if (IF_QFULL(ifq)) {
                    891:                IF_DROP(ifq);
1.6       deraadt   892:                ifp->if_collisions++;
                    893:                m_freem(top);
1.70      pk        894:                error = ENOBUFS;
                    895:                goto out;
1.6       deraadt   896:        }
1.70      pk        897:
1.26      pk        898:        IF_ENQUEUE(ifq, top);
1.6       deraadt   899:        ifp->if_ipackets++;
1.58      jdolecek  900:        ifp->if_ibytes += tlen;
1.26      pk        901:        schednetisr(isr);
1.70      pk        902: out:
1.46      atatat    903:        simple_unlock(&tp->tun_lock);
1.70      pk        904: out_nolock:
                    905:        splx(s);
                    906: out0:
1.26      pk        907:        return (error);
1.1       cgd       908: }
                    909:
1.50      itojun    910: #ifdef ALTQ
                    911: /*
                    912:  * Start packet transmission on the interface.
                    913:  * when the interface queue is rate-limited by ALTQ or TBR,
                    914:  * if_start is needed to drain packets from the queue in order
                    915:  * to notify readers when outgoing packets become ready.
1.70      pk        916:  *
                    917:  * Should be called at splnet.
1.50      itojun    918:  */
                    919: static void
                    920: tunstart(ifp)
                    921:        struct ifnet *ifp;
                    922: {
                    923:        struct tun_softc *tp = ifp->if_softc;
                    924:
                    925:        if (!ALTQ_IS_ENABLED(&ifp->if_snd) && !TBR_IS_ENABLED(&ifp->if_snd))
                    926:                return;
                    927:
1.70      pk        928:        simple_lock(&tp->tun_lock);
                    929:        if (!IF_IS_EMPTY(&ifp->if_snd)) {
1.50      itojun    930:                if (tp->tun_flags & TUN_RWAIT) {
                    931:                        tp->tun_flags &= ~TUN_RWAIT;
                    932:                        wakeup((caddr_t)tp);
                    933:                }
1.64      jdolecek  934:                if (tp->tun_flags & TUN_ASYNC && tp->tun_pgid)
1.67      cl        935:                        fownsignal(tp->tun_pgid, SIGIO, POLL_OUT,
                    936:                                POLLOUT|POLLWRNORM, NULL);
1.70      pk        937:
1.50      itojun    938:                selwakeup(&tp->tun_rsel);
                    939:        }
1.70      pk        940:        simple_unlock(&tp->tun_lock);
1.50      itojun    941: }
                    942: #endif /* ALTQ */
1.1       cgd       943: /*
1.27      mycroft   944:  * tunpoll - the poll interface, this is only useful on reads
1.6       deraadt   945:  * really. The write detect always returns true, write never blocks
                    946:  * anyway, it either accepts the packet or drops it.
                    947:  */
                    948: int
1.63      fvdl      949: tunpoll(dev, events, p)
1.6       deraadt   950:        dev_t           dev;
1.27      mycroft   951:        int             events;
1.63      fvdl      952:        struct proc     *p;
1.6       deraadt   953: {
1.46      atatat    954:        struct tun_softc *tp;
                    955:        struct ifnet    *ifp;
                    956:        int             s, revents = 0;
                    957:
1.70      pk        958:        s = splnet();
1.46      atatat    959:        tp = tun_find_unit(dev);
                    960:
                    961:        /* interface was "destroyed" already */
                    962:        if (tp == NULL)
1.70      pk        963:                goto out_nolock;
1.46      atatat    964:
                    965:        ifp = &tp->tun_if;
1.6       deraadt   966:
1.27      mycroft   967:        TUNDEBUG("%s: tunpoll\n", ifp->if_xname);
1.6       deraadt   968:
1.35      veego     969:        if (events & (POLLIN | POLLRDNORM)) {
1.70      pk        970:                if (!IFQ_IS_EMPTY(&ifp->if_snd)) {
1.27      mycroft   971:                        TUNDEBUG("%s: tunpoll q=%d\n", ifp->if_xname,
1.24      thorpej   972:                            ifp->if_snd.ifq_len);
1.27      mycroft   973:                        revents |= events & (POLLIN | POLLRDNORM);
                    974:                } else {
                    975:                        TUNDEBUG("%s: tunpoll waiting\n", ifp->if_xname);
1.63      fvdl      976:                        selrecord(p, &tp->tun_rsel);
1.6       deraadt   977:                }
1.35      veego     978:        }
1.27      mycroft   979:
                    980:        if (events & (POLLOUT | POLLWRNORM))
                    981:                revents |= events & (POLLOUT | POLLWRNORM);
                    982:
1.70      pk        983:        simple_unlock(&tp->tun_lock);
                    984: out_nolock:
1.6       deraadt   985:        splx(s);
1.27      mycroft   986:        return (revents);
1.56      jdolecek  987: }
                    988:
                    989: static void
                    990: filt_tunrdetach(struct knote *kn)
                    991: {
                    992:        struct tun_softc *tp = kn->kn_hook;
                    993:        int s;
                    994:
                    995:        s = splnet();
1.57      christos  996:        SLIST_REMOVE(&tp->tun_rsel.sel_klist, kn, knote, kn_selnext);
1.56      jdolecek  997:        splx(s);
                    998: }
                    999:
                   1000: static int
                   1001: filt_tunread(struct knote *kn, long hint)
                   1002: {
                   1003:        struct tun_softc *tp = kn->kn_hook;
                   1004:        struct ifnet *ifp = &tp->tun_if;
                   1005:        struct mbuf *m;
                   1006:        int s;
                   1007:
                   1008:        s = splnet();
                   1009:        IF_POLL(&ifp->if_snd, m);
                   1010:        if (m == NULL) {
                   1011:                splx(s);
                   1012:                return (0);
                   1013:        }
                   1014:
                   1015:        for (kn->kn_data = 0; m != NULL; m = m->m_next)
                   1016:                kn->kn_data += m->m_len;
                   1017:
                   1018:        splx(s);
                   1019:        return (1);
                   1020: }
                   1021:
                   1022: static const struct filterops tunread_filtops =
                   1023:        { 1, NULL, filt_tunrdetach, filt_tunread };
                   1024:
                   1025: static const struct filterops tun_seltrue_filtops =
                   1026:        { 1, NULL, filt_tunrdetach, filt_seltrue };
                   1027:
                   1028: int
                   1029: tunkqfilter(dev_t dev, struct knote *kn)
                   1030: {
1.70      pk       1031:        struct tun_softc *tp;
1.56      jdolecek 1032:        struct klist *klist;
1.70      pk       1033:        int rv = 0, s;
                   1034:
                   1035:        s = splnet();
                   1036:        tp = tun_find_unit(dev);
                   1037:        if (tp == NULL)
                   1038:                goto out_nolock;
1.56      jdolecek 1039:
                   1040:        switch (kn->kn_filter) {
                   1041:        case EVFILT_READ:
1.57      christos 1042:                klist = &tp->tun_rsel.sel_klist;
1.56      jdolecek 1043:                kn->kn_fop = &tunread_filtops;
                   1044:                break;
                   1045:
                   1046:        case EVFILT_WRITE:
1.57      christos 1047:                klist = &tp->tun_rsel.sel_klist;
1.56      jdolecek 1048:                kn->kn_fop = &tun_seltrue_filtops;
                   1049:                break;
                   1050:
                   1051:        default:
1.70      pk       1052:                rv = 1;
                   1053:                goto out;
1.56      jdolecek 1054:        }
                   1055:
                   1056:        kn->kn_hook = tp;
                   1057:
                   1058:        SLIST_INSERT_HEAD(klist, kn, kn_selnext);
1.70      pk       1059:
                   1060: out:
                   1061:        simple_unlock(&tp->tun_lock);
                   1062: out_nolock:
1.56      jdolecek 1063:        splx(s);
1.70      pk       1064:        return (rv);
1.1       cgd      1065: }

CVSweb <webmaster@jp.NetBSD.org>