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 ifc_link_ifp(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 void 242 if_clone_addif(struct if_clone *ifc, struct ifnet *ifp) 243 { 244 ifc_link_ifp(ifc, ifp); 245 } 246 247 bool 248 ifc_unlink_ifp(struct if_clone *ifc, struct ifnet *ifp) 249 { 250 struct ifnet *ifcifp; 251 252 IF_CLONE_LOCK(ifc); 253 LIST_FOREACH(ifcifp, &ifc->ifc_iflist, if_clones) { 254 if (ifcifp == ifp) { 255 IFC_IFLIST_REMOVE(ifc, ifp); 256 break; 257 } 258 } 259 IF_CLONE_UNLOCK(ifc); 260 261 if (ifcifp != NULL && (ifc->ifc_flags & IFC_F_NOGROUP) == 0) 262 if_delgroup(ifp, ifc->ifc_name); 263 264 return (ifcifp != NULL); 265 } 266 267 static struct if_clone * 268 ifc_find_cloner(const char *name, struct vnet *vnet) 269 { 270 struct if_clone *ifc; 271 272 CURVNET_SET_QUIET(vnet); 273 IF_CLONERS_LOCK(); 274 LIST_FOREACH(ifc, &V_if_cloners, ifc_list) { 275 if (strcmp(ifc->ifc_name, name) == 0) { 276 break; 277 } 278 } 279 IF_CLONERS_UNLOCK(); 280 CURVNET_RESTORE(); 281 282 return (ifc); 283 } 284 285 /* 286 * Create a clone network interface. 287 */ 288 static int 289 if_clone_createif(struct if_clone *ifc, char *name, size_t len, 290 struct ifc_data *ifd, struct ifnet **ifpp) 291 { 292 int err, unit = 0; 293 294 if (ifunit(name) != NULL) 295 return (EEXIST); 296 297 if (ifc->ifc_flags & IFC_F_AUTOUNIT) { 298 if ((err = ifc_handle_unit(ifc, name, len, &unit)) != 0) 299 return (err); 300 ifd->unit = unit; 301 } 302 *ifpp = NULL; 303 err = (*ifc->ifc_create)(ifc, name, len, ifd, ifpp); 304 305 if (err == 0) { 306 MPASS(*ifpp != NULL); 307 if_clone_addif(ifc, *ifpp); 308 } else if (ifc->ifc_flags & IFC_F_AUTOUNIT) 309 ifc_free_unit(ifc, unit); 310 311 return (err); 312 } 313 314 /* 315 * Lookup and destroy a clone network interface. 316 */ 317 int 318 if_clone_destroy(const char *name) 319 { 320 int err; 321 struct if_clone *ifc; 322 struct ifnet *ifp; 323 324 ifp = ifunit_ref(name); 325 if (ifp == NULL) 326 return (ENXIO); 327 328 ifc = ifc_find_cloner(ifp->if_dname, ifp->if_home_vnet); 329 if (ifc == NULL) { 330 if_rele(ifp); 331 return (EINVAL); 332 } 333 334 err = if_clone_destroyif(ifc, ifp); 335 if_rele(ifp); 336 return err; 337 } 338 339 /* 340 * Destroy a clone network interface. 341 */ 342 static int 343 if_clone_destroyif_flags(struct if_clone *ifc, struct ifnet *ifp, uint32_t flags) 344 { 345 int err; 346 347 /* 348 * Given that the cloned ifnet might be attached to a different 349 * vnet from where its cloner was registered, we have to 350 * switch to the vnet context of the target vnet. 351 */ 352 CURVNET_SET_QUIET(ifp->if_vnet); 353 354 if (!ifc_unlink_ifp(ifc, ifp)) { 355 CURVNET_RESTORE(); 356 return (ENXIO); /* ifp is not on the list. */ 357 } 358 359 int unit = ifp->if_dunit; 360 err = (*ifc->ifc_destroy)(ifc, ifp, flags); 361 362 if (err != 0) 363 ifc_link_ifp(ifc, ifp); 364 else if (ifc->ifc_flags & IFC_F_AUTOUNIT) 365 ifc_free_unit(ifc, unit); 366 CURVNET_RESTORE(); 367 return (err); 368 } 369 370 int 371 if_clone_destroyif(struct if_clone *ifc, struct ifnet *ifp) 372 { 373 return (if_clone_destroyif_flags(ifc, ifp, 0)); 374 } 375 376 static struct if_clone * 377 if_clone_alloc(const char *name, int maxunit) 378 { 379 struct if_clone *ifc; 380 381 KASSERT(name != NULL, ("%s: no name\n", __func__)); 382 383 ifc = malloc(sizeof(struct if_clone), M_CLONE, M_WAITOK | M_ZERO); 384 strncpy(ifc->ifc_name, name, IFCLOSIZ-1); 385 IF_CLONE_LOCK_INIT(ifc); 386 IF_CLONE_ADDREF(ifc); 387 ifc->ifc_maxunit = maxunit ? maxunit : IF_MAXUNIT; 388 ifc->ifc_unrhdr = new_unrhdr(0, ifc->ifc_maxunit, &ifc->ifc_mtx); 389 LIST_INIT(&ifc->ifc_iflist); 390 391 return (ifc); 392 } 393 394 static int 395 if_clone_attach(struct if_clone *ifc) 396 { 397 struct if_clone *ifc1; 398 399 IF_CLONERS_LOCK(); 400 LIST_FOREACH(ifc1, &V_if_cloners, ifc_list) 401 if (strcmp(ifc->ifc_name, ifc1->ifc_name) == 0) { 402 IF_CLONERS_UNLOCK(); 403 IF_CLONE_REMREF(ifc); 404 return (EEXIST); 405 } 406 LIST_INSERT_HEAD(&V_if_cloners, ifc, ifc_list); 407 V_if_cloners_count++; 408 IF_CLONERS_UNLOCK(); 409 410 return (0); 411 } 412 413 struct if_clone * 414 ifc_attach_cloner(const char *name, struct if_clone_addreq *req) 415 { 416 if (req->create_f == NULL || req->destroy_f == NULL) 417 return (NULL); 418 if (strnlen(name, IFCLOSIZ) >= (IFCLOSIZ - 1)) 419 return (NULL); 420 421 struct if_clone *ifc = if_clone_alloc(name, req->maxunit); 422 ifc->ifc_match = req->match_f != NULL ? req->match_f : ifc_simple_match; 423 ifc->ifc_create = req->create_f; 424 ifc->ifc_destroy = req->destroy_f; 425 ifc->ifc_flags = (req->flags & (IFC_F_AUTOUNIT | IFC_F_NOGROUP)); 426 427 if (if_clone_attach(ifc) != 0) 428 return (NULL); 429 430 EVENTHANDLER_INVOKE(if_clone_event, ifc); 431 432 return (ifc); 433 } 434 435 void 436 ifc_detach_cloner(struct if_clone *ifc) 437 { 438 if_clone_detach(ifc); 439 } 440 441 442 #ifdef CLONE_COMPAT_13 443 444 static int 445 ifc_advanced_create_wrapper(struct if_clone *ifc, char *name, size_t maxlen, 446 struct ifc_data *ifc_data, struct ifnet **ifpp) 447 { 448 int error = ifc->ifca_create(ifc, name, maxlen, ifc_data->params); 449 450 if (error == 0) 451 *ifpp = ifunit(name); 452 return (error); 453 } 454 455 static int 456 ifc_advanced_destroy_wrapper(struct if_clone *ifc, struct ifnet *ifp, uint32_t flags) 457 { 458 if (ifc->ifca_destroy == NULL) 459 return (ENOTSUP); 460 return (ifc->ifca_destroy(ifc, ifp)); 461 } 462 463 struct if_clone * 464 if_clone_advanced(const char *name, u_int maxunit, ifc_match_t match, 465 ifc_create_t create, ifc_destroy_t destroy) 466 { 467 struct if_clone *ifc; 468 469 ifc = if_clone_alloc(name, maxunit); 470 ifc->ifc_match = match; 471 ifc->ifc_create = ifc_advanced_create_wrapper; 472 ifc->ifc_destroy = ifc_advanced_destroy_wrapper; 473 ifc->ifca_destroy = destroy; 474 ifc->ifca_create = create; 475 476 if (if_clone_attach(ifc) != 0) 477 return (NULL); 478 479 EVENTHANDLER_INVOKE(if_clone_event, ifc); 480 481 return (ifc); 482 } 483 484 static int 485 ifc_simple_create_wrapper(struct if_clone *ifc, char *name, size_t maxlen, 486 struct ifc_data *ifc_data, struct ifnet **ifpp) 487 { 488 int unit = 0; 489 490 ifc_name2unit(name, &unit); 491 int error = ifc->ifcs_create(ifc, unit, ifc_data->params); 492 if (error == 0) 493 *ifpp = ifunit(name); 494 return (error); 495 } 496 497 static int 498 ifc_simple_destroy_wrapper(struct if_clone *ifc, struct ifnet *ifp, uint32_t flags) 499 { 500 if (ifp->if_dunit < ifc->ifcs_minifs && (flags & IFC_F_FORCE) == 0) 501 return (EINVAL); 502 503 ifc->ifcs_destroy(ifp); 504 return (0); 505 } 506 507 struct if_clone * 508 if_clone_simple(const char *name, ifcs_create_t create, ifcs_destroy_t destroy, 509 u_int minifs) 510 { 511 struct if_clone *ifc; 512 u_int unit; 513 514 ifc = if_clone_alloc(name, 0); 515 ifc->ifc_match = ifc_simple_match; 516 ifc->ifc_create = ifc_simple_create_wrapper; 517 ifc->ifc_destroy = ifc_simple_destroy_wrapper; 518 ifc->ifcs_create = create; 519 ifc->ifcs_destroy = destroy; 520 ifc->ifcs_minifs = minifs; 521 ifc->ifc_flags = IFC_F_AUTOUNIT; 522 523 if (if_clone_attach(ifc) != 0) 524 return (NULL); 525 526 for (unit = 0; unit < minifs; unit++) { 527 char name[IFNAMSIZ]; 528 int error __unused; 529 struct ifc_data ifd = {}; 530 struct ifnet *ifp; 531 532 snprintf(name, IFNAMSIZ, "%s%d", ifc->ifc_name, unit); 533 error = if_clone_createif(ifc, name, IFNAMSIZ, &ifd, &ifp); 534 KASSERT(error == 0, 535 ("%s: failed to create required interface %s", 536 __func__, name)); 537 } 538 539 EVENTHANDLER_INVOKE(if_clone_event, ifc); 540 541 return (ifc); 542 } 543 #endif 544 545 /* 546 * Unregister a network interface cloner. 547 */ 548 void 549 if_clone_detach(struct if_clone *ifc) 550 { 551 552 IF_CLONERS_LOCK(); 553 LIST_REMOVE(ifc, ifc_list); 554 V_if_cloners_count--; 555 IF_CLONERS_UNLOCK(); 556 557 /* destroy all interfaces for this cloner */ 558 while (!LIST_EMPTY(&ifc->ifc_iflist)) 559 if_clone_destroyif_flags(ifc, LIST_FIRST(&ifc->ifc_iflist), IFC_F_FORCE); 560 561 IF_CLONE_REMREF(ifc); 562 } 563 564 static void 565 if_clone_free(struct if_clone *ifc) 566 { 567 568 KASSERT(LIST_EMPTY(&ifc->ifc_iflist), 569 ("%s: ifc_iflist not empty", __func__)); 570 571 IF_CLONE_LOCK_DESTROY(ifc); 572 delete_unrhdr(ifc->ifc_unrhdr); 573 free(ifc, M_CLONE); 574 } 575 576 /* 577 * Provide list of interface cloners to userspace. 578 */ 579 int 580 if_clone_list(struct if_clonereq *ifcr) 581 { 582 char *buf, *dst, *outbuf = NULL; 583 struct if_clone *ifc; 584 int buf_count, count, err = 0; 585 586 if (ifcr->ifcr_count < 0) 587 return (EINVAL); 588 589 IF_CLONERS_LOCK(); 590 /* 591 * Set our internal output buffer size. We could end up not 592 * reporting a cloner that is added between the unlock and lock 593 * below, but that's not a major problem. Not caping our 594 * allocation to the number of cloners actually in the system 595 * could be because that would let arbitrary users cause us to 596 * allocate arbitrary amounts of kernel memory. 597 */ 598 buf_count = (V_if_cloners_count < ifcr->ifcr_count) ? 599 V_if_cloners_count : ifcr->ifcr_count; 600 IF_CLONERS_UNLOCK(); 601 602 outbuf = malloc(IFNAMSIZ*buf_count, M_CLONE, M_WAITOK | M_ZERO); 603 604 IF_CLONERS_LOCK(); 605 606 ifcr->ifcr_total = V_if_cloners_count; 607 if ((dst = ifcr->ifcr_buffer) == NULL) { 608 /* Just asking how many there are. */ 609 goto done; 610 } 611 count = (V_if_cloners_count < buf_count) ? 612 V_if_cloners_count : buf_count; 613 614 for (ifc = LIST_FIRST(&V_if_cloners), buf = outbuf; 615 ifc != NULL && count != 0; 616 ifc = LIST_NEXT(ifc, ifc_list), count--, buf += IFNAMSIZ) { 617 strlcpy(buf, ifc->ifc_name, IFNAMSIZ); 618 } 619 620 done: 621 IF_CLONERS_UNLOCK(); 622 if (err == 0 && dst != NULL) 623 err = copyout(outbuf, dst, buf_count*IFNAMSIZ); 624 if (outbuf != NULL) 625 free(outbuf, M_CLONE); 626 return (err); 627 } 628 629 #ifdef VIMAGE 630 /* 631 * if_clone_restoregroup() is used in context of if_vmove(). 632 * 633 * Since if_detach_internal() has removed the interface from ALL groups, we 634 * need to "restore" interface membership in the cloner's group. Note that 635 * interface belongs to cloner in its home vnet, so we first find the original 636 * cloner, and then we confirm that cloner with the same name exists in the 637 * current vnet. 638 */ 639 void 640 if_clone_restoregroup(struct ifnet *ifp) 641 { 642 struct if_clone *ifc; 643 struct ifnet *ifcifp; 644 char ifc_name[IFCLOSIZ] = { [0] = '\0' }; 645 646 CURVNET_SET_QUIET(ifp->if_home_vnet); 647 IF_CLONERS_LOCK(); 648 LIST_FOREACH(ifc, &V_if_cloners, ifc_list) { 649 IF_CLONE_LOCK(ifc); 650 LIST_FOREACH(ifcifp, &ifc->ifc_iflist, if_clones) { 651 if (ifp == ifcifp) { 652 strncpy(ifc_name, ifc->ifc_name, IFCLOSIZ-1); 653 break; 654 } 655 } 656 IF_CLONE_UNLOCK(ifc); 657 if (ifc_name[0] != '\0') 658 break; 659 } 660 CURVNET_RESTORE(); 661 LIST_FOREACH(ifc, &V_if_cloners, ifc_list) 662 if (strcmp(ifc->ifc_name, ifc_name) == 0 && 663 ((ifc->ifc_flags & IFC_NOGROUP) == 0)) 664 break; 665 IF_CLONERS_UNLOCK(); 666 667 if (ifc != NULL) 668 if_addgroup(ifp, ifc_name); 669 } 670 #endif 671 672 /* 673 * A utility function to extract unit numbers from interface names of 674 * the form name###. 675 * 676 * Returns 0 on success and an error on failure. 677 */ 678 int 679 ifc_name2unit(const char *name, int *unit) 680 { 681 const char *cp; 682 int cutoff = INT_MAX / 10; 683 int cutlim = INT_MAX % 10; 684 685 for (cp = name; *cp != '\0' && (*cp < '0' || *cp > '9'); cp++) 686 ; 687 if (*cp == '\0') { 688 *unit = -1; 689 } else if (cp[0] == '0' && cp[1] != '\0') { 690 /* Disallow leading zeroes. */ 691 return (EINVAL); 692 } else { 693 for (*unit = 0; *cp != '\0'; cp++) { 694 if (*cp < '0' || *cp > '9') { 695 /* Bogus unit number. */ 696 return (EINVAL); 697 } 698 if (*unit > cutoff || 699 (*unit == cutoff && *cp - '0' > cutlim)) 700 return (EINVAL); 701 *unit = (*unit * 10) + (*cp - '0'); 702 } 703 } 704 705 return (0); 706 } 707 708 static int 709 ifc_alloc_unit_specific(struct if_clone *ifc, int *unit) 710 { 711 char name[IFNAMSIZ]; 712 713 if (*unit > ifc->ifc_maxunit) 714 return (ENOSPC); 715 716 if (alloc_unr_specific(ifc->ifc_unrhdr, *unit) == -1) 717 return (EEXIST); 718 719 snprintf(name, IFNAMSIZ, "%s%d", ifc->ifc_name, *unit); 720 if (ifunit(name) != NULL) { 721 free_unr(ifc->ifc_unrhdr, *unit); 722 return (EEXIST); 723 } 724 725 IF_CLONE_ADDREF(ifc); 726 727 return (0); 728 } 729 730 static int 731 ifc_alloc_unit_next(struct if_clone *ifc, int *unit) 732 { 733 int error; 734 735 *unit = alloc_unr(ifc->ifc_unrhdr); 736 if (*unit == -1) 737 return (ENOSPC); 738 739 free_unr(ifc->ifc_unrhdr, *unit); 740 for (;;) { 741 error = ifc_alloc_unit_specific(ifc, unit); 742 if (error != EEXIST) 743 break; 744 745 (*unit)++; 746 } 747 748 return (error); 749 } 750 751 int 752 ifc_alloc_unit(struct if_clone *ifc, int *unit) 753 { 754 if (*unit < 0) 755 return (ifc_alloc_unit_next(ifc, unit)); 756 else 757 return (ifc_alloc_unit_specific(ifc, unit)); 758 } 759 760 void 761 ifc_free_unit(struct if_clone *ifc, int unit) 762 { 763 764 free_unr(ifc->ifc_unrhdr, unit); 765 IF_CLONE_REMREF(ifc); 766 } 767 768 static int 769 ifc_simple_match(struct if_clone *ifc, const char *name) 770 { 771 const char *cp; 772 int i; 773 774 /* Match the name */ 775 for (cp = name, i = 0; i < strlen(ifc->ifc_name); i++, cp++) { 776 if (ifc->ifc_name[i] != *cp) 777 return (0); 778 } 779 780 /* Make sure there's a unit number or nothing after the name */ 781 for (; *cp != '\0'; cp++) { 782 if (*cp < '0' || *cp > '9') 783 return (0); 784 } 785 786 return (1); 787 } 788 789 static int 790 ifc_handle_unit(struct if_clone *ifc, char *name, size_t len, int *punit) 791 { 792 char *dp; 793 int wildcard; 794 int unit; 795 int err; 796 797 err = ifc_name2unit(name, &unit); 798 if (err != 0) 799 return (err); 800 801 wildcard = (unit < 0); 802 803 err = ifc_alloc_unit(ifc, &unit); 804 if (err != 0) 805 return (err); 806 807 /* In the wildcard case, we need to update the name. */ 808 if (wildcard) { 809 for (dp = name; *dp != '\0'; dp++); 810 if (snprintf(dp, len - (dp-name), "%d", unit) > 811 len - (dp-name) - 1) { 812 /* 813 * This can only be a programmer error and 814 * there's no straightforward way to recover if 815 * it happens. 816 */ 817 panic("if_clone_create(): interface name too long"); 818 } 819 } 820 *punit = unit; 821 822 return (0); 823 } 824 825 int 826 ifc_copyin(const struct ifc_data *ifd, void *target, size_t len) 827 { 828 if (ifd->params == NULL) 829 return (EINVAL); 830 831 if (ifd->flags & IFC_F_SYSSPACE) { 832 memcpy(target, ifd->params, len); 833 return (0); 834 } else 835 return (copyin(ifd->params, target, len)); 836 } 837 838 const char * 839 ifc_name(struct if_clone *ifc) 840 { 841 return (ifc->ifc_name); 842 } 843 844 void 845 ifc_flags_set(struct if_clone *ifc, int flags) 846 { 847 ifc->ifc_flags = flags; 848 } 849 850 int 851 ifc_flags_get(struct if_clone *ifc) 852 { 853 return (ifc->ifc_flags); 854 } 855