if_tap.c revision 166497
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: head/sys/net/if_tap.c 166497 2007-02-04 16:32:46Z bms $ 35 * $Id: if_tap.c,v 0.21 2000/07/23 21:46:02 max Exp $ 36 */ 37 38#include "opt_compat.h" 39#include "opt_inet.h" 40 41#include <sys/param.h> 42#include <sys/conf.h> 43#include <sys/fcntl.h> 44#include <sys/filio.h> 45#include <sys/kernel.h> 46#include <sys/malloc.h> 47#include <sys/mbuf.h> 48#include <sys/module.h> 49#include <sys/poll.h> 50#include <sys/priv.h> 51#include <sys/proc.h> 52#include <sys/selinfo.h> 53#include <sys/signalvar.h> 54#include <sys/socket.h> 55#include <sys/sockio.h> 56#include <sys/sysctl.h> 57#include <sys/systm.h> 58#include <sys/ttycom.h> 59#include <sys/uio.h> 60#include <sys/queue.h> 61 62#include <net/bpf.h> 63#include <net/ethernet.h> 64#include <net/if.h> 65#include <net/if_clone.h> 66#include <net/if_dl.h> 67#include <net/route.h> 68#include <net/if_types.h> 69 70#include <netinet/in.h> 71 72#include <net/if_tapvar.h> 73#include <net/if_tap.h> 74 75 76#define CDEV_NAME "tap" 77#define TAPDEBUG if (tapdebug) printf 78 79#define TAP "tap" 80#define VMNET "vmnet" 81#define TAPMAXUNIT 0x7fff 82#define VMNET_DEV_MASK CLONE_FLAG0 83 84/* module */ 85static int tapmodevent(module_t, int, void *); 86 87/* device */ 88static void tapclone(void *, struct ucred *, char *, int, 89 struct cdev **); 90static void tapcreate(struct cdev *); 91 92/* network interface */ 93static void tapifstart(struct ifnet *); 94static int tapifioctl(struct ifnet *, u_long, caddr_t); 95static void tapifinit(void *); 96 97static int tap_clone_create(struct if_clone *, int, caddr_t); 98static void tap_clone_destroy(struct ifnet *); 99static int vmnet_clone_create(struct if_clone *, int, caddr_t); 100static void vmnet_clone_destroy(struct ifnet *); 101 102IFC_SIMPLE_DECLARE(tap, 0); 103IFC_SIMPLE_DECLARE(vmnet, 0); 104 105/* character device */ 106static d_open_t tapopen; 107static d_close_t tapclose; 108static d_read_t tapread; 109static d_write_t tapwrite; 110static d_ioctl_t tapioctl; 111static d_poll_t tappoll; 112static d_kqfilter_t tapkqfilter; 113 114/* kqueue(2) */ 115static int tapkqread(struct knote *, long); 116static int tapkqwrite(struct knote *, long); 117static void tapkqdetach(struct knote *); 118 119static struct filterops tap_read_filterops = { 120 .f_isfd = 1, 121 .f_attach = NULL, 122 .f_detach = tapkqdetach, 123 .f_event = tapkqread, 124}; 125 126static struct filterops tap_write_filterops = { 127 .f_isfd = 1, 128 .f_attach = NULL, 129 .f_detach = tapkqdetach, 130 .f_event = tapkqwrite, 131}; 132 133static struct cdevsw tap_cdevsw = { 134 .d_version = D_VERSION, 135 .d_flags = D_PSEUDO | D_NEEDGIANT, 136 .d_open = tapopen, 137 .d_close = tapclose, 138 .d_read = tapread, 139 .d_write = tapwrite, 140 .d_ioctl = tapioctl, 141 .d_poll = tappoll, 142 .d_name = CDEV_NAME, 143 .d_kqfilter = tapkqfilter, 144}; 145 146/* 147 * All global variables in if_tap.c are locked with tapmtx, with the 148 * exception of tapdebug, which is accessed unlocked; tapclones is 149 * static at runtime. 150 */ 151static struct mtx tapmtx; 152static int tapdebug = 0; /* debug flag */ 153static int tapuopen = 0; /* allow user open() */ 154static int tapdclone = 1; /* enable devfs cloning */ 155static SLIST_HEAD(, tap_softc) taphead; /* first device */ 156static struct clonedevs *tapclones; 157 158MALLOC_DECLARE(M_TAP); 159MALLOC_DEFINE(M_TAP, CDEV_NAME, "Ethernet tunnel interface"); 160SYSCTL_INT(_debug, OID_AUTO, if_tap_debug, CTLFLAG_RW, &tapdebug, 0, ""); 161 162SYSCTL_DECL(_net_link); 163SYSCTL_NODE(_net_link, OID_AUTO, tap, CTLFLAG_RW, 0, 164 "Ethernet tunnel software network interface"); 165SYSCTL_INT(_net_link_tap, OID_AUTO, user_open, CTLFLAG_RW, &tapuopen, 0, 166 "Allow user to open /dev/tap (based on node permissions)"); 167SYSCTL_INT(_net_link_tap, OID_AUTO, devfs_cloning, CTLFLAG_RW, &tapdclone, 0, 168 "Enably legacy devfs interface creation"); 169SYSCTL_INT(_net_link_tap, OID_AUTO, debug, CTLFLAG_RW, &tapdebug, 0, ""); 170 171TUNABLE_INT("net.link.tap.devfs_cloning", &tapdclone); 172 173DEV_MODULE(if_tap, tapmodevent, NULL); 174 175static int 176tap_clone_create(struct if_clone *ifc, int unit, caddr_t params) 177{ 178 struct cdev *dev; 179 int i; 180 int extra; 181 182 if (strcmp(ifc->ifc_name, VMNET) == 0) 183 extra = VMNET_DEV_MASK; 184 else 185 extra = 0; 186 187 /* find any existing device, or allocate new unit number */ 188 i = clone_create(&tapclones, &tap_cdevsw, &unit, &dev, extra); 189 if (i) { 190 dev = make_dev(&tap_cdevsw, unit2minor(unit | extra), 191 UID_ROOT, GID_WHEEL, 0600, "%s%d", ifc->ifc_name, unit); 192 if (dev != NULL) { 193 dev_ref(dev); 194 dev->si_flags |= SI_CHEAPCLONE; 195 } 196 } 197 198 tapcreate(dev); 199 return (0); 200} 201 202/* vmnet devices are tap devices in disguise */ 203static int 204vmnet_clone_create(struct if_clone *ifc, int unit, caddr_t params) 205{ 206 return tap_clone_create(ifc, unit, params); 207} 208 209static void 210tap_destroy(struct tap_softc *tp) 211{ 212 struct ifnet *ifp = tp->tap_ifp; 213 int s; 214 215 /* Unlocked read. */ 216 KASSERT(!(tp->tap_flags & TAP_OPEN), 217 ("%s flags is out of sync", ifp->if_xname)); 218 219 knlist_destroy(&tp->tap_rsel.si_note); 220 destroy_dev(tp->tap_dev); 221 s = splimp(); 222 ether_ifdetach(ifp); 223 if_free_type(ifp, IFT_ETHER); 224 splx(s); 225 226 mtx_destroy(&tp->tap_mtx); 227 free(tp, M_TAP); 228} 229 230static void 231tap_clone_destroy(struct ifnet *ifp) 232{ 233 struct tap_softc *tp = ifp->if_softc; 234 235 mtx_lock(&tapmtx); 236 SLIST_REMOVE(&taphead, tp, tap_softc, tap_next); 237 mtx_unlock(&tapmtx); 238 tap_destroy(tp); 239} 240 241/* vmnet devices are tap devices in disguise */ 242static void 243vmnet_clone_destroy(struct ifnet *ifp) 244{ 245 tap_clone_destroy(ifp); 246} 247 248/* 249 * tapmodevent 250 * 251 * module event handler 252 */ 253static int 254tapmodevent(module_t mod, int type, void *data) 255{ 256 static eventhandler_tag eh_tag = NULL; 257 struct tap_softc *tp = NULL; 258 struct ifnet *ifp = NULL; 259 260 switch (type) { 261 case MOD_LOAD: 262 263 /* intitialize device */ 264 265 mtx_init(&tapmtx, "tapmtx", NULL, MTX_DEF); 266 SLIST_INIT(&taphead); 267 268 clone_setup(&tapclones); 269 eh_tag = EVENTHANDLER_REGISTER(dev_clone, tapclone, 0, 1000); 270 if (eh_tag == NULL) { 271 clone_cleanup(&tapclones); 272 mtx_destroy(&tapmtx); 273 return (ENOMEM); 274 } 275 if_clone_attach(&tap_cloner); 276 if_clone_attach(&vmnet_cloner); 277 return (0); 278 279 case MOD_UNLOAD: 280 /* 281 * The EBUSY algorithm here can't quite atomically 282 * guarantee that this is race-free since we have to 283 * release the tap mtx to deregister the clone handler. 284 */ 285 mtx_lock(&tapmtx); 286 SLIST_FOREACH(tp, &taphead, tap_next) { 287 mtx_lock(&tp->tap_mtx); 288 if (tp->tap_flags & TAP_OPEN) { 289 mtx_unlock(&tp->tap_mtx); 290 mtx_unlock(&tapmtx); 291 return (EBUSY); 292 } 293 mtx_unlock(&tp->tap_mtx); 294 } 295 mtx_unlock(&tapmtx); 296 297 EVENTHANDLER_DEREGISTER(dev_clone, eh_tag); 298 if_clone_detach(&tap_cloner); 299 if_clone_detach(&vmnet_cloner); 300 301 mtx_lock(&tapmtx); 302 while ((tp = SLIST_FIRST(&taphead)) != NULL) { 303 SLIST_REMOVE_HEAD(&taphead, tap_next); 304 mtx_unlock(&tapmtx); 305 306 ifp = tp->tap_ifp; 307 308 TAPDEBUG("detaching %s\n", ifp->if_xname); 309 310 tap_destroy(tp); 311 mtx_lock(&tapmtx); 312 } 313 mtx_unlock(&tapmtx); 314 clone_cleanup(&tapclones); 315 316 mtx_destroy(&tapmtx); 317 318 break; 319 320 default: 321 return (EOPNOTSUPP); 322 } 323 324 return (0); 325} /* tapmodevent */ 326 327 328/* 329 * DEVFS handler 330 * 331 * We need to support two kind of devices - tap and vmnet 332 */ 333static void 334tapclone(void *arg, struct ucred *cred, char *name, int namelen, struct cdev **dev) 335{ 336 char devname[SPECNAMELEN + 1]; 337 int i, unit, append_unit; 338 int extra; 339 340 if (*dev != NULL) 341 return; 342 343 /* 344 * If tap cloning is enabled, only the superuser can create 345 * an interface. 346 */ 347 if (!tapdclone || priv_check_cred(cred, PRIV_NET_IFCREATE, 0) != 0) 348 return; 349 350 unit = 0; 351 append_unit = 0; 352 extra = 0; 353 354 /* We're interested in only tap/vmnet devices. */ 355 if (strcmp(name, TAP) == 0) { 356 unit = -1; 357 } else if (strcmp(name, VMNET) == 0) { 358 unit = -1; 359 extra = VMNET_DEV_MASK; 360 } else if (dev_stdclone(name, NULL, TAP, &unit) != 1) { 361 if (dev_stdclone(name, NULL, VMNET, &unit) != 1) { 362 return; 363 } else { 364 extra = VMNET_DEV_MASK; 365 } 366 } 367 368 if (unit == -1) 369 append_unit = 1; 370 371 /* find any existing device, or allocate new unit number */ 372 i = clone_create(&tapclones, &tap_cdevsw, &unit, dev, extra); 373 if (i) { 374 if (append_unit) { 375 /* 376 * We were passed 'tun' or 'tap', with no unit specified 377 * so we'll need to append it now. 378 */ 379 namelen = snprintf(devname, sizeof(devname), "%s%d", name, 380 unit); 381 name = devname; 382 } 383 384 *dev = make_dev(&tap_cdevsw, unit2minor(unit | extra), 385 UID_ROOT, GID_WHEEL, 0600, "%s", name); 386 if (*dev != NULL) { 387 dev_ref(*dev); 388 (*dev)->si_flags |= SI_CHEAPCLONE; 389 } 390 } 391 392 if_clone_create(name, namelen, NULL); 393} /* tapclone */ 394 395 396/* 397 * tapcreate 398 * 399 * to create interface 400 */ 401static void 402tapcreate(struct cdev *dev) 403{ 404 struct ifnet *ifp = NULL; 405 struct tap_softc *tp = NULL; 406 unsigned short macaddr_hi; 407 int unit, s; 408 char *name = NULL; 409 u_char eaddr[6]; 410 411 dev->si_flags &= ~SI_CHEAPCLONE; 412 413 /* allocate driver storage and create device */ 414 MALLOC(tp, struct tap_softc *, sizeof(*tp), M_TAP, M_WAITOK | M_ZERO); 415 mtx_init(&tp->tap_mtx, "tap_mtx", NULL, MTX_DEF); 416 mtx_lock(&tapmtx); 417 SLIST_INSERT_HEAD(&taphead, tp, tap_next); 418 mtx_unlock(&tapmtx); 419 420 unit = dev2unit(dev); 421 422 /* select device: tap or vmnet */ 423 if (unit & VMNET_DEV_MASK) { 424 name = VMNET; 425 tp->tap_flags |= TAP_VMNET; 426 } else 427 name = TAP; 428 429 unit &= TAPMAXUNIT; 430 431 TAPDEBUG("tapcreate(%s%d). minor = %#x\n", name, unit, minor(dev)); 432 433 /* generate fake MAC address: 00 bd xx xx xx unit_no */ 434 macaddr_hi = htons(0x00bd); 435 bcopy(&macaddr_hi, eaddr, sizeof(short)); 436 bcopy(&ticks, &eaddr[2], sizeof(long)); 437 eaddr[5] = (u_char)unit; 438 439 /* fill the rest and attach interface */ 440 ifp = tp->tap_ifp = if_alloc(IFT_ETHER); 441 if (ifp == NULL) 442 panic("%s%d: can not if_alloc()", name, unit); 443 ifp->if_softc = tp; 444 if_initname(ifp, name, unit); 445 ifp->if_init = tapifinit; 446 ifp->if_start = tapifstart; 447 ifp->if_ioctl = tapifioctl; 448 ifp->if_mtu = ETHERMTU; 449 ifp->if_flags = (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST); 450 ifp->if_snd.ifq_maxlen = ifqmaxlen; 451 452 dev->si_drv1 = tp; 453 tp->tap_dev = dev; 454 455 s = splimp(); 456 ether_ifattach(ifp, eaddr); 457 splx(s); 458 459 mtx_lock(&tp->tap_mtx); 460 tp->tap_flags |= TAP_INITED; 461 mtx_unlock(&tp->tap_mtx); 462 463 knlist_init(&tp->tap_rsel.si_note, NULL, NULL, NULL, NULL); 464 465 TAPDEBUG("interface %s is created. minor = %#x\n", 466 ifp->if_xname, minor(dev)); 467} /* tapcreate */ 468 469 470/* 471 * tapopen 472 * 473 * to open tunnel. must be superuser 474 */ 475static int 476tapopen(struct cdev *dev, int flag, int mode, struct thread *td) 477{ 478 struct tap_softc *tp = NULL; 479 struct ifnet *ifp = NULL; 480 int error, s; 481 482 if (tapuopen == 0) { 483 error = priv_check(td, PRIV_NET_TAP); 484 if (error) 485 return (error); 486 } 487 488 if ((dev2unit(dev) & CLONE_UNITMASK) > TAPMAXUNIT) 489 return (ENXIO); 490 491 tp = dev->si_drv1; 492 493 mtx_lock(&tp->tap_mtx); 494 if (tp->tap_flags & TAP_OPEN) { 495 mtx_unlock(&tp->tap_mtx); 496 return (EBUSY); 497 } 498 499 bcopy(IF_LLADDR(tp->tap_ifp), tp->ether_addr, sizeof(tp->ether_addr)); 500 tp->tap_pid = td->td_proc->p_pid; 501 tp->tap_flags |= TAP_OPEN; 502 ifp = tp->tap_ifp; 503 mtx_unlock(&tp->tap_mtx); 504 505 s = splimp(); 506 ifp->if_drv_flags |= IFF_DRV_RUNNING; 507 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 508 splx(s); 509 510 TAPDEBUG("%s is open. minor = %#x\n", ifp->if_xname, minor(dev)); 511 512 return (0); 513} /* tapopen */ 514 515 516/* 517 * tapclose 518 * 519 * close the device - mark i/f down & delete routing info 520 */ 521static int 522tapclose(struct cdev *dev, int foo, int bar, struct thread *td) 523{ 524 struct ifaddr *ifa; 525 struct tap_softc *tp = dev->si_drv1; 526 struct ifnet *ifp = tp->tap_ifp; 527 int s; 528 529 /* junk all pending output */ 530 IF_DRAIN(&ifp->if_snd); 531 532 /* 533 * do not bring the interface down, and do not anything with 534 * interface, if we are in VMnet mode. just close the device. 535 */ 536 537 mtx_lock(&tp->tap_mtx); 538 if (((tp->tap_flags & TAP_VMNET) == 0) && (ifp->if_flags & IFF_UP)) { 539 mtx_unlock(&tp->tap_mtx); 540 s = splimp(); 541 if_down(ifp); 542 if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 543 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 544 rtinit(ifa, (int)RTM_DELETE, 0); 545 } 546 if_purgeaddrs(ifp); 547 ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 548 } 549 splx(s); 550 } else 551 mtx_unlock(&tp->tap_mtx); 552 553 funsetown(&tp->tap_sigio); 554 selwakeuppri(&tp->tap_rsel, PZERO+1); 555 KNOTE_UNLOCKED(&tp->tap_rsel.si_note, 0); 556 557 mtx_lock(&tp->tap_mtx); 558 tp->tap_flags &= ~TAP_OPEN; 559 tp->tap_pid = 0; 560 mtx_unlock(&tp->tap_mtx); 561 562 TAPDEBUG("%s is closed. minor = %#x\n", 563 ifp->if_xname, minor(dev)); 564 565 return (0); 566} /* tapclose */ 567 568 569/* 570 * tapifinit 571 * 572 * network interface initialization function 573 */ 574static void 575tapifinit(void *xtp) 576{ 577 struct tap_softc *tp = (struct tap_softc *)xtp; 578 struct ifnet *ifp = tp->tap_ifp; 579 580 TAPDEBUG("initializing %s\n", ifp->if_xname); 581 582 ifp->if_drv_flags |= IFF_DRV_RUNNING; 583 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 584 585 /* attempt to start output */ 586 tapifstart(ifp); 587} /* tapifinit */ 588 589 590/* 591 * tapifioctl 592 * 593 * Process an ioctl request on network interface 594 */ 595static int 596tapifioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 597{ 598 struct tap_softc *tp = ifp->if_softc; 599 struct ifstat *ifs = NULL; 600 int s, dummy; 601 602 switch (cmd) { 603 case SIOCSIFFLAGS: /* XXX -- just like vmnet does */ 604 case SIOCADDMULTI: 605 case SIOCDELMULTI: 606 break; 607 608 case SIOCGIFSTATUS: 609 s = splimp(); 610 ifs = (struct ifstat *)data; 611 dummy = strlen(ifs->ascii); 612 mtx_lock(&tp->tap_mtx); 613 if (tp->tap_pid != 0 && dummy < sizeof(ifs->ascii)) 614 snprintf(ifs->ascii + dummy, 615 sizeof(ifs->ascii) - dummy, 616 "\tOpened by PID %d\n", tp->tap_pid); 617 mtx_unlock(&tp->tap_mtx); 618 splx(s); 619 break; 620 621 default: 622 s = splimp(); 623 dummy = ether_ioctl(ifp, cmd, data); 624 splx(s); 625 return (dummy); 626 /* NOT REACHED */ 627 } 628 629 return (0); 630} /* tapifioctl */ 631 632 633/* 634 * tapifstart 635 * 636 * queue packets from higher level ready to put out 637 */ 638static void 639tapifstart(struct ifnet *ifp) 640{ 641 struct tap_softc *tp = ifp->if_softc; 642 int s; 643 644 TAPDEBUG("%s starting\n", ifp->if_xname); 645 646 /* 647 * do not junk pending output if we are in VMnet mode. 648 * XXX: can this do any harm because of queue overflow? 649 */ 650 651 mtx_lock(&tp->tap_mtx); 652 if (((tp->tap_flags & TAP_VMNET) == 0) && 653 ((tp->tap_flags & TAP_READY) != TAP_READY)) { 654 struct mbuf *m = NULL; 655 656 mtx_unlock(&tp->tap_mtx); 657 658 /* Unlocked read. */ 659 TAPDEBUG("%s not ready, tap_flags = 0x%x\n", ifp->if_xname, 660 tp->tap_flags); 661 662 s = splimp(); 663 do { 664 IF_DEQUEUE(&ifp->if_snd, m); 665 if (m != NULL) 666 m_freem(m); 667 ifp->if_oerrors ++; 668 } while (m != NULL); 669 splx(s); 670 671 return; 672 } 673 mtx_unlock(&tp->tap_mtx); 674 675 s = splimp(); 676 ifp->if_drv_flags |= IFF_DRV_OACTIVE; 677 678 if (ifp->if_snd.ifq_len != 0) { 679 mtx_lock(&tp->tap_mtx); 680 if (tp->tap_flags & TAP_RWAIT) { 681 tp->tap_flags &= ~TAP_RWAIT; 682 wakeup(tp); 683 } 684 685 if ((tp->tap_flags & TAP_ASYNC) && (tp->tap_sigio != NULL)) { 686 mtx_unlock(&tp->tap_mtx); 687 pgsigio(&tp->tap_sigio, SIGIO, 0); 688 } else 689 mtx_unlock(&tp->tap_mtx); 690 691 selwakeuppri(&tp->tap_rsel, PZERO+1); 692 KNOTE_UNLOCKED(&tp->tap_rsel.si_note, 0); 693 ifp->if_opackets ++; /* obytes are counted in ether_output */ 694 } 695 696 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 697 splx(s); 698} /* tapifstart */ 699 700 701/* 702 * tapioctl 703 * 704 * the cdevsw interface is now pretty minimal 705 */ 706static int 707tapioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) 708{ 709 struct tap_softc *tp = dev->si_drv1; 710 struct ifnet *ifp = tp->tap_ifp; 711 struct tapinfo *tapp = NULL; 712 int s; 713 int f; 714#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ 715 defined(COMPAT_FREEBSD4) 716 int ival; 717#endif 718 719 switch (cmd) { 720 case TAPSIFINFO: 721 s = splimp(); 722 tapp = (struct tapinfo *)data; 723 ifp->if_mtu = tapp->mtu; 724 ifp->if_type = tapp->type; 725 ifp->if_baudrate = tapp->baudrate; 726 splx(s); 727 break; 728 729 case TAPGIFINFO: 730 tapp = (struct tapinfo *)data; 731 tapp->mtu = ifp->if_mtu; 732 tapp->type = ifp->if_type; 733 tapp->baudrate = ifp->if_baudrate; 734 break; 735 736 case TAPSDEBUG: 737 tapdebug = *(int *)data; 738 break; 739 740 case TAPGDEBUG: 741 *(int *)data = tapdebug; 742 break; 743 744 case FIONBIO: 745 break; 746 747 case FIOASYNC: 748 s = splimp(); 749 mtx_lock(&tp->tap_mtx); 750 if (*(int *)data) 751 tp->tap_flags |= TAP_ASYNC; 752 else 753 tp->tap_flags &= ~TAP_ASYNC; 754 mtx_unlock(&tp->tap_mtx); 755 splx(s); 756 break; 757 758 case FIONREAD: 759 s = splimp(); 760 if (ifp->if_snd.ifq_head) { 761 struct mbuf *mb = ifp->if_snd.ifq_head; 762 763 for(*(int *)data = 0;mb != NULL;mb = mb->m_next) 764 *(int *)data += mb->m_len; 765 } else 766 *(int *)data = 0; 767 splx(s); 768 break; 769 770 case FIOSETOWN: 771 return (fsetown(*(int *)data, &tp->tap_sigio)); 772 773 case FIOGETOWN: 774 *(int *)data = fgetown(&tp->tap_sigio); 775 return (0); 776 777 /* this is deprecated, FIOSETOWN should be used instead */ 778 case TIOCSPGRP: 779 return (fsetown(-(*(int *)data), &tp->tap_sigio)); 780 781 /* this is deprecated, FIOGETOWN should be used instead */ 782 case TIOCGPGRP: 783 *(int *)data = -fgetown(&tp->tap_sigio); 784 return (0); 785 786 /* VMware/VMnet port ioctl's */ 787 788 case SIOCGIFFLAGS: /* get ifnet flags */ 789 bcopy(&ifp->if_flags, data, sizeof(ifp->if_flags)); 790 break; 791 792#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ 793 defined(COMPAT_FREEBSD4) 794 case _IO('V', 0): 795 ival = IOCPARM_IVAL(data); 796 data = (caddr_t)&ival; 797 /* FALLTHROUGH */ 798#endif 799 case VMIO_SIOCSIFFLAGS: /* VMware/VMnet SIOCSIFFLAGS */ 800 f = *(int *)data; 801 f &= 0x0fff; 802 f &= ~IFF_CANTCHANGE; 803 f |= IFF_UP; 804 805 s = splimp(); 806 ifp->if_flags = f | (ifp->if_flags & IFF_CANTCHANGE); 807 splx(s); 808 break; 809 810 case OSIOCGIFADDR: /* get MAC address of the remote side */ 811 case SIOCGIFADDR: 812 mtx_lock(&tp->tap_mtx); 813 bcopy(tp->ether_addr, data, sizeof(tp->ether_addr)); 814 mtx_unlock(&tp->tap_mtx); 815 break; 816 817 case SIOCSIFADDR: /* set MAC address of the remote side */ 818 mtx_lock(&tp->tap_mtx); 819 bcopy(data, tp->ether_addr, sizeof(tp->ether_addr)); 820 mtx_unlock(&tp->tap_mtx); 821 break; 822 823 default: 824 return (ENOTTY); 825 } 826 return (0); 827} /* tapioctl */ 828 829 830/* 831 * tapread 832 * 833 * the cdevsw read interface - reads a packet at a time, or at 834 * least as much of a packet as can be read 835 */ 836static int 837tapread(struct cdev *dev, struct uio *uio, int flag) 838{ 839 struct tap_softc *tp = dev->si_drv1; 840 struct ifnet *ifp = tp->tap_ifp; 841 struct mbuf *m = NULL; 842 int error = 0, len, s; 843 844 TAPDEBUG("%s reading, minor = %#x\n", ifp->if_xname, minor(dev)); 845 846 mtx_lock(&tp->tap_mtx); 847 if ((tp->tap_flags & TAP_READY) != TAP_READY) { 848 mtx_unlock(&tp->tap_mtx); 849 850 /* Unlocked read. */ 851 TAPDEBUG("%s not ready. minor = %#x, tap_flags = 0x%x\n", 852 ifp->if_xname, minor(dev), tp->tap_flags); 853 854 return (EHOSTDOWN); 855 } 856 857 tp->tap_flags &= ~TAP_RWAIT; 858 mtx_unlock(&tp->tap_mtx); 859 860 /* sleep until we get a packet */ 861 do { 862 s = splimp(); 863 IF_DEQUEUE(&ifp->if_snd, m); 864 splx(s); 865 866 if (m == NULL) { 867 if (flag & O_NONBLOCK) 868 return (EWOULDBLOCK); 869 870 mtx_lock(&tp->tap_mtx); 871 tp->tap_flags |= TAP_RWAIT; 872 mtx_unlock(&tp->tap_mtx); 873 error = tsleep(tp,PCATCH|(PZERO+1),"taprd",0); 874 if (error) 875 return (error); 876 } 877 } while (m == NULL); 878 879 /* feed packet to bpf */ 880 BPF_MTAP(ifp, m); 881 882 /* xfer packet to user space */ 883 while ((m != NULL) && (uio->uio_resid > 0) && (error == 0)) { 884 len = min(uio->uio_resid, m->m_len); 885 if (len == 0) 886 break; 887 888 error = uiomove(mtod(m, void *), len, uio); 889 m = m_free(m); 890 } 891 892 if (m != NULL) { 893 TAPDEBUG("%s dropping mbuf, minor = %#x\n", ifp->if_xname, 894 minor(dev)); 895 m_freem(m); 896 } 897 898 return (error); 899} /* tapread */ 900 901 902/* 903 * tapwrite 904 * 905 * the cdevsw write interface - an atomic write is a packet - or else! 906 */ 907static int 908tapwrite(struct cdev *dev, struct uio *uio, int flag) 909{ 910 struct ether_header *eh; 911 struct tap_softc *tp = dev->si_drv1; 912 struct ifnet *ifp = tp->tap_ifp; 913 struct mbuf *m; 914 915 TAPDEBUG("%s writting, minor = %#x\n", 916 ifp->if_xname, minor(dev)); 917 918 if (uio->uio_resid == 0) 919 return (0); 920 921 if ((uio->uio_resid < 0) || (uio->uio_resid > TAPMRU)) { 922 TAPDEBUG("%s invalid packet len = %d, minor = %#x\n", 923 ifp->if_xname, uio->uio_resid, minor(dev)); 924 925 return (EIO); 926 } 927 928 if ((m = m_uiotombuf(uio, M_DONTWAIT, 0, ETHER_ALIGN, 929 M_PKTHDR)) == NULL) { 930 ifp->if_ierrors ++; 931 return (ENOBUFS); 932 } 933 934 m->m_pkthdr.rcvif = ifp; 935 936 /* 937 * Only pass a unicast frame to ether_input(), if it would actually 938 * have been received by non-virtual hardware. 939 */ 940 if (m->m_len < sizeof(struct ether_header)) { 941 m_freem(m); 942 return (0); 943 } 944 eh = mtod(m, struct ether_header *); 945 946 if (eh && (ifp->if_flags & IFF_PROMISC) == 0 && 947 !ETHER_IS_MULTICAST(eh->ether_dhost) && 948 bcmp(eh->ether_dhost, IF_LLADDR(ifp), ETHER_ADDR_LEN) != 0) { 949 m_freem(m); 950 return (0); 951 } 952 953 /* Pass packet up to parent. */ 954 (*ifp->if_input)(ifp, m); 955 ifp->if_ipackets ++; /* ibytes are counted in parent */ 956 957 return (0); 958} /* tapwrite */ 959 960 961/* 962 * tappoll 963 * 964 * the poll interface, this is only useful on reads 965 * really. the write detect always returns true, write never blocks 966 * anyway, it either accepts the packet or drops it 967 */ 968static int 969tappoll(struct cdev *dev, int events, struct thread *td) 970{ 971 struct tap_softc *tp = dev->si_drv1; 972 struct ifnet *ifp = tp->tap_ifp; 973 int s, revents = 0; 974 975 TAPDEBUG("%s polling, minor = %#x\n", 976 ifp->if_xname, minor(dev)); 977 978 s = splimp(); 979 if (events & (POLLIN | POLLRDNORM)) { 980 if (ifp->if_snd.ifq_len > 0) { 981 TAPDEBUG("%s have data in queue. len = %d, " \ 982 "minor = %#x\n", ifp->if_xname, 983 ifp->if_snd.ifq_len, minor(dev)); 984 985 revents |= (events & (POLLIN | POLLRDNORM)); 986 } else { 987 TAPDEBUG("%s waiting for data, minor = %#x\n", 988 ifp->if_xname, minor(dev)); 989 990 selrecord(td, &tp->tap_rsel); 991 } 992 } 993 994 if (events & (POLLOUT | POLLWRNORM)) 995 revents |= (events & (POLLOUT | POLLWRNORM)); 996 997 splx(s); 998 return (revents); 999} /* tappoll */ 1000 1001 1002/* 1003 * tap_kqfilter 1004 * 1005 * support for kevent() system call 1006 */ 1007static int 1008tapkqfilter(struct cdev *dev, struct knote *kn) 1009{ 1010 int s; 1011 struct tap_softc *tp = dev->si_drv1; 1012 struct ifnet *ifp = tp->tap_ifp; 1013 1014 s = splimp(); 1015 switch (kn->kn_filter) { 1016 case EVFILT_READ: 1017 TAPDEBUG("%s kqfilter: EVFILT_READ, minor = %#x\n", 1018 ifp->if_xname, minor(dev)); 1019 kn->kn_fop = &tap_read_filterops; 1020 break; 1021 1022 case EVFILT_WRITE: 1023 TAPDEBUG("%s kqfilter: EVFILT_WRITE, minor = %#x\n", 1024 ifp->if_xname, minor(dev)); 1025 kn->kn_fop = &tap_write_filterops; 1026 break; 1027 1028 default: 1029 TAPDEBUG("%s kqfilter: invalid filter, minor = %#x\n", 1030 ifp->if_xname, minor(dev)); 1031 splx(s); 1032 return (EINVAL); 1033 /* NOT REACHED */ 1034 } 1035 splx(s); 1036 1037 kn->kn_hook = (caddr_t) dev; 1038 knlist_add(&tp->tap_rsel.si_note, kn, 0); 1039 1040 return (0); 1041} /* tapkqfilter */ 1042 1043 1044/* 1045 * tap_kqread 1046 * 1047 * Return true if there is data in the interface queue 1048 */ 1049static int 1050tapkqread(struct knote *kn, long hint) 1051{ 1052 int ret, s; 1053 struct cdev *dev = (struct cdev *)(kn->kn_hook); 1054 struct tap_softc *tp = dev->si_drv1; 1055 struct ifnet *ifp = tp->tap_ifp; 1056 1057 s = splimp(); 1058 if ((kn->kn_data = ifp->if_snd.ifq_len) > 0) { 1059 TAPDEBUG("%s have data in queue. len = %d, minor = %#x\n", 1060 ifp->if_xname, ifp->if_snd.ifq_len, minor(dev)); 1061 ret = 1; 1062 } else { 1063 TAPDEBUG("%s waiting for data, minor = %#x\n", 1064 ifp->if_xname, minor(dev)); 1065 ret = 0; 1066 } 1067 splx(s); 1068 1069 return (ret); 1070} /* tapkqread */ 1071 1072 1073/* 1074 * tap_kqwrite 1075 * 1076 * Always can write. Return the MTU in kn->data 1077 */ 1078static int 1079tapkqwrite(struct knote *kn, long hint) 1080{ 1081 int s; 1082 struct tap_softc *tp = ((struct cdev *) kn->kn_hook)->si_drv1; 1083 struct ifnet *ifp = tp->tap_ifp; 1084 1085 s = splimp(); 1086 kn->kn_data = ifp->if_mtu; 1087 splx(s); 1088 1089 return (1); 1090} /* tapkqwrite */ 1091 1092 1093static void 1094tapkqdetach(struct knote *kn) 1095{ 1096 struct tap_softc *tp = ((struct cdev *) kn->kn_hook)->si_drv1; 1097 1098 knlist_remove(&tp->tap_rsel.si_note, kn, 0); 1099} /* tapkqdetach */ 1100 1101