The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/net/if_tap.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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: releng/10.1/sys/net/if_tap.c 257285 2013-10-28 22:41:36Z grehan $
   35  * $Id: if_tap.c,v 0.21 2000/07/23 21:46:02 max Exp $
   36  */
   37 
   38 #include "opt_compat.h"
   39 #include "opt_inet.h"
   40 
   41 #include <sys/param.h>
   42 #include <sys/conf.h>
   43 #include <sys/fcntl.h>
   44 #include <sys/filio.h>
   45 #include <sys/jail.h>
   46 #include <sys/kernel.h>
   47 #include <sys/malloc.h>
   48 #include <sys/mbuf.h>
   49 #include <sys/module.h>
   50 #include <sys/poll.h>
   51 #include <sys/priv.h>
   52 #include <sys/proc.h>
   53 #include <sys/selinfo.h>
   54 #include <sys/signalvar.h>
   55 #include <sys/socket.h>
   56 #include <sys/sockio.h>
   57 #include <sys/sysctl.h>
   58 #include <sys/systm.h>
   59 #include <sys/ttycom.h>
   60 #include <sys/uio.h>
   61 #include <sys/queue.h>
   62 
   63 #include <net/bpf.h>
   64 #include <net/ethernet.h>
   65 #include <net/if.h>
   66 #include <net/if_clone.h>
   67 #include <net/if_dl.h>
   68 #include <net/if_media.h>
   69 #include <net/if_types.h>
   70 #include <net/route.h>
   71 #include <net/vnet.h>
   72 
   73 #include <netinet/in.h>
   74 
   75 #include <net/if_tapvar.h>
   76 #include <net/if_tap.h>
   77 
   78 
   79 #define CDEV_NAME       "tap"
   80 #define TAPDEBUG        if (tapdebug) printf
   81 
   82 static const char tapname[] = "tap";
   83 static const char vmnetname[] = "vmnet";
   84 #define TAPMAXUNIT      0x7fff
   85 #define VMNET_DEV_MASK  CLONE_FLAG0
   86 
   87 /* module */
   88 static int              tapmodevent(module_t, int, void *);
   89 
   90 /* device */
   91 static void             tapclone(void *, struct ucred *, char *, int,
   92                             struct cdev **);
   93 static void             tapcreate(struct cdev *);
   94 
   95 /* network interface */
   96 static void             tapifstart(struct ifnet *);
   97 static int              tapifioctl(struct ifnet *, u_long, caddr_t);
   98 static void             tapifinit(void *);
   99 
  100 static int              tap_clone_create(struct if_clone *, int, caddr_t);
  101 static void             tap_clone_destroy(struct ifnet *);
  102 static struct if_clone *tap_cloner;
  103 static int              vmnet_clone_create(struct if_clone *, int, caddr_t);
  104 static void             vmnet_clone_destroy(struct ifnet *);
  105 static struct if_clone *vmnet_cloner;
  106 
  107 /* character device */
  108 static d_open_t         tapopen;
  109 static d_close_t        tapclose;
  110 static d_read_t         tapread;
  111 static d_write_t        tapwrite;
  112 static d_ioctl_t        tapioctl;
  113 static d_poll_t         tappoll;
  114 static d_kqfilter_t     tapkqfilter;
  115 
  116 /* kqueue(2) */
  117 static int              tapkqread(struct knote *, long);
  118 static int              tapkqwrite(struct knote *, long);
  119 static void             tapkqdetach(struct knote *);
  120 
  121 static struct filterops tap_read_filterops = {
  122         .f_isfd =       1,
  123         .f_attach =     NULL,
  124         .f_detach =     tapkqdetach,
  125         .f_event =      tapkqread,
  126 };
  127 
  128 static struct filterops tap_write_filterops = {
  129         .f_isfd =       1,
  130         .f_attach =     NULL,
  131         .f_detach =     tapkqdetach,
  132         .f_event =      tapkqwrite,
  133 };
  134 
  135 static struct cdevsw    tap_cdevsw = {
  136         .d_version =    D_VERSION,
  137         .d_flags =      D_NEEDMINOR,
  138         .d_open =       tapopen,
  139         .d_close =      tapclose,
  140         .d_read =       tapread,
  141         .d_write =      tapwrite,
  142         .d_ioctl =      tapioctl,
  143         .d_poll =       tappoll,
  144         .d_name =       CDEV_NAME,
  145         .d_kqfilter =   tapkqfilter,
  146 };
  147 
  148 /*
  149  * All global variables in if_tap.c are locked with tapmtx, with the
  150  * exception of tapdebug, which is accessed unlocked; tapclones is
  151  * static at runtime.
  152  */
  153 static struct mtx               tapmtx;
  154 static int                      tapdebug = 0;        /* debug flag   */
  155 static int                      tapuopen = 0;        /* allow user open() */
  156 static int                      tapuponopen = 0;    /* IFF_UP on open() */
  157 static int                      tapdclone = 1;  /* enable devfs cloning */
  158 static SLIST_HEAD(, tap_softc)  taphead;             /* first device */
  159 static struct clonedevs         *tapclones;
  160 
  161 MALLOC_DECLARE(M_TAP);
  162 MALLOC_DEFINE(M_TAP, CDEV_NAME, "Ethernet tunnel interface");
  163 SYSCTL_INT(_debug, OID_AUTO, if_tap_debug, CTLFLAG_RW, &tapdebug, 0, "");
  164 
  165 SYSCTL_DECL(_net_link);
  166 static SYSCTL_NODE(_net_link, OID_AUTO, tap, CTLFLAG_RW, 0,
  167     "Ethernet tunnel software network interface");
  168 SYSCTL_INT(_net_link_tap, OID_AUTO, user_open, CTLFLAG_RW, &tapuopen, 0,
  169         "Allow user to open /dev/tap (based on node permissions)");
  170 SYSCTL_INT(_net_link_tap, OID_AUTO, up_on_open, CTLFLAG_RW, &tapuponopen, 0,
  171         "Bring interface up when /dev/tap is opened");
  172 SYSCTL_INT(_net_link_tap, OID_AUTO, devfs_cloning, CTLFLAG_RW, &tapdclone, 0,
  173         "Enably legacy devfs interface creation");
  174 SYSCTL_INT(_net_link_tap, OID_AUTO, debug, CTLFLAG_RW, &tapdebug, 0, "");
  175 
  176 TUNABLE_INT("net.link.tap.devfs_cloning", &tapdclone);
  177 
  178 DEV_MODULE(if_tap, tapmodevent, NULL);
  179 
  180 static int
  181 tap_clone_create(struct if_clone *ifc, int unit, caddr_t params)
  182 {
  183         struct cdev *dev;
  184         int i;
  185 
  186         /* Find any existing device, or allocate new unit number. */
  187         i = clone_create(&tapclones, &tap_cdevsw, &unit, &dev, 0);
  188         if (i) {
  189                 dev = make_dev(&tap_cdevsw, unit, UID_ROOT, GID_WHEEL, 0600,
  190                     "%s%d", tapname, unit);
  191         }
  192 
  193         tapcreate(dev);
  194         return (0);
  195 }
  196 
  197 /* vmnet devices are tap devices in disguise */
  198 static int
  199 vmnet_clone_create(struct if_clone *ifc, int unit, caddr_t params)
  200 {
  201         struct cdev *dev;
  202         int i;
  203 
  204         /* Find any existing device, or allocate new unit number. */
  205         i = clone_create(&tapclones, &tap_cdevsw, &unit, &dev, VMNET_DEV_MASK);
  206         if (i) {
  207                 dev = make_dev(&tap_cdevsw, unit | VMNET_DEV_MASK, UID_ROOT,
  208                     GID_WHEEL, 0600, "%s%d", vmnetname, unit);
  209         }
  210 
  211         tapcreate(dev);
  212         return (0);
  213 }
  214 
  215 static void
  216 tap_destroy(struct tap_softc *tp)
  217 {
  218         struct ifnet *ifp = tp->tap_ifp;
  219 
  220         CURVNET_SET(ifp->if_vnet);
  221         destroy_dev(tp->tap_dev);
  222         seldrain(&tp->tap_rsel);
  223         knlist_clear(&tp->tap_rsel.si_note, 0);
  224         knlist_destroy(&tp->tap_rsel.si_note);
  225         ether_ifdetach(ifp);
  226         if_free(ifp);
  227 
  228         mtx_destroy(&tp->tap_mtx);
  229         free(tp, M_TAP);
  230         CURVNET_RESTORE();
  231 }
  232 
  233 static void
  234 tap_clone_destroy(struct ifnet *ifp)
  235 {
  236         struct tap_softc *tp = ifp->if_softc;
  237 
  238         mtx_lock(&tapmtx);
  239         SLIST_REMOVE(&taphead, tp, tap_softc, tap_next);
  240         mtx_unlock(&tapmtx);
  241         tap_destroy(tp);
  242 }
  243 
  244 /* vmnet devices are tap devices in disguise */
  245 static void
  246 vmnet_clone_destroy(struct ifnet *ifp)
  247 {
  248         tap_clone_destroy(ifp);
  249 }
  250 
  251 /*
  252  * tapmodevent
  253  *
  254  * module event handler
  255  */
  256 static int
  257 tapmodevent(module_t mod, int type, void *data)
  258 {
  259         static eventhandler_tag  eh_tag = NULL;
  260         struct tap_softc        *tp = NULL;
  261         struct ifnet            *ifp = NULL;
  262 
  263         switch (type) {
  264         case MOD_LOAD:
  265 
  266                 /* intitialize device */
  267 
  268                 mtx_init(&tapmtx, "tapmtx", NULL, MTX_DEF);
  269                 SLIST_INIT(&taphead);
  270 
  271                 clone_setup(&tapclones);
  272                 eh_tag = EVENTHANDLER_REGISTER(dev_clone, tapclone, 0, 1000);
  273                 if (eh_tag == NULL) {
  274                         clone_cleanup(&tapclones);
  275                         mtx_destroy(&tapmtx);
  276                         return (ENOMEM);
  277                 }
  278                 tap_cloner = if_clone_simple(tapname, tap_clone_create,
  279                     tap_clone_destroy, 0);
  280                 vmnet_cloner = if_clone_simple(vmnetname, vmnet_clone_create,
  281                     vmnet_clone_destroy, 0);
  282                 return (0);
  283 
  284         case MOD_UNLOAD:
  285                 /*
  286                  * The EBUSY algorithm here can't quite atomically
  287                  * guarantee that this is race-free since we have to
  288                  * release the tap mtx to deregister the clone handler.
  289                  */
  290                 mtx_lock(&tapmtx);
  291                 SLIST_FOREACH(tp, &taphead, tap_next) {
  292                         mtx_lock(&tp->tap_mtx);
  293                         if (tp->tap_flags & TAP_OPEN) {
  294                                 mtx_unlock(&tp->tap_mtx);
  295                                 mtx_unlock(&tapmtx);
  296                                 return (EBUSY);
  297                         }
  298                         mtx_unlock(&tp->tap_mtx);
  299                 }
  300                 mtx_unlock(&tapmtx);
  301 
  302                 EVENTHANDLER_DEREGISTER(dev_clone, eh_tag);
  303                 if_clone_detach(tap_cloner);
  304                 if_clone_detach(vmnet_cloner);
  305                 drain_dev_clone_events();
  306 
  307                 mtx_lock(&tapmtx);
  308                 while ((tp = SLIST_FIRST(&taphead)) != NULL) {
  309                         SLIST_REMOVE_HEAD(&taphead, tap_next);
  310                         mtx_unlock(&tapmtx);
  311 
  312                         ifp = tp->tap_ifp;
  313 
  314                         TAPDEBUG("detaching %s\n", ifp->if_xname);
  315 
  316                         tap_destroy(tp);
  317                         mtx_lock(&tapmtx);
  318                 }
  319                 mtx_unlock(&tapmtx);
  320                 clone_cleanup(&tapclones);
  321 
  322                 mtx_destroy(&tapmtx);
  323 
  324                 break;
  325 
  326         default:
  327                 return (EOPNOTSUPP);
  328         }
  329 
  330         return (0);
  331 } /* tapmodevent */
  332 
  333 
  334 /*
  335  * DEVFS handler
  336  *
  337  * We need to support two kind of devices - tap and vmnet
  338  */
  339 static void
  340 tapclone(void *arg, struct ucred *cred, char *name, int namelen, struct cdev **dev)
  341 {
  342         char            devname[SPECNAMELEN + 1];
  343         int             i, unit, append_unit;
  344         int             extra;
  345 
  346         if (*dev != NULL)
  347                 return;
  348 
  349         if (!tapdclone ||
  350             (!tapuopen && priv_check_cred(cred, PRIV_NET_IFCREATE, 0) != 0))
  351                 return;
  352 
  353         unit = 0;
  354         append_unit = 0;
  355         extra = 0;
  356 
  357         /* We're interested in only tap/vmnet devices. */
  358         if (strcmp(name, tapname) == 0) {
  359                 unit = -1;
  360         } else if (strcmp(name, vmnetname) == 0) {
  361                 unit = -1;
  362                 extra = VMNET_DEV_MASK;
  363         } else if (dev_stdclone(name, NULL, tapname, &unit) != 1) {
  364                 if (dev_stdclone(name, NULL, vmnetname, &unit) != 1) {
  365                         return;
  366                 } else {
  367                         extra = VMNET_DEV_MASK;
  368                 }
  369         }
  370 
  371         if (unit == -1)
  372                 append_unit = 1;
  373 
  374         CURVNET_SET(CRED_TO_VNET(cred));
  375         /* find any existing device, or allocate new unit number */
  376         i = clone_create(&tapclones, &tap_cdevsw, &unit, dev, extra);
  377         if (i) {
  378                 if (append_unit) {
  379                         /*
  380                          * We were passed 'tun' or 'tap', with no unit specified
  381                          * so we'll need to append it now.
  382                          */
  383                         namelen = snprintf(devname, sizeof(devname), "%s%d", name,
  384                             unit);
  385                         name = devname;
  386                 }
  387 
  388                 *dev = make_dev_credf(MAKEDEV_REF, &tap_cdevsw, unit | extra,
  389                      cred, UID_ROOT, GID_WHEEL, 0600, "%s", name);
  390         }
  391 
  392         if_clone_create(name, namelen, NULL);
  393         CURVNET_RESTORE();
  394 } /* tapclone */
  395 
  396 
  397 /*
  398  * tapcreate
  399  *
  400  * to create interface
  401  */
  402 static void
  403 tapcreate(struct cdev *dev)
  404 {
  405         struct ifnet            *ifp = NULL;
  406         struct tap_softc        *tp = NULL;
  407         unsigned short           macaddr_hi;
  408         uint32_t                 macaddr_mid;
  409         int                      unit;
  410         const char              *name = NULL;
  411         u_char                  eaddr[6];
  412 
  413         /* allocate driver storage and create device */
  414         tp = malloc(sizeof(*tp), M_TAP, M_WAITOK | M_ZERO);
  415         mtx_init(&tp->tap_mtx, "tap_mtx", NULL, MTX_DEF);
  416         mtx_lock(&tapmtx);
  417         SLIST_INSERT_HEAD(&taphead, tp, tap_next);
  418         mtx_unlock(&tapmtx);
  419 
  420         unit = dev2unit(dev);
  421 
  422         /* select device: tap or vmnet */
  423         if (unit & VMNET_DEV_MASK) {
  424                 name = vmnetname;
  425                 tp->tap_flags |= TAP_VMNET;
  426         } else
  427                 name = tapname;
  428 
  429         unit &= TAPMAXUNIT;
  430 
  431         TAPDEBUG("tapcreate(%s%d). minor = %#x\n", name, unit, dev2unit(dev));
  432 
  433         /* generate fake MAC address: 00 bd xx xx xx unit_no */
  434         macaddr_hi = htons(0x00bd);
  435         macaddr_mid = (uint32_t) ticks;
  436         bcopy(&macaddr_hi, eaddr, sizeof(short));
  437         bcopy(&macaddr_mid, &eaddr[2], sizeof(uint32_t));
  438         eaddr[5] = (u_char)unit;
  439 
  440         /* fill the rest and attach interface */
  441         ifp = tp->tap_ifp = if_alloc(IFT_ETHER);
  442         if (ifp == NULL)
  443                 panic("%s%d: can not if_alloc()", name, unit);
  444         ifp->if_softc = tp;
  445         if_initname(ifp, name, unit);
  446         ifp->if_init = tapifinit;
  447         ifp->if_start = tapifstart;
  448         ifp->if_ioctl = tapifioctl;
  449         ifp->if_mtu = ETHERMTU;
  450         ifp->if_flags = (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST);
  451         IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
  452         ifp->if_capabilities |= IFCAP_LINKSTATE;
  453         ifp->if_capenable |= IFCAP_LINKSTATE;
  454 
  455         dev->si_drv1 = tp;
  456         tp->tap_dev = dev;
  457 
  458         ether_ifattach(ifp, eaddr);
  459 
  460         mtx_lock(&tp->tap_mtx);
  461         tp->tap_flags |= TAP_INITED;
  462         mtx_unlock(&tp->tap_mtx);
  463 
  464         knlist_init_mtx(&tp->tap_rsel.si_note, &tp->tap_mtx);
  465 
  466         TAPDEBUG("interface %s is created. minor = %#x\n", 
  467                 ifp->if_xname, dev2unit(dev));
  468 } /* tapcreate */
  469 
  470 
  471 /*
  472  * tapopen
  473  *
  474  * to open tunnel. must be superuser
  475  */
  476 static int
  477 tapopen(struct cdev *dev, int flag, int mode, struct thread *td)
  478 {
  479         struct tap_softc        *tp = NULL;
  480         struct ifnet            *ifp = NULL;
  481         int                      error;
  482 
  483         if (tapuopen == 0) {
  484                 error = priv_check(td, PRIV_NET_TAP);
  485                 if (error)
  486                         return (error);
  487         }
  488 
  489         if ((dev2unit(dev) & CLONE_UNITMASK) > TAPMAXUNIT)
  490                 return (ENXIO);
  491 
  492         tp = dev->si_drv1;
  493 
  494         mtx_lock(&tp->tap_mtx);
  495         if (tp->tap_flags & TAP_OPEN) {
  496                 mtx_unlock(&tp->tap_mtx);
  497                 return (EBUSY);
  498         }
  499 
  500         bcopy(IF_LLADDR(tp->tap_ifp), tp->ether_addr, sizeof(tp->ether_addr));
  501         tp->tap_pid = td->td_proc->p_pid;
  502         tp->tap_flags |= TAP_OPEN;
  503         ifp = tp->tap_ifp;
  504 
  505         ifp->if_drv_flags |= IFF_DRV_RUNNING;
  506         ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
  507         if (tapuponopen)
  508                 ifp->if_flags |= IFF_UP;
  509         if_link_state_change(ifp, LINK_STATE_UP);
  510         mtx_unlock(&tp->tap_mtx);
  511 
  512         TAPDEBUG("%s is open. minor = %#x\n", ifp->if_xname, dev2unit(dev));
  513 
  514         return (0);
  515 } /* tapopen */
  516 
  517 
  518 /*
  519  * tapclose
  520  *
  521  * close the device - mark i/f down & delete routing info
  522  */
  523 static int
  524 tapclose(struct cdev *dev, int foo, int bar, struct thread *td)
  525 {
  526         struct ifaddr           *ifa;
  527         struct tap_softc        *tp = dev->si_drv1;
  528         struct ifnet            *ifp = tp->tap_ifp;
  529 
  530         /* junk all pending output */
  531         mtx_lock(&tp->tap_mtx);
  532         CURVNET_SET(ifp->if_vnet);
  533         IF_DRAIN(&ifp->if_snd);
  534 
  535         /*
  536          * do not bring the interface down, and do not anything with
  537          * interface, if we are in VMnet mode. just close the device.
  538          */
  539 
  540         if (((tp->tap_flags & TAP_VMNET) == 0) && (ifp->if_flags & IFF_UP)) {
  541                 mtx_unlock(&tp->tap_mtx);
  542                 if_down(ifp);
  543                 mtx_lock(&tp->tap_mtx);
  544                 if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
  545                         ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
  546                         mtx_unlock(&tp->tap_mtx);
  547                         TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
  548                                 rtinit(ifa, (int)RTM_DELETE, 0);
  549                         }
  550                         if_purgeaddrs(ifp);
  551                         mtx_lock(&tp->tap_mtx);
  552                 }
  553         }
  554 
  555         if_link_state_change(ifp, LINK_STATE_DOWN);
  556         CURVNET_RESTORE();
  557 
  558         funsetown(&tp->tap_sigio);
  559         selwakeuppri(&tp->tap_rsel, PZERO+1);
  560         KNOTE_LOCKED(&tp->tap_rsel.si_note, 0);
  561 
  562         tp->tap_flags &= ~TAP_OPEN;
  563         tp->tap_pid = 0;
  564         mtx_unlock(&tp->tap_mtx);
  565 
  566         TAPDEBUG("%s is closed. minor = %#x\n", 
  567                 ifp->if_xname, dev2unit(dev));
  568 
  569         return (0);
  570 } /* tapclose */
  571 
  572 
  573 /*
  574  * tapifinit
  575  *
  576  * network interface initialization function
  577  */
  578 static void
  579 tapifinit(void *xtp)
  580 {
  581         struct tap_softc        *tp = (struct tap_softc *)xtp;
  582         struct ifnet            *ifp = tp->tap_ifp;
  583 
  584         TAPDEBUG("initializing %s\n", ifp->if_xname);
  585 
  586         mtx_lock(&tp->tap_mtx);
  587         ifp->if_drv_flags |= IFF_DRV_RUNNING;
  588         ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
  589         mtx_unlock(&tp->tap_mtx);
  590 
  591         /* attempt to start output */
  592         tapifstart(ifp);
  593 } /* tapifinit */
  594 
  595 
  596 /*
  597  * tapifioctl
  598  *
  599  * Process an ioctl request on network interface
  600  */
  601 static int
  602 tapifioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
  603 {
  604         struct tap_softc        *tp = ifp->if_softc;
  605         struct ifreq            *ifr = (struct ifreq *)data;
  606         struct ifstat           *ifs = NULL;
  607         struct ifmediareq       *ifmr = NULL;
  608         int                      dummy, error = 0;
  609 
  610         switch (cmd) {
  611                 case SIOCSIFFLAGS: /* XXX -- just like vmnet does */
  612                 case SIOCADDMULTI:
  613                 case SIOCDELMULTI:
  614                         break;
  615 
  616                 case SIOCGIFMEDIA:
  617                         ifmr = (struct ifmediareq *)data;
  618                         dummy = ifmr->ifm_count;
  619                         ifmr->ifm_count = 1;
  620                         ifmr->ifm_status = IFM_AVALID;
  621                         ifmr->ifm_active = IFM_ETHER;
  622                         if (tp->tap_flags & TAP_OPEN)
  623                                 ifmr->ifm_status |= IFM_ACTIVE;
  624                         ifmr->ifm_current = ifmr->ifm_active;
  625                         if (dummy >= 1) {
  626                                 int media = IFM_ETHER;
  627                                 error = copyout(&media, ifmr->ifm_ulist,
  628                                     sizeof(int));
  629                         }
  630                         break;
  631 
  632                 case SIOCSIFMTU:
  633                         ifp->if_mtu = ifr->ifr_mtu;
  634                         break;
  635 
  636                 case SIOCGIFSTATUS:
  637                         ifs = (struct ifstat *)data;
  638                         dummy = strlen(ifs->ascii);
  639                         mtx_lock(&tp->tap_mtx);
  640                         if (tp->tap_pid != 0 && dummy < sizeof(ifs->ascii))
  641                                 snprintf(ifs->ascii + dummy,
  642                                         sizeof(ifs->ascii) - dummy,
  643                                         "\tOpened by PID %d\n", tp->tap_pid);
  644                         mtx_unlock(&tp->tap_mtx);
  645                         break;
  646 
  647                 default:
  648                         error = ether_ioctl(ifp, cmd, data);
  649                         break;
  650         }
  651 
  652         return (error);
  653 } /* tapifioctl */
  654 
  655 
  656 /*
  657  * tapifstart
  658  *
  659  * queue packets from higher level ready to put out
  660  */
  661 static void
  662 tapifstart(struct ifnet *ifp)
  663 {
  664         struct tap_softc        *tp = ifp->if_softc;
  665 
  666         TAPDEBUG("%s starting\n", ifp->if_xname);
  667 
  668         /*
  669          * do not junk pending output if we are in VMnet mode.
  670          * XXX: can this do any harm because of queue overflow?
  671          */
  672 
  673         mtx_lock(&tp->tap_mtx);
  674         if (((tp->tap_flags & TAP_VMNET) == 0) &&
  675             ((tp->tap_flags & TAP_READY) != TAP_READY)) {
  676                 struct mbuf *m;
  677 
  678                 /* Unlocked read. */
  679                 TAPDEBUG("%s not ready, tap_flags = 0x%x\n", ifp->if_xname, 
  680                     tp->tap_flags);
  681 
  682                 for (;;) {
  683                         IF_DEQUEUE(&ifp->if_snd, m);
  684                         if (m != NULL) {
  685                                 m_freem(m);
  686                                 ifp->if_oerrors++;
  687                         } else
  688                                 break;
  689                 }
  690                 mtx_unlock(&tp->tap_mtx);
  691 
  692                 return;
  693         }
  694 
  695         ifp->if_drv_flags |= IFF_DRV_OACTIVE;
  696 
  697         if (!IFQ_IS_EMPTY(&ifp->if_snd)) {
  698                 if (tp->tap_flags & TAP_RWAIT) {
  699                         tp->tap_flags &= ~TAP_RWAIT;
  700                         wakeup(tp);
  701                 }
  702 
  703                 if ((tp->tap_flags & TAP_ASYNC) && (tp->tap_sigio != NULL)) {
  704                         mtx_unlock(&tp->tap_mtx);
  705                         pgsigio(&tp->tap_sigio, SIGIO, 0);
  706                         mtx_lock(&tp->tap_mtx);
  707                 }
  708 
  709                 selwakeuppri(&tp->tap_rsel, PZERO+1);
  710                 KNOTE_LOCKED(&tp->tap_rsel.si_note, 0);
  711                 ifp->if_opackets ++; /* obytes are counted in ether_output */
  712         }
  713 
  714         ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
  715         mtx_unlock(&tp->tap_mtx);
  716 } /* tapifstart */
  717 
  718 
  719 /*
  720  * tapioctl
  721  *
  722  * the cdevsw interface is now pretty minimal
  723  */
  724 static int
  725 tapioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
  726 {
  727         struct tap_softc        *tp = dev->si_drv1;
  728         struct ifnet            *ifp = tp->tap_ifp;
  729         struct tapinfo          *tapp = NULL;
  730         int                      f;
  731 #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
  732     defined(COMPAT_FREEBSD4)
  733         int                      ival;
  734 #endif
  735 
  736         switch (cmd) {
  737                 case TAPSIFINFO:
  738                         tapp = (struct tapinfo *)data;
  739                         mtx_lock(&tp->tap_mtx);
  740                         ifp->if_mtu = tapp->mtu;
  741                         ifp->if_type = tapp->type;
  742                         ifp->if_baudrate = tapp->baudrate;
  743                         mtx_unlock(&tp->tap_mtx);
  744                         break;
  745 
  746                 case TAPGIFINFO:
  747                         tapp = (struct tapinfo *)data;
  748                         mtx_lock(&tp->tap_mtx);
  749                         tapp->mtu = ifp->if_mtu;
  750                         tapp->type = ifp->if_type;
  751                         tapp->baudrate = ifp->if_baudrate;
  752                         mtx_unlock(&tp->tap_mtx);
  753                         break;
  754 
  755                 case TAPSDEBUG:
  756                         tapdebug = *(int *)data;
  757                         break;
  758 
  759                 case TAPGDEBUG:
  760                         *(int *)data = tapdebug;
  761                         break;
  762 
  763                 case TAPGIFNAME: {
  764                         struct ifreq    *ifr = (struct ifreq *) data;
  765 
  766                         strlcpy(ifr->ifr_name, ifp->if_xname, IFNAMSIZ);
  767                         } break;
  768 
  769                 case FIONBIO:
  770                         break;
  771 
  772                 case FIOASYNC:
  773                         mtx_lock(&tp->tap_mtx);
  774                         if (*(int *)data)
  775                                 tp->tap_flags |= TAP_ASYNC;
  776                         else
  777                                 tp->tap_flags &= ~TAP_ASYNC;
  778                         mtx_unlock(&tp->tap_mtx);
  779                         break;
  780 
  781                 case FIONREAD:
  782                         if (!IFQ_IS_EMPTY(&ifp->if_snd)) {
  783                                 struct mbuf *mb;
  784 
  785                                 IFQ_LOCK(&ifp->if_snd);
  786                                 IFQ_POLL_NOLOCK(&ifp->if_snd, mb);
  787                                 for (*(int *)data = 0; mb != NULL;
  788                                      mb = mb->m_next)
  789                                         *(int *)data += mb->m_len;
  790                                 IFQ_UNLOCK(&ifp->if_snd);
  791                         } else
  792                                 *(int *)data = 0;
  793                         break;
  794 
  795                 case FIOSETOWN:
  796                         return (fsetown(*(int *)data, &tp->tap_sigio));
  797 
  798                 case FIOGETOWN:
  799                         *(int *)data = fgetown(&tp->tap_sigio);
  800                         return (0);
  801 
  802                 /* this is deprecated, FIOSETOWN should be used instead */
  803                 case TIOCSPGRP:
  804                         return (fsetown(-(*(int *)data), &tp->tap_sigio));
  805 
  806                 /* this is deprecated, FIOGETOWN should be used instead */
  807                 case TIOCGPGRP:
  808                         *(int *)data = -fgetown(&tp->tap_sigio);
  809                         return (0);
  810 
  811                 /* VMware/VMnet port ioctl's */
  812 
  813 #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
  814     defined(COMPAT_FREEBSD4)
  815                 case _IO('V', 0):
  816                         ival = IOCPARM_IVAL(data);
  817                         data = (caddr_t)&ival;
  818                         /* FALLTHROUGH */
  819 #endif
  820                 case VMIO_SIOCSIFFLAGS: /* VMware/VMnet SIOCSIFFLAGS */
  821                         f = *(int *)data;
  822                         f &= 0x0fff;
  823                         f &= ~IFF_CANTCHANGE;
  824                         f |= IFF_UP;
  825 
  826                         mtx_lock(&tp->tap_mtx);
  827                         ifp->if_flags = f | (ifp->if_flags & IFF_CANTCHANGE);
  828                         mtx_unlock(&tp->tap_mtx);
  829                         break;
  830 
  831                 case OSIOCGIFADDR:      /* get MAC address of the remote side */
  832                 case SIOCGIFADDR:
  833                         mtx_lock(&tp->tap_mtx);
  834                         bcopy(tp->ether_addr, data, sizeof(tp->ether_addr));
  835                         mtx_unlock(&tp->tap_mtx);
  836                         break;
  837 
  838                 case SIOCSIFADDR:       /* set MAC address of the remote side */
  839                         mtx_lock(&tp->tap_mtx);
  840                         bcopy(data, tp->ether_addr, sizeof(tp->ether_addr));
  841                         mtx_unlock(&tp->tap_mtx);
  842                         break;
  843 
  844                 default:
  845                         return (ENOTTY);
  846         }
  847         return (0);
  848 } /* tapioctl */
  849 
  850 
  851 /*
  852  * tapread
  853  *
  854  * the cdevsw read interface - reads a packet at a time, or at
  855  * least as much of a packet as can be read
  856  */
  857 static int
  858 tapread(struct cdev *dev, struct uio *uio, int flag)
  859 {
  860         struct tap_softc        *tp = dev->si_drv1;
  861         struct ifnet            *ifp = tp->tap_ifp;
  862         struct mbuf             *m = NULL;
  863         int                      error = 0, len;
  864 
  865         TAPDEBUG("%s reading, minor = %#x\n", ifp->if_xname, dev2unit(dev));
  866 
  867         mtx_lock(&tp->tap_mtx);
  868         if ((tp->tap_flags & TAP_READY) != TAP_READY) {
  869                 mtx_unlock(&tp->tap_mtx);
  870 
  871                 /* Unlocked read. */
  872                 TAPDEBUG("%s not ready. minor = %#x, tap_flags = 0x%x\n",
  873                         ifp->if_xname, dev2unit(dev), tp->tap_flags);
  874 
  875                 return (EHOSTDOWN);
  876         }
  877 
  878         tp->tap_flags &= ~TAP_RWAIT;
  879 
  880         /* sleep until we get a packet */
  881         do {
  882                 IF_DEQUEUE(&ifp->if_snd, m);
  883 
  884                 if (m == NULL) {
  885                         if (flag & O_NONBLOCK) {
  886                                 mtx_unlock(&tp->tap_mtx);
  887                                 return (EWOULDBLOCK);
  888                         }
  889 
  890                         tp->tap_flags |= TAP_RWAIT;
  891                         error = mtx_sleep(tp, &tp->tap_mtx, PCATCH | (PZERO + 1),
  892                             "taprd", 0);
  893                         if (error) {
  894                                 mtx_unlock(&tp->tap_mtx);
  895                                 return (error);
  896                         }
  897                 }
  898         } while (m == NULL);
  899         mtx_unlock(&tp->tap_mtx);
  900 
  901         /* feed packet to bpf */
  902         BPF_MTAP(ifp, m);
  903 
  904         /* xfer packet to user space */
  905         while ((m != NULL) && (uio->uio_resid > 0) && (error == 0)) {
  906                 len = min(uio->uio_resid, m->m_len);
  907                 if (len == 0)
  908                         break;
  909 
  910                 error = uiomove(mtod(m, void *), len, uio);
  911                 m = m_free(m);
  912         }
  913 
  914         if (m != NULL) {
  915                 TAPDEBUG("%s dropping mbuf, minor = %#x\n", ifp->if_xname, 
  916                         dev2unit(dev));
  917                 m_freem(m);
  918         }
  919 
  920         return (error);
  921 } /* tapread */
  922 
  923 
  924 /*
  925  * tapwrite
  926  *
  927  * the cdevsw write interface - an atomic write is a packet - or else!
  928  */
  929 static int
  930 tapwrite(struct cdev *dev, struct uio *uio, int flag)
  931 {
  932         struct ether_header     *eh;
  933         struct tap_softc        *tp = dev->si_drv1;
  934         struct ifnet            *ifp = tp->tap_ifp;
  935         struct mbuf             *m;
  936 
  937         TAPDEBUG("%s writing, minor = %#x\n", 
  938                 ifp->if_xname, dev2unit(dev));
  939 
  940         if (uio->uio_resid == 0)
  941                 return (0);
  942 
  943         if ((uio->uio_resid < 0) || (uio->uio_resid > TAPMRU)) {
  944                 TAPDEBUG("%s invalid packet len = %zd, minor = %#x\n",
  945                         ifp->if_xname, uio->uio_resid, dev2unit(dev));
  946 
  947                 return (EIO);
  948         }
  949 
  950         if ((m = m_uiotombuf(uio, M_NOWAIT, 0, ETHER_ALIGN,
  951             M_PKTHDR)) == NULL) {
  952                 ifp->if_ierrors ++;
  953                 return (ENOBUFS);
  954         }
  955 
  956         m->m_pkthdr.rcvif = ifp;
  957 
  958         /*
  959          * Only pass a unicast frame to ether_input(), if it would actually
  960          * have been received by non-virtual hardware.
  961          */
  962         if (m->m_len < sizeof(struct ether_header)) {
  963                 m_freem(m);
  964                 return (0);
  965         }
  966         eh = mtod(m, struct ether_header *);
  967 
  968         if (eh && (ifp->if_flags & IFF_PROMISC) == 0 &&
  969             !ETHER_IS_MULTICAST(eh->ether_dhost) &&
  970             bcmp(eh->ether_dhost, IF_LLADDR(ifp), ETHER_ADDR_LEN) != 0) {
  971                 m_freem(m);
  972                 return (0);
  973         }
  974 
  975         /* Pass packet up to parent. */
  976         CURVNET_SET(ifp->if_vnet);
  977         (*ifp->if_input)(ifp, m);
  978         CURVNET_RESTORE();
  979         ifp->if_ipackets ++; /* ibytes are counted in parent */
  980 
  981         return (0);
  982 } /* tapwrite */
  983 
  984 
  985 /*
  986  * tappoll
  987  *
  988  * the poll interface, this is only useful on reads
  989  * really. the write detect always returns true, write never blocks
  990  * anyway, it either accepts the packet or drops it
  991  */
  992 static int
  993 tappoll(struct cdev *dev, int events, struct thread *td)
  994 {
  995         struct tap_softc        *tp = dev->si_drv1;
  996         struct ifnet            *ifp = tp->tap_ifp;
  997         int                      revents = 0;
  998 
  999         TAPDEBUG("%s polling, minor = %#x\n", 
 1000                 ifp->if_xname, dev2unit(dev));
 1001 
 1002         if (events & (POLLIN | POLLRDNORM)) {
 1003                 IFQ_LOCK(&ifp->if_snd);
 1004                 if (!IFQ_IS_EMPTY(&ifp->if_snd)) {
 1005                         TAPDEBUG("%s have data in queue. len = %d, " \
 1006                                 "minor = %#x\n", ifp->if_xname,
 1007                                 ifp->if_snd.ifq_len, dev2unit(dev));
 1008 
 1009                         revents |= (events & (POLLIN | POLLRDNORM));
 1010                 } else {
 1011                         TAPDEBUG("%s waiting for data, minor = %#x\n",
 1012                                 ifp->if_xname, dev2unit(dev));
 1013 
 1014                         selrecord(td, &tp->tap_rsel);
 1015                 }
 1016                 IFQ_UNLOCK(&ifp->if_snd);
 1017         }
 1018 
 1019         if (events & (POLLOUT | POLLWRNORM))
 1020                 revents |= (events & (POLLOUT | POLLWRNORM));
 1021 
 1022         return (revents);
 1023 } /* tappoll */
 1024 
 1025 
 1026 /*
 1027  * tap_kqfilter
 1028  *
 1029  * support for kevent() system call
 1030  */
 1031 static int
 1032 tapkqfilter(struct cdev *dev, struct knote *kn)
 1033 {
 1034         struct tap_softc        *tp = dev->si_drv1;
 1035         struct ifnet            *ifp = tp->tap_ifp;
 1036 
 1037         switch (kn->kn_filter) {
 1038         case EVFILT_READ:
 1039                 TAPDEBUG("%s kqfilter: EVFILT_READ, minor = %#x\n",
 1040                         ifp->if_xname, dev2unit(dev));
 1041                 kn->kn_fop = &tap_read_filterops;
 1042                 break;
 1043 
 1044         case EVFILT_WRITE:
 1045                 TAPDEBUG("%s kqfilter: EVFILT_WRITE, minor = %#x\n",
 1046                         ifp->if_xname, dev2unit(dev));
 1047                 kn->kn_fop = &tap_write_filterops;
 1048                 break;
 1049 
 1050         default:
 1051                 TAPDEBUG("%s kqfilter: invalid filter, minor = %#x\n",
 1052                         ifp->if_xname, dev2unit(dev));
 1053                 return (EINVAL);
 1054                 /* NOT REACHED */
 1055         }
 1056 
 1057         kn->kn_hook = tp;
 1058         knlist_add(&tp->tap_rsel.si_note, kn, 0);
 1059 
 1060         return (0);
 1061 } /* tapkqfilter */
 1062 
 1063 
 1064 /*
 1065  * tap_kqread
 1066  * 
 1067  * Return true if there is data in the interface queue
 1068  */
 1069 static int
 1070 tapkqread(struct knote *kn, long hint)
 1071 {
 1072         int                      ret;
 1073         struct tap_softc        *tp = kn->kn_hook;
 1074         struct cdev             *dev = tp->tap_dev;
 1075         struct ifnet            *ifp = tp->tap_ifp;
 1076 
 1077         if ((kn->kn_data = ifp->if_snd.ifq_len) > 0) {
 1078                 TAPDEBUG("%s have data in queue. len = %d, minor = %#x\n",
 1079                         ifp->if_xname, ifp->if_snd.ifq_len, dev2unit(dev));
 1080                 ret = 1;
 1081         } else {
 1082                 TAPDEBUG("%s waiting for data, minor = %#x\n",
 1083                         ifp->if_xname, dev2unit(dev));
 1084                 ret = 0;
 1085         }
 1086 
 1087         return (ret);
 1088 } /* tapkqread */
 1089 
 1090 
 1091 /*
 1092  * tap_kqwrite
 1093  *
 1094  * Always can write. Return the MTU in kn->data
 1095  */
 1096 static int
 1097 tapkqwrite(struct knote *kn, long hint)
 1098 {
 1099         struct tap_softc        *tp = kn->kn_hook;
 1100         struct ifnet            *ifp = tp->tap_ifp;
 1101 
 1102         kn->kn_data = ifp->if_mtu;
 1103 
 1104         return (1);
 1105 } /* tapkqwrite */
 1106 
 1107 
 1108 static void
 1109 tapkqdetach(struct knote *kn)
 1110 {
 1111         struct tap_softc        *tp = kn->kn_hook;
 1112 
 1113         knlist_remove(&tp->tap_rsel.si_note, kn, 0);
 1114 } /* tapkqdetach */
 1115 

Cache object: 2d39f5bf048d8fd9f4a76ada5d34a94f


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.