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