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