117}; 118 119static int tapdebug = 0; /* debug flag */ 120static SLIST_HEAD(, tap_softc) taphead; /* first device */ 121static udev_t tapbasedev = NOUDEV; /* base device */ 122static struct rman tapdevunits[2]; /* device units */ 123#define tapunits tapdevunits 124#define vmnetunits (tapdevunits + 1) 125 126MALLOC_DECLARE(M_TAP); 127MALLOC_DEFINE(M_TAP, CDEV_NAME, "Ethernet tunnel interface"); 128SYSCTL_INT(_debug, OID_AUTO, if_tap_debug, CTLFLAG_RW, &tapdebug, 0, ""); 129DEV_MODULE(if_tap, tapmodevent, NULL); 130 131/* 132 * tapmodevent 133 * 134 * module event handler 135 */ 136static int 137tapmodevent(mod, type, data) 138 module_t mod; 139 int type; 140 void *data; 141{ 142 static eventhandler_tag eh_tag = NULL; 143 struct tap_softc *tp = NULL; 144 struct ifnet *ifp = NULL; 145 int error, s; 146 147 switch (type) { 148 case MOD_LOAD: 149 /* initialize resources */ 150 tapunits->rm_type = RMAN_ARRAY; 151 tapunits->rm_descr = "open tap units"; 152 vmnetunits->rm_type = RMAN_ARRAY; 153 vmnetunits->rm_descr = "open vmnet units"; 154 155 error = rman_init(tapunits); 156 if (error != 0) 157 goto bail; 158 159 error = rman_init(vmnetunits); 160 if (error != 0) 161 goto bail1; 162 163 error = rman_manage_region(tapunits, 0, TAPMAXUNIT); 164 if (error != 0) 165 goto bail2; 166 167 error = rman_manage_region(vmnetunits, 0, TAPMAXUNIT); 168 if (error != 0) 169 goto bail2; 170 171 /* intitialize device */ 172 173 SLIST_INIT(&taphead); 174 175 eh_tag = EVENTHANDLER_REGISTER(dev_clone, tapclone, 0, 1000); 176 if (eh_tag == NULL) { 177 error = ENOMEM; 178 goto bail2; 179 } 180 181 182 return (0); 183bail2: 184 rman_fini(vmnetunits); 185bail1: 186 rman_fini(tapunits); 187bail: 188 return (error); 189 190 case MOD_UNLOAD: 191 SLIST_FOREACH(tp, &taphead, tap_next) 192 if (tp->tap_unit != NULL) 193 return (EBUSY); 194 195 EVENTHANDLER_DEREGISTER(dev_clone, eh_tag); 196 197 error = rman_fini(tapunits); 198 KASSERT((error == 0), ("Could not fini tap units")); 199 error = rman_fini(vmnetunits); 200 KASSERT((error == 0), ("Could not fini vmnet units")); 201 202 while ((tp = SLIST_FIRST(&taphead)) != NULL) { 203 SLIST_REMOVE_HEAD(&taphead, tap_next); 204 205 ifp = &tp->tap_if; 206 207 TAPDEBUG("detaching %s%d\n", ifp->if_name,ifp->if_unit); 208 209 KASSERT(!(tp->tap_flags & TAP_OPEN), 210 ("%s%d flags is out of sync", ifp->if_name, 211 ifp->if_unit)); 212 213 /* XXX makedev check? nah.. not right now :) */ 214 215 s = splimp(); 216 ether_ifdetach(ifp); 217 splx(s); 218 219 free(tp, M_TAP); 220 } 221 222 if (tapbasedev != NOUDEV) 223 destroy_dev(udev2dev(tapbasedev, 0)); 224 225 226 break; 227 228 default: 229 return (EOPNOTSUPP); 230 } 231 232 return (0); 233} /* tapmodevent */ 234 235 236/* 237 * DEVFS handler 238 * 239 * We need to support two kind of devices - tap and vmnet 240 */ 241static void 242tapclone(arg, name, namelen, dev) 243 void *arg; 244 char *name; 245 int namelen; 246 dev_t *dev; 247{ 248 int unit, minor = 0 /* XXX avoid warning */ , error; 249 char *device_name = name; 250 struct resource *r = NULL; 251 252 if (*dev != NODEV) 253 return; 254 255 if (strcmp(device_name, TAP) == 0) { 256 /* get first free tap unit */ 257 r = rman_reserve_resource(tapunits, 0, TAPMAXUNIT, 1, 258 RF_ALLOCATED | RF_ACTIVE, NULL); 259 unit = rman_get_start(r); 260 minor = unit2minor(unit); 261 } 262 else if (strcmp(device_name, VMNET) == 0) { 263 /* get first free vmnet unit */ 264 r = rman_reserve_resource(vmnetunits, 0, TAPMAXUNIT, 1, 265 RF_ALLOCATED | RF_ACTIVE, NULL); 266 unit = rman_get_start(r); 267 minor = unit2minor(unit) | VMNET_DEV_MASK; 268 } 269 270 if (r != NULL) { /* need cloning */ 271 TAPDEBUG("%s%d is available. minor = %#x\n", 272 device_name, unit, minor); 273 274 error = rman_release_resource(r); 275 KASSERT((error == 0), ("Could not release tap/vmnet unit")); 276 277 /* check if device for the unit has been created */ 278 *dev = makedev(CDEV_MAJOR, minor); 279 if ((*dev)->si_flags & SI_NAMED) { 280 TAPDEBUG("%s%d device exists. minor = %#x\n", 281 device_name, unit, minor); 282 return; /* device has been created */ 283 } 284 } else { /* try to match name/unit, first try tap then vmnet */ 285 device_name = TAP; 286 if (dev_stdclone(name, NULL, device_name, &unit) != 1) { 287 device_name = VMNET; 288 289 if (dev_stdclone(name, NULL, device_name, &unit) != 1) 290 return; 291 292 minor = unit2minor(unit) | VMNET_DEV_MASK; 293 } else 294 minor = unit2minor(unit); 295 } 296 297 TAPDEBUG("make_dev(%s%d). minor = %#x\n", device_name, unit, minor); 298 299 *dev = make_dev(&tap_cdevsw, minor, UID_ROOT, GID_WHEEL, 0600, "%s%d", 300 device_name, unit); 301 302 if (tapbasedev == NOUDEV) 303 tapbasedev = (*dev)->si_udev; 304 else { 305 (*dev)->si_flags |= SI_CHEAPCLONE; 306 dev_depends(udev2dev(tapbasedev, 0), *dev); 307 } 308} /* tapclone */ 309 310 311/* 312 * tapcreate 313 * 314 * to create interface 315 */ 316static void 317tapcreate(dev) 318 dev_t dev; 319{ 320 struct ifnet *ifp = NULL; 321 struct tap_softc *tp = NULL; 322 unsigned short macaddr_hi; 323 int unit, s; 324 char *name = NULL; 325 326 /* allocate driver storage and create device */ 327 MALLOC(tp, struct tap_softc *, sizeof(*tp), M_TAP, M_WAITOK | M_ZERO); 328 SLIST_INSERT_HEAD(&taphead, tp, tap_next); 329 330 unit = dev2unit(dev) & TAPMAXUNIT; 331 332 /* select device: tap or vmnet */ 333 if (minor(dev) & VMNET_DEV_MASK) { 334 name = VMNET; 335 tp->tap_flags |= TAP_VMNET; 336 } else 337 name = TAP; 338 339 TAPDEBUG("tapcreate(%s%d). minor = %#x\n", name, unit, minor(dev)); 340 341 if (!(dev->si_flags & SI_NAMED)) 342 dev = make_dev(&tap_cdevsw, minor(dev), UID_ROOT, GID_WHEEL, 343 0600, "%s%d", name, unit); 344 345 /* generate fake MAC address: 00 bd xx xx xx unit_no */ 346 macaddr_hi = htons(0x00bd); 347 bcopy(&macaddr_hi, &tp->arpcom.ac_enaddr[0], sizeof(short)); 348 bcopy(&ticks, &tp->arpcom.ac_enaddr[2], sizeof(long)); 349 tp->arpcom.ac_enaddr[5] = (u_char)unit; 350 351 /* fill the rest and attach interface */ 352 ifp = &tp->tap_if; 353 ifp->if_softc = tp; 354 ifp->if_unit = unit; 355 ifp->if_name = name; 356 ifp->if_init = tapifinit; 357 ifp->if_start = tapifstart; 358 ifp->if_ioctl = tapifioctl; 359 ifp->if_mtu = ETHERMTU; 360 ifp->if_flags = (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST); 361 ifp->if_snd.ifq_maxlen = ifqmaxlen; 362 363 dev->si_drv1 = tp; 364 365 s = splimp(); 366 ether_ifattach(ifp, tp->arpcom.ac_enaddr); 367 splx(s); 368 369 tp->tap_flags |= TAP_INITED; 370 371 TAPDEBUG("interface %s%d is created. minor = %#x\n", 372 ifp->if_name, ifp->if_unit, minor(dev)); 373} /* tapcreate */ 374 375 376/* 377 * tapopen 378 * 379 * to open tunnel. must be superuser 380 */ 381static int 382tapopen(dev, flag, mode, td) 383 dev_t dev; 384 int flag; 385 int mode; 386 struct thread *td; 387{ 388 struct tap_softc *tp = NULL; 389 int unit, error; 390 struct resource *r = NULL; 391 392 if ((error = suser(td)) != 0) 393 return (error); 394 395 unit = dev2unit(dev) & TAPMAXUNIT; 396 397 if (minor(dev) & VMNET_DEV_MASK) 398 r = rman_reserve_resource(vmnetunits, unit, unit, 1, 399 RF_ALLOCATED | RF_ACTIVE, NULL); 400 else 401 r = rman_reserve_resource(tapunits, unit, unit, 1, 402 RF_ALLOCATED | RF_ACTIVE, NULL); 403 404 if (r == NULL) 405 return (EBUSY); 406 407 dev->si_flags &= ~SI_CHEAPCLONE; 408 409 tp = dev->si_drv1; 410 if (tp == NULL) { 411 tapcreate(dev); 412 tp = dev->si_drv1; 413 } 414 415 KASSERT(!(tp->tap_flags & TAP_OPEN), 416 ("%s%d flags is out of sync", tp->tap_if.if_name, unit)); 417 418 bcopy(tp->arpcom.ac_enaddr, tp->ether_addr, sizeof(tp->ether_addr)); 419 420 tp->tap_unit = r; 421 tp->tap_pid = td->td_proc->p_pid; 422 tp->tap_flags |= TAP_OPEN; 423 424 TAPDEBUG("%s%d is open. minor = %#x\n", 425 tp->tap_if.if_name, unit, minor(dev)); 426 427 return (0); 428} /* tapopen */ 429 430 431/* 432 * tapclose 433 * 434 * close the device - mark i/f down & delete routing info 435 */ 436static int 437tapclose(dev, foo, bar, td) 438 dev_t dev; 439 int foo; 440 int bar; 441 struct thread *td; 442{ 443 int s, error; 444 struct tap_softc *tp = dev->si_drv1; 445 struct ifnet *ifp = &tp->tap_if; 446 447 KASSERT((tp->tap_unit != NULL), 448 ("%s%d is not open", ifp->if_name, ifp->if_unit)); 449 450 /* junk all pending output */ 451 IF_DRAIN(&ifp->if_snd); 452 453 /* 454 * do not bring the interface down, and do not anything with 455 * interface, if we are in VMnet mode. just close the device. 456 */ 457 458 if (((tp->tap_flags & TAP_VMNET) == 0) && (ifp->if_flags & IFF_UP)) { 459 s = splimp(); 460 if_down(ifp); 461 if (ifp->if_flags & IFF_RUNNING) { 462 /* find internet addresses and delete routes */ 463 struct ifaddr *ifa = NULL; 464 465 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 466 if (ifa->ifa_addr->sa_family == AF_INET) { 467 rtinit(ifa, (int)RTM_DELETE, 0); 468 469 /* remove address from interface */ 470 bzero(ifa->ifa_addr, 471 sizeof(*(ifa->ifa_addr))); 472 bzero(ifa->ifa_dstaddr, 473 sizeof(*(ifa->ifa_dstaddr))); 474 bzero(ifa->ifa_netmask, 475 sizeof(*(ifa->ifa_netmask))); 476 } 477 } 478 479 ifp->if_flags &= ~IFF_RUNNING; 480 } 481 splx(s); 482 } 483 484 funsetown(&tp->tap_sigio); 485 selwakeup(&tp->tap_rsel); 486 487 tp->tap_flags &= ~TAP_OPEN; 488 tp->tap_pid = 0; 489 error = rman_release_resource(tp->tap_unit); 490 KASSERT((error == 0), 491 ("%s%d could not release unit", ifp->if_name, ifp->if_unit)); 492 tp->tap_unit = NULL; 493 494 TAPDEBUG("%s%d is closed. minor = %#x\n", 495 ifp->if_name, ifp->if_unit, minor(dev)); 496 497 return (0); 498} /* tapclose */ 499 500 501/* 502 * tapifinit 503 * 504 * network interface initialization function 505 */ 506static void 507tapifinit(xtp) 508 void *xtp; 509{ 510 struct tap_softc *tp = (struct tap_softc *)xtp; 511 struct ifnet *ifp = &tp->tap_if; 512 513 TAPDEBUG("initializing %s%d\n", ifp->if_name, ifp->if_unit); 514 515 ifp->if_flags |= IFF_RUNNING; 516 ifp->if_flags &= ~IFF_OACTIVE; 517 518 /* attempt to start output */ 519 tapifstart(ifp); 520} /* tapifinit */ 521 522 523/* 524 * tapifioctl 525 * 526 * Process an ioctl request on network interface 527 */ 528static int 529tapifioctl(ifp, cmd, data) 530 struct ifnet *ifp; 531 u_long cmd; 532 caddr_t data; 533{ 534 struct tap_softc *tp = (struct tap_softc *)(ifp->if_softc); 535 struct ifstat *ifs = NULL; 536 int s, dummy; 537 538 switch (cmd) { 539 case SIOCSIFFLAGS: /* XXX -- just like vmnet does */ 540 case SIOCADDMULTI: 541 case SIOCDELMULTI: 542 break; 543 544 case SIOCGIFSTATUS: 545 s = splimp(); 546 ifs = (struct ifstat *)data; 547 dummy = strlen(ifs->ascii); 548 if (tp->tap_pid != 0 && dummy < sizeof(ifs->ascii)) 549 snprintf(ifs->ascii + dummy, 550 sizeof(ifs->ascii) - dummy, 551 "\tOpened by PID %d\n", tp->tap_pid); 552 splx(s); 553 break; 554 555 default: 556 s = splimp(); 557 dummy = ether_ioctl(ifp, cmd, data); 558 splx(s); 559 return (dummy); 560 } 561 562 return (0); 563} /* tapifioctl */ 564 565 566/* 567 * tapifstart 568 * 569 * queue packets from higher level ready to put out 570 */ 571static void 572tapifstart(ifp) 573 struct ifnet *ifp; 574{ 575 struct tap_softc *tp = ifp->if_softc; 576 int s; 577 578 TAPDEBUG("%s%d starting\n", ifp->if_name, ifp->if_unit); 579 580 /* 581 * do not junk pending output if we are in VMnet mode. 582 * XXX: can this do any harm because of queue overflow? 583 */ 584 585 if (((tp->tap_flags & TAP_VMNET) == 0) && 586 ((tp->tap_flags & TAP_READY) != TAP_READY)) { 587 struct mbuf *m = NULL; 588 589 TAPDEBUG("%s%d not ready, tap_flags = 0x%x\n", ifp->if_name, 590 ifp->if_unit, tp->tap_flags); 591 592 s = splimp(); 593 do { 594 IF_DEQUEUE(&ifp->if_snd, m); 595 if (m != NULL) 596 m_freem(m); 597 ifp->if_oerrors ++; 598 } while (m != NULL); 599 splx(s); 600 601 return; 602 } 603 604 s = splimp(); 605 ifp->if_flags |= IFF_OACTIVE; 606 607 if (ifp->if_snd.ifq_len != 0) { 608 if (tp->tap_flags & TAP_RWAIT) { 609 tp->tap_flags &= ~TAP_RWAIT; 610 wakeup(tp); 611 } 612 613 if ((tp->tap_flags & TAP_ASYNC) && (tp->tap_sigio != NULL)) 614 pgsigio(&tp->tap_sigio, SIGIO, 0); 615 616 selwakeup(&tp->tap_rsel); 617 ifp->if_opackets ++; /* obytes are counted in ether_output */ 618 } 619 620 ifp->if_flags &= ~IFF_OACTIVE; 621 splx(s); 622} /* tapifstart */ 623 624 625/* 626 * tapioctl 627 * 628 * the cdevsw interface is now pretty minimal 629 */ 630static int 631tapioctl(dev, cmd, data, flag, td) 632 dev_t dev; 633 u_long cmd; 634 caddr_t data; 635 int flag; 636 struct thread *td; 637{ 638 struct tap_softc *tp = dev->si_drv1; 639 struct ifnet *ifp = &tp->tap_if; 640 struct tapinfo *tapp = NULL; 641 int s; 642 int f; 643 644 switch (cmd) { 645 case TAPSIFINFO: 646 s = splimp(); 647 tapp = (struct tapinfo *)data; 648 ifp->if_mtu = tapp->mtu; 649 ifp->if_type = tapp->type; 650 ifp->if_baudrate = tapp->baudrate; 651 splx(s); 652 break; 653 654 case TAPGIFINFO: 655 tapp = (struct tapinfo *)data; 656 tapp->mtu = ifp->if_mtu; 657 tapp->type = ifp->if_type; 658 tapp->baudrate = ifp->if_baudrate; 659 break; 660 661 case TAPSDEBUG: 662 tapdebug = *(int *)data; 663 break; 664 665 case TAPGDEBUG: 666 *(int *)data = tapdebug; 667 break; 668 669 case FIONBIO: 670 break; 671 672 case FIOASYNC: 673 s = splimp(); 674 if (*(int *)data) 675 tp->tap_flags |= TAP_ASYNC; 676 else 677 tp->tap_flags &= ~TAP_ASYNC; 678 splx(s); 679 break; 680 681 case FIONREAD: 682 s = splimp(); 683 if (ifp->if_snd.ifq_head) { 684 struct mbuf *mb = ifp->if_snd.ifq_head; 685 686 for(*(int *)data = 0;mb != NULL;mb = mb->m_next) 687 *(int *)data += mb->m_len; 688 } else 689 *(int *)data = 0; 690 splx(s); 691 break; 692 693 case FIOSETOWN: 694 return (fsetown(*(int *)data, &tp->tap_sigio)); 695 696 case FIOGETOWN: 697 *(int *)data = fgetown(&tp->tap_sigio); 698 return (0); 699 700 /* this is deprecated, FIOSETOWN should be used instead */ 701 case TIOCSPGRP: 702 return (fsetown(-(*(int *)data), &tp->tap_sigio)); 703 704 /* this is deprecated, FIOGETOWN should be used instead */ 705 case TIOCGPGRP: 706 *(int *)data = -fgetown(&tp->tap_sigio); 707 return (0); 708 709 /* VMware/VMnet port ioctl's */ 710 711 case SIOCGIFFLAGS: /* get ifnet flags */ 712 bcopy(&ifp->if_flags, data, sizeof(ifp->if_flags)); 713 break; 714 715 case VMIO_SIOCSIFFLAGS: /* VMware/VMnet SIOCSIFFLAGS */ 716 f = *(int *)data; 717 f &= 0x0fff; 718 f &= ~IFF_CANTCHANGE; 719 f |= IFF_UP; 720 721 s = splimp(); 722 ifp->if_flags = f | (ifp->if_flags & IFF_CANTCHANGE); 723 splx(s); 724 break; 725 726 case OSIOCGIFADDR: /* get MAC address of the remote side */ 727 case SIOCGIFADDR: 728 bcopy(tp->ether_addr, data, sizeof(tp->ether_addr)); 729 break; 730 731 case SIOCSIFADDR: /* set MAC address of the remote side */ 732 bcopy(data, tp->ether_addr, sizeof(tp->ether_addr)); 733 break; 734 735 default: 736 return (ENOTTY); 737 } 738 return (0); 739} /* tapioctl */ 740 741 742/* 743 * tapread 744 * 745 * the cdevsw read interface - reads a packet at a time, or at 746 * least as much of a packet as can be read 747 */ 748static int 749tapread(dev, uio, flag) 750 dev_t dev; 751 struct uio *uio; 752 int flag; 753{ 754 struct tap_softc *tp = dev->si_drv1; 755 struct ifnet *ifp = &tp->tap_if; 756 struct mbuf *m = NULL; 757 int error = 0, len, s; 758 759 TAPDEBUG("%s%d reading, minor = %#x\n", 760 ifp->if_name, ifp->if_unit, minor(dev)); 761 762 if ((tp->tap_flags & TAP_READY) != TAP_READY) { 763 TAPDEBUG("%s%d not ready. minor = %#x, tap_flags = 0x%x\n", 764 ifp->if_name, ifp->if_unit, minor(dev), tp->tap_flags); 765 766 return (EHOSTDOWN); 767 } 768 769 tp->tap_flags &= ~TAP_RWAIT; 770 771 /* sleep until we get a packet */ 772 do { 773 s = splimp(); 774 IF_DEQUEUE(&ifp->if_snd, m); 775 splx(s); 776 777 if (m == NULL) { 778 if (flag & IO_NDELAY) 779 return (EWOULDBLOCK); 780 781 tp->tap_flags |= TAP_RWAIT; 782 error = tsleep(tp,PCATCH|(PZERO+1),"taprd",0); 783 if (error) 784 return (error); 785 } 786 } while (m == NULL); 787 788 /* feed packet to bpf */ 789 BPF_MTAP(ifp, m); 790 791 /* xfer packet to user space */ 792 while ((m != NULL) && (uio->uio_resid > 0) && (error == 0)) { 793 len = min(uio->uio_resid, m->m_len); 794 if (len == 0) 795 break; 796 797 error = uiomove(mtod(m, void *), len, uio); 798 m = m_free(m); 799 } 800 801 if (m != NULL) { 802 TAPDEBUG("%s%d dropping mbuf, minor = %#x\n", ifp->if_name, 803 ifp->if_unit, minor(dev)); 804 m_freem(m); 805 } 806 807 return (error); 808} /* tapread */ 809 810 811/* 812 * tapwrite 813 * 814 * the cdevsw write interface - an atomic write is a packet - or else! 815 */ 816static int 817tapwrite(dev, uio, flag) 818 dev_t dev; 819 struct uio *uio; 820 int flag; 821{ 822 struct tap_softc *tp = dev->si_drv1; 823 struct ifnet *ifp = &tp->tap_if; 824 struct mbuf *top = NULL, **mp = NULL, *m = NULL; 825 int error = 0, tlen, mlen; 826 827 TAPDEBUG("%s%d writting, minor = %#x\n", 828 ifp->if_name, ifp->if_unit, minor(dev)); 829 830 if (uio->uio_resid == 0) 831 return (0); 832 833 if ((uio->uio_resid < 0) || (uio->uio_resid > TAPMRU)) { 834 TAPDEBUG("%s%d invalid packet len = %d, minor = %#x\n", 835 ifp->if_name, ifp->if_unit, uio->uio_resid, minor(dev)); 836 837 return (EIO); 838 } 839 tlen = uio->uio_resid; 840 841 /* get a header mbuf */ 842 MGETHDR(m, M_DONTWAIT, MT_DATA); 843 if (m == NULL) 844 return (ENOBUFS); 845 mlen = MHLEN; 846 847 top = 0; 848 mp = ⊤ 849 while ((error == 0) && (uio->uio_resid > 0)) { 850 m->m_len = min(mlen, uio->uio_resid); 851 error = uiomove(mtod(m, void *), m->m_len, uio); 852 *mp = m; 853 mp = &m->m_next; 854 if (uio->uio_resid > 0) { 855 MGET(m, M_DONTWAIT, MT_DATA); 856 if (m == NULL) { 857 error = ENOBUFS; 858 break; 859 } 860 mlen = MLEN; 861 } 862 } 863 if (error) { 864 ifp->if_ierrors ++; 865 if (top) 866 m_freem(top); 867 return (error); 868 } 869 870 top->m_pkthdr.len = tlen; 871 top->m_pkthdr.rcvif = ifp; 872 873 /* Pass packet up to parent. */ 874 (*ifp->if_input)(ifp, top); 875 ifp->if_ipackets ++; /* ibytes are counted in parent */ 876 877 return (0); 878} /* tapwrite */ 879 880 881/* 882 * tappoll 883 * 884 * the poll interface, this is only useful on reads 885 * really. the write detect always returns true, write never blocks 886 * anyway, it either accepts the packet or drops it 887 */ 888static int 889tappoll(dev, events, td) 890 dev_t dev; 891 int events; 892 struct thread *td; 893{ 894 struct tap_softc *tp = dev->si_drv1; 895 struct ifnet *ifp = &tp->tap_if; 896 int s, revents = 0; 897 898 TAPDEBUG("%s%d polling, minor = %#x\n", 899 ifp->if_name, ifp->if_unit, minor(dev)); 900 901 s = splimp(); 902 if (events & (POLLIN | POLLRDNORM)) { 903 if (ifp->if_snd.ifq_len > 0) { 904 TAPDEBUG("%s%d have data in queue. len = %d, " \ 905 "minor = %#x\n", ifp->if_name, ifp->if_unit, 906 ifp->if_snd.ifq_len, minor(dev)); 907 908 revents |= (events & (POLLIN | POLLRDNORM)); 909 } else { 910 TAPDEBUG("%s%d waiting for data, minor = %#x\n", 911 ifp->if_name, ifp->if_unit, minor(dev)); 912 913 selrecord(td, &tp->tap_rsel); 914 } 915 } 916 917 if (events & (POLLOUT | POLLWRNORM)) 918 revents |= (events & (POLLOUT | POLLWRNORM)); 919 920 splx(s); 921 return (revents); 922} /* tappoll */
| 112}; 113 114static int tapdebug = 0; /* debug flag */ 115static SLIST_HEAD(, tap_softc) taphead; /* first device */ 116static udev_t tapbasedev = NOUDEV; /* base device */ 117static struct rman tapdevunits[2]; /* device units */ 118#define tapunits tapdevunits 119#define vmnetunits (tapdevunits + 1) 120 121MALLOC_DECLARE(M_TAP); 122MALLOC_DEFINE(M_TAP, CDEV_NAME, "Ethernet tunnel interface"); 123SYSCTL_INT(_debug, OID_AUTO, if_tap_debug, CTLFLAG_RW, &tapdebug, 0, ""); 124DEV_MODULE(if_tap, tapmodevent, NULL); 125 126/* 127 * tapmodevent 128 * 129 * module event handler 130 */ 131static int 132tapmodevent(mod, type, data) 133 module_t mod; 134 int type; 135 void *data; 136{ 137 static eventhandler_tag eh_tag = NULL; 138 struct tap_softc *tp = NULL; 139 struct ifnet *ifp = NULL; 140 int error, s; 141 142 switch (type) { 143 case MOD_LOAD: 144 /* initialize resources */ 145 tapunits->rm_type = RMAN_ARRAY; 146 tapunits->rm_descr = "open tap units"; 147 vmnetunits->rm_type = RMAN_ARRAY; 148 vmnetunits->rm_descr = "open vmnet units"; 149 150 error = rman_init(tapunits); 151 if (error != 0) 152 goto bail; 153 154 error = rman_init(vmnetunits); 155 if (error != 0) 156 goto bail1; 157 158 error = rman_manage_region(tapunits, 0, TAPMAXUNIT); 159 if (error != 0) 160 goto bail2; 161 162 error = rman_manage_region(vmnetunits, 0, TAPMAXUNIT); 163 if (error != 0) 164 goto bail2; 165 166 /* intitialize device */ 167 168 SLIST_INIT(&taphead); 169 170 eh_tag = EVENTHANDLER_REGISTER(dev_clone, tapclone, 0, 1000); 171 if (eh_tag == NULL) { 172 error = ENOMEM; 173 goto bail2; 174 } 175 176 177 return (0); 178bail2: 179 rman_fini(vmnetunits); 180bail1: 181 rman_fini(tapunits); 182bail: 183 return (error); 184 185 case MOD_UNLOAD: 186 SLIST_FOREACH(tp, &taphead, tap_next) 187 if (tp->tap_unit != NULL) 188 return (EBUSY); 189 190 EVENTHANDLER_DEREGISTER(dev_clone, eh_tag); 191 192 error = rman_fini(tapunits); 193 KASSERT((error == 0), ("Could not fini tap units")); 194 error = rman_fini(vmnetunits); 195 KASSERT((error == 0), ("Could not fini vmnet units")); 196 197 while ((tp = SLIST_FIRST(&taphead)) != NULL) { 198 SLIST_REMOVE_HEAD(&taphead, tap_next); 199 200 ifp = &tp->tap_if; 201 202 TAPDEBUG("detaching %s%d\n", ifp->if_name,ifp->if_unit); 203 204 KASSERT(!(tp->tap_flags & TAP_OPEN), 205 ("%s%d flags is out of sync", ifp->if_name, 206 ifp->if_unit)); 207 208 /* XXX makedev check? nah.. not right now :) */ 209 210 s = splimp(); 211 ether_ifdetach(ifp); 212 splx(s); 213 214 free(tp, M_TAP); 215 } 216 217 if (tapbasedev != NOUDEV) 218 destroy_dev(udev2dev(tapbasedev, 0)); 219 220 221 break; 222 223 default: 224 return (EOPNOTSUPP); 225 } 226 227 return (0); 228} /* tapmodevent */ 229 230 231/* 232 * DEVFS handler 233 * 234 * We need to support two kind of devices - tap and vmnet 235 */ 236static void 237tapclone(arg, name, namelen, dev) 238 void *arg; 239 char *name; 240 int namelen; 241 dev_t *dev; 242{ 243 int unit, minor = 0 /* XXX avoid warning */ , error; 244 char *device_name = name; 245 struct resource *r = NULL; 246 247 if (*dev != NODEV) 248 return; 249 250 if (strcmp(device_name, TAP) == 0) { 251 /* get first free tap unit */ 252 r = rman_reserve_resource(tapunits, 0, TAPMAXUNIT, 1, 253 RF_ALLOCATED | RF_ACTIVE, NULL); 254 unit = rman_get_start(r); 255 minor = unit2minor(unit); 256 } 257 else if (strcmp(device_name, VMNET) == 0) { 258 /* get first free vmnet unit */ 259 r = rman_reserve_resource(vmnetunits, 0, TAPMAXUNIT, 1, 260 RF_ALLOCATED | RF_ACTIVE, NULL); 261 unit = rman_get_start(r); 262 minor = unit2minor(unit) | VMNET_DEV_MASK; 263 } 264 265 if (r != NULL) { /* need cloning */ 266 TAPDEBUG("%s%d is available. minor = %#x\n", 267 device_name, unit, minor); 268 269 error = rman_release_resource(r); 270 KASSERT((error == 0), ("Could not release tap/vmnet unit")); 271 272 /* check if device for the unit has been created */ 273 *dev = makedev(CDEV_MAJOR, minor); 274 if ((*dev)->si_flags & SI_NAMED) { 275 TAPDEBUG("%s%d device exists. minor = %#x\n", 276 device_name, unit, minor); 277 return; /* device has been created */ 278 } 279 } else { /* try to match name/unit, first try tap then vmnet */ 280 device_name = TAP; 281 if (dev_stdclone(name, NULL, device_name, &unit) != 1) { 282 device_name = VMNET; 283 284 if (dev_stdclone(name, NULL, device_name, &unit) != 1) 285 return; 286 287 minor = unit2minor(unit) | VMNET_DEV_MASK; 288 } else 289 minor = unit2minor(unit); 290 } 291 292 TAPDEBUG("make_dev(%s%d). minor = %#x\n", device_name, unit, minor); 293 294 *dev = make_dev(&tap_cdevsw, minor, UID_ROOT, GID_WHEEL, 0600, "%s%d", 295 device_name, unit); 296 297 if (tapbasedev == NOUDEV) 298 tapbasedev = (*dev)->si_udev; 299 else { 300 (*dev)->si_flags |= SI_CHEAPCLONE; 301 dev_depends(udev2dev(tapbasedev, 0), *dev); 302 } 303} /* tapclone */ 304 305 306/* 307 * tapcreate 308 * 309 * to create interface 310 */ 311static void 312tapcreate(dev) 313 dev_t dev; 314{ 315 struct ifnet *ifp = NULL; 316 struct tap_softc *tp = NULL; 317 unsigned short macaddr_hi; 318 int unit, s; 319 char *name = NULL; 320 321 /* allocate driver storage and create device */ 322 MALLOC(tp, struct tap_softc *, sizeof(*tp), M_TAP, M_WAITOK | M_ZERO); 323 SLIST_INSERT_HEAD(&taphead, tp, tap_next); 324 325 unit = dev2unit(dev) & TAPMAXUNIT; 326 327 /* select device: tap or vmnet */ 328 if (minor(dev) & VMNET_DEV_MASK) { 329 name = VMNET; 330 tp->tap_flags |= TAP_VMNET; 331 } else 332 name = TAP; 333 334 TAPDEBUG("tapcreate(%s%d). minor = %#x\n", name, unit, minor(dev)); 335 336 if (!(dev->si_flags & SI_NAMED)) 337 dev = make_dev(&tap_cdevsw, minor(dev), UID_ROOT, GID_WHEEL, 338 0600, "%s%d", name, unit); 339 340 /* generate fake MAC address: 00 bd xx xx xx unit_no */ 341 macaddr_hi = htons(0x00bd); 342 bcopy(&macaddr_hi, &tp->arpcom.ac_enaddr[0], sizeof(short)); 343 bcopy(&ticks, &tp->arpcom.ac_enaddr[2], sizeof(long)); 344 tp->arpcom.ac_enaddr[5] = (u_char)unit; 345 346 /* fill the rest and attach interface */ 347 ifp = &tp->tap_if; 348 ifp->if_softc = tp; 349 ifp->if_unit = unit; 350 ifp->if_name = name; 351 ifp->if_init = tapifinit; 352 ifp->if_start = tapifstart; 353 ifp->if_ioctl = tapifioctl; 354 ifp->if_mtu = ETHERMTU; 355 ifp->if_flags = (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST); 356 ifp->if_snd.ifq_maxlen = ifqmaxlen; 357 358 dev->si_drv1 = tp; 359 360 s = splimp(); 361 ether_ifattach(ifp, tp->arpcom.ac_enaddr); 362 splx(s); 363 364 tp->tap_flags |= TAP_INITED; 365 366 TAPDEBUG("interface %s%d is created. minor = %#x\n", 367 ifp->if_name, ifp->if_unit, minor(dev)); 368} /* tapcreate */ 369 370 371/* 372 * tapopen 373 * 374 * to open tunnel. must be superuser 375 */ 376static int 377tapopen(dev, flag, mode, td) 378 dev_t dev; 379 int flag; 380 int mode; 381 struct thread *td; 382{ 383 struct tap_softc *tp = NULL; 384 int unit, error; 385 struct resource *r = NULL; 386 387 if ((error = suser(td)) != 0) 388 return (error); 389 390 unit = dev2unit(dev) & TAPMAXUNIT; 391 392 if (minor(dev) & VMNET_DEV_MASK) 393 r = rman_reserve_resource(vmnetunits, unit, unit, 1, 394 RF_ALLOCATED | RF_ACTIVE, NULL); 395 else 396 r = rman_reserve_resource(tapunits, unit, unit, 1, 397 RF_ALLOCATED | RF_ACTIVE, NULL); 398 399 if (r == NULL) 400 return (EBUSY); 401 402 dev->si_flags &= ~SI_CHEAPCLONE; 403 404 tp = dev->si_drv1; 405 if (tp == NULL) { 406 tapcreate(dev); 407 tp = dev->si_drv1; 408 } 409 410 KASSERT(!(tp->tap_flags & TAP_OPEN), 411 ("%s%d flags is out of sync", tp->tap_if.if_name, unit)); 412 413 bcopy(tp->arpcom.ac_enaddr, tp->ether_addr, sizeof(tp->ether_addr)); 414 415 tp->tap_unit = r; 416 tp->tap_pid = td->td_proc->p_pid; 417 tp->tap_flags |= TAP_OPEN; 418 419 TAPDEBUG("%s%d is open. minor = %#x\n", 420 tp->tap_if.if_name, unit, minor(dev)); 421 422 return (0); 423} /* tapopen */ 424 425 426/* 427 * tapclose 428 * 429 * close the device - mark i/f down & delete routing info 430 */ 431static int 432tapclose(dev, foo, bar, td) 433 dev_t dev; 434 int foo; 435 int bar; 436 struct thread *td; 437{ 438 int s, error; 439 struct tap_softc *tp = dev->si_drv1; 440 struct ifnet *ifp = &tp->tap_if; 441 442 KASSERT((tp->tap_unit != NULL), 443 ("%s%d is not open", ifp->if_name, ifp->if_unit)); 444 445 /* junk all pending output */ 446 IF_DRAIN(&ifp->if_snd); 447 448 /* 449 * do not bring the interface down, and do not anything with 450 * interface, if we are in VMnet mode. just close the device. 451 */ 452 453 if (((tp->tap_flags & TAP_VMNET) == 0) && (ifp->if_flags & IFF_UP)) { 454 s = splimp(); 455 if_down(ifp); 456 if (ifp->if_flags & IFF_RUNNING) { 457 /* find internet addresses and delete routes */ 458 struct ifaddr *ifa = NULL; 459 460 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 461 if (ifa->ifa_addr->sa_family == AF_INET) { 462 rtinit(ifa, (int)RTM_DELETE, 0); 463 464 /* remove address from interface */ 465 bzero(ifa->ifa_addr, 466 sizeof(*(ifa->ifa_addr))); 467 bzero(ifa->ifa_dstaddr, 468 sizeof(*(ifa->ifa_dstaddr))); 469 bzero(ifa->ifa_netmask, 470 sizeof(*(ifa->ifa_netmask))); 471 } 472 } 473 474 ifp->if_flags &= ~IFF_RUNNING; 475 } 476 splx(s); 477 } 478 479 funsetown(&tp->tap_sigio); 480 selwakeup(&tp->tap_rsel); 481 482 tp->tap_flags &= ~TAP_OPEN; 483 tp->tap_pid = 0; 484 error = rman_release_resource(tp->tap_unit); 485 KASSERT((error == 0), 486 ("%s%d could not release unit", ifp->if_name, ifp->if_unit)); 487 tp->tap_unit = NULL; 488 489 TAPDEBUG("%s%d is closed. minor = %#x\n", 490 ifp->if_name, ifp->if_unit, minor(dev)); 491 492 return (0); 493} /* tapclose */ 494 495 496/* 497 * tapifinit 498 * 499 * network interface initialization function 500 */ 501static void 502tapifinit(xtp) 503 void *xtp; 504{ 505 struct tap_softc *tp = (struct tap_softc *)xtp; 506 struct ifnet *ifp = &tp->tap_if; 507 508 TAPDEBUG("initializing %s%d\n", ifp->if_name, ifp->if_unit); 509 510 ifp->if_flags |= IFF_RUNNING; 511 ifp->if_flags &= ~IFF_OACTIVE; 512 513 /* attempt to start output */ 514 tapifstart(ifp); 515} /* tapifinit */ 516 517 518/* 519 * tapifioctl 520 * 521 * Process an ioctl request on network interface 522 */ 523static int 524tapifioctl(ifp, cmd, data) 525 struct ifnet *ifp; 526 u_long cmd; 527 caddr_t data; 528{ 529 struct tap_softc *tp = (struct tap_softc *)(ifp->if_softc); 530 struct ifstat *ifs = NULL; 531 int s, dummy; 532 533 switch (cmd) { 534 case SIOCSIFFLAGS: /* XXX -- just like vmnet does */ 535 case SIOCADDMULTI: 536 case SIOCDELMULTI: 537 break; 538 539 case SIOCGIFSTATUS: 540 s = splimp(); 541 ifs = (struct ifstat *)data; 542 dummy = strlen(ifs->ascii); 543 if (tp->tap_pid != 0 && dummy < sizeof(ifs->ascii)) 544 snprintf(ifs->ascii + dummy, 545 sizeof(ifs->ascii) - dummy, 546 "\tOpened by PID %d\n", tp->tap_pid); 547 splx(s); 548 break; 549 550 default: 551 s = splimp(); 552 dummy = ether_ioctl(ifp, cmd, data); 553 splx(s); 554 return (dummy); 555 } 556 557 return (0); 558} /* tapifioctl */ 559 560 561/* 562 * tapifstart 563 * 564 * queue packets from higher level ready to put out 565 */ 566static void 567tapifstart(ifp) 568 struct ifnet *ifp; 569{ 570 struct tap_softc *tp = ifp->if_softc; 571 int s; 572 573 TAPDEBUG("%s%d starting\n", ifp->if_name, ifp->if_unit); 574 575 /* 576 * do not junk pending output if we are in VMnet mode. 577 * XXX: can this do any harm because of queue overflow? 578 */ 579 580 if (((tp->tap_flags & TAP_VMNET) == 0) && 581 ((tp->tap_flags & TAP_READY) != TAP_READY)) { 582 struct mbuf *m = NULL; 583 584 TAPDEBUG("%s%d not ready, tap_flags = 0x%x\n", ifp->if_name, 585 ifp->if_unit, tp->tap_flags); 586 587 s = splimp(); 588 do { 589 IF_DEQUEUE(&ifp->if_snd, m); 590 if (m != NULL) 591 m_freem(m); 592 ifp->if_oerrors ++; 593 } while (m != NULL); 594 splx(s); 595 596 return; 597 } 598 599 s = splimp(); 600 ifp->if_flags |= IFF_OACTIVE; 601 602 if (ifp->if_snd.ifq_len != 0) { 603 if (tp->tap_flags & TAP_RWAIT) { 604 tp->tap_flags &= ~TAP_RWAIT; 605 wakeup(tp); 606 } 607 608 if ((tp->tap_flags & TAP_ASYNC) && (tp->tap_sigio != NULL)) 609 pgsigio(&tp->tap_sigio, SIGIO, 0); 610 611 selwakeup(&tp->tap_rsel); 612 ifp->if_opackets ++; /* obytes are counted in ether_output */ 613 } 614 615 ifp->if_flags &= ~IFF_OACTIVE; 616 splx(s); 617} /* tapifstart */ 618 619 620/* 621 * tapioctl 622 * 623 * the cdevsw interface is now pretty minimal 624 */ 625static int 626tapioctl(dev, cmd, data, flag, td) 627 dev_t dev; 628 u_long cmd; 629 caddr_t data; 630 int flag; 631 struct thread *td; 632{ 633 struct tap_softc *tp = dev->si_drv1; 634 struct ifnet *ifp = &tp->tap_if; 635 struct tapinfo *tapp = NULL; 636 int s; 637 int f; 638 639 switch (cmd) { 640 case TAPSIFINFO: 641 s = splimp(); 642 tapp = (struct tapinfo *)data; 643 ifp->if_mtu = tapp->mtu; 644 ifp->if_type = tapp->type; 645 ifp->if_baudrate = tapp->baudrate; 646 splx(s); 647 break; 648 649 case TAPGIFINFO: 650 tapp = (struct tapinfo *)data; 651 tapp->mtu = ifp->if_mtu; 652 tapp->type = ifp->if_type; 653 tapp->baudrate = ifp->if_baudrate; 654 break; 655 656 case TAPSDEBUG: 657 tapdebug = *(int *)data; 658 break; 659 660 case TAPGDEBUG: 661 *(int *)data = tapdebug; 662 break; 663 664 case FIONBIO: 665 break; 666 667 case FIOASYNC: 668 s = splimp(); 669 if (*(int *)data) 670 tp->tap_flags |= TAP_ASYNC; 671 else 672 tp->tap_flags &= ~TAP_ASYNC; 673 splx(s); 674 break; 675 676 case FIONREAD: 677 s = splimp(); 678 if (ifp->if_snd.ifq_head) { 679 struct mbuf *mb = ifp->if_snd.ifq_head; 680 681 for(*(int *)data = 0;mb != NULL;mb = mb->m_next) 682 *(int *)data += mb->m_len; 683 } else 684 *(int *)data = 0; 685 splx(s); 686 break; 687 688 case FIOSETOWN: 689 return (fsetown(*(int *)data, &tp->tap_sigio)); 690 691 case FIOGETOWN: 692 *(int *)data = fgetown(&tp->tap_sigio); 693 return (0); 694 695 /* this is deprecated, FIOSETOWN should be used instead */ 696 case TIOCSPGRP: 697 return (fsetown(-(*(int *)data), &tp->tap_sigio)); 698 699 /* this is deprecated, FIOGETOWN should be used instead */ 700 case TIOCGPGRP: 701 *(int *)data = -fgetown(&tp->tap_sigio); 702 return (0); 703 704 /* VMware/VMnet port ioctl's */ 705 706 case SIOCGIFFLAGS: /* get ifnet flags */ 707 bcopy(&ifp->if_flags, data, sizeof(ifp->if_flags)); 708 break; 709 710 case VMIO_SIOCSIFFLAGS: /* VMware/VMnet SIOCSIFFLAGS */ 711 f = *(int *)data; 712 f &= 0x0fff; 713 f &= ~IFF_CANTCHANGE; 714 f |= IFF_UP; 715 716 s = splimp(); 717 ifp->if_flags = f | (ifp->if_flags & IFF_CANTCHANGE); 718 splx(s); 719 break; 720 721 case OSIOCGIFADDR: /* get MAC address of the remote side */ 722 case SIOCGIFADDR: 723 bcopy(tp->ether_addr, data, sizeof(tp->ether_addr)); 724 break; 725 726 case SIOCSIFADDR: /* set MAC address of the remote side */ 727 bcopy(data, tp->ether_addr, sizeof(tp->ether_addr)); 728 break; 729 730 default: 731 return (ENOTTY); 732 } 733 return (0); 734} /* tapioctl */ 735 736 737/* 738 * tapread 739 * 740 * the cdevsw read interface - reads a packet at a time, or at 741 * least as much of a packet as can be read 742 */ 743static int 744tapread(dev, uio, flag) 745 dev_t dev; 746 struct uio *uio; 747 int flag; 748{ 749 struct tap_softc *tp = dev->si_drv1; 750 struct ifnet *ifp = &tp->tap_if; 751 struct mbuf *m = NULL; 752 int error = 0, len, s; 753 754 TAPDEBUG("%s%d reading, minor = %#x\n", 755 ifp->if_name, ifp->if_unit, minor(dev)); 756 757 if ((tp->tap_flags & TAP_READY) != TAP_READY) { 758 TAPDEBUG("%s%d not ready. minor = %#x, tap_flags = 0x%x\n", 759 ifp->if_name, ifp->if_unit, minor(dev), tp->tap_flags); 760 761 return (EHOSTDOWN); 762 } 763 764 tp->tap_flags &= ~TAP_RWAIT; 765 766 /* sleep until we get a packet */ 767 do { 768 s = splimp(); 769 IF_DEQUEUE(&ifp->if_snd, m); 770 splx(s); 771 772 if (m == NULL) { 773 if (flag & IO_NDELAY) 774 return (EWOULDBLOCK); 775 776 tp->tap_flags |= TAP_RWAIT; 777 error = tsleep(tp,PCATCH|(PZERO+1),"taprd",0); 778 if (error) 779 return (error); 780 } 781 } while (m == NULL); 782 783 /* feed packet to bpf */ 784 BPF_MTAP(ifp, m); 785 786 /* xfer packet to user space */ 787 while ((m != NULL) && (uio->uio_resid > 0) && (error == 0)) { 788 len = min(uio->uio_resid, m->m_len); 789 if (len == 0) 790 break; 791 792 error = uiomove(mtod(m, void *), len, uio); 793 m = m_free(m); 794 } 795 796 if (m != NULL) { 797 TAPDEBUG("%s%d dropping mbuf, minor = %#x\n", ifp->if_name, 798 ifp->if_unit, minor(dev)); 799 m_freem(m); 800 } 801 802 return (error); 803} /* tapread */ 804 805 806/* 807 * tapwrite 808 * 809 * the cdevsw write interface - an atomic write is a packet - or else! 810 */ 811static int 812tapwrite(dev, uio, flag) 813 dev_t dev; 814 struct uio *uio; 815 int flag; 816{ 817 struct tap_softc *tp = dev->si_drv1; 818 struct ifnet *ifp = &tp->tap_if; 819 struct mbuf *top = NULL, **mp = NULL, *m = NULL; 820 int error = 0, tlen, mlen; 821 822 TAPDEBUG("%s%d writting, minor = %#x\n", 823 ifp->if_name, ifp->if_unit, minor(dev)); 824 825 if (uio->uio_resid == 0) 826 return (0); 827 828 if ((uio->uio_resid < 0) || (uio->uio_resid > TAPMRU)) { 829 TAPDEBUG("%s%d invalid packet len = %d, minor = %#x\n", 830 ifp->if_name, ifp->if_unit, uio->uio_resid, minor(dev)); 831 832 return (EIO); 833 } 834 tlen = uio->uio_resid; 835 836 /* get a header mbuf */ 837 MGETHDR(m, M_DONTWAIT, MT_DATA); 838 if (m == NULL) 839 return (ENOBUFS); 840 mlen = MHLEN; 841 842 top = 0; 843 mp = ⊤ 844 while ((error == 0) && (uio->uio_resid > 0)) { 845 m->m_len = min(mlen, uio->uio_resid); 846 error = uiomove(mtod(m, void *), m->m_len, uio); 847 *mp = m; 848 mp = &m->m_next; 849 if (uio->uio_resid > 0) { 850 MGET(m, M_DONTWAIT, MT_DATA); 851 if (m == NULL) { 852 error = ENOBUFS; 853 break; 854 } 855 mlen = MLEN; 856 } 857 } 858 if (error) { 859 ifp->if_ierrors ++; 860 if (top) 861 m_freem(top); 862 return (error); 863 } 864 865 top->m_pkthdr.len = tlen; 866 top->m_pkthdr.rcvif = ifp; 867 868 /* Pass packet up to parent. */ 869 (*ifp->if_input)(ifp, top); 870 ifp->if_ipackets ++; /* ibytes are counted in parent */ 871 872 return (0); 873} /* tapwrite */ 874 875 876/* 877 * tappoll 878 * 879 * the poll interface, this is only useful on reads 880 * really. the write detect always returns true, write never blocks 881 * anyway, it either accepts the packet or drops it 882 */ 883static int 884tappoll(dev, events, td) 885 dev_t dev; 886 int events; 887 struct thread *td; 888{ 889 struct tap_softc *tp = dev->si_drv1; 890 struct ifnet *ifp = &tp->tap_if; 891 int s, revents = 0; 892 893 TAPDEBUG("%s%d polling, minor = %#x\n", 894 ifp->if_name, ifp->if_unit, minor(dev)); 895 896 s = splimp(); 897 if (events & (POLLIN | POLLRDNORM)) { 898 if (ifp->if_snd.ifq_len > 0) { 899 TAPDEBUG("%s%d have data in queue. len = %d, " \ 900 "minor = %#x\n", ifp->if_name, ifp->if_unit, 901 ifp->if_snd.ifq_len, minor(dev)); 902 903 revents |= (events & (POLLIN | POLLRDNORM)); 904 } else { 905 TAPDEBUG("%s%d waiting for data, minor = %#x\n", 906 ifp->if_name, ifp->if_unit, minor(dev)); 907 908 selrecord(td, &tp->tap_rsel); 909 } 910 } 911 912 if (events & (POLLOUT | POLLWRNORM)) 913 revents |= (events & (POLLOUT | POLLWRNORM)); 914 915 splx(s); 916 return (revents); 917} /* tappoll */
|