1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 /* 26 * Copyright (c) 2016 by Delphix. All rights reserved. 27 */ 28 29 /* 30 * Datalink management routines. 31 */ 32 33 #include <sys/types.h> 34 #include <sys/door.h> 35 #include <sys/zone.h> 36 #include <sys/modctl.h> 37 #include <sys/file.h> 38 #include <sys/modhash.h> 39 #include <sys/kstat.h> 40 #include <sys/vnode.h> 41 #include <sys/cmn_err.h> 42 #include <sys/softmac.h> 43 #include <sys/dls.h> 44 #include <sys/dls_impl.h> 45 #include <sys/stropts.h> 46 #include <sys/netstack.h> 47 #include <inet/iptun/iptun_impl.h> 48 49 /* 50 * This vanity name management module is treated as part of the GLD framework 51 * and we don't hold any GLD framework lock across a call to any mac 52 * function that needs to acquire the mac perimeter. The hierarchy is 53 * mac perimeter -> framework locks 54 */ 55 56 typedef struct dls_stack { 57 zoneid_t dlss_zoneid; 58 } dls_stack_t; 59 60 static kmem_cache_t *i_dls_devnet_cachep; 61 static kmutex_t i_dls_mgmt_lock; 62 static krwlock_t i_dls_devnet_lock; 63 static mod_hash_t *i_dls_devnet_id_hash; 64 static mod_hash_t *i_dls_devnet_hash; 65 66 boolean_t devnet_need_rebuild; 67 68 #define VLAN_HASHSZ 67 /* prime */ 69 70 /* 71 * The following macros take a link name without the trailing PPA as input. 72 * Opening a /dev/net node with one of these names causes a tunnel link to be 73 * implicitly created in dls_devnet_hold_by_name() for backward compatibility 74 * with Solaris 10 and prior. 75 */ 76 #define IS_IPV4_TUN(name) (strcmp((name), "ip.tun") == 0) 77 #define IS_IPV6_TUN(name) (strcmp((name), "ip6.tun") == 0) 78 #define IS_6TO4_TUN(name) (strcmp((name), "ip.6to4tun") == 0) 79 #define IS_IPTUN_LINK(name) ( \ 80 IS_IPV4_TUN(name) || IS_IPV6_TUN(name) || IS_6TO4_TUN(name)) 81 82 /* Upcall door handle */ 83 static door_handle_t dls_mgmt_dh = NULL; 84 85 /* dls_devnet_t dd_flags */ 86 #define DD_CONDEMNED 0x1 87 #define DD_IMPLICIT_IPTUN 0x2 /* Implicitly-created ip*.*tun* tunnel */ 88 89 /* 90 * This structure is used to keep the <linkid, macname> mapping. 91 * This structure itself is not protected by the mac perimeter, but is 92 * protected by the dd_mutex and i_dls_devnet_lock. Thus most of the 93 * functions manipulating this structure such as dls_devnet_set/unset etc. 94 * may be called while not holding the mac perimeter. 95 */ 96 typedef struct dls_devnet_s { 97 datalink_id_t dd_linkid; 98 char dd_linkname[MAXLINKNAMELEN]; 99 char dd_mac[MAXNAMELEN]; 100 kstat_t *dd_ksp; /* kstat in owner_zid */ 101 kstat_t *dd_zone_ksp; /* in dd_zid if != owner_zid */ 102 uint32_t dd_ref; 103 kmutex_t dd_mutex; 104 kcondvar_t dd_cv; 105 uint32_t dd_tref; 106 uint_t dd_flags; 107 zoneid_t dd_owner_zid; /* zone where node was created */ 108 zoneid_t dd_zid; /* current zone */ 109 boolean_t dd_prop_loaded; 110 taskqid_t dd_prop_taskid; 111 } dls_devnet_t; 112 113 static int i_dls_devnet_create_iptun(const char *, const char *, 114 datalink_id_t *); 115 static int i_dls_devnet_destroy_iptun(datalink_id_t); 116 static int i_dls_devnet_setzid(dls_devnet_t *, zoneid_t, boolean_t); 117 static int dls_devnet_unset(const char *, datalink_id_t *, boolean_t); 118 119 /*ARGSUSED*/ 120 static int 121 i_dls_devnet_constructor(void *buf, void *arg, int kmflag) 122 { 123 dls_devnet_t *ddp = buf; 124 125 bzero(buf, sizeof (dls_devnet_t)); 126 mutex_init(&ddp->dd_mutex, NULL, MUTEX_DEFAULT, NULL); 127 cv_init(&ddp->dd_cv, NULL, CV_DEFAULT, NULL); 128 return (0); 129 } 130 131 /*ARGSUSED*/ 132 static void 133 i_dls_devnet_destructor(void *buf, void *arg) 134 { 135 dls_devnet_t *ddp = buf; 136 137 ASSERT(ddp->dd_ksp == NULL); 138 ASSERT(ddp->dd_ref == 0); 139 ASSERT(ddp->dd_tref == 0); 140 mutex_destroy(&ddp->dd_mutex); 141 cv_destroy(&ddp->dd_cv); 142 } 143 144 /* ARGSUSED */ 145 static int 146 dls_zone_remove(datalink_id_t linkid, void *arg) 147 { 148 dls_devnet_t *ddp; 149 150 if (dls_devnet_hold_tmp(linkid, &ddp) == 0) { 151 (void) dls_devnet_setzid(ddp, GLOBAL_ZONEID); 152 dls_devnet_rele_tmp(ddp); 153 } 154 return (0); 155 } 156 157 /* ARGSUSED */ 158 static void * 159 dls_stack_init(netstackid_t stackid, netstack_t *ns) 160 { 161 dls_stack_t *dlss; 162 163 dlss = kmem_zalloc(sizeof (*dlss), KM_SLEEP); 164 dlss->dlss_zoneid = netstackid_to_zoneid(stackid); 165 return (dlss); 166 } 167 168 /* ARGSUSED */ 169 static void 170 dls_stack_shutdown(netstackid_t stackid, void *arg) 171 { 172 dls_stack_t *dlss = (dls_stack_t *)arg; 173 174 /* Move remaining datalinks in this zone back to the global zone. */ 175 (void) zone_datalink_walk(dlss->dlss_zoneid, dls_zone_remove, NULL); 176 } 177 178 /* ARGSUSED */ 179 static void 180 dls_stack_fini(netstackid_t stackid, void *arg) 181 { 182 dls_stack_t *dlss = (dls_stack_t *)arg; 183 184 kmem_free(dlss, sizeof (*dlss)); 185 } 186 187 /* 188 * Module initialization and finalization functions. 189 */ 190 void 191 dls_mgmt_init(void) 192 { 193 mutex_init(&i_dls_mgmt_lock, NULL, MUTEX_DEFAULT, NULL); 194 rw_init(&i_dls_devnet_lock, NULL, RW_DEFAULT, NULL); 195 196 /* 197 * Create a kmem_cache of dls_devnet_t structures. 198 */ 199 i_dls_devnet_cachep = kmem_cache_create("dls_devnet_cache", 200 sizeof (dls_devnet_t), 0, i_dls_devnet_constructor, 201 i_dls_devnet_destructor, NULL, NULL, NULL, 0); 202 ASSERT(i_dls_devnet_cachep != NULL); 203 204 /* 205 * Create a hash table, keyed by dd_linkid, of dls_devnet_t. 206 */ 207 i_dls_devnet_id_hash = mod_hash_create_idhash("dls_devnet_id_hash", 208 VLAN_HASHSZ, mod_hash_null_valdtor); 209 210 /* 211 * Create a hash table, keyed by dd_mac 212 */ 213 i_dls_devnet_hash = mod_hash_create_extended("dls_devnet_hash", 214 VLAN_HASHSZ, mod_hash_null_keydtor, mod_hash_null_valdtor, 215 mod_hash_bystr, NULL, mod_hash_strkey_cmp, KM_SLEEP); 216 217 devnet_need_rebuild = B_FALSE; 218 219 netstack_register(NS_DLS, dls_stack_init, dls_stack_shutdown, 220 dls_stack_fini); 221 } 222 223 void 224 dls_mgmt_fini(void) 225 { 226 netstack_unregister(NS_DLS); 227 mod_hash_destroy_hash(i_dls_devnet_hash); 228 mod_hash_destroy_hash(i_dls_devnet_id_hash); 229 kmem_cache_destroy(i_dls_devnet_cachep); 230 rw_destroy(&i_dls_devnet_lock); 231 mutex_destroy(&i_dls_mgmt_lock); 232 } 233 234 int 235 dls_mgmt_door_set(boolean_t start) 236 { 237 int err; 238 239 /* handle daemon restart */ 240 mutex_enter(&i_dls_mgmt_lock); 241 if (dls_mgmt_dh != NULL) { 242 door_ki_rele(dls_mgmt_dh); 243 dls_mgmt_dh = NULL; 244 } 245 246 if (start && ((err = door_ki_open(DLMGMT_DOOR, &dls_mgmt_dh)) != 0)) { 247 mutex_exit(&i_dls_mgmt_lock); 248 return (err); 249 } 250 251 mutex_exit(&i_dls_mgmt_lock); 252 253 /* 254 * Create and associate <link name, linkid> mapping for network devices 255 * which are already attached before the daemon is started. 256 */ 257 if (start) 258 softmac_recreate(); 259 return (0); 260 } 261 262 static boolean_t 263 i_dls_mgmt_door_revoked(door_handle_t dh) 264 { 265 struct door_info info; 266 extern int sys_shutdown; 267 268 ASSERT(dh != NULL); 269 270 if (sys_shutdown) { 271 cmn_err(CE_NOTE, "dls_mgmt_door: shutdown observed\n"); 272 return (B_TRUE); 273 } 274 275 if (door_ki_info(dh, &info) != 0) 276 return (B_TRUE); 277 278 return ((info.di_attributes & DOOR_REVOKED) != 0); 279 } 280 281 /* 282 * Upcall to the datalink management daemon (dlmgmtd). 283 */ 284 static int 285 i_dls_mgmt_upcall(void *arg, size_t asize, void *rbuf, size_t rsize) 286 { 287 door_arg_t darg, save_arg; 288 door_handle_t dh; 289 int err; 290 int retry = 0; 291 292 #define MAXRETRYNUM 3 293 294 ASSERT(arg); 295 darg.data_ptr = arg; 296 darg.data_size = asize; 297 darg.desc_ptr = NULL; 298 darg.desc_num = 0; 299 darg.rbuf = rbuf; 300 darg.rsize = rsize; 301 save_arg = darg; 302 303 retry: 304 mutex_enter(&i_dls_mgmt_lock); 305 dh = dls_mgmt_dh; 306 if ((dh == NULL) || i_dls_mgmt_door_revoked(dh)) { 307 mutex_exit(&i_dls_mgmt_lock); 308 return (EBADF); 309 } 310 door_ki_hold(dh); 311 mutex_exit(&i_dls_mgmt_lock); 312 313 for (;;) { 314 retry++; 315 if ((err = door_ki_upcall_limited(dh, &darg, zone_kcred(), 316 SIZE_MAX, 0)) == 0) 317 break; 318 319 /* 320 * handle door call errors 321 */ 322 darg = save_arg; 323 switch (err) { 324 case EINTR: 325 /* 326 * If the operation which caused this door upcall gets 327 * interrupted, return directly. 328 */ 329 goto done; 330 case EAGAIN: 331 /* 332 * Repeat upcall if the maximum attempt limit has not 333 * been reached. 334 */ 335 if (retry < MAXRETRYNUM) { 336 delay(2 * hz); 337 break; 338 } 339 cmn_err(CE_WARN, "dls: dlmgmtd fatal error %d\n", err); 340 goto done; 341 default: 342 /* A fatal door error */ 343 if (i_dls_mgmt_door_revoked(dh)) { 344 cmn_err(CE_NOTE, 345 "dls: dlmgmtd door service revoked\n"); 346 347 if (retry < MAXRETRYNUM) { 348 door_ki_rele(dh); 349 goto retry; 350 } 351 } 352 cmn_err(CE_WARN, "dls: dlmgmtd fatal error %d\n", err); 353 goto done; 354 } 355 } 356 357 if (darg.rbuf != rbuf) { 358 /* 359 * The size of the input rbuf was not big enough, so the 360 * upcall allocated the rbuf itself. If this happens, assume 361 * that this was an invalid door call request. 362 */ 363 kmem_free(darg.rbuf, darg.rsize); 364 err = ENOSPC; 365 goto done; 366 } 367 368 if (darg.rsize != rsize) { 369 err = EINVAL; 370 goto done; 371 } 372 373 err = ((dlmgmt_retval_t *)rbuf)->lr_err; 374 375 done: 376 door_ki_rele(dh); 377 return (err); 378 } 379 380 /* 381 * Request the datalink management daemon to create a link with the attributes 382 * below. Upon success, zero is returned and linkidp contains the linkid for 383 * the new link; otherwise, an errno is returned. 384 * 385 * - dev physical dev_t. required for all physical links, 386 * including GLDv3 links. It will be used to force the 387 * attachment of a physical device, hence the 388 * registration of its mac 389 * - class datalink class 390 * - media type media type; DL_OTHER means unknown 391 * - persist whether to persist the datalink 392 */ 393 int 394 dls_mgmt_create(const char *devname, dev_t dev, datalink_class_t class, 395 uint32_t media, boolean_t persist, datalink_id_t *linkidp) 396 { 397 dlmgmt_upcall_arg_create_t create; 398 dlmgmt_create_retval_t retval; 399 int err; 400 401 create.ld_cmd = DLMGMT_CMD_DLS_CREATE; 402 create.ld_class = class; 403 create.ld_media = media; 404 create.ld_phymaj = getmajor(dev); 405 create.ld_phyinst = getminor(dev); 406 create.ld_persist = persist; 407 if (strlcpy(create.ld_devname, devname, sizeof (create.ld_devname)) >= 408 sizeof (create.ld_devname)) 409 return (EINVAL); 410 411 if ((err = i_dls_mgmt_upcall(&create, sizeof (create), &retval, 412 sizeof (retval))) == 0) { 413 *linkidp = retval.lr_linkid; 414 } 415 return (err); 416 } 417 418 /* 419 * Request the datalink management daemon to destroy the specified link. 420 * Returns zero upon success, or an errno upon failure. 421 */ 422 int 423 dls_mgmt_destroy(datalink_id_t linkid, boolean_t persist) 424 { 425 dlmgmt_upcall_arg_destroy_t destroy; 426 dlmgmt_destroy_retval_t retval; 427 428 destroy.ld_cmd = DLMGMT_CMD_DLS_DESTROY; 429 destroy.ld_linkid = linkid; 430 destroy.ld_persist = persist; 431 432 return (i_dls_mgmt_upcall(&destroy, sizeof (destroy), 433 &retval, sizeof (retval))); 434 } 435 436 /* 437 * Request the datalink management daemon to verify/update the information 438 * for a physical link. Upon success, get its linkid. 439 * 440 * - media type media type 441 * - novanity whether this physical datalink supports vanity naming. 442 * physical links that do not use the GLDv3 MAC plugin 443 * cannot suport vanity naming 444 * 445 * This function could fail with ENOENT or EEXIST. Two cases return EEXIST: 446 * 447 * 1. A link with devname already exists, but the media type does not match. 448 * In this case, mediap will bee set to the media type of the existing link. 449 * 2. A link with devname already exists, but its link name does not match 450 * the device name, although this link does not support vanity naming. 451 */ 452 int 453 dls_mgmt_update(const char *devname, uint32_t media, boolean_t novanity, 454 uint32_t *mediap, datalink_id_t *linkidp) 455 { 456 dlmgmt_upcall_arg_update_t update; 457 dlmgmt_update_retval_t retval; 458 int err; 459 460 update.ld_cmd = DLMGMT_CMD_DLS_UPDATE; 461 462 if (strlcpy(update.ld_devname, devname, sizeof (update.ld_devname)) >= 463 sizeof (update.ld_devname)) 464 return (EINVAL); 465 466 update.ld_media = media; 467 update.ld_novanity = novanity; 468 469 if ((err = i_dls_mgmt_upcall(&update, sizeof (update), &retval, 470 sizeof (retval))) == EEXIST) { 471 *linkidp = retval.lr_linkid; 472 *mediap = retval.lr_media; 473 } else if (err == 0) { 474 *linkidp = retval.lr_linkid; 475 } 476 477 return (err); 478 } 479 480 /* 481 * Request the datalink management daemon to get the information for a link. 482 * Returns zero upon success, or an errno upon failure. 483 * 484 * Only fills in information for argument pointers that are non-NULL. 485 * Note that the link argument is expected to be MAXLINKNAMELEN bytes. 486 */ 487 int 488 dls_mgmt_get_linkinfo(datalink_id_t linkid, char *link, 489 datalink_class_t *classp, uint32_t *mediap, uint32_t *flagsp) 490 { 491 dlmgmt_door_getname_t getname; 492 dlmgmt_getname_retval_t retval; 493 int err, len; 494 495 getname.ld_cmd = DLMGMT_CMD_GETNAME; 496 getname.ld_linkid = linkid; 497 498 if ((err = i_dls_mgmt_upcall(&getname, sizeof (getname), &retval, 499 sizeof (retval))) != 0) { 500 return (err); 501 } 502 503 len = strlen(retval.lr_link); 504 if (len <= 1 || len >= MAXLINKNAMELEN) 505 return (EINVAL); 506 507 if (link != NULL) 508 (void) strlcpy(link, retval.lr_link, MAXLINKNAMELEN); 509 if (classp != NULL) 510 *classp = retval.lr_class; 511 if (mediap != NULL) 512 *mediap = retval.lr_media; 513 if (flagsp != NULL) 514 *flagsp = retval.lr_flags; 515 return (0); 516 } 517 518 /* 519 * Request the datalink management daemon to get the linkid for a link. 520 * Returns a non-zero error code on failure. The linkid argument is only 521 * set on success (when zero is returned.) 522 */ 523 int 524 dls_mgmt_get_linkid(const char *link, datalink_id_t *linkid) 525 { 526 dlmgmt_door_getlinkid_t getlinkid; 527 dlmgmt_getlinkid_retval_t retval; 528 int err; 529 530 getlinkid.ld_cmd = DLMGMT_CMD_GETLINKID; 531 (void) strlcpy(getlinkid.ld_link, link, MAXLINKNAMELEN); 532 533 if ((err = i_dls_mgmt_upcall(&getlinkid, sizeof (getlinkid), &retval, 534 sizeof (retval))) == 0) { 535 *linkid = retval.lr_linkid; 536 } 537 return (err); 538 } 539 540 datalink_id_t 541 dls_mgmt_get_next(datalink_id_t linkid, datalink_class_t class, 542 datalink_media_t dmedia, uint32_t flags) 543 { 544 dlmgmt_door_getnext_t getnext; 545 dlmgmt_getnext_retval_t retval; 546 547 getnext.ld_cmd = DLMGMT_CMD_GETNEXT; 548 getnext.ld_class = class; 549 getnext.ld_dmedia = dmedia; 550 getnext.ld_flags = flags; 551 getnext.ld_linkid = linkid; 552 553 if (i_dls_mgmt_upcall(&getnext, sizeof (getnext), &retval, 554 sizeof (retval)) != 0) { 555 return (DATALINK_INVALID_LINKID); 556 } 557 558 return (retval.lr_linkid); 559 } 560 561 static int 562 i_dls_mgmt_get_linkattr(const datalink_id_t linkid, const char *attr, 563 void *attrval, size_t *attrszp) 564 { 565 dlmgmt_upcall_arg_getattr_t getattr; 566 dlmgmt_getattr_retval_t retval; 567 int err; 568 569 getattr.ld_cmd = DLMGMT_CMD_DLS_GETATTR; 570 getattr.ld_linkid = linkid; 571 (void) strlcpy(getattr.ld_attr, attr, MAXLINKATTRLEN); 572 573 if ((err = i_dls_mgmt_upcall(&getattr, sizeof (getattr), &retval, 574 sizeof (retval))) == 0) { 575 if (*attrszp < retval.lr_attrsz) 576 return (EINVAL); 577 *attrszp = retval.lr_attrsz; 578 bcopy(retval.lr_attrval, attrval, retval.lr_attrsz); 579 } 580 581 return (err); 582 } 583 584 /* 585 * Note that this function can only get devp successfully for non-VLAN link. 586 */ 587 int 588 dls_mgmt_get_phydev(datalink_id_t linkid, dev_t *devp) 589 { 590 uint64_t maj, inst; 591 size_t attrsz = sizeof (uint64_t); 592 593 if (i_dls_mgmt_get_linkattr(linkid, FPHYMAJ, &maj, &attrsz) != 0 || 594 attrsz != sizeof (uint64_t) || 595 i_dls_mgmt_get_linkattr(linkid, FPHYINST, &inst, &attrsz) != 0 || 596 attrsz != sizeof (uint64_t)) { 597 return (EINVAL); 598 } 599 600 *devp = makedevice((major_t)maj, (minor_t)inst); 601 return (0); 602 } 603 604 /* 605 * Request the datalink management daemon to push in 606 * all properties associated with the link. 607 * Returns a non-zero error code on failure. 608 */ 609 int 610 dls_mgmt_linkprop_init(datalink_id_t linkid) 611 { 612 dlmgmt_door_linkprop_init_t li; 613 dlmgmt_linkprop_init_retval_t retval; 614 int err; 615 616 li.ld_cmd = DLMGMT_CMD_LINKPROP_INIT; 617 li.ld_linkid = linkid; 618 619 err = i_dls_mgmt_upcall(&li, sizeof (li), &retval, sizeof (retval)); 620 return (err); 621 } 622 623 static void 624 dls_devnet_prop_task(void *arg) 625 { 626 dls_devnet_t *ddp = arg; 627 628 (void) dls_mgmt_linkprop_init(ddp->dd_linkid); 629 630 mutex_enter(&ddp->dd_mutex); 631 ddp->dd_prop_loaded = B_TRUE; 632 ddp->dd_prop_taskid = NULL; 633 cv_broadcast(&ddp->dd_cv); 634 mutex_exit(&ddp->dd_mutex); 635 } 636 637 /* 638 * Ensure property loading task is completed. 639 */ 640 void 641 dls_devnet_prop_task_wait(dls_dl_handle_t ddp) 642 { 643 mutex_enter(&ddp->dd_mutex); 644 while (ddp->dd_prop_taskid != NULL) 645 cv_wait(&ddp->dd_cv, &ddp->dd_mutex); 646 mutex_exit(&ddp->dd_mutex); 647 } 648 649 void 650 dls_devnet_rele_tmp(dls_dl_handle_t dlh) 651 { 652 dls_devnet_t *ddp = dlh; 653 654 mutex_enter(&ddp->dd_mutex); 655 ASSERT(ddp->dd_tref != 0); 656 if (--ddp->dd_tref == 0) 657 cv_signal(&ddp->dd_cv); 658 mutex_exit(&ddp->dd_mutex); 659 } 660 661 int 662 dls_devnet_hold_link(datalink_id_t linkid, dls_dl_handle_t *ddhp, 663 dls_link_t **dlpp) 664 { 665 dls_dl_handle_t dlh; 666 dls_link_t *dlp; 667 int err; 668 669 if ((err = dls_devnet_hold_tmp(linkid, &dlh)) != 0) 670 return (err); 671 672 if ((err = dls_link_hold(dls_devnet_mac(dlh), &dlp)) != 0) { 673 dls_devnet_rele_tmp(dlh); 674 return (err); 675 } 676 677 ASSERT(MAC_PERIM_HELD(dlp->dl_mh)); 678 679 *ddhp = dlh; 680 *dlpp = dlp; 681 return (0); 682 } 683 684 void 685 dls_devnet_rele_link(dls_dl_handle_t dlh, dls_link_t *dlp) 686 { 687 ASSERT(MAC_PERIM_HELD(dlp->dl_mh)); 688 689 dls_link_rele(dlp); 690 dls_devnet_rele_tmp(dlh); 691 } 692 693 /* 694 * "link" kstats related functions. 695 */ 696 697 /* 698 * Query the "link" kstats. 699 * 700 * We may be called from the kstat subsystem in an arbitrary context. 701 * If the caller is the stack, the context could be an upcall data 702 * thread. Hence we can't acquire the mac perimeter in this function 703 * for fear of deadlock. 704 */ 705 static int 706 dls_devnet_stat_update(kstat_t *ksp, int rw) 707 { 708 datalink_id_t linkid = (datalink_id_t)(uintptr_t)ksp->ks_private; 709 dls_devnet_t *ddp; 710 dls_link_t *dlp; 711 int err; 712 713 if ((err = dls_devnet_hold_tmp(linkid, &ddp)) != 0) { 714 return (err); 715 } 716 717 /* 718 * If a device detach happens at this time, it will block in 719 * dls_devnet_unset since the dd_tref has been bumped in 720 * dls_devnet_hold_tmp(). So the access to 'dlp' is safe even though 721 * we don't hold the mac perimeter. 722 */ 723 if (mod_hash_find(i_dls_link_hash, (mod_hash_key_t)ddp->dd_mac, 724 (mod_hash_val_t *)&dlp) != 0) { 725 dls_devnet_rele_tmp(ddp); 726 return (ENOENT); 727 } 728 729 err = dls_stat_update(ksp, dlp, rw); 730 731 dls_devnet_rele_tmp(ddp); 732 return (err); 733 } 734 735 /* 736 * Create the "link" kstats. 737 */ 738 static void 739 dls_devnet_stat_create(dls_devnet_t *ddp, zoneid_t zoneid) 740 { 741 kstat_t *ksp; 742 743 if (dls_stat_create("link", 0, ddp->dd_linkname, zoneid, 744 dls_devnet_stat_update, (void *)(uintptr_t)ddp->dd_linkid, 745 &ksp) == 0) { 746 ASSERT(ksp != NULL); 747 if (zoneid == ddp->dd_owner_zid) { 748 ASSERT(ddp->dd_ksp == NULL); 749 ddp->dd_ksp = ksp; 750 } else { 751 ASSERT(ddp->dd_zone_ksp == NULL); 752 ddp->dd_zone_ksp = ksp; 753 } 754 } 755 } 756 757 /* 758 * Destroy the "link" kstats. 759 */ 760 static void 761 dls_devnet_stat_destroy(dls_devnet_t *ddp, zoneid_t zoneid) 762 { 763 if (zoneid == ddp->dd_owner_zid) { 764 if (ddp->dd_ksp != NULL) { 765 kstat_delete(ddp->dd_ksp); 766 ddp->dd_ksp = NULL; 767 } 768 } else { 769 if (ddp->dd_zone_ksp != NULL) { 770 kstat_delete(ddp->dd_zone_ksp); 771 ddp->dd_zone_ksp = NULL; 772 } 773 } 774 } 775 776 /* 777 * The link has been renamed. Destroy the old non-legacy kstats ("link kstats") 778 * and create the new set using the new name. 779 */ 780 static void 781 dls_devnet_stat_rename(dls_devnet_t *ddp) 782 { 783 if (ddp->dd_ksp != NULL) { 784 kstat_delete(ddp->dd_ksp); 785 ddp->dd_ksp = NULL; 786 } 787 /* We can't rename a link while it's assigned to a non-global zone. */ 788 ASSERT(ddp->dd_zone_ksp == NULL); 789 dls_devnet_stat_create(ddp, ddp->dd_owner_zid); 790 } 791 792 /* 793 * Associate a linkid with a given link (identified by macname) 794 */ 795 static int 796 dls_devnet_set(const char *macname, datalink_id_t linkid, zoneid_t zoneid, 797 dls_devnet_t **ddpp) 798 { 799 dls_devnet_t *ddp = NULL; 800 datalink_class_t class; 801 int err; 802 boolean_t stat_create = B_FALSE; 803 char linkname[MAXLINKNAMELEN]; 804 805 rw_enter(&i_dls_devnet_lock, RW_WRITER); 806 807 /* 808 * Don't allow callers to set a link name with a linkid that already 809 * has a name association (that's what rename is for). 810 */ 811 if (linkid != DATALINK_INVALID_LINKID) { 812 if (mod_hash_find(i_dls_devnet_id_hash, 813 (mod_hash_key_t)(uintptr_t)linkid, 814 (mod_hash_val_t *)&ddp) == 0) { 815 err = EEXIST; 816 goto done; 817 } 818 if ((err = dls_mgmt_get_linkinfo(linkid, linkname, &class, 819 NULL, NULL)) != 0) 820 goto done; 821 } 822 823 if ((err = mod_hash_find(i_dls_devnet_hash, 824 (mod_hash_key_t)macname, (mod_hash_val_t *)&ddp)) == 0) { 825 if (ddp->dd_linkid != DATALINK_INVALID_LINKID) { 826 err = EEXIST; 827 goto done; 828 } 829 830 /* 831 * This might be a physical link that has already 832 * been created, but which does not have a linkid 833 * because dlmgmtd was not running when it was created. 834 */ 835 if (linkid == DATALINK_INVALID_LINKID || 836 class != DATALINK_CLASS_PHYS) { 837 err = EINVAL; 838 goto done; 839 } 840 } else { 841 ddp = kmem_cache_alloc(i_dls_devnet_cachep, KM_SLEEP); 842 ddp->dd_tref = 0; 843 ddp->dd_ref++; 844 ddp->dd_owner_zid = zoneid; 845 (void) strlcpy(ddp->dd_mac, macname, sizeof (ddp->dd_mac)); 846 VERIFY(mod_hash_insert(i_dls_devnet_hash, 847 (mod_hash_key_t)ddp->dd_mac, (mod_hash_val_t)ddp) == 0); 848 } 849 850 if (linkid != DATALINK_INVALID_LINKID) { 851 ddp->dd_linkid = linkid; 852 (void) strlcpy(ddp->dd_linkname, linkname, 853 sizeof (ddp->dd_linkname)); 854 VERIFY(mod_hash_insert(i_dls_devnet_id_hash, 855 (mod_hash_key_t)(uintptr_t)linkid, 856 (mod_hash_val_t)ddp) == 0); 857 devnet_need_rebuild = B_TRUE; 858 stat_create = B_TRUE; 859 mutex_enter(&ddp->dd_mutex); 860 if (!ddp->dd_prop_loaded && (ddp->dd_prop_taskid == NULL)) { 861 ddp->dd_prop_taskid = taskq_dispatch(system_taskq, 862 dls_devnet_prop_task, ddp, TQ_SLEEP); 863 } 864 mutex_exit(&ddp->dd_mutex); 865 } 866 err = 0; 867 done: 868 /* 869 * It is safe to drop the i_dls_devnet_lock at this point. In the case 870 * of physical devices, the softmac framework will fail the device 871 * detach based on the smac_state or smac_hold_cnt. Other cases like 872 * vnic and aggr use their own scheme to serialize creates and deletes 873 * and ensure that *ddp is valid. 874 */ 875 rw_exit(&i_dls_devnet_lock); 876 if (err == 0) { 877 if (zoneid != GLOBAL_ZONEID && 878 (err = i_dls_devnet_setzid(ddp, zoneid, B_FALSE)) != 0) 879 (void) dls_devnet_unset(macname, &linkid, B_TRUE); 880 /* 881 * The kstat subsystem holds its own locks (rather perimeter) 882 * before calling the ks_update (dls_devnet_stat_update) entry 883 * point which in turn grabs the i_dls_devnet_lock. So the 884 * lock hierarchy is kstat locks -> i_dls_devnet_lock. 885 */ 886 if (stat_create) 887 dls_devnet_stat_create(ddp, zoneid); 888 if (ddpp != NULL) 889 *ddpp = ddp; 890 } 891 return (err); 892 } 893 894 /* 895 * Disassociate a linkid with a given link (identified by macname) 896 * This waits until temporary references to the dls_devnet_t are gone. 897 */ 898 static int 899 dls_devnet_unset(const char *macname, datalink_id_t *id, boolean_t wait) 900 { 901 dls_devnet_t *ddp; 902 int err; 903 mod_hash_val_t val; 904 905 rw_enter(&i_dls_devnet_lock, RW_WRITER); 906 if ((err = mod_hash_find(i_dls_devnet_hash, 907 (mod_hash_key_t)macname, (mod_hash_val_t *)&ddp)) != 0) { 908 ASSERT(err == MH_ERR_NOTFOUND); 909 rw_exit(&i_dls_devnet_lock); 910 return (ENOENT); 911 } 912 913 mutex_enter(&ddp->dd_mutex); 914 915 /* 916 * Make sure downcalls into softmac_create or softmac_destroy from 917 * devfs don't cv_wait on any devfs related condition for fear of 918 * deadlock. Return EBUSY if the asynchronous thread started for 919 * property loading as part of the post attach hasn't yet completed. 920 */ 921 ASSERT(ddp->dd_ref != 0); 922 if ((ddp->dd_ref != 1) || (!wait && 923 (ddp->dd_tref != 0 || ddp->dd_prop_taskid != NULL))) { 924 mutex_exit(&ddp->dd_mutex); 925 rw_exit(&i_dls_devnet_lock); 926 return (EBUSY); 927 } 928 929 ddp->dd_flags |= DD_CONDEMNED; 930 ddp->dd_ref--; 931 *id = ddp->dd_linkid; 932 933 if (ddp->dd_zid != GLOBAL_ZONEID) 934 (void) i_dls_devnet_setzid(ddp, GLOBAL_ZONEID, B_FALSE); 935 936 /* 937 * Remove this dls_devnet_t from the hash table. 938 */ 939 VERIFY(mod_hash_remove(i_dls_devnet_hash, 940 (mod_hash_key_t)ddp->dd_mac, &val) == 0); 941 942 if (ddp->dd_linkid != DATALINK_INVALID_LINKID) { 943 VERIFY(mod_hash_remove(i_dls_devnet_id_hash, 944 (mod_hash_key_t)(uintptr_t)ddp->dd_linkid, &val) == 0); 945 946 devnet_need_rebuild = B_TRUE; 947 } 948 rw_exit(&i_dls_devnet_lock); 949 950 if (wait) { 951 /* 952 * Wait until all temporary references are released. 953 */ 954 while ((ddp->dd_tref != 0) || (ddp->dd_prop_taskid != NULL)) 955 cv_wait(&ddp->dd_cv, &ddp->dd_mutex); 956 } else { 957 ASSERT(ddp->dd_tref == 0 && ddp->dd_prop_taskid == NULL); 958 } 959 960 if (ddp->dd_linkid != DATALINK_INVALID_LINKID) 961 dls_devnet_stat_destroy(ddp, ddp->dd_owner_zid); 962 963 ddp->dd_prop_loaded = B_FALSE; 964 ddp->dd_linkid = DATALINK_INVALID_LINKID; 965 ddp->dd_flags = 0; 966 mutex_exit(&ddp->dd_mutex); 967 kmem_cache_free(i_dls_devnet_cachep, ddp); 968 969 return (0); 970 } 971 972 static int 973 dls_devnet_hold_common(datalink_id_t linkid, dls_devnet_t **ddpp, 974 boolean_t tmp_hold) 975 { 976 dls_devnet_t *ddp; 977 int err; 978 979 rw_enter(&i_dls_devnet_lock, RW_READER); 980 if ((err = mod_hash_find(i_dls_devnet_id_hash, 981 (mod_hash_key_t)(uintptr_t)linkid, (mod_hash_val_t *)&ddp)) != 0) { 982 ASSERT(err == MH_ERR_NOTFOUND); 983 rw_exit(&i_dls_devnet_lock); 984 return (ENOENT); 985 } 986 987 mutex_enter(&ddp->dd_mutex); 988 ASSERT(ddp->dd_ref > 0); 989 if (ddp->dd_flags & DD_CONDEMNED) { 990 mutex_exit(&ddp->dd_mutex); 991 rw_exit(&i_dls_devnet_lock); 992 return (ENOENT); 993 } 994 if (tmp_hold) 995 ddp->dd_tref++; 996 else 997 ddp->dd_ref++; 998 mutex_exit(&ddp->dd_mutex); 999 rw_exit(&i_dls_devnet_lock); 1000 1001 *ddpp = ddp; 1002 return (0); 1003 } 1004 1005 int 1006 dls_devnet_hold(datalink_id_t linkid, dls_devnet_t **ddpp) 1007 { 1008 return (dls_devnet_hold_common(linkid, ddpp, B_FALSE)); 1009 } 1010 1011 /* 1012 * Hold the vanity naming structure (dls_devnet_t) temporarily. The request to 1013 * delete the dls_devnet_t will wait until the temporary reference is released. 1014 */ 1015 int 1016 dls_devnet_hold_tmp(datalink_id_t linkid, dls_devnet_t **ddpp) 1017 { 1018 return (dls_devnet_hold_common(linkid, ddpp, B_TRUE)); 1019 } 1020 1021 /* 1022 * This funtion is called when a DLS client tries to open a device node. 1023 * This dev_t could be a result of a /dev/net node access (returned by 1024 * devnet_create_rvp->dls_devnet_open()) or a direct /dev node access. 1025 * In both cases, this function bumps up the reference count of the 1026 * dls_devnet_t structure. The reference is held as long as the device node 1027 * is open. In the case of /dev/net while it is true that the initial reference 1028 * is held when the devnet_create_rvp->dls_devnet_open call happens, this 1029 * initial reference is released immediately in devnet_inactive_callback -> 1030 * dls_devnet_close(). (Note that devnet_inactive_callback() is called right 1031 * after dld_open completes, not when the /dev/net node is being closed). 1032 * To undo this function, call dls_devnet_rele() 1033 */ 1034 int 1035 dls_devnet_hold_by_dev(dev_t dev, dls_dl_handle_t *ddhp) 1036 { 1037 char name[MAXNAMELEN]; 1038 char *drv; 1039 dls_devnet_t *ddp; 1040 int err; 1041 1042 if ((drv = ddi_major_to_name(getmajor(dev))) == NULL) 1043 return (EINVAL); 1044 1045 (void) snprintf(name, sizeof (name), "%s%d", drv, 1046 DLS_MINOR2INST(getminor(dev))); 1047 1048 rw_enter(&i_dls_devnet_lock, RW_READER); 1049 if ((err = mod_hash_find(i_dls_devnet_hash, 1050 (mod_hash_key_t)name, (mod_hash_val_t *)&ddp)) != 0) { 1051 ASSERT(err == MH_ERR_NOTFOUND); 1052 rw_exit(&i_dls_devnet_lock); 1053 return (ENOENT); 1054 } 1055 mutex_enter(&ddp->dd_mutex); 1056 ASSERT(ddp->dd_ref > 0); 1057 if (ddp->dd_flags & DD_CONDEMNED) { 1058 mutex_exit(&ddp->dd_mutex); 1059 rw_exit(&i_dls_devnet_lock); 1060 return (ENOENT); 1061 } 1062 ddp->dd_ref++; 1063 mutex_exit(&ddp->dd_mutex); 1064 rw_exit(&i_dls_devnet_lock); 1065 1066 *ddhp = ddp; 1067 return (0); 1068 } 1069 1070 void 1071 dls_devnet_rele(dls_devnet_t *ddp) 1072 { 1073 mutex_enter(&ddp->dd_mutex); 1074 ASSERT(ddp->dd_ref > 1); 1075 ddp->dd_ref--; 1076 if ((ddp->dd_flags & DD_IMPLICIT_IPTUN) && ddp->dd_ref == 1) { 1077 mutex_exit(&ddp->dd_mutex); 1078 if (i_dls_devnet_destroy_iptun(ddp->dd_linkid) != 0) 1079 ddp->dd_flags |= DD_IMPLICIT_IPTUN; 1080 return; 1081 } 1082 mutex_exit(&ddp->dd_mutex); 1083 } 1084 1085 static int 1086 dls_devnet_hold_by_name(const char *link, dls_devnet_t **ddpp) 1087 { 1088 char drv[MAXLINKNAMELEN]; 1089 uint_t ppa; 1090 major_t major; 1091 dev_t phy_dev, tmp_dev; 1092 datalink_id_t linkid; 1093 dls_dev_handle_t ddh; 1094 int err; 1095 1096 if ((err = dls_mgmt_get_linkid(link, &linkid)) == 0) 1097 return (dls_devnet_hold(linkid, ddpp)); 1098 1099 /* 1100 * If we failed to get the link's linkid because the dlmgmtd daemon 1101 * has not been started, return ENOENT so that the application can 1102 * fallback to open the /dev node. 1103 */ 1104 if (err == EBADF) 1105 return (ENOENT); 1106 1107 if (err != ENOENT) 1108 return (err); 1109 1110 /* 1111 * If we reach this point it means dlmgmtd is up but has no 1112 * mapping for the link name. 1113 */ 1114 if (ddi_parse(link, drv, &ppa) != DDI_SUCCESS) 1115 return (ENOENT); 1116 1117 if (IS_IPTUN_LINK(drv)) { 1118 if ((err = i_dls_devnet_create_iptun(link, drv, &linkid)) != 0) 1119 return (err); 1120 /* 1121 * At this point, an IP tunnel MAC has registered, which 1122 * resulted in a link being created. 1123 */ 1124 err = dls_devnet_hold(linkid, ddpp); 1125 if (err != 0) { 1126 VERIFY(i_dls_devnet_destroy_iptun(linkid) == 0); 1127 return (err); 1128 } 1129 /* 1130 * dls_devnet_rele() will know to destroy the implicit IP 1131 * tunnel on last reference release if DD_IMPLICIT_IPTUN is 1132 * set. 1133 */ 1134 (*ddpp)->dd_flags |= DD_IMPLICIT_IPTUN; 1135 return (0); 1136 } 1137 1138 /* 1139 * If this link: 1140 * (a) is a physical device, (b) this is the first boot, (c) the MAC 1141 * is not registered yet, and (d) we cannot find its linkid, then the 1142 * linkname is the same as the devname. 1143 * 1144 * First filter out invalid names. 1145 */ 1146 if ((major = ddi_name_to_major(drv)) == (major_t)-1) 1147 return (ENOENT); 1148 1149 phy_dev = makedevice(major, DLS_PPA2MINOR(ppa)); 1150 if (softmac_hold_device(phy_dev, &ddh) != 0) 1151 return (ENOENT); 1152 1153 /* 1154 * At this time, the MAC should be registered, check its phy_dev using 1155 * the given name. 1156 */ 1157 if ((err = dls_mgmt_get_linkid(link, &linkid)) != 0 || 1158 (err = dls_mgmt_get_phydev(linkid, &tmp_dev)) != 0) { 1159 softmac_rele_device(ddh); 1160 return (err); 1161 } 1162 if (tmp_dev != phy_dev) { 1163 softmac_rele_device(ddh); 1164 return (ENOENT); 1165 } 1166 1167 err = dls_devnet_hold(linkid, ddpp); 1168 softmac_rele_device(ddh); 1169 return (err); 1170 } 1171 1172 int 1173 dls_devnet_macname2linkid(const char *macname, datalink_id_t *linkidp) 1174 { 1175 dls_devnet_t *ddp; 1176 1177 rw_enter(&i_dls_devnet_lock, RW_READER); 1178 if (mod_hash_find(i_dls_devnet_hash, (mod_hash_key_t)macname, 1179 (mod_hash_val_t *)&ddp) != 0) { 1180 rw_exit(&i_dls_devnet_lock); 1181 return (ENOENT); 1182 } 1183 1184 *linkidp = ddp->dd_linkid; 1185 rw_exit(&i_dls_devnet_lock); 1186 return (0); 1187 } 1188 1189 /* 1190 * Get linkid for the given dev. 1191 */ 1192 int 1193 dls_devnet_dev2linkid(dev_t dev, datalink_id_t *linkidp) 1194 { 1195 char macname[MAXNAMELEN]; 1196 char *drv; 1197 1198 if ((drv = ddi_major_to_name(getmajor(dev))) == NULL) 1199 return (EINVAL); 1200 1201 (void) snprintf(macname, sizeof (macname), "%s%d", drv, 1202 DLS_MINOR2INST(getminor(dev))); 1203 return (dls_devnet_macname2linkid(macname, linkidp)); 1204 } 1205 1206 /* 1207 * Get the link's physical dev_t. It this is a VLAN, get the dev_t of the 1208 * link this VLAN is created on. 1209 */ 1210 int 1211 dls_devnet_phydev(datalink_id_t vlanid, dev_t *devp) 1212 { 1213 dls_devnet_t *ddp; 1214 int err; 1215 1216 if ((err = dls_devnet_hold_tmp(vlanid, &ddp)) != 0) 1217 return (err); 1218 1219 err = dls_mgmt_get_phydev(ddp->dd_linkid, devp); 1220 dls_devnet_rele_tmp(ddp); 1221 return (err); 1222 } 1223 1224 /* 1225 * Handle the renaming requests. There are two rename cases: 1226 * 1227 * 1. Request to rename a valid link (id1) to an non-existent link name 1228 * (id2). In this case id2 is DATALINK_INVALID_LINKID. Just check whether 1229 * id1 is held by any applications. 1230 * 1231 * In this case, the link's kstats need to be updated using the given name. 1232 * 1233 * 2. Request to rename a valid link (id1) to the name of a REMOVED 1234 * physical link (id2). In this case, check that id1 and its associated 1235 * mac is not held by any application, and update the link's linkid to id2. 1236 * 1237 * This case does not change the <link name, linkid> mapping, so the link's 1238 * kstats need to be updated with using name associated the given id2. 1239 */ 1240 int 1241 dls_devnet_rename(datalink_id_t id1, datalink_id_t id2, const char *link) 1242 { 1243 dls_dev_handle_t ddh = NULL; 1244 int err = 0; 1245 dev_t phydev = 0; 1246 dls_devnet_t *ddp; 1247 mac_perim_handle_t mph = NULL; 1248 mac_handle_t mh; 1249 mod_hash_val_t val; 1250 1251 /* 1252 * In the second case, id2 must be a REMOVED physical link. 1253 */ 1254 if ((id2 != DATALINK_INVALID_LINKID) && 1255 (dls_mgmt_get_phydev(id2, &phydev) == 0) && 1256 softmac_hold_device(phydev, &ddh) == 0) { 1257 softmac_rele_device(ddh); 1258 return (EEXIST); 1259 } 1260 1261 /* 1262 * Hold id1 to prevent it from being detached (if a physical link). 1263 */ 1264 if (dls_mgmt_get_phydev(id1, &phydev) == 0) 1265 (void) softmac_hold_device(phydev, &ddh); 1266 1267 /* 1268 * The framework does not hold hold locks across calls to the 1269 * mac perimeter, hence enter the perimeter first. This also waits 1270 * for the property loading to finish. 1271 */ 1272 if ((err = mac_perim_enter_by_linkid(id1, &mph)) != 0) { 1273 softmac_rele_device(ddh); 1274 return (err); 1275 } 1276 1277 rw_enter(&i_dls_devnet_lock, RW_WRITER); 1278 if ((err = mod_hash_find(i_dls_devnet_id_hash, 1279 (mod_hash_key_t)(uintptr_t)id1, (mod_hash_val_t *)&ddp)) != 0) { 1280 ASSERT(err == MH_ERR_NOTFOUND); 1281 err = ENOENT; 1282 goto done; 1283 } 1284 1285 mutex_enter(&ddp->dd_mutex); 1286 if (ddp->dd_ref > 1) { 1287 mutex_exit(&ddp->dd_mutex); 1288 err = EBUSY; 1289 goto done; 1290 } 1291 mutex_exit(&ddp->dd_mutex); 1292 1293 if (id2 == DATALINK_INVALID_LINKID) { 1294 (void) strlcpy(ddp->dd_linkname, link, 1295 sizeof (ddp->dd_linkname)); 1296 1297 /* rename mac client name and its flow if exists */ 1298 if ((err = mac_open(ddp->dd_mac, &mh)) != 0) 1299 goto done; 1300 (void) mac_rename_primary(mh, link); 1301 mac_close(mh); 1302 goto done; 1303 } 1304 1305 /* 1306 * The second case, check whether the MAC is used by any MAC 1307 * user. This must be a physical link so ddh must not be NULL. 1308 */ 1309 if (ddh == NULL) { 1310 err = EINVAL; 1311 goto done; 1312 } 1313 1314 if ((err = mac_open(ddp->dd_mac, &mh)) != 0) 1315 goto done; 1316 1317 /* 1318 * We release the reference of the MAC which mac_open() is 1319 * holding. Note that this mac will not be unregistered 1320 * because the physical device is held. 1321 */ 1322 mac_close(mh); 1323 1324 /* 1325 * Check if there is any other MAC clients, if not, hold this mac 1326 * exclusively until we are done. 1327 */ 1328 if ((err = mac_mark_exclusive(mh)) != 0) 1329 goto done; 1330 1331 /* 1332 * Update the link's linkid. 1333 */ 1334 if ((err = mod_hash_find(i_dls_devnet_id_hash, 1335 (mod_hash_key_t)(uintptr_t)id2, &val)) != MH_ERR_NOTFOUND) { 1336 mac_unmark_exclusive(mh); 1337 err = EEXIST; 1338 goto done; 1339 } 1340 1341 err = dls_mgmt_get_linkinfo(id2, ddp->dd_linkname, NULL, NULL, NULL); 1342 if (err != 0) { 1343 mac_unmark_exclusive(mh); 1344 goto done; 1345 } 1346 1347 (void) mod_hash_remove(i_dls_devnet_id_hash, 1348 (mod_hash_key_t)(uintptr_t)id1, &val); 1349 1350 ddp->dd_linkid = id2; 1351 (void) mod_hash_insert(i_dls_devnet_id_hash, 1352 (mod_hash_key_t)(uintptr_t)ddp->dd_linkid, (mod_hash_val_t)ddp); 1353 1354 mac_unmark_exclusive(mh); 1355 1356 /* load properties for new id */ 1357 mutex_enter(&ddp->dd_mutex); 1358 ddp->dd_prop_loaded = B_FALSE; 1359 ddp->dd_prop_taskid = taskq_dispatch(system_taskq, 1360 dls_devnet_prop_task, ddp, TQ_SLEEP); 1361 mutex_exit(&ddp->dd_mutex); 1362 1363 done: 1364 rw_exit(&i_dls_devnet_lock); 1365 1366 if (err == 0) 1367 dls_devnet_stat_rename(ddp); 1368 1369 if (mph != NULL) 1370 mac_perim_exit(mph); 1371 softmac_rele_device(ddh); 1372 return (err); 1373 } 1374 1375 static int 1376 i_dls_devnet_setzid(dls_devnet_t *ddp, zoneid_t new_zoneid, boolean_t setprop) 1377 { 1378 int err; 1379 mac_perim_handle_t mph; 1380 boolean_t upcall_done = B_FALSE; 1381 datalink_id_t linkid = ddp->dd_linkid; 1382 zoneid_t old_zoneid = ddp->dd_zid; 1383 dlmgmt_door_setzoneid_t setzid; 1384 dlmgmt_setzoneid_retval_t retval; 1385 1386 if (old_zoneid == new_zoneid) 1387 return (0); 1388 1389 if ((err = mac_perim_enter_by_macname(ddp->dd_mac, &mph)) != 0) 1390 return (err); 1391 1392 /* 1393 * When changing the zoneid of an existing link, we need to tell 1394 * dlmgmtd about it. dlmgmtd already knows the zoneid associated with 1395 * newly created links. 1396 */ 1397 if (setprop) { 1398 setzid.ld_cmd = DLMGMT_CMD_SETZONEID; 1399 setzid.ld_linkid = linkid; 1400 setzid.ld_zoneid = new_zoneid; 1401 err = i_dls_mgmt_upcall(&setzid, sizeof (setzid), &retval, 1402 sizeof (retval)); 1403 if (err != 0) 1404 goto done; 1405 upcall_done = B_TRUE; 1406 } 1407 if ((err = dls_link_setzid(ddp->dd_mac, new_zoneid)) == 0) { 1408 ddp->dd_zid = new_zoneid; 1409 devnet_need_rebuild = B_TRUE; 1410 } 1411 1412 done: 1413 if (err != 0 && upcall_done) { 1414 setzid.ld_zoneid = old_zoneid; 1415 (void) i_dls_mgmt_upcall(&setzid, sizeof (setzid), &retval, 1416 sizeof (retval)); 1417 } 1418 mac_perim_exit(mph); 1419 return (err); 1420 } 1421 1422 int 1423 dls_devnet_setzid(dls_dl_handle_t ddh, zoneid_t new_zid) 1424 { 1425 dls_devnet_t *ddp; 1426 int err; 1427 zoneid_t old_zid; 1428 boolean_t refheld = B_FALSE; 1429 1430 old_zid = ddh->dd_zid; 1431 1432 if (old_zid == new_zid) 1433 return (0); 1434 1435 /* 1436 * Acquire an additional reference to the link if it is being assigned 1437 * to a non-global zone from the global zone. 1438 */ 1439 if (old_zid == GLOBAL_ZONEID && new_zid != GLOBAL_ZONEID) { 1440 if ((err = dls_devnet_hold(ddh->dd_linkid, &ddp)) != 0) 1441 return (err); 1442 refheld = B_TRUE; 1443 } 1444 1445 if ((err = i_dls_devnet_setzid(ddh, new_zid, B_TRUE)) != 0) { 1446 if (refheld) 1447 dls_devnet_rele(ddp); 1448 return (err); 1449 } 1450 1451 /* 1452 * Release the additional reference if the link is returning to the 1453 * global zone from a non-global zone. 1454 */ 1455 if (old_zid != GLOBAL_ZONEID && new_zid == GLOBAL_ZONEID) 1456 dls_devnet_rele(ddh); 1457 1458 /* Re-create kstats in the appropriate zones. */ 1459 if (old_zid != GLOBAL_ZONEID) 1460 dls_devnet_stat_destroy(ddh, old_zid); 1461 if (new_zid != GLOBAL_ZONEID) 1462 dls_devnet_stat_create(ddh, new_zid); 1463 1464 return (0); 1465 } 1466 1467 zoneid_t 1468 dls_devnet_getzid(dls_dl_handle_t ddh) 1469 { 1470 return (((dls_devnet_t *)ddh)->dd_zid); 1471 } 1472 1473 zoneid_t 1474 dls_devnet_getownerzid(dls_dl_handle_t ddh) 1475 { 1476 return (((dls_devnet_t *)ddh)->dd_owner_zid); 1477 } 1478 1479 /* 1480 * Is linkid visible from zoneid? A link is visible if it was created in the 1481 * zone, or if it is currently assigned to the zone. 1482 */ 1483 boolean_t 1484 dls_devnet_islinkvisible(datalink_id_t linkid, zoneid_t zoneid) 1485 { 1486 dls_devnet_t *ddp; 1487 boolean_t result; 1488 1489 if (dls_devnet_hold_tmp(linkid, &ddp) != 0) 1490 return (B_FALSE); 1491 result = (ddp->dd_owner_zid == zoneid || ddp->dd_zid == zoneid); 1492 dls_devnet_rele_tmp(ddp); 1493 return (result); 1494 } 1495 1496 /* 1497 * Access a vanity naming node. 1498 */ 1499 int 1500 dls_devnet_open(const char *link, dls_dl_handle_t *dhp, dev_t *devp) 1501 { 1502 dls_devnet_t *ddp; 1503 dls_link_t *dlp; 1504 zoneid_t zid = getzoneid(); 1505 int err; 1506 mac_perim_handle_t mph; 1507 1508 if ((err = dls_devnet_hold_by_name(link, &ddp)) != 0) 1509 return (err); 1510 1511 dls_devnet_prop_task_wait(ddp); 1512 1513 /* 1514 * Opening a link that does not belong to the current non-global zone 1515 * is not allowed. 1516 */ 1517 if (zid != GLOBAL_ZONEID && ddp->dd_zid != zid) { 1518 dls_devnet_rele(ddp); 1519 return (ENOENT); 1520 } 1521 1522 err = mac_perim_enter_by_macname(ddp->dd_mac, &mph); 1523 if (err != 0) { 1524 dls_devnet_rele(ddp); 1525 return (err); 1526 } 1527 1528 err = dls_link_hold_create(ddp->dd_mac, &dlp); 1529 mac_perim_exit(mph); 1530 1531 if (err != 0) { 1532 dls_devnet_rele(ddp); 1533 return (err); 1534 } 1535 1536 *dhp = ddp; 1537 *devp = dls_link_dev(dlp); 1538 return (0); 1539 } 1540 1541 /* 1542 * Close access to a vanity naming node. 1543 */ 1544 void 1545 dls_devnet_close(dls_dl_handle_t dlh) 1546 { 1547 dls_devnet_t *ddp = dlh; 1548 dls_link_t *dlp; 1549 mac_perim_handle_t mph; 1550 1551 VERIFY(mac_perim_enter_by_macname(ddp->dd_mac, &mph) == 0); 1552 VERIFY(dls_link_hold(ddp->dd_mac, &dlp) == 0); 1553 1554 /* 1555 * One rele for the hold placed in dls_devnet_open, another for 1556 * the hold done just above 1557 */ 1558 dls_link_rele(dlp); 1559 dls_link_rele(dlp); 1560 mac_perim_exit(mph); 1561 1562 dls_devnet_rele(ddp); 1563 } 1564 1565 /* 1566 * This is used by /dev/net to rebuild the nodes for readdir(). It is not 1567 * critical and no protection is needed. 1568 */ 1569 boolean_t 1570 dls_devnet_rebuild() 1571 { 1572 boolean_t updated = devnet_need_rebuild; 1573 1574 devnet_need_rebuild = B_FALSE; 1575 return (updated); 1576 } 1577 1578 int 1579 dls_devnet_create(mac_handle_t mh, datalink_id_t linkid, zoneid_t zoneid) 1580 { 1581 dls_link_t *dlp; 1582 dls_devnet_t *ddp; 1583 int err; 1584 mac_perim_handle_t mph; 1585 1586 /* 1587 * Holding the mac perimeter ensures that the downcall from the 1588 * dlmgmt daemon which does the property loading does not proceed 1589 * until we relinquish the perimeter. 1590 */ 1591 mac_perim_enter_by_mh(mh, &mph); 1592 /* 1593 * Make this association before we call dls_link_hold_create as 1594 * we need to use the linkid to get the user name for the link 1595 * when we create the MAC client. 1596 */ 1597 if ((err = dls_devnet_set(mac_name(mh), linkid, zoneid, &ddp)) == 0) { 1598 if ((err = dls_link_hold_create(mac_name(mh), &dlp)) != 0) { 1599 mac_perim_exit(mph); 1600 (void) dls_devnet_unset(mac_name(mh), &linkid, B_TRUE); 1601 return (err); 1602 } 1603 } 1604 mac_perim_exit(mph); 1605 return (err); 1606 } 1607 1608 /* 1609 * Set the linkid of the dls_devnet_t and add it into the i_dls_devnet_id_hash. 1610 * This is called in the case that the dlmgmtd daemon is started later than 1611 * the physical devices get attached, and the linkid is only known after the 1612 * daemon starts. 1613 */ 1614 int 1615 dls_devnet_recreate(mac_handle_t mh, datalink_id_t linkid) 1616 { 1617 ASSERT(linkid != DATALINK_INVALID_LINKID); 1618 return (dls_devnet_set(mac_name(mh), linkid, GLOBAL_ZONEID, NULL)); 1619 } 1620 1621 int 1622 dls_devnet_destroy(mac_handle_t mh, datalink_id_t *idp, boolean_t wait) 1623 { 1624 int err; 1625 mac_perim_handle_t mph; 1626 1627 *idp = DATALINK_INVALID_LINKID; 1628 err = dls_devnet_unset(mac_name(mh), idp, wait); 1629 if (err != 0 && err != ENOENT) 1630 return (err); 1631 1632 mac_perim_enter_by_mh(mh, &mph); 1633 err = dls_link_rele_by_name(mac_name(mh)); 1634 mac_perim_exit(mph); 1635 1636 if (err != 0) { 1637 /* 1638 * XXX It is a general GLDv3 bug that dls_devnet_set() has to 1639 * be called to re-set the link when destroy fails. The 1640 * zoneid below will be incorrect if this function is ever 1641 * called from kernel context or from a zone other than that 1642 * which initially created the link. 1643 */ 1644 (void) dls_devnet_set(mac_name(mh), *idp, crgetzoneid(CRED()), 1645 NULL); 1646 } 1647 return (err); 1648 } 1649 1650 /* 1651 * Implicitly create an IP tunnel link. 1652 */ 1653 static int 1654 i_dls_devnet_create_iptun(const char *linkname, const char *drvname, 1655 datalink_id_t *linkid) 1656 { 1657 int err; 1658 iptun_kparams_t ik; 1659 uint32_t media; 1660 netstack_t *ns; 1661 major_t iptun_major; 1662 dev_info_t *iptun_dip; 1663 1664 /* First ensure that the iptun device is attached. */ 1665 if ((iptun_major = ddi_name_to_major(IPTUN_DRIVER_NAME)) == (major_t)-1) 1666 return (EINVAL); 1667 if ((iptun_dip = ddi_hold_devi_by_instance(iptun_major, 0, 0)) == NULL) 1668 return (EINVAL); 1669 1670 if (IS_IPV4_TUN(drvname)) { 1671 ik.iptun_kparam_type = IPTUN_TYPE_IPV4; 1672 media = DL_IPV4; 1673 } else if (IS_6TO4_TUN(drvname)) { 1674 ik.iptun_kparam_type = IPTUN_TYPE_6TO4; 1675 media = DL_6TO4; 1676 } else if (IS_IPV6_TUN(drvname)) { 1677 ik.iptun_kparam_type = IPTUN_TYPE_IPV6; 1678 media = DL_IPV6; 1679 } 1680 ik.iptun_kparam_flags = (IPTUN_KPARAM_TYPE | IPTUN_KPARAM_IMPLICIT); 1681 1682 /* Obtain a datalink id for this tunnel. */ 1683 err = dls_mgmt_create((char *)linkname, 0, DATALINK_CLASS_IPTUN, media, 1684 B_FALSE, &ik.iptun_kparam_linkid); 1685 if (err != 0) { 1686 ddi_release_devi(iptun_dip); 1687 return (err); 1688 } 1689 1690 ns = netstack_get_current(); 1691 err = iptun_create(&ik, CRED()); 1692 netstack_rele(ns); 1693 1694 if (err != 0) 1695 VERIFY(dls_mgmt_destroy(ik.iptun_kparam_linkid, B_FALSE) == 0); 1696 else 1697 *linkid = ik.iptun_kparam_linkid; 1698 1699 ddi_release_devi(iptun_dip); 1700 return (err); 1701 } 1702 1703 static int 1704 i_dls_devnet_destroy_iptun(datalink_id_t linkid) 1705 { 1706 int err; 1707 1708 /* 1709 * Note the use of zone_kcred() here as opposed to CRED(). This is 1710 * because the process that does the last close of this /dev/net node 1711 * may not have necessary privileges to delete this IP tunnel, but the 1712 * tunnel must always be implicitly deleted on last close. 1713 */ 1714 if ((err = iptun_delete(linkid, zone_kcred())) == 0) 1715 (void) dls_mgmt_destroy(linkid, B_FALSE); 1716 return (err); 1717 } 1718 1719 const char * 1720 dls_devnet_mac(dls_dl_handle_t ddh) 1721 { 1722 return (ddh->dd_mac); 1723 } 1724 1725 datalink_id_t 1726 dls_devnet_linkid(dls_dl_handle_t ddh) 1727 { 1728 return (ddh->dd_linkid); 1729 } 1730