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

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

unix.superglobalmegacorp.com

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