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 = 0; 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 != 0) 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 == 0)) { 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 != 0))) { 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 != 0)) 955 cv_wait(&ddp->dd_cv, &ddp->dd_mutex); 956 } else { 957 ASSERT(ddp->dd_tref == 0 && 958 ddp->dd_prop_taskid == (taskqid_t)NULL); 959 } 960 961 if (ddp->dd_linkid != DATALINK_INVALID_LINKID) 962 dls_devnet_stat_destroy(ddp, ddp->dd_owner_zid); 963 964 ddp->dd_prop_loaded = B_FALSE; 965 ddp->dd_linkid = DATALINK_INVALID_LINKID; 966 ddp->dd_flags = 0; 967 mutex_exit(&ddp->dd_mutex); 968 kmem_cache_free(i_dls_devnet_cachep, ddp); 969 970 return (0); 971 } 972 973 static int 974 dls_devnet_hold_common(datalink_id_t linkid, dls_devnet_t **ddpp, 975 boolean_t tmp_hold) 976 { 977 dls_devnet_t *ddp; 978 int err; 979 980 rw_enter(&i_dls_devnet_lock, RW_READER); 981 if ((err = mod_hash_find(i_dls_devnet_id_hash, 982 (mod_hash_key_t)(uintptr_t)linkid, (mod_hash_val_t *)&ddp)) != 0) { 983 ASSERT(err == MH_ERR_NOTFOUND); 984 rw_exit(&i_dls_devnet_lock); 985 return (ENOENT); 986 } 987 988 mutex_enter(&ddp->dd_mutex); 989 ASSERT(ddp->dd_ref > 0); 990 if (ddp->dd_flags & DD_CONDEMNED) { 991 mutex_exit(&ddp->dd_mutex); 992 rw_exit(&i_dls_devnet_lock); 993 return (ENOENT); 994 } 995 if (tmp_hold) 996 ddp->dd_tref++; 997 else 998 ddp->dd_ref++; 999 mutex_exit(&ddp->dd_mutex); 1000 rw_exit(&i_dls_devnet_lock); 1001 1002 *ddpp = ddp; 1003 return (0); 1004 } 1005 1006 int 1007 dls_devnet_hold(datalink_id_t linkid, dls_devnet_t **ddpp) 1008 { 1009 return (dls_devnet_hold_common(linkid, ddpp, B_FALSE)); 1010 } 1011 1012 /* 1013 * Hold the vanity naming structure (dls_devnet_t) temporarily. The request to 1014 * delete the dls_devnet_t will wait until the temporary reference is released. 1015 */ 1016 int 1017 dls_devnet_hold_tmp(datalink_id_t linkid, dls_devnet_t **ddpp) 1018 { 1019 return (dls_devnet_hold_common(linkid, ddpp, B_TRUE)); 1020 } 1021 1022 /* 1023 * This funtion is called when a DLS client tries to open a device node. 1024 * This dev_t could be a result of a /dev/net node access (returned by 1025 * devnet_create_rvp->dls_devnet_open()) or a direct /dev node access. 1026 * In both cases, this function bumps up the reference count of the 1027 * dls_devnet_t structure. The reference is held as long as the device node 1028 * is open. In the case of /dev/net while it is true that the initial reference 1029 * is held when the devnet_create_rvp->dls_devnet_open call happens, this 1030 * initial reference is released immediately in devnet_inactive_callback -> 1031 * dls_devnet_close(). (Note that devnet_inactive_callback() is called right 1032 * after dld_open completes, not when the /dev/net node is being closed). 1033 * To undo this function, call dls_devnet_rele() 1034 */ 1035 int 1036 dls_devnet_hold_by_dev(dev_t dev, dls_dl_handle_t *ddhp) 1037 { 1038 char name[MAXNAMELEN]; 1039 char *drv; 1040 dls_devnet_t *ddp; 1041 int err; 1042 1043 if ((drv = ddi_major_to_name(getmajor(dev))) == NULL) 1044 return (EINVAL); 1045 1046 (void) snprintf(name, sizeof (name), "%s%d", drv, 1047 DLS_MINOR2INST(getminor(dev))); 1048 1049 rw_enter(&i_dls_devnet_lock, RW_READER); 1050 if ((err = mod_hash_find(i_dls_devnet_hash, 1051 (mod_hash_key_t)name, (mod_hash_val_t *)&ddp)) != 0) { 1052 ASSERT(err == MH_ERR_NOTFOUND); 1053 rw_exit(&i_dls_devnet_lock); 1054 return (ENOENT); 1055 } 1056 mutex_enter(&ddp->dd_mutex); 1057 ASSERT(ddp->dd_ref > 0); 1058 if (ddp->dd_flags & DD_CONDEMNED) { 1059 mutex_exit(&ddp->dd_mutex); 1060 rw_exit(&i_dls_devnet_lock); 1061 return (ENOENT); 1062 } 1063 ddp->dd_ref++; 1064 mutex_exit(&ddp->dd_mutex); 1065 rw_exit(&i_dls_devnet_lock); 1066 1067 *ddhp = ddp; 1068 return (0); 1069 } 1070 1071 void 1072 dls_devnet_rele(dls_devnet_t *ddp) 1073 { 1074 mutex_enter(&ddp->dd_mutex); 1075 ASSERT(ddp->dd_ref > 1); 1076 ddp->dd_ref--; 1077 if ((ddp->dd_flags & DD_IMPLICIT_IPTUN) && ddp->dd_ref == 1) { 1078 mutex_exit(&ddp->dd_mutex); 1079 if (i_dls_devnet_destroy_iptun(ddp->dd_linkid) != 0) 1080 ddp->dd_flags |= DD_IMPLICIT_IPTUN; 1081 return; 1082 } 1083 mutex_exit(&ddp->dd_mutex); 1084 } 1085 1086 static int 1087 dls_devnet_hold_by_name(const char *link, dls_devnet_t **ddpp) 1088 { 1089 char drv[MAXLINKNAMELEN]; 1090 uint_t ppa; 1091 major_t major; 1092 dev_t phy_dev, tmp_dev; 1093 datalink_id_t linkid; 1094 dls_dev_handle_t ddh; 1095 int err; 1096 1097 if ((err = dls_mgmt_get_linkid(link, &linkid)) == 0) 1098 return (dls_devnet_hold(linkid, ddpp)); 1099 1100 /* 1101 * If we failed to get the link's linkid because the dlmgmtd daemon 1102 * has not been started, return ENOENT so that the application can 1103 * fallback to open the /dev node. 1104 */ 1105 if (err == EBADF) 1106 return (ENOENT); 1107 1108 if (err != ENOENT) 1109 return (err); 1110 1111 /* 1112 * If we reach this point it means dlmgmtd is up but has no 1113 * mapping for the link name. 1114 */ 1115 if (ddi_parse(link, drv, &ppa) != DDI_SUCCESS) 1116 return (ENOENT); 1117 1118 if (IS_IPTUN_LINK(drv)) { 1119 if ((err = i_dls_devnet_create_iptun(link, drv, &linkid)) != 0) 1120 return (err); 1121 /* 1122 * At this point, an IP tunnel MAC has registered, which 1123 * resulted in a link being created. 1124 */ 1125 err = dls_devnet_hold(linkid, ddpp); 1126 if (err != 0) { 1127 VERIFY(i_dls_devnet_destroy_iptun(linkid) == 0); 1128 return (err); 1129 } 1130 /* 1131 * dls_devnet_rele() will know to destroy the implicit IP 1132 * tunnel on last reference release if DD_IMPLICIT_IPTUN is 1133 * set. 1134 */ 1135 (*ddpp)->dd_flags |= DD_IMPLICIT_IPTUN; 1136 return (0); 1137 } 1138 1139 /* 1140 * If this link: 1141 * (a) is a physical device, (b) this is the first boot, (c) the MAC 1142 * is not registered yet, and (d) we cannot find its linkid, then the 1143 * linkname is the same as the devname. 1144 * 1145 * First filter out invalid names. 1146 */ 1147 if ((major = ddi_name_to_major(drv)) == (major_t)-1) 1148 return (ENOENT); 1149 1150 phy_dev = makedevice(major, DLS_PPA2MINOR(ppa)); 1151 if (softmac_hold_device(phy_dev, &ddh) != 0) 1152 return (ENOENT); 1153 1154 /* 1155 * At this time, the MAC should be registered, check its phy_dev using 1156 * the given name. 1157 */ 1158 if ((err = dls_mgmt_get_linkid(link, &linkid)) != 0 || 1159 (err = dls_mgmt_get_phydev(linkid, &tmp_dev)) != 0) { 1160 softmac_rele_device(ddh); 1161 return (err); 1162 } 1163 if (tmp_dev != phy_dev) { 1164 softmac_rele_device(ddh); 1165 return (ENOENT); 1166 } 1167 1168 err = dls_devnet_hold(linkid, ddpp); 1169 softmac_rele_device(ddh); 1170 return (err); 1171 } 1172 1173 int 1174 dls_devnet_macname2linkid(const char *macname, datalink_id_t *linkidp) 1175 { 1176 dls_devnet_t *ddp; 1177 1178 rw_enter(&i_dls_devnet_lock, RW_READER); 1179 if (mod_hash_find(i_dls_devnet_hash, (mod_hash_key_t)macname, 1180 (mod_hash_val_t *)&ddp) != 0) { 1181 rw_exit(&i_dls_devnet_lock); 1182 return (ENOENT); 1183 } 1184 1185 *linkidp = ddp->dd_linkid; 1186 rw_exit(&i_dls_devnet_lock); 1187 return (0); 1188 } 1189 1190 /* 1191 * Get linkid for the given dev. 1192 */ 1193 int 1194 dls_devnet_dev2linkid(dev_t dev, datalink_id_t *linkidp) 1195 { 1196 char macname[MAXNAMELEN]; 1197 char *drv; 1198 1199 if ((drv = ddi_major_to_name(getmajor(dev))) == NULL) 1200 return (EINVAL); 1201 1202 (void) snprintf(macname, sizeof (macname), "%s%d", drv, 1203 DLS_MINOR2INST(getminor(dev))); 1204 return (dls_devnet_macname2linkid(macname, linkidp)); 1205 } 1206 1207 /* 1208 * Get the link's physical dev_t. It this is a VLAN, get the dev_t of the 1209 * link this VLAN is created on. 1210 */ 1211 int 1212 dls_devnet_phydev(datalink_id_t vlanid, dev_t *devp) 1213 { 1214 dls_devnet_t *ddp; 1215 int err; 1216 1217 if ((err = dls_devnet_hold_tmp(vlanid, &ddp)) != 0) 1218 return (err); 1219 1220 err = dls_mgmt_get_phydev(ddp->dd_linkid, devp); 1221 dls_devnet_rele_tmp(ddp); 1222 return (err); 1223 } 1224 1225 /* 1226 * Handle the renaming requests. There are two rename cases: 1227 * 1228 * 1. Request to rename a valid link (id1) to an non-existent link name 1229 * (id2). In this case id2 is DATALINK_INVALID_LINKID. Just check whether 1230 * id1 is held by any applications. 1231 * 1232 * In this case, the link's kstats need to be updated using the given name. 1233 * 1234 * 2. Request to rename a valid link (id1) to the name of a REMOVED 1235 * physical link (id2). In this case, check that id1 and its associated 1236 * mac is not held by any application, and update the link's linkid to id2. 1237 * 1238 * This case does not change the <link name, linkid> mapping, so the link's 1239 * kstats need to be updated with using name associated the given id2. 1240 */ 1241 int 1242 dls_devnet_rename(datalink_id_t id1, datalink_id_t id2, const char *link) 1243 { 1244 dls_dev_handle_t ddh = NULL; 1245 int err = 0; 1246 dev_t phydev = 0; 1247 dls_devnet_t *ddp; 1248 mac_perim_handle_t mph = NULL; 1249 mac_handle_t mh; 1250 mod_hash_val_t val; 1251 1252 /* 1253 * In the second case, id2 must be a REMOVED physical link. 1254 */ 1255 if ((id2 != DATALINK_INVALID_LINKID) && 1256 (dls_mgmt_get_phydev(id2, &phydev) == 0) && 1257 softmac_hold_device(phydev, &ddh) == 0) { 1258 softmac_rele_device(ddh); 1259 return (EEXIST); 1260 } 1261 1262 /* 1263 * Hold id1 to prevent it from being detached (if a physical link). 1264 */ 1265 if (dls_mgmt_get_phydev(id1, &phydev) == 0) 1266 (void) softmac_hold_device(phydev, &ddh); 1267 1268 /* 1269 * The framework does not hold hold locks across calls to the 1270 * mac perimeter, hence enter the perimeter first. This also waits 1271 * for the property loading to finish. 1272 */ 1273 if ((err = mac_perim_enter_by_linkid(id1, &mph)) != 0) { 1274 softmac_rele_device(ddh); 1275 return (err); 1276 } 1277 1278 rw_enter(&i_dls_devnet_lock, RW_WRITER); 1279 if ((err = mod_hash_find(i_dls_devnet_id_hash, 1280 (mod_hash_key_t)(uintptr_t)id1, (mod_hash_val_t *)&ddp)) != 0) { 1281 ASSERT(err == MH_ERR_NOTFOUND); 1282 err = ENOENT; 1283 goto done; 1284 } 1285 1286 mutex_enter(&ddp->dd_mutex); 1287 if (ddp->dd_ref > 1) { 1288 mutex_exit(&ddp->dd_mutex); 1289 err = EBUSY; 1290 goto done; 1291 } 1292 mutex_exit(&ddp->dd_mutex); 1293 1294 if (id2 == DATALINK_INVALID_LINKID) { 1295 (void) strlcpy(ddp->dd_linkname, link, 1296 sizeof (ddp->dd_linkname)); 1297 1298 /* rename mac client name and its flow if exists */ 1299 if ((err = mac_open(ddp->dd_mac, &mh)) != 0) 1300 goto done; 1301 (void) mac_rename_primary(mh, link); 1302 mac_close(mh); 1303 goto done; 1304 } 1305 1306 /* 1307 * The second case, check whether the MAC is used by any MAC 1308 * user. This must be a physical link so ddh must not be NULL. 1309 */ 1310 if (ddh == NULL) { 1311 err = EINVAL; 1312 goto done; 1313 } 1314 1315 if ((err = mac_open(ddp->dd_mac, &mh)) != 0) 1316 goto done; 1317 1318 /* 1319 * We release the reference of the MAC which mac_open() is 1320 * holding. Note that this mac will not be unregistered 1321 * because the physical device is held. 1322 */ 1323 mac_close(mh); 1324 1325 /* 1326 * Check if there is any other MAC clients, if not, hold this mac 1327 * exclusively until we are done. 1328 */ 1329 if ((err = mac_mark_exclusive(mh)) != 0) 1330 goto done; 1331 1332 /* 1333 * Update the link's linkid. 1334 */ 1335 if ((err = mod_hash_find(i_dls_devnet_id_hash, 1336 (mod_hash_key_t)(uintptr_t)id2, &val)) != MH_ERR_NOTFOUND) { 1337 mac_unmark_exclusive(mh); 1338 err = EEXIST; 1339 goto done; 1340 } 1341 1342 err = dls_mgmt_get_linkinfo(id2, ddp->dd_linkname, NULL, NULL, NULL); 1343 if (err != 0) { 1344 mac_unmark_exclusive(mh); 1345 goto done; 1346 } 1347 1348 (void) mod_hash_remove(i_dls_devnet_id_hash, 1349 (mod_hash_key_t)(uintptr_t)id1, &val); 1350 1351 ddp->dd_linkid = id2; 1352 (void) mod_hash_insert(i_dls_devnet_id_hash, 1353 (mod_hash_key_t)(uintptr_t)ddp->dd_linkid, (mod_hash_val_t)ddp); 1354 1355 mac_unmark_exclusive(mh); 1356 1357 /* load properties for new id */ 1358 mutex_enter(&ddp->dd_mutex); 1359 ddp->dd_prop_loaded = B_FALSE; 1360 ddp->dd_prop_taskid = taskq_dispatch(system_taskq, 1361 dls_devnet_prop_task, ddp, TQ_SLEEP); 1362 mutex_exit(&ddp->dd_mutex); 1363 1364 done: 1365 rw_exit(&i_dls_devnet_lock); 1366 1367 if (err == 0) 1368 dls_devnet_stat_rename(ddp); 1369 1370 if (mph != NULL) 1371 mac_perim_exit(mph); 1372 softmac_rele_device(ddh); 1373 return (err); 1374 } 1375 1376 static int 1377 i_dls_devnet_setzid(dls_devnet_t *ddp, zoneid_t new_zoneid, boolean_t setprop) 1378 { 1379 int err; 1380 mac_perim_handle_t mph; 1381 boolean_t upcall_done = B_FALSE; 1382 datalink_id_t linkid = ddp->dd_linkid; 1383 zoneid_t old_zoneid = ddp->dd_zid; 1384 dlmgmt_door_setzoneid_t setzid; 1385 dlmgmt_setzoneid_retval_t retval; 1386 1387 if (old_zoneid == new_zoneid) 1388 return (0); 1389 1390 if ((err = mac_perim_enter_by_macname(ddp->dd_mac, &mph)) != 0) 1391 return (err); 1392 1393 /* 1394 * When changing the zoneid of an existing link, we need to tell 1395 * dlmgmtd about it. dlmgmtd already knows the zoneid associated with 1396 * newly created links. 1397 */ 1398 if (setprop) { 1399 setzid.ld_cmd = DLMGMT_CMD_SETZONEID; 1400 setzid.ld_linkid = linkid; 1401 setzid.ld_zoneid = new_zoneid; 1402 err = i_dls_mgmt_upcall(&setzid, sizeof (setzid), &retval, 1403 sizeof (retval)); 1404 if (err != 0) 1405 goto done; 1406 upcall_done = B_TRUE; 1407 } 1408 if ((err = dls_link_setzid(ddp->dd_mac, new_zoneid)) == 0) { 1409 ddp->dd_zid = new_zoneid; 1410 devnet_need_rebuild = B_TRUE; 1411 } 1412 1413 done: 1414 if (err != 0 && upcall_done) { 1415 setzid.ld_zoneid = old_zoneid; 1416 (void) i_dls_mgmt_upcall(&setzid, sizeof (setzid), &retval, 1417 sizeof (retval)); 1418 } 1419 mac_perim_exit(mph); 1420 return (err); 1421 } 1422 1423 int 1424 dls_devnet_setzid(dls_dl_handle_t ddh, zoneid_t new_zid) 1425 { 1426 dls_devnet_t *ddp; 1427 int err; 1428 zoneid_t old_zid; 1429 boolean_t refheld = B_FALSE; 1430 1431 old_zid = ddh->dd_zid; 1432 1433 if (old_zid == new_zid) 1434 return (0); 1435 1436 /* 1437 * Acquire an additional reference to the link if it is being assigned 1438 * to a non-global zone from the global zone. 1439 */ 1440 if (old_zid == GLOBAL_ZONEID && new_zid != GLOBAL_ZONEID) { 1441 if ((err = dls_devnet_hold(ddh->dd_linkid, &ddp)) != 0) 1442 return (err); 1443 refheld = B_TRUE; 1444 } 1445 1446 if ((err = i_dls_devnet_setzid(ddh, new_zid, B_TRUE)) != 0) { 1447 if (refheld) 1448 dls_devnet_rele(ddp); 1449 return (err); 1450 } 1451 1452 /* 1453 * Release the additional reference if the link is returning to the 1454 * global zone from a non-global zone. 1455 */ 1456 if (old_zid != GLOBAL_ZONEID && new_zid == GLOBAL_ZONEID) 1457 dls_devnet_rele(ddh); 1458 1459 /* Re-create kstats in the appropriate zones. */ 1460 if (old_zid != GLOBAL_ZONEID) 1461 dls_devnet_stat_destroy(ddh, old_zid); 1462 if (new_zid != GLOBAL_ZONEID) 1463 dls_devnet_stat_create(ddh, new_zid); 1464 1465 return (0); 1466 } 1467 1468 zoneid_t 1469 dls_devnet_getzid(dls_dl_handle_t ddh) 1470 { 1471 return (((dls_devnet_t *)ddh)->dd_zid); 1472 } 1473 1474 zoneid_t 1475 dls_devnet_getownerzid(dls_dl_handle_t ddh) 1476 { 1477 return (((dls_devnet_t *)ddh)->dd_owner_zid); 1478 } 1479 1480 /* 1481 * Is linkid visible from zoneid? A link is visible if it was created in the 1482 * zone, or if it is currently assigned to the zone. 1483 */ 1484 boolean_t 1485 dls_devnet_islinkvisible(datalink_id_t linkid, zoneid_t zoneid) 1486 { 1487 dls_devnet_t *ddp; 1488 boolean_t result; 1489 1490 if (dls_devnet_hold_tmp(linkid, &ddp) != 0) 1491 return (B_FALSE); 1492 result = (ddp->dd_owner_zid == zoneid || ddp->dd_zid == zoneid); 1493 dls_devnet_rele_tmp(ddp); 1494 return (result); 1495 } 1496 1497 /* 1498 * Access a vanity naming node. 1499 */ 1500 int 1501 dls_devnet_open(const char *link, dls_dl_handle_t *dhp, dev_t *devp) 1502 { 1503 dls_devnet_t *ddp; 1504 dls_link_t *dlp; 1505 zoneid_t zid = getzoneid(); 1506 int err; 1507 mac_perim_handle_t mph; 1508 1509 if ((err = dls_devnet_hold_by_name(link, &ddp)) != 0) 1510 return (err); 1511 1512 dls_devnet_prop_task_wait(ddp); 1513 1514 /* 1515 * Opening a link that does not belong to the current non-global zone 1516 * is not allowed. 1517 */ 1518 if (zid != GLOBAL_ZONEID && ddp->dd_zid != zid) { 1519 dls_devnet_rele(ddp); 1520 return (ENOENT); 1521 } 1522 1523 err = mac_perim_enter_by_macname(ddp->dd_mac, &mph); 1524 if (err != 0) { 1525 dls_devnet_rele(ddp); 1526 return (err); 1527 } 1528 1529 err = dls_link_hold_create(ddp->dd_mac, &dlp); 1530 mac_perim_exit(mph); 1531 1532 if (err != 0) { 1533 dls_devnet_rele(ddp); 1534 return (err); 1535 } 1536 1537 *dhp = ddp; 1538 *devp = dls_link_dev(dlp); 1539 return (0); 1540 } 1541 1542 /* 1543 * Close access to a vanity naming node. 1544 */ 1545 void 1546 dls_devnet_close(dls_dl_handle_t dlh) 1547 { 1548 dls_devnet_t *ddp = dlh; 1549 dls_link_t *dlp; 1550 mac_perim_handle_t mph; 1551 1552 VERIFY(mac_perim_enter_by_macname(ddp->dd_mac, &mph) == 0); 1553 VERIFY(dls_link_hold(ddp->dd_mac, &dlp) == 0); 1554 1555 /* 1556 * One rele for the hold placed in dls_devnet_open, another for 1557 * the hold done just above 1558 */ 1559 dls_link_rele(dlp); 1560 dls_link_rele(dlp); 1561 mac_perim_exit(mph); 1562 1563 dls_devnet_rele(ddp); 1564 } 1565 1566 /* 1567 * This is used by /dev/net to rebuild the nodes for readdir(). It is not 1568 * critical and no protection is needed. 1569 */ 1570 boolean_t 1571 dls_devnet_rebuild() 1572 { 1573 boolean_t updated = devnet_need_rebuild; 1574 1575 devnet_need_rebuild = B_FALSE; 1576 return (updated); 1577 } 1578 1579 int 1580 dls_devnet_create(mac_handle_t mh, datalink_id_t linkid, zoneid_t zoneid) 1581 { 1582 dls_link_t *dlp; 1583 dls_devnet_t *ddp; 1584 int err; 1585 mac_perim_handle_t mph; 1586 1587 /* 1588 * Holding the mac perimeter ensures that the downcall from the 1589 * dlmgmt daemon which does the property loading does not proceed 1590 * until we relinquish the perimeter. 1591 */ 1592 mac_perim_enter_by_mh(mh, &mph); 1593 /* 1594 * Make this association before we call dls_link_hold_create as 1595 * we need to use the linkid to get the user name for the link 1596 * when we create the MAC client. 1597 */ 1598 if ((err = dls_devnet_set(mac_name(mh), linkid, zoneid, &ddp)) == 0) { 1599 if ((err = dls_link_hold_create(mac_name(mh), &dlp)) != 0) { 1600 mac_perim_exit(mph); 1601 (void) dls_devnet_unset(mac_name(mh), &linkid, B_TRUE); 1602 return (err); 1603 } 1604 } 1605 mac_perim_exit(mph); 1606 return (err); 1607 } 1608 1609 /* 1610 * Set the linkid of the dls_devnet_t and add it into the i_dls_devnet_id_hash. 1611 * This is called in the case that the dlmgmtd daemon is started later than 1612 * the physical devices get attached, and the linkid is only known after the 1613 * daemon starts. 1614 */ 1615 int 1616 dls_devnet_recreate(mac_handle_t mh, datalink_id_t linkid) 1617 { 1618 ASSERT(linkid != DATALINK_INVALID_LINKID); 1619 return (dls_devnet_set(mac_name(mh), linkid, GLOBAL_ZONEID, NULL)); 1620 } 1621 1622 int 1623 dls_devnet_destroy(mac_handle_t mh, datalink_id_t *idp, boolean_t wait) 1624 { 1625 int err; 1626 mac_perim_handle_t mph; 1627 1628 *idp = DATALINK_INVALID_LINKID; 1629 err = dls_devnet_unset(mac_name(mh), idp, wait); 1630 if (err != 0 && err != ENOENT) 1631 return (err); 1632 1633 mac_perim_enter_by_mh(mh, &mph); 1634 err = dls_link_rele_by_name(mac_name(mh)); 1635 mac_perim_exit(mph); 1636 1637 if (err != 0) { 1638 /* 1639 * XXX It is a general GLDv3 bug that dls_devnet_set() has to 1640 * be called to re-set the link when destroy fails. The 1641 * zoneid below will be incorrect if this function is ever 1642 * called from kernel context or from a zone other than that 1643 * which initially created the link. 1644 */ 1645 (void) dls_devnet_set(mac_name(mh), *idp, crgetzoneid(CRED()), 1646 NULL); 1647 } 1648 return (err); 1649 } 1650 1651 /* 1652 * Implicitly create an IP tunnel link. 1653 */ 1654 static int 1655 i_dls_devnet_create_iptun(const char *linkname, const char *drvname, 1656 datalink_id_t *linkid) 1657 { 1658 int err; 1659 iptun_kparams_t ik; 1660 uint32_t media; 1661 netstack_t *ns; 1662 major_t iptun_major; 1663 dev_info_t *iptun_dip; 1664 1665 /* First ensure that the iptun device is attached. */ 1666 if ((iptun_major = ddi_name_to_major(IPTUN_DRIVER_NAME)) == (major_t)-1) 1667 return (EINVAL); 1668 if ((iptun_dip = ddi_hold_devi_by_instance(iptun_major, 0, 0)) == NULL) 1669 return (EINVAL); 1670 1671 if (IS_IPV4_TUN(drvname)) { 1672 ik.iptun_kparam_type = IPTUN_TYPE_IPV4; 1673 media = DL_IPV4; 1674 } else if (IS_6TO4_TUN(drvname)) { 1675 ik.iptun_kparam_type = IPTUN_TYPE_6TO4; 1676 media = DL_6TO4; 1677 } else if (IS_IPV6_TUN(drvname)) { 1678 ik.iptun_kparam_type = IPTUN_TYPE_IPV6; 1679 media = DL_IPV6; 1680 } 1681 ik.iptun_kparam_flags = (IPTUN_KPARAM_TYPE | IPTUN_KPARAM_IMPLICIT); 1682 1683 /* Obtain a datalink id for this tunnel. */ 1684 err = dls_mgmt_create((char *)linkname, 0, DATALINK_CLASS_IPTUN, media, 1685 B_FALSE, &ik.iptun_kparam_linkid); 1686 if (err != 0) { 1687 ddi_release_devi(iptun_dip); 1688 return (err); 1689 } 1690 1691 ns = netstack_get_current(); 1692 err = iptun_create(&ik, CRED()); 1693 netstack_rele(ns); 1694 1695 if (err != 0) 1696 VERIFY(dls_mgmt_destroy(ik.iptun_kparam_linkid, B_FALSE) == 0); 1697 else 1698 *linkid = ik.iptun_kparam_linkid; 1699 1700 ddi_release_devi(iptun_dip); 1701 return (err); 1702 } 1703 1704 static int 1705 i_dls_devnet_destroy_iptun(datalink_id_t linkid) 1706 { 1707 int err; 1708 1709 /* 1710 * Note the use of zone_kcred() here as opposed to CRED(). This is 1711 * because the process that does the last close of this /dev/net node 1712 * may not have necessary privileges to delete this IP tunnel, but the 1713 * tunnel must always be implicitly deleted on last close. 1714 */ 1715 if ((err = iptun_delete(linkid, zone_kcred())) == 0) 1716 (void) dls_mgmt_destroy(linkid, B_FALSE); 1717 return (err); 1718 } 1719 1720 const char * 1721 dls_devnet_mac(dls_dl_handle_t ddh) 1722 { 1723 return (ddh->dd_mac); 1724 } 1725 1726 datalink_id_t 1727 dls_devnet_linkid(dls_dl_handle_t ddh) 1728 { 1729 return (ddh->dd_linkid); 1730 } 1731