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