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: src/sys/net/if_tun.c,v 1.74.2.8 2002/02/13 00:43:11 dillon Exp $ 17 * $DragonFly: src/sys/net/tun/if_tun.c,v 1.27 2005/12/11 13:00:17 swildner Exp $ 18 */ 19 20 #include "opt_atalk.h" 21 #include "opt_inet.h" 22 #include "opt_inet6.h" 23 #include "opt_ipx.h" 24 25 #include <sys/param.h> 26 #include <sys/proc.h> 27 #include <sys/systm.h> 28 #include <sys/mbuf.h> 29 #include <sys/socket.h> 30 #include <sys/filio.h> 31 #include <sys/sockio.h> 32 #include <sys/thread2.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/if_types.h> 46 #include <net/ifq_var.h> 47 #include <net/netisr.h> 48 #include <net/route.h> 49 50 #ifdef INET 51 #include <netinet/in.h> 52 #endif 53 54 #include <net/bpf.h> 55 56 #include "if_tunvar.h" 57 #include "if_tun.h" 58 59 static MALLOC_DEFINE(M_TUN, "tun", "Tunnel Interface"); 60 61 static void tunattach (void *); 62 PSEUDO_SET(tunattach, if_tun); 63 64 static void tuncreate (dev_t dev); 65 66 #define TUNDEBUG if (tundebug) if_printf 67 static int tundebug = 0; 68 SYSCTL_INT(_debug, OID_AUTO, if_tun_debug, CTLFLAG_RW, &tundebug, 0, ""); 69 70 static int tunoutput (struct ifnet *, struct mbuf *, struct sockaddr *, 71 struct rtentry *rt); 72 static int tunifioctl (struct ifnet *, u_long, caddr_t, struct ucred *); 73 static int tuninit (struct ifnet *); 74 static void tunstart(struct ifnet *); 75 76 static d_open_t tunopen; 77 static d_close_t tunclose; 78 static d_read_t tunread; 79 static d_write_t tunwrite; 80 static d_ioctl_t tunioctl; 81 static d_poll_t tunpoll; 82 83 #define CDEV_MAJOR 52 84 static struct cdevsw tun_cdevsw = { 85 /* name */ "tun", 86 /* maj */ CDEV_MAJOR, 87 /* flags */ 0, 88 /* port */ NULL, 89 /* clone */ NULL, 90 91 /* open */ tunopen, 92 /* close */ tunclose, 93 /* read */ tunread, 94 /* write */ tunwrite, 95 /* ioctl */ tunioctl, 96 /* poll */ tunpoll, 97 /* mmap */ nommap, 98 /* strategy */ nostrategy, 99 /* dump */ nodump, 100 /* psize */ nopsize 101 }; 102 103 static void 104 tunattach(void *dummy) 105 { 106 cdevsw_add(&tun_cdevsw, 0, 0); 107 } 108 109 static void 110 tuncreate(dev_t dev) 111 { 112 struct tun_softc *sc; 113 struct ifnet *ifp; 114 115 dev = make_dev(&tun_cdevsw, minor(dev), 116 UID_UUCP, GID_DIALER, 0600, "tun%d", lminor(dev)); 117 118 MALLOC(sc, struct tun_softc *, sizeof(*sc), M_TUN, M_WAITOK); 119 bzero(sc, sizeof *sc); 120 sc->tun_flags = TUN_INITED; 121 122 ifp = &sc->tun_if; 123 if_initname(ifp, "tun", lminor(dev)); 124 ifp->if_mtu = TUNMTU; 125 ifp->if_ioctl = tunifioctl; 126 ifp->if_output = tunoutput; 127 ifp->if_start = tunstart; 128 ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 129 ifp->if_type = IFT_PPP; 130 ifq_set_maxlen(&ifp->if_snd, ifqmaxlen); 131 ifq_set_ready(&ifp->if_snd); 132 ifp->if_softc = sc; 133 if_attach(ifp, NULL); 134 bpfattach(ifp, DLT_NULL, sizeof(u_int)); 135 dev->si_drv1 = sc; 136 } 137 138 /* 139 * tunnel open - must be superuser & the device must be 140 * configured in 141 */ 142 static int 143 tunopen(dev_t dev, int flag, int mode, struct thread *td) 144 { 145 struct ifnet *ifp; 146 struct tun_softc *tp; 147 int error; 148 149 KKASSERT(td->td_proc); 150 if ((error = suser(td)) != NULL) 151 return (error); 152 153 tp = dev->si_drv1; 154 if (!tp) { 155 tuncreate(dev); 156 tp = dev->si_drv1; 157 } 158 if (tp->tun_flags & TUN_OPEN) 159 return EBUSY; 160 tp->tun_pid = td->td_proc->p_pid; 161 ifp = &tp->tun_if; 162 tp->tun_flags |= TUN_OPEN; 163 TUNDEBUG(ifp, "open\n"); 164 return (0); 165 } 166 167 /* 168 * tunclose - close the device - mark i/f down & delete 169 * routing info 170 */ 171 static int 172 tunclose(dev_t dev, int foo, int bar, struct thread *td) 173 { 174 struct tun_softc *tp; 175 struct ifnet *ifp; 176 177 tp = dev->si_drv1; 178 ifp = &tp->tun_if; 179 180 tp->tun_flags &= ~TUN_OPEN; 181 tp->tun_pid = 0; 182 183 /* Junk all pending output. */ 184 lwkt_serialize_enter(ifp->if_serializer); 185 ifq_purge(&ifp->if_snd); 186 lwkt_serialize_exit(ifp->if_serializer); 187 188 if (ifp->if_flags & IFF_UP) { 189 lwkt_serialize_enter(ifp->if_serializer); 190 if_down(ifp); 191 lwkt_serialize_exit(ifp->if_serializer); 192 } 193 194 if (ifp->if_flags & IFF_RUNNING) { 195 struct ifaddr *ifa; 196 197 lwkt_serialize_enter(ifp->if_serializer); 198 /* find internet addresses and delete routes */ 199 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 200 if (ifa->ifa_addr->sa_family == AF_INET) { 201 rtinit(ifa, (int)RTM_DELETE, 202 tp->tun_flags & TUN_DSTADDR ? RTF_HOST : 0); 203 } 204 } 205 ifp->if_flags &= ~IFF_RUNNING; 206 lwkt_serialize_exit(ifp->if_serializer); 207 } 208 209 funsetown(tp->tun_sigio); 210 selwakeup(&tp->tun_rsel); 211 212 TUNDEBUG(ifp, "closed\n"); 213 return (0); 214 } 215 216 static int 217 tuninit(struct ifnet *ifp) 218 { 219 struct tun_softc *tp = ifp->if_softc; 220 struct ifaddr *ifa; 221 int error = 0; 222 223 TUNDEBUG(ifp, "tuninit\n"); 224 225 ifp->if_flags |= IFF_UP | IFF_RUNNING; 226 getmicrotime(&ifp->if_lastchange); 227 228 for (ifa = TAILQ_FIRST(&ifp->if_addrhead); ifa; 229 ifa = TAILQ_NEXT(ifa, ifa_link)) { 230 if (ifa->ifa_addr == NULL) 231 error = EFAULT; 232 /* XXX: Should maybe return straight off? */ 233 else { 234 #ifdef INET 235 if (ifa->ifa_addr->sa_family == AF_INET) { 236 struct sockaddr_in *si; 237 238 si = (struct sockaddr_in *)ifa->ifa_addr; 239 if (si->sin_addr.s_addr) 240 tp->tun_flags |= TUN_IASET; 241 242 si = (struct sockaddr_in *)ifa->ifa_dstaddr; 243 if (si && si->sin_addr.s_addr) 244 tp->tun_flags |= TUN_DSTADDR; 245 } 246 #endif 247 } 248 } 249 return (error); 250 } 251 252 /* 253 * Process an ioctl request. 254 * 255 * MPSAFE 256 */ 257 int 258 tunifioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr) 259 { 260 struct ifreq *ifr = (struct ifreq *)data; 261 struct tun_softc *tp = ifp->if_softc; 262 struct ifstat *ifs; 263 int error = 0; 264 265 switch(cmd) { 266 case SIOCGIFSTATUS: 267 ifs = (struct ifstat *)data; 268 if (tp->tun_pid) 269 sprintf(ifs->ascii + strlen(ifs->ascii), 270 "\tOpened by PID %d\n", tp->tun_pid); 271 break; 272 case SIOCSIFADDR: 273 error = tuninit(ifp); 274 TUNDEBUG(ifp, "address set, error=%d\n", error); 275 break; 276 case SIOCSIFDSTADDR: 277 error = tuninit(ifp); 278 TUNDEBUG(ifp, "destination address set, error=%d\n", error); 279 break; 280 case SIOCSIFMTU: 281 ifp->if_mtu = ifr->ifr_mtu; 282 TUNDEBUG(ifp, "mtu set\n"); 283 break; 284 case SIOCSIFFLAGS: 285 case SIOCADDMULTI: 286 case SIOCDELMULTI: 287 break; 288 default: 289 error = EINVAL; 290 } 291 return (error); 292 } 293 294 /* 295 * tunoutput - queue packets from higher level ready to put out. 296 * 297 * MPSAFE 298 */ 299 int 300 tunoutput(struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst, 301 struct rtentry *rt) 302 { 303 struct tun_softc *tp = ifp->if_softc; 304 int error; 305 struct altq_pktattr pktattr; 306 307 TUNDEBUG(ifp, "tunoutput\n"); 308 309 if ((tp->tun_flags & TUN_READY) != TUN_READY) { 310 TUNDEBUG(ifp, "not ready 0%o\n", tp->tun_flags); 311 m_freem (m0); 312 return EHOSTDOWN; 313 } 314 315 /* 316 * if the queueing discipline needs packet classification, 317 * do it before prepending link headers. 318 */ 319 ifq_classify(&ifp->if_snd, m0, dst->sa_family, &pktattr); 320 321 /* BPF write needs to be handled specially */ 322 if (dst->sa_family == AF_UNSPEC) { 323 dst->sa_family = *(mtod(m0, int *)); 324 m0->m_len -= sizeof(int); 325 m0->m_pkthdr.len -= sizeof(int); 326 m0->m_data += sizeof(int); 327 } 328 329 if (ifp->if_bpf) { 330 /* 331 * We need to prepend the address family as 332 * a four byte field. 333 */ 334 uint32_t af = dst->sa_family; 335 336 bpf_ptap(ifp->if_bpf, m0, &af, sizeof(af)); 337 } 338 339 /* prepend sockaddr? this may abort if the mbuf allocation fails */ 340 if (tp->tun_flags & TUN_LMODE) { 341 /* allocate space for sockaddr */ 342 M_PREPEND(m0, dst->sa_len, MB_DONTWAIT); 343 344 /* if allocation failed drop packet */ 345 if (m0 == NULL){ 346 IF_DROP(&ifp->if_snd); 347 ifp->if_oerrors++; 348 return (ENOBUFS); 349 } else { 350 bcopy(dst, m0->m_data, dst->sa_len); 351 } 352 } 353 354 if (tp->tun_flags & TUN_IFHEAD) { 355 /* Prepend the address family */ 356 M_PREPEND(m0, 4, MB_DONTWAIT); 357 358 /* if allocation failed drop packet */ 359 if (m0 == NULL){ 360 IF_DROP(&ifp->if_snd); 361 ifp->if_oerrors++; 362 return ENOBUFS; 363 } else 364 *(u_int32_t *)m0->m_data = htonl(dst->sa_family); 365 } else { 366 #ifdef INET 367 if (dst->sa_family != AF_INET) 368 #endif 369 { 370 m_freem(m0); 371 return EAFNOSUPPORT; 372 } 373 } 374 375 error = ifq_handoff(ifp, m0, &pktattr); 376 if (error) { 377 ifp->if_collisions++; 378 } else { 379 ifp->if_opackets++; 380 if (tp->tun_flags & TUN_RWAIT) { 381 tp->tun_flags &= ~TUN_RWAIT; 382 wakeup((caddr_t)tp); 383 } 384 get_mplock(); 385 if (tp->tun_flags & TUN_ASYNC && tp->tun_sigio) 386 pgsigio(tp->tun_sigio, SIGIO, 0); 387 selwakeup(&tp->tun_rsel); 388 rel_mplock(); 389 } 390 return (error); 391 } 392 393 /* 394 * the cdevsw interface is now pretty minimal. 395 */ 396 static int 397 tunioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td) 398 { 399 struct tun_softc *tp = dev->si_drv1; 400 struct tuninfo *tunp; 401 402 switch (cmd) { 403 case TUNSIFINFO: 404 tunp = (struct tuninfo *)data; 405 if (tunp->mtu < IF_MINMTU) 406 return (EINVAL); 407 tp->tun_if.if_mtu = tunp->mtu; 408 tp->tun_if.if_type = tunp->type; 409 tp->tun_if.if_baudrate = tunp->baudrate; 410 break; 411 case TUNGIFINFO: 412 tunp = (struct tuninfo *)data; 413 tunp->mtu = tp->tun_if.if_mtu; 414 tunp->type = tp->tun_if.if_type; 415 tunp->baudrate = tp->tun_if.if_baudrate; 416 break; 417 case TUNSDEBUG: 418 tundebug = *(int *)data; 419 break; 420 case TUNGDEBUG: 421 *(int *)data = tundebug; 422 break; 423 case TUNSLMODE: 424 if (*(int *)data) { 425 tp->tun_flags |= TUN_LMODE; 426 tp->tun_flags &= ~TUN_IFHEAD; 427 } else 428 tp->tun_flags &= ~TUN_LMODE; 429 break; 430 case TUNSIFHEAD: 431 if (*(int *)data) { 432 tp->tun_flags |= TUN_IFHEAD; 433 tp->tun_flags &= ~TUN_LMODE; 434 } else 435 tp->tun_flags &= ~TUN_IFHEAD; 436 break; 437 case TUNGIFHEAD: 438 *(int *)data = (tp->tun_flags & TUN_IFHEAD) ? 1 : 0; 439 break; 440 case TUNSIFMODE: 441 /* deny this if UP */ 442 if (tp->tun_if.if_flags & IFF_UP) 443 return(EBUSY); 444 445 switch (*(int *)data & ~IFF_MULTICAST) { 446 case IFF_POINTOPOINT: 447 case IFF_BROADCAST: 448 tp->tun_if.if_flags &= ~(IFF_BROADCAST|IFF_POINTOPOINT); 449 tp->tun_if.if_flags |= *(int *)data; 450 break; 451 default: 452 return(EINVAL); 453 } 454 break; 455 case TUNSIFPID: 456 tp->tun_pid = curproc->p_pid; 457 break; 458 case FIONBIO: 459 break; 460 case FIOASYNC: 461 if (*(int *)data) 462 tp->tun_flags |= TUN_ASYNC; 463 else 464 tp->tun_flags &= ~TUN_ASYNC; 465 break; 466 case FIONREAD: 467 lwkt_serialize_enter(tp->tun_if.if_serializer); 468 if (!ifq_is_empty(&tp->tun_if.if_snd)) { 469 struct mbuf *mb; 470 471 mb = ifq_poll(&tp->tun_if.if_snd); 472 for( *(int *)data = 0; mb != 0; mb = mb->m_next) 473 *(int *)data += mb->m_len; 474 } else { 475 *(int *)data = 0; 476 } 477 lwkt_serialize_exit(tp->tun_if.if_serializer); 478 break; 479 case FIOSETOWN: 480 return (fsetown(*(int *)data, &tp->tun_sigio)); 481 482 case FIOGETOWN: 483 *(int *)data = fgetown(tp->tun_sigio); 484 return (0); 485 486 /* This is deprecated, FIOSETOWN should be used instead. */ 487 case TIOCSPGRP: 488 return (fsetown(-(*(int *)data), &tp->tun_sigio)); 489 490 /* This is deprecated, FIOGETOWN should be used instead. */ 491 case TIOCGPGRP: 492 *(int *)data = -fgetown(tp->tun_sigio); 493 return (0); 494 495 default: 496 return (ENOTTY); 497 } 498 return (0); 499 } 500 501 /* 502 * The cdevsw read interface - reads a packet at a time, or at 503 * least as much of a packet as can be read. 504 */ 505 static int 506 tunread(dev_t dev, struct uio *uio, int flag) 507 { 508 struct tun_softc *tp = dev->si_drv1; 509 struct ifnet *ifp = &tp->tun_if; 510 struct mbuf *m0; 511 int error=0, len; 512 513 TUNDEBUG(ifp, "read\n"); 514 if ((tp->tun_flags & TUN_READY) != TUN_READY) { 515 TUNDEBUG(ifp, "not ready 0%o\n", tp->tun_flags); 516 return EHOSTDOWN; 517 } 518 519 tp->tun_flags &= ~TUN_RWAIT; 520 521 lwkt_serialize_enter(ifp->if_serializer); 522 523 while ((m0 = ifq_dequeue(&ifp->if_snd, NULL)) == NULL) { 524 if (flag & IO_NDELAY) { 525 lwkt_serialize_exit(ifp->if_serializer); 526 return EWOULDBLOCK; 527 } 528 tp->tun_flags |= TUN_RWAIT; 529 lwkt_serialize_exit(ifp->if_serializer); 530 if ((error = tsleep(tp, PCATCH, "tunread", 0)) != 0) 531 return error; 532 lwkt_serialize_enter(ifp->if_serializer); 533 } 534 535 lwkt_serialize_exit(ifp->if_serializer); 536 537 while (m0 && uio->uio_resid > 0 && error == 0) { 538 len = min(uio->uio_resid, m0->m_len); 539 if (len != 0) 540 error = uiomove(mtod(m0, caddr_t), len, uio); 541 m0 = m_free(m0); 542 } 543 544 if (m0) { 545 TUNDEBUG(ifp, "Dropping mbuf\n"); 546 m_freem(m0); 547 } 548 return error; 549 } 550 551 /* 552 * the cdevsw write interface - an atomic write is a packet - or else! 553 */ 554 static int 555 tunwrite(dev_t dev, struct uio *uio, int flag) 556 { 557 struct tun_softc *tp = dev->si_drv1; 558 struct ifnet *ifp = &tp->tun_if; 559 struct mbuf *top, **mp, *m; 560 int error=0, tlen, mlen; 561 uint32_t family; 562 int isr; 563 564 TUNDEBUG(ifp, "tunwrite\n"); 565 566 if (uio->uio_resid == 0) 567 return 0; 568 569 if (uio->uio_resid < 0 || uio->uio_resid > TUNMRU) { 570 TUNDEBUG(ifp, "len=%d!\n", uio->uio_resid); 571 return EIO; 572 } 573 tlen = uio->uio_resid; 574 575 /* get a header mbuf */ 576 MGETHDR(m, MB_DONTWAIT, MT_DATA); 577 if (m == NULL) 578 return ENOBUFS; 579 mlen = MHLEN; 580 581 top = 0; 582 mp = ⊤ 583 while (error == 0 && uio->uio_resid > 0) { 584 m->m_len = min(mlen, uio->uio_resid); 585 error = uiomove(mtod (m, caddr_t), m->m_len, uio); 586 *mp = m; 587 mp = &m->m_next; 588 if (uio->uio_resid > 0) { 589 MGET (m, MB_DONTWAIT, MT_DATA); 590 if (m == 0) { 591 error = ENOBUFS; 592 break; 593 } 594 mlen = MLEN; 595 } 596 } 597 if (error) { 598 if (top) 599 m_freem (top); 600 ifp->if_ierrors++; 601 return error; 602 } 603 604 top->m_pkthdr.len = tlen; 605 top->m_pkthdr.rcvif = ifp; 606 607 if (ifp->if_bpf) { 608 if (tp->tun_flags & TUN_IFHEAD) { 609 /* 610 * Conveniently, we already have a 4-byte address 611 * family prepended to our packet ! 612 * Inconveniently, it's in the wrong byte order ! 613 */ 614 if ((top = m_pullup(top, sizeof(family))) == NULL) 615 return ENOBUFS; 616 *mtod(top, u_int32_t *) = 617 ntohl(*mtod(top, u_int32_t *)); 618 bpf_mtap(ifp->if_bpf, top); 619 *mtod(top, u_int32_t *) = 620 htonl(*mtod(top, u_int32_t *)); 621 } else { 622 /* 623 * We need to prepend the address family as 624 * a four byte field. 625 */ 626 static const uint32_t af = AF_INET; 627 628 bpf_ptap(ifp->if_bpf, top, &af, sizeof(af)); 629 } 630 } 631 632 if (tp->tun_flags & TUN_IFHEAD) { 633 if (top->m_len < sizeof(family) && 634 (top = m_pullup(top, sizeof(family))) == NULL) 635 return ENOBUFS; 636 family = ntohl(*mtod(top, u_int32_t *)); 637 m_adj(top, sizeof(family)); 638 } else 639 family = AF_INET; 640 641 ifp->if_ibytes += top->m_pkthdr.len; 642 ifp->if_ipackets++; 643 644 switch (family) { 645 #ifdef INET 646 case AF_INET: 647 isr = NETISR_IP; 648 break; 649 #endif 650 #ifdef INET6 651 case AF_INET6: 652 isr = NETISR_IPV6; 653 break; 654 #endif 655 #ifdef IPX 656 case AF_IPX: 657 isr = NETISR_IPX; 658 break; 659 #endif 660 #ifdef NETATALK 661 case AF_APPLETALK: 662 isr = NETISR_ATALK2; 663 break; 664 #endif 665 default: 666 m_freem(m); 667 return (EAFNOSUPPORT); 668 } 669 670 netisr_dispatch(isr, top); 671 return (0); 672 } 673 674 /* 675 * tunpoll - the poll interface, this is only useful on reads 676 * really. The write detect always returns true, write never blocks 677 * anyway, it either accepts the packet or drops it. 678 */ 679 static int 680 tunpoll(dev_t dev, int events, struct thread *td) 681 { 682 struct tun_softc *tp = dev->si_drv1; 683 struct ifnet *ifp = &tp->tun_if; 684 int revents = 0; 685 686 TUNDEBUG(ifp, "tunpoll\n"); 687 688 lwkt_serialize_enter(ifp->if_serializer); 689 690 if (events & (POLLIN | POLLRDNORM)) { 691 if (!ifq_is_empty(&ifp->if_snd)) { 692 TUNDEBUG(ifp, "tunpoll q=%d\n", ifp->if_snd.ifq_len); 693 revents |= events & (POLLIN | POLLRDNORM); 694 } else { 695 TUNDEBUG(ifp, "tunpoll waiting\n"); 696 selrecord(td, &tp->tun_rsel); 697 } 698 } 699 if (events & (POLLOUT | POLLWRNORM)) 700 revents |= events & (POLLOUT | POLLWRNORM); 701 702 lwkt_serialize_exit(ifp->if_serializer); 703 704 return (revents); 705 } 706 707 /* 708 * Start packet transmission on the interface. 709 * when the interface queue is rate-limited by ALTQ, 710 * if_start is needed to drain packets from the queue in order 711 * to notify readers when outgoing packets become ready. 712 */ 713 static void 714 tunstart(struct ifnet *ifp) 715 { 716 struct tun_softc *tp = ifp->if_softc; 717 struct mbuf *m; 718 719 if (!ifq_is_enabled(&ifp->if_snd)) 720 return; 721 722 m = ifq_poll(&ifp->if_snd); 723 if (m != NULL) { 724 if (tp->tun_flags & TUN_RWAIT) { 725 tp->tun_flags &= ~TUN_RWAIT; 726 wakeup((caddr_t)tp); 727 } 728 if (tp->tun_flags & TUN_ASYNC && tp->tun_sigio) 729 pgsigio(tp->tun_sigio, SIGIO, 0); 730 selwakeup(&tp->tun_rsel); 731 } 732 } 733