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