--- old/usr/src/Makefile.lint	Wed Jan 21 15:51:16 2015
+++ new/usr/src/Makefile.lint	Wed Jan 21 15:51:16 2015
@@ -463,7 +463,6 @@
 	lib/pam_modules \
 	lib/passwdutil \
 	lib/pkcs11 \
-	lib/print \
 	lib/raidcfg_plugins \
 	lib/scsi \
 	lib/smbsrv \
--- old/usr/src/cmd/dladm/dladm.c	Wed Jan 21 15:51:16 2015
+++ new/usr/src/cmd/dladm/dladm.c	Wed Jan 21 15:51:16 2015
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012 Joyent, Inc. All rights reserved.
  */
 
 #include <stdio.h>
@@ -154,6 +155,7 @@
 	dladm_status_t	vs_status;
 	uint32_t	vs_flags;
 	ofmt_handle_t	vs_ofmt;
+	char		*vs_zonename;
 } show_vnic_state_t;
 
 typedef struct show_part_state {
@@ -265,7 +267,7 @@
 
 static cmd_t	cmds[] = {
 	{ "rename-link",	do_rename_link,
-	    "    rename-link      <oldlink> <newlink>"			},
+	    "    rename-link      [-z zonename] <oldlink> <newlink>"	},
 	{ "show-link",		do_show_link,
 	    "    show-link        [-pP] [-o <field>,..] [-s [-i <interval>]] "
 	    "[<link>]\n"						},
@@ -300,12 +302,13 @@
 	{ "show-wifi",		do_show_wifi,
 	    "    show-wifi        [-p] [-o <field>,...] [<link>]\n"	},
 	{ "set-linkprop",	do_set_linkprop,
-	    "    set-linkprop     [-t] -p <prop>=<value>[,...] <name>"	},
+	    "    set-linkprop     [-t] [-z zonename] -p <prop>=<value>[,...] "
+	    "<name>"							},
 	{ "reset-linkprop",	do_reset_linkprop,
-	    "    reset-linkprop   [-t] [-p <prop>,...] <name>"		},
+	    "    reset-linkprop   [-t] [-z zonename] [-p <prop>,...] <name>"},
 	{ "show-linkprop",	do_show_linkprop,
-	    "    show-linkprop    [-cP] [-o <field>,...] [-p <prop>,...] "
-	    "<name>\n"							},
+	    "    show-linkprop    [-cP] [-o <field>,...] [-z zonename] "
+	    "[-p <prop>,...] <name>\n"					},
 	{ "show-ether",		do_show_ether,
 	    "    show-ether       [-px][-o <field>,...] <link>\n"	},
 	{ "create-secobj",	do_create_secobj,
@@ -347,10 +350,10 @@
 	    "\t\t     {vrrp -V <vrid> -A {inet | inet6}} [-v <vid> [-f]]\n"
 	    "\t\t     [-p <prop>=<value>[,...]] <vnic-link>"	},
 	{ "delete-vnic",	do_delete_vnic,
-	    "    delete-vnic      [-t] <vnic-link>"			},
+	    "    delete-vnic      [-t] [-z zonename] <vnic-link>"	},
 	{ "show-vnic",		do_show_vnic,
-	    "    show-vnic        [-pP] [-l <link>] [-s [-i <interval>]] "
-	    "[<link>]\n"						},
+	    "    show-vnic        [-pP] [-l <link>] [-z zonename] "
+	    "[-s [-i <interval>]] [<link>]\n"						},
 	{ "up-vnic",		do_up_vnic,		NULL		},
 	{ "create-part",	do_create_part,
 	    "    create-part      [-t] [-f] -l <link> [-P <pkey>]\n"
@@ -959,6 +962,7 @@
 	char			ls_link[MAXLINKNAMELEN];
 	char			*ls_line;
 	char			**ls_propvals;
+	char			*ls_zonename;
 	dladm_arg_list_t	*ls_proplist;
 	boolean_t		ls_parsable;
 	boolean_t		ls_persist;
@@ -1011,21 +1015,24 @@
 	char vnic_macaddr[18];
 	char vnic_macaddrtype[19];
 	char vnic_vid[6];
+	char vnic_zone[ZONENAME_MAX];
 } vnic_fields_buf_t;
 
 static const ofmt_field_t vnic_fields[] = {
 { "LINK",		13,
 	offsetof(vnic_fields_buf_t, vnic_link),	print_default_cb},
-{ "OVER",		13,
+{ "OVER",		11,
 	offsetof(vnic_fields_buf_t, vnic_over),	print_default_cb},
-{ "SPEED",		7,
+{ "SPEED",		6,
 	offsetof(vnic_fields_buf_t, vnic_speed), print_default_cb},
 { "MACADDRESS",		18,
 	offsetof(vnic_fields_buf_t, vnic_macaddr), print_default_cb},
-{ "MACADDRTYPE",	20,
+{ "MACADDRTYPE",	12,
 	offsetof(vnic_fields_buf_t, vnic_macaddrtype), print_default_cb},
-{ "VID",		7,
+{ "VID",		5,
 	offsetof(vnic_fields_buf_t, vnic_vid), print_default_cb},
+{ "ZONE",		20,
+	offsetof(vnic_fields_buf_t, vnic_zone), print_default_cb},
 { NULL,			0, 0, NULL}}
 ;
 
@@ -2495,13 +2502,17 @@
 	char		*link1, *link2;
 	char		*altroot = NULL;
 	dladm_status_t	status;
+	char		*zonename = NULL;
 
 	opterr = 0;
-	while ((option = getopt_long(argc, argv, ":R:", lopts, NULL)) != -1) {
+	while ((option = getopt_long(argc, argv, ":R:z:", lopts, NULL)) != -1) {
 		switch (option) {
 		case 'R':
 			altroot = optarg;
 			break;
+		case 'z':
+			zonename = optarg;
+			break;
 		default:
 			die_opterr(optopt, option, use);
 			break;
@@ -2517,7 +2528,7 @@
 
 	link1 = argv[optind++];
 	link2 = argv[optind];
-	if ((status = dladm_rename_link(handle, link1, link2)) !=
+	if ((status = dladm_rename_link(handle, zonename, link1, link2)) !=
 	    DLADM_STATUS_OK)
 		die_dlerr(status, "rename operation failed");
 }
@@ -3407,11 +3418,12 @@
 	ofmt_handle_t	ofmt;
 	ofmt_status_t	oferr;
 	uint_t		ofmtflags = 0;
+	char		*zonename = NULL;
 
 	bzero(&state, sizeof (state));
 
 	opterr = 0;
-	while ((option = getopt_long(argc, argv, ":pPsSi:o:",
+	while ((option = getopt_long(argc, argv, ":pPsSi:o:z:",
 	    show_lopts, NULL)) != -1) {
 		switch (option) {
 		case 'p':
@@ -3450,6 +3462,9 @@
 			if (!dladm_str2interval(optarg, &interval))
 				die("invalid interval value '%s'", optarg);
 			break;
+		case 'z':
+			zonename = optarg;
+			break;
 		default:
 			die_opterr(optopt, option, use);
 			break;
@@ -3475,8 +3490,8 @@
 		if (strlcpy(linkname, argv[optind], MAXLINKNAMELEN) >=
 		    MAXLINKNAMELEN)
 			die("link name too long");
-		if ((status = dladm_name2info(handle, linkname, &linkid, &f,
-		    NULL, NULL)) != DLADM_STATUS_OK) {
+		if ((status = dladm_zname2info(handle, zonename, linkname,
+		    &linkid, &f, NULL, NULL)) != DLADM_STATUS_OK) {
 			die_dlerr(status, "link %s is not valid", linkname);
 		}
 
@@ -4741,6 +4756,12 @@
 	if ((flags & DLADM_OPT_FORCE) != 0 && vid == 0)
 		die("-f option can only be used with -v");
 
+	/*
+	 * If creating a transient VNIC for a zone, mark it in the kernel.
+	 */
+	if (strstr(propstr, "zone=") != NULL && !(flags & DLADM_OPT_PERSIST))
+		flags |= DLADM_OPT_TRANSIENT;
+
 	if (mac_prefix_len != 0 && mac_addr_type != VNIC_MAC_ADDR_TYPE_RANDOM &&
 	    mac_addr_type != VNIC_MAC_ADDR_TYPE_FIXED)
 		usage();
@@ -4832,9 +4853,10 @@
 	datalink_id_t linkid;
 	char *altroot = NULL;
 	dladm_status_t status;
+	char	*zonename = NULL;
 
 	opterr = 0;
-	while ((option = getopt_long(argc, argv, ":R:t", lopts,
+	while ((option = getopt_long(argc, argv, ":R:tz:", lopts,
 	    NULL)) != -1) {
 		switch (option) {
 		case 't':
@@ -4843,6 +4865,9 @@
 		case 'R':
 			altroot = optarg;
 			break;
+		case 'z':
+			zonename = optarg;
+			break;
 		default:
 			die_opterr(optopt, option, use);
 		}
@@ -4855,8 +4880,8 @@
 	if (altroot != NULL)
 		altroot_cmd(altroot, argc, argv);
 
-	status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL,
-	    NULL);
+	status = dladm_zname2info(handle, zonename, argv[optind], &linkid, NULL,
+	    NULL, NULL);
 	if (status != DLADM_STATUS_OK)
 		die("invalid link name '%s'", argv[optind]);
 
@@ -4988,6 +5013,9 @@
 	char			vnic_name[MAXLINKNAMELEN];
 	char			mstr[MAXMACADDRLEN * 3];
 	vnic_fields_buf_t	vbuf;
+	uint_t			valcnt = 1;
+	char			zonename[DLADM_PROP_VAL_MAX + 1];
+	char			*valptr[1];
 
 	if ((status = dladm_vnic_info(handle, linkid, vnic, state->vs_flags)) !=
 	    DLADM_STATUS_OK)
@@ -5017,6 +5045,18 @@
 	    NULL, devname, sizeof (devname)) != DLADM_STATUS_OK)
 		(void) sprintf(devname, "?");
 
+	
+	zonename[0] = '\0';
+	if (!is_etherstub) {
+		valptr[0] = zonename;
+		(void) dladm_get_linkprop(handle, linkid,
+		    DLADM_PROP_VAL_CURRENT, "zone", (char **)valptr, &valcnt);
+	}
+
+	if (state->vs_zonename != NULL &&
+	     strcmp(state->vs_zonename, zonename) != 0)
+		return (DLADM_STATUS_OK);
+
 	state->vs_found = B_TRUE;
 	if (state->vs_stats) {
 		/* print vnic statistics */
@@ -5092,6 +5132,13 @@
 
 			(void) snprintf(vbuf.vnic_vid, sizeof (vbuf.vnic_vid),
 			    "%d", vnic->va_vid);
+
+			if (zonename[0] != '\0')
+				(void) snprintf(vbuf.vnic_zone,
+				    sizeof (vbuf.vnic_zone), "%s", zonename);
+			else
+				(void) strlcpy(vbuf.vnic_zone, "--",
+				     sizeof (vbuf.vnic_zone));
 		}
 
 		ofmt_print(state->vs_ofmt, &vbuf);
@@ -5130,10 +5177,11 @@
 	ofmt_handle_t		ofmt;
 	ofmt_status_t		oferr;
 	uint_t			ofmtflags = 0;
+	char			*zonename = NULL;
 
 	bzero(&state, sizeof (state));
 	opterr = 0;
-	while ((option = getopt_long(argc, argv, ":pPl:si:o:", lopts,
+	while ((option = getopt_long(argc, argv, ":pPl:si:o:z:", lopts,
 	    NULL)) != -1) {
 		switch (option) {
 		case 'p':
@@ -5172,6 +5220,9 @@
 			o_arg = B_TRUE;
 			fields_str = optarg;
 			break;
+		case 'z':
+			zonename = optarg;
+			break;
 		default:
 			die_opterr(optopt, option, use);
 		}
@@ -5182,8 +5233,8 @@
 
 	/* get vnic ID (optional last argument) */
 	if (optind == (argc - 1)) {
-		status = dladm_name2info(handle, argv[optind], &linkid, NULL,
-		    NULL, NULL);
+		status = dladm_zname2info(handle, zonename, argv[optind],
+		    &linkid, NULL, NULL, NULL);
 		if (status != DLADM_STATUS_OK) {
 			die_dlerr(status, "invalid vnic name '%s'",
 			    argv[optind]);
@@ -5194,8 +5245,8 @@
 	}
 
 	if (l_arg) {
-		status = dladm_name2info(handle, state.vs_link, &dev_linkid,
-		    NULL, NULL, NULL);
+		status = dladm_zname2info(handle, zonename, state.vs_link,
+		    &dev_linkid, NULL, NULL, NULL);
 		if (status != DLADM_STATUS_OK) {
 			die_dlerr(status, "invalid link name '%s'",
 			    state.vs_link);
@@ -5207,6 +5258,7 @@
 	state.vs_etherstub = etherstub;
 	state.vs_found = B_FALSE;
 	state.vs_flags = flags;
+	state.vs_zonename = zonename;
 
 	if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) {
 		if (etherstub)
@@ -6695,6 +6747,7 @@
 	ofmt_handle_t		ofmt;
 	ofmt_status_t		oferr;
 	uint_t			ofmtflags = 0;
+	char			*zonename = NULL;
 
 	bzero(propstr, DLADM_STRSIZE);
 	opterr = 0;
@@ -6705,7 +6758,7 @@
 	state.ls_header = B_TRUE;
 	state.ls_retstatus = DLADM_STATUS_OK;
 
-	while ((option = getopt_long(argc, argv, ":p:cPo:",
+	while ((option = getopt_long(argc, argv, ":p:cPo:z:",
 	    prop_longopts, NULL)) != -1) {
 		switch (option) {
 		case 'p':
@@ -6724,6 +6777,9 @@
 		case 'o':
 			fields_str = optarg;
 			break;
+		case 'z':
+			zonename = optarg;
+			break;
 		default:
 			die_opterr(optopt, option, use);
 			break;
@@ -6731,8 +6787,8 @@
 	}
 
 	if (optind == (argc - 1)) {
-		if ((status = dladm_name2info(handle, argv[optind], &linkid,
-		    NULL, NULL, NULL)) != DLADM_STATUS_OK) {
+		if ((status = dladm_zname2info(handle, zonename, argv[optind],
+		    &linkid, NULL, NULL, NULL)) != DLADM_STATUS_OK) {
 			die_dlerr(status, "link %s is not valid", argv[optind]);
 		}
 	} else if (optind != argc) {
@@ -6743,6 +6799,7 @@
 	    != DLADM_STATUS_OK)
 		die("invalid link properties specified");
 	state.ls_proplist = proplist;
+	state.ls_zonename = zonename;
 	state.ls_status = DLADM_STATUS_OK;
 
 	if (state.ls_parsable)
@@ -6787,6 +6844,17 @@
 		return (DLADM_WALK_CONTINUE);
 	}
 
+	if (statep->ls_zonename != NULL) {
+		datalink_id_t	tlinkid;
+
+		if (dladm_zname2info(hdl, statep->ls_zonename, statep->ls_link,
+		    &tlinkid, NULL, NULL, NULL) != DLADM_STATUS_OK ||
+		    linkid != tlinkid) {
+			statep->ls_status = DLADM_STATUS_NOTFOUND;
+			return (DLADM_WALK_CONTINUE);
+		}
+	}
+
 	if ((statep->ls_persist && !(flags & DLADM_OPT_PERSIST)) ||
 	    (!statep->ls_persist && !(flags & DLADM_OPT_ACTIVE))) {
 		statep->ls_status = DLADM_STATUS_BADARG;
@@ -6869,11 +6937,12 @@
 	dladm_status_t		status = DLADM_STATUS_OK;
 	char			propstr[DLADM_STRSIZE];
 	dladm_arg_list_t	*proplist = NULL;
+	char			*zonename = NULL;
 
 	opterr = 0;
 	bzero(propstr, DLADM_STRSIZE);
 
-	while ((option = getopt_long(argc, argv, ":p:R:t",
+	while ((option = getopt_long(argc, argv, ":p:R:tz:",
 	    prop_longopts, NULL)) != -1) {
 		switch (option) {
 		case 'p':
@@ -6888,6 +6957,9 @@
 		case 'R':
 			altroot = optarg;
 			break;
+		case 'z':
+			zonename = optarg;
+			break;
 		default:
 			die_opterr(optopt, option, use);
 
@@ -6910,8 +6982,8 @@
 		altroot_cmd(altroot, argc, argv);
 	}
 
-	status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL,
-	    NULL);
+	status = dladm_zname2info(handle, zonename, argv[optind], &linkid,
+	    NULL, NULL, NULL);
 	if (status != DLADM_STATUS_OK)
 		die_dlerr(status, "link %s is not valid", argv[optind]);
 
--- old/usr/src/cmd/dlmgmtd/dlmgmt_db.c	Wed Jan 21 15:51:16 2015
+++ new/usr/src/cmd/dlmgmtd/dlmgmt_db.c	Wed Jan 21 15:51:16 2015
@@ -21,6 +21,7 @@
 
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2014, Joyent Inc. All rights reserved.
  */
 
 #include <assert.h>
@@ -43,6 +44,8 @@
 #include <libcontract.h>
 #include <libcontract_priv.h>
 #include <sys/contract/process.h>
+#include <sys/vnic.h>
+#include <zone.h>
 #include "dlmgmt_impl.h"
 
 typedef enum dlmgmt_db_op {
@@ -552,6 +555,10 @@
 	    linkp->ll_zoneid, flags, &err)) == NULL)
 		return (err);
 
+	/* If transient op and onloan, use the global zone cache file. */
+	if (flags == DLMGMT_ACTIVE && linkp->ll_onloan)
+		req->ls_zoneid = GLOBAL_ZONEID;
+
 	/*
 	 * If the return error is EINPROGRESS, this request is handled
 	 * asynchronously; return success.
@@ -714,6 +721,7 @@
 	char			attr_name[MAXLINKATTRLEN];
 	size_t			attr_buf_len = 0;
 	void			*attr_buf = NULL;
+	boolean_t		rename;
 
 	curr = buf;
 	len = strlen(buf);
@@ -723,6 +731,8 @@
 		boolean_t	match = (c == '=' ||
 		    (c == ',' && !found_type) || c == ';');
 
+		rename = B_FALSE;
+
 		/*
 		 * Move to the next character if there is no match and
 		 * if we have not reached the last character.
@@ -768,6 +778,21 @@
 					goto parse_fail;
 				linkp->ll_media =
 				    (uint32_t)*(int64_t *)attr_buf;
+			} else if (strcmp(attr_name, "zone") == 0) {
+				if (read_str(curr, &attr_buf) == 0)
+					goto parse_fail;
+				linkp->ll_zoneid = getzoneidbyname(attr_buf);
+				if (linkp->ll_zoneid == -1) {
+					if (errno == EFAULT)
+						abort();
+					/*
+					 * If we can't find the zone, assign the
+					 * link to the GZ and mark it for being
+					 * renamed.
+					 */
+					linkp->ll_zoneid = 0;
+					rename = B_TRUE;
+				}
 			} else {
 				attr_buf_len = translators[type].read_func(curr,
 				    &attr_buf);
@@ -811,6 +836,16 @@
 
 			(void) snprintf(attr_name, MAXLINKATTRLEN, "%s", curr);
 		}
+
+		/*
+		 * The zone that this link belongs to has died, we are
+		 * reparenting it to the GZ and renaming it to avoid name
+		 * collisions.
+		 */
+		if (rename == B_TRUE) {
+			(void) snprintf(linkp->ll_link, MAXLINKNAMELEN,
+			    "SUNWorphan%u", (uint16_t)(gethrtime() / 1000));
+		}
 		curr = buf + i + 1;
 	}
 
@@ -1222,12 +1257,19 @@
 
 	ptr += snprintf(ptr, BUFLEN(lim, ptr), "%s\t", linkp->ll_link);
 	if (!persist) {
+		char zname[ZONENAME_MAX];
 		/*
-		 * We store the linkid in the active database so that dlmgmtd
-		 * can recover in the event that it is restarted.
+		 * We store the linkid and the zone name in the active database
+		 * so that dlmgmtd can recover in the event that it is
+		 * restarted.
 		 */
 		u64 = linkp->ll_linkid;
 		ptr += write_uint64(ptr, BUFLEN(lim, ptr), "linkid", &u64);
+
+		if (getzonenamebyid(linkp->ll_zoneid, zname,
+		    sizeof (zname)) != -1) {
+			ptr += write_str(ptr, BUFLEN(lim, ptr), "zone", zname);
+		}
 	}
 	u64 = linkp->ll_class;
 	ptr += write_uint64(ptr, BUFLEN(lim, ptr), "class", &u64);
@@ -1382,6 +1424,42 @@
 }
 
 /*
+ * Attempt to mitigate one of the deadlocks in the dlmgmtd architecture.
+ *
+ * dlmgmt_db_init() calls dlmgmt_process_db_req() which eventually gets to
+ * dlmgmt_zfop() which tries to fork, enter the zone and read the file.
+ * Because of the upcall architecture of dlmgmtd this can lead to deadlock
+ * with the following scenario:
+ *    a) the thread preparing to fork will have acquired the malloc locks
+ *       then attempt to suspend every thread in preparation to fork.
+ *    b) all of the upcalls will be blocked in door_ucred() trying to malloc()
+ *       and get the credentials of their caller.
+ *    c) we can't suspend the in-kernel thread making the upcall.
+ *
+ * Thus, we cannot serve door requests because we're blocked in malloc()
+ * which fork() owns, but fork() is in turn blocked on the in-kernel thread
+ * making the door upcall.  This is a fundamental architectural problem with
+ * any server handling upcalls and also trying to fork().
+ *
+ * To minimize the chance of this deadlock occuring, we check ahead of time to
+ * see if the file we want to read actually exists in the zone (which it almost
+ * never does), so we don't need fork in that case (i.e. rarely to never).
+ */
+static boolean_t
+zone_file_exists(char *zoneroot, char *filename)
+{
+	struct stat	sb;
+	char		fname[MAXPATHLEN];
+
+	(void) snprintf(fname, sizeof (fname), "%s/%s", zoneroot, filename);
+
+	if (stat(fname, &sb) == -1)
+		return (B_FALSE);
+
+	return (B_TRUE);
+}
+
+/*
  * Initialize the datalink <link name, linkid> mapping and the link's
  * attributes list based on the configuration file /etc/dladm/datalink.conf
  * and the active configuration cache file
@@ -1388,7 +1466,7 @@
  * /etc/svc/volatile/dladm/datalink-management:default.cache.
  */
 int
-dlmgmt_db_init(zoneid_t zoneid)
+dlmgmt_db_init(zoneid_t zoneid, char *zoneroot)
 {
 	dlmgmt_db_req_t	*req;
 	int		err;
@@ -1398,22 +1476,36 @@
 	    DATALINK_INVALID_LINKID, zoneid, DLMGMT_ACTIVE, &err)) == NULL)
 		return (err);
 
-	if ((err = dlmgmt_process_db_req(req)) != 0) {
-		/*
-		 * If we get back ENOENT, that means that the active
-		 * configuration file doesn't exist yet, and is not an error.
-		 * We'll create it down below after we've loaded the
-		 * persistent configuration.
-		 */
-		if (err != ENOENT)
-			goto done;
+	/* Handle running in a non-native branded zone (i.e. has /native) */
+	if (zone_file_exists(zoneroot, "/native" DLMGMT_TMPFS_DIR)) {
+		char tdir[MAXPATHLEN];
+
+		(void) snprintf(tdir, sizeof (tdir), "/native%s", cachefile);
+		(void) strlcpy(cachefile, tdir, sizeof (cachefile));
+	}
+
+	if (zone_file_exists(zoneroot, cachefile)) {
+		if ((err = dlmgmt_process_db_req(req)) != 0) {
+			/*
+			 * If we get back ENOENT, that means that the active
+			 * configuration file doesn't exist yet, and is not an
+			 * error.  We'll create it down below after we've
+			 * loaded the persistent configuration.
+			 */
+			if (err != ENOENT)
+				goto done;
+			boot = B_TRUE;
+		}
+	} else {
 		boot = B_TRUE;
 	}
 
-	req->ls_flags = DLMGMT_PERSIST;
-	err = dlmgmt_process_db_req(req);
-	if (err != 0 && err != ENOENT)
-		goto done;
+	if (zone_file_exists(zoneroot, DLMGMT_PERSISTENT_DB_PATH)) {
+		req->ls_flags = DLMGMT_PERSIST;
+		err = dlmgmt_process_db_req(req);
+		if (err != 0 && err != ENOENT)
+			goto done;
+	}
 	err = 0;
 	if (rewrite_needed) {
 		/*
@@ -1442,6 +1534,11 @@
 
 /*
  * Remove all links in the given zoneid.
+ *
+ * We do this work in two different passes. In the first pass, we remove any
+ * entry that hasn't been loaned and mark every entry that has been loaned as
+ * something that is going to be tombstomed. In the second pass, we drop the
+ * table lock for every entry and remove the tombstombed entry for our zone.
  */
 void
 dlmgmt_db_fini(zoneid_t zoneid)
@@ -1451,9 +1548,66 @@
 	while (linkp != NULL) {
 		next_linkp = AVL_NEXT(&dlmgmt_name_avl, linkp);
 		if (linkp->ll_zoneid == zoneid) {
-			(void) dlmgmt_destroy_common(linkp,
-			    DLMGMT_ACTIVE | DLMGMT_PERSIST);
+			boolean_t onloan = linkp->ll_onloan;
+
+			/*
+			 * Cleanup any VNICs that were loaned to the zone
+			 * before the zone goes away and we can no longer
+			 * refer to the VNIC by the name/zoneid.
+			 */
+			if (onloan) {
+				(void) dlmgmt_delete_db_entry(linkp,
+				    DLMGMT_ACTIVE);
+				linkp->ll_tomb = B_TRUE;
+			} else {
+				(void) dlmgmt_destroy_common(linkp,
+				    DLMGMT_ACTIVE | DLMGMT_PERSIST);
+			}
+
 		}
 		linkp = next_linkp;
 	}
+
+again:
+	linkp = avl_first(&dlmgmt_name_avl);
+	while (linkp != NULL) {
+		vnic_ioc_delete_t ioc;
+
+		next_linkp = AVL_NEXT(&dlmgmt_name_avl, linkp);
+
+		if (linkp->ll_zoneid != zoneid) {
+			linkp = next_linkp;
+			continue;
+		}
+		ioc.vd_vnic_id = linkp->ll_linkid;
+		if (linkp->ll_tomb != B_TRUE)
+			abort();
+
+		/*
+		 * We have to drop the table lock while going up into the
+		 * kernel. If we hold the table lock while deleting a vnic, we
+		 * may get blocked on the mac perimeter and the holder of it may
+		 * want something from dlmgmtd.
+		 */
+		dlmgmt_table_unlock();
+
+		if (ioctl(dladm_dld_fd(dld_handle),
+		    VNIC_IOC_DELETE, &ioc) < 0)
+			dlmgmt_log(LOG_WARNING, "dlmgmt_db_fini "
+			    "delete VNIC ioctl failed %d %d",
+			    ioc.vd_vnic_id, errno);
+
+		/*
+		 * Even though we've dropped the lock, we know that nothing else
+		 * could have removed us. Therefore, it should be safe to go
+		 * through and delete ourselves, but do nothing else. We'll have
+		 * to restart iteration from the beginning. This can be painful.
+		 */
+		dlmgmt_table_lock(B_TRUE);
+
+		(void) dlmgmt_destroy_common(linkp,
+		    DLMGMT_ACTIVE | DLMGMT_PERSIST);
+		goto again;
+	}
+
 }
--- old/usr/src/cmd/dlmgmtd/dlmgmt_door.c	Wed Jan 21 15:51:17 2015
+++ new/usr/src/cmd/dlmgmtd/dlmgmt_door.c	Wed Jan 21 15:51:17 2015
@@ -21,6 +21,7 @@
 
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, Joyent Inc. All rights reserved.
  */
 
 /*
@@ -58,6 +59,10 @@
 #include <libsysevent.h>
 #include <libdlmgmt.h>
 #include <librcm.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
 #include "dlmgmt_impl.h"
 
 typedef void dlmgmt_door_handler_t(void *, void *, size_t *, zoneid_t,
@@ -379,6 +384,11 @@
 	if ((err = dlmgmt_checkprivs(linkp->ll_class, cred)) != 0)
 		goto done;
 
+	if (linkp->ll_tomb == B_TRUE) {
+		err = EINPROGRESS;
+		goto done;
+	}
+
 	if (((linkp->ll_flags & flags) & DLMGMT_ACTIVE) != 0) {
 		if ((err = dlmgmt_delete_db_entry(linkp, DLMGMT_ACTIVE)) != 0)
 			goto done;
@@ -439,6 +449,10 @@
 	dlmgmt_link_t		*linkp;
 	int			err = 0;
 
+	/* Enable the global zone to lookup links it has given away. */
+	if (zoneid == GLOBAL_ZONEID && getlinkid->ld_zoneid != -1)
+		zoneid = getlinkid->ld_zoneid;
+
 	/*
 	 * Hold the reader lock to access the link
 	 */
@@ -648,6 +662,12 @@
 	if ((err = dlmgmt_checkprivs(linkp->ll_class, cred)) != 0)
 		goto done;
 
+	if (linkp->ll_tomb == B_TRUE) {
+		err = EBUSY;
+		goto done;
+	}
+
+
 	if (link_by_name(remapid->ld_link, linkp->ll_zoneid) != NULL) {
 		err = EEXIST;
 		goto done;
@@ -709,6 +729,11 @@
 	if ((err = dlmgmt_checkprivs(linkp->ll_class, cred)) != 0)
 		goto done;
 
+	if (linkp->ll_tomb == B_TRUE) {
+		err = EBUSY;
+		goto done;
+	}
+
 	if (linkp->ll_flags & DLMGMT_ACTIVE) {
 		err = EINVAL;
 		goto done;
@@ -1216,6 +1241,11 @@
 	if ((err = dlmgmt_checkprivs(linkp->ll_class, cred)) != 0)
 		goto done;
 
+	if (linkp->ll_tomb == B_TRUE) {
+		err = EBUSY;
+		goto done;
+	}
+
 	/* We can only assign an active link to a zone. */
 	if (!(linkp->ll_flags & DLMGMT_ACTIVE)) {
 		err = EINVAL;
@@ -1245,7 +1275,19 @@
 			    "zone %d: %s", linkid, oldzoneid, strerror(err));
 			goto done;
 		}
-		avl_remove(&dlmgmt_loan_avl, linkp);
+
+		if (newzoneid == GLOBAL_ZONEID && linkp->ll_onloan) {
+			/*
+			 * We can only reassign a loaned VNIC back to the
+			 * global zone when the zone is shutting down, since
+			 * otherwise the VNIC is in use by the zone and will be
+			 * busy.  Leave the VNIC assigned to the zone so we can
+			 * still see it and delete it when dlmgmt_zonehalt()
+			 * runs.
+			 */
+			goto done;
+		}
+
 		linkp->ll_onloan = B_FALSE;
 	}
 	if (newzoneid != GLOBAL_ZONEID) {
@@ -1256,7 +1298,6 @@
 			(void) zone_add_datalink(oldzoneid, linkid);
 			goto done;
 		}
-		avl_add(&dlmgmt_loan_avl, linkp);
 		linkp->ll_onloan = B_TRUE;
 	}
 
@@ -1309,7 +1350,11 @@
 	int			err = 0;
 	dlmgmt_door_zonehalt_t	*zonehalt = argp;
 	dlmgmt_zonehalt_retval_t *retvalp = retp;
+	static char my_pid[10];
 
+	if (my_pid[0] == NULL)
+		(void) snprintf(my_pid, sizeof (my_pid), "%d\n", getpid());
+
 	if ((err = dlmgmt_checkprivs(0, cred)) == 0) {
 		if (zoneid != GLOBAL_ZONEID) {
 			err = EACCES;
@@ -1316,9 +1361,26 @@
 		} else if (zonehalt->ld_zoneid == GLOBAL_ZONEID) {
 			err = EINVAL;
 		} else {
+			/*
+			 * dls and mac don't honor the locking rules defined in
+			 * mac. In order to try and make that case less likely
+			 * to happen, we try to serialize some of the zone
+			 * activity here between dlmgmtd and the brands on
+			 * /etc/dladm/zone.lck
+			 */
+			int fd;
+
+			while ((fd = open(ZONE_LOCK, O_WRONLY |
+			    O_CREAT | O_EXCL, S_IRUSR | S_IWUSR)) < 0)
+			(void) sleep(1);
+			(void) write(fd, my_pid, sizeof (my_pid));
+			(void) close(fd);
+
 			dlmgmt_table_lock(B_TRUE);
 			dlmgmt_db_fini(zonehalt->ld_zoneid);
 			dlmgmt_table_unlock();
+
+			(void) unlink(ZONE_LOCK);
 		}
 	}
 	retvalp->lr_err = err;
--- old/usr/src/cmd/dlmgmtd/dlmgmt_impl.h	Wed Jan 21 15:51:17 2015
+++ new/usr/src/cmd/dlmgmtd/dlmgmt_impl.h	Wed Jan 21 15:51:17 2015
@@ -21,6 +21,7 @@
 
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, Joyent Inc. All rights reserved.
  */
 
 /*
@@ -67,6 +68,7 @@
 	avl_node_t		ll_loan_node;
 	uint32_t		ll_flags;
 	uint32_t		ll_gen;		/* generation number */
+	boolean_t		ll_tomb;	/* tombstombed */
 } dlmgmt_link_t;
 
 /*
@@ -84,6 +86,8 @@
 	avl_node_t		ld_node;
 } dlmgmt_dlconf_t;
 
+#define	ZONE_LOCK	"/etc/dladm/zone.lck"
+
 extern boolean_t	debug;
 extern const char	*progname;
 extern char		cachefile[];
@@ -138,7 +142,7 @@
 void		dlmgmt_log(int, const char *, ...);
 int		dlmgmt_write_db_entry(const char *, dlmgmt_link_t *, uint32_t);
 int		dlmgmt_delete_db_entry(dlmgmt_link_t *, uint32_t);
-int 		dlmgmt_db_init(zoneid_t);
+int 		dlmgmt_db_init(zoneid_t, char *);
 void		dlmgmt_db_fini(zoneid_t);
 
 #ifdef  __cplusplus
--- old/usr/src/cmd/dlmgmtd/dlmgmt_main.c	Wed Jan 21 15:51:17 2015
+++ new/usr/src/cmd/dlmgmtd/dlmgmt_main.c	Wed Jan 21 15:51:17 2015
@@ -22,6 +22,7 @@
 /*
  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ * Copyright 2014 Joyent, Inc.  All rights reserved.
  */
 
 /*
@@ -125,15 +126,24 @@
 	dlmgmt_door_fd = -1;
 }
 
-int
+static int
 dlmgmt_door_attach(zoneid_t zoneid, char *rootdir)
 {
 	int	fd;
 	int	err = 0;
 	char	doorpath[MAXPATHLEN];
+	struct stat statbuf;
 
-	(void) snprintf(doorpath, sizeof (doorpath), "%s%s", rootdir,
-	    DLMGMT_DOOR);
+	/* Handle running in a non-native branded zone (i.e. has /native) */
+	(void) snprintf(doorpath, sizeof (doorpath), "%s/native%s",
+	    rootdir, DLMGMT_TMPFS_DIR);
+	if (stat(doorpath, &statbuf) == 0) {
+		(void) snprintf(doorpath, sizeof (doorpath), "%s/native%s",
+		    rootdir, DLMGMT_DOOR);
+	} else {
+		(void) snprintf(doorpath, sizeof (doorpath), "%s%s",
+		    rootdir, DLMGMT_DOOR);
+	}
 
 	/*
 	 * Create the door file for dlmgmtd.
@@ -192,8 +202,16 @@
 	(void) snprintf(tmpfsdir, sizeof (tmpfsdir), "%s%s", rootdir,
 	    DLMGMT_TMPFS_DIR);
 	if (stat(tmpfsdir, &statbuf) < 0) {
-		if (mkdir(tmpfsdir, (mode_t)0755) < 0)
-			return (errno);
+		if (mkdir(tmpfsdir, (mode_t)0755) < 0) {
+			/*
+			 * Handle running in a non-native branded zone
+			 * (i.e. has /native)
+			 */
+			(void) snprintf(tmpfsdir, sizeof (tmpfsdir),
+			    "%s/native%s", rootdir, DLMGMT_TMPFS_DIR);
+			if (mkdir(tmpfsdir, (mode_t)0755) < 0)
+				return (errno);
+		}
 	} else if ((statbuf.st_mode & S_IFMT) != S_IFDIR) {
 		return (ENOTDIR);
 	}
@@ -203,7 +221,7 @@
 		return (EPERM);
 	}
 
-	if ((err = dlmgmt_db_init(zoneid)) != 0)
+	if ((err = dlmgmt_db_init(zoneid, rootdir)) != 0)
 		return (err);
 	return (dlmgmt_door_attach(zoneid, rootdir));
 }
@@ -214,7 +232,7 @@
 static int
 dlmgmt_allzones_init(void)
 {
-	int		err, i;
+	int		i;
 	zoneid_t	*zids = NULL;
 	uint_t		nzids, nzids_saved;
 
@@ -235,11 +253,37 @@
 	}
 
 	for (i = 0; i < nzids; i++) {
-		if ((err = dlmgmt_zone_init(zids[i])) != 0)
-			break;
+		int res;
+		zone_status_t status;
+
+		/*
+		 * Skip over zones that have gone away or are going down
+		 * since we got the list.  Process all zones in the list,
+		 * logging errors for any that failed.
+		 */
+		if (zone_getattr(zids[i], ZONE_ATTR_STATUS, &status,
+		    sizeof (status)) < 0)
+			continue;
+		switch (status) {
+			case ZONE_IS_SHUTTING_DOWN:
+			case ZONE_IS_EMPTY:
+			case ZONE_IS_DOWN:
+			case ZONE_IS_DYING:
+			case ZONE_IS_DEAD:
+				/* FALLTHRU */
+				continue;
+			default:
+				break;
+		}
+		if ((res = dlmgmt_zone_init(zids[i])) != 0) {
+			(void) fprintf(stderr, "zone (%ld) init error %s",
+			    zids[i], strerror(res));
+			dlmgmt_log(LOG_ERR, "zone (%d) init error %s",
+			    zids[i], strerror(res));
+		}
 	}
 	free(zids);
-	return (err);
+	return (0);
 }
 
 static int
@@ -262,6 +306,8 @@
 		return (err);
 	}
 
+	(void) unlink(ZONE_LOCK);
+
 	/*
 	 * First derive the name of the cache file from the FMRI name. This
 	 * cache name is used to keep active datalink configuration.
--- old/usr/src/cmd/dlmgmtd/dlmgmt_util.c	Wed Jan 21 15:51:17 2015
+++ new/usr/src/cmd/dlmgmtd/dlmgmt_util.c	Wed Jan 21 15:51:17 2015
@@ -21,6 +21,7 @@
 
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, Joyent Inc. All rights reserved.
  */
 
 /*
@@ -45,13 +46,10 @@
 /*
  * There are three datalink AVL tables.  The dlmgmt_name_avl tree contains all
  * datalinks and is keyed by zoneid and link name.  The dlmgmt_id_avl also
- * contains all datalinks, and it is keyed by link ID.  The dlmgmt_loan_avl is
- * keyed by link name, and contains the set of global-zone links that are
- * currently on loan to non-global zones.
+ * contains all datalinks, and it is keyed by link ID.
  */
 avl_tree_t	dlmgmt_name_avl;
 avl_tree_t	dlmgmt_id_avl;
-avl_tree_t	dlmgmt_loan_avl;
 
 avl_tree_t	dlmgmt_dlconf_avl;
 
@@ -162,8 +160,6 @@
 	    offsetof(dlmgmt_link_t, ll_name_node));
 	avl_create(&dlmgmt_id_avl, cmp_link_by_id, sizeof (dlmgmt_link_t),
 	    offsetof(dlmgmt_link_t, ll_id_node));
-	avl_create(&dlmgmt_loan_avl, cmp_link_by_name, sizeof (dlmgmt_link_t),
-	    offsetof(dlmgmt_link_t, ll_loan_node));
 	avl_create(&dlmgmt_dlconf_avl, cmp_dlconf_by_id,
 	    sizeof (dlmgmt_dlconf_t), offsetof(dlmgmt_dlconf_t, ld_node));
 	dlmgmt_nextlinkid = 1;
@@ -181,7 +177,6 @@
 
 	avl_destroy(&dlmgmt_dlconf_avl);
 	avl_destroy(&dlmgmt_name_avl);
-	avl_destroy(&dlmgmt_loan_avl);
 	avl_destroy(&dlmgmt_id_avl);
 }
 
@@ -385,7 +380,6 @@
 
 			linkp->ll_zoneid = zoneid;
 			avl_add(&dlmgmt_name_avl, linkp);
-			avl_add(&dlmgmt_loan_avl, linkp);
 			linkp->ll_onloan = B_TRUE;
 		}
 	} else if (linkp->ll_zoneid != GLOBAL_ZONEID) {
@@ -430,10 +424,6 @@
 	(void) strlcpy(link.ll_link, name, MAXLINKNAMELEN);
 	link.ll_zoneid = zoneid;
 	linkp = avl_find(&dlmgmt_name_avl, &link, NULL);
-	if (linkp == NULL && zoneid == GLOBAL_ZONEID) {
-		/* The link could be on loan to a non-global zone? */
-		linkp = avl_find(&dlmgmt_loan_avl, &link, NULL);
-	}
 	return (linkp);
 }
 
@@ -461,6 +451,7 @@
 	linkp->ll_linkid = dlmgmt_nextlinkid;
 	linkp->ll_zoneid = zoneid;
 	linkp->ll_gen = 0;
+	linkp->ll_tomb = B_FALSE;
 
 	if (avl_find(&dlmgmt_name_avl, linkp, &name_where) != NULL ||
 	    avl_find(&dlmgmt_id_avl, linkp, &id_where) != NULL) {
@@ -511,8 +502,6 @@
 
 	if ((flags & DLMGMT_ACTIVE) && linkp->ll_zoneid != GLOBAL_ZONEID) {
 		(void) zone_remove_datalink(linkp->ll_zoneid, linkp->ll_linkid);
-		if (linkp->ll_onloan)
-			avl_remove(&dlmgmt_loan_avl, linkp);
 	}
 
 	if (linkp->ll_flags == 0) {
--- old/usr/src/cmd/dlstat/dlstat.c	Wed Jan 21 15:51:17 2015
+++ new/usr/src/cmd/dlstat/dlstat.c	Wed Jan 21 15:51:17 2015
@@ -62,7 +62,7 @@
 	struct link_chain_s	*lc_next;
 } link_chain_t;
 
-typedef void *	(*stats2str_t)(const char *, void *,
+typedef void *	(*stats2str_t)(const char *, const char *, void *,
 		    char, boolean_t);
 
 typedef struct show_state {
@@ -141,6 +141,7 @@
 	char t_rbytes[MAXSTATLEN];
 	char t_opackets[MAXSTATLEN];
 	char t_obytes[MAXSTATLEN];
+	char t_zone[ZONENAME_MAX];
 } total_fields_buf_t;
 
 static ofmt_field_t total_s_fields[] = {
@@ -154,6 +155,8 @@
     offsetof(total_fields_buf_t, t_opackets),	print_default_cb},
 { "OBYTES",	8,
     offsetof(total_fields_buf_t, t_obytes),	print_default_cb},
+{ "ZONE",	20,
+    offsetof(total_fields_buf_t, t_zone),	print_default_cb},
 { NULL,		0,	0,		NULL}};
 
 /*
@@ -957,8 +960,8 @@
 }
 
 void *
-print_total_stats(const char *linkname, void *statentry, char unit,
-    boolean_t parsable)
+print_total_stats(const char *linkname, const char *zonename, void *statentry,
+    char unit, boolean_t parsable)
 {
 	total_stat_entry_t	*sentry = statentry;
 	total_stat_t		*link_stats = &sentry->tse_stats;
@@ -970,6 +973,7 @@
 
 	(void) snprintf(buf->t_linkname, sizeof (buf->t_linkname), "%s",
 	    linkname);
+	(void) snprintf(buf->t_zone, sizeof (buf->t_zone), "%s", zonename);
 
 	map_to_units(buf->t_ipackets, sizeof (buf->t_ipackets),
 	    link_stats->ts_ipackets, unit, parsable);
@@ -988,8 +992,8 @@
 }
 
 void *
-print_rx_generic_ring_stats(const char *linkname, void *statentry, char unit,
-    boolean_t parsable)
+print_rx_generic_ring_stats(const char *linkname, const char *zonename, 
+    void *statentry, char unit, boolean_t parsable)
 {
 	ring_stat_entry_t	*sentry = statentry;
 	ring_stat_t		*link_stats = &sentry->re_stats;
@@ -1022,8 +1026,8 @@
 }
 
 void *
-print_tx_generic_ring_stats(const char *linkname, void *statentry, char unit,
-    boolean_t parsable)
+print_tx_generic_ring_stats(const char *linkname, const char *zonename,
+    void *statentry, char unit, boolean_t parsable)
 {
 	ring_stat_entry_t	*sentry = statentry;
 	ring_stat_t		*link_stats = &sentry->re_stats;
@@ -1056,8 +1060,8 @@
 }
 
 void *
-print_rx_ring_stats(const char *linkname, void *statentry, char unit,
-    boolean_t parsable)
+print_rx_ring_stats(const char *linkname, const char *zonename, void *statentry,
+    char unit, boolean_t parsable)
 {
 	ring_stat_entry_t	*sentry = statentry;
 	ring_stat_t		*link_stats = &sentry->re_stats;
@@ -1090,8 +1094,8 @@
 }
 
 void *
-print_tx_ring_stats(const char *linkname, void *statentry, char unit,
-    boolean_t parsable)
+print_tx_ring_stats(const char *linkname, const char *zonename, void *statentry,
+    char unit, boolean_t parsable)
 {
 	ring_stat_entry_t	*sentry = statentry;
 	ring_stat_t		*link_stats = &sentry->re_stats;
@@ -1124,8 +1128,8 @@
 }
 
 void *
-print_rx_generic_lane_stats(const char *linkname, void *statentry, char unit,
-    boolean_t parsable)
+print_rx_generic_lane_stats(const char *linkname, const char *zonename,
+    void *statentry, char unit, boolean_t parsable)
 {
 	rx_lane_stat_entry_t	*sentry = statentry;
 	rx_lane_stat_t		*link_stats = &sentry->rle_stats;
@@ -1172,8 +1176,8 @@
 }
 
 void *
-print_tx_generic_lane_stats(const char *linkname, void *statentry, char unit,
-    boolean_t parsable)
+print_tx_generic_lane_stats(const char *linkname, const char *zonename,
+    void *statentry, char unit, boolean_t parsable)
 {
 	tx_lane_stat_entry_t	*sentry = statentry;
 	tx_lane_stat_t		*link_stats = &sentry->tle_stats;
@@ -1217,8 +1221,8 @@
 }
 
 void *
-print_rx_lane_stats(const char *linkname, void *statentry, char unit,
-    boolean_t parsable)
+print_rx_lane_stats(const char *linkname, const char *zonename, void *statentry,
+    char unit, boolean_t parsable)
 {
 	rx_lane_stat_entry_t	*sentry = statentry;
 	rx_lane_stat_t		*link_stats = &sentry->rle_stats;
@@ -1283,9 +1287,8 @@
 }
 
 void *
-print_tx_lane_stats(const char *linkname, void *statentry, char unit,
-    boolean_t parsable)
-{
+print_tx_lane_stats(const char *linkname, const char *zonename, void *statentry,
+    char unit, boolean_t parsable) {
 	tx_lane_stat_entry_t	*sentry = statentry;
 	tx_lane_stat_t		*link_stats = &sentry->tle_stats;
 	tx_lane_fields_buf_t	*buf = NULL;
@@ -1338,8 +1341,8 @@
 }
 
 void *
-print_fanout_stats(const char *linkname, void *statentry, char unit,
-    boolean_t parsable)
+print_fanout_stats(const char *linkname, const char *zonename, void *statentry,
+    char unit, boolean_t parsable)
 {
 	fanout_stat_entry_t		*sentry = statentry;
 	fanout_stat_t			*link_stats = &sentry->fe_stats;
@@ -1392,8 +1395,8 @@
 }
 
 void *
-print_aggr_port_stats(const char *linkname, void *statentry, char unit,
-    boolean_t parsable)
+print_aggr_port_stats(const char *linkname, const char *zonename,
+    void *statentry, char unit, boolean_t parsable)
 {
 	aggr_port_stat_entry_t	*sentry = statentry;
 	aggr_port_stat_t	*link_stats = &sentry->ape_stats;
@@ -1470,7 +1473,8 @@
 
 void
 walk_dlstat_stats(show_state_t *state, const char *linkname,
-    dladm_stat_type_t stattype, dladm_stat_chain_t *diff_stat)
+    const char *zonename, dladm_stat_type_t stattype,
+    dladm_stat_chain_t *diff_stat)
 {
 	dladm_stat_chain_t  *curr;
 
@@ -1480,7 +1484,8 @@
 
 		/* Format the raw numbers for printing */
 		fields_buf = state->ls_stats2str[stattype](linkname,
-		    curr->dc_statentry, state->ls_unit, state->ls_parsable);
+		    zonename, curr->dc_statentry, state->ls_unit,
+		    state->ls_parsable);
 		/* Print the stats */
 		if (fields_buf != NULL)
 			ofmt_print(state->ls_ofmt, fields_buf);
@@ -1495,6 +1500,9 @@
 	int 			i;
 	dladm_stat_chain_t	*diff_stat;
 	char			linkname[DLPI_LINKNAME_MAX];
+	char			zonename[DLADM_PROP_VAL_MAX + 1];
+	char			*valptr[1];
+	uint_t			valcnt = 1;
 
 	if (dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, linkname,
 	    DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) {
@@ -1501,6 +1509,11 @@
 		goto done;
 	}
 
+	valptr[0] = zonename;
+	if (dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_CURRENT, "zone",
+	    (char **)valptr, &valcnt) != 0)
+		zonename[0] = '\0';
+
 	for (i = 0; i < DLADM_STAT_NUM_STATS; i++) {
 		if (state->ls_stattype[i]) {
 			/*
@@ -1508,7 +1521,8 @@
 			 * Stats are returned as chain of raw numbers
 			 */
 			diff_stat = query_link_stats(handle, linkid, arg, i);
-			walk_dlstat_stats(state, linkname, i, diff_stat);
+			walk_dlstat_stats(state, linkname, zonename, i,
+			    diff_stat);
 			dladm_link_stat_free(diff_stat);
 		}
 	}
@@ -1628,7 +1642,7 @@
 	char			*o_fields_str = NULL;
 
 	char			*total_stat_fields =
-	    "link,ipkts,rbytes,opkts,obytes";
+	    "link,ipkts,rbytes,opkts,obytes,zone";
 	char			*rx_total_stat_fields =
 	    "link,ipkts,rbytes,intrs,polls,ch<10,ch10-50,ch>50";
 	char			*tx_total_stat_fields =
--- old/usr/src/cmd/flowadm/flowadm.c	Wed Jan 21 15:51:17 2015
+++ new/usr/src/cmd/flowadm/flowadm.c	Wed Jan 21 15:51:17 2015
@@ -21,6 +21,7 @@
 /*
  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ * Copyright 2011 Joyent, Inc.  All rights reserved.
  */
 
 #include <stdio.h>
@@ -233,9 +234,9 @@
 	(void) fprintf(stderr, gettext("usage: flowadm <subcommand>"
 	    " <args>...\n"
 	    "    add-flow       [-t] -l <link> -a <attr>=<value>[,...]\n"
-	    "\t\t   [-p <prop>=<value>,...] <flow>\n"
-	    "    remove-flow    [-t] {-l <link> | <flow>}\n"
-	    "    show-flow      [-p] [-l <link>] "
+	    "\t\t   [-p <prop>=<value>,...] [-z zonename] <flow>\n"
+	    "    remove-flow    [-t] [-z zonename] {-l <link> | <flow>}\n"
+	    "    show-flow      [-p] [-l <link>] [-z zonename] "
 	    "[<flow>]\n\n"
 	    "    set-flowprop   [-t] -p <prop>=<value>[,...] <flow>\n"
 	    "    reset-flowprop [-t] [-p <prop>,...] <flow>\n"
@@ -333,11 +334,12 @@
 	dladm_arg_list_t	*proplist = NULL;
 	dladm_arg_list_t	*attrlist = NULL;
 	dladm_status_t		status;
+	char			*zonename = NULL;
 
 	bzero(propstr, DLADM_STRSIZE);
 	bzero(attrstr, DLADM_STRSIZE);
 
-	while ((option = getopt_long(argc, argv, "tR:l:a:p:",
+	while ((option = getopt_long(argc, argv, "tR:l:a:p:z:",
 	    prop_longopts, NULL)) != -1) {
 		switch (option) {
 		case 't':
@@ -351,9 +353,6 @@
 			    MAXLINKNAMELEN) >= MAXLINKNAMELEN) {
 				die("link name too long");
 			}
-			if (dladm_name2info(handle, devname, &linkid, NULL,
-			    NULL, NULL) != DLADM_STATUS_OK)
-				die("invalid link '%s'", devname);
 			l_arg = B_TRUE;
 			break;
 		case 'a':
@@ -368,6 +367,9 @@
 			    DLADM_STRSIZE)
 				die("property list too long '%s'", propstr);
 			break;
+		case 'z':
+			zonename = optarg;
+			break;
 		default:
 			die_opterr(optopt, option);
 		}
@@ -376,6 +378,10 @@
 		die("link is required");
 	}
 
+	if (dladm_zname2info(handle, zonename, devname, &linkid, NULL,
+	    NULL, NULL) != DLADM_STATUS_OK)
+		die("invalid link '%s'", devname);
+
 	opterr = 0;
 	index = optind;
 
@@ -414,11 +420,12 @@
 	boolean_t		l_arg = B_FALSE;
 	remove_flow_state_t	state;
 	dladm_status_t		status;
+	char			*zonename = NULL;
 
 	bzero(&state, sizeof (state));
 
 	opterr = 0;
-	while ((option = getopt_long(argc, argv, ":tR:l:",
+	while ((option = getopt_long(argc, argv, ":tR:l:z:",
 	    longopts, NULL)) != -1) {
 		switch (option) {
 		case 't':
@@ -432,12 +439,11 @@
 			    MAXLINKNAMELEN) >= MAXLINKNAMELEN) {
 				die("link name too long");
 			}
-			if (dladm_name2info(handle, linkname, &linkid, NULL,
-			    NULL, NULL) != DLADM_STATUS_OK) {
-				die("invalid link '%s'", linkname);
-			}
 			l_arg = B_TRUE;
 			break;
+		case 'z':
+			zonename = optarg;
+			break;
 		default:
 			die_opterr(optopt, option);
 			break;
@@ -458,6 +464,12 @@
 		/* if link is specified then flow name should not be there */
 		if (optind == argc-1)
 			usage();
+
+		if (dladm_zname2info(handle, zonename, linkname, &linkid, NULL,
+		    NULL, NULL) != DLADM_STATUS_OK) {
+			die("invalid link '%s'", linkname);
+		}
+
 		/* walk the link to find flows and remove them */
 		state.fs_tempop = t_arg;
 		state.fs_altroot = altroot;
@@ -597,11 +609,12 @@
 	ofmt_handle_t		ofmt;
 	ofmt_status_t		oferr;
 	uint_t			ofmtflags = 0;
+	char			*zonename = NULL;
 
 	bzero(&state, sizeof (state));
 
 	opterr = 0;
-	while ((option = getopt_long(argc, argv, ":pPl:o:",
+	while ((option = getopt_long(argc, argv, ":pPl:o:z:",
 	    longopts, NULL)) != -1) {
 		switch (option) {
 		case 'p':
@@ -622,11 +635,11 @@
 			if (strlcpy(linkname, optarg, MAXLINKNAMELEN)
 			    >= MAXLINKNAMELEN)
 				die("link name too long\n");
-			if (dladm_name2info(handle, linkname, &linkid, NULL,
-			    NULL, NULL) != DLADM_STATUS_OK)
-				die("invalid link '%s'", linkname);
 			l_arg = B_TRUE;
 			break;
+		case 'z':
+			zonename = optarg;
+			break;
 		default:
 			die_opterr(optopt, option);
 			break;
@@ -633,6 +646,12 @@
 		}
 	}
 
+	if (l_arg) {
+		if (dladm_zname2info(handle, zonename, linkname, &linkid, NULL,
+		    NULL, NULL) != DLADM_STATUS_OK)
+			die("invalid link '%s'", linkname);
+	}
+
 	/* get flow name (optional last argument */
 	if (optind == (argc-1)) {
 		if (strlcpy(flowname, argv[optind], MAXFLOWNAMELEN)
--- old/usr/src/cmd/flowstat/flowstat.c	Wed Jan 21 15:51:17 2015
+++ new/usr/src/cmd/flowstat/flowstat.c	Wed Jan 21 15:51:17 2015
@@ -21,6 +21,7 @@
 /*
  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ * Copyright 2011 Joyent, Inc.  All rights reserved.
  */
 
 #include <stdio.h>
@@ -190,9 +191,9 @@
 static dladm_handle_t handle = NULL;
 
 const char *usage_ermsg = "flowstat [-r | -t] [-i interval] "
-	    "[-l link] [flow]\n"
+	    "[-l link] [-z zonename] [flow]\n"
 	    "       flowstat [-S] [-A] [-i interval] [-p] [ -o field[,...]]\n"
-	    "                [-u R|K|M|G|T|P] [-l link] [flow]\n"
+	    "                [-u R|K|M|G|T|P] [-l link] [-z zonename] [flow]\n"
 	    "       flowstat -h [-a] [-d] [-F format]"
 	    " [-s <DD/MM/YYYY,HH:MM:SS>]\n"
 	    "                [-e <DD/MM/YYYY,HH:MM:SS>] -f <logfile> "
@@ -556,6 +557,7 @@
 	show_flow_state_t	state;
 	char			*fields_str = NULL;
 	char			*o_fields_str = NULL;
+	char			*zonename = NULL;
 
 	char			*total_stat_fields =
 	    "flow,ipkts,rbytes,ierrs,opkts,obytes,oerrs";
@@ -582,10 +584,11 @@
 	if ((status = dladm_open(&handle)) != DLADM_STATUS_OK)
 		die_dlerr(status, "could not open /dev/dld");
 
+	linkname[0] = '\0';
 	bzero(&state, sizeof (state));
 
 	opterr = 0;
-	while ((option = getopt_long(argc, argv, ":rtApSi:o:u:l:h",
+	while ((option = getopt_long(argc, argv, ":rtApSi:o:u:l:hz:",
 	    NULL, NULL)) != -1) {
 		switch (option) {
 		case 'r':
@@ -642,9 +645,6 @@
 			if (strlcpy(linkname, optarg, MAXLINKNAMELEN)
 			    >= MAXLINKNAMELEN)
 				die("link name too long\n");
-			if (dladm_name2info(handle, linkname, &linkid, NULL,
-			    NULL, NULL) != DLADM_STATUS_OK)
-				die("invalid link '%s'", linkname);
 			break;
 		case 'h':
 			if (r_arg || t_arg || p_arg || o_arg || u_arg ||
@@ -655,6 +655,9 @@
 			do_show_history(argc, argv);
 			return (0);
 			break;
+		case 'z':
+			zonename = optarg;
+			break;
 		default:
 			die_opterr(optopt, option, usage_ermsg);
 			break;
@@ -683,6 +686,12 @@
 		die("the option -A is not compatible with "
 		    "-r, -t, -p, -o, -u, -i");
 
+	if (linkname[0] != '\0') {
+		if (dladm_zname2info(handle, zonename, linkname, &linkid, NULL,
+		    NULL, NULL) != DLADM_STATUS_OK)
+			die("invalid link '%s'", linkname);
+	}
+
 	/* get flow name (optional last argument) */
 	if (optind == (argc-1)) {
 		if (strlcpy(flowname, argv[optind], MAXFLOWNAMELEN)
--- old/usr/src/cmd/ibd_upgrade/ibd_delete_link.c	Wed Jan 21 15:51:17 2015
+++ new/usr/src/cmd/ibd_upgrade/ibd_delete_link.c	Wed Jan 21 15:51:17 2015
@@ -21,6 +21,7 @@
 
 /*
  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, Joyent Inc. All rights reserved.
  */
 
 #include <stdio.h>
@@ -86,6 +87,7 @@
 
 	getlinkid.ld_cmd = DLMGMT_CMD_GETLINKID;
 	(void) strlcpy(getlinkid.ld_link, link, MAXLINKNAMELEN);
+	getlinkid.ld_zoneid = -1;
 
 	if ((status = ibd_dladm_door_call(dlh, &getlinkid, sizeof (getlinkid),
 	    &retval, sizeof (retval))) != DLADM_STATUS_OK) {
--- old/usr/src/cmd/zoneadm/zoneadm.c	Wed Jan 21 15:51:17 2015
+++ new/usr/src/cmd/zoneadm/zoneadm.c	Wed Jan 21 15:51:17 2015
@@ -2611,7 +2611,6 @@
 	dladm_handle_t dh;
 	dladm_status_t status;
 	datalink_id_t linkid;
-	char errmsg[DLADM_STRSIZE];
 
 	in_alt_root = zonecfg_in_alt_root();
 	if (in_alt_root)
@@ -2633,6 +2632,7 @@
 		struct lifreq lifr;
 		sa_family_t af = AF_UNSPEC;
 		char dl_owner_zname[ZONENAME_MAX];
+		char errmsg[DLADM_STRSIZE];
 		zoneid_t dl_owner_zid;
 		zoneid_t target_zid;
 		int res;
--- old/usr/src/cmd/zoneadmd/vplat.c	Wed Jan 21 15:51:18 2015
+++ new/usr/src/cmd/zoneadmd/vplat.c	Wed Jan 21 15:51:18 2015
@@ -3124,20 +3124,17 @@
 			/* datalink does not belong to the GZ */
 			continue;
 		}
-		if (dlstatus != DLADM_STATUS_OK) {
+		if (dlstatus != DLADM_STATUS_OK)
 			zerror(zlogp, B_FALSE,
+			    "clear 'protection' link property: %s",
 			    dladm_status2str(dlstatus, dlerr));
-			free(dllinks);
-			return (-1);
-		}
+
 		dlstatus = dladm_set_linkprop(dld_handle, *dllink,
 		    "allowed-ips", NULL, 0, DLADM_OPT_ACTIVE);
-		if (dlstatus != DLADM_STATUS_OK) {
+		if (dlstatus != DLADM_STATUS_OK)
 			zerror(zlogp, B_FALSE,
+			    "clear 'allowed-ips' link property: %s",
 			    dladm_status2str(dlstatus, dlerr));
-			free(dllinks);
-			return (-1);
-		}
 	}
 	free(dllinks);
 	return (0);
@@ -3144,28 +3141,6 @@
 }
 
 static int
-unconfigure_exclusive_network_interfaces(zlog_t *zlogp, zoneid_t zoneid)
-{
-	int dlnum = 0;
-
-	/*
-	 * The kernel shutdown callback for the dls module should have removed
-	 * all datalinks from this zone.  If any remain, then there's a
-	 * problem.
-	 */
-	if (zone_list_datalink(zoneid, &dlnum, NULL) != 0) {
-		zerror(zlogp, B_TRUE, "unable to list network interfaces");
-		return (-1);
-	}
-	if (dlnum != 0) {
-		zerror(zlogp, B_FALSE,
-		    "datalinks remain in zone after shutdown");
-		return (-1);
-	}
-	return (0);
-}
-
-static int
 tcp_abort_conn(zlog_t *zlogp, zoneid_t zoneid,
     const struct sockaddr_storage *local, const struct sockaddr_storage *remote)
 {
@@ -5158,16 +5133,12 @@
 		goto error;
 	}
 
-	if (remove_datalink_pool(zlogp, zoneid) != 0) {
+	if (remove_datalink_pool(zlogp, zoneid) != 0)
 		zerror(zlogp, B_FALSE, "unable clear datalink pool property");
-		goto error;
-	}
 
-	if (remove_datalink_protect(zlogp, zoneid) != 0) {
+	if (remove_datalink_protect(zlogp, zoneid) != 0)
 		zerror(zlogp, B_FALSE,
 		    "unable clear datalink protect property");
-		goto error;
-	}
 
 	/*
 	 * The datalinks assigned to the zone will be removed from the NGZ as
@@ -5239,12 +5210,6 @@
 			}
 			break;
 		case ZS_EXCLUSIVE:
-			if (unconfigure_exclusive_network_interfaces(zlogp,
-			    zoneid) != 0) {
-				zerror(zlogp, B_FALSE, "unable to unconfigure "
-				    "network interfaces in zone");
-				goto error;
-			}
 			status = dladm_zone_halt(dld_handle, zoneid);
 			if (status != DLADM_STATUS_OK) {
 				zerror(zlogp, B_FALSE, "unable to notify "
--- old/usr/src/cmd/zoneadmd/zoneadmd.c	Wed Jan 21 15:51:18 2015
+++ new/usr/src/cmd/zoneadmd/zoneadmd.c	Wed Jan 21 15:51:18 2015
@@ -771,8 +771,13 @@
 
 	while (fgets(inbuf, 1024, file) != NULL) {
 		if (retstr == NULL) {
-			if (zlogp != &logsys)
+			if (zlogp != &logsys) {
+				int last = strlen(inbuf) - 1;
+
+				if (inbuf[last] == '\n')
+					inbuf[last] = '\0';
 				zerror(zlogp, B_FALSE, "%s", inbuf);
+			}
 		} else {
 			char *p;
 
@@ -1477,6 +1482,7 @@
 			rval = 0;
 			break;
 		case Z_BOOT:
+		case Z_FORCEBOOT:
 			(void) strlcpy(boot_args, zargp->bootbuf,
 			    sizeof (boot_args));
 			eventstream_write(Z_EVT_ZONE_BOOTING);
@@ -1502,6 +1508,7 @@
 		case Z_REBOOT:
 		case Z_NOTE_UNINSTALLING:
 		case Z_MOUNT:
+		case Z_FORCEMOUNT:
 		case Z_UNMOUNT:
 			if (kernelcall)	/* Invalid; can't happen */
 				abort();
@@ -1549,6 +1556,7 @@
 				eventstream_write(Z_EVT_ZONE_HALTED);
 			break;
 		case Z_BOOT:
+		case Z_FORCEBOOT:
 			/*
 			 * We could have two clients racing to boot this
 			 * zone; the second client loses, but his request
@@ -1596,6 +1604,7 @@
 			break;
 		case Z_NOTE_UNINSTALLING:
 		case Z_MOUNT:
+		case Z_FORCEMOUNT:
 		case Z_UNMOUNT:
 			zerror(zlogp, B_FALSE, "%s operation is invalid "
 			    "for zones in state '%s'", z_cmd_name(cmd),
--- old/usr/src/lib/libdladm/common/libdladm.h	Wed Jan 21 15:51:18 2015
+++ new/usr/src/lib/libdladm/common/libdladm.h	Wed Jan 21 15:51:18 2015
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, Joyent, Inc. All rights reserved.
  */
 
 #ifndef _LIBDLADM_H
@@ -71,6 +72,10 @@
  *  - DLADM_OPT_BOOT:
  *    Bypass check functions during boot (used by pool property since pools
  *    can come up after link properties are set)
+ *
+ *  - DLADM_OPT_TRANSIENT:
+ *    Indicates that the link assigned to a zone is transient and will be
+ *    removed when the zone shuts down.
  */
 #define	DLADM_OPT_ACTIVE	0x00000001
 #define	DLADM_OPT_PERSIST	0x00000002
@@ -81,6 +86,7 @@
 #define	DLADM_OPT_VLAN		0x00000040
 #define	DLADM_OPT_NOREFRESH	0x00000080
 #define	DLADM_OPT_BOOT		0x00000100
+#define	DLADM_OPT_TRANSIENT	0x00000200
 
 #define	DLADM_WALK_TERMINATE	0
 #define	DLADM_WALK_CONTINUE	-1
--- old/usr/src/lib/libdladm/common/libdllink.c	Wed Jan 21 15:51:18 2015
+++ new/usr/src/lib/libdladm/common/libdllink.c	Wed Jan 21 15:51:18 2015
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, Joyent Inc. All rights reserved.
  */
 
 #include <sys/types.h>
@@ -386,10 +387,14 @@
 /*
  * Case 1: rename an existing link1 to a link2 that does not exist.
  * Result: <linkid1, link2>
+ * The zonename parameter is used to allow us to create a VNIC in the global
+ * zone which is assigned to a non-global zone.  Since there is a race condition
+ * in the create process if two VNICs have the same name, we need to rename it
+ * after it has been assigned to the zone.
  */
 static dladm_status_t
 i_dladm_rename_link_c1(dladm_handle_t handle, datalink_id_t linkid1,
-    const char *link1, const char *link2, uint32_t flags)
+    const char *link1, const char *link2, uint32_t flags, const char *zonename)
 {
 	dld_ioc_rename_t	dir;
 	dladm_status_t		status = DLADM_STATUS_OK;
@@ -402,6 +407,10 @@
 		dir.dir_linkid1 = linkid1;
 		dir.dir_linkid2 = DATALINK_INVALID_LINKID;
 		(void) strlcpy(dir.dir_link, link2, MAXLINKNAMELEN);
+		if (zonename != NULL)
+			dir.dir_zoneinit = B_TRUE;
+		else
+			dir.dir_zoneinit = B_FALSE;
 
 		if (ioctl(dladm_dld_fd(handle), DLDIOC_RENAME, &dir) < 0) {
 			status = dladm_errno2status(errno);
@@ -412,6 +421,7 @@
 	status = dladm_remap_datalink_id(handle, linkid1, link2);
 	if (status != DLADM_STATUS_OK && (flags & DLADM_OPT_ACTIVE)) {
 		(void) strlcpy(dir.dir_link, link1, MAXLINKNAMELEN);
+		dir.dir_zoneinit = B_FALSE;
 		(void) ioctl(dladm_dld_fd(handle), DLDIOC_RENAME, &dir);
 	}
 	return (status);
@@ -508,6 +518,7 @@
 	 */
 	dir.dir_linkid1 = linkid1;
 	dir.dir_linkid2 = linkid2;
+	dir.dir_zoneinit = B_FALSE;
 	if (ioctl(dladm_dld_fd(handle), DLDIOC_RENAME, &dir) < 0)
 		status = dladm_errno2status(errno);
 
@@ -617,7 +628,8 @@
 }
 
 dladm_status_t
-dladm_rename_link(dladm_handle_t handle, const char *link1, const char *link2)
+dladm_rename_link(dladm_handle_t handle, const char *zonename,
+    const char *link1, const char *link2)
 {
 	datalink_id_t		linkid1 = DATALINK_INVALID_LINKID;
 	datalink_id_t		linkid2 = DATALINK_INVALID_LINKID;
@@ -627,11 +639,11 @@
 	boolean_t		remphy2 = B_FALSE;
 	dladm_status_t  	status;
 
-	(void) dladm_name2info(handle, link1, &linkid1, &flags1, &class1,
-	    &media1);
-	if ((dladm_name2info(handle, link2, &linkid2, &flags2, &class2,
-	    &media2) == DLADM_STATUS_OK) && (class2 == DATALINK_CLASS_PHYS) &&
-	    (flags2 == DLADM_OPT_PERSIST)) {
+	(void) dladm_zname2info(handle, zonename, link1, &linkid1, &flags1,
+	    &class1, &media1);
+	if ((dladm_zname2info(handle, zonename, link2, &linkid2, &flags2,
+	    &class2, &media2) == DLADM_STATUS_OK) &&
+	    (class2 == DATALINK_CLASS_PHYS) && (flags2 == DLADM_OPT_PERSIST)) {
 		/*
 		 * see whether link2 is a removed physical link.
 		 */
@@ -645,7 +657,7 @@
 			 * does not exist.
 			 */
 			status = i_dladm_rename_link_c1(handle, linkid1, link1,
-			    link2, flags1);
+			    link2, flags1, zonename);
 		} else if (remphy2) {
 			/*
 			 * case 2: rename an available link to a REMOVED
--- old/usr/src/lib/libdladm/common/libdllink.h	Wed Jan 21 15:51:18 2015
+++ new/usr/src/lib/libdladm/common/libdllink.h	Wed Jan 21 15:51:18 2015
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, Joyent Inc. All rights reserved.
  */
 
 #ifndef _LIBDLLINK_H
@@ -121,7 +122,7 @@
 			    dladm_attr_t *);
 
 extern dladm_status_t	dladm_rename_link(dladm_handle_t, const char *,
-			    const char *);
+			    const char *, const char *);
 
 extern dladm_status_t	dladm_set_linkprop(dladm_handle_t, datalink_id_t,
 			    const char *, char **, uint_t, uint_t);
@@ -170,6 +171,9 @@
 extern dladm_status_t	dladm_name2info(dladm_handle_t, const char *,
 			    datalink_id_t *, uint32_t *, datalink_class_t *,
 			    uint32_t *);
+extern dladm_status_t	dladm_zname2info(dladm_handle_t, const char *,
+			    const char *, datalink_id_t *, uint32_t *,
+			    datalink_class_t *, uint32_t *);
 extern dladm_status_t	dladm_datalink_id2info(dladm_handle_t, datalink_id_t,
 			    uint32_t *, datalink_class_t *, uint32_t *, char *,
 			    size_t);
--- old/usr/src/lib/libdladm/common/libdlmgmt.c	Wed Jan 21 15:51:18 2015
+++ new/usr/src/lib/libdladm/common/libdlmgmt.c	Wed Jan 21 15:51:18 2015
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, Joyent Inc. All rights reserved.
  */
 
 #include <door.h>
@@ -528,12 +529,24 @@
 }
 
 /*
- * Get the link ID that is associated with the given name.
+ * Get the link ID that is associated with the given name in the current zone.
  */
 dladm_status_t
 dladm_name2info(dladm_handle_t handle, const char *link, datalink_id_t *linkidp,
     uint32_t *flagp, datalink_class_t *classp, uint32_t *mediap)
 {
+	return (dladm_zname2info(handle, NULL, link, linkidp, flagp, classp,
+	   mediap));
+}
+
+/*
+ * Get the link ID that is associated with the given zone/name pair.
+ */
+dladm_status_t
+dladm_zname2info(dladm_handle_t handle, const char *zonename, const char *link,
+    datalink_id_t *linkidp, uint32_t *flagp, datalink_class_t *classp,
+    uint32_t *mediap)
+{
 	dlmgmt_door_getlinkid_t		getlinkid;
 	dlmgmt_getlinkid_retval_t	retval;
 	datalink_id_t			linkid;
@@ -542,6 +555,10 @@
 
 	getlinkid.ld_cmd = DLMGMT_CMD_GETLINKID;
 	(void) strlcpy(getlinkid.ld_link, link, MAXLINKNAMELEN);
+	if (zonename != NULL)
+		getlinkid.ld_zoneid = getzoneidbyname(zonename);
+	else
+		getlinkid.ld_zoneid = -1;
 
 	if ((status = dladm_door_call(handle, &getlinkid, sizeof (getlinkid),
 	    &retval, &sz)) != DLADM_STATUS_OK) {
--- old/usr/src/lib/libdladm/common/libdlvnic.c	Wed Jan 21 15:51:18 2015
+++ new/usr/src/lib/libdladm/common/libdlvnic.c	Wed Jan 21 15:51:18 2015
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, Joyent Inc. All rights reserved.
  */
 
 #include <stdio.h>
@@ -539,27 +540,35 @@
 	vnic_created = B_TRUE;
 
 	/* Save vnic configuration and its properties */
-	if (!(flags & DLADM_OPT_PERSIST))
-		goto done;
+	if (flags & DLADM_OPT_PERSIST) {
+		status = dladm_vnic_persist_conf(handle, name, &attr, class);
+		if (status == DLADM_STATUS_OK)
+			conf_set = B_TRUE;
+	}
 
-	status = dladm_vnic_persist_conf(handle, name, &attr, class);
-	if (status != DLADM_STATUS_OK)
-		goto done;
-	conf_set = B_TRUE;
+done:
+	if (status == DLADM_STATUS_OK && proplist != NULL) {
+    		uint32_t flg;
 
-	if (proplist != NULL) {
+		flg = (flags & DLADM_OPT_PERSIST) ?
+		    DLADM_OPT_PERSIST : DLADM_OPT_ACTIVE;
+
 		for (i = 0; i < proplist->al_count; i++) {
 			dladm_arg_info_t	*aip = &proplist->al_info[i];
 
+			if (strcmp(aip->ai_name, "zone") == 0 &&
+			    flags & DLADM_OPT_TRANSIENT)
+				flg |= DLADM_OPT_TRANSIENT;
+			else
+				flg &= ~DLADM_OPT_TRANSIENT;
+
 			status = dladm_set_linkprop(handle, vnic_id,
-			    aip->ai_name, aip->ai_val, aip->ai_count,
-			    DLADM_OPT_PERSIST);
+			    aip->ai_name, aip->ai_val, aip->ai_count, flg);
 			if (status != DLADM_STATUS_OK)
 				break;
 		}
 	}
 
-done:
 	if (status != DLADM_STATUS_OK) {
 		if (conf_set)
 			(void) dladm_remove_conf(handle, vnic_id);
--- old/usr/src/lib/libdladm/common/linkprop.c	Wed Jan 21 15:51:18 2015
+++ new/usr/src/lib/libdladm/common/linkprop.c	Wed Jan 21 15:51:19 2015
@@ -1529,6 +1529,9 @@
 	if (zid_new == zid_old)
 		return (DLADM_STATUS_OK);
 
+	if (flags & DLADM_OPT_TRANSIENT)
+		dzp->diz_transient = B_TRUE;
+
 	if ((status = set_public_prop(handle, pdp, linkid, vdp, val_cnt,
 	    flags, media)) != DLADM_STATUS_OK)
 		return (status);
--- old/usr/src/lib/libdladm/common/mapfile-vers	Wed Jan 21 15:51:19 2015
+++ new/usr/src/lib/libdladm/common/mapfile-vers	Wed Jan 21 15:51:19 2015
@@ -20,6 +20,7 @@
 #
 #
 # Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, Joyent Inc. All rights reserved.
 #
 
 #
@@ -134,6 +135,7 @@
 	dladm_remap_datalink_id;
 	dladm_up_datalink_id;
 	dladm_name2info;
+	dladm_zname2info;
 	dladm_datalink_id2info;
 	dladm_walk_datalink_id;
 	dladm_create_conf;
--- old/usr/src/man/man1m/dladm.1m	Wed Jan 21 15:51:19 2015
+++ new/usr/src/man/man1m/dladm.1m	Wed Jan 21 15:51:19 2015
@@ -16,7 +16,7 @@
 .LP
 .nf
 \fBdladm show-link\fR [\fB-P\fR] [\fB-s\fR [\fB-i\fR \fIinterval\fR]] [[\fB-p\fR] \fB-o\fR \fIfield\fR[,...]] [\fIlink\fR]
-\fBdladm rename-link\fR [\fB-R\fR \fIroot-dir\fR] \fIlink\fR \fInew-link\fR
+\fBdladm rename-link\fR [\fB-R\fR \fIroot-dir\fR] [\fB-z\fR \fIzonename\fR] \fIlink\fR \fInew-link\fR
 .fi
 
 .LP
@@ -99,9 +99,11 @@
 
 .LP
 .nf
-\fBdladm set-linkprop\fR [\fB-t\fR] [\fB-R\fR \fIroot-dir\fR] \fB-p\fR \fIprop\fR=\fIvalue\fR[,...] \fIlink\fR
-\fBdladm reset-linkprop\fR [\fB-t\fR] [\fB-R\fR \fIroot-dir\fR] [\fB-p\fR \fIprop\fR[,...]] \fIlink\fR
-\fBdladm show-linkprop\fR [\fB-P\fR] [[\fB-c\fR] \fB-o\fR \fIfield\fR[,...]] [\fB-p\fR \fIprop\fR[,...]] [\fIlink\fR]
+\fBdladm set-linkprop\fR [\fB-t\fR] [\fB-R\fR \fIroot-dir\fR] [\fB-z\fR \fIzonename\fR] \fB-p\fR \fIprop\fR=\fIvalue\fR[,...]
+     \fIlink\fR
+\fBdladm reset-linkprop\fR [\fB-t\fR] [\fB-R\fR \fIroot-dir\fR] [\fB-z\fR \fIzonename\fR] [\fB-p\fR \fIprop\fR[,...]] \fIlink\fR
+\fBdladm show-linkprop\fR [\fB-P\fR] [\fB-z\fR \fIzonename\fR] [[\fB-c\fR] \fB-o\fR \fIfield\fR[,...]]
+     [\fB-p\fR \fIprop\fR[,...]] [\fIlink\fR]
 .fi
 
 .LP
@@ -116,9 +118,9 @@
 \fBdladm create-vnic\fR [\fB-t\fR] \fB-l\fR \fIlink\fR [\fB-R\fR \fIroot-dir\fR] [\fB-m\fR \fIvalue\fR | auto |
      {factory \fB-n\fR \fIslot-identifier\fR]} | {random [\fB-r\fR \fIprefix\fR]}]
      [\fB-v\fR \fIvlan-id\fR] [\fB-p\fR \fIprop\fR=\fIvalue\fR[,...]] \fIvnic-link\fR
-\fBdladm delete-vnic\fR [\fB-t\fR] [\fB-R\fR \fIroot-dir\fR] \fIvnic-link\fR
+\fBdladm delete-vnic\fR [\fB-t\fR] [\fB-R\fR \fIroot-dir\fR] [\fB-z\fR \fIzonename\fR] \fIvnic-link\fR
 \fBdladm show-vnic\fR [\fB-pP\fR] [\fB-s\fR [\fB-i\fR \fIinterval\fR]] [\fB-o\fR \fIfield\fR[,...]]
-     [\fB-l\fR \fIlink\fR] [\fIvnic-link\fR]
+     [\fB-l\fR \fIlink\fR] [\fB-z\fR \fIzonename\fR] [\fIvnic-link\fR]
 .fi
 
 .LP
@@ -568,8 +570,7 @@
 .sp
 .ne 2
 .na
-\fB\fBdladm rename-link\fR [\fB-R\fR \fIroot-dir\fR] \fIlink\fR
-\fInew-link\fR\fR
+\fB\fBdladm rename-link\fR [\fB-R\fR \fIroot-dir\fR] [\fB-z\fR \fIzonename\fR] \fIlink\fR \fInew-link\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -587,8 +588,18 @@
 See "Options," above.
 .RE
 
+.sp
+.ne 2
+.na
+\fB\fB-z\fR \fIzonename\fR
+.ad
+.sp .6
+.RS 4n
+A link assigned to a zone can only be renamed while the zone is in the ready state.
 .RE
 
+.RE
+
 .sp
 .ne 2
 .na
@@ -3192,8 +3203,7 @@
 .sp
 .ne 2
 .na
-\fB\fBdladm set-linkprop\fR [\fB-t\fR] [\fB-R\fR \fIroot-dir\fR] \fB-p\fR
-\fIprop\fR=\fIvalue\fR[,...] \fIlink\fR\fR
+\fB\fBdladm set-linkprop\fR [\fB-t\fR] [\fB-R\fR \fIroot-dir\fR] [\fB-z\fR \fIzonename\fR] \fB-p\fR \fIprop\fR=\fIvalue\fR[,...] \fIlink\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -3225,6 +3235,16 @@
 .sp
 .ne 2
 .na
+\fB\fB-z\fR \fIzonenme\fR
+.ad
+.sp .6
+.RS 4n
+Operate on a link that has been delegated to the specified zone.
+.RE
+
+.sp
+.ne 2
+.na
 \fB\fB-p\fR \fIprop\fR=\fIvalue\fR[,...], \fB--prop\fR
 \fIprop\fR=\fIvalue\fR[,...]\fR
 .ad
@@ -3244,8 +3264,7 @@
 .sp
 .ne 2
 .na
-\fB\fBdladm reset-linkprop\fR [\fB-t\fR] [\fB-R\fR \fIroot-dir\fR] [\fB-p\fR
-\fIprop\fR,...] \fIlink\fR\fR
+\fB\fBdladm reset-linkprop\fR [\fB-t\fR] [\fB-R\fR \fIroot-dir\fR] [\fB-z\fR \fIzonename\fR] [\fB-p\fR \fIprop\fR,...] \fIlink\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -3277,6 +3296,16 @@
 .sp
 .ne 2
 .na
+\fB\fB-z\fR \fIzonenme\fR
+.ad
+.sp .6
+.RS 4n
+Operate on a link that has been delegated to the specified zone.
+.RE
+
+.sp
+.ne 2
+.na
 \fB\fB-p\fR \fIprop, ...\fR, \fB--prop\fR=\fIprop, ...\fR\fR
 .ad
 .sp .6
@@ -3291,8 +3320,7 @@
 .sp
 .ne 2
 .na
-\fB\fBdladm show-linkprop\fR [\fB-P\fR] [[\fB-c\fR] \fB-o\fR
-\fIfield\fR[,...]][\fB-p\fR \fIprop\fR[,...]] [\fIlink\fR]\fR
+\fB\fBdladm show-linkprop\fR [\fB-P\fR] [\fB-z\fR \fIzonename\fR] [[\fB-c\fR] \fB-o\fR \fIfield\fR[,...]][\fB-p\fR \fIprop\fR[,...]] [\fIlink\fR]\fR
 .ad
 .sp .6
 .RS 4n
@@ -3410,6 +3438,16 @@
 .sp
 .ne 2
 .na
+\fB\fB-z\fR \fIzonenme\fR
+.ad
+.sp .6
+.RS 4n
+Operate on a link that has been delegated to the specified zone.
+.RE
+
+.sp
+.ne 2
+.na
 \fB\fB-p\fR \fIprop, ...\fR, \fB--prop\fR=\fIprop, ...\fR\fR
 .ad
 .sp .6
@@ -3727,8 +3765,7 @@
 .sp
 .ne 2
 .na
-\fB\fBdladm delete-vnic\fR [\fB-t\fR] [\fB-R\fR \fIroot-dir\fR]
-\fIvnic-link\fR\fR
+\fB\fBdladm delete-vnic\fR [\fB-t\fR] [\fB-R\fR \fIroot-dir\fR] [\fB-z\fR \fIzonename\fR] \fIvnic-link\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -3754,13 +3791,22 @@
 See "Options," above.
 .RE
 
+.sp
+.ne 2
+.na
+\fB\fB-z\fR \fIzonenme\fR
+.ad
+.sp .6
+.RS 4n
+Operate on a link that has been delegated to the specified zone.
 .RE
 
+.RE
+
 .sp
 .ne 2
 .na
-\fB\fBdladm show-vnic\fR [\fB-pP\fR] [\fB-s\fR [\fB-i\fR \fIinterval\fR]]
-[\fB-o\fR \fIfield\fR[,...]] [\fB-l\fR \fIlink\fR] [\fIvnic-link\fR]\fR
+\fB\fBdladm show-vnic\fR [\fB-pP\fR] [\fB-s\fR [\fB-i\fR \fIinterval\fR]] [\fB-o\fR \fIfield\fR[,...]] [\fB-l\fR \fIlink\fR] [\fB-z\fR \fIzonename\fR] [\fIvnic-link\fR]\fR
 .ad
 .sp .6
 .RS 4n
@@ -3903,6 +3949,16 @@
 Display information for all VNICs on the named link.
 .RE
 
+.sp
+.ne 2
+.na
+\fB\fB-z\fR \fIzonenme\fR
+.ad
+.sp .6
+.RS 4n
+Operate on a link that has been delegated to the specified zone.
+.RE
+
 .RE
 
 .sp
--- old/usr/src/man/man1m/flowadm.1m	Wed Jan 21 15:51:19 2015
+++ new/usr/src/man/man1m/flowadm.1m	Wed Jan 21 15:51:19 2015
@@ -1,5 +1,6 @@
 '\" te
 .\" Copyright (c) 2009, Sun Microsystems, Inc. All Rights Reserved
+.\" Copyright (c) 2011, Joyent, Inc. All Rights Reserved
 .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License").  You may not use this file except in compliance with the License.
 .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing.  See the License for the specific language governing permissions and limitations under the License.
 .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE.  If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
@@ -11,14 +12,14 @@
 .LP
 .nf
 \fBflowadm show-flow\fR [\fB-pP\fR] [\fB-S\fR] [\fB-s\fR [\fB-i\fR \fIinterval\fR]] [\fB-l\fR \fIlink\fR]
-     [\fB-o\fR \fIfield\fR[,...]] [\fIflow\fR]
+     [\fB-o\fR \fIfield\fR[,...]] [\fB-z\fR \fIzonename\fR] [\fIflow\fR]
 .fi
 
 .LP
 .nf
-\fBflowadm add-flow\fR [\fB-t\fR] [\fB-R\fR \fIroot-dir\fR] \fB-l\fR \fIlink\fR \fB-a\fR \fIattr\fR=\fIvalue\fR[,...]
-     \fB-p\fR \fIprop\fR=\fIvalue\fR[,...] \fIflow\fR
-\fBflowadm remove-flow\fR [\fB-t\fR] [\fB-R\fR \fIroot-dir\fR] {\fB-l\fR \fIlink\fR | \fIflow\fR}
+\fBflowadm add-flow\fR [\fB-t\fR] [\fB-R\fR \fIroot-dir\fR] [\fB-z\fR \fIzonename\fR] \fB-l\fR \fIlink\fR
+     \fB-a\fR \fIattr\fR=\fIvalue\fR[,...] \fB-p\fR \fIprop\fR=\fIvalue\fR[,...] \fIflow\fR
+\fBflowadm remove-flow\fR [\fB-t\fR] [\fB-R\fR \fIroot-dir\fR] [\fB-z\fR \fIzonename\fR] {\fB-l\fR \fIlink\fR | \fIflow\fR}
 .fi
 
 .LP
@@ -77,8 +78,7 @@
 .sp
 .ne 2
 .na
-\fB\fBflowadm show-flow\fR [\fB-pP\fR] [\fB-s\fR [\fB-i\fR \fIinterval\fR]]
-[\fB-o\fR \fIfield\fR[,...]] [\fB-l\fR \fIlink\fR] [\fIflow\fR]\fR
+\fB\fBflowadm show-flow\fR [\fB-pP\fR] [\fB-s\fR [\fB-i\fR \fIinterval\fR]] [\fB-o\fR \fIfield\fR[,...]] [\fB-l\fR \fIlink\fR] [\fB-z\fR \fIzonename\fR] [\fIflow\fR]\fR
 .ad
 .sp .6
 .RS 4n
@@ -223,14 +223,22 @@
 named flow.
 .RE
 
+.sp
+.ne 2
+.na
+\fB\fB-z\fR \fIzonename\fR
+.ad
+.sp .6
+.RS 4n
+Operate on a link that has been delegated to the specified zone.
 .RE
 
+.RE
+
 .sp
 .ne 2
 .na
-\fB\fBflowadm add-flow\fR [\fB-t\fR] [\fB-R\fR \fIroot-dir\fR] \fB-l\fR
-\fIlink\fR \fB-a\fR \fIattr\fR=\fIvalue\fR[,...] \fB-p\fR
-\fIprop\fR=\fIvalue\fR[,...] \fIflow\fR\fR
+\fB\fBflowadm add-flow\fR [\fB-t\fR] [\fB-R\fR \fIroot-dir\fR] [\fB-z\fR \fIzonename\fR] \fB-l\fR \fIlink\fR \fB-a\fR \fIattr\fR=\fIvalue\fR[,...] \fB-p\fR \fIprop\fR=\fIvalue\fR[,...] \fIflow\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -268,6 +276,16 @@
 .sp
 .ne 2
 .na
+\fB\fB-z\fR \fIzonename\fR
+.ad
+.sp .6
+.RS 4n
+Operate on a link that has been delegated to the specified zone.
+.RE
+
+.sp
+.ne 2
+.na
 \fB\fB-l\fR \fIlink\fR, \fB--link\fR=\fIlink\fR\fR
 .ad
 .sp .6
@@ -300,8 +318,7 @@
 .sp
 .ne 2
 .na
-\fB\fBflowadm remove-flow\fR [\fB-t\fR] [\fB-R\fR \fIroot-dir\fR] \fB-l\fR
-{\fIlink\fR | \fIflow\fR}\fR
+\fB\fBflowadm remove-flow\fR [\fB-t\fR] [\fB-R\fR \fIroot-dir\fR] [\fB-z\fR \fIzonename\fR] \fB-l\fR {\fIlink\fR | \fIflow\fR}\fR
 .ad
 .sp .6
 .RS 4n
@@ -328,6 +345,16 @@
 persistent removal.
 .RE
 
+.sp
+.ne 2
+.na
+\fB\fB-z\fR \fIzonename\fR
+.ad
+.sp .6
+.RS 4n
+Operate on a link that has been delegated to the specified zone.
+.RE
+
 .sp
 .ne 2
 .na
--- old/usr/src/uts/common/io/dld/dld_drv.c	Wed Jan 21 15:51:20 2015
+++ new/usr/src/uts/common/io/dld/dld_drv.c	Wed Jan 21 15:51:20 2015
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, Joyent Inc. All rights reserved.
  */
 
 /*
@@ -701,7 +702,8 @@
 				err = EACCES;
 				goto done;
 			}
-			err = dls_devnet_setzid(dlh, dzp->diz_zid);
+			err = dls_devnet_setzid(dlh, dzp->diz_zid,
+			    dzp->diz_transient);
 		} else {
 			kprop->pr_perm_flags = MAC_PROP_PERM_RW;
 			(*(zoneid_t *)kprop->pr_val) = dls_devnet_getzid(dlh);
@@ -865,7 +867,7 @@
 		return (err);
 
 	if ((err = dls_devnet_rename(dir->dir_linkid1, dir->dir_linkid2,
-	    dir->dir_link)) != 0)
+	    dir->dir_link, dir->dir_zoneinit)) != 0)
 		return (err);
 
 	if (dir->dir_linkid2 == DATALINK_INVALID_LINKID)
--- old/usr/src/uts/common/io/dls/dls_mgmt.c	Wed Jan 21 15:51:20 2015
+++ new/usr/src/uts/common/io/dls/dls_mgmt.c	Wed Jan 21 15:51:20 2015
@@ -21,6 +21,7 @@
 /*
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ * Copyright (c) 2013 Joyent, Inc.  All rights reserved.
  */
 
 /*
@@ -105,12 +106,13 @@
 	zoneid_t	dd_zid;		/* current zone */
 	boolean_t	dd_prop_loaded;
 	taskqid_t	dd_prop_taskid;
+	boolean_t	dd_transient;	/* link goes away when zone does */
 } dls_devnet_t;
 
 static int i_dls_devnet_create_iptun(const char *, const char *,
     datalink_id_t *);
 static int i_dls_devnet_destroy_iptun(datalink_id_t);
-static int i_dls_devnet_setzid(dls_devnet_t *, zoneid_t, boolean_t);
+static int i_dls_devnet_setzid(dls_devnet_t *, zoneid_t, boolean_t, boolean_t);
 static int dls_devnet_unset(const char *, datalink_id_t *, boolean_t);
 
 /*ARGSUSED*/
@@ -145,7 +147,12 @@
 	dls_devnet_t *ddp;
 
 	if (dls_devnet_hold_tmp(linkid, &ddp) == 0) {
-		(void) dls_devnet_setzid(ddp, GLOBAL_ZONEID);
+		/*
+		 * Don't bother moving transient links back to the global zone
+		 * since we will simply delete them in dls_devnet_unset.
+		 */
+		if (!ddp->dd_transient)
+			(void) dls_devnet_setzid(ddp, GLOBAL_ZONEID, B_FALSE);
 		dls_devnet_rele_tmp(ddp);
 	}
 	return (0);
@@ -526,6 +533,7 @@
 
 	getlinkid.ld_cmd = DLMGMT_CMD_GETLINKID;
 	(void) strlcpy(getlinkid.ld_link, link, MAXLINKNAMELEN);
+	getlinkid.ld_zoneid = getzoneid();
 
 	if ((err = i_dls_mgmt_upcall(&getlinkid, sizeof (getlinkid), &retval,
 	    sizeof (retval))) == 0) {
@@ -740,12 +748,23 @@
  * Create the "link" kstats.
  */
 static void
-dls_devnet_stat_create(dls_devnet_t *ddp, zoneid_t zoneid)
+dls_devnet_stat_create(dls_devnet_t *ddp, zoneid_t zoneid, zoneid_t newzoneid)
 {
 	kstat_t	*ksp;
+	char	*nm;
+	char	kname[MAXLINKNAMELEN];
 
-	if (dls_stat_create("link", 0, ddp->dd_linkname, zoneid,
-	    dls_devnet_stat_update, ddp, &ksp) == 0) {
+	if (zoneid != newzoneid) {
+		ASSERT(zoneid == GLOBAL_ZONEID);
+		(void) snprintf(kname, sizeof (kname), "z%d_%s", newzoneid,
+		    ddp->dd_linkname);
+		nm = kname;
+	} else {
+		nm = ddp->dd_linkname;
+	}
+
+	if (dls_stat_create("link", 0, nm, zoneid,
+	    dls_devnet_stat_update, ddp, &ksp, newzoneid) == 0) {
 		ASSERT(ksp != NULL);
 		if (zoneid == ddp->dd_owner_zid) {
 			ASSERT(ddp->dd_ksp == NULL);
@@ -765,12 +784,12 @@
 {
 	if (zoneid == ddp->dd_owner_zid) {
 		if (ddp->dd_ksp != NULL) {
-			kstat_delete(ddp->dd_ksp);
+			dls_stat_delete(ddp->dd_ksp);
 			ddp->dd_ksp = NULL;
 		}
 	} else {
 		if (ddp->dd_zone_ksp != NULL) {
-			kstat_delete(ddp->dd_zone_ksp);
+			dls_stat_delete(ddp->dd_zone_ksp);
 			ddp->dd_zone_ksp = NULL;
 		}
 	}
@@ -781,15 +800,25 @@
  * and create the new set using the new name.
  */
 static void
-dls_devnet_stat_rename(dls_devnet_t *ddp)
+dls_devnet_stat_rename(dls_devnet_t *ddp, boolean_t zoneinit)
 {
 	if (ddp->dd_ksp != NULL) {
-		kstat_delete(ddp->dd_ksp);
+		dls_stat_delete(ddp->dd_ksp);
 		ddp->dd_ksp = NULL;
 	}
-	/* We can't rename a link while it's assigned to a non-global zone. */
+	if (zoneinit && ddp->dd_zone_ksp != NULL) {
+		dls_stat_delete(ddp->dd_zone_ksp);
+		ddp->dd_zone_ksp = NULL;
+	}
+	/*
+	 * We can't rename a link while it's assigned to a non-global zone
+	 * unless we're first initializing the zone while readying it.
+	 */
 	ASSERT(ddp->dd_zone_ksp == NULL);
-	dls_devnet_stat_create(ddp, ddp->dd_owner_zid);
+	dls_devnet_stat_create(ddp, ddp->dd_owner_zid,
+	    (zoneinit ? ddp->dd_zid : ddp->dd_owner_zid));
+	if (zoneinit)
+		dls_devnet_stat_create(ddp, ddp->dd_zid, ddp->dd_zid);
 }
 
 /*
@@ -878,7 +907,8 @@
 	rw_exit(&i_dls_devnet_lock);
 	if (err == 0) {
 		if (zoneid != GLOBAL_ZONEID &&
-		    (err = i_dls_devnet_setzid(ddp, zoneid, B_FALSE)) != 0)
+		    (err = i_dls_devnet_setzid(ddp, zoneid, B_FALSE,
+		    B_FALSE)) != 0)
 			(void) dls_devnet_unset(macname, &linkid, B_TRUE);
 		/*
 		 * The kstat subsystem holds its own locks (rather perimeter)
@@ -887,7 +917,7 @@
 		 * lock hierarchy is kstat locks -> i_dls_devnet_lock.
 		 */
 		if (stat_create)
-			dls_devnet_stat_create(ddp, zoneid);
+			dls_devnet_stat_create(ddp, zoneid, zoneid);
 		if (ddpp != NULL)
 			*ddpp = ddp;
 	}
@@ -924,9 +954,53 @@
 	ASSERT(ddp->dd_ref != 0);
 	if ((ddp->dd_ref != 1) || (!wait &&
 	    (ddp->dd_tref != 0 || ddp->dd_prop_taskid != NULL))) {
-		mutex_exit(&ddp->dd_mutex);
-		rw_exit(&i_dls_devnet_lock);
-		return (EBUSY);
+		int zstatus = 0;
+
+		/*
+		 * There are a couple of alternatives that might be going on
+		 * here; a) the zone is shutting down and it has a transient
+		 * link assigned, in which case we want to clean it up instead
+		 * of moving it back to the global zone, or b) its possible
+		 * that we're trying to clean up an orphaned vnic that was
+		 * delegated to a zone and which wasn't cleaned up properly
+		 * when the zone went away.  Check for either of these cases
+		 * before we simply return EBUSY.
+		 *
+		 * zstatus indicates which situation we are dealing with:
+		 *	 0 - means return EBUSY
+		 *	 1 - means case (a), cleanup transient link
+		 *	-1 - means case (b), orphained VNIC
+		 */
+		if (ddp->dd_ref > 1 && ddp->dd_zid != GLOBAL_ZONEID) {
+			zone_t	*zp;
+
+			if ((zp = zone_find_by_id(ddp->dd_zid)) == NULL) {
+				zstatus = -1;
+			} else {
+				if (ddp->dd_transient) {
+					zone_status_t s = zone_status_get(zp);
+
+					if (s >= ZONE_IS_SHUTTING_DOWN)
+						zstatus = 1;
+				}
+				zone_rele(zp);
+			}
+		}
+
+		if (zstatus == 0) {
+			mutex_exit(&ddp->dd_mutex);
+			rw_exit(&i_dls_devnet_lock);
+			return (EBUSY);
+		}
+
+		/*
+		 * We want to delete the link, reset ref to 1;
+		 */
+		if (zstatus == -1)
+			/* Log a warning, but continue in this case */
+			cmn_err(CE_WARN, "clear orphaned datalink: %s\n",
+			    ddp->dd_linkname);
+		ddp->dd_ref = 1;
 	}
 
 	ddp->dd_flags |= DD_CONDEMNED;
@@ -933,8 +1007,25 @@
 	ddp->dd_ref--;
 	*id = ddp->dd_linkid;
 
-	if (ddp->dd_zid != GLOBAL_ZONEID)
-		(void) i_dls_devnet_setzid(ddp, GLOBAL_ZONEID, B_FALSE);
+	if (ddp->dd_zid != GLOBAL_ZONEID) {
+		/*
+		 * We need to release the dd_mutex before we try and destroy the
+		 * stat. When we destroy it, we'll need to grab the lock for the
+		 * kstat but if there's a concurrent reader of the kstat, we'll
+		 * be blocked on it. This will lead to deadlock because these
+		 * kstats employ a ks_update function (dls_devnet_stat_update)
+		 * which needs the dd_mutex that we currently hold.
+		 *
+		 * Because we've already flagged the dls_devnet_t as
+		 * DD_CONDEMNED and we still have a write lock on
+		 * i_dls_devnet_lock, we should be able to release the dd_mutex.
+		 */
+		mutex_exit(&ddp->dd_mutex);
+		dls_devnet_stat_destroy(ddp, ddp->dd_zid);
+		mutex_enter(&ddp->dd_mutex);
+		(void) i_dls_devnet_setzid(ddp, GLOBAL_ZONEID, B_FALSE,
+		    B_FALSE);
+	}
 
 	/*
 	 * Remove this dls_devnet_t from the hash table.
@@ -960,9 +1051,16 @@
 		ASSERT(ddp->dd_tref == 0 && ddp->dd_prop_taskid == NULL);
 	}
 
-	if (ddp->dd_linkid != DATALINK_INVALID_LINKID)
+	if (ddp->dd_linkid != DATALINK_INVALID_LINKID) {
+		/*
+		 * See the earlier call in this function for an explanation.
+		 */
+		mutex_exit(&ddp->dd_mutex);
 		dls_devnet_stat_destroy(ddp, ddp->dd_owner_zid);
+		mutex_enter(&ddp->dd_mutex);
+	}
 
+
 	ddp->dd_prop_loaded = B_FALSE;
 	ddp->dd_linkid = DATALINK_INVALID_LINKID;
 	ddp->dd_flags = 0;
@@ -1261,9 +1359,15 @@
  *
  *    This case does not change the <link name, linkid> mapping, so the link's
  *    kstats need to be updated with using name associated the given id2.
+ *
+ * The zonename parameter is used to allow us to create a VNIC in the global
+ * zone which is assigned to a non-global zone.  Since there is a race condition
+ * in the create process if two VNICs have the same name, we need to rename it
+ * after it has been assigned to the zone.
  */
 int
-dls_devnet_rename(datalink_id_t id1, datalink_id_t id2, const char *link)
+dls_devnet_rename(datalink_id_t id1, datalink_id_t id2, const char *link,
+    boolean_t zoneinit)
 {
 	dls_dev_handle_t	ddh = NULL;
 	int			err = 0;
@@ -1313,13 +1417,16 @@
 	 * is currently accessing the link kstats, or if the link is on-loan
 	 * to a non-global zone. Then set the DD_KSTAT_CHANGING flag to
 	 * prevent any access to the kstats while we delete and recreate
-	 * kstats below.
+	 * kstats below.  However, we skip this check if we're renaming the
+	 * vnic as part of bringing it up for a zone.
 	 */
 	mutex_enter(&ddp->dd_mutex);
-	if (ddp->dd_ref > 1) {
-		mutex_exit(&ddp->dd_mutex);
-		err = EBUSY;
-		goto done;
+	if (!zoneinit) {
+		if (ddp->dd_ref > 1) {
+			mutex_exit(&ddp->dd_mutex);
+			err = EBUSY;
+			goto done;
+		}
 	}
 
 	ddp->dd_flags |= DD_KSTAT_CHANGING;
@@ -1333,7 +1440,15 @@
 		/* rename mac client name and its flow if exists */
 		if ((err = mac_open(ddp->dd_mac, &mh)) != 0)
 			goto done;
-		(void) mac_rename_primary(mh, link);
+		if (zoneinit) {
+			char tname[MAXLINKNAMELEN];
+
+			(void) snprintf(tname, sizeof (tname), "z%d_%s",
+			    ddp->dd_zid, link);
+			(void) mac_rename_primary(mh, tname);
+		} else {
+			(void) mac_rename_primary(mh, link);
+		}
 		mac_close(mh);
 		goto done;
 	}
@@ -1406,7 +1521,7 @@
 	 */
 	rw_exit(&i_dls_devnet_lock);
 	if (err == 0)
-		dls_devnet_stat_rename(ddp);
+		dls_devnet_stat_rename(ddp, zoneinit);
 
 	if (clear_dd_flag) {
 		mutex_enter(&ddp->dd_mutex);
@@ -1421,7 +1536,8 @@
 }
 
 static int
-i_dls_devnet_setzid(dls_devnet_t *ddp, zoneid_t new_zoneid, boolean_t setprop)
+i_dls_devnet_setzid(dls_devnet_t *ddp, zoneid_t new_zoneid, boolean_t setprop,
+    boolean_t transient)
 {
 	int			err;
 	mac_perim_handle_t	mph;
@@ -1454,6 +1570,7 @@
 	}
 	if ((err = dls_link_setzid(ddp->dd_mac, new_zoneid)) == 0) {
 		ddp->dd_zid = new_zoneid;
+		ddp->dd_transient = transient;
 		devnet_need_rebuild = B_TRUE;
 	}
 
@@ -1468,7 +1585,7 @@
 }
 
 int
-dls_devnet_setzid(dls_dl_handle_t ddh, zoneid_t new_zid)
+dls_devnet_setzid(dls_dl_handle_t ddh, zoneid_t new_zid, boolean_t transient)
 {
 	dls_devnet_t	*ddp;
 	int		err;
@@ -1490,7 +1607,7 @@
 		refheld = B_TRUE;
 	}
 
-	if ((err = i_dls_devnet_setzid(ddh, new_zid, B_TRUE)) != 0) {
+	if ((err = i_dls_devnet_setzid(ddh, new_zid, B_TRUE, transient)) != 0) {
 		if (refheld)
 			dls_devnet_rele(ddp);
 		return (err);
@@ -1507,7 +1624,7 @@
 	if (old_zid != GLOBAL_ZONEID)
 		dls_devnet_stat_destroy(ddh, old_zid);
 	if (new_zid != GLOBAL_ZONEID)
-		dls_devnet_stat_create(ddh, new_zid);
+		dls_devnet_stat_create(ddh, new_zid, new_zid);
 
 	return (0);
 }
--- old/usr/src/uts/common/io/dls/dls_stat.c	Wed Jan 21 15:51:20 2015
+++ new/usr/src/uts/common/io/dls/dls_stat.c	Wed Jan 21 15:51:20 2015
@@ -21,6 +21,7 @@
 /*
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ * Copyright 2011 Joyent, Inc.  All rights reserved.
  */
 
 /*
@@ -30,31 +31,34 @@
 #include <sys/dld_impl.h>
 #include <sys/mac_ether.h>
 
-static mac_stat_info_t	i_dls_si[] = {
-	{ MAC_STAT_IFSPEED, "ifspeed", KSTAT_DATA_UINT64, 0 },
-	{ MAC_STAT_MULTIRCV, "multircv", KSTAT_DATA_UINT32, 0 },
-	{ MAC_STAT_BRDCSTRCV, "brdcstrcv", KSTAT_DATA_UINT32, 0 },
-	{ MAC_STAT_MULTIXMT, "multixmt", KSTAT_DATA_UINT32, 0 },
-	{ MAC_STAT_BRDCSTXMT, "brdcstxmt", KSTAT_DATA_UINT32, 0 },
-	{ MAC_STAT_NORCVBUF, "norcvbuf", KSTAT_DATA_UINT32, 0 },
-	{ MAC_STAT_IERRORS, "ierrors", KSTAT_DATA_UINT32, 0 },
-	{ MAC_STAT_NOXMTBUF, "noxmtbuf", KSTAT_DATA_UINT32, 0 },
-	{ MAC_STAT_OERRORS, "oerrors", KSTAT_DATA_UINT32, 0 },
-	{ MAC_STAT_COLLISIONS, "collisions", KSTAT_DATA_UINT32, 0 },
-	{ MAC_STAT_RBYTES, "rbytes", KSTAT_DATA_UINT32, 0 },
-	{ MAC_STAT_IPACKETS, "ipackets", KSTAT_DATA_UINT32, 0 },
-	{ MAC_STAT_OBYTES, "obytes", KSTAT_DATA_UINT32, 0 },
-	{ MAC_STAT_OPACKETS, "opackets", KSTAT_DATA_UINT32, 0 },
-	{ MAC_STAT_RBYTES, "rbytes64", KSTAT_DATA_UINT64, 0 },
-	{ MAC_STAT_IPACKETS, "ipackets64", KSTAT_DATA_UINT64, 0 },
-	{ MAC_STAT_OBYTES, "obytes64", KSTAT_DATA_UINT64, 0 },
-	{ MAC_STAT_OPACKETS, "opackets64", KSTAT_DATA_UINT64, 0 },
-	{ MAC_STAT_LINK_STATE, "link_state", KSTAT_DATA_UINT32,
-	    (uint64_t)LINK_STATE_UNKNOWN}
-};
+/*
+ * structure for link kstats
+ */
+typedef struct {
+	kstat_named_t	dk_ifspeed;
+	kstat_named_t	dk_multircv;
+	kstat_named_t	dk_brdcstrcv;
+	kstat_named_t	dk_multixmt;
+	kstat_named_t	dk_brdcstxmt;
+	kstat_named_t	dk_norcvbuf;
+	kstat_named_t	dk_ierrors;
+	kstat_named_t	dk_noxmtbuf;
+	kstat_named_t	dk_oerrors;
+	kstat_named_t	dk_collisions;
+	kstat_named_t	dk_rbytes;
+	kstat_named_t	dk_ipackets;
+	kstat_named_t	dk_obytes;
+	kstat_named_t	dk_opackets;
+	kstat_named_t	dk_rbytes64;
+	kstat_named_t	dk_ipackets64;
+	kstat_named_t	dk_obytes64;
+	kstat_named_t	dk_opackets64;
+	kstat_named_t	dk_link_state;
+	kstat_named_t	dk_link_duplex;
+	kstat_named_t	dk_unknowns;
+	kstat_named_t	dk_zonename;
+} dls_kstat_t;
 
-#define	STAT_INFO_COUNT	(sizeof (i_dls_si) / sizeof (i_dls_si[0]))
-
 /*
  * Exported functions.
  */
@@ -61,43 +65,55 @@
 int
 dls_stat_update(kstat_t *ksp, dls_link_t *dlp, int rw)
 {
-	kstat_named_t	*knp;
-	uint_t		i;
-	uint64_t	val;
+	dls_kstat_t *dkp = ksp->ks_data;
 
 	if (rw != KSTAT_READ)
 		return (EACCES);
 
-	knp = (kstat_named_t *)ksp->ks_data;
-	for (i = 0; i < STAT_INFO_COUNT; i++) {
-		val = mac_stat_get(dlp->dl_mh, i_dls_si[i].msi_stat);
+	dkp->dk_ifspeed.value.ui64 = mac_stat_get(dlp->dl_mh, MAC_STAT_IFSPEED);
+	dkp->dk_multircv.value.ui32 = mac_stat_get(dlp->dl_mh,
+	    MAC_STAT_MULTIRCV);
+	dkp->dk_brdcstrcv.value.ui32 = mac_stat_get(dlp->dl_mh,
+	    MAC_STAT_BRDCSTRCV);
+	dkp->dk_multixmt.value.ui32 = mac_stat_get(dlp->dl_mh,
+	    MAC_STAT_MULTIXMT);
+	dkp->dk_brdcstxmt.value.ui32 = mac_stat_get(dlp->dl_mh,
+	    MAC_STAT_BRDCSTXMT);
+	dkp->dk_norcvbuf.value.ui32 = mac_stat_get(dlp->dl_mh,
+	    MAC_STAT_NORCVBUF);
+	dkp->dk_ierrors.value.ui32 = mac_stat_get(dlp->dl_mh, MAC_STAT_IERRORS);
+	dkp->dk_noxmtbuf.value.ui32 = mac_stat_get(dlp->dl_mh,
+	    MAC_STAT_NOXMTBUF);
+	dkp->dk_oerrors.value.ui32 = mac_stat_get(dlp->dl_mh, MAC_STAT_OERRORS);
+	dkp->dk_collisions.value.ui32 = mac_stat_get(dlp->dl_mh,
+	    MAC_STAT_COLLISIONS);
+	dkp->dk_rbytes.value.ui32 = mac_stat_get(dlp->dl_mh, MAC_STAT_RBYTES);
+	dkp->dk_ipackets.value.ui32 = mac_stat_get(dlp->dl_mh,
+	    MAC_STAT_IPACKETS);
+	dkp->dk_obytes.value.ui32 = mac_stat_get(dlp->dl_mh, MAC_STAT_OBYTES);
+	dkp->dk_opackets.value.ui32 = mac_stat_get(dlp->dl_mh,
+	    MAC_STAT_OPACKETS);
+	dkp->dk_rbytes64.value.ui64 = mac_stat_get(dlp->dl_mh, MAC_STAT_RBYTES);
+	dkp->dk_ipackets64.value.ui64 = mac_stat_get(dlp->dl_mh,
+	    MAC_STAT_IPACKETS);
+	dkp->dk_obytes64.value.ui64 = mac_stat_get(dlp->dl_mh, MAC_STAT_OBYTES);
+	dkp->dk_opackets64.value.ui64 = mac_stat_get(dlp->dl_mh,
+	    MAC_STAT_OPACKETS);
+	dkp->dk_link_state.value.ui32 = mac_stat_get(dlp->dl_mh,
+	    MAC_STAT_LINK_STATE);
 
-		switch (i_dls_si[i].msi_type) {
-		case KSTAT_DATA_UINT64:
-			knp->value.ui64 = val;
-			break;
-		case KSTAT_DATA_UINT32:
-			knp->value.ui32 = (uint32_t)val;
-			break;
-		default:
-			ASSERT(B_FALSE);
-		}
-
-		knp++;
-	}
-
 	/*
 	 * Ethernet specific kstat "link_duplex"
 	 */
 	if (dlp->dl_mip->mi_nativemedia != DL_ETHER) {
-		knp->value.ui32 = LINK_DUPLEX_UNKNOWN;
+		dkp->dk_link_duplex.value.ui32 = LINK_DUPLEX_UNKNOWN;
 	} else {
-		val = mac_stat_get(dlp->dl_mh, ETHER_STAT_LINK_DUPLEX);
-		knp->value.ui32 = (uint32_t)val;
+		dkp->dk_link_duplex.value.ui32 =
+		    (uint32_t)mac_stat_get(dlp->dl_mh, ETHER_STAT_LINK_DUPLEX);
 	}
-	knp++;
-	knp->value.ui32 = dlp->dl_unknowns;
 
+	dkp->dk_unknowns.value.ui32 = dlp->dl_unknowns;
+
 	return (0);
 }
 
@@ -104,30 +120,66 @@
 int
 dls_stat_create(const char *module, int instance, const char *name,
     zoneid_t zoneid, int (*update)(struct kstat *, int), void *private,
-    kstat_t **kspp)
+    kstat_t **kspp, zoneid_t newzoneid)
 {
 	kstat_t		*ksp;
-	kstat_named_t	*knp;
-	uint_t		i;
+	zone_t		*zone;
+	dls_kstat_t	*dkp;
 
 	if ((ksp = kstat_create_zone(module, instance, name, "net",
-	    KSTAT_TYPE_NAMED, STAT_INFO_COUNT + 2, 0, zoneid)) == NULL) {
+	    KSTAT_TYPE_NAMED, sizeof (dls_kstat_t) / sizeof (kstat_named_t),
+	    KSTAT_FLAG_VIRTUAL, zoneid)) == NULL) {
 		return (EINVAL);
 	}
 
 	ksp->ks_update = update;
 	ksp->ks_private = private;
+	dkp = ksp->ks_data = kmem_zalloc(sizeof (dls_kstat_t), KM_SLEEP);
+	if ((zone = zone_find_by_id(newzoneid)) != NULL) {
+		ksp->ks_data_size += strlen(zone->zone_name) + 1;
+	}
 
-	knp = (kstat_named_t *)ksp->ks_data;
-	for (i = 0; i < STAT_INFO_COUNT; i++) {
-		kstat_named_init(knp, i_dls_si[i].msi_name,
-		    i_dls_si[i].msi_type);
-		knp++;
+	kstat_named_init(&dkp->dk_ifspeed, "ifspeed", KSTAT_DATA_UINT64);
+	kstat_named_init(&dkp->dk_multircv, "multircv", KSTAT_DATA_UINT32);
+	kstat_named_init(&dkp->dk_brdcstrcv, "brdcstrcv", KSTAT_DATA_UINT32);
+	kstat_named_init(&dkp->dk_multixmt, "multixmt", KSTAT_DATA_UINT32);
+	kstat_named_init(&dkp->dk_brdcstxmt, "brdcstxmt", KSTAT_DATA_UINT32);
+	kstat_named_init(&dkp->dk_norcvbuf, "norcvbuf", KSTAT_DATA_UINT32);
+	kstat_named_init(&dkp->dk_ierrors, "ierrors", KSTAT_DATA_UINT32);
+	kstat_named_init(&dkp->dk_noxmtbuf, "noxmtbuf", KSTAT_DATA_UINT32);
+	kstat_named_init(&dkp->dk_oerrors, "oerrors", KSTAT_DATA_UINT32);
+	kstat_named_init(&dkp->dk_collisions, "collisions", KSTAT_DATA_UINT32);
+	kstat_named_init(&dkp->dk_rbytes, "rbytes", KSTAT_DATA_UINT32);
+	kstat_named_init(&dkp->dk_ipackets, "ipackets", KSTAT_DATA_UINT32);
+	kstat_named_init(&dkp->dk_obytes, "obytes", KSTAT_DATA_UINT32);
+	kstat_named_init(&dkp->dk_opackets, "opackets", KSTAT_DATA_UINT32);
+	kstat_named_init(&dkp->dk_rbytes64, "rbytes64", KSTAT_DATA_UINT64);
+	kstat_named_init(&dkp->dk_ipackets64, "ipackets64", KSTAT_DATA_UINT64);
+	kstat_named_init(&dkp->dk_obytes64, "obytes64", KSTAT_DATA_UINT64);
+	kstat_named_init(&dkp->dk_opackets64, "opackets64", KSTAT_DATA_UINT64);
+	kstat_named_init(&dkp->dk_link_state, "link_state", KSTAT_DATA_UINT32);
+	kstat_named_init(&dkp->dk_link_duplex, "link_duplex",
+		    KSTAT_DATA_UINT32);
+	kstat_named_init(&dkp->dk_unknowns, "unknowns", KSTAT_DATA_UINT32);
+	kstat_named_init(&dkp->dk_zonename, "zonename", KSTAT_DATA_STRING);
+
+	if (zone != NULL) {
+		kstat_named_setstr(&dkp->dk_zonename, zone->zone_name);
+		zone_rele(zone);
 	}
 
-	kstat_named_init(knp++, "link_duplex", KSTAT_DATA_UINT32);
-	kstat_named_init(knp, "unknowns", KSTAT_DATA_UINT32);
 	kstat_install(ksp);
 	*kspp = ksp;
 	return (0);
+}
+
+void
+dls_stat_delete(kstat_t *ksp)
+{
+	void *data;
+	if (ksp != NULL) {
+		data = ksp->ks_data;
+		kstat_delete(ksp);
+		kmem_free(data, sizeof (dls_kstat_t));
+	}
 }
--- old/usr/src/uts/common/os/zone.c	Wed Jan 21 15:51:20 2015
+++ new/usr/src/uts/common/os/zone.c	Wed Jan 21 15:51:20 2015
@@ -2252,6 +2252,8 @@
 static void
 zone_free(zone_t *zone)
 {
+	zone_dl_t *zdl;
+
 	ASSERT(zone != global_zone);
 	ASSERT(zone->zone_ntasks == 0);
 	ASSERT(zone->zone_nlwps == 0);
@@ -2280,6 +2282,19 @@
 	list_destroy(&zone->zone_ref_list);
 	zone_free_zsd(zone);
 	zone_free_datasets(zone);
+
+	/*
+	 * While dlmgmtd should have removed all of these, it could have left
+	 * something behind or crashed. In which case it's not safe for us to
+	 * assume that the list is empty which list_destroy() will ASSERT. We
+	 * clean up for our userland comrades which may have crashed, or worse,
+	 * been disabled by SMF.
+	 */
+	while ((zdl = list_remove_head(&zone->zone_dl_list)) != NULL) {
+		if (zdl->zdl_net != NULL)
+			nvlist_free(zdl->zdl_net);
+		kmem_free(zdl, sizeof (zone_dl_t));
+	}
 	list_destroy(&zone->zone_dl_list);
 
 	if (zone->zone_rootvp != NULL)
--- old/usr/src/uts/common/sys/dld.h	Wed Jan 21 15:51:20 2015
+++ new/usr/src/uts/common/sys/dld.h	Wed Jan 21 15:51:20 2015
@@ -21,6 +21,7 @@
 /*
  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ * Copyright 2011 Joyent, Inc.  All rights reserved.
  */
 
 #ifndef	_SYS_DLD_H
@@ -191,6 +192,7 @@
 	datalink_id_t	dir_linkid1;
 	datalink_id_t	dir_linkid2;
 	char		dir_link[MAXLINKNAMELEN];
+	boolean_t	dir_zoneinit;
 } dld_ioc_rename_t;
 
 /*
@@ -203,6 +205,7 @@
 typedef struct dld_ioc_zid {
 	zoneid_t	diz_zid;
 	datalink_id_t	diz_linkid;
+	boolean_t	diz_transient;
 } dld_ioc_zid_t;
 
 /*
--- old/usr/src/uts/common/sys/dls.h	Wed Jan 21 15:51:20 2015
+++ new/usr/src/uts/common/sys/dls.h	Wed Jan 21 15:51:20 2015
@@ -21,6 +21,7 @@
 /*
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ * Copyright 2011 Joyent, Inc.  All rights reserved.
  */
 
 #ifndef	_SYS_DLS_H
@@ -110,7 +111,7 @@
 extern boolean_t	dls_devnet_rebuild();
 
 extern int		dls_devnet_rename(datalink_id_t, datalink_id_t,
-			    const char *);
+			    const char *, boolean_t);
 extern int		dls_devnet_create(mac_handle_t, datalink_id_t,
 			    zoneid_t);
 extern int		dls_devnet_destroy(mac_handle_t, datalink_id_t *,
@@ -127,7 +128,7 @@
 extern datalink_id_t	dls_devnet_linkid(dls_dl_handle_t);
 extern int		dls_devnet_dev2linkid(dev_t, datalink_id_t *);
 extern int		dls_devnet_phydev(datalink_id_t, dev_t *);
-extern int		dls_devnet_setzid(dls_dl_handle_t, zoneid_t);
+extern int		dls_devnet_setzid(dls_dl_handle_t, zoneid_t, boolean_t);
 extern zoneid_t		dls_devnet_getzid(dls_dl_handle_t);
 extern zoneid_t		dls_devnet_getownerzid(dls_dl_handle_t);
 extern boolean_t	dls_devnet_islinkvisible(datalink_id_t, zoneid_t);
--- old/usr/src/uts/common/sys/dls_impl.h	Wed Jan 21 15:51:21 2015
+++ new/usr/src/uts/common/sys/dls_impl.h	Wed Jan 21 15:51:21 2015
@@ -21,6 +21,7 @@
 /*
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ * Copyright 2011 Joyent, Inc.  All rights reserved.
  */
 
 #ifndef	_SYS_DLS_IMPL_H
@@ -96,7 +97,8 @@
 extern int		dls_stat_update(kstat_t *, dls_link_t *, int);
 extern int		dls_stat_create(const char *, int, const char *,
 			    zoneid_t, int (*)(struct kstat *, int), void *,
-			    kstat_t **);
+			    kstat_t **, zoneid_t);
+extern void	dls_stat_delete(kstat_t *);
 
 extern int		dls_devnet_open_by_dev(dev_t, dls_link_t **,
 			    dls_dl_handle_t *);
--- old/usr/src/uts/common/sys/dls_mgmt.h	Wed Jan 21 15:51:21 2015
+++ new/usr/src/uts/common/sys/dls_mgmt.h	Wed Jan 21 15:51:21 2015
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, Joyent Inc. All rights reserved.
  */
 
 #ifndef	_DLS_MGMT_H
@@ -165,6 +166,7 @@
 typedef struct dlmgmt_door_getlinkid {
 	int			ld_cmd;
 	char			ld_link[MAXLINKNAMELEN];
+	zoneid_t		ld_zoneid;
 } dlmgmt_door_getlinkid_t;
 
 typedef struct dlmgmt_door_getnext_s {
