1 /*- 2 * Copyright (c) 1980, 1986, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 4. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * @(#)if.c 8.5 (Berkeley) 1/9/95 30 * $FreeBSD$ 31 */ 32 33 #include <sys/param.h> 34 #include <sys/malloc.h> 35 #include <sys/limits.h> 36 #include <sys/lock.h> 37 #include <sys/mutex.h> 38 #include <sys/kernel.h> 39 #include <sys/systm.h> 40 #include <sys/types.h> 41 #include <sys/socket.h> 42 #include <sys/vimage.h> 43 44 #include <net/if.h> 45 #include <net/if_clone.h> 46 #if 0 47 #include <net/if_dl.h> 48 #endif 49 #include <net/if_types.h> 50 #include <net/if_var.h> 51 #include <net/radix.h> 52 #include <net/route.h> 53 #include <net/vnet.h> 54 55 static void if_clone_free(struct if_clone *ifc); 56 static int if_clone_createif(struct if_clone *ifc, char *name, size_t len, 57 caddr_t params); 58 static int vnet_clone_iattach(const void *); 59 60 static struct mtx if_cloners_mtx; 61 #ifdef VIMAGE_GLOBALS 62 static int if_cloners_count; 63 LIST_HEAD(, if_clone) if_cloners; 64 #endif 65 66 #define IF_CLONERS_LOCK_INIT() \ 67 mtx_init(&if_cloners_mtx, "if_cloners lock", NULL, MTX_DEF) 68 #define IF_CLONERS_LOCK_ASSERT() mtx_assert(&if_cloners_mtx, MA_OWNED) 69 #define IF_CLONERS_LOCK() mtx_lock(&if_cloners_mtx) 70 #define IF_CLONERS_UNLOCK() mtx_unlock(&if_cloners_mtx) 71 72 #define IF_CLONE_LOCK_INIT(ifc) \ 73 mtx_init(&(ifc)->ifc_mtx, "if_clone lock", NULL, MTX_DEF) 74 #define IF_CLONE_LOCK_DESTROY(ifc) mtx_destroy(&(ifc)->ifc_mtx) 75 #define IF_CLONE_LOCK_ASSERT(ifc) mtx_assert(&(ifc)->ifc_mtx, MA_OWNED) 76 #define IF_CLONE_LOCK(ifc) mtx_lock(&(ifc)->ifc_mtx) 77 #define IF_CLONE_UNLOCK(ifc) mtx_unlock(&(ifc)->ifc_mtx) 78 79 #define IF_CLONE_ADDREF(ifc) \ 80 do { \ 81 IF_CLONE_LOCK(ifc); \ 82 IF_CLONE_ADDREF_LOCKED(ifc); \ 83 IF_CLONE_UNLOCK(ifc); \ 84 } while (0) 85 #define IF_CLONE_ADDREF_LOCKED(ifc) \ 86 do { \ 87 IF_CLONE_LOCK_ASSERT(ifc); \ 88 KASSERT((ifc)->ifc_refcnt >= 0, \ 89 ("negative refcnt %ld", (ifc)->ifc_refcnt)); \ 90 (ifc)->ifc_refcnt++; \ 91 } while (0) 92 #define IF_CLONE_REMREF(ifc) \ 93 do { \ 94 IF_CLONE_LOCK(ifc); \ 95 IF_CLONE_REMREF_LOCKED(ifc); \ 96 } while (0) 97 #define IF_CLONE_REMREF_LOCKED(ifc) \ 98 do { \ 99 IF_CLONE_LOCK_ASSERT(ifc); \ 100 KASSERT((ifc)->ifc_refcnt > 0, \ 101 ("bogus refcnt %ld", (ifc)->ifc_refcnt)); \ 102 if (--(ifc)->ifc_refcnt == 0) { \ 103 IF_CLONE_UNLOCK(ifc); \ 104 if_clone_free(ifc); \ 105 } else { \ 106 /* silently free the lock */ \ 107 IF_CLONE_UNLOCK(ifc); \ 108 } \ 109 } while (0) 110 111 #define IFC_IFLIST_INSERT(_ifc, _ifp) \ 112 LIST_INSERT_HEAD(&_ifc->ifc_iflist, _ifp, if_clones) 113 #define IFC_IFLIST_REMOVE(_ifc, _ifp) \ 114 LIST_REMOVE(_ifp, if_clones) 115 116 static MALLOC_DEFINE(M_CLONE, "clone", "interface cloning framework"); 117 118 #ifndef VIMAGE_GLOBALS 119 static const vnet_modinfo_t vnet_clone_modinfo = { 120 .vmi_id = VNET_MOD_IF_CLONE, 121 .vmi_name = "if_clone", 122 .vmi_iattach = vnet_clone_iattach 123 }; 124 #endif /* !VIMAGE_GLOBALS */ 125 126 static int vnet_clone_iattach(const void *unused __unused) 127 { 128 INIT_VNET_NET(curvnet); 129 130 LIST_INIT(&V_if_cloners); 131 return (0); 132 } 133 134 void 135 if_clone_init(void) 136 { 137 138 IF_CLONERS_LOCK_INIT(); 139 #ifndef VIMAGE_GLOBALS 140 vnet_mod_register(&vnet_clone_modinfo); 141 #else 142 vnet_clone_iattach(NULL); 143 #endif 144 } 145 146 /* 147 * Lookup and create a clone network interface. 148 */ 149 int 150 if_clone_create(char *name, size_t len, caddr_t params) 151 { 152 INIT_VNET_NET(curvnet); 153 struct if_clone *ifc; 154 155 /* Try to find an applicable cloner for this request */ 156 IF_CLONERS_LOCK(); 157 LIST_FOREACH(ifc, &V_if_cloners, ifc_list) { 158 if (ifc->ifc_match(ifc, name)) { 159 break; 160 } 161 } 162 #ifdef VIMAGE 163 if (ifc == NULL && !IS_DEFAULT_VNET(curvnet)) { 164 CURVNET_SET_QUIET(vnet0); 165 INIT_VNET_NET(vnet0); 166 LIST_FOREACH(ifc, &V_if_cloners, ifc_list) { 167 if (ifc->ifc_match(ifc, name)) 168 break; 169 } 170 CURVNET_RESTORE(); 171 } 172 #endif 173 IF_CLONERS_UNLOCK(); 174 175 if (ifc == NULL) 176 return (EINVAL); 177 178 return (if_clone_createif(ifc, name, len, params)); 179 } 180 181 /* 182 * Create a clone network interface. 183 */ 184 static int 185 if_clone_createif(struct if_clone *ifc, char *name, size_t len, caddr_t params) 186 { 187 int err; 188 struct ifnet *ifp; 189 190 if (ifunit(name) != NULL) 191 return (EEXIST); 192 193 err = (*ifc->ifc_create)(ifc, name, len, params); 194 195 if (!err) { 196 ifp = ifunit(name); 197 if (ifp == NULL) 198 panic("%s: lookup failed for %s", __func__, name); 199 200 if_addgroup(ifp, ifc->ifc_name); 201 202 IF_CLONE_LOCK(ifc); 203 IFC_IFLIST_INSERT(ifc, ifp); 204 IF_CLONE_UNLOCK(ifc); 205 } 206 207 return (err); 208 } 209 210 /* 211 * Lookup and destroy a clone network interface. 212 */ 213 int 214 if_clone_destroy(const char *name) 215 { 216 INIT_VNET_NET(curvnet); 217 struct if_clone *ifc; 218 struct ifnet *ifp; 219 220 ifp = ifunit(name); 221 if (ifp == NULL) 222 return (ENXIO); 223 224 /* Find the cloner for this interface */ 225 IF_CLONERS_LOCK(); 226 LIST_FOREACH(ifc, &V_if_cloners, ifc_list) { 227 if (strcmp(ifc->ifc_name, ifp->if_dname) == 0) { 228 break; 229 } 230 } 231 #ifdef VIMAGE 232 if (ifc == NULL && !IS_DEFAULT_VNET(curvnet)) { 233 CURVNET_SET_QUIET(vnet0); 234 INIT_VNET_NET(vnet0); 235 LIST_FOREACH(ifc, &V_if_cloners, ifc_list) { 236 if (ifc->ifc_match(ifc, name)) 237 break; 238 } 239 CURVNET_RESTORE(); 240 } 241 #endif 242 IF_CLONERS_UNLOCK(); 243 if (ifc == NULL) 244 return (EINVAL); 245 246 return (if_clone_destroyif(ifc, ifp)); 247 } 248 249 /* 250 * Destroy a clone network interface. 251 */ 252 int 253 if_clone_destroyif(struct if_clone *ifc, struct ifnet *ifp) 254 { 255 int err; 256 257 if (ifc->ifc_destroy == NULL) 258 return(EOPNOTSUPP); 259 260 /* 261 * Given that the cloned ifnet might be attached to a different 262 * vnet from where its cloner was registered, we have to 263 * switch to the vnet context of the target vnet. 264 */ 265 CURVNET_SET_QUIET(ifp->if_vnet); 266 267 IF_CLONE_LOCK(ifc); 268 IFC_IFLIST_REMOVE(ifc, ifp); 269 IF_CLONE_UNLOCK(ifc); 270 271 if_delgroup(ifp, ifc->ifc_name); 272 273 err = (*ifc->ifc_destroy)(ifc, ifp); 274 275 if (err != 0) { 276 if_addgroup(ifp, ifc->ifc_name); 277 278 IF_CLONE_LOCK(ifc); 279 IFC_IFLIST_INSERT(ifc, ifp); 280 IF_CLONE_UNLOCK(ifc); 281 } 282 CURVNET_RESTORE(); 283 return (err); 284 } 285 286 /* 287 * Register a network interface cloner. 288 */ 289 void 290 if_clone_attach(struct if_clone *ifc) 291 { 292 INIT_VNET_NET(curvnet); 293 int len, maxclone; 294 295 /* 296 * Compute bitmap size and allocate it. 297 */ 298 maxclone = ifc->ifc_maxunit + 1; 299 len = maxclone >> 3; 300 if ((len << 3) < maxclone) 301 len++; 302 ifc->ifc_units = malloc(len, M_CLONE, M_WAITOK | M_ZERO); 303 ifc->ifc_bmlen = len; 304 IF_CLONE_LOCK_INIT(ifc); 305 IF_CLONE_ADDREF(ifc); 306 307 IF_CLONERS_LOCK(); 308 LIST_INSERT_HEAD(&V_if_cloners, ifc, ifc_list); 309 V_if_cloners_count++; 310 IF_CLONERS_UNLOCK(); 311 312 LIST_INIT(&ifc->ifc_iflist); 313 314 if (ifc->ifc_attach != NULL) 315 (*ifc->ifc_attach)(ifc); 316 EVENTHANDLER_INVOKE(if_clone_event, ifc); 317 } 318 319 /* 320 * Unregister a network interface cloner. 321 */ 322 void 323 if_clone_detach(struct if_clone *ifc) 324 { 325 INIT_VNET_NET(curvnet); 326 struct ifc_simple_data *ifcs = ifc->ifc_data; 327 328 IF_CLONERS_LOCK(); 329 LIST_REMOVE(ifc, ifc_list); 330 V_if_cloners_count--; 331 IF_CLONERS_UNLOCK(); 332 333 /* Allow all simples to be destroyed */ 334 if (ifc->ifc_attach == ifc_simple_attach) 335 ifcs->ifcs_minifs = 0; 336 337 /* destroy all interfaces for this cloner */ 338 while (!LIST_EMPTY(&ifc->ifc_iflist)) 339 if_clone_destroyif(ifc, LIST_FIRST(&ifc->ifc_iflist)); 340 341 IF_CLONE_REMREF(ifc); 342 } 343 344 static void 345 if_clone_free(struct if_clone *ifc) 346 { 347 for (int bytoff = 0; bytoff < ifc->ifc_bmlen; bytoff++) { 348 KASSERT(ifc->ifc_units[bytoff] == 0x00, 349 ("ifc_units[%d] is not empty", bytoff)); 350 } 351 352 KASSERT(LIST_EMPTY(&ifc->ifc_iflist), 353 ("%s: ifc_iflist not empty", __func__)); 354 355 IF_CLONE_LOCK_DESTROY(ifc); 356 free(ifc->ifc_units, M_CLONE); 357 } 358 359 /* 360 * Provide list of interface cloners to userspace. 361 */ 362 int 363 if_clone_list(struct if_clonereq *ifcr) 364 { 365 INIT_VNET_NET(curvnet); 366 char *buf, *dst, *outbuf = NULL; 367 struct if_clone *ifc; 368 int buf_count, count, err = 0; 369 370 if (ifcr->ifcr_count < 0) 371 return (EINVAL); 372 373 IF_CLONERS_LOCK(); 374 /* 375 * Set our internal output buffer size. We could end up not 376 * reporting a cloner that is added between the unlock and lock 377 * below, but that's not a major problem. Not caping our 378 * allocation to the number of cloners actually in the system 379 * could be because that would let arbitrary users cause us to 380 * allocate abritrary amounts of kernel memory. 381 */ 382 buf_count = (V_if_cloners_count < ifcr->ifcr_count) ? 383 V_if_cloners_count : ifcr->ifcr_count; 384 IF_CLONERS_UNLOCK(); 385 386 outbuf = malloc(IFNAMSIZ*buf_count, M_CLONE, M_WAITOK | M_ZERO); 387 388 IF_CLONERS_LOCK(); 389 390 ifcr->ifcr_total = V_if_cloners_count; 391 if ((dst = ifcr->ifcr_buffer) == NULL) { 392 /* Just asking how many there are. */ 393 goto done; 394 } 395 count = (V_if_cloners_count < buf_count) ? 396 V_if_cloners_count : buf_count; 397 398 for (ifc = LIST_FIRST(&V_if_cloners), buf = outbuf; 399 ifc != NULL && count != 0; 400 ifc = LIST_NEXT(ifc, ifc_list), count--, buf += IFNAMSIZ) { 401 strlcpy(buf, ifc->ifc_name, IFNAMSIZ); 402 } 403 404 done: 405 IF_CLONERS_UNLOCK(); 406 if (err == 0) 407 err = copyout(outbuf, dst, buf_count*IFNAMSIZ); 408 if (outbuf != NULL) 409 free(outbuf, M_CLONE); 410 return (err); 411 } 412 413 /* 414 * A utility function to extract unit numbers from interface names of 415 * the form name###. 416 * 417 * Returns 0 on success and an error on failure. 418 */ 419 int 420 ifc_name2unit(const char *name, int *unit) 421 { 422 const char *cp; 423 int cutoff = INT_MAX / 10; 424 int cutlim = INT_MAX % 10; 425 426 for (cp = name; *cp != '\0' && (*cp < '0' || *cp > '9'); cp++); 427 if (*cp == '\0') { 428 *unit = -1; 429 } else if (cp[0] == '0' && cp[1] != '\0') { 430 /* Disallow leading zeroes. */ 431 return (EINVAL); 432 } else { 433 for (*unit = 0; *cp != '\0'; cp++) { 434 if (*cp < '0' || *cp > '9') { 435 /* Bogus unit number. */ 436 return (EINVAL); 437 } 438 if (*unit > cutoff || 439 (*unit == cutoff && *cp - '0' > cutlim)) 440 return (EINVAL); 441 *unit = (*unit * 10) + (*cp - '0'); 442 } 443 } 444 445 return (0); 446 } 447 448 int 449 ifc_alloc_unit(struct if_clone *ifc, int *unit) 450 { 451 int wildcard, bytoff, bitoff; 452 int err = 0; 453 454 IF_CLONE_LOCK(ifc); 455 456 bytoff = bitoff = 0; 457 wildcard = (*unit < 0); 458 /* 459 * Find a free unit if none was given. 460 */ 461 if (wildcard) { 462 while ((bytoff < ifc->ifc_bmlen) 463 && (ifc->ifc_units[bytoff] == 0xff)) 464 bytoff++; 465 if (bytoff >= ifc->ifc_bmlen) { 466 err = ENOSPC; 467 goto done; 468 } 469 while ((ifc->ifc_units[bytoff] & (1 << bitoff)) != 0) 470 bitoff++; 471 *unit = (bytoff << 3) + bitoff; 472 } 473 474 if (*unit > ifc->ifc_maxunit) { 475 err = ENOSPC; 476 goto done; 477 } 478 479 if (!wildcard) { 480 bytoff = *unit >> 3; 481 bitoff = *unit - (bytoff << 3); 482 } 483 484 if((ifc->ifc_units[bytoff] & (1 << bitoff)) != 0) { 485 err = EEXIST; 486 goto done; 487 } 488 /* 489 * Allocate the unit in the bitmap. 490 */ 491 KASSERT((ifc->ifc_units[bytoff] & (1 << bitoff)) == 0, 492 ("%s: bit is already set", __func__)); 493 ifc->ifc_units[bytoff] |= (1 << bitoff); 494 IF_CLONE_ADDREF_LOCKED(ifc); 495 496 done: 497 IF_CLONE_UNLOCK(ifc); 498 return (err); 499 } 500 501 void 502 ifc_free_unit(struct if_clone *ifc, int unit) 503 { 504 int bytoff, bitoff; 505 506 507 /* 508 * Compute offset in the bitmap and deallocate the unit. 509 */ 510 bytoff = unit >> 3; 511 bitoff = unit - (bytoff << 3); 512 513 IF_CLONE_LOCK(ifc); 514 KASSERT((ifc->ifc_units[bytoff] & (1 << bitoff)) != 0, 515 ("%s: bit is already cleared", __func__)); 516 ifc->ifc_units[bytoff] &= ~(1 << bitoff); 517 IF_CLONE_REMREF_LOCKED(ifc); /* releases lock */ 518 } 519 520 void 521 ifc_simple_attach(struct if_clone *ifc) 522 { 523 int err; 524 int unit; 525 char name[IFNAMSIZ]; 526 struct ifc_simple_data *ifcs = ifc->ifc_data; 527 528 KASSERT(ifcs->ifcs_minifs - 1 <= ifc->ifc_maxunit, 529 ("%s: %s requested more units than allowed (%d > %d)", 530 __func__, ifc->ifc_name, ifcs->ifcs_minifs, 531 ifc->ifc_maxunit + 1)); 532 533 for (unit = 0; unit < ifcs->ifcs_minifs; unit++) { 534 snprintf(name, IFNAMSIZ, "%s%d", ifc->ifc_name, unit); 535 err = if_clone_createif(ifc, name, IFNAMSIZ, NULL); 536 KASSERT(err == 0, 537 ("%s: failed to create required interface %s", 538 __func__, name)); 539 } 540 } 541 542 int 543 ifc_simple_match(struct if_clone *ifc, const char *name) 544 { 545 const char *cp; 546 int i; 547 548 /* Match the name */ 549 for (cp = name, i = 0; i < strlen(ifc->ifc_name); i++, cp++) { 550 if (ifc->ifc_name[i] != *cp) 551 return (0); 552 } 553 554 /* Make sure there's a unit number or nothing after the name */ 555 for (; *cp != '\0'; cp++) { 556 if (*cp < '0' || *cp > '9') 557 return (0); 558 } 559 560 return (1); 561 } 562 563 int 564 ifc_simple_create(struct if_clone *ifc, char *name, size_t len, caddr_t params) 565 { 566 char *dp; 567 int wildcard; 568 int unit; 569 int err; 570 struct ifc_simple_data *ifcs = ifc->ifc_data; 571 572 err = ifc_name2unit(name, &unit); 573 if (err != 0) 574 return (err); 575 576 wildcard = (unit < 0); 577 578 err = ifc_alloc_unit(ifc, &unit); 579 if (err != 0) 580 return (err); 581 582 err = ifcs->ifcs_create(ifc, unit, params); 583 if (err != 0) { 584 ifc_free_unit(ifc, unit); 585 return (err); 586 } 587 588 /* In the wildcard case, we need to update the name. */ 589 if (wildcard) { 590 for (dp = name; *dp != '\0'; dp++); 591 if (snprintf(dp, len - (dp-name), "%d", unit) > 592 len - (dp-name) - 1) { 593 /* 594 * This can only be a programmer error and 595 * there's no straightforward way to recover if 596 * it happens. 597 */ 598 panic("if_clone_create(): interface name too long"); 599 } 600 601 } 602 603 return (0); 604 } 605 606 int 607 ifc_simple_destroy(struct if_clone *ifc, struct ifnet *ifp) 608 { 609 int unit; 610 struct ifc_simple_data *ifcs = ifc->ifc_data; 611 612 unit = ifp->if_dunit; 613 614 if (unit < ifcs->ifcs_minifs) 615 return (EINVAL); 616 617 ifcs->ifcs_destroy(ifp); 618 619 ifc_free_unit(ifc, unit); 620 621 return (0); 622 } 623