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