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