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