1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 2012 Gleb Smirnoff <glebius@FreeBSD.org> 5 * Copyright (c) 1980, 1986, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * @(#)if.c 8.5 (Berkeley) 1/9/95 33 * $FreeBSD$ 34 */ 35 36 #include <sys/param.h> 37 #include <sys/eventhandler.h> 38 #include <sys/malloc.h> 39 #include <sys/limits.h> 40 #include <sys/lock.h> 41 #include <sys/mutex.h> 42 #include <sys/kernel.h> 43 #include <sys/systm.h> 44 #include <sys/types.h> 45 #include <sys/socket.h> 46 47 #include <net/if.h> 48 #include <net/if_var.h> 49 #include <net/if_clone.h> 50 #include <net/radix.h> 51 #include <net/route.h> 52 #include <net/vnet.h> 53 54 /* Current IF_MAXUNIT expands maximum to 5 characters. */ 55 #define IFCLOSIZ (IFNAMSIZ - 5) 56 57 /* 58 * Structure describing a `cloning' interface. 59 * 60 * List of locks 61 * (c) const until freeing 62 * (d) driver specific data, may need external protection. 63 * (e) locked by if_cloners_mtx 64 * (i) locked by ifc_mtx mtx 65 */ 66 struct if_clone { 67 char ifc_name[IFCLOSIZ]; /* (c) Name of device, e.g. `gif' */ 68 struct unrhdr *ifc_unrhdr; /* (c) alloc_unr(9) header */ 69 int ifc_maxunit; /* (c) maximum unit number */ 70 int ifc_flags; 71 long ifc_refcnt; /* (i) Reference count. */ 72 LIST_HEAD(, ifnet) ifc_iflist; /* (i) List of cloned interfaces */ 73 struct mtx ifc_mtx; /* Mutex to protect members. */ 74 75 ifc_match_f *ifc_match; /* (c) Matcher function */ 76 ifc_create_f *ifc_create; /* (c) Creates new interface */ 77 ifc_destroy_f *ifc_destroy; /* (c) Destroys cloned interface */ 78 79 #ifdef CLONE_COMPAT_13 80 /* (c) Driver specific cloning functions. Called with no locks held. */ 81 union { 82 struct { /* advanced cloner */ 83 ifc_create_t *_ifc_create; 84 ifc_destroy_t *_ifc_destroy; 85 } A; 86 struct { /* simple cloner */ 87 ifcs_create_t *_ifcs_create; 88 ifcs_destroy_t *_ifcs_destroy; 89 int _ifcs_minifs; /* minimum ifs */ 90 91 } S; 92 } U; 93 #define ifca_create U.A._ifc_create 94 #define ifca_destroy U.A._ifc_destroy 95 #define ifcs_create U.S._ifcs_create 96 #define ifcs_destroy U.S._ifcs_destroy 97 #define ifcs_minifs U.S._ifcs_minifs 98 #endif 99 100 LIST_ENTRY(if_clone) ifc_list; /* (e) On list of cloners */ 101 }; 102 103 104 105 static void if_clone_free(struct if_clone *ifc); 106 static int if_clone_createif(struct if_clone *ifc, char *name, size_t len, 107 struct ifc_data *ifd, struct ifnet **ifpp); 108 109 static int ifc_simple_match(struct if_clone *ifc, const char *name); 110 static int ifc_handle_unit(struct if_clone *ifc, char *name, size_t len, int *punit); 111 112 #ifdef CLONE_COMPAT_13 113 static int ifc_simple_create_wrapper(struct if_clone *ifc, char *name, size_t maxlen, 114 struct ifc_data *ifc_data, struct ifnet **ifpp); 115 static int ifc_advanced_create_wrapper(struct if_clone *ifc, char *name, size_t maxlen, 116 struct ifc_data *ifc_data, struct ifnet **ifpp); 117 #endif 118 119 static struct mtx if_cloners_mtx; 120 MTX_SYSINIT(if_cloners_lock, &if_cloners_mtx, "if_cloners lock", MTX_DEF); 121 VNET_DEFINE_STATIC(int, if_cloners_count); 122 VNET_DEFINE(LIST_HEAD(, if_clone), if_cloners); 123 124 #define V_if_cloners_count VNET(if_cloners_count) 125 #define V_if_cloners VNET(if_cloners) 126 127 #define IF_CLONERS_LOCK_ASSERT() mtx_assert(&if_cloners_mtx, MA_OWNED) 128 #define IF_CLONERS_LOCK() mtx_lock(&if_cloners_mtx) 129 #define IF_CLONERS_UNLOCK() mtx_unlock(&if_cloners_mtx) 130 131 #define IF_CLONE_LOCK_INIT(ifc) \ 132 mtx_init(&(ifc)->ifc_mtx, "if_clone lock", NULL, MTX_DEF) 133 #define IF_CLONE_LOCK_DESTROY(ifc) mtx_destroy(&(ifc)->ifc_mtx) 134 #define IF_CLONE_LOCK_ASSERT(ifc) mtx_assert(&(ifc)->ifc_mtx, MA_OWNED) 135 #define IF_CLONE_LOCK(ifc) mtx_lock(&(ifc)->ifc_mtx) 136 #define IF_CLONE_UNLOCK(ifc) mtx_unlock(&(ifc)->ifc_mtx) 137 138 #define IF_CLONE_ADDREF(ifc) \ 139 do { \ 140 IF_CLONE_LOCK(ifc); \ 141 IF_CLONE_ADDREF_LOCKED(ifc); \ 142 IF_CLONE_UNLOCK(ifc); \ 143 } while (0) 144 #define IF_CLONE_ADDREF_LOCKED(ifc) \ 145 do { \ 146 IF_CLONE_LOCK_ASSERT(ifc); \ 147 KASSERT((ifc)->ifc_refcnt >= 0, \ 148 ("negative refcnt %ld", (ifc)->ifc_refcnt)); \ 149 (ifc)->ifc_refcnt++; \ 150 } while (0) 151 #define IF_CLONE_REMREF(ifc) \ 152 do { \ 153 IF_CLONE_LOCK(ifc); \ 154 IF_CLONE_REMREF_LOCKED(ifc); \ 155 } while (0) 156 #define IF_CLONE_REMREF_LOCKED(ifc) \ 157 do { \ 158 IF_CLONE_LOCK_ASSERT(ifc); \ 159 KASSERT((ifc)->ifc_refcnt > 0, \ 160 ("bogus refcnt %ld", (ifc)->ifc_refcnt)); \ 161 if (--(ifc)->ifc_refcnt == 0) { \ 162 IF_CLONE_UNLOCK(ifc); \ 163 if_clone_free(ifc); \ 164 } else { \ 165 /* silently free the lock */ \ 166 IF_CLONE_UNLOCK(ifc); \ 167 } \ 168 } while (0) 169 170 #define IFC_IFLIST_INSERT(_ifc, _ifp) \ 171 LIST_INSERT_HEAD(&_ifc->ifc_iflist, _ifp, if_clones) 172 #define IFC_IFLIST_REMOVE(_ifc, _ifp) \ 173 LIST_REMOVE(_ifp, if_clones) 174 175 static MALLOC_DEFINE(M_CLONE, "clone", "interface cloning framework"); 176 177 void 178 vnet_if_clone_init(void) 179 { 180 181 LIST_INIT(&V_if_cloners); 182 } 183 184 /* 185 * Lookup and create a clone network interface. 186 */ 187 int 188 ifc_create_ifp(const char *name, struct ifc_data *ifd, 189 struct ifnet **ifpp) 190 { 191 struct if_clone *ifc; 192 char ifname[IFNAMSIZ]; 193 struct ifnet *ifp = NULL; 194 int error; 195 196 /* Try to find an applicable cloner for this request */ 197 IF_CLONERS_LOCK(); 198 LIST_FOREACH(ifc, &V_if_cloners, ifc_list) { 199 if (ifc->ifc_match(ifc, name)) 200 break; 201 } 202 IF_CLONERS_UNLOCK(); 203 204 if (ifc == NULL) 205 return (EINVAL); 206 207 strlcpy(ifname, name, IFNAMSIZ); 208 error = if_clone_createif(ifc, ifname, IFNAMSIZ, ifd, &ifp); 209 if (ifpp != NULL) 210 *ifpp = ifp; 211 212 return (error); 213 } 214 215 int 216 if_clone_create(char *name, size_t len, caddr_t params) 217 { 218 struct ifc_data ifd = { .params = params }; 219 struct ifnet *ifp; 220 221 int error = ifc_create_ifp(name, &ifd, &ifp); 222 223 if (error == 0) 224 strlcpy(name, if_name(ifp), len); 225 226 return (error); 227 } 228 229 void 230 if_clone_addif(struct if_clone *ifc, struct ifnet *ifp) 231 { 232 233 if ((ifc->ifc_flags & IFC_NOGROUP) == 0) 234 if_addgroup(ifp, ifc->ifc_name); 235 236 IF_CLONE_LOCK(ifc); 237 IFC_IFLIST_INSERT(ifc, ifp); 238 IF_CLONE_UNLOCK(ifc); 239 } 240 241 /* 242 * Create a clone network interface. 243 */ 244 static int 245 if_clone_createif(struct if_clone *ifc, char *name, size_t len, 246 struct ifc_data *ifd, struct ifnet **ifpp) 247 { 248 int err, unit = 0; 249 250 if (ifunit(name) != NULL) 251 return (EEXIST); 252 253 if (ifc->ifc_flags & IFC_F_AUTOUNIT) { 254 if ((err = ifc_handle_unit(ifc, name, len, &unit)) != 0) 255 return (err); 256 ifd->unit = unit; 257 } 258 *ifpp = NULL; 259 err = (*ifc->ifc_create)(ifc, name, len, ifd, ifpp); 260 261 if (err == 0) { 262 MPASS(*ifpp != NULL); 263 if_clone_addif(ifc, *ifpp); 264 } else if (ifc->ifc_flags & IFC_F_AUTOUNIT) 265 ifc_free_unit(ifc, unit); 266 267 return (err); 268 } 269 270 /* 271 * Lookup and destroy a clone network interface. 272 */ 273 int 274 if_clone_destroy(const char *name) 275 { 276 int err; 277 struct if_clone *ifc; 278 struct ifnet *ifp; 279 280 ifp = ifunit_ref(name); 281 if (ifp == NULL) 282 return (ENXIO); 283 284 /* Find the cloner for this interface */ 285 CURVNET_SET_QUIET(ifp->if_home_vnet); 286 IF_CLONERS_LOCK(); 287 LIST_FOREACH(ifc, &V_if_cloners, ifc_list) { 288 if (strcmp(ifc->ifc_name, ifp->if_dname) == 0) { 289 break; 290 } 291 } 292 IF_CLONERS_UNLOCK(); 293 CURVNET_RESTORE(); 294 if (ifc == NULL) { 295 if_rele(ifp); 296 return (EINVAL); 297 } 298 299 err = if_clone_destroyif(ifc, ifp); 300 if_rele(ifp); 301 return err; 302 } 303 304 /* 305 * Destroy a clone network interface. 306 */ 307 static int 308 if_clone_destroyif_flags(struct if_clone *ifc, struct ifnet *ifp, uint32_t flags) 309 { 310 int err; 311 struct ifnet *ifcifp; 312 313 /* 314 * Given that the cloned ifnet might be attached to a different 315 * vnet from where its cloner was registered, we have to 316 * switch to the vnet context of the target vnet. 317 */ 318 CURVNET_SET_QUIET(ifp->if_vnet); 319 320 IF_CLONE_LOCK(ifc); 321 LIST_FOREACH(ifcifp, &ifc->ifc_iflist, if_clones) { 322 if (ifcifp == ifp) { 323 IFC_IFLIST_REMOVE(ifc, ifp); 324 break; 325 } 326 } 327 IF_CLONE_UNLOCK(ifc); 328 if (ifcifp == NULL) { 329 CURVNET_RESTORE(); 330 return (ENXIO); /* ifp is not on the list. */ 331 } 332 if ((ifc->ifc_flags & IFC_F_NOGROUP) == 0) 333 if_delgroup(ifp, ifc->ifc_name); 334 335 int unit = ifp->if_dunit; 336 err = (*ifc->ifc_destroy)(ifc, ifp, flags); 337 338 if (err != 0) { 339 if ((ifc->ifc_flags & IFC_F_NOGROUP) == 0) 340 if_addgroup(ifp, ifc->ifc_name); 341 342 IF_CLONE_LOCK(ifc); 343 IFC_IFLIST_INSERT(ifc, ifp); 344 IF_CLONE_UNLOCK(ifc); 345 } else if (ifc->ifc_flags & IFC_F_AUTOUNIT) 346 ifc_free_unit(ifc, unit); 347 CURVNET_RESTORE(); 348 return (err); 349 } 350 351 int 352 if_clone_destroyif(struct if_clone *ifc, struct ifnet *ifp) 353 { 354 return (if_clone_destroyif_flags(ifc, ifp, 0)); 355 } 356 357 static struct if_clone * 358 if_clone_alloc(const char *name, int maxunit) 359 { 360 struct if_clone *ifc; 361 362 KASSERT(name != NULL, ("%s: no name\n", __func__)); 363 364 ifc = malloc(sizeof(struct if_clone), M_CLONE, M_WAITOK | M_ZERO); 365 strncpy(ifc->ifc_name, name, IFCLOSIZ-1); 366 IF_CLONE_LOCK_INIT(ifc); 367 IF_CLONE_ADDREF(ifc); 368 ifc->ifc_maxunit = maxunit ? maxunit : IF_MAXUNIT; 369 ifc->ifc_unrhdr = new_unrhdr(0, ifc->ifc_maxunit, &ifc->ifc_mtx); 370 LIST_INIT(&ifc->ifc_iflist); 371 372 return (ifc); 373 } 374 375 static int 376 if_clone_attach(struct if_clone *ifc) 377 { 378 struct if_clone *ifc1; 379 380 IF_CLONERS_LOCK(); 381 LIST_FOREACH(ifc1, &V_if_cloners, ifc_list) 382 if (strcmp(ifc->ifc_name, ifc1->ifc_name) == 0) { 383 IF_CLONERS_UNLOCK(); 384 IF_CLONE_REMREF(ifc); 385 return (EEXIST); 386 } 387 LIST_INSERT_HEAD(&V_if_cloners, ifc, ifc_list); 388 V_if_cloners_count++; 389 IF_CLONERS_UNLOCK(); 390 391 return (0); 392 } 393 394 struct if_clone * 395 ifc_attach_cloner(const char *name, struct if_clone_addreq *req) 396 { 397 if (req->create_f == NULL || req->destroy_f == NULL) 398 return (NULL); 399 if (strnlen(name, IFCLOSIZ) >= (IFCLOSIZ - 1)) 400 return (NULL); 401 402 struct if_clone *ifc = if_clone_alloc(name, req->maxunit); 403 ifc->ifc_match = req->match_f != NULL ? req->match_f : ifc_simple_match; 404 ifc->ifc_create = req->create_f; 405 ifc->ifc_destroy = req->destroy_f; 406 ifc->ifc_flags = (req->flags & (IFC_F_AUTOUNIT | IFC_F_NOGROUP)); 407 408 if (if_clone_attach(ifc) != 0) 409 return (NULL); 410 411 EVENTHANDLER_INVOKE(if_clone_event, ifc); 412 413 return (ifc); 414 } 415 416 void 417 ifc_detach_cloner(struct if_clone *ifc) 418 { 419 if_clone_detach(ifc); 420 } 421 422 423 #ifdef CLONE_COMPAT_13 424 425 static int 426 ifc_advanced_create_wrapper(struct if_clone *ifc, char *name, size_t maxlen, 427 struct ifc_data *ifc_data, struct ifnet **ifpp) 428 { 429 int error = ifc->ifca_create(ifc, name, maxlen, ifc_data->params); 430 431 if (error == 0) 432 *ifpp = ifunit(name); 433 return (error); 434 } 435 436 static int 437 ifc_advanced_destroy_wrapper(struct if_clone *ifc, struct ifnet *ifp, uint32_t flags) 438 { 439 if (ifc->ifca_destroy == NULL) 440 return (ENOTSUP); 441 return (ifc->ifca_destroy(ifc, ifp)); 442 } 443 444 struct if_clone * 445 if_clone_advanced(const char *name, u_int maxunit, ifc_match_t match, 446 ifc_create_t create, ifc_destroy_t destroy) 447 { 448 struct if_clone *ifc; 449 450 ifc = if_clone_alloc(name, maxunit); 451 ifc->ifc_match = match; 452 ifc->ifc_create = ifc_advanced_create_wrapper; 453 ifc->ifc_destroy = ifc_advanced_destroy_wrapper; 454 ifc->ifca_destroy = destroy; 455 ifc->ifca_create = create; 456 457 if (if_clone_attach(ifc) != 0) 458 return (NULL); 459 460 EVENTHANDLER_INVOKE(if_clone_event, ifc); 461 462 return (ifc); 463 } 464 465 static int 466 ifc_simple_create_wrapper(struct if_clone *ifc, char *name, size_t maxlen, 467 struct ifc_data *ifc_data, struct ifnet **ifpp) 468 { 469 int unit = 0; 470 471 ifc_name2unit(name, &unit); 472 int error = ifc->ifcs_create(ifc, unit, ifc_data->params); 473 if (error == 0) 474 *ifpp = ifunit(name); 475 return (error); 476 } 477 478 static int 479 ifc_simple_destroy_wrapper(struct if_clone *ifc, struct ifnet *ifp, uint32_t flags) 480 { 481 if (ifp->if_dunit < ifc->ifcs_minifs && (flags & IFC_F_FORCE) == 0) 482 return (EINVAL); 483 484 ifc->ifcs_destroy(ifp); 485 return (0); 486 } 487 488 struct if_clone * 489 if_clone_simple(const char *name, ifcs_create_t create, ifcs_destroy_t destroy, 490 u_int minifs) 491 { 492 struct if_clone *ifc; 493 u_int unit; 494 495 ifc = if_clone_alloc(name, 0); 496 ifc->ifc_match = ifc_simple_match; 497 ifc->ifc_create = ifc_simple_create_wrapper; 498 ifc->ifc_destroy = ifc_simple_destroy_wrapper; 499 ifc->ifcs_create = create; 500 ifc->ifcs_destroy = destroy; 501 ifc->ifcs_minifs = minifs; 502 ifc->ifc_flags = IFC_F_AUTOUNIT; 503 504 if (if_clone_attach(ifc) != 0) 505 return (NULL); 506 507 for (unit = 0; unit < minifs; unit++) { 508 char name[IFNAMSIZ]; 509 int error __unused; 510 struct ifc_data ifd = {}; 511 struct ifnet *ifp; 512 513 snprintf(name, IFNAMSIZ, "%s%d", ifc->ifc_name, unit); 514 error = if_clone_createif(ifc, name, IFNAMSIZ, &ifd, &ifp); 515 KASSERT(error == 0, 516 ("%s: failed to create required interface %s", 517 __func__, name)); 518 } 519 520 EVENTHANDLER_INVOKE(if_clone_event, ifc); 521 522 return (ifc); 523 } 524 #endif 525 526 /* 527 * Unregister a network interface cloner. 528 */ 529 void 530 if_clone_detach(struct if_clone *ifc) 531 { 532 533 IF_CLONERS_LOCK(); 534 LIST_REMOVE(ifc, ifc_list); 535 V_if_cloners_count--; 536 IF_CLONERS_UNLOCK(); 537 538 /* destroy all interfaces for this cloner */ 539 while (!LIST_EMPTY(&ifc->ifc_iflist)) 540 if_clone_destroyif_flags(ifc, LIST_FIRST(&ifc->ifc_iflist), IFC_F_FORCE); 541 542 IF_CLONE_REMREF(ifc); 543 } 544 545 static void 546 if_clone_free(struct if_clone *ifc) 547 { 548 549 KASSERT(LIST_EMPTY(&ifc->ifc_iflist), 550 ("%s: ifc_iflist not empty", __func__)); 551 552 IF_CLONE_LOCK_DESTROY(ifc); 553 delete_unrhdr(ifc->ifc_unrhdr); 554 free(ifc, M_CLONE); 555 } 556 557 /* 558 * Provide list of interface cloners to userspace. 559 */ 560 int 561 if_clone_list(struct if_clonereq *ifcr) 562 { 563 char *buf, *dst, *outbuf = NULL; 564 struct if_clone *ifc; 565 int buf_count, count, err = 0; 566 567 if (ifcr->ifcr_count < 0) 568 return (EINVAL); 569 570 IF_CLONERS_LOCK(); 571 /* 572 * Set our internal output buffer size. We could end up not 573 * reporting a cloner that is added between the unlock and lock 574 * below, but that's not a major problem. Not caping our 575 * allocation to the number of cloners actually in the system 576 * could be because that would let arbitrary users cause us to 577 * allocate arbitrary amounts of kernel memory. 578 */ 579 buf_count = (V_if_cloners_count < ifcr->ifcr_count) ? 580 V_if_cloners_count : ifcr->ifcr_count; 581 IF_CLONERS_UNLOCK(); 582 583 outbuf = malloc(IFNAMSIZ*buf_count, M_CLONE, M_WAITOK | M_ZERO); 584 585 IF_CLONERS_LOCK(); 586 587 ifcr->ifcr_total = V_if_cloners_count; 588 if ((dst = ifcr->ifcr_buffer) == NULL) { 589 /* Just asking how many there are. */ 590 goto done; 591 } 592 count = (V_if_cloners_count < buf_count) ? 593 V_if_cloners_count : buf_count; 594 595 for (ifc = LIST_FIRST(&V_if_cloners), buf = outbuf; 596 ifc != NULL && count != 0; 597 ifc = LIST_NEXT(ifc, ifc_list), count--, buf += IFNAMSIZ) { 598 strlcpy(buf, ifc->ifc_name, IFNAMSIZ); 599 } 600 601 done: 602 IF_CLONERS_UNLOCK(); 603 if (err == 0 && dst != NULL) 604 err = copyout(outbuf, dst, buf_count*IFNAMSIZ); 605 if (outbuf != NULL) 606 free(outbuf, M_CLONE); 607 return (err); 608 } 609 610 #ifdef VIMAGE 611 /* 612 * if_clone_restoregroup() is used in context of if_vmove(). 613 * 614 * Since if_detach_internal() has removed the interface from ALL groups, we 615 * need to "restore" interface membership in the cloner's group. Note that 616 * interface belongs to cloner in its home vnet, so we first find the original 617 * cloner, and then we confirm that cloner with the same name exists in the 618 * current vnet. 619 */ 620 void 621 if_clone_restoregroup(struct ifnet *ifp) 622 { 623 struct if_clone *ifc; 624 struct ifnet *ifcifp; 625 char ifc_name[IFCLOSIZ] = { [0] = '\0' }; 626 627 CURVNET_SET_QUIET(ifp->if_home_vnet); 628 IF_CLONERS_LOCK(); 629 LIST_FOREACH(ifc, &V_if_cloners, ifc_list) { 630 IF_CLONE_LOCK(ifc); 631 LIST_FOREACH(ifcifp, &ifc->ifc_iflist, if_clones) { 632 if (ifp == ifcifp) { 633 strncpy(ifc_name, ifc->ifc_name, IFCLOSIZ-1); 634 break; 635 } 636 } 637 IF_CLONE_UNLOCK(ifc); 638 if (ifc_name[0] != '\0') 639 break; 640 } 641 CURVNET_RESTORE(); 642 LIST_FOREACH(ifc, &V_if_cloners, ifc_list) 643 if (strcmp(ifc->ifc_name, ifc_name) == 0 && 644 ((ifc->ifc_flags & IFC_NOGROUP) == 0)) 645 break; 646 IF_CLONERS_UNLOCK(); 647 648 if (ifc != NULL) 649 if_addgroup(ifp, ifc_name); 650 } 651 #endif 652 653 /* 654 * A utility function to extract unit numbers from interface names of 655 * the form name###. 656 * 657 * Returns 0 on success and an error on failure. 658 */ 659 int 660 ifc_name2unit(const char *name, int *unit) 661 { 662 const char *cp; 663 int cutoff = INT_MAX / 10; 664 int cutlim = INT_MAX % 10; 665 666 for (cp = name; *cp != '\0' && (*cp < '0' || *cp > '9'); cp++) 667 ; 668 if (*cp == '\0') { 669 *unit = -1; 670 } else if (cp[0] == '0' && cp[1] != '\0') { 671 /* Disallow leading zeroes. */ 672 return (EINVAL); 673 } else { 674 for (*unit = 0; *cp != '\0'; cp++) { 675 if (*cp < '0' || *cp > '9') { 676 /* Bogus unit number. */ 677 return (EINVAL); 678 } 679 if (*unit > cutoff || 680 (*unit == cutoff && *cp - '0' > cutlim)) 681 return (EINVAL); 682 *unit = (*unit * 10) + (*cp - '0'); 683 } 684 } 685 686 return (0); 687 } 688 689 static int 690 ifc_alloc_unit_specific(struct if_clone *ifc, int *unit) 691 { 692 char name[IFNAMSIZ]; 693 694 if (*unit > ifc->ifc_maxunit) 695 return (ENOSPC); 696 697 if (alloc_unr_specific(ifc->ifc_unrhdr, *unit) == -1) 698 return (EEXIST); 699 700 snprintf(name, IFNAMSIZ, "%s%d", ifc->ifc_name, *unit); 701 if (ifunit(name) != NULL) { 702 free_unr(ifc->ifc_unrhdr, *unit); 703 return (EEXIST); 704 } 705 706 IF_CLONE_ADDREF(ifc); 707 708 return (0); 709 } 710 711 static int 712 ifc_alloc_unit_next(struct if_clone *ifc, int *unit) 713 { 714 int error; 715 716 *unit = alloc_unr(ifc->ifc_unrhdr); 717 if (*unit == -1) 718 return (ENOSPC); 719 720 free_unr(ifc->ifc_unrhdr, *unit); 721 for (;;) { 722 error = ifc_alloc_unit_specific(ifc, unit); 723 if (error != EEXIST) 724 break; 725 726 (*unit)++; 727 } 728 729 return (error); 730 } 731 732 int 733 ifc_alloc_unit(struct if_clone *ifc, int *unit) 734 { 735 if (*unit < 0) 736 return (ifc_alloc_unit_next(ifc, unit)); 737 else 738 return (ifc_alloc_unit_specific(ifc, unit)); 739 } 740 741 void 742 ifc_free_unit(struct if_clone *ifc, int unit) 743 { 744 745 free_unr(ifc->ifc_unrhdr, unit); 746 IF_CLONE_REMREF(ifc); 747 } 748 749 static int 750 ifc_simple_match(struct if_clone *ifc, const char *name) 751 { 752 const char *cp; 753 int i; 754 755 /* Match the name */ 756 for (cp = name, i = 0; i < strlen(ifc->ifc_name); i++, cp++) { 757 if (ifc->ifc_name[i] != *cp) 758 return (0); 759 } 760 761 /* Make sure there's a unit number or nothing after the name */ 762 for (; *cp != '\0'; cp++) { 763 if (*cp < '0' || *cp > '9') 764 return (0); 765 } 766 767 return (1); 768 } 769 770 static int 771 ifc_handle_unit(struct if_clone *ifc, char *name, size_t len, int *punit) 772 { 773 char *dp; 774 int wildcard; 775 int unit; 776 int err; 777 778 err = ifc_name2unit(name, &unit); 779 if (err != 0) 780 return (err); 781 782 wildcard = (unit < 0); 783 784 err = ifc_alloc_unit(ifc, &unit); 785 if (err != 0) 786 return (err); 787 788 /* In the wildcard case, we need to update the name. */ 789 if (wildcard) { 790 for (dp = name; *dp != '\0'; dp++); 791 if (snprintf(dp, len - (dp-name), "%d", unit) > 792 len - (dp-name) - 1) { 793 /* 794 * This can only be a programmer error and 795 * there's no straightforward way to recover if 796 * it happens. 797 */ 798 panic("if_clone_create(): interface name too long"); 799 } 800 } 801 *punit = unit; 802 803 return (0); 804 } 805 806 int 807 ifc_copyin(const struct ifc_data *ifd, void *target, size_t len) 808 { 809 if (ifd->params == NULL) 810 return (EINVAL); 811 812 if (ifd->flags & IFC_F_SYSSPACE) { 813 memcpy(target, ifd->params, len); 814 return (0); 815 } else 816 return (copyin(ifd->params, target, len)); 817 } 818 819 const char * 820 ifc_name(struct if_clone *ifc) 821 { 822 return (ifc->ifc_name); 823 } 824 825 void 826 ifc_flags_set(struct if_clone *ifc, int flags) 827 { 828 ifc->ifc_flags = flags; 829 } 830 831 int 832 ifc_flags_get(struct if_clone *ifc) 833 { 834 return (ifc->ifc_flags); 835 } 836