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