Annotation of Net2/net/if_tun.c, revision 1.1.1.2

1.1       root        1: /* UNFINISHED CONVERSION TO 386BSD -wfj */
                      2: 
                      3: /* if_tun.c - tunnel interface module & driver */
                      4: 
                      5: /*
                      6:  * Copyright (c) 1988, Julian Onions. 
                      7:  *
                      8:  * This source may be freely distributed, however I would be interested
                      9:  * in any changes that are made.
                     10:  */
                     11: 
                     12: /*
                     13:  * 90/02/06 15:03 - Fixed a bug in where TIOCGPGRP and TIOCSPGRP were
                     14:  * mixed up. Anders Klemets - [email protected]
                     15:  *
1.1.1.2 ! root       16:  * $Header: /cvsroot/src/sys/net/if_tun.c,v 1.1.1.1 1993/03/21 09:46:06 cgd Exp $
1.1       root       17:  * 
1.1.1.2 ! root       18:  * $Log: if_tun.c,v $
        !            19:  * Revision 1.1.1.1  1993/03/21 09:46:06  cgd
        !            20:  * initial import of 386bsd-0.1 sources
        !            21:  *
1.1       root       22:  * Revision 1.13  88/07/11  08:28:51  jpo
                     23:  * Some tidying up
                     24:  * 
                     25:  * Revision 1.12  87/12/10  09:16:29  jpo
                     26:  * Decided the vax/mtpr was unnecessay.
                     27:  * 
                     28:  * Revision 1.11  87/12/10  09:10:36  jpo
                     29:  * Fixed some minor things & 1 major bug.
                     30:  * 
                     31:  * Revision 1.10  87/11/04  14:27:41  jpo
                     32:  * A few sanity checks added.
                     33:  * 
                     34:  * Revision 1.9  87/11/04  14:13:45  jpo
                     35:  * Added some ioctls for non-blocking & async I/O
                     36:  * 
                     37:  * Revision 1.8  87/10/19  10:28:14  jpo
                     38:  * Another touch up (sigh)
                     39:  * 
                     40:  * Revision 1.7  87/10/19  10:25:48  jpo
                     41:  * Touch up.
                     42:  * 
                     43:  * Revision 1.6  87/10/19  09:15:14  jpo
                     44:  * Touch up.
                     45:  * 
                     46:  * Revision 1.5  87/10/19  08:34:51  jpo
                     47:  * General clean up - plus sun specific fixes
                     48:  * 
                     49:  * Revision 1.4  87/10/16  17:10:12  jpo
                     50:  * Purged all ioctl read/writes and non-standard routing stuff.
                     51:  *
                     52:  * Revision 1.3  87/10/05  11:57:09  jpo
                     53:  * More debugging - in error mainly.
                     54:  * 
                     55:  * Revision 1.2  87/10/04  18:29:45  jpo
                     56:  * Select & read/write working.
                     57:  */
                     58: 
                     59: #include "tun.h"
                     60: #if NTUN > 0
                     61: 
                     62: /*
                     63:  * Tunnel driver.
                     64:  *
                     65:  * This driver takes packets off the IP i/f and hands them up to a
                     66:  * user process to have it's wicked way with. This driver has it's
                     67:  * roots in a similar driver written by Phil Cockcroft (formerly) at
                     68:  * UCL. This driver is based much more on read/write/select mode of
                     69:  * operation though.
                     70:  * 
                     71:  * Julian Onions <[email protected]>
                     72:  * Nottingham University 1987.
                     73:  */
                     74: 
                     75: #include "param.h"
                     76: #include "systm.h"
                     77: #include "mbuf.h"
                     78: #include "buf.h"
                     79: #include "protosw.h"
                     80: #include "socket.h"
                     81: #include "ioctl.h"
                     82: #include "errno.h"
                     83: #include "syslog.h"
                     84: 
                     85: #include "net/if.h"
                     86: #include "net/netisr.h"
                     87: #include "net/route.h"
                     88: 
                     89: #ifdef INET
                     90: #include "netinet/in.h"
                     91: #include "netinet/in_systm.h"
                     92: #include "netinet/in_var.h"
                     93: #include "netinet/ip.h"
                     94: #include "netinet/if_ether.h"
                     95: #endif
                     96: 
                     97: #ifdef NS
                     98: #include "netns/ns.h"
                     99: #include "netns/ns_if.h"
                    100: #endif
                    101: 
                    102: #define TUNDEBUG        if (tundebug) printf
                    103: 
                    104: int             tundebug = 0;
                    105: struct tunctl
                    106: {
                    107:         u_short         tun_flags;      /* misc flags */
                    108:         struct ifnet    tun_if;         /* the interface */
                    109:         int             tun_pgrp;       /* the process group - if any */
                    110:         struct proc    *tun_rsel;       /* read select */
                    111:         struct proc    *tun_wsel;       /* write select (not used) */
                    112: }       tunctl[NTUN];
                    113: 
                    114: extern int      ifqmaxlen;
                    115: 
                    116: int             tunoutput (), tunioctl (), tuninit ();
                    117: 
                    118: /* tunnel open - must be superuser & the device must be configured in */
                    119: tunopen (dev, flag)
                    120: dev_t           dev;
                    121: {
                    122:         register int    unit;
                    123:         struct tunctl  *tp;
                    124:         register struct ifnet *ifp;
                    125: 
                    126:         if (!suser ())
                    127:                 return EACCES;
                    128:         if ((unit = minor (dev)) >= NTUN)
                    129:                 return (ENXIO);
                    130:         tp = &tunctl[unit];
                    131:         if (tp->tun_flags & TUN_OPEN)
                    132:                 return ENXIO;
                    133:         if ((tp->tun_flags & TUN_INITED) == 0) {
                    134:                 tp->tun_flags = TUN_INITED;
                    135:                 tunattach (unit);
                    136:         }
                    137:         ifp = &tp->tun_if;
                    138:         tp->tun_flags |= TUN_OPEN;
                    139:         TUNDEBUG ("%s%d: open\n", ifp->if_name, ifp->if_unit);
                    140:         return (0);
                    141: }
                    142: 
                    143: /* tunclose - close the device - mark i/f down & delete routing info */
                    144: tunclose (dev, flag)
                    145: dev_t           dev;
                    146: {
                    147:         int             s;
                    148:         int             rcoll;
                    149:         register int    unit = minor (dev);
                    150:         register struct tunctl *tp = &tunctl[unit];
                    151:         register struct ifnet *ifp = &tp->tun_if;
                    152:         register struct mbuf *m;
                    153: 
                    154:         rcoll = tp->tun_flags & TUN_RCOLL;
                    155:         tp->tun_flags &= TUN_INITED;
                    156: 
                    157:         /*
                    158:          * junk all pending output
                    159:          */
                    160:         do {
                    161:                 s = splimp ();
                    162:                 IF_DEQUEUE (&ifp->if_snd, m);
                    163:                 splx (s);
                    164:                 if (m) /* actually - m_freem checks this - but what the hell */
                    165:                         m_freem (m);
                    166:         } while (m != 0);
                    167:         if (ifp->if_flags & IFF_UP) {
                    168:                 s = splimp ();
                    169:                 if_down (ifp);
                    170:                 if (ifp->if_flags & IFF_RUNNING)
                    171:                         rtinit (ifp->if_addrlist, (int)SIOCDELRT, RTF_HOST);
                    172:                 splx (s);
                    173:         }
                    174:         tp -> tun_pgrp = 0;
                    175:         if (tp -> tun_rsel)
                    176:                 selwakeup (tp->tun_rsel, rcoll);
                    177:                 
                    178:         tp -> tun_rsel = tp -> tun_wsel = (struct proc *)0;
                    179: 
                    180:         TUNDEBUG ("%s%d: closed\n", ifp->if_name, ifp->if_unit);
                    181:         return (0);
                    182: }
                    183: 
                    184: /*
                    185:  * attach an interface N.B. argument is not same as other drivers
                    186:  */
                    187: int
                    188: tunattach (unit)
                    189: int             unit;
                    190: {
                    191:         register struct ifnet *ifp = &tunctl[unit].tun_if;
                    192:         register struct sockaddr_in *sin;
                    193: 
                    194:         ifp->if_unit = unit;
                    195:         ifp->if_name = "tun";
                    196:         ifp->if_mtu = TUNMTU;
                    197:         ifp->if_ioctl = tunioctl;
                    198:         ifp->if_output = tunoutput;
                    199:         ifp->if_init = tuninit;
                    200: #ifndef BSD4_3
                    201:         sin = (struct sockaddr_in *) & ifp->if_addr;
                    202:         sin->sin_family = AF_INET;
                    203: #endif
                    204:         ifp->if_flags = IFF_POINTOPOINT;
                    205:         ifp->if_snd.ifq_maxlen = ifqmaxlen;
                    206:         ifp->if_collisions = ifp->if_ierrors = ifp->if_oerrors = 0;
                    207:         ifp->if_ipackets = ifp->if_opackets = 0;
                    208:         if_attach (ifp);
                    209:         TUNDEBUG ("%s%d: tunattach\n", ifp->if_name, ifp->if_unit);
                    210:         return 0;
                    211: }
                    212: 
                    213: int
                    214: tuninit (unit)
                    215: int             unit;
                    216: {
                    217:         register struct tunctl *tp = &tunctl[unit];
                    218:         register struct ifnet *ifp = &tp->tun_if;
                    219: #ifndef BSD4_3
                    220:         register struct sockaddr_in *sin;
                    221: 
                    222:         sin = (struct sockaddr_in *) & ifp->if_addr;
                    223:         if (sin->sin_addr.s_addr == 0)  /* if address still unknown */
                    224:                 return;
                    225:         if_rtinit (ifp, RTF_UP);
                    226: #endif
                    227:         ifp->if_flags |= IFF_UP | IFF_RUNNING;
                    228:         tp->tun_flags |= TUN_IASET;
                    229:         TUNDEBUG ("%s%d: tuninit\n", ifp->if_name, ifp->if_unit);
                    230:         return 0;
                    231: }
                    232: 
                    233: /*
                    234:  * Process an ioctl request.
                    235:  * The problem here is 4.2 pass a struct ifreq * to this routine,
                    236:  * sun only passes a struct sockaddr * since 3.2 at least. This is
                    237:  * rather upsetting! Also, sun doesn't pass the SIOCDSTADDR ioctl through
                    238:  * so we can't detect this being set directly. This is the reason for
                    239:  * tuncheckready.
                    240:  * Under 4.3 and SunOs 4.0 we now get the SIOCSIFDSTADDR ioctl, and we get a
                    241:  * struct in_ifaddr * for data. (tte)
                    242:  */
                    243: 
                    244: #if !defined(BSD4_3) && defined(sun)
                    245: 
                    246: /*
                    247:  * workaround for not being able to detect DSTADDR being set.
                    248:  */
                    249: 
                    250: tuncheckready (ifp)
                    251: struct ifnet *ifp;
                    252: {
                    253:         struct tunctl *tp = &tunctl[ifp->if_unit];
                    254:         struct sockaddr_in *sin;
                    255: 
                    256:         sin = (struct sockaddr_in *) &ifp->if_dstaddr;
                    257:         if (sin->sin_addr.s_addr == 0)
                    258:                 return 0;
                    259:         tp -> tun_flags |= TUN_DSTADDR;
                    260:         return 1;
                    261: }
                    262: #else
                    263: #define tuncheckready(dummy) 1
                    264: #endif /* !defined(BSD4_3) && defined(sun) */
                    265: 
                    266: int
                    267: tunioctl (ifp, cmd, data)
                    268: register struct ifnet *ifp;
                    269: int             cmd;
                    270: caddr_t         data;
                    271: {
                    272: #ifndef BSD4_3
                    273: #ifdef sun      
                    274:         struct sockaddr_in *sin = (struct sockaddr_in *) data;
                    275: #else
                    276:         struct sockaddr_in *sin;
                    277:         struct ifreq    *ifr = (struct ifreq *) data;
                    278: #endif
                    279: #endif /* BSD4_3 */
                    280: 
                    281:         int             s = splimp (), error = 0;
                    282:         struct tunctl  *tp = &tunctl[ifp->if_unit];
                    283: 
                    284:         switch (cmd)
                    285:         {
                    286:             case SIOCSIFADDR:
                    287: #ifndef BSD4_3
                    288:                 if (ifp->if_flags & IFF_RUNNING)
                    289:                         if_rtinit (ifp, -1);    /* delete previous route */
                    290: #ifndef sun
                    291:                 sin = (struct sockaddr_in *)&ifr -> ifr_addr;
                    292: #endif
                    293:                 ifp->if_addr = *((struct sockaddr *) sin);
                    294:                 ifp->if_net = in_netof (sin->sin_addr);
                    295:                 ifp->if_host[0] = in_lnaof (sin->sin_addr);
                    296: #endif
                    297:                 tuninit (ifp->if_unit);
                    298:                 break;
                    299:             case SIOCSIFDSTADDR:
                    300:                 tp->tun_flags |= TUN_DSTADDR;
                    301: #ifndef BSD4_3
                    302: #ifndef sun
                    303:                 sin = (struct sockaddr_in *)&ifr -> ifr_addr;
                    304: #endif
                    305:                 ifp->if_dstaddr = *((struct sockaddr *)sin);
                    306: #endif BSD4_3
                    307:                 TUNDEBUG ("%s%d: destination addres set\n", ifp->if_name,
                    308:                         ifp -> if_unit);
                    309:                 break;
                    310:             default:
                    311:                 error = EINVAL;
                    312:         }
                    313:         splx (s);
                    314:         return (error);
                    315: }
                    316: 
                    317: /*
                    318:  * tunoutput - queue packets from higher level ready to put out.
                    319:  */
                    320: tunoutput (ifp, m0, dst)
                    321: struct ifnet   *ifp;
                    322: struct mbuf    *m0;
                    323: struct sockaddr *dst;
                    324: {
                    325:         struct tunctl  *tp;
                    326:         struct proc     *p;
                    327:         int             s;
                    328: 
                    329:         TUNDEBUG ("%s%d: tunoutput\n", ifp->if_name, ifp->if_unit);
                    330:         tp = &tunctl[ifp->if_unit];
                    331:         if ((tp->tun_flags & TUN_READY) != TUN_READY) {
                    332:                 if(tuncheckready(ifp) == 0) {
                    333:                         TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name,
                    334:                                 ifp->if_unit, tp->tun_flags);
                    335:                         m_freem (m0);
                    336:                         return EHOSTDOWN;
                    337:                 }
                    338:         }
                    339: 
                    340:         switch (dst->sa_family) {
                    341: #ifdef INET
                    342:             case AF_INET:
                    343:                 s = splimp ();
                    344:                 if (IF_QFULL (&ifp->if_snd))
                    345:                 {
                    346:                         IF_DROP (&ifp->if_snd);
                    347:                         m_freem (m0);
                    348:                         splx (s);
                    349:                         ifp->if_collisions++;
                    350:                         return (ENOBUFS);
                    351:                 }
                    352:                 IF_ENQUEUE (&ifp->if_snd, m0);
                    353:                 splx (s);
                    354:                 ifp->if_opackets++;
                    355:                 break;
                    356: #endif
                    357:             default:
                    358:                 m_freem (m0);
                    359:                 return EAFNOSUPPORT;
                    360:         }
                    361: 
                    362:         if (tp->tun_flags & TUN_RWAIT) {
                    363:                 tp->tun_flags &= ~TUN_RWAIT;
                    364:                 wakeup ((caddr_t) tp);
                    365:         }
                    366:         if (tp->tun_flags & TUN_ASYNC && tp -> tun_pgrp != 0) {
                    367:                 if (tp->tun_pgrp > 0)
                    368:                         gsignal (tp->tun_pgrp, SIGIO);
                    369:                 else if ((p = pfind (-tp->tun_pgrp)) != 0)
                    370:                         psignal (p, SIGIO);
                    371:         }
                    372:         if (tp->tun_rsel) {
                    373:                 selwakeup (tp->tun_rsel, tp->tun_flags & TUN_RCOLL);
                    374:                 tp->tun_flags &= ~TUN_RCOLL;
                    375:                 tp->tun_rsel = (struct proc *) 0;
                    376:         }
                    377:         return 0;
                    378: }
                    379: 
                    380: /*
                    381:  * the cdevsw interface is now pretty minimal.
                    382:  */
                    383: 
                    384: tuncioctl (dev, cmd, data, flag)
                    385: dev_t           dev;
                    386: caddr_t         data;
                    387: {
                    388:         int     unit = minor(dev);
                    389:         struct tunctl *tp = &tunctl[unit];
                    390:         int     s;
                    391: 
                    392:         switch (cmd) {
                    393:             case TUNSDEBUG:
                    394:                 tundebug = *(int *)data;
                    395:                 break;
                    396: 
                    397:             case TUNGDEBUG:
                    398:                 *(int *)data = tundebug;
                    399:                 break;
                    400: 
                    401:             case FIONBIO:
                    402:                 if (*(int *)data)
                    403:                         tp->tun_flags |= TUN_NBIO;
                    404:                 else
                    405:                         tp->tun_flags &= ~TUN_NBIO;
                    406:                 break;
                    407: 
                    408:             case FIOASYNC:
                    409:                 if (*(int *)data)
                    410:                         tp->tun_flags |= TUN_ASYNC;
                    411:                 else
                    412:                         tp->tun_flags &= ~TUN_ASYNC;
                    413:                 break;
                    414: 
                    415:             case FIONREAD:
                    416:                 s = splimp ();
                    417:                 if (tp->tun_if.if_snd.ifq_head)
                    418:                         *(int *)data = tp->tun_if.if_snd.ifq_head->m_len;
                    419:                 else    *(int *)data = 0;
                    420:                 splx (s);
                    421:                 break;
                    422: 
                    423:             case TIOCSPGRP:
                    424:                 tp->tun_pgrp = *(int *)data;
                    425:                 break;
                    426: 
                    427:             case TIOCGPGRP:
                    428:                 *(int *)data = tp->tun_pgrp;
                    429:                 break;
                    430: 
                    431:             default:
                    432:                 return (ENOTTY);
                    433:         }
                    434:         return (0);
                    435: }
                    436: 
                    437: /*
                    438:  * The cdevsw read interface - reads a packet at a time, or at least as much
                    439:  * of a packet as can be read.
                    440:  */
                    441: tunread (dev, uio)
                    442: dev_t           dev;
                    443: struct uio     *uio;
                    444: {
                    445:         register struct ifnet *ifp;
                    446:         register struct mbuf *m, *m0;
                    447:         int             unit = minor (dev);
                    448:         int             len, s;
                    449:         int             error = 0;
                    450:         struct tunctl  *tp;
                    451: 
                    452:         tp = &tunctl[unit];
                    453:         ifp = &tp->tun_if;
                    454:         TUNDEBUG ("%s%d: read\n", ifp->if_name, ifp->if_unit);
                    455:         if ((tp->tun_flags & TUN_READY) != TUN_READY) {
                    456:                 if(tuncheckready(ifp) == 0) {
                    457:                         TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name,
                    458:                                 ifp->if_unit, tp->tun_flags);
                    459:                         return EHOSTDOWN;
                    460:                 }
                    461:         }
                    462: 
                    463:         tp->tun_flags &= ~TUN_RWAIT;
                    464: 
                    465:         s = splimp ();
                    466:         do {
                    467:                 IF_DEQUEUE (&ifp->if_snd, m0);
                    468:                 if (m0 == 0) {
                    469:                         if (tp -> tun_flags & TUN_NBIO) {
                    470:                                 splx (s);
                    471:                                 return EWOULDBLOCK;
                    472:                         }
                    473:                         tp->tun_flags |= TUN_RWAIT;
                    474:                         sleep ((caddr_t) tp, PZERO + 1);
                    475:                 }
                    476:         } while (m0 == 0);
                    477:         splx (s);
                    478: 
                    479:         while (m0 && uio->uio_resid > 0 && error == 0) {
                    480:                 len = MIN (uio->uio_resid, m0->m_len);
                    481:                 if (len == 0)
                    482:                         break;
                    483:                 error = uiomove (mtod (m0, caddr_t), len,
                    484:                                  UIO_READ, uio);
                    485:                 MFREE (m0, m);
                    486:                 m0 = m;
                    487:         }
                    488: 
                    489:         if (m0 != 0) {
                    490:                 TUNDEBUG ("Dropping mbuf\n");
                    491:                 m_freem (m0);
                    492:         }
                    493:         return error;
                    494: }
                    495: 
                    496: /*
                    497:  * the cdevsw write interface - an atomic write is a packet - or else!
                    498:  */
                    499: 
                    500: tunwrite (dev, uio)
                    501: int             dev;
                    502: struct uio     *uio;
                    503: {
                    504:         int             error = 0;
                    505:         int             unit = minor (dev);
                    506:         struct mbuf    *top, **mp, *m;
                    507:         struct ifnet   *ifp = &(tunctl[unit].tun_if);
                    508:         int             s;
                    509: 
                    510:         TUNDEBUG ("%s%d: tunwrite\n", ifp->if_name, ifp->if_unit);
                    511: 
                    512:         if (uio->uio_resid < 0 || uio->uio_resid > TUNMTU) {
                    513:                 TUNDEBUG ("%s%d: len=%d!\n", ifp->if_name, ifp->if_unit,
                    514:                           uio->uio_resid);
                    515:                 return EIO;
                    516:         }
                    517:         top = 0;
                    518:         mp = &top;
                    519:         while (error == 0 && uio->uio_resid > 0) {
                    520:                 MGET (m, M_DONTWAIT, MT_DATA);
                    521:                 if (m == 0) {
                    522:                         error = ENOBUFS;
                    523:                         break;
                    524:                 }
                    525:                 m->m_len = MIN (MLEN, uio->uio_resid);
                    526:                 error = uiomove (mtod (m, caddr_t), m->m_len, UIO_WRITE, uio);
                    527:                 *mp = m;
                    528:                 mp = &m->m_next;
                    529:         }
                    530:         if (error) {
                    531:                 if (top)
                    532:                         m_freem (top);
                    533:                 return error;
                    534:         }
                    535: 
                    536: #ifdef BSD4_3
                    537:         /*
                    538:          * Place interface pointer before the data
                    539:          * for the receiving protocol.
                    540:          */
                    541:         if (top->m_off <= MMAXOFF &&
                    542:             top->m_off >= MMINOFF + sizeof(struct ifnet *)) {
                    543:                 top->m_off -= sizeof(struct ifnet *);
                    544:                 top->m_len += sizeof(struct ifnet *);
                    545:         } else {
                    546:                 MGET(m, M_DONTWAIT, MT_HEADER);
                    547:                 if (m == (struct mbuf *)0)
                    548:                         return (ENOBUFS);
                    549:                 m->m_len = sizeof(struct ifnet *);
                    550:                 m->m_next = top;
                    551:                 top = m;
                    552:         }
                    553:         *(mtod(top, struct ifnet **)) = ifp;
                    554: #endif /* BSD4_3 */
                    555: 
                    556:         s = splimp ();
                    557:         if (IF_QFULL (&ipintrq)) {
                    558:                 IF_DROP (&ipintrq);
                    559:                 splx (s);
                    560:                 ifp->if_collisions++;
                    561:                 m_freem (top);
                    562:                 return ENOBUFS;
                    563:         }
                    564:         IF_ENQUEUE (&ipintrq, top);
                    565:         splx (s);
                    566:         ifp->if_ipackets++;
                    567:         schednetisr (NETISR_IP);
                    568:         return error;
                    569: }
                    570: 
                    571: /*
                    572:  * tunselect - the select interface, this is only useful on reads really.
                    573:  * The write detect always returns true, write never blocks anyway, it either
                    574:  * accepts the packet or drops it.
                    575:  */
                    576: tunselect (dev, rw)
                    577: dev_t           dev;
                    578: int             rw;
                    579: {
                    580:         int             unit = minor (dev);
                    581:         register struct tunctl *tp = &tunctl[unit];
                    582:         struct ifnet   *ifp = &tp->tun_if;
                    583:         int             s = splimp ();
                    584: 
                    585:         TUNDEBUG ("%s%d: tunselect\n", ifp->if_name, ifp->if_unit);
                    586:         switch (rw) {
                    587:             case FREAD:
                    588:                 if (ifp->if_snd.ifq_len > 0) {
                    589:                         splx (s);
                    590:                         TUNDEBUG ("%s%d: tunselect q=%d\n", ifp->if_name,
                    591:                                   ifp->if_unit, ifp->if_snd.ifq_len);
                    592:                         return 1;
                    593:                 }
                    594:                 if (tp->tun_rsel && tp->tun_rsel->p_wchan ==
                    595:                     (caddr_t) & selwait)
                    596:                         tp->tun_flags |= TUN_RCOLL;
                    597:                 else
                    598:                         tp->tun_rsel = u.u_procp;
                    599:                 break;
                    600:             case FWRITE:
                    601:                 splx (s);
                    602:                 return 1;
                    603:         }
                    604:         splx (s);
                    605:         TUNDEBUG ("%s%d: tunselect waiting\n", ifp->if_name, ifp->if_unit);
                    606:         return 0;
                    607: }
                    608: #endif  NTUN

unix.superglobalmegacorp.com

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