if_tun.c revision 77178
1/* $NetBSD: if_tun.c,v 1.14 1994/06/29 06:36:25 cgd Exp $ */ 2 3/* 4 * Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk> 5 * Nottingham University 1987. 6 * 7 * This source may be freely distributed, however I would be interested 8 * in any changes that are made. 9 * 10 * This driver takes packets off the IP i/f and hands them up to a 11 * user process to have its wicked way with. This driver has it's 12 * roots in a similar driver written by Phil Cockcroft (formerly) at 13 * UCL. This driver is based much more on read/write/poll mode of 14 * operation though. 15 * 16 * $FreeBSD: head/sys/net/if_tun.c 77178 2001-05-25 13:32:53Z phk $ 17 */ 18 19#include "opt_inet.h" 20 21#include <sys/param.h> 22#include <sys/proc.h> 23#include <sys/systm.h> 24#include <sys/mbuf.h> 25#include <sys/module.h> 26#include <sys/socket.h> 27#include <sys/filio.h> 28#include <sys/sockio.h> 29#include <sys/ttycom.h> 30#include <sys/poll.h> 31#include <sys/signalvar.h> 32#include <sys/filedesc.h> 33#include <sys/kernel.h> 34#include <sys/sysctl.h> 35#include <sys/conf.h> 36#include <sys/uio.h> 37#include <sys/vnode.h> 38#include <sys/malloc.h> 39 40#include <net/if.h> 41#include <net/if_types.h> 42#include <net/route.h> 43#include <net/intrq.h> 44 45#ifdef INET 46#include <netinet/in.h> 47#endif 48 49#include <net/bpf.h> 50 51#include <net/if_tunvar.h> 52#include <net/if_tun.h> 53 54static MALLOC_DEFINE(M_TUN, "tun", "Tunnel Interface"); 55 56static void tuncreate __P((dev_t dev)); 57 58#define TUNDEBUG if (tundebug) printf 59static int tundebug = 0; 60static struct tun_softc *tunhead = NULL; 61SYSCTL_INT(_debug, OID_AUTO, if_tun_debug, CTLFLAG_RW, &tundebug, 0, ""); 62 63static int tunoutput __P((struct ifnet *, struct mbuf *, struct sockaddr *, 64 struct rtentry *rt)); 65static int tunifioctl __P((struct ifnet *, u_long, caddr_t)); 66static int tuninit __P((struct ifnet *)); 67static void tunstart __P((struct ifnet *)); 68 69static d_open_t tunopen; 70static d_close_t tunclose; 71static d_read_t tunread; 72static d_write_t tunwrite; 73static d_ioctl_t tunioctl; 74static d_poll_t tunpoll; 75 76#define CDEV_MAJOR 52 77static struct cdevsw tun_cdevsw = { 78 /* open */ tunopen, 79 /* close */ tunclose, 80 /* read */ tunread, 81 /* write */ tunwrite, 82 /* ioctl */ tunioctl, 83 /* poll */ tunpoll, 84 /* mmap */ nommap, 85 /* strategy */ nostrategy, 86 /* name */ "tun", 87 /* maj */ CDEV_MAJOR, 88 /* dump */ nodump, 89 /* psize */ nopsize, 90 /* flags */ 0, 91}; 92 93static void tun_clone __P((void *arg, char *name, int namelen, dev_t *dev)); 94 95static void 96tun_clone(arg, name, namelen, dev) 97 void *arg; 98 char *name; 99 int namelen; 100 dev_t *dev; 101{ 102 int u; 103 104 if (*dev != NODEV) 105 return; 106 if (dev_stdclone(name, NULL, "tun", &u) != 1) 107 return; 108 *dev = make_dev(&tun_cdevsw, unit2minor(u), 109 UID_ROOT, GID_WHEEL, 0600, "tun%d", u); 110 (*dev)->si_flags |= SI_CHEAPCLONE; 111} 112 113static int 114tun_modevent(module_t mod, int type, void *data) 115{ 116 static eventhandler_tag tag; 117 struct tun_softc *tp; 118 dev_t dev; 119 int err; 120 121 switch (type) { 122 case MOD_LOAD: 123 tag = EVENTHANDLER_REGISTER(dev_clone, tun_clone, 0, 1000); 124 if (tag == NULL) 125 return (ENOMEM); 126 err = cdevsw_add(&tun_cdevsw); 127 if (err != 0) { 128 EVENTHANDLER_DEREGISTER(dev_clone, tag); 129 return (err); 130 } 131 break; 132 case MOD_UNLOAD: 133 while (tunhead != NULL) { 134 if (tunhead->tun_flags & TUN_OPEN) 135 return (EBUSY); 136 tp = tunhead; 137 dev = makedev(tun_cdevsw.d_maj, 138 unit2minor(tp->tun_if.if_unit)); 139 KASSERT(dev->si_drv1 == tp, ("Bad makedev result")); 140 tunhead = tp->next; 141 bpfdetach(&tp->tun_if); 142 if_detach(&tp->tun_if); 143 KASSERT(dev->si_flags & SI_NAMED, ("Missing make_dev")); 144 destroy_dev(dev); 145 FREE(tp, M_TUN); 146 } 147 cdevsw_remove(&tun_cdevsw); 148 EVENTHANDLER_DEREGISTER(dev_clone, tag); 149 break; 150 } 151 return 0; 152} 153 154static moduledata_t tun_mod = { 155 "if_tun", 156 tun_modevent, 157 0 158}; 159 160DECLARE_MODULE(if_tun, tun_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); 161 162static void 163tunstart(ifp) 164 struct ifnet *ifp; 165{ 166 struct tun_softc *tp = ifp->if_softc; 167 168 if (tp->tun_flags & TUN_RWAIT) { 169 tp->tun_flags &= ~TUN_RWAIT; 170 wakeup((caddr_t)tp); 171 } 172 if (tp->tun_flags & TUN_ASYNC && tp->tun_sigio) 173 pgsigio(tp->tun_sigio, SIGIO, 0); 174 selwakeup(&tp->tun_rsel); 175} 176 177static void 178tuncreate(dev) 179 dev_t dev; 180{ 181 struct tun_softc *sc; 182 struct ifnet *ifp; 183 184 if (!(dev->si_flags & SI_NAMED)) 185 dev = make_dev(&tun_cdevsw, minor(dev), 186 UID_UUCP, GID_DIALER, 0600, "tun%d", dev2unit(dev)); 187 188 MALLOC(sc, struct tun_softc *, sizeof(*sc), M_TUN, M_WAITOK | M_ZERO); 189 sc->tun_flags = TUN_INITED; 190 sc->next = tunhead; 191 tunhead = sc; 192 193 ifp = &sc->tun_if; 194 ifp->if_unit = dev2unit(dev); 195 ifp->if_name = "tun"; 196 ifp->if_mtu = TUNMTU; 197 ifp->if_ioctl = tunifioctl; 198 ifp->if_output = tunoutput; 199 ifp->if_start = tunstart; 200 ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 201 ifp->if_type = IFT_PPP; 202 ifp->if_snd.ifq_maxlen = ifqmaxlen; 203 ifp->if_softc = sc; 204 if_attach(ifp); 205 bpfattach(ifp, DLT_NULL, sizeof(u_int)); 206 dev->si_drv1 = sc; 207} 208 209/* 210 * tunnel open. We assume that any tun_clone() call is immediately 211 * followed by a call to tunopen() - otherwise nothing will ever 212 * destroy_dev() the specinfo. 213 */ 214static int 215tunopen(dev, flag, mode, p) 216 dev_t dev; 217 int flag, mode; 218 struct proc *p; 219{ 220 struct ifnet *ifp; 221 struct tun_softc *tp; 222 223 tp = dev->si_drv1; 224 if (!tp) { 225 tuncreate(dev); 226 tp = dev->si_drv1; 227 } 228 if (tp->tun_flags & TUN_OPEN) 229 return EBUSY; 230 tp->tun_pid = p->p_pid; 231 ifp = &tp->tun_if; 232 tp->tun_flags |= TUN_OPEN; 233 TUNDEBUG("%s%d: open\n", ifp->if_name, ifp->if_unit); 234 return (0); 235} 236 237/* 238 * tunclose - close the device - mark i/f down & delete 239 * routing info 240 */ 241static int 242tunclose(dev, foo, bar, p) 243 dev_t dev; 244 int foo; 245 int bar; 246 struct proc *p; 247{ 248 register int s; 249 struct tun_softc *tp; 250 struct ifnet *ifp; 251 252 tp = dev->si_drv1; 253 ifp = &tp->tun_if; 254 255 tp->tun_flags &= ~TUN_OPEN; 256 tp->tun_pid = 0; 257 258 /* 259 * junk all pending output 260 */ 261 IF_DRAIN(&ifp->if_snd); 262 263 if (ifp->if_flags & IFF_UP) { 264 s = splimp(); 265 if_down(ifp); 266 splx(s); 267 } 268 269 if (ifp->if_flags & IFF_RUNNING) { 270 register struct ifaddr *ifa; 271 272 s = splimp(); 273 /* find internet addresses and delete routes */ 274 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 275 if (ifa->ifa_addr->sa_family == AF_INET) 276 rtinit(ifa, (int)RTM_DELETE, 277 tp->tun_flags & TUN_DSTADDR ? RTF_HOST : 0); 278 ifp->if_flags &= ~IFF_RUNNING; 279 splx(s); 280 } 281 282 funsetown(tp->tun_sigio); 283 selwakeup(&tp->tun_rsel); 284 285 TUNDEBUG ("%s%d: closed\n", ifp->if_name, ifp->if_unit); 286 return (0); 287} 288 289static int 290tuninit(ifp) 291 struct ifnet *ifp; 292{ 293 struct tun_softc *tp = ifp->if_softc; 294 register struct ifaddr *ifa; 295 int error = 0; 296 297 TUNDEBUG("%s%d: tuninit\n", ifp->if_name, ifp->if_unit); 298 299 ifp->if_flags |= IFF_UP | IFF_RUNNING; 300 getmicrotime(&ifp->if_lastchange); 301 302 for (ifa = TAILQ_FIRST(&ifp->if_addrhead); ifa; 303 ifa = TAILQ_NEXT(ifa, ifa_link)) { 304 if (ifa->ifa_addr == NULL) 305 error = EFAULT; 306 /* XXX: Should maybe return straight off? */ 307 else { 308#ifdef INET 309 if (ifa->ifa_addr->sa_family == AF_INET) { 310 struct sockaddr_in *si; 311 312 si = (struct sockaddr_in *)ifa->ifa_addr; 313 if (si->sin_addr.s_addr) 314 tp->tun_flags |= TUN_IASET; 315 316 si = (struct sockaddr_in *)ifa->ifa_dstaddr; 317 if (si && si->sin_addr.s_addr) 318 tp->tun_flags |= TUN_DSTADDR; 319 } 320#endif 321 } 322 } 323 return (error); 324} 325 326/* 327 * Process an ioctl request. 328 */ 329int 330tunifioctl(ifp, cmd, data) 331 struct ifnet *ifp; 332 u_long cmd; 333 caddr_t data; 334{ 335 struct ifreq *ifr = (struct ifreq *)data; 336 struct tun_softc *tp = ifp->if_softc; 337 struct ifstat *ifs; 338 int error = 0, s; 339 340 s = splimp(); 341 switch(cmd) { 342 case SIOCGIFSTATUS: 343 ifs = (struct ifstat *)data; 344 if (tp->tun_pid) 345 sprintf(ifs->ascii + strlen(ifs->ascii), 346 "\tOpened by PID %d\n", tp->tun_pid); 347 break; 348 case SIOCSIFADDR: 349 error = tuninit(ifp); 350 TUNDEBUG("%s%d: address set, error=%d\n", 351 ifp->if_name, ifp->if_unit, error); 352 break; 353 case SIOCSIFDSTADDR: 354 error = tuninit(ifp); 355 TUNDEBUG("%s%d: destination address set, error=%d\n", 356 ifp->if_name, ifp->if_unit, error); 357 break; 358 case SIOCSIFMTU: 359 ifp->if_mtu = ifr->ifr_mtu; 360 TUNDEBUG("%s%d: mtu set\n", ifp->if_name, ifp->if_unit); 361 break; 362 case SIOCSIFFLAGS: 363 case SIOCADDMULTI: 364 case SIOCDELMULTI: 365 break; 366 default: 367 error = EINVAL; 368 } 369 splx(s); 370 return (error); 371} 372 373/* 374 * tunoutput - queue packets from higher level ready to put out. 375 */ 376int 377tunoutput(ifp, m0, dst, rt) 378 struct ifnet *ifp; 379 struct mbuf *m0; 380 struct sockaddr *dst; 381 struct rtentry *rt; 382{ 383 struct tun_softc *tp = ifp->if_softc; 384 385 TUNDEBUG ("%s%d: tunoutput\n", ifp->if_name, ifp->if_unit); 386 387 if ((tp->tun_flags & TUN_READY) != TUN_READY) { 388 TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name, 389 ifp->if_unit, tp->tun_flags); 390 m_freem (m0); 391 return EHOSTDOWN; 392 } 393 394 /* BPF write needs to be handled specially */ 395 if (dst->sa_family == AF_UNSPEC) { 396 dst->sa_family = *(mtod(m0, int *)); 397 m0->m_len -= sizeof(int); 398 m0->m_pkthdr.len -= sizeof(int); 399 m0->m_data += sizeof(int); 400 } 401 402 if (ifp->if_bpf) { 403 /* 404 * We need to prepend the address family as 405 * a four byte field. Cons up a dummy header 406 * to pacify bpf. This is safe because bpf 407 * will only read from the mbuf (i.e., it won't 408 * try to free it or keep a pointer to it). 409 */ 410 struct mbuf m; 411 uint32_t af = dst->sa_family; 412 413 m.m_next = m0; 414 m.m_len = 4; 415 m.m_data = (char *)⁡ 416 417 bpf_mtap(ifp, &m); 418 } 419 420 /* prepend sockaddr? this may abort if the mbuf allocation fails */ 421 if (tp->tun_flags & TUN_LMODE) { 422 /* allocate space for sockaddr */ 423 M_PREPEND(m0, dst->sa_len, M_DONTWAIT); 424 425 /* if allocation failed drop packet */ 426 if (m0 == NULL) { 427 ifp->if_iqdrops++; 428 ifp->if_oerrors++; 429 return (ENOBUFS); 430 } else { 431 bcopy(dst, m0->m_data, dst->sa_len); 432 } 433 } 434 435 if (tp->tun_flags & TUN_IFHEAD) { 436 /* Prepend the address family */ 437 M_PREPEND(m0, 4, M_DONTWAIT); 438 439 /* if allocation failed drop packet */ 440 if (m0 == NULL) { 441 ifp->if_iqdrops++; 442 ifp->if_oerrors++; 443 return ENOBUFS; 444 } else 445 *(u_int32_t *)m0->m_data = htonl(dst->sa_family); 446 } else { 447#ifdef INET 448 if (dst->sa_family != AF_INET) 449#endif 450 { 451 m_freem(m0); 452 return EAFNOSUPPORT; 453 } 454 } 455 456 if (! IF_HANDOFF(&ifp->if_snd, m0, ifp)) { 457 ifp->if_collisions++; 458 return ENOBUFS; 459 } 460 ifp->if_opackets++; 461 return 0; 462} 463 464/* 465 * the cdevsw interface is now pretty minimal. 466 */ 467static int 468tunioctl(dev, cmd, data, flag, p) 469 dev_t dev; 470 u_long cmd; 471 caddr_t data; 472 int flag; 473 struct proc *p; 474{ 475 int s; 476 int error; 477 struct tun_softc *tp = dev->si_drv1; 478 struct tuninfo *tunp; 479 480 switch (cmd) { 481 case TUNSIFINFO: 482 tunp = (struct tuninfo *)data; 483 if (tunp->mtu < IF_MINMTU) 484 return (EINVAL); 485 if (tp->tun_if.if_mtu != tunp->mtu && (error = suser(p)) != 0) 486 return (error); 487 tp->tun_if.if_mtu = tunp->mtu; 488 tp->tun_if.if_type = tunp->type; 489 tp->tun_if.if_baudrate = tunp->baudrate; 490 break; 491 case TUNGIFINFO: 492 tunp = (struct tuninfo *)data; 493 tunp->mtu = tp->tun_if.if_mtu; 494 tunp->type = tp->tun_if.if_type; 495 tunp->baudrate = tp->tun_if.if_baudrate; 496 break; 497 case TUNSDEBUG: 498 tundebug = *(int *)data; 499 break; 500 case TUNGDEBUG: 501 *(int *)data = tundebug; 502 break; 503 case TUNSLMODE: 504 if (*(int *)data) { 505 tp->tun_flags |= TUN_LMODE; 506 tp->tun_flags &= ~TUN_IFHEAD; 507 } else 508 tp->tun_flags &= ~TUN_LMODE; 509 break; 510 case TUNSIFHEAD: 511 if (*(int *)data) { 512 tp->tun_flags |= TUN_IFHEAD; 513 tp->tun_flags &= ~TUN_LMODE; 514 } else 515 tp->tun_flags &= ~TUN_IFHEAD; 516 break; 517 case TUNGIFHEAD: 518 *(int *)data = (tp->tun_flags & TUN_IFHEAD) ? 1 : 0; 519 break; 520 case TUNSIFMODE: 521 /* deny this if UP */ 522 if (tp->tun_if.if_flags & IFF_UP) 523 return(EBUSY); 524 525 switch (*(int *)data) { 526 case IFF_POINTOPOINT: 527 tp->tun_if.if_flags |= IFF_POINTOPOINT; 528 tp->tun_if.if_flags &= ~IFF_BROADCAST; 529 break; 530 case IFF_BROADCAST: 531 tp->tun_if.if_flags &= ~IFF_POINTOPOINT; 532 tp->tun_if.if_flags |= IFF_BROADCAST; 533 break; 534 default: 535 return(EINVAL); 536 } 537 break; 538 case TUNSIFPID: 539 tp->tun_pid = curproc->p_pid; 540 break; 541 case FIONBIO: 542 break; 543 case FIOASYNC: 544 if (*(int *)data) 545 tp->tun_flags |= TUN_ASYNC; 546 else 547 tp->tun_flags &= ~TUN_ASYNC; 548 break; 549 case FIONREAD: 550 s = splimp(); 551 if (tp->tun_if.if_snd.ifq_head) { 552 struct mbuf *mb = tp->tun_if.if_snd.ifq_head; 553 for( *(int *)data = 0; mb != 0; mb = mb->m_next) 554 *(int *)data += mb->m_len; 555 } else 556 *(int *)data = 0; 557 splx(s); 558 break; 559 case FIOSETOWN: 560 return (fsetown(*(int *)data, &tp->tun_sigio)); 561 562 case FIOGETOWN: 563 *(int *)data = fgetown(tp->tun_sigio); 564 return (0); 565 566 /* This is deprecated, FIOSETOWN should be used instead. */ 567 case TIOCSPGRP: 568 return (fsetown(-(*(int *)data), &tp->tun_sigio)); 569 570 /* This is deprecated, FIOGETOWN should be used instead. */ 571 case TIOCGPGRP: 572 *(int *)data = -fgetown(tp->tun_sigio); 573 return (0); 574 575 default: 576 return (ENOTTY); 577 } 578 return (0); 579} 580 581/* 582 * The cdevsw read interface - reads a packet at a time, or at 583 * least as much of a packet as can be read. 584 */ 585static int 586tunread(dev, uio, flag) 587 dev_t dev; 588 struct uio *uio; 589 int flag; 590{ 591 struct tun_softc *tp = dev->si_drv1; 592 struct ifnet *ifp = &tp->tun_if; 593 struct mbuf *m, *m0; 594 int error=0, len, s; 595 596 TUNDEBUG ("%s%d: read\n", ifp->if_name, ifp->if_unit); 597 if ((tp->tun_flags & TUN_READY) != TUN_READY) { 598 TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name, 599 ifp->if_unit, tp->tun_flags); 600 return EHOSTDOWN; 601 } 602 603 tp->tun_flags &= ~TUN_RWAIT; 604 605 s = splimp(); 606 do { 607 IF_DEQUEUE(&ifp->if_snd, m0); 608 if (m0 == 0) { 609 if (flag & IO_NDELAY) { 610 splx(s); 611 return EWOULDBLOCK; 612 } 613 tp->tun_flags |= TUN_RWAIT; 614 if((error = tsleep((caddr_t)tp, PCATCH | (PZERO + 1), 615 "tunread", 0)) != 0) { 616 splx(s); 617 return error; 618 } 619 } 620 } while (m0 == 0); 621 splx(s); 622 623 while (m0 && uio->uio_resid > 0 && error == 0) { 624 len = min(uio->uio_resid, m0->m_len); 625 if (len == 0) 626 break; 627 error = uiomove(mtod(m0, caddr_t), len, uio); 628 MFREE(m0, m); 629 m0 = m; 630 } 631 632 if (m0) { 633 TUNDEBUG("Dropping mbuf\n"); 634 m_freem(m0); 635 } 636 return error; 637} 638 639/* 640 * the cdevsw write interface - an atomic write is a packet - or else! 641 */ 642static int 643tunwrite(dev, uio, flag) 644 dev_t dev; 645 struct uio *uio; 646 int flag; 647{ 648 struct tun_softc *tp = dev->si_drv1; 649 struct ifnet *ifp = &tp->tun_if; 650 struct mbuf *top, **mp, *m; 651 int error=0, tlen, mlen; 652 uint32_t family; 653 654 TUNDEBUG("%s%d: tunwrite\n", ifp->if_name, ifp->if_unit); 655 656 if (uio->uio_resid == 0) 657 return 0; 658 659 if (uio->uio_resid < 0 || uio->uio_resid > TUNMRU) { 660 TUNDEBUG("%s%d: len=%d!\n", ifp->if_name, ifp->if_unit, 661 uio->uio_resid); 662 return EIO; 663 } 664 tlen = uio->uio_resid; 665 666 /* get a header mbuf */ 667 MGETHDR(m, M_DONTWAIT, MT_DATA); 668 if (m == NULL) 669 return ENOBUFS; 670 mlen = MHLEN; 671 672 top = 0; 673 mp = ⊤ 674 while (error == 0 && uio->uio_resid > 0) { 675 m->m_len = min(mlen, uio->uio_resid); 676 error = uiomove(mtod (m, caddr_t), m->m_len, uio); 677 *mp = m; 678 mp = &m->m_next; 679 if (uio->uio_resid > 0) { 680 MGET (m, M_DONTWAIT, MT_DATA); 681 if (m == 0) { 682 error = ENOBUFS; 683 break; 684 } 685 mlen = MLEN; 686 } 687 } 688 if (error) { 689 if (top) 690 m_freem (top); 691 ifp->if_ierrors++; 692 return error; 693 } 694 695 top->m_pkthdr.len = tlen; 696 top->m_pkthdr.rcvif = ifp; 697 698 if (ifp->if_bpf) { 699 if (tp->tun_flags & TUN_IFHEAD) { 700 /* 701 * Conveniently, we already have a 4-byte address 702 * family prepended to our packet ! 703 * Inconveniently, it's in the wrong byte order ! 704 */ 705 if ((top = m_pullup(top, sizeof(family))) == NULL) 706 return ENOBUFS; 707 *mtod(top, u_int32_t *) = 708 ntohl(*mtod(top, u_int32_t *)); 709 bpf_mtap(ifp, top); 710 *mtod(top, u_int32_t *) = 711 htonl(*mtod(top, u_int32_t *)); 712 } else { 713 /* 714 * We need to prepend the address family as 715 * a four byte field. Cons up a dummy header 716 * to pacify bpf. This is safe because bpf 717 * will only read from the mbuf (i.e., it won't 718 * try to free it or keep a pointer to it). 719 */ 720 struct mbuf m; 721 uint32_t af = AF_INET; 722 723 m.m_next = top; 724 m.m_len = 4; 725 m.m_data = (char *)⁡ 726 727 bpf_mtap(ifp, &m); 728 } 729 } 730 731 if (tp->tun_flags & TUN_IFHEAD) { 732 if (top->m_len < sizeof(family) && 733 (top = m_pullup(top, sizeof(family))) == NULL) 734 return ENOBUFS; 735 family = ntohl(*mtod(top, u_int32_t *)); 736 m_adj(top, sizeof(family)); 737 } else 738 family = AF_INET; 739 740 ifp->if_ibytes += top->m_pkthdr.len; 741 ifp->if_ipackets++; 742 743 return family_enqueue(family, top); 744} 745 746/* 747 * tunpoll - the poll interface, this is only useful on reads 748 * really. The write detect always returns true, write never blocks 749 * anyway, it either accepts the packet or drops it. 750 */ 751static int 752tunpoll(dev, events, p) 753 dev_t dev; 754 int events; 755 struct proc *p; 756{ 757 int s; 758 struct tun_softc *tp = dev->si_drv1; 759 struct ifnet *ifp = &tp->tun_if; 760 int revents = 0; 761 762 s = splimp(); 763 TUNDEBUG("%s%d: tunpoll\n", ifp->if_name, ifp->if_unit); 764 765 if (events & (POLLIN | POLLRDNORM)) { 766 if (ifp->if_snd.ifq_len > 0) { 767 TUNDEBUG("%s%d: tunpoll q=%d\n", ifp->if_name, 768 ifp->if_unit, ifp->if_snd.ifq_len); 769 revents |= events & (POLLIN | POLLRDNORM); 770 } else { 771 TUNDEBUG("%s%d: tunpoll waiting\n", ifp->if_name, 772 ifp->if_unit); 773 selrecord(p, &tp->tun_rsel); 774 } 775 } 776 if (events & (POLLOUT | POLLWRNORM)) 777 revents |= events & (POLLOUT | POLLWRNORM); 778 779 splx(s); 780 return (revents); 781} 782