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