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