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