1 /* 2 * Copyright (C) 1999-2000 by Maksim Yevmenkin <m_evmenkin@yahoo.com> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * BASED ON: 27 * ------------------------------------------------------------------------- 28 * 29 * Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk> 30 * Nottingham University 1987. 31 */ 32 33 /* 34 * $FreeBSD: src/sys/net/if_tap.c,v 1.3.2.3 2002/04/14 21:41:48 luigi Exp $ 35 * $DragonFly: src/sys/net/tap/if_tap.c,v 1.2 2003/06/17 04:28:48 dillon Exp $ 36 * $Id: if_tap.c,v 0.21 2000/07/23 21:46:02 max Exp $ 37 */ 38 39 #include "opt_inet.h" 40 41 #include <sys/param.h> 42 #include <sys/conf.h> 43 #include <sys/filedesc.h> 44 #include <sys/filio.h> 45 #include <sys/kernel.h> 46 #include <sys/malloc.h> 47 #include <sys/mbuf.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 59 #include <net/bpf.h> 60 #include <net/ethernet.h> 61 #include <net/if.h> 62 #include <net/if_arp.h> 63 #include <net/route.h> 64 65 #include <netinet/in.h> 66 67 #include <net/if_tapvar.h> 68 #include <net/if_tap.h> 69 70 71 #define CDEV_NAME "tap" 72 #define CDEV_MAJOR 149 73 #define TAPDEBUG if (tapdebug) printf 74 75 #define TAP "tap" 76 #define VMNET "vmnet" 77 #define VMNET_DEV_MASK 0x00010000 78 79 /* module */ 80 static int tapmodevent __P((module_t, int, void *)); 81 82 /* device */ 83 static void tapcreate __P((dev_t)); 84 85 /* network interface */ 86 static void tapifstart __P((struct ifnet *)); 87 static int tapifioctl __P((struct ifnet *, u_long, caddr_t)); 88 static void tapifinit __P((void *)); 89 90 /* character device */ 91 static d_open_t tapopen; 92 static d_close_t tapclose; 93 static d_read_t tapread; 94 static d_write_t tapwrite; 95 static d_ioctl_t tapioctl; 96 static d_poll_t tappoll; 97 98 static struct cdevsw tap_cdevsw = { 99 /* open */ tapopen, 100 /* close */ tapclose, 101 /* read */ tapread, 102 /* write */ tapwrite, 103 /* ioctl */ tapioctl, 104 /* poll */ tappoll, 105 /* mmap */ nommap, 106 /* startegy */ nostrategy, 107 /* dev name */ CDEV_NAME, 108 /* dev major */ CDEV_MAJOR, 109 /* dump */ nodump, 110 /* psize */ nopsize, 111 /* flags */ 0, 112 /* bmaj */ -1 113 }; 114 115 static int taprefcnt = 0; /* module ref. counter */ 116 static int taplastunit = -1; /* max. open unit number */ 117 static int tapdebug = 0; /* debug flag */ 118 119 MALLOC_DECLARE(M_TAP); 120 MALLOC_DEFINE(M_TAP, CDEV_NAME, "Ethernet tunnel interface"); 121 SYSCTL_INT(_debug, OID_AUTO, if_tap_debug, CTLFLAG_RW, &tapdebug, 0, ""); 122 DEV_MODULE(if_tap, tapmodevent, NULL); 123 124 /* 125 * tapmodevent 126 * 127 * module event handler 128 */ 129 static int 130 tapmodevent(mod, type, data) 131 module_t mod; 132 int type; 133 void *data; 134 { 135 static int attached = 0; 136 struct ifnet *ifp = NULL; 137 int unit, s; 138 139 switch (type) { 140 case MOD_LOAD: 141 if (attached) 142 return (EEXIST); 143 144 cdevsw_add(&tap_cdevsw); 145 attached = 1; 146 break; 147 148 case MOD_UNLOAD: 149 if (taprefcnt > 0) 150 return (EBUSY); 151 152 cdevsw_remove(&tap_cdevsw); 153 154 unit = 0; 155 while (unit <= taplastunit) { 156 s = splimp(); 157 TAILQ_FOREACH(ifp, &ifnet, if_link) 158 if ((strcmp(ifp->if_name, TAP) == 0) || 159 (strcmp(ifp->if_name, VMNET) == 0)) 160 if (ifp->if_unit == unit) 161 break; 162 splx(s); 163 164 if (ifp != NULL) { 165 struct tap_softc *tp = ifp->if_softc; 166 167 TAPDEBUG("detaching %s%d. minor = %#x, " \ 168 "taplastunit = %d\n", 169 ifp->if_name, unit, minor(tp->tap_dev), 170 taplastunit); 171 172 s = splimp(); 173 ether_ifdetach(ifp, 1); 174 splx(s); 175 destroy_dev(tp->tap_dev); 176 free(tp, M_TAP); 177 } 178 else 179 unit ++; 180 } 181 182 attached = 0; 183 break; 184 185 default: 186 return (EOPNOTSUPP); 187 } 188 189 return (0); 190 } /* tapmodevent */ 191 192 193 /* 194 * tapcreate 195 * 196 * to create interface 197 */ 198 static void 199 tapcreate(dev) 200 dev_t dev; 201 { 202 struct ifnet *ifp = NULL; 203 struct tap_softc *tp = NULL; 204 unsigned short macaddr_hi; 205 int unit, s; 206 char *name = NULL; 207 208 /* allocate driver storage and create device */ 209 MALLOC(tp, struct tap_softc *, sizeof(*tp), M_TAP, M_WAITOK); 210 bzero(tp, sizeof(*tp)); 211 212 /* select device: tap or vmnet */ 213 if (minor(dev) & VMNET_DEV_MASK) { 214 name = VMNET; 215 unit = lminor(dev) & 0xff; 216 tp->tap_flags |= TAP_VMNET; 217 } 218 else { 219 name = TAP; 220 unit = lminor(dev); 221 } 222 223 tp->tap_dev = make_dev(&tap_cdevsw, minor(dev), UID_ROOT, GID_WHEEL, 224 0600, "%s%d", name, unit); 225 tp->tap_dev->si_drv1 = dev->si_drv1 = tp; 226 227 /* generate fake MAC address: 00 bd xx xx xx unit_no */ 228 macaddr_hi = htons(0x00bd); 229 bcopy(&macaddr_hi, &tp->arpcom.ac_enaddr[0], sizeof(short)); 230 bcopy(&ticks, &tp->arpcom.ac_enaddr[2], sizeof(long)); 231 tp->arpcom.ac_enaddr[5] = (u_char)unit; 232 233 /* fill the rest and attach interface */ 234 ifp = &tp->tap_if; 235 ifp->if_softc = tp; 236 237 ifp->if_unit = unit; 238 if (unit > taplastunit) 239 taplastunit = unit; 240 241 ifp->if_name = name; 242 ifp->if_init = tapifinit; 243 ifp->if_output = ether_output; 244 ifp->if_start = tapifstart; 245 ifp->if_ioctl = tapifioctl; 246 ifp->if_mtu = ETHERMTU; 247 ifp->if_flags = (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST); 248 ifp->if_snd.ifq_maxlen = ifqmaxlen; 249 250 s = splimp(); 251 ether_ifattach(ifp, 1); 252 splx(s); 253 254 tp->tap_flags |= TAP_INITED; 255 256 TAPDEBUG("interface %s%d created. minor = %#x\n", 257 ifp->if_name, ifp->if_unit, minor(tp->tap_dev)); 258 } /* tapcreate */ 259 260 261 /* 262 * tapopen 263 * 264 * to open tunnel. must be superuser 265 */ 266 static int 267 tapopen(dev, flag, mode, p) 268 dev_t dev; 269 int flag; 270 int mode; 271 struct proc *p; 272 { 273 struct tap_softc *tp = NULL; 274 int error; 275 276 if ((error = suser(p)) != 0) 277 return (error); 278 279 tp = dev->si_drv1; 280 if (tp == NULL) { 281 tapcreate(dev); 282 tp = dev->si_drv1; 283 } 284 285 if (tp->tap_flags & TAP_OPEN) 286 return (EBUSY); 287 288 bcopy(tp->arpcom.ac_enaddr, tp->ether_addr, sizeof(tp->ether_addr)); 289 290 tp->tap_pid = p->p_pid; 291 tp->tap_flags |= TAP_OPEN; 292 taprefcnt ++; 293 294 TAPDEBUG("%s%d is open. minor = %#x, refcnt = %d, taplastunit = %d\n", 295 tp->tap_if.if_name, tp->tap_if.if_unit, 296 minor(tp->tap_dev), taprefcnt, taplastunit); 297 298 return (0); 299 } /* tapopen */ 300 301 302 /* 303 * tapclose 304 * 305 * close the device - mark i/f down & delete routing info 306 */ 307 static int 308 tapclose(dev, foo, bar, p) 309 dev_t dev; 310 int foo; 311 int bar; 312 struct proc *p; 313 { 314 int s; 315 struct tap_softc *tp = dev->si_drv1; 316 struct ifnet *ifp = &tp->tap_if; 317 struct mbuf *m = NULL; 318 319 /* junk all pending output */ 320 321 s = splimp(); 322 do { 323 IF_DEQUEUE(&ifp->if_snd, m); 324 if (m != NULL) 325 m_freem(m); 326 } while (m != NULL); 327 splx(s); 328 329 /* 330 * do not bring the interface down, and do not anything with 331 * interface, if we are in VMnet mode. just close the device. 332 */ 333 334 if (((tp->tap_flags & TAP_VMNET) == 0) && (ifp->if_flags & IFF_UP)) { 335 s = splimp(); 336 if_down(ifp); 337 if (ifp->if_flags & IFF_RUNNING) { 338 /* find internet addresses and delete routes */ 339 struct ifaddr *ifa = NULL; 340 341 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 342 if (ifa->ifa_addr->sa_family == AF_INET) { 343 rtinit(ifa, (int)RTM_DELETE, 0); 344 345 /* remove address from interface */ 346 bzero(ifa->ifa_addr, 347 sizeof(*(ifa->ifa_addr))); 348 bzero(ifa->ifa_dstaddr, 349 sizeof(*(ifa->ifa_dstaddr))); 350 bzero(ifa->ifa_netmask, 351 sizeof(*(ifa->ifa_netmask))); 352 } 353 } 354 355 ifp->if_flags &= ~IFF_RUNNING; 356 } 357 splx(s); 358 } 359 360 funsetown(tp->tap_sigio); 361 selwakeup(&tp->tap_rsel); 362 363 tp->tap_flags &= ~TAP_OPEN; 364 tp->tap_pid = 0; 365 366 taprefcnt --; 367 if (taprefcnt < 0) { 368 taprefcnt = 0; 369 printf("%s%d minor = %#x, refcnt = %d is out of sync. " \ 370 "set refcnt to 0\n", ifp->if_name, ifp->if_unit, 371 minor(tp->tap_dev), taprefcnt); 372 } 373 374 TAPDEBUG("%s%d is closed. minor = %#x, refcnt = %d, taplastunit = %d\n", 375 ifp->if_name, ifp->if_unit, minor(tp->tap_dev), 376 taprefcnt, taplastunit); 377 378 return (0); 379 } /* tapclose */ 380 381 382 /* 383 * tapifinit 384 * 385 * network interface initialization function 386 */ 387 static void 388 tapifinit(xtp) 389 void *xtp; 390 { 391 struct tap_softc *tp = (struct tap_softc *)xtp; 392 struct ifnet *ifp = &tp->tap_if; 393 394 TAPDEBUG("initializing %s%d, minor = %#x\n", 395 ifp->if_name, ifp->if_unit, minor(tp->tap_dev)); 396 397 ifp->if_flags |= IFF_RUNNING; 398 ifp->if_flags &= ~IFF_OACTIVE; 399 400 /* attempt to start output */ 401 tapifstart(ifp); 402 } /* tapifinit */ 403 404 405 /* 406 * tapifioctl 407 * 408 * Process an ioctl request on network interface 409 */ 410 int 411 tapifioctl(ifp, cmd, data) 412 struct ifnet *ifp; 413 u_long cmd; 414 caddr_t data; 415 { 416 struct tap_softc *tp = (struct tap_softc *)(ifp->if_softc); 417 struct ifstat *ifs = NULL; 418 int s, dummy; 419 420 switch (cmd) { 421 case SIOCSIFADDR: 422 case SIOCGIFADDR: 423 case SIOCSIFMTU: 424 s = splimp(); 425 dummy = ether_ioctl(ifp, cmd, data); 426 splx(s); 427 return (dummy); 428 429 case SIOCSIFFLAGS: /* XXX -- just like vmnet does */ 430 case SIOCADDMULTI: 431 case SIOCDELMULTI: 432 break; 433 434 case SIOCGIFSTATUS: 435 s = splimp(); 436 ifs = (struct ifstat *)data; 437 dummy = strlen(ifs->ascii); 438 if (tp->tap_pid != 0 && dummy < sizeof(ifs->ascii)) 439 snprintf(ifs->ascii + dummy, 440 sizeof(ifs->ascii) - dummy, 441 "\tOpened by PID %d\n", tp->tap_pid); 442 splx(s); 443 break; 444 445 default: 446 return (EINVAL); 447 } 448 449 return (0); 450 } /* tapifioctl */ 451 452 453 /* 454 * tapifstart 455 * 456 * queue packets from higher level ready to put out 457 */ 458 static void 459 tapifstart(ifp) 460 struct ifnet *ifp; 461 { 462 struct tap_softc *tp = ifp->if_softc; 463 int s; 464 465 TAPDEBUG("%s%d starting, minor = %#x\n", 466 ifp->if_name, ifp->if_unit, minor(tp->tap_dev)); 467 468 /* 469 * do not junk pending output if we are in VMnet mode. 470 * XXX: can this do any harm because of queue overflow? 471 */ 472 473 if (((tp->tap_flags & TAP_VMNET) == 0) && 474 ((tp->tap_flags & TAP_READY) != TAP_READY)) { 475 struct mbuf *m = NULL; 476 477 TAPDEBUG("%s%d not ready. minor = %#x, tap_flags = 0x%x\n", 478 ifp->if_name, ifp->if_unit, 479 minor(tp->tap_dev), tp->tap_flags); 480 481 s = splimp(); 482 do { 483 IF_DEQUEUE(&ifp->if_snd, m); 484 if (m != NULL) 485 m_freem(m); 486 ifp->if_oerrors ++; 487 } while (m != NULL); 488 splx(s); 489 490 return; 491 } 492 493 s = splimp(); 494 ifp->if_flags |= IFF_OACTIVE; 495 496 if (ifp->if_snd.ifq_len != 0) { 497 if (tp->tap_flags & TAP_RWAIT) { 498 tp->tap_flags &= ~TAP_RWAIT; 499 wakeup((caddr_t)tp); 500 } 501 502 if ((tp->tap_flags & TAP_ASYNC) && (tp->tap_sigio != NULL)) 503 pgsigio(tp->tap_sigio, SIGIO, 0); 504 505 selwakeup(&tp->tap_rsel); 506 ifp->if_opackets ++; /* obytes are counted in ether_output */ 507 } 508 509 ifp->if_flags &= ~IFF_OACTIVE; 510 splx(s); 511 } /* tapifstart */ 512 513 514 /* 515 * tapioctl 516 * 517 * the cdevsw interface is now pretty minimal 518 */ 519 static int 520 tapioctl(dev, cmd, data, flag, p) 521 dev_t dev; 522 u_long cmd; 523 caddr_t data; 524 int flag; 525 struct proc *p; 526 { 527 struct tap_softc *tp = dev->si_drv1; 528 struct ifnet *ifp = &tp->tap_if; 529 struct tapinfo *tapp = NULL; 530 int s; 531 532 switch (cmd) { 533 case TAPSIFINFO: 534 s = splimp(); 535 tapp = (struct tapinfo *)data; 536 ifp->if_mtu = tapp->mtu; 537 ifp->if_type = tapp->type; 538 ifp->if_baudrate = tapp->baudrate; 539 splx(s); 540 break; 541 542 case TAPGIFINFO: 543 tapp = (struct tapinfo *)data; 544 tapp->mtu = ifp->if_mtu; 545 tapp->type = ifp->if_type; 546 tapp->baudrate = ifp->if_baudrate; 547 break; 548 549 case TAPSDEBUG: 550 tapdebug = *(int *)data; 551 break; 552 553 case TAPGDEBUG: 554 *(int *)data = tapdebug; 555 break; 556 557 case FIONBIO: 558 break; 559 560 case FIOASYNC: 561 s = splimp(); 562 if (*(int *)data) 563 tp->tap_flags |= TAP_ASYNC; 564 else 565 tp->tap_flags &= ~TAP_ASYNC; 566 splx(s); 567 break; 568 569 case FIONREAD: 570 s = splimp(); 571 if (ifp->if_snd.ifq_head) { 572 struct mbuf *mb = ifp->if_snd.ifq_head; 573 574 for(*(int *)data = 0;mb != NULL;mb = mb->m_next) 575 *(int *)data += mb->m_len; 576 } 577 else 578 *(int *)data = 0; 579 splx(s); 580 break; 581 582 case FIOSETOWN: 583 return (fsetown(*(int *)data, &tp->tap_sigio)); 584 585 case FIOGETOWN: 586 *(int *)data = fgetown(tp->tap_sigio); 587 return (0); 588 589 /* this is deprecated, FIOSETOWN should be used instead */ 590 case TIOCSPGRP: 591 return (fsetown(-(*(int *)data), &tp->tap_sigio)); 592 593 /* this is deprecated, FIOGETOWN should be used instead */ 594 case TIOCGPGRP: 595 *(int *)data = -fgetown(tp->tap_sigio); 596 return (0); 597 598 /* VMware/VMnet port ioctl's */ 599 600 case SIOCGIFFLAGS: /* get ifnet flags */ 601 bcopy(&ifp->if_flags, data, sizeof(ifp->if_flags)); 602 break; 603 604 case VMIO_SIOCSIFFLAGS: { /* VMware/VMnet SIOCSIFFLAGS */ 605 short f = *(short *)data; 606 607 f &= 0x0fff; 608 f &= ~IFF_CANTCHANGE; 609 f |= IFF_UP; 610 611 s = splimp(); 612 ifp->if_flags = f | (ifp->if_flags & IFF_CANTCHANGE); 613 splx(s); 614 } break; 615 616 case OSIOCGIFADDR: /* get MAC address of the remote side */ 617 case SIOCGIFADDR: 618 bcopy(tp->ether_addr, data, sizeof(tp->ether_addr)); 619 break; 620 621 case SIOCSIFADDR: /* set MAC address of the remote side */ 622 bcopy(data, tp->ether_addr, sizeof(tp->ether_addr)); 623 break; 624 625 default: 626 return (ENOTTY); 627 } 628 return (0); 629 } /* tapioctl */ 630 631 632 /* 633 * tapread 634 * 635 * the cdevsw read interface - reads a packet at a time, or at 636 * least as much of a packet as can be read 637 */ 638 static int 639 tapread(dev, uio, flag) 640 dev_t dev; 641 struct uio *uio; 642 int flag; 643 { 644 struct tap_softc *tp = dev->si_drv1; 645 struct ifnet *ifp = &tp->tap_if; 646 struct mbuf *m0 = NULL; 647 int error = 0, len, s; 648 649 TAPDEBUG("%s%d reading, minor = %#x\n", 650 ifp->if_name, ifp->if_unit, minor(tp->tap_dev)); 651 652 if ((tp->tap_flags & TAP_READY) != TAP_READY) { 653 TAPDEBUG("%s%d not ready. minor = %#x, tap_flags = 0x%x\n", 654 ifp->if_name, ifp->if_unit, 655 minor(tp->tap_dev), tp->tap_flags); 656 657 return (EHOSTDOWN); 658 } 659 660 tp->tap_flags &= ~TAP_RWAIT; 661 662 /* sleep until we get a packet */ 663 do { 664 s = splimp(); 665 IF_DEQUEUE(&ifp->if_snd, m0); 666 splx(s); 667 668 if (m0 == NULL) { 669 if (flag & IO_NDELAY) 670 return (EWOULDBLOCK); 671 672 tp->tap_flags |= TAP_RWAIT; 673 error = tsleep((caddr_t)tp,PCATCH|(PZERO+1),"taprd",0); 674 if (error) 675 return (error); 676 } 677 } while (m0 == NULL); 678 679 /* feed packet to bpf */ 680 if (ifp->if_bpf != NULL) 681 bpf_mtap(ifp, m0); 682 683 /* xfer packet to user space */ 684 while ((m0 != NULL) && (uio->uio_resid > 0) && (error == 0)) { 685 len = min(uio->uio_resid, m0->m_len); 686 if (len == 0) 687 break; 688 689 error = uiomove(mtod(m0, caddr_t), len, uio); 690 m0 = m_free(m0); 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 */ 708 static int 709 tapwrite(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 */ 789 static int 790 tappoll(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 */ 825