if_tap.c revision 156783
1272343Sngie/*- 2272343Sngie * Copyright (C) 1999-2000 by Maksim Yevmenkin <m_evmenkin@yahoo.com> 3272343Sngie * All rights reserved. 4272343Sngie * 5272343Sngie * Redistribution and use in source and binary forms, with or without 6272343Sngie * modification, are permitted provided that the following conditions 7272343Sngie * are met: 8272343Sngie * 1. Redistributions of source code must retain the above copyright 9272343Sngie * notice, this list of conditions and the following disclaimer. 10272343Sngie * 2. Redistributions in binary form must reproduce the above copyright 11272343Sngie * notice, this list of conditions and the following disclaimer in the 12272343Sngie * documentation and/or other materials provided with the distribution. 13272343Sngie * 14272343Sngie * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15272343Sngie * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16272343Sngie * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17272343Sngie * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18272343Sngie * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19272343Sngie * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20272343Sngie * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21272343Sngie * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22272343Sngie * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23272343Sngie * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24272343Sngie * SUCH DAMAGE. 25272343Sngie * 26272343Sngie * BASED ON: 27272343Sngie * ------------------------------------------------------------------------- 28272343Sngie * 29272343Sngie * Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk> 30272343Sngie * Nottingham University 1987. 31272343Sngie */ 32272343Sngie 33272343Sngie/* 34272343Sngie * $FreeBSD: head/sys/net/if_tap.c 156783 2006-03-16 18:22:01Z emax $ 35272343Sngie * $Id: if_tap.c,v 0.21 2000/07/23 21:46:02 max Exp $ 36272343Sngie */ 37272343Sngie 38272343Sngie#include "opt_inet.h" 39272343Sngie 40272343Sngie#include <sys/param.h> 41272343Sngie#include <sys/conf.h> 42272343Sngie#include <sys/fcntl.h> 43272343Sngie#include <sys/filio.h> 44272343Sngie#include <sys/kernel.h> 45272343Sngie#include <sys/malloc.h> 46272343Sngie#include <sys/mbuf.h> 47272343Sngie#include <sys/module.h> 48272343Sngie#include <sys/poll.h> 49272343Sngie#include <sys/proc.h> 50276478Sngie#include <sys/selinfo.h> 51276478Sngie#include <sys/signalvar.h> 52276478Sngie#include <sys/socket.h> 53276478Sngie#include <sys/sockio.h> 54272343Sngie#include <sys/sysctl.h> 55272343Sngie#include <sys/systm.h> 56272343Sngie#include <sys/ttycom.h> 57272343Sngie#include <sys/uio.h> 58272343Sngie#include <sys/queue.h> 59272343Sngie 60272343Sngie#include <net/bpf.h> 61272343Sngie#include <net/ethernet.h> 62272343Sngie#include <net/if.h> 63272343Sngie#include <net/if_dl.h> 64272343Sngie#include <net/route.h> 65272343Sngie#include <net/if_types.h> 66272343Sngie 67272343Sngie#include <netinet/in.h> 68272343Sngie 69272343Sngie#include <net/if_tapvar.h> 70272343Sngie#include <net/if_tap.h> 71272343Sngie 72272343Sngie 73272343Sngie#define CDEV_NAME "tap" 74272343Sngie#define TAPDEBUG if (tapdebug) printf 75272343Sngie 76272343Sngie#define TAP "tap" 77272343Sngie#define VMNET "vmnet" 78272343Sngie#define TAPMAXUNIT 0x7fff 79272343Sngie#define VMNET_DEV_MASK CLONE_FLAG0 80272343Sngie 81272343Sngie/* module */ 82272343Sngiestatic int tapmodevent(module_t, int, void *); 83272343Sngie 84272343Sngie/* device */ 85272343Sngiestatic void tapclone(void *, struct ucred *, char *, int, 86272343Sngie struct cdev **); 87272343Sngiestatic void tapcreate(struct cdev *); 88272343Sngie 89272343Sngie/* network interface */ 90272343Sngiestatic void tapifstart(struct ifnet *); 91272343Sngiestatic int tapifioctl(struct ifnet *, u_long, caddr_t); 92272343Sngiestatic void tapifinit(void *); 93272343Sngie 94272343Sngie/* character device */ 95272343Sngiestatic d_open_t tapopen; 96272343Sngiestatic d_close_t tapclose; 97272343Sngiestatic d_read_t tapread; 98272343Sngiestatic d_write_t tapwrite; 99272343Sngiestatic d_ioctl_t tapioctl; 100272343Sngiestatic d_poll_t tappoll; 101272343Sngiestatic d_kqfilter_t tapkqfilter; 102272343Sngie 103272343Sngie/* kqueue(2) */ 104272343Sngiestatic int tapkqread(struct knote *, long); 105272343Sngiestatic int tapkqwrite(struct knote *, long); 106272343Sngiestatic void tapkqdetach(struct knote *); 107272343Sngie 108272343Sngiestatic struct filterops tap_read_filterops = { 109272343Sngie .f_isfd = 1, 110272343Sngie .f_attach = NULL, 111272343Sngie .f_detach = tapkqdetach, 112272343Sngie .f_event = tapkqread, 113272343Sngie}; 114272343Sngie 115272343Sngiestatic struct filterops tap_write_filterops = { 116272343Sngie .f_isfd = 1, 117272343Sngie .f_attach = NULL, 118272343Sngie .f_detach = tapkqdetach, 119272343Sngie .f_event = tapkqwrite, 120272343Sngie}; 121272343Sngie 122272343Sngiestatic struct cdevsw tap_cdevsw = { 123272343Sngie .d_version = D_VERSION, 124272343Sngie .d_flags = D_PSEUDO | D_NEEDGIANT, 125272343Sngie .d_open = tapopen, 126272343Sngie .d_close = tapclose, 127272343Sngie .d_read = tapread, 128272343Sngie .d_write = tapwrite, 129272343Sngie .d_ioctl = tapioctl, 130272343Sngie .d_poll = tappoll, 131272343Sngie .d_name = CDEV_NAME, 132272343Sngie .d_kqfilter = tapkqfilter, 133272343Sngie}; 134272343Sngie 135272343Sngie/* 136272343Sngie * All global variables in if_tap.c are locked with tapmtx, with the 137272343Sngie * exception of tapdebug, which is accessed unlocked; tapclones is 138272343Sngie * static at runtime. 139272343Sngie */ 140272343Sngiestatic struct mtx tapmtx; 141272343Sngiestatic int tapdebug = 0; /* debug flag */ 142272343Sngiestatic int tapuopen = 0; /* allow user open() */ 143272343Sngiestatic SLIST_HEAD(, tap_softc) taphead; /* first device */ 144272343Sngiestatic struct clonedevs *tapclones; 145272343Sngie 146272343SngieMALLOC_DECLARE(M_TAP); 147272343SngieMALLOC_DEFINE(M_TAP, CDEV_NAME, "Ethernet tunnel interface"); 148272343SngieSYSCTL_INT(_debug, OID_AUTO, if_tap_debug, CTLFLAG_RW, &tapdebug, 0, ""); 149272343Sngie 150272343SngieSYSCTL_DECL(_net_link); 151272343SngieSYSCTL_NODE(_net_link, OID_AUTO, tap, CTLFLAG_RW, 0, 152272343Sngie "Ethernet tunnel software network interface"); 153272343SngieSYSCTL_INT(_net_link_tap, OID_AUTO, user_open, CTLFLAG_RW, &tapuopen, 0, 154272343Sngie "Allow user to open /dev/tap (based on node permissions)"); 155272343SngieSYSCTL_INT(_net_link_tap, OID_AUTO, debug, CTLFLAG_RW, &tapdebug, 0, ""); 156272343Sngie 157272343SngieDEV_MODULE(if_tap, tapmodevent, NULL); 158272343Sngie 159272343Sngie/* 160272343Sngie * tapmodevent 161272343Sngie * 162272343Sngie * module event handler 163272343Sngie */ 164272343Sngiestatic int 165272343Sngietapmodevent(module_t mod, int type, void *data) 166272343Sngie{ 167272343Sngie static eventhandler_tag eh_tag = NULL; 168272343Sngie struct tap_softc *tp = NULL; 169272343Sngie struct ifnet *ifp = NULL; 170272343Sngie int s; 171272343Sngie 172272343Sngie switch (type) { 173272343Sngie case MOD_LOAD: 174272343Sngie 175272343Sngie /* intitialize device */ 176272343Sngie 177272343Sngie mtx_init(&tapmtx, "tapmtx", NULL, MTX_DEF); 178272343Sngie SLIST_INIT(&taphead); 179272343Sngie 180272343Sngie clone_setup(&tapclones); 181272343Sngie eh_tag = EVENTHANDLER_REGISTER(dev_clone, tapclone, 0, 1000); 182272343Sngie if (eh_tag == NULL) { 183272343Sngie clone_cleanup(&tapclones); 184272343Sngie mtx_destroy(&tapmtx); 185272343Sngie return (ENOMEM); 186272343Sngie } 187272343Sngie return (0); 188272343Sngie 189272343Sngie case MOD_UNLOAD: 190272343Sngie /* 191272343Sngie * The EBUSY algorithm here can't quite atomically 192272343Sngie * guarantee that this is race-free since we have to 193272343Sngie * release the tap mtx to deregister the clone handler. 194272343Sngie */ 195272343Sngie mtx_lock(&tapmtx); 196272343Sngie SLIST_FOREACH(tp, &taphead, tap_next) { 197272343Sngie mtx_lock(&tp->tap_mtx); 198272343Sngie if (tp->tap_flags & TAP_OPEN) { 199272343Sngie mtx_unlock(&tp->tap_mtx); 200272343Sngie mtx_unlock(&tapmtx); 201272343Sngie return (EBUSY); 202272343Sngie } 203272343Sngie mtx_unlock(&tp->tap_mtx); 204272343Sngie } 205272343Sngie mtx_unlock(&tapmtx); 206272343Sngie 207272343Sngie EVENTHANDLER_DEREGISTER(dev_clone, eh_tag); 208272343Sngie 209272343Sngie mtx_lock(&tapmtx); 210272343Sngie while ((tp = SLIST_FIRST(&taphead)) != NULL) { 211272343Sngie SLIST_REMOVE_HEAD(&taphead, tap_next); 212272343Sngie mtx_unlock(&tapmtx); 213272343Sngie 214272343Sngie ifp = tp->tap_ifp; 215272343Sngie 216272343Sngie TAPDEBUG("detaching %s\n", ifp->if_xname); 217272343Sngie 218272343Sngie /* Unlocked read. */ 219272343Sngie KASSERT(!(tp->tap_flags & TAP_OPEN), 220272343Sngie ("%s flags is out of sync", ifp->if_xname)); 221272343Sngie 222272343Sngie destroy_dev(tp->tap_dev); 223272343Sngie s = splimp(); 224272343Sngie ether_ifdetach(ifp); 225272343Sngie if_free_type(ifp, IFT_ETHER); 226272343Sngie splx(s); 227272343Sngie 228272343Sngie mtx_destroy(&tp->tap_mtx); 229272343Sngie free(tp, M_TAP); 230272343Sngie mtx_lock(&tapmtx); 231272343Sngie } 232272343Sngie mtx_unlock(&tapmtx); 233272343Sngie clone_cleanup(&tapclones); 234272343Sngie 235272343Sngie mtx_destroy(&tapmtx); 236272343Sngie 237272343Sngie break; 238272343Sngie 239272343Sngie default: 240272343Sngie return (EOPNOTSUPP); 241272343Sngie } 242272343Sngie 243272343Sngie return (0); 244272343Sngie} /* tapmodevent */ 245272343Sngie 246272343Sngie 247272343Sngie/* 248272343Sngie * DEVFS handler 249272343Sngie * 250272343Sngie * We need to support two kind of devices - tap and vmnet 251272343Sngie */ 252272343Sngiestatic void 253272343Sngietapclone(void *arg, struct ucred *cred, char *name, int namelen, struct cdev **dev) 254272343Sngie{ 255272343Sngie u_int extra; 256272343Sngie int i, unit; 257272343Sngie char *device_name = name; 258272343Sngie 259272343Sngie if (*dev != NULL) 260272343Sngie return; 261272343Sngie 262272343Sngie device_name = TAP; 263272343Sngie extra = 0; 264272343Sngie if (strcmp(name, TAP) == 0) { 265272343Sngie unit = -1; 266272343Sngie } else if (strcmp(name, VMNET) == 0) { 267272343Sngie device_name = VMNET; 268272343Sngie extra = VMNET_DEV_MASK; 269272343Sngie unit = -1; 270272343Sngie } else if (dev_stdclone(name, NULL, device_name, &unit) != 1) { 271272343Sngie device_name = VMNET; 272272343Sngie extra = VMNET_DEV_MASK; 273272343Sngie if (dev_stdclone(name, NULL, device_name, &unit) != 1) 274272343Sngie return; 275272343Sngie } 276272343Sngie 277272343Sngie /* find any existing device, or allocate new unit number */ 278272343Sngie i = clone_create(&tapclones, &tap_cdevsw, &unit, dev, extra); 279272343Sngie if (i) { 280272343Sngie *dev = make_dev(&tap_cdevsw, unit2minor(unit | extra), 281272343Sngie UID_ROOT, GID_WHEEL, 0600, "%s%d", device_name, unit); 282272343Sngie if (*dev != NULL) { 283272343Sngie dev_ref(*dev); 284272343Sngie (*dev)->si_flags |= SI_CHEAPCLONE; 285272343Sngie } 286272343Sngie } 287272343Sngie} /* tapclone */ 288272343Sngie 289272343Sngie 290272343Sngie/* 291272343Sngie * tapcreate 292272343Sngie * 293272343Sngie * to create interface 294272343Sngie */ 295272343Sngiestatic void 296272343Sngietapcreate(struct cdev *dev) 297272343Sngie{ 298272343Sngie struct ifnet *ifp = NULL; 299272343Sngie struct tap_softc *tp = NULL; 300272343Sngie unsigned short macaddr_hi; 301272343Sngie int unit, s; 302272343Sngie char *name = NULL; 303272343Sngie u_char eaddr[6]; 304272343Sngie 305272343Sngie dev->si_flags &= ~SI_CHEAPCLONE; 306272343Sngie 307272343Sngie /* allocate driver storage and create device */ 308272343Sngie MALLOC(tp, struct tap_softc *, sizeof(*tp), M_TAP, M_WAITOK | M_ZERO); 309272343Sngie mtx_init(&tp->tap_mtx, "tap_mtx", NULL, MTX_DEF); 310272343Sngie mtx_lock(&tapmtx); 311272343Sngie SLIST_INSERT_HEAD(&taphead, tp, tap_next); 312272343Sngie mtx_unlock(&tapmtx); 313272343Sngie 314272343Sngie unit = dev2unit(dev); 315272343Sngie 316272343Sngie /* select device: tap or vmnet */ 317272343Sngie if (unit & VMNET_DEV_MASK) { 318272343Sngie name = VMNET; 319272343Sngie tp->tap_flags |= TAP_VMNET; 320272343Sngie } else 321272343Sngie name = TAP; 322272343Sngie 323272343Sngie unit &= TAPMAXUNIT; 324272343Sngie 325272343Sngie TAPDEBUG("tapcreate(%s%d). minor = %#x\n", name, unit, minor(dev)); 326272343Sngie 327272343Sngie /* generate fake MAC address: 00 bd xx xx xx unit_no */ 328272343Sngie macaddr_hi = htons(0x00bd); 329272343Sngie bcopy(&macaddr_hi, eaddr, sizeof(short)); 330272343Sngie bcopy(&ticks, &eaddr[2], sizeof(long)); 331272343Sngie eaddr[5] = (u_char)unit; 332272343Sngie 333272343Sngie /* fill the rest and attach interface */ 334272343Sngie ifp = tp->tap_ifp = if_alloc(IFT_ETHER); 335272343Sngie if (ifp == NULL) 336272343Sngie panic("%s%d: can not if_alloc()", name, unit); 337272343Sngie ifp->if_softc = tp; 338272343Sngie if_initname(ifp, name, unit); 339272343Sngie ifp->if_init = tapifinit; 340272343Sngie ifp->if_start = tapifstart; 341272343Sngie ifp->if_ioctl = tapifioctl; 342272343Sngie ifp->if_mtu = ETHERMTU; 343272343Sngie ifp->if_flags = (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST); 344272343Sngie ifp->if_snd.ifq_maxlen = ifqmaxlen; 345272343Sngie 346272343Sngie dev->si_drv1 = tp; 347272343Sngie tp->tap_dev = dev; 348272343Sngie 349272343Sngie s = splimp(); 350272343Sngie ether_ifattach(ifp, eaddr); 351272343Sngie splx(s); 352272343Sngie 353272343Sngie mtx_lock(&tp->tap_mtx); 354272343Sngie tp->tap_flags |= TAP_INITED; 355272343Sngie mtx_unlock(&tp->tap_mtx); 356272343Sngie 357272343Sngie TAPDEBUG("interface %s is created. minor = %#x\n", 358272343Sngie ifp->if_xname, minor(dev)); 359272343Sngie} /* tapcreate */ 360272343Sngie 361272343Sngie 362272343Sngie/* 363272343Sngie * tapopen 364272343Sngie * 365272343Sngie * to open tunnel. must be superuser 366272343Sngie */ 367272343Sngiestatic int 368272343Sngietapopen(struct cdev *dev, int flag, int mode, struct thread *td) 369272343Sngie{ 370272343Sngie struct tap_softc *tp = NULL; 371272343Sngie struct ifnet *ifp = NULL; 372272343Sngie int s; 373272343Sngie 374272343Sngie if (tapuopen == 0 && suser(td) != 0) 375272343Sngie return (EPERM); 376272343Sngie 377272343Sngie if ((dev2unit(dev) & CLONE_UNITMASK) > TAPMAXUNIT) 378272343Sngie return (ENXIO); 379272343Sngie 380272343Sngie /* 381272343Sngie * XXXRW: Non-atomic test-and-set of si_drv1. Currently protected 382272343Sngie * by Giant, but the race actually exists under memory pressure as 383272343Sngie * well even when running with Giant, as malloc() may sleep. 384272343Sngie */ 385272343Sngie tp = dev->si_drv1; 386272343Sngie if (tp == NULL) { 387272343Sngie tapcreate(dev); 388272343Sngie tp = dev->si_drv1; 389272343Sngie } 390272343Sngie 391272343Sngie mtx_lock(&tp->tap_mtx); 392272343Sngie if (tp->tap_flags & TAP_OPEN) { 393272343Sngie mtx_unlock(&tp->tap_mtx); 394272343Sngie return (EBUSY); 395272343Sngie } 396272343Sngie 397272343Sngie bcopy(IF_LLADDR(tp->tap_ifp), tp->ether_addr, sizeof(tp->ether_addr)); 398272343Sngie tp->tap_pid = td->td_proc->p_pid; 399272343Sngie tp->tap_flags |= TAP_OPEN; 400272343Sngie ifp = tp->tap_ifp; 401272343Sngie mtx_unlock(&tp->tap_mtx); 402272343Sngie 403272343Sngie s = splimp(); 404272343Sngie ifp->if_drv_flags |= IFF_DRV_RUNNING; 405272343Sngie ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 406272343Sngie splx(s); 407272343Sngie 408272343Sngie knlist_init(&tp->tap_rsel.si_note, NULL, NULL, NULL, NULL); 409272343Sngie 410272343Sngie TAPDEBUG("%s is open. minor = %#x\n", ifp->if_xname, minor(dev)); 411272343Sngie 412272343Sngie return (0); 413272343Sngie} /* tapopen */ 414272343Sngie 415272343Sngie 416272343Sngie/* 417272343Sngie * tapclose 418272343Sngie * 419272343Sngie * close the device - mark i/f down & delete routing info 420272343Sngie */ 421272343Sngiestatic int 422tapclose(struct cdev *dev, int foo, int bar, struct thread *td) 423{ 424 struct ifaddr *ifa; 425 struct tap_softc *tp = dev->si_drv1; 426 struct ifnet *ifp = tp->tap_ifp; 427 int s; 428 429 /* junk all pending output */ 430 IF_DRAIN(&ifp->if_snd); 431 432 /* 433 * do not bring the interface down, and do not anything with 434 * interface, if we are in VMnet mode. just close the device. 435 */ 436 437 mtx_lock(&tp->tap_mtx); 438 if (((tp->tap_flags & TAP_VMNET) == 0) && (ifp->if_flags & IFF_UP)) { 439 mtx_unlock(&tp->tap_mtx); 440 s = splimp(); 441 if_down(ifp); 442 if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 443 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 444 rtinit(ifa, (int)RTM_DELETE, 0); 445 } 446 if_purgeaddrs(ifp); 447 ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 448 } 449 splx(s); 450 } else 451 mtx_unlock(&tp->tap_mtx); 452 453 funsetown(&tp->tap_sigio); 454 selwakeuppri(&tp->tap_rsel, PZERO+1); 455 KNOTE_UNLOCKED(&tp->tap_rsel.si_note, 0); 456 457 mtx_lock(&tp->tap_mtx); 458 tp->tap_flags &= ~TAP_OPEN; 459 tp->tap_pid = 0; 460 mtx_unlock(&tp->tap_mtx); 461 462 knlist_destroy(&tp->tap_rsel.si_note); 463 464 TAPDEBUG("%s is closed. minor = %#x\n", 465 ifp->if_xname, minor(dev)); 466 467 return (0); 468} /* tapclose */ 469 470 471/* 472 * tapifinit 473 * 474 * network interface initialization function 475 */ 476static void 477tapifinit(void *xtp) 478{ 479 struct tap_softc *tp = (struct tap_softc *)xtp; 480 struct ifnet *ifp = tp->tap_ifp; 481 482 TAPDEBUG("initializing %s\n", ifp->if_xname); 483 484 ifp->if_drv_flags |= IFF_DRV_RUNNING; 485 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 486 487 /* attempt to start output */ 488 tapifstart(ifp); 489} /* tapifinit */ 490 491 492/* 493 * tapifioctl 494 * 495 * Process an ioctl request on network interface 496 */ 497static int 498tapifioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 499{ 500 struct tap_softc *tp = (struct tap_softc *)(ifp->if_softc); 501 struct ifstat *ifs = NULL; 502 int s, dummy; 503 504 switch (cmd) { 505 case SIOCSIFFLAGS: /* XXX -- just like vmnet does */ 506 case SIOCADDMULTI: 507 case SIOCDELMULTI: 508 break; 509 510 case SIOCGIFSTATUS: 511 s = splimp(); 512 ifs = (struct ifstat *)data; 513 dummy = strlen(ifs->ascii); 514 mtx_lock(&tp->tap_mtx); 515 if (tp->tap_pid != 0 && dummy < sizeof(ifs->ascii)) 516 snprintf(ifs->ascii + dummy, 517 sizeof(ifs->ascii) - dummy, 518 "\tOpened by PID %d\n", tp->tap_pid); 519 mtx_unlock(&tp->tap_mtx); 520 splx(s); 521 break; 522 523 default: 524 s = splimp(); 525 dummy = ether_ioctl(ifp, cmd, data); 526 splx(s); 527 return (dummy); 528 /* NOT REACHED */ 529 } 530 531 return (0); 532} /* tapifioctl */ 533 534 535/* 536 * tapifstart 537 * 538 * queue packets from higher level ready to put out 539 */ 540static void 541tapifstart(struct ifnet *ifp) 542{ 543 struct tap_softc *tp = ifp->if_softc; 544 int s; 545 546 TAPDEBUG("%s starting\n", ifp->if_xname); 547 548 /* 549 * do not junk pending output if we are in VMnet mode. 550 * XXX: can this do any harm because of queue overflow? 551 */ 552 553 mtx_lock(&tp->tap_mtx); 554 if (((tp->tap_flags & TAP_VMNET) == 0) && 555 ((tp->tap_flags & TAP_READY) != TAP_READY)) { 556 struct mbuf *m = NULL; 557 558 mtx_unlock(&tp->tap_mtx); 559 560 /* Unlocked read. */ 561 TAPDEBUG("%s not ready, tap_flags = 0x%x\n", ifp->if_xname, 562 tp->tap_flags); 563 564 s = splimp(); 565 do { 566 IF_DEQUEUE(&ifp->if_snd, m); 567 if (m != NULL) 568 m_freem(m); 569 ifp->if_oerrors ++; 570 } while (m != NULL); 571 splx(s); 572 573 return; 574 } 575 mtx_unlock(&tp->tap_mtx); 576 577 s = splimp(); 578 ifp->if_drv_flags |= IFF_DRV_OACTIVE; 579 580 if (ifp->if_snd.ifq_len != 0) { 581 mtx_lock(&tp->tap_mtx); 582 if (tp->tap_flags & TAP_RWAIT) { 583 tp->tap_flags &= ~TAP_RWAIT; 584 wakeup(tp); 585 } 586 587 if ((tp->tap_flags & TAP_ASYNC) && (tp->tap_sigio != NULL)) { 588 mtx_unlock(&tp->tap_mtx); 589 pgsigio(&tp->tap_sigio, SIGIO, 0); 590 } else 591 mtx_unlock(&tp->tap_mtx); 592 593 selwakeuppri(&tp->tap_rsel, PZERO+1); 594 KNOTE_UNLOCKED(&tp->tap_rsel.si_note, 0); 595 ifp->if_opackets ++; /* obytes are counted in ether_output */ 596 } 597 598 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 599 splx(s); 600} /* tapifstart */ 601 602 603/* 604 * tapioctl 605 * 606 * the cdevsw interface is now pretty minimal 607 */ 608static int 609tapioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) 610{ 611 struct tap_softc *tp = dev->si_drv1; 612 struct ifnet *ifp = tp->tap_ifp; 613 struct tapinfo *tapp = NULL; 614 int s; 615 int f; 616 617 switch (cmd) { 618 case TAPSIFINFO: 619 s = splimp(); 620 tapp = (struct tapinfo *)data; 621 ifp->if_mtu = tapp->mtu; 622 ifp->if_type = tapp->type; 623 ifp->if_baudrate = tapp->baudrate; 624 splx(s); 625 break; 626 627 case TAPGIFINFO: 628 tapp = (struct tapinfo *)data; 629 tapp->mtu = ifp->if_mtu; 630 tapp->type = ifp->if_type; 631 tapp->baudrate = ifp->if_baudrate; 632 break; 633 634 case TAPSDEBUG: 635 tapdebug = *(intptr_t *)data; 636 break; 637 638 case TAPGDEBUG: 639 *(intptr_t *)data = tapdebug; 640 break; 641 642 case FIONBIO: 643 break; 644 645 case FIOASYNC: 646 s = splimp(); 647 mtx_lock(&tp->tap_mtx); 648 if (*(intptr_t *)data) 649 tp->tap_flags |= TAP_ASYNC; 650 else 651 tp->tap_flags &= ~TAP_ASYNC; 652 mtx_unlock(&tp->tap_mtx); 653 splx(s); 654 break; 655 656 case FIONREAD: 657 s = splimp(); 658 if (ifp->if_snd.ifq_head) { 659 struct mbuf *mb = ifp->if_snd.ifq_head; 660 661 for(*(intptr_t *)data = 0;mb != NULL;mb = mb->m_next) 662 *(intptr_t *)data += mb->m_len; 663 } else 664 *(intptr_t *)data = 0; 665 splx(s); 666 break; 667 668 case FIOSETOWN: 669 return (fsetown(*(intptr_t *)data, &tp->tap_sigio)); 670 671 case FIOGETOWN: 672 *(intptr_t *)data = fgetown(&tp->tap_sigio); 673 return (0); 674 675 /* this is deprecated, FIOSETOWN should be used instead */ 676 case TIOCSPGRP: 677 return (fsetown(-(*(intptr_t *)data), &tp->tap_sigio)); 678 679 /* this is deprecated, FIOGETOWN should be used instead */ 680 case TIOCGPGRP: 681 *(intptr_t *)data = -fgetown(&tp->tap_sigio); 682 return (0); 683 684 /* VMware/VMnet port ioctl's */ 685 686 case SIOCGIFFLAGS: /* get ifnet flags */ 687 bcopy(&ifp->if_flags, data, sizeof(ifp->if_flags)); 688 break; 689 690 case VMIO_SIOCSIFFLAGS: /* VMware/VMnet SIOCSIFFLAGS */ 691 f = *(intptr_t *)data; 692 f &= 0x0fff; 693 f &= ~IFF_CANTCHANGE; 694 f |= IFF_UP; 695 696 s = splimp(); 697 ifp->if_flags = f | (ifp->if_flags & IFF_CANTCHANGE); 698 splx(s); 699 break; 700 701 case OSIOCGIFADDR: /* get MAC address of the remote side */ 702 case SIOCGIFADDR: 703 mtx_lock(&tp->tap_mtx); 704 bcopy(tp->ether_addr, data, sizeof(tp->ether_addr)); 705 mtx_unlock(&tp->tap_mtx); 706 break; 707 708 case SIOCSIFADDR: /* set MAC address of the remote side */ 709 mtx_lock(&tp->tap_mtx); 710 bcopy(data, tp->ether_addr, sizeof(tp->ether_addr)); 711 mtx_unlock(&tp->tap_mtx); 712 break; 713 714 default: 715 return (ENOTTY); 716 } 717 return (0); 718} /* tapioctl */ 719 720 721/* 722 * tapread 723 * 724 * the cdevsw read interface - reads a packet at a time, or at 725 * least as much of a packet as can be read 726 */ 727static int 728tapread(struct cdev *dev, struct uio *uio, int flag) 729{ 730 struct tap_softc *tp = dev->si_drv1; 731 struct ifnet *ifp = tp->tap_ifp; 732 struct mbuf *m = NULL; 733 int error = 0, len, s; 734 735 TAPDEBUG("%s reading, minor = %#x\n", ifp->if_xname, minor(dev)); 736 737 mtx_lock(&tp->tap_mtx); 738 if ((tp->tap_flags & TAP_READY) != TAP_READY) { 739 mtx_unlock(&tp->tap_mtx); 740 741 /* Unlocked read. */ 742 TAPDEBUG("%s not ready. minor = %#x, tap_flags = 0x%x\n", 743 ifp->if_xname, minor(dev), tp->tap_flags); 744 745 return (EHOSTDOWN); 746 } 747 748 tp->tap_flags &= ~TAP_RWAIT; 749 mtx_unlock(&tp->tap_mtx); 750 751 /* sleep until we get a packet */ 752 do { 753 s = splimp(); 754 IF_DEQUEUE(&ifp->if_snd, m); 755 splx(s); 756 757 if (m == NULL) { 758 if (flag & O_NONBLOCK) 759 return (EWOULDBLOCK); 760 761 mtx_lock(&tp->tap_mtx); 762 tp->tap_flags |= TAP_RWAIT; 763 mtx_unlock(&tp->tap_mtx); 764 error = tsleep(tp,PCATCH|(PZERO+1),"taprd",0); 765 if (error) 766 return (error); 767 } 768 } while (m == NULL); 769 770 /* feed packet to bpf */ 771 BPF_MTAP(ifp, m); 772 773 /* xfer packet to user space */ 774 while ((m != NULL) && (uio->uio_resid > 0) && (error == 0)) { 775 len = min(uio->uio_resid, m->m_len); 776 if (len == 0) 777 break; 778 779 error = uiomove(mtod(m, void *), len, uio); 780 m = m_free(m); 781 } 782 783 if (m != NULL) { 784 TAPDEBUG("%s dropping mbuf, minor = %#x\n", ifp->if_xname, 785 minor(dev)); 786 m_freem(m); 787 } 788 789 return (error); 790} /* tapread */ 791 792 793/* 794 * tapwrite 795 * 796 * the cdevsw write interface - an atomic write is a packet - or else! 797 */ 798static int 799tapwrite(struct cdev *dev, struct uio *uio, int flag) 800{ 801 struct tap_softc *tp = dev->si_drv1; 802 struct ifnet *ifp = tp->tap_ifp; 803 struct mbuf *m; 804 int error = 0; 805 806 TAPDEBUG("%s writting, minor = %#x\n", 807 ifp->if_xname, minor(dev)); 808 809 if (uio->uio_resid == 0) 810 return (0); 811 812 if ((uio->uio_resid < 0) || (uio->uio_resid > TAPMRU)) { 813 TAPDEBUG("%s invalid packet len = %d, minor = %#x\n", 814 ifp->if_xname, uio->uio_resid, minor(dev)); 815 816 return (EIO); 817 } 818 819 if ((m = m_uiotombuf(uio, M_DONTWAIT, 0, ETHER_ALIGN)) == NULL) { 820 ifp->if_ierrors ++; 821 return (error); 822 } 823 824 m->m_pkthdr.rcvif = ifp; 825 826 /* Pass packet up to parent. */ 827 (*ifp->if_input)(ifp, m); 828 ifp->if_ipackets ++; /* ibytes are counted in parent */ 829 830 return (0); 831} /* tapwrite */ 832 833 834/* 835 * tappoll 836 * 837 * the poll interface, this is only useful on reads 838 * really. the write detect always returns true, write never blocks 839 * anyway, it either accepts the packet or drops it 840 */ 841static int 842tappoll(struct cdev *dev, int events, struct thread *td) 843{ 844 struct tap_softc *tp = dev->si_drv1; 845 struct ifnet *ifp = tp->tap_ifp; 846 int s, revents = 0; 847 848 TAPDEBUG("%s polling, minor = %#x\n", 849 ifp->if_xname, minor(dev)); 850 851 s = splimp(); 852 if (events & (POLLIN | POLLRDNORM)) { 853 if (ifp->if_snd.ifq_len > 0) { 854 TAPDEBUG("%s have data in queue. len = %d, " \ 855 "minor = %#x\n", ifp->if_xname, 856 ifp->if_snd.ifq_len, minor(dev)); 857 858 revents |= (events & (POLLIN | POLLRDNORM)); 859 } else { 860 TAPDEBUG("%s waiting for data, minor = %#x\n", 861 ifp->if_xname, minor(dev)); 862 863 selrecord(td, &tp->tap_rsel); 864 } 865 } 866 867 if (events & (POLLOUT | POLLWRNORM)) 868 revents |= (events & (POLLOUT | POLLWRNORM)); 869 870 splx(s); 871 return (revents); 872} /* tappoll */ 873 874 875/* 876 * tap_kqfilter 877 * 878 * support for kevent() system call 879 */ 880static int 881tapkqfilter(struct cdev *dev, struct knote *kn) 882{ 883 int s; 884 struct tap_softc *tp = dev->si_drv1; 885 struct ifnet *ifp = tp->tap_ifp; 886 887 s = splimp(); 888 switch (kn->kn_filter) { 889 case EVFILT_READ: 890 TAPDEBUG("%s kqfilter: EVFILT_READ, minor = %#x\n", 891 ifp->if_xname, minor(dev)); 892 kn->kn_fop = &tap_read_filterops; 893 break; 894 895 case EVFILT_WRITE: 896 TAPDEBUG("%s kqfilter: EVFILT_WRITE, minor = %#x\n", 897 ifp->if_xname, minor(dev)); 898 kn->kn_fop = &tap_write_filterops; 899 break; 900 901 default: 902 TAPDEBUG("%s kqfilter: invalid filter, minor = %#x\n", 903 ifp->if_xname, minor(dev)); 904 splx(s); 905 return (EINVAL); 906 /* NOT REACHED */ 907 } 908 splx(s); 909 910 kn->kn_hook = (caddr_t) dev; 911 knlist_add(&tp->tap_rsel.si_note, kn, 0); 912 913 return (0); 914} /* tapkqfilter */ 915 916 917/* 918 * tap_kqread 919 * 920 * Return true if there is data in the interface queue 921 */ 922static int 923tapkqread(struct knote *kn, long hint) 924{ 925 int ret, s; 926 struct cdev *dev = (struct cdev *)(kn->kn_hook); 927 struct tap_softc *tp = dev->si_drv1; 928 struct ifnet *ifp = tp->tap_ifp; 929 930 s = splimp(); 931 if ((kn->kn_data = ifp->if_snd.ifq_len) > 0) { 932 TAPDEBUG("%s have data in queue. len = %d, minor = %#x\n", 933 ifp->if_xname, ifp->if_snd.ifq_len, minor(dev)); 934 ret = 1; 935 } else { 936 TAPDEBUG("%s waiting for data, minor = %#x\n", 937 ifp->if_xname, minor(dev)); 938 ret = 0; 939 } 940 splx(s); 941 942 return (ret); 943} /* tapkqread */ 944 945 946/* 947 * tap_kqwrite 948 * 949 * Always can write. Return the MTU in kn->data 950 */ 951static int 952tapkqwrite(struct knote *kn, long hint) 953{ 954 int s; 955 struct tap_softc *tp = ((struct cdev *) kn->kn_hook)->si_drv1; 956 struct ifnet *ifp = tp->tap_ifp; 957 958 s = splimp(); 959 kn->kn_data = ifp->if_mtu; 960 splx(s); 961 962 return (1); 963} /* tapkqwrite */ 964 965 966static void 967tapkqdetach(struct knote *kn) 968{ 969 struct tap_softc *tp = ((struct cdev *) kn->kn_hook)->si_drv1; 970 971 knlist_remove(&tp->tap_rsel.si_note, kn, 0); 972} /* tapkqdetach */ 973 974