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

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

unix.superglobalmegacorp.com

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