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 }