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