Deleted Added
full compact
30c30
< * $FreeBSD: head/sys/net/if.c 130585 2004-06-16 09:47:26Z phk $
---
> * $FreeBSD: head/sys/net/if.c 130933 2004-06-22 20:13:25Z brooks $
58a59
> #include <net/if_clone.h>
93,94d93
< static struct if_clone *if_clone_lookup(const char *, int *);
< static int if_clone_list(struct if_clonereq *);
109,110d107
< static int if_cloners_count;
< LIST_HEAD(, if_clone) if_cloners = LIST_HEAD_INITIALIZER(if_cloners);
129d125
< MALLOC_DEFINE(M_CLONE, "clone", "interface cloning framework");
265a262
> if_clone_init();
671,907d667
< /*
< * Create a clone network interface.
< */
< int
< if_clone_create(char *name, int len)
< {
< struct if_clone *ifc;
< char *dp;
< int wildcard, bytoff, bitoff;
< int unit;
< int err;
<
< ifc = if_clone_lookup(name, &unit);
< if (ifc == NULL)
< return (EINVAL);
<
< if (ifunit(name) != NULL)
< return (EEXIST);
<
< bytoff = bitoff = 0;
< wildcard = (unit < 0);
< /*
< * Find a free unit if none was given.
< */
< if (wildcard) {
< while ((bytoff < ifc->ifc_bmlen)
< && (ifc->ifc_units[bytoff] == 0xff))
< bytoff++;
< if (bytoff >= ifc->ifc_bmlen)
< return (ENOSPC);
< while ((ifc->ifc_units[bytoff] & (1 << bitoff)) != 0)
< bitoff++;
< unit = (bytoff << 3) + bitoff;
< }
<
< if (unit > ifc->ifc_maxunit)
< return (ENXIO);
<
< err = (*ifc->ifc_create)(ifc, unit);
< if (err != 0)
< return (err);
<
< if (!wildcard) {
< bytoff = unit >> 3;
< bitoff = unit - (bytoff << 3);
< }
<
< /*
< * Allocate the unit in the bitmap.
< */
< KASSERT((ifc->ifc_units[bytoff] & (1 << bitoff)) == 0,
< ("%s: bit is already set", __func__));
< ifc->ifc_units[bytoff] |= (1 << bitoff);
<
< /* In the wildcard case, we need to update the name. */
< if (wildcard) {
< for (dp = name; *dp != '\0'; dp++);
< if (snprintf(dp, len - (dp-name), "%d", unit) >
< len - (dp-name) - 1) {
< /*
< * This can only be a programmer error and
< * there's no straightforward way to recover if
< * it happens.
< */
< panic("if_clone_create(): interface name too long");
< }
<
< }
<
< return (0);
< }
<
< /*
< * Destroy a clone network interface.
< */
< int
< if_clone_destroy(const char *name)
< {
< struct if_clone *ifc;
< struct ifnet *ifp;
< int bytoff, bitoff;
< int unit;
<
< ifp = ifunit(name);
< if (ifp == NULL)
< return (ENXIO);
<
< unit = ifp->if_dunit;
<
< ifc = if_clone_lookup(ifp->if_dname, NULL);
< if (ifc == NULL)
< return (EINVAL);
<
< if (ifc->ifc_destroy == NULL)
< return (EOPNOTSUPP);
<
< (*ifc->ifc_destroy)(ifp);
<
< /*
< * Compute offset in the bitmap and deallocate the unit.
< */
< bytoff = unit >> 3;
< bitoff = unit - (bytoff << 3);
< KASSERT((ifc->ifc_units[bytoff] & (1 << bitoff)) != 0,
< ("%s: bit is already cleared", __func__));
< ifc->ifc_units[bytoff] &= ~(1 << bitoff);
< return (0);
< }
<
< /*
< * Look up a network interface cloner.
< */
< static struct if_clone *
< if_clone_lookup(const char *name, int *unitp)
< {
< struct if_clone *ifc;
< const char *cp;
< int i;
<
< for (ifc = LIST_FIRST(&if_cloners); ifc != NULL;) {
< for (cp = name, i = 0; i < ifc->ifc_namelen; i++, cp++) {
< if (ifc->ifc_name[i] != *cp)
< goto next_ifc;
< }
< goto found_name;
< next_ifc:
< ifc = LIST_NEXT(ifc, ifc_list);
< }
<
< /* No match. */
< return ((struct if_clone *)NULL);
<
< found_name:
< if (*cp == '\0') {
< i = -1;
< } else {
< for (i = 0; *cp != '\0'; cp++) {
< if (*cp < '0' || *cp > '9') {
< /* Bogus unit number. */
< return (NULL);
< }
< i = (i * 10) + (*cp - '0');
< }
< }
<
< if (unitp != NULL)
< *unitp = i;
< return (ifc);
< }
<
< /*
< * Register a network interface cloner.
< */
< void
< if_clone_attach(struct if_clone *ifc)
< {
< int bytoff, bitoff;
< int err;
< int len, maxclone;
< int unit;
<
< KASSERT(ifc->ifc_minifs - 1 <= ifc->ifc_maxunit,
< ("%s: %s requested more units then allowed (%d > %d)",
< __func__, ifc->ifc_name, ifc->ifc_minifs,
< ifc->ifc_maxunit + 1));
< /*
< * Compute bitmap size and allocate it.
< */
< maxclone = ifc->ifc_maxunit + 1;
< len = maxclone >> 3;
< if ((len << 3) < maxclone)
< len++;
< ifc->ifc_units = malloc(len, M_CLONE, M_WAITOK | M_ZERO);
< ifc->ifc_bmlen = len;
<
< LIST_INSERT_HEAD(&if_cloners, ifc, ifc_list);
< if_cloners_count++;
<
< for (unit = 0; unit < ifc->ifc_minifs; unit++) {
< err = (*ifc->ifc_create)(ifc, unit);
< KASSERT(err == 0,
< ("%s: failed to create required interface %s%d",
< __func__, ifc->ifc_name, unit));
<
< /* Allocate the unit in the bitmap. */
< bytoff = unit >> 3;
< bitoff = unit - (bytoff << 3);
< ifc->ifc_units[bytoff] |= (1 << bitoff);
< }
< EVENTHANDLER_INVOKE(if_clone_event, ifc);
< }
<
< /*
< * Unregister a network interface cloner.
< */
< void
< if_clone_detach(struct if_clone *ifc)
< {
<
< LIST_REMOVE(ifc, ifc_list);
< free(ifc->ifc_units, M_CLONE);
< if_cloners_count--;
< }
<
< /*
< * Provide list of interface cloners to userspace.
< */
< static int
< if_clone_list(struct if_clonereq *ifcr)
< {
< char outbuf[IFNAMSIZ], *dst;
< struct if_clone *ifc;
< int count, error = 0;
<
< ifcr->ifcr_total = if_cloners_count;
< if ((dst = ifcr->ifcr_buffer) == NULL) {
< /* Just asking how many there are. */
< return (0);
< }
<
< if (ifcr->ifcr_count < 0)
< return (EINVAL);
<
< count = (if_cloners_count < ifcr->ifcr_count) ?
< if_cloners_count : ifcr->ifcr_count;
<
< for (ifc = LIST_FIRST(&if_cloners); ifc != NULL && count != 0;
< ifc = LIST_NEXT(ifc, ifc_list), count--, dst += IFNAMSIZ) {
< strlcpy(outbuf, ifc->ifc_name, IFNAMSIZ);
< error = copyout(outbuf, dst, IFNAMSIZ);
< if (error)
< break;
< }
<
< return (error);
< }
<