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

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