1 /* 2 * Copyright (C) 1999-2000 by Maksim Yevmenkin <m_evmenkin@yahoo.com> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * BASED ON: 27 * ------------------------------------------------------------------------- 28 * 29 * Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk> 30 * Nottingham University 1987. 31 */ 32 33 /* 34 * $FreeBSD: src/sys/net/if_tap.c,v 1.3.2.3 2002/04/14 21:41:48 luigi Exp $ 35 * $Id: if_tap.c,v 0.21 2000/07/23 21:46:02 max Exp $ 36 */ 37 38 #include "opt_inet.h" 39 #include "use_tap.h" 40 41 #include <sys/param.h> 42 #include <sys/conf.h> 43 #include <sys/device.h> 44 #include <sys/filedesc.h> 45 #include <sys/filio.h> 46 #include <sys/kernel.h> 47 #include <sys/malloc.h> 48 #include <sys/mbuf.h> 49 #include <sys/proc.h> 50 #include <sys/priv.h> 51 #include <sys/signalvar.h> 52 #include <sys/socket.h> 53 #include <sys/sockio.h> 54 #include <sys/sysctl.h> 55 #include <sys/systm.h> 56 #include <sys/ttycom.h> 57 #include <sys/uio.h> 58 #include <sys/vnode.h> 59 #include <sys/serialize.h> 60 61 #include <sys/thread2.h> 62 #include <sys/mplock2.h> 63 64 #include <net/bpf.h> 65 #include <net/ethernet.h> 66 #include <net/if.h> 67 #include <net/ifq_var.h> 68 #include <net/if_arp.h> 69 #include <net/if_clone.h> 70 #include <net/if_media.h> 71 #include <net/route.h> 72 #include <sys/devfs.h> 73 74 #include <netinet/in.h> 75 76 #include "if_tapvar.h" 77 #include "if_tap.h" 78 79 #define TAP_IFFLAGS (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST) 80 81 #if NTAP <= 1 82 #define TAP_PREALLOCATED_UNITS 4 83 #else 84 #define TAP_PREALLOCATED_UNITS NTAP 85 #endif 86 87 #define CDEV_NAME "tap" 88 #define TAPDEBUG if (tapdebug) if_printf 89 90 #define TAP "tap" 91 #define VMNET "vmnet" 92 #define VMNET_DEV_MASK 0x00010000 93 94 DEVFS_DECLARE_CLONE_BITMAP(tap); 95 96 /* module */ 97 static int tapmodevent (module_t, int, void *); 98 99 /* device */ 100 static struct tap_softc *tapcreate(int, cdev_t); 101 static void tapdestroy(struct tap_softc *); 102 103 /* clone */ 104 static int tap_clone_create(struct if_clone *, int, caddr_t); 105 static int tap_clone_destroy(struct ifnet *); 106 107 108 /* network interface */ 109 static void tapifstart (struct ifnet *); 110 static int tapifioctl (struct ifnet *, u_long, caddr_t, 111 struct ucred *); 112 static void tapifinit (void *); 113 static void tapifstop(struct tap_softc *, int); 114 static void tapifflags(struct tap_softc *); 115 116 117 /* character device */ 118 static d_open_t tapopen; 119 static d_clone_t tapclone; 120 static d_close_t tapclose; 121 static d_read_t tapread; 122 static d_write_t tapwrite; 123 static d_ioctl_t tapioctl; 124 static d_kqfilter_t tapkqfilter; 125 126 static struct dev_ops tap_ops = { 127 { CDEV_NAME, 0, 0 }, 128 .d_open = tapopen, 129 .d_close = tapclose, 130 .d_read = tapread, 131 .d_write = tapwrite, 132 .d_ioctl = tapioctl, 133 .d_kqfilter = tapkqfilter 134 }; 135 136 static int taprefcnt = 0; /* module ref. counter */ 137 static int taplastunit = -1; /* max. open unit number */ 138 static int tapdebug = 0; /* debug flag */ 139 static int tapuopen = 0; /* all user open() */ 140 static int tapuponopen = 0; /* IFF_UP */ 141 142 MALLOC_DECLARE(M_TAP); 143 MALLOC_DEFINE(M_TAP, CDEV_NAME, "Ethernet tunnel interface"); 144 struct if_clone tap_cloner = IF_CLONE_INITIALIZER("tap", 145 tap_clone_create, tap_clone_destroy, 146 0, IF_MAXUNIT); 147 static SLIST_HEAD(,tap_softc) tap_listhead = 148 SLIST_HEAD_INITIALIZER(&tap_listhead); 149 150 SYSCTL_INT(_debug, OID_AUTO, if_tap_debug, CTLFLAG_RW, &tapdebug, 0, ""); 151 SYSCTL_DECL(_net_link); 152 SYSCTL_NODE(_net_link, OID_AUTO, tap, CTLFLAG_RW, 0, 153 "Ethernet tunnel software network interface"); 154 SYSCTL_INT(_net_link_tap, OID_AUTO, user_open, CTLFLAG_RW, &tapuopen, 0, 155 "Allow user to open /dev/tap (based on node permissions)"); 156 SYSCTL_INT(_net_link_tap, OID_AUTO, up_on_open, CTLFLAG_RW, &tapuponopen, 0, 157 "Bring interface up when /dev/tap is opened"); 158 SYSCTL_INT(_net_link_tap, OID_AUTO, debug, CTLFLAG_RW, &tapdebug, 0, ""); 159 160 DEV_MODULE(if_tap, tapmodevent, NULL); 161 162 /* 163 * tapmodevent 164 * 165 * module event handler 166 */ 167 static int 168 tapmodevent(module_t mod, int type, void *data) 169 { 170 static int attached = 0; 171 struct tap_softc *tp, *ntp; 172 int i; 173 174 switch (type) { 175 case MOD_LOAD: 176 if (attached) 177 return (EEXIST); 178 179 make_autoclone_dev(&tap_ops, &DEVFS_CLONE_BITMAP(tap), tapclone, 180 UID_ROOT, GID_WHEEL, 0600, "tap"); 181 SLIST_INIT(&tap_listhead); 182 if_clone_attach(&tap_cloner); 183 184 for (i = 0; i < TAP_PREALLOCATED_UNITS; ++i) { 185 make_dev(&tap_ops, i, UID_ROOT, GID_WHEEL, 186 0600, "tap%d", i); 187 devfs_clone_bitmap_set(&DEVFS_CLONE_BITMAP(tap), i); 188 } 189 190 attached = 1; 191 break; 192 193 case MOD_UNLOAD: 194 if (taprefcnt > 0) 195 return (EBUSY); 196 197 if_clone_detach(&tap_cloner); 198 199 /* Maintain tap ifs in a local list */ 200 SLIST_FOREACH_MUTABLE(tp, &tap_listhead, tap_link, ntp) 201 tapdestroy(tp); 202 203 attached = 0; 204 205 devfs_clone_handler_del("tap"); 206 dev_ops_remove_all(&tap_ops); 207 devfs_clone_bitmap_uninit(&DEVFS_CLONE_BITMAP(tap)); 208 break; 209 210 default: 211 return (EOPNOTSUPP); 212 } 213 214 return (0); 215 } /* tapmodevent */ 216 217 218 /* 219 * tapcreate - create or clone an interface 220 */ 221 static struct tap_softc * 222 tapcreate(int unit, cdev_t dev) 223 { 224 const char *name = TAP; 225 struct ifnet *ifp; 226 struct tap_softc *tp; 227 uint8_t ether_addr[ETHER_ADDR_LEN]; 228 229 tp = kmalloc(sizeof(*tp), M_TAP, M_WAITOK | M_ZERO); 230 dev->si_drv1 = tp; 231 tp->tap_dev = dev; 232 tp->tap_unit = unit; 233 234 reference_dev(dev); /* tp association */ 235 236 /* generate fake MAC address: 00 bd xx xx xx unit_no */ 237 ether_addr[0] = 0x00; 238 ether_addr[1] = 0xbd; 239 bcopy(&ticks, ðer_addr[2], 3); 240 ether_addr[5] = (u_char)unit; 241 242 /* fill the rest and attach interface */ 243 ifp = &tp->tap_if; 244 ifp->if_softc = tp; 245 246 if_initname(ifp, name, unit); 247 if (unit > taplastunit) 248 taplastunit = unit; 249 250 ifp->if_init = tapifinit; 251 ifp->if_start = tapifstart; 252 ifp->if_ioctl = tapifioctl; 253 ifp->if_mtu = ETHERMTU; 254 ifp->if_flags = TAP_IFFLAGS; 255 ifq_set_maxlen(&ifp->if_snd, ifqmaxlen); 256 ifq_set_ready(&ifp->if_snd); 257 258 ether_ifattach(ifp, ether_addr, NULL); 259 260 tp->tap_flags |= TAP_INITED; 261 tp->tap_devq.ifq_maxlen = ifqmaxlen; 262 263 SLIST_INSERT_HEAD(&tap_listhead, tp, tap_link); 264 265 TAPDEBUG(ifp, "created. minor = %#x\n", minor(dev)); 266 return (tp); 267 } 268 269 static 270 struct tap_softc * 271 tapfind(int unit) 272 { 273 struct tap_softc *tp; 274 275 SLIST_FOREACH(tp, &tap_listhead, tap_link) { 276 if (tp->tap_unit == unit) 277 return(tp); 278 } 279 return (NULL); 280 } 281 282 /* 283 * tap_clone_create: 284 * 285 * Create a new tap instance via ifconfig. 286 */ 287 static int 288 tap_clone_create(struct if_clone *ifc __unused, int unit, 289 caddr_t param __unused) 290 { 291 struct tap_softc *tp; 292 cdev_t dev; 293 294 tp = tapfind(unit); 295 if (tp == NULL) { 296 if (!devfs_clone_bitmap_chk(&DEVFS_CLONE_BITMAP(tap), unit)) { 297 devfs_clone_bitmap_set(&DEVFS_CLONE_BITMAP(tap), unit); 298 dev = make_dev(&tap_ops, unit, UID_ROOT, GID_WHEEL, 299 0600, "%s%d", TAP, unit); 300 } else { 301 dev = devfs_find_device_by_name("%s%d", TAP, unit); 302 } 303 304 KKASSERT(dev != NULL); 305 tp = tapcreate(unit, dev); 306 } 307 tp->tap_flags |= TAP_CLONE; 308 TAPDEBUG(&tp->tap_if, "clone created. minor = %#x tap_flags = 0x%x\n", 309 minor(tp->tap_dev), tp->tap_flags); 310 311 return (0); 312 } 313 314 /* 315 * tapopen 316 * 317 * to open tunnel. must be superuser 318 */ 319 static int 320 tapopen(struct dev_open_args *ap) 321 { 322 cdev_t dev = NULL; 323 struct tap_softc *tp = NULL; 324 struct ifnet *ifp = NULL; 325 int error; 326 327 if (tapuopen == 0 && 328 (error = priv_check_cred(ap->a_cred, PRIV_ROOT, 0)) != 0) 329 return (error); 330 331 get_mplock(); 332 dev = ap->a_head.a_dev; 333 tp = dev->si_drv1; 334 if (tp == NULL) 335 tp = tapcreate(minor(dev), dev); 336 if (tp->tap_flags & TAP_OPEN) { 337 rel_mplock(); 338 return (EBUSY); 339 } 340 ifp = &tp->arpcom.ac_if; 341 342 if ((tp->tap_flags & TAP_CLONE) == 0) { 343 EVENTHANDLER_INVOKE(ifnet_attach_event, ifp); 344 345 /* Announce the return of the interface. */ 346 rt_ifannouncemsg(ifp, IFAN_ARRIVAL); 347 } 348 349 bcopy(tp->arpcom.ac_enaddr, tp->ether_addr, sizeof(tp->ether_addr)); 350 351 if (curthread->td_proc) 352 fsetown(curthread->td_proc->p_pid, &tp->tap_sigtd); 353 tp->tap_flags |= TAP_OPEN; 354 taprefcnt ++; 355 356 if (tapuponopen && (ifp->if_flags & IFF_UP) == 0) { 357 crit_enter(); 358 if_up(ifp); 359 crit_exit(); 360 361 ifnet_serialize_all(ifp); 362 tapifflags(tp); 363 ifnet_deserialize_all(ifp); 364 365 tp->tap_flags |= TAP_CLOSEDOWN; 366 } 367 368 TAPDEBUG(ifp, "opened. minor = %#x, refcnt = %d, taplastunit = %d\n", 369 minor(tp->tap_dev), taprefcnt, taplastunit); 370 371 rel_mplock(); 372 return (0); 373 } 374 375 static int 376 tapclone(struct dev_clone_args *ap) 377 { 378 int unit; 379 380 unit = devfs_clone_bitmap_get(&DEVFS_CLONE_BITMAP(tap), 0); 381 ap->a_dev = make_only_dev(&tap_ops, unit, UID_ROOT, GID_WHEEL, 382 0600, "%s%d", TAP, unit); 383 tapcreate(unit, ap->a_dev); 384 return (0); 385 } 386 387 /* 388 * tapclose 389 * 390 * close the device - mark i/f down & delete routing info 391 */ 392 static int 393 tapclose(struct dev_close_args *ap) 394 { 395 cdev_t dev = ap->a_head.a_dev; 396 struct tap_softc *tp = dev->si_drv1; 397 struct ifnet *ifp = &tp->tap_if; 398 int clear_flags = 0; 399 400 get_mplock(); 401 402 /* Junk all pending output */ 403 ifq_purge(&ifp->if_snd); 404 405 /* 406 * Do not bring the interface down, and do not anything with 407 * interface, if we are in VMnet mode. just close the device. 408 * 409 * If the interface is not cloned, we always bring it down. 410 * 411 * If the interface is cloned, then we bring it down during 412 * closing only if it was brought up during opening. 413 */ 414 if ((tp->tap_flags & TAP_VMNET) == 0 && 415 ((tp->tap_flags & TAP_CLONE) == 0 || 416 (tp->tap_flags & TAP_CLOSEDOWN))) { 417 if (ifp->if_flags & IFF_UP) 418 if_down(ifp); 419 clear_flags = 1; 420 } 421 ifnet_serialize_all(ifp); 422 tapifstop(tp, clear_flags); 423 ifnet_deserialize_all(ifp); 424 425 if ((tp->tap_flags & TAP_CLONE) == 0) { 426 if_purgeaddrs_nolink(ifp); 427 428 EVENTHANDLER_INVOKE(ifnet_detach_event, ifp); 429 430 /* Announce the departure of the interface. */ 431 rt_ifannouncemsg(ifp, IFAN_DEPARTURE); 432 } 433 434 funsetown(&tp->tap_sigio); 435 tp->tap_sigio = NULL; 436 KNOTE(&tp->tap_rkq.ki_note, 0); 437 438 tp->tap_flags &= ~TAP_OPEN; 439 funsetown(&tp->tap_sigtd); 440 tp->tap_sigtd = NULL; 441 442 taprefcnt --; 443 if (taprefcnt < 0) { 444 taprefcnt = 0; 445 if_printf(ifp, "minor = %#x, refcnt = %d is out of sync. " 446 "set refcnt to 0\n", minor(tp->tap_dev), taprefcnt); 447 } 448 449 TAPDEBUG(ifp, "closed. minor = %#x, refcnt = %d, taplastunit = %d\n", 450 minor(tp->tap_dev), taprefcnt, taplastunit); 451 452 if (tp->tap_unit >= TAP_PREALLOCATED_UNITS) 453 tapdestroy(tp); 454 455 rel_mplock(); 456 return (0); 457 } 458 459 /* 460 * tapdestroy: 461 * 462 * Destroy a tap instance. 463 */ 464 static void 465 tapdestroy(struct tap_softc *tp) 466 { 467 struct ifnet *ifp = &tp->arpcom.ac_if; 468 cdev_t dev; 469 470 TAPDEBUG(ifp, "destroyed. minor = %#x, refcnt = %d, taplastunit = %d\n", 471 minor(tp->tap_dev), taprefcnt, taplastunit); 472 473 ifnet_serialize_all(ifp); 474 tapifstop(tp, 1); 475 ifnet_deserialize_all(ifp); 476 477 ether_ifdetach(ifp); 478 SLIST_REMOVE(&tap_listhead, tp, tap_softc, tap_link); 479 480 dev = tp->tap_dev; 481 tp->tap_dev = NULL; 482 dev->si_drv1 = NULL; 483 484 release_dev(dev); /* tp association */ 485 486 /* 487 * Also destroy the cloned device 488 */ 489 if (tp->tap_unit >= TAP_PREALLOCATED_UNITS) { 490 destroy_dev(dev); 491 devfs_clone_bitmap_put(&DEVFS_CLONE_BITMAP(tap), tp->tap_unit); 492 } 493 494 kfree(tp, M_TAP); 495 496 taplastunit--; 497 } 498 499 /* 500 * tap_clone_destroy: 501 * 502 * Destroy a tap instance. 503 */ 504 static int 505 tap_clone_destroy(struct ifnet *ifp) 506 { 507 struct tap_softc *tp = ifp->if_softc; 508 509 if ((tp->tap_flags & TAP_CLONE) == 0) 510 return ENXIO; 511 512 TAPDEBUG(&tp->tap_if, "clone destroyed. minor = %#x tap_flags = 0x%x\n", 513 minor(tp->tap_dev), tp->tap_flags); 514 tapdestroy(tp); 515 516 return 0; 517 } 518 519 /* 520 * tapifinit 521 * 522 * Network interface initialization function (called with if serializer held) 523 * 524 * MPSAFE 525 */ 526 static void 527 tapifinit(void *xtp) 528 { 529 struct tap_softc *tp = xtp; 530 struct ifnet *ifp = &tp->tap_if; 531 532 TAPDEBUG(ifp, "initializing, minor = %#x tap_flags = 0x%x\n", 533 minor(tp->tap_dev), tp->tap_flags); 534 535 ASSERT_IFNET_SERIALIZED_ALL(ifp); 536 537 tapifstop(tp, 1); 538 539 ifp->if_flags |= IFF_RUNNING; 540 ifp->if_flags &= ~IFF_OACTIVE; 541 542 /* attempt to start output */ 543 tapifstart(ifp); 544 } 545 546 547 /* 548 * tapifioctl 549 * 550 * Process an ioctl request on network interface (called with if serializer 551 * held). 552 * 553 * MPSAFE 554 */ 555 static int 556 tapifioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr) 557 { 558 struct tap_softc *tp = (struct tap_softc *)(ifp->if_softc); 559 struct ifstat *ifs = NULL; 560 struct ifmediareq *ifmr = NULL; 561 int error = 0; 562 int dummy; 563 564 switch (cmd) { 565 case SIOCSIFADDR: 566 case SIOCGIFADDR: 567 case SIOCSIFMTU: 568 error = ether_ioctl(ifp, cmd, data); 569 break; 570 571 case SIOCSIFFLAGS: 572 tapifflags(tp); 573 break; 574 575 case SIOCADDMULTI: /* XXX -- just like vmnet does */ 576 case SIOCDELMULTI: 577 break; 578 579 case SIOCGIFMEDIA: 580 /* 581 * The bridge code needs this when running the 582 * spanning tree protocol. 583 */ 584 ifmr = (struct ifmediareq *)data; 585 dummy = ifmr->ifm_count; 586 ifmr->ifm_count = 1; 587 ifmr->ifm_status = IFM_AVALID; 588 ifmr->ifm_active = IFM_ETHER; 589 if (tp->tap_flags & TAP_OPEN) 590 ifmr->ifm_status |= IFM_ACTIVE; 591 ifmr->ifm_current = ifmr->ifm_active; 592 if (dummy >= 1) { 593 int media = IFM_ETHER; 594 error = copyout(&media, 595 ifmr->ifm_ulist, 596 sizeof(int)); 597 } 598 break; 599 600 case SIOCGIFSTATUS: 601 ifs = (struct ifstat *)data; 602 dummy = strlen(ifs->ascii); 603 if ((tp->tap_flags & TAP_OPEN) && 604 dummy < sizeof(ifs->ascii)) { 605 if (tp->tap_sigtd && tp->tap_sigtd->sio_proc) { 606 ksnprintf(ifs->ascii + dummy, 607 sizeof(ifs->ascii) - dummy, 608 "\tOpened by pid %d\n", 609 (int)tp->tap_sigtd->sio_proc->p_pid); 610 } else { 611 ksnprintf(ifs->ascii + dummy, 612 sizeof(ifs->ascii) - dummy, 613 "\tOpened by <unknown>\n"); 614 } 615 } 616 break; 617 618 default: 619 error = EINVAL; 620 break; 621 } 622 623 return (error); 624 } 625 626 627 /* 628 * tapifstart 629 * 630 * Queue packets from higher level ready to put out (called with if serializer 631 * held) 632 * 633 * MPSAFE 634 */ 635 static void 636 tapifstart(struct ifnet *ifp) 637 { 638 struct tap_softc *tp = ifp->if_softc; 639 struct ifqueue *ifq; 640 struct mbuf *m; 641 int has_data = 0; 642 643 TAPDEBUG(ifp, "starting, minor = %#x\n", minor(tp->tap_dev)); 644 645 /* 646 * do not junk pending output if we are in VMnet mode. 647 * XXX: can this do any harm because of queue overflow? 648 */ 649 650 if (((tp->tap_flags & TAP_VMNET) == 0) && 651 ((tp->tap_flags & TAP_READY) != TAP_READY)) { 652 TAPDEBUG(ifp, "not ready. minor = %#x, tap_flags = 0x%x\n", 653 minor(tp->tap_dev), tp->tap_flags); 654 ifq_purge(&ifp->if_snd); 655 return; 656 } 657 658 ifp->if_flags |= IFF_OACTIVE; 659 660 ifq = &tp->tap_devq; 661 while ((m = ifq_dequeue(&ifp->if_snd, NULL)) != NULL) { 662 if (IF_QFULL(ifq)) { 663 IF_DROP(ifq); 664 ifp->if_oerrors++; 665 m_freem(m); 666 } else { 667 IF_ENQUEUE(ifq, m); 668 ifp->if_opackets++; 669 has_data = 1; 670 } 671 } 672 673 if (has_data) { 674 if (tp->tap_flags & TAP_RWAIT) { 675 tp->tap_flags &= ~TAP_RWAIT; 676 wakeup((caddr_t)tp); 677 } 678 679 KNOTE(&tp->tap_rkq.ki_note, 0); 680 681 if ((tp->tap_flags & TAP_ASYNC) && (tp->tap_sigio != NULL)) { 682 get_mplock(); 683 pgsigio(tp->tap_sigio, SIGIO, 0); 684 rel_mplock(); 685 } 686 } 687 688 ifp->if_flags &= ~IFF_OACTIVE; 689 } 690 691 692 /* 693 * tapioctl 694 * 695 * The ops interface is now pretty minimal. Called via fileops with nothing 696 * held. 697 * 698 * MPSAFE 699 */ 700 static int 701 tapioctl(struct dev_ioctl_args *ap) 702 { 703 cdev_t dev = ap->a_head.a_dev; 704 caddr_t data = ap->a_data; 705 struct tap_softc *tp = dev->si_drv1; 706 struct ifnet *ifp = &tp->tap_if; 707 struct tapinfo *tapp = NULL; 708 struct mbuf *mb; 709 short f; 710 int error; 711 712 ifnet_serialize_all(ifp); 713 error = 0; 714 715 switch (ap->a_cmd) { 716 case TAPSIFINFO: 717 tapp = (struct tapinfo *)data; 718 ifp->if_mtu = tapp->mtu; 719 ifp->if_type = tapp->type; 720 ifp->if_baudrate = tapp->baudrate; 721 break; 722 723 case TAPGIFINFO: 724 tapp = (struct tapinfo *)data; 725 tapp->mtu = ifp->if_mtu; 726 tapp->type = ifp->if_type; 727 tapp->baudrate = ifp->if_baudrate; 728 break; 729 730 case TAPSDEBUG: 731 tapdebug = *(int *)data; 732 break; 733 734 case TAPGDEBUG: 735 *(int *)data = tapdebug; 736 break; 737 738 case FIOASYNC: 739 if (*(int *)data) 740 tp->tap_flags |= TAP_ASYNC; 741 else 742 tp->tap_flags &= ~TAP_ASYNC; 743 break; 744 745 case FIONREAD: 746 *(int *)data = 0; 747 748 /* Take a look at devq first */ 749 IF_POLL(&tp->tap_devq, mb); 750 if (mb == NULL) 751 mb = ifq_poll(&ifp->if_snd); 752 753 if (mb != NULL) { 754 for(; mb != NULL; mb = mb->m_next) 755 *(int *)data += mb->m_len; 756 } 757 break; 758 759 case FIOSETOWN: 760 error = fsetown(*(int *)data, &tp->tap_sigio); 761 break; 762 763 case FIOGETOWN: 764 *(int *)data = fgetown(&tp->tap_sigio); 765 break; 766 767 /* this is deprecated, FIOSETOWN should be used instead */ 768 case TIOCSPGRP: 769 error = fsetown(-(*(int *)data), &tp->tap_sigio); 770 break; 771 772 /* this is deprecated, FIOGETOWN should be used instead */ 773 case TIOCGPGRP: 774 *(int *)data = -fgetown(&tp->tap_sigio); 775 break; 776 777 /* VMware/VMnet port ioctl's */ 778 779 case SIOCGIFFLAGS: /* get ifnet flags */ 780 bcopy(&ifp->if_flags, data, sizeof(ifp->if_flags)); 781 break; 782 783 case VMIO_SIOCSIFFLAGS: /* VMware/VMnet SIOCSIFFLAGS */ 784 f = *(short *)data; 785 f &= 0x0fff; 786 f &= ~IFF_CANTCHANGE; 787 f |= IFF_UP; 788 ifp->if_flags = f | (ifp->if_flags & IFF_CANTCHANGE); 789 break; 790 791 case OSIOCGIFADDR: /* get MAC address of the remote side */ 792 case SIOCGIFADDR: 793 bcopy(tp->ether_addr, data, sizeof(tp->ether_addr)); 794 break; 795 796 case SIOCSIFADDR: /* set MAC address of the remote side */ 797 bcopy(data, tp->ether_addr, sizeof(tp->ether_addr)); 798 break; 799 800 default: 801 error = ENOTTY; 802 break; 803 } 804 ifnet_deserialize_all(ifp); 805 return (error); 806 } 807 808 809 /* 810 * tapread 811 * 812 * The ops read interface - reads a packet at a time, or at 813 * least as much of a packet as can be read. 814 * 815 * Called from the fileops interface with nothing held. 816 * 817 * MPSAFE 818 */ 819 static int 820 tapread(struct dev_read_args *ap) 821 { 822 cdev_t dev = ap->a_head.a_dev; 823 struct uio *uio = ap->a_uio; 824 struct tap_softc *tp = dev->si_drv1; 825 struct ifnet *ifp = &tp->tap_if; 826 struct mbuf *m0 = NULL; 827 int error = 0, len; 828 829 TAPDEBUG(ifp, "reading, minor = %#x\n", minor(tp->tap_dev)); 830 831 if ((tp->tap_flags & TAP_READY) != TAP_READY) { 832 TAPDEBUG(ifp, "not ready. minor = %#x, tap_flags = 0x%x\n", 833 minor(tp->tap_dev), tp->tap_flags); 834 835 return (EHOSTDOWN); 836 } 837 838 tp->tap_flags &= ~TAP_RWAIT; 839 840 /* sleep until we get a packet */ 841 do { 842 ifnet_serialize_all(ifp); 843 IF_DEQUEUE(&tp->tap_devq, m0); 844 if (m0 == NULL) { 845 if (ap->a_ioflag & IO_NDELAY) { 846 ifnet_deserialize_all(ifp); 847 return (EWOULDBLOCK); 848 } 849 tp->tap_flags |= TAP_RWAIT; 850 tsleep_interlock(tp, PCATCH); 851 ifnet_deserialize_all(ifp); 852 error = tsleep(tp, PCATCH | PINTERLOCKED, "taprd", 0); 853 if (error) 854 return (error); 855 } else { 856 ifnet_deserialize_all(ifp); 857 } 858 } while (m0 == NULL); 859 860 BPF_MTAP(ifp, m0); 861 862 /* xfer packet to user space */ 863 while ((m0 != NULL) && (uio->uio_resid > 0) && (error == 0)) { 864 len = (int)szmin(uio->uio_resid, m0->m_len); 865 if (len == 0) 866 break; 867 868 error = uiomove(mtod(m0, caddr_t), (size_t)len, uio); 869 m0 = m_free(m0); 870 } 871 872 if (m0 != NULL) { 873 TAPDEBUG(ifp, "dropping mbuf, minor = %#x\n", 874 minor(tp->tap_dev)); 875 m_freem(m0); 876 } 877 878 return (error); 879 } 880 881 /* 882 * tapwrite 883 * 884 * The ops write interface - an atomic write is a packet - or else! 885 * 886 * Called from the fileops interface with nothing held. 887 * 888 * MPSAFE 889 */ 890 static int 891 tapwrite(struct dev_write_args *ap) 892 { 893 cdev_t dev = ap->a_head.a_dev; 894 struct uio *uio = ap->a_uio; 895 struct tap_softc *tp = dev->si_drv1; 896 struct ifnet *ifp = &tp->tap_if; 897 struct mbuf *top = NULL, **mp = NULL, *m = NULL; 898 int error; 899 size_t tlen, mlen; 900 901 TAPDEBUG(ifp, "writing, minor = %#x\n", minor(tp->tap_dev)); 902 903 if ((tp->tap_flags & TAP_READY) != TAP_READY) { 904 TAPDEBUG(ifp, "not ready. minor = %#x, tap_flags = 0x%x\n", 905 minor(tp->tap_dev), tp->tap_flags); 906 return (EHOSTDOWN); 907 } 908 909 if (uio->uio_resid == 0) 910 return (0); 911 912 if (uio->uio_resid > TAPMRU) { 913 TAPDEBUG(ifp, "invalid packet len = %zu, minor = %#x\n", 914 uio->uio_resid, minor(tp->tap_dev)); 915 916 return (EIO); 917 } 918 tlen = uio->uio_resid; 919 920 /* get a header mbuf */ 921 MGETHDR(m, MB_WAIT, MT_DATA); 922 if (m == NULL) 923 return (ENOBUFS); 924 mlen = MHLEN; 925 926 top = NULL; 927 mp = ⊤ 928 error = 0; 929 930 while (error == 0 && uio->uio_resid > 0) { 931 m->m_len = (int)szmin(mlen, uio->uio_resid); 932 error = uiomove(mtod(m, caddr_t), (size_t)m->m_len, uio); 933 *mp = m; 934 mp = &m->m_next; 935 if (uio->uio_resid > 0) { 936 MGET(m, MB_WAIT, MT_DATA); 937 if (m == NULL) { 938 error = ENOBUFS; 939 break; 940 } 941 mlen = MLEN; 942 } 943 } 944 if (error) { 945 ifp->if_ierrors ++; 946 if (top) 947 m_freem(top); 948 return (error); 949 } 950 951 top->m_pkthdr.len = (int)tlen; 952 top->m_pkthdr.rcvif = ifp; 953 954 /* 955 * Ethernet bridge and bpf are handled in ether_input 956 * 957 * adjust mbuf and give packet to the ether_input 958 */ 959 ifnet_serialize_all(ifp); 960 ifp->if_input(ifp, top); 961 ifp->if_ipackets ++; /* ibytes are counted in ether_input */ 962 ifnet_deserialize_all(ifp); 963 964 return (0); 965 } 966 967 /* 968 * tapkqfilter - called from the fileops interface with nothing held 969 * 970 * MPSAFE 971 */ 972 static int filt_tapread(struct knote *kn, long hint); 973 static int filt_tapwrite(struct knote *kn, long hint); 974 static void filt_tapdetach(struct knote *kn); 975 static struct filterops tapread_filtops = 976 { FILTEROP_ISFD, NULL, filt_tapdetach, filt_tapread }; 977 static struct filterops tapwrite_filtops = 978 { FILTEROP_ISFD, NULL, filt_tapdetach, filt_tapwrite }; 979 980 static int 981 tapkqfilter(struct dev_kqfilter_args *ap) 982 { 983 cdev_t dev = ap->a_head.a_dev; 984 struct knote *kn = ap->a_kn; 985 struct tap_softc *tp; 986 struct klist *list; 987 struct ifnet *ifp; 988 989 tp = dev->si_drv1; 990 list = &tp->tap_rkq.ki_note; 991 ifp = &tp->tap_if; 992 ap->a_result =0; 993 994 switch(kn->kn_filter) { 995 case EVFILT_READ: 996 kn->kn_fop = &tapread_filtops; 997 kn->kn_hook = (void *)tp; 998 break; 999 case EVFILT_WRITE: 1000 kn->kn_fop = &tapwrite_filtops; 1001 kn->kn_hook = (void *)tp; 1002 break; 1003 default: 1004 ap->a_result = EOPNOTSUPP; 1005 return(0); 1006 } 1007 1008 knote_insert(list, kn); 1009 return(0); 1010 } 1011 1012 static int 1013 filt_tapread(struct knote *kn, long hint) 1014 { 1015 struct tap_softc *tp = (void *)kn->kn_hook; 1016 1017 if (IF_QEMPTY(&tp->tap_devq) == 0) /* XXX serializer */ 1018 return(1); 1019 else 1020 return(0); 1021 } 1022 1023 static int 1024 filt_tapwrite(struct knote *kn, long hint) 1025 { 1026 /* Always ready for a write */ 1027 return (1); 1028 } 1029 1030 static void 1031 filt_tapdetach(struct knote *kn) 1032 { 1033 struct tap_softc *tp = (void *)kn->kn_hook; 1034 1035 knote_remove(&tp->tap_rkq.ki_note, kn); 1036 } 1037 1038 static void 1039 tapifstop(struct tap_softc *tp, int clear_flags) 1040 { 1041 struct ifnet *ifp = &tp->tap_if; 1042 1043 ASSERT_IFNET_SERIALIZED_ALL(ifp); 1044 IF_DRAIN(&tp->tap_devq); 1045 tp->tap_flags &= ~TAP_CLOSEDOWN; 1046 if (clear_flags) 1047 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 1048 } 1049 1050 static void 1051 tapifflags(struct tap_softc *tp) 1052 { 1053 struct ifnet *ifp = &tp->arpcom.ac_if; 1054 1055 ASSERT_IFNET_SERIALIZED_ALL(ifp); 1056 if ((tp->tap_flags & TAP_VMNET) == 0) { 1057 /* 1058 * Only for non-vmnet tap(4) 1059 */ 1060 if (ifp->if_flags & IFF_UP) { 1061 if ((ifp->if_flags & IFF_RUNNING) == 0) 1062 tapifinit(tp); 1063 } else { 1064 tapifstop(tp, 1); 1065 } 1066 } else { 1067 /* XXX */ 1068 } 1069 } 1070