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_clone.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) 1980, 1986, 1993
    3  *      The Regents of the University of California.  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  * 3. Neither the name of the University nor the names of its contributors
   14  *    may be used to endorse or promote products derived from this software
   15  *    without specific prior written permission.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  *
   29  *      @(#)if.c        8.3 (Berkeley) 1/4/94
   30  * $FreeBSD: src/sys/net/if.c,v 1.185 2004/03/13 02:35:03 brooks Exp $
   31  * $DragonFly: src/sys/net/if_clone.c,v 1.1 2008/01/11 11:59:40 sephe Exp $
   32  */
   33 
   34 #include <sys/param.h>
   35 #include <sys/kernel.h>
   36 #include <sys/malloc.h>
   37 
   38 #include <net/if.h>
   39 #include <net/if_clone.h>
   40 
   41 static LIST_HEAD(, if_clone) if_cloners = LIST_HEAD_INITIALIZER(if_cloners);
   42 static int              if_cloners_count;
   43 
   44 MALLOC_DEFINE(M_CLONE, "clone", "interface cloning framework");
   45 
   46 static struct if_clone  *if_clone_lookup(const char *, int *);
   47 
   48 /*
   49  * Create a clone network interface.
   50  */
   51 int
   52 if_clone_create(char *name, int len, caddr_t params)
   53 {
   54         struct if_clone *ifc;
   55         char *dp;
   56         int wildcard, bytoff, bitoff;
   57         int unit;
   58         int err;
   59 
   60         ifc = if_clone_lookup(name, &unit);
   61         if (ifc == NULL)
   62                 return (EINVAL);
   63 
   64         if (ifunit(name) != NULL)
   65                 return (EEXIST);
   66 
   67         bytoff = bitoff = 0;
   68         wildcard = (unit < 0);
   69         /*
   70          * Find a free unit if none was given.
   71          */
   72         if (wildcard) {
   73                 while (bytoff < ifc->ifc_bmlen &&
   74                     ifc->ifc_units[bytoff] == 0xff)
   75                         bytoff++;
   76                 if (bytoff >= ifc->ifc_bmlen)
   77                         return (ENOSPC);
   78                 while ((ifc->ifc_units[bytoff] & (1 << bitoff)) != 0)
   79                         bitoff++;
   80                 unit = (bytoff << 3) + bitoff;
   81         }
   82 
   83         if (unit > ifc->ifc_maxunit)
   84                 return (ENXIO);
   85 
   86         err = (*ifc->ifc_create)(ifc, unit, params);
   87         if (err != 0)
   88                 return (err);
   89 
   90         if (!wildcard) {
   91                 bytoff = unit >> 3;
   92                 bitoff = unit - (bytoff << 3);
   93         }
   94 
   95         /*
   96          * Allocate the unit in the bitmap.
   97          */
   98         KASSERT((ifc->ifc_units[bytoff] & (1 << bitoff)) == 0,
   99             ("%s: bit is already set", __func__));
  100         ifc->ifc_units[bytoff] |= (1 << bitoff);
  101 
  102         /* In the wildcard case, we need to update the name. */
  103         if (wildcard) {
  104                 for (dp = name; *dp != '\0'; dp++);
  105                 if (ksnprintf(dp, len - (dp-name), "%d", unit) >
  106                     len - (dp-name) - 1) {
  107                         /*
  108                          * This can only be a programmer error and
  109                          * there's no straightforward way to recover if
  110                          * it happens.
  111                          */
  112                         panic("if_clone_create(): interface name too long");
  113                 }
  114 
  115         }
  116 
  117         EVENTHANDLER_INVOKE(if_clone_event, ifc);
  118 
  119         return (0);
  120 }
  121 
  122 /*
  123  * Destroy a clone network interface.
  124  */
  125 int
  126 if_clone_destroy(const char *name)
  127 {
  128         struct if_clone *ifc;
  129         struct ifnet *ifp;
  130         int bytoff, bitoff;
  131         int unit, error;
  132 
  133         ifc = if_clone_lookup(name, &unit);
  134         if (ifc == NULL)
  135                 return (EINVAL);
  136 
  137         if (unit < ifc->ifc_minifs)
  138                 return (EINVAL);
  139 
  140         ifp = ifunit(name);
  141         if (ifp == NULL)
  142                 return (ENXIO);
  143 
  144         if (ifc->ifc_destroy == NULL)
  145                 return (EOPNOTSUPP);
  146 
  147         error = ifc->ifc_destroy(ifp);
  148         if (error)
  149                 return error;
  150 
  151         /*
  152          * Compute offset in the bitmap and deallocate the unit.
  153          */
  154         bytoff = unit >> 3;
  155         bitoff = unit - (bytoff << 3);
  156         KASSERT((ifc->ifc_units[bytoff] & (1 << bitoff)) != 0,
  157             ("%s: bit is already cleared", __func__));
  158         ifc->ifc_units[bytoff] &= ~(1 << bitoff);
  159         return (0);
  160 }
  161 
  162 /*
  163  * Register a network interface cloner.
  164  */
  165 void
  166 if_clone_attach(struct if_clone *ifc)
  167 {
  168         int bytoff, bitoff;
  169         int err;
  170         int len, maxclone;
  171         int unit;
  172 
  173         KASSERT(ifc->ifc_minifs - 1 <= ifc->ifc_maxunit,
  174             ("%s: %s requested more units then allowed (%d > %d)",
  175             __func__, ifc->ifc_name, ifc->ifc_minifs,
  176             ifc->ifc_maxunit + 1));
  177         /*
  178          * Compute bitmap size and allocate it.
  179          */
  180         maxclone = ifc->ifc_maxunit + 1;
  181         len = maxclone >> 3;
  182         if ((len << 3) < maxclone)
  183                 len++;
  184         ifc->ifc_units = kmalloc(len, M_CLONE, M_WAITOK | M_ZERO);
  185         ifc->ifc_bmlen = len;
  186 
  187         LIST_INSERT_HEAD(&if_cloners, ifc, ifc_list);
  188         if_cloners_count++;
  189 
  190         for (unit = 0; unit < ifc->ifc_minifs; unit++) {
  191                 err = (*ifc->ifc_create)(ifc, unit, NULL);
  192                 KASSERT(err == 0,
  193                     ("%s: failed to create required interface %s%d",
  194                     __func__, ifc->ifc_name, unit));
  195 
  196                 /* Allocate the unit in the bitmap. */
  197                 bytoff = unit >> 3;
  198                 bitoff = unit - (bytoff << 3);
  199                 ifc->ifc_units[bytoff] |= (1 << bitoff);
  200         }
  201 }
  202 
  203 /*
  204  * Unregister a network interface cloner.
  205  */
  206 void
  207 if_clone_detach(struct if_clone *ifc)
  208 {
  209 
  210         LIST_REMOVE(ifc, ifc_list);
  211         kfree(ifc->ifc_units, M_CLONE);
  212         if_cloners_count--;
  213 }
  214 
  215 /*
  216  * Provide list of interface cloners to userspace.
  217  */
  218 int
  219 if_clone_list(struct if_clonereq *ifcr)
  220 {
  221         char outbuf[IFNAMSIZ], *dst;
  222         struct if_clone *ifc;
  223         int count, error = 0;
  224 
  225         ifcr->ifcr_total = if_cloners_count;
  226         if ((dst = ifcr->ifcr_buffer) == NULL) {
  227                 /* Just asking how many there are. */
  228                 return (0);
  229         }
  230 
  231         if (ifcr->ifcr_count < 0)
  232                 return (EINVAL);
  233 
  234         count = (if_cloners_count < ifcr->ifcr_count) ?
  235             if_cloners_count : ifcr->ifcr_count;
  236 
  237         for (ifc = LIST_FIRST(&if_cloners); ifc != NULL && count != 0;
  238              ifc = LIST_NEXT(ifc, ifc_list), count--, dst += IFNAMSIZ) {
  239                 strlcpy(outbuf, ifc->ifc_name, IFNAMSIZ);
  240                 error = copyout(outbuf, dst, IFNAMSIZ);
  241                 if (error)
  242                         break;
  243         }
  244 
  245         return (error);
  246 }
  247 
  248 /*
  249  * Look up a network interface cloner.
  250  */
  251 static struct if_clone *
  252 if_clone_lookup(const char *name, int *unitp)
  253 {
  254         struct if_clone *ifc;
  255         const char *cp;
  256         int i;
  257 
  258         for (ifc = LIST_FIRST(&if_cloners); ifc != NULL;) {
  259                 for (cp = name, i = 0; i < ifc->ifc_namelen; i++, cp++) {
  260                         if (ifc->ifc_name[i] != *cp)
  261                                 goto next_ifc;
  262                 }
  263                 goto found_name;
  264  next_ifc:
  265                 ifc = LIST_NEXT(ifc, ifc_list);
  266         }
  267 
  268         /* No match. */
  269         return (NULL);
  270 
  271  found_name:
  272         if (*cp == '\0') {
  273                 i = -1;
  274         } else {
  275                 for (i = 0; *cp != '\0'; cp++) {
  276                         if (*cp < '' || *cp > '9') {
  277                                 /* Bogus unit number. */
  278                                 return (NULL);
  279                         }
  280                         i = (i * 10) + (*cp - '');
  281                 }
  282         }
  283 
  284         if (unitp != NULL)
  285                 *unitp = i;
  286         return (ifc);
  287 }

Cache object: de85ee9fb02a9fb53e9f8c364c1eec73


[ 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.