Index: sys/net/if_clone.c =================================================================== --- sys/net/if_clone.c (revision 228109) +++ sys/net/if_clone.c (working copy) @@ -436,30 +436,49 @@ } int -ifc_alloc_unit(struct if_clone *ifc, int *unit) +ifc_alloc_unit(struct if_clone *ifc, int *unit_nr) { char name[IFNAMSIZ]; - int wildcard; + int ret, unit, wildcard; - wildcard = (*unit < 0); + unit = *unit_nr; + wildcard = (unit < 0); retry: - if (wildcard) { - *unit = alloc_unr(ifc->ifc_unrhdr); - if (*unit == -1) + if (unit > ifc->ifc_maxunit) + return (ENOSPC); + + if (unit < 0) { + /* first, try to allocate a unit number automatically */ + unit = alloc_unr(ifc->ifc_unrhdr); + if (unit == -1) return (ENOSPC); } else { - *unit = alloc_unr_specific(ifc->ifc_unrhdr, *unit); - if (*unit == -1) - return (EEXIST); + ret = alloc_unr_specific(ifc->ifc_unrhdr, unit); + if (ret == -1) { + if (wildcard) { + /* unit number already claimed. try next */ + unit++; + goto retry; + } else { + /* specified unit number already claimed */ + return (EEXIST); + } + } } - snprintf(name, IFNAMSIZ, "%s%d", ifc->ifc_name, *unit); + /* if we reach this point, a unit number has been allocated */ + snprintf(name, IFNAMSIZ, "%s%d", ifc->ifc_name, unit); if (ifunit(name) != NULL) { - if (wildcard) - goto retry; /* XXXGL: yep, it's a unit leak */ - else - return (EEXIST); + /* name is already taken */ + free_unr(ifc->ifc_unrhdr, unit); + if (wildcard) { + /* increment unit number and try again */ + unit++; + goto retry; + } + return (EEXIST); } + *unit_nr = unit; IF_CLONE_ADDREF(ifc);