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 --- 17 unchanged lines hidden (view full) --- 26 * BASED ON: 27 * ------------------------------------------------------------------------- 28 * 29 * Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk> 30 * Nottingham University 1987. 31 */ 32 33/* |
34 * $FreeBSD: head/sys/net/if_tap.c 111742 2003-03-02 15:56:49Z des $ |
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> --- 33 unchanged lines hidden (view full) --- 76 77#define TAP "tap" 78#define VMNET "vmnet" 79#define TAPMAXUNIT 0x7fff 80#define VMNET_DEV_MASK 0x00800000 81 /* 0x007f00ff */ 82 83/* module */ |
84static int tapmodevent(module_t, int, void *); |
85 86/* device */ 87static void tapclone(void *, char *, int, dev_t *); 88static void tapcreate(dev_t); 89 90/* network interface */ 91static void tapifstart(struct ifnet *); 92static int tapifioctl(struct ifnet *, u_long, caddr_t); --- 108 unchanged lines hidden (view full) --- 201 202 while ((tp = SLIST_FIRST(&taphead)) != NULL) { 203 SLIST_REMOVE_HEAD(&taphead, tap_next); 204 205 ifp = &tp->tap_if; 206 207 TAPDEBUG("detaching %s%d\n", ifp->if_name,ifp->if_unit); 208 |
209 KASSERT(!(tp->tap_flags & TAP_OPEN), 210 ("%s%d flags is out of sync", ifp->if_name, |
211 ifp->if_unit)); 212 213 /* XXX makedev check? nah.. not right now :) */ 214 215 s = splimp(); 216 ether_ifdetach(ifp); 217 splx(s); 218 219 free(tp, M_TAP); 220 } 221 |
222 if (tapbasedev != NOUDEV) |
223 destroy_dev(udev2dev(tapbasedev, 0)); 224 225 226 break; 227 228 default: 229 return (EOPNOTSUPP); 230 } --- 18 unchanged lines hidden (view full) --- 249 char *device_name = name; 250 struct resource *r = NULL; 251 252 if (*dev != NODEV) 253 return; 254 255 if (strcmp(device_name, TAP) == 0) { 256 /* get first free tap unit */ |
257 r = rman_reserve_resource(tapunits, 0, TAPMAXUNIT, 1, |
258 RF_ALLOCATED | RF_ACTIVE, NULL); 259 unit = rman_get_start(r); 260 minor = unit2minor(unit); 261 } 262 else if (strcmp(device_name, VMNET) == 0) { 263 /* get first free vmnet unit */ |
264 r = rman_reserve_resource(vmnetunits, 0, TAPMAXUNIT, 1, |
265 RF_ALLOCATED | RF_ACTIVE, NULL); 266 unit = rman_get_start(r); 267 minor = unit2minor(unit) | VMNET_DEV_MASK; 268 } 269 270 if (r != NULL) { /* need cloning */ 271 TAPDEBUG("%s%d is available. minor = %#x\n", 272 device_name, unit, minor); 273 274 error = rman_release_resource(r); 275 KASSERT((error == 0), ("Could not release tap/vmnet unit")); 276 277 /* check if device for the unit has been created */ 278 *dev = makedev(CDEV_MAJOR, minor); 279 if ((*dev)->si_flags & SI_NAMED) { |
280 TAPDEBUG("%s%d device exists. minor = %#x\n", |
281 device_name, unit, minor); 282 return; /* device has been created */ 283 } 284 } else { /* try to match name/unit, first try tap then vmnet */ 285 device_name = TAP; 286 if (dev_stdclone(name, NULL, device_name, &unit) != 1) { 287 device_name = VMNET; 288 --- 45 unchanged lines hidden (view full) --- 334 name = VMNET; 335 tp->tap_flags |= TAP_VMNET; 336 } else 337 name = TAP; 338 339 TAPDEBUG("tapcreate(%s%d). minor = %#x\n", name, unit, minor(dev)); 340 341 if (!(dev->si_flags & SI_NAMED)) |
342 dev = make_dev(&tap_cdevsw, minor(dev), UID_ROOT, GID_WHEEL, |
343 0600, "%s%d", name, unit); 344 345 /* generate fake MAC address: 00 bd xx xx xx unit_no */ 346 macaddr_hi = htons(0x00bd); 347 bcopy(&macaddr_hi, &tp->arpcom.ac_enaddr[0], sizeof(short)); 348 bcopy(&ticks, &tp->arpcom.ac_enaddr[2], sizeof(long)); 349 tp->arpcom.ac_enaddr[5] = (u_char)unit; 350 |
351 /* fill the rest and attach interface */ |
352 ifp = &tp->tap_if; 353 ifp->if_softc = tp; 354 ifp->if_unit = unit; 355 ifp->if_name = name; 356 ifp->if_init = tapifinit; 357 ifp->if_start = tapifstart; 358 ifp->if_ioctl = tapifioctl; 359 ifp->if_mtu = ETHERMTU; 360 ifp->if_flags = (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST); 361 ifp->if_snd.ifq_maxlen = ifqmaxlen; 362 363 dev->si_drv1 = tp; 364 365 s = splimp(); 366 ether_ifattach(ifp, tp->arpcom.ac_enaddr); 367 splx(s); 368 369 tp->tap_flags |= TAP_INITED; 370 |
371 TAPDEBUG("interface %s%d is created. minor = %#x\n", |
372 ifp->if_name, ifp->if_unit, minor(dev)); 373} /* tapcreate */ 374 375 376/* |
377 * tapopen |
378 * 379 * to open tunnel. must be superuser 380 */ 381static int 382tapopen(dev, flag, mode, td) 383 dev_t dev; 384 int flag; 385 int mode; --- 4 unchanged lines hidden (view full) --- 390 struct resource *r = NULL; 391 392 if ((error = suser(td)) != 0) 393 return (error); 394 395 unit = dev2unit(dev) & TAPMAXUNIT; 396 397 if (minor(dev) & VMNET_DEV_MASK) |
398 r = rman_reserve_resource(vmnetunits, unit, unit, 1, |
399 RF_ALLOCATED | RF_ACTIVE, NULL); 400 else |
401 r = rman_reserve_resource(tapunits, unit, unit, 1, |
402 RF_ALLOCATED | RF_ACTIVE, NULL); 403 404 if (r == NULL) 405 return (EBUSY); 406 407 dev->si_flags &= ~SI_CHEAPCLONE; 408 409 tp = dev->si_drv1; 410 if (tp == NULL) { 411 tapcreate(dev); 412 tp = dev->si_drv1; 413 } 414 |
415 KASSERT(!(tp->tap_flags & TAP_OPEN), |
416 ("%s%d flags is out of sync", tp->tap_if.if_name, unit)); 417 418 bcopy(tp->arpcom.ac_enaddr, tp->ether_addr, sizeof(tp->ether_addr)); 419 420 tp->tap_unit = r; 421 tp->tap_pid = td->td_proc->p_pid; 422 tp->tap_flags |= TAP_OPEN; 423 |
424 TAPDEBUG("%s%d is open. minor = %#x\n", |
425 tp->tap_if.if_name, unit, minor(dev)); 426 427 return (0); 428} /* tapopen */ 429 430 431/* 432 * tapclose --- 29 unchanged lines hidden (view full) --- 462 /* find internet addresses and delete routes */ 463 struct ifaddr *ifa = NULL; 464 465 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 466 if (ifa->ifa_addr->sa_family == AF_INET) { 467 rtinit(ifa, (int)RTM_DELETE, 0); 468 469 /* remove address from interface */ |
470 bzero(ifa->ifa_addr, |
471 sizeof(*(ifa->ifa_addr))); |
472 bzero(ifa->ifa_dstaddr, |
473 sizeof(*(ifa->ifa_dstaddr))); |
474 bzero(ifa->ifa_netmask, |
475 sizeof(*(ifa->ifa_netmask))); 476 } 477 } 478 479 ifp->if_flags &= ~IFF_RUNNING; 480 } 481 splx(s); 482 } 483 484 funsetown(&tp->tap_sigio); 485 selwakeup(&tp->tap_rsel); 486 487 tp->tap_flags &= ~TAP_OPEN; 488 tp->tap_pid = 0; 489 error = rman_release_resource(tp->tap_unit); |
490 KASSERT((error == 0), 491 ("%s%d could not release unit", ifp->if_name, ifp->if_unit)); |
492 tp->tap_unit = NULL; 493 |
494 TAPDEBUG("%s%d is closed. minor = %#x\n", |
495 ifp->if_name, ifp->if_unit, minor(dev)); 496 497 return (0); 498} /* tapclose */ 499 500 501/* 502 * tapifinit --- 23 unchanged lines hidden (view full) --- 526 * Process an ioctl request on network interface 527 */ 528static int 529tapifioctl(ifp, cmd, data) 530 struct ifnet *ifp; 531 u_long cmd; 532 caddr_t data; 533{ |
534 struct tap_softc *tp = (struct tap_softc *)(ifp->if_softc); |
535 struct ifstat *ifs = NULL; 536 int s, dummy; 537 538 switch (cmd) { 539 case SIOCSIFFLAGS: /* XXX -- just like vmnet does */ 540 case SIOCADDMULTI: 541 case SIOCDELMULTI: 542 break; --- 16 unchanged lines hidden (view full) --- 559 return (dummy); 560 } 561 562 return (0); 563} /* tapifioctl */ 564 565 566/* |
567 * tapifstart 568 * |
569 * queue packets from higher level ready to put out 570 */ 571static void 572tapifstart(ifp) 573 struct ifnet *ifp; 574{ 575 struct tap_softc *tp = ifp->if_softc; 576 int s; 577 578 TAPDEBUG("%s%d starting\n", ifp->if_name, ifp->if_unit); 579 580 /* 581 * do not junk pending output if we are in VMnet mode. 582 * XXX: can this do any harm because of queue overflow? 583 */ 584 |
585 if (((tp->tap_flags & TAP_VMNET) == 0) && |
586 ((tp->tap_flags & TAP_READY) != TAP_READY)) { 587 struct mbuf *m = NULL; 588 |
589 TAPDEBUG("%s%d not ready, tap_flags = 0x%x\n", ifp->if_name, |
590 ifp->if_unit, tp->tap_flags); 591 592 s = splimp(); 593 do { 594 IF_DEQUEUE(&ifp->if_snd, m); 595 if (m != NULL) 596 m_freem(m); 597 ifp->if_oerrors ++; --- 34 unchanged lines hidden (view full) --- 632 dev_t dev; 633 u_long cmd; 634 caddr_t data; 635 int flag; 636 struct thread *td; 637{ 638 struct tap_softc *tp = dev->si_drv1; 639 struct ifnet *ifp = &tp->tap_if; |
640 struct tapinfo *tapp = NULL; |
641 int s; 642 int f; 643 644 switch (cmd) { |
645 case TAPSIFINFO: |
646 s = splimp(); |
647 tapp = (struct tapinfo *)data; 648 ifp->if_mtu = tapp->mtu; 649 ifp->if_type = tapp->type; 650 ifp->if_baudrate = tapp->baudrate; |
651 splx(s); |
652 break; |
653 |
654 case TAPGIFINFO: 655 tapp = (struct tapinfo *)data; 656 tapp->mtu = ifp->if_mtu; 657 tapp->type = ifp->if_type; 658 tapp->baudrate = ifp->if_baudrate; 659 break; |
660 661 case TAPSDEBUG: 662 tapdebug = *(int *)data; 663 break; 664 665 case TAPGDEBUG: 666 *(int *)data = tapdebug; 667 break; --- 83 unchanged lines hidden (view full) --- 751 struct uio *uio; 752 int flag; 753{ 754 struct tap_softc *tp = dev->si_drv1; 755 struct ifnet *ifp = &tp->tap_if; 756 struct mbuf *m = NULL; 757 int error = 0, len, s; 758 |
759 TAPDEBUG("%s%d reading, minor = %#x\n", |
760 ifp->if_name, ifp->if_unit, minor(dev)); 761 762 if ((tp->tap_flags & TAP_READY) != TAP_READY) { 763 TAPDEBUG("%s%d not ready. minor = %#x, tap_flags = 0x%x\n", 764 ifp->if_name, ifp->if_unit, minor(dev), tp->tap_flags); 765 766 return (EHOSTDOWN); 767 } --- 4 unchanged lines hidden (view full) --- 772 do { 773 s = splimp(); 774 IF_DEQUEUE(&ifp->if_snd, m); 775 splx(s); 776 777 if (m == NULL) { 778 if (flag & IO_NDELAY) 779 return (EWOULDBLOCK); |
780 |
781 tp->tap_flags |= TAP_RWAIT; 782 error = tsleep((caddr_t)tp,PCATCH|(PZERO+1),"taprd",0); 783 if (error) 784 return (error); 785 } 786 } while (m == NULL); 787 788 /* feed packet to bpf */ --- 5 unchanged lines hidden (view full) --- 794 if (len == 0) 795 break; 796 797 error = uiomove(mtod(m, void *), len, uio); 798 m = m_free(m); 799 } 800 801 if (m != NULL) { |
802 TAPDEBUG("%s%d dropping mbuf, minor = %#x\n", ifp->if_name, |
803 ifp->if_unit, minor(dev)); 804 m_freem(m); 805 } 806 807 return (error); 808} /* tapread */ 809 810 --- 6 unchanged lines hidden (view full) --- 817tapwrite(dev, uio, flag) 818 dev_t dev; 819 struct uio *uio; 820 int flag; 821{ 822 struct tap_softc *tp = dev->si_drv1; 823 struct ifnet *ifp = &tp->tap_if; 824 struct mbuf *top = NULL, **mp = NULL, *m = NULL; |
825 int error = 0, tlen, mlen; |
826 |
827 TAPDEBUG("%s%d writting, minor = %#x\n", |
828 ifp->if_name, ifp->if_unit, minor(dev)); 829 830 if (uio->uio_resid == 0) 831 return (0); 832 833 if ((uio->uio_resid < 0) || (uio->uio_resid > TAPMRU)) { 834 TAPDEBUG("%s%d invalid packet len = %d, minor = %#x\n", 835 ifp->if_name, ifp->if_unit, uio->uio_resid, minor(dev)); --- 28 unchanged lines hidden (view full) --- 864 ifp->if_ierrors ++; 865 if (top) 866 m_freem(top); 867 return (error); 868 } 869 870 top->m_pkthdr.len = tlen; 871 top->m_pkthdr.rcvif = ifp; |
872 |
873 /* Pass packet up to parent. */ 874 (*ifp->if_input)(ifp, top); 875 ifp->if_ipackets ++; /* ibytes are counted in parent */ 876 877 return (0); 878} /* tapwrite */ 879 880 --- 7 unchanged lines hidden (view full) --- 888static int 889tappoll(dev, events, td) 890 dev_t dev; 891 int events; 892 struct thread *td; 893{ 894 struct tap_softc *tp = dev->si_drv1; 895 struct ifnet *ifp = &tp->tap_if; |
896 int s, revents = 0; |
897 |
898 TAPDEBUG("%s%d polling, minor = %#x\n", |
899 ifp->if_name, ifp->if_unit, minor(dev)); 900 901 s = splimp(); 902 if (events & (POLLIN | POLLRDNORM)) { 903 if (ifp->if_snd.ifq_len > 0) { 904 TAPDEBUG("%s%d have data in queue. len = %d, " \ 905 "minor = %#x\n", ifp->if_name, ifp->if_unit, 906 ifp->if_snd.ifq_len, minor(dev)); --- 16 unchanged lines hidden --- |