--- old/usr/src/cmd/zoneadmd/vplat.c	Wed Oct  5 00:33:11 2016
+++ new/usr/src/cmd/zoneadmd/vplat.c	Wed Oct  5 00:33:11 2016
@@ -21,8 +21,8 @@
 
 /*
  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2016, Joyent Inc.
  * Copyright (c) 2015 by Delphix. All rights reserved.
+ * Copyright 2016, Joyent Inc.
  */
 
 /*
@@ -136,9 +136,6 @@
 #define	DFSTYPES	"/etc/dfs/fstypes"
 #define	MAXTNZLEN	2048
 
-/* Number of times to retry unmounting if it fails */
-#define	UMOUNT_RETRIES	30
-
 /* a reasonable estimate for the number of lwps per process */
 #define	LWPS_PER_PROCESS	10
 
@@ -180,7 +177,6 @@
 
 /* from zoneadmd */
 extern char query_hook[];
-extern char post_statechg_hook[];
 
 /*
  * For each "net" resource configured in zonecfg, we track a zone_addr_list_t
@@ -217,7 +213,7 @@
 	/*
 	 * Ask autofs to unmount all trigger nodes in the given zone.
 	 */
-	return (_autofssys(AUTOFS_UNMOUNTALL, (void *)((uintptr_t)zoneid)));
+	return (_autofssys(AUTOFS_UNMOUNTALL, (void *)zoneid));
 }
 
 static void
@@ -608,24 +604,6 @@
 }
 
 /*
- * Perform brand-specific cleanup if we are unable to unmount a FS.
- */
-static void
-brand_umount_cleanup(zlog_t *zlogp, char *path)
-{
-	char cmdbuf[2 * MAXPATHLEN];
-
-	if (post_statechg_hook[0] == '\0')
-		return;
-
-	if (snprintf(cmdbuf, sizeof (cmdbuf), "%s %d %d %s", post_statechg_hook,
-	    ZONE_STATE_DOWN, Z_UNMOUNT, path) > sizeof (cmdbuf))
-		return;
-
-	(void) do_subproc(zlogp, cmdbuf, NULL, B_FALSE);
-}
-
-/*
  * The general strategy for unmounting filesystems is as follows:
  *
  * - Remote filesystems may be dead, and attempting to contact them as
@@ -658,7 +636,6 @@
 unmount_filesystems(zlog_t *zlogp, zoneid_t zoneid, boolean_t unmount_cmd)
 {
 	int error = 0;
-	int fail = 0;
 	FILE *mnttab;
 	struct mnttab *mnts;
 	uint_t nmnt;
@@ -746,39 +723,18 @@
 				if (umount2(path, MS_FORCE) == 0) {
 					unmounted = B_TRUE;
 					stuck = B_FALSE;
-					fail = 0;
 				} else {
 					/*
-					 * We may hit a failure here if there
-					 * is an app in the GZ with an open
-					 * pipe into the zone (commonly into
-					 * the zone's /var/run).  This type
-					 * of app will notice the closed
-					 * connection and cleanup, but it may
-					 * take a while and we have no easy
-					 * way to notice that.  To deal with
-					 * this case, we will wait and retry
-					 * a few times before we give up.
+					 * The first failure indicates a
+					 * mount we won't be able to get
+					 * rid of automatically, so we
+					 * bail.
 					 */
-					fail++;
-					if (fail < (UMOUNT_RETRIES - 1)) {
-						zerror(zlogp, B_FALSE,
-						    "unable to unmount '%s', "
-						    "retrying in 2 seconds",
-						    path);
-						(void) sleep(2);
-					} else if (fail > UMOUNT_RETRIES) {
-						error++;
-						zerror(zlogp, B_FALSE,
-						    "unmount of '%s' failed",
-						    path);
-						free_mnttable(mnts, nmnt);
-						goto out;
-					} else {
-						/* Try the hook 2 times */
-						brand_umount_cleanup(zlogp,
-						    path);
-					}
+					error++;
+					zerror(zlogp, B_FALSE,
+					    "unable to unmount '%s'", path);
+					free_mnttable(mnts, nmnt);
+					goto out;
 				}
 			}
 			/*
@@ -1116,10 +1072,23 @@
 int
 vplat_get_iptype(zlog_t *zlogp, zone_iptype_t *iptypep)
 {
-	if (zonecfg_get_iptype(snap_hndl, iptypep) != Z_OK) {
+	zone_dochandle_t handle;
+
+	if ((handle = zonecfg_init_handle()) == NULL) {
+		zerror(zlogp, B_TRUE, "getting zone configuration handle");
+		return (-1);
+	}
+	if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) {
+		zerror(zlogp, B_FALSE, "invalid configuration");
+		zonecfg_fini_handle(handle);
+		return (-1);
+	}
+	if (zonecfg_get_iptype(handle, iptypep) != Z_OK) {
 		zerror(zlogp, B_FALSE, "invalid ip-type configuration");
+		zonecfg_fini_handle(handle);
 		return (-1);
 	}
+	zonecfg_fini_handle(handle);
 	return (0);
 }
 
@@ -1132,6 +1101,7 @@
 mount_one_dev(zlog_t *zlogp, char *devpath, zone_mnt_t mount_cmd)
 {
 	char			brand[MAXNAMELEN];
+	zone_dochandle_t	handle = NULL;
 	brand_handle_t		bh = NULL;
 	struct zone_devtab	ztab;
 	di_prof_t		prof = NULL;
@@ -1138,7 +1108,7 @@
 	int			err;
 	int			retval = -1;
 	zone_iptype_t		iptype;
-	const char 		*curr_iptype = NULL;
+	const char 		*curr_iptype;
 
 	if (di_prof_init(devpath, &prof)) {
 		zerror(zlogp, B_TRUE, "failed to initialize profile");
@@ -1173,8 +1143,6 @@
 		curr_iptype = "exclusive";
 		break;
 	}
-	if (curr_iptype == NULL)
-		abort();
 
 	if (brand_platform_iter_devices(bh, zone_name,
 	    mount_one_dev_device_cb, prof, curr_iptype) != 0) {
@@ -1189,12 +1157,21 @@
 	}
 
 	/* Add user-specified devices and directories */
-	if ((err = zonecfg_setdevent(snap_hndl)) != 0) {
+	if ((handle = zonecfg_init_handle()) == NULL) {
+		zerror(zlogp, B_FALSE, "can't initialize zone handle");
+		goto cleanup;
+	}
+	if ((err = zonecfg_get_handle(zone_name, handle)) != 0) {
+		zerror(zlogp, B_FALSE, "can't get handle for zone "
+		    "%s: %s", zone_name, zonecfg_strerror(err));
+		goto cleanup;
+	}
+	if ((err = zonecfg_setdevent(handle)) != 0) {
 		zerror(zlogp, B_FALSE, "%s: %s", zone_name,
 		    zonecfg_strerror(err));
 		goto cleanup;
 	}
-	while (zonecfg_getdevent(snap_hndl, &ztab) == Z_OK) {
+	while (zonecfg_getdevent(handle, &ztab) == Z_OK) {
 		if (di_prof_add_dev(prof, ztab.zone_dev_match)) {
 			zerror(zlogp, B_TRUE, "failed to add "
 			    "user-specified device");
@@ -1201,7 +1178,7 @@
 			goto cleanup;
 		}
 	}
-	(void) zonecfg_enddevent(snap_hndl);
+	(void) zonecfg_enddevent(handle);
 
 	/* Send profile to kernel */
 	if (di_prof_commit(prof)) {
@@ -1214,6 +1191,8 @@
 cleanup:
 	if (bh != NULL)
 		brand_close(bh);
+	if (handle != NULL)
+		zonecfg_fini_handle(handle);
 	if (prof)
 		di_prof_fini(prof);
 	return (retval);
@@ -1707,6 +1686,7 @@
 	char luroot[MAXPATHLEN];
 	int i, num_fs = 0;
 	struct zone_fstab *fs_ptr = NULL;
+	zone_dochandle_t handle = NULL;
 	zone_state_t zstate;
 	brand_handle_t bh;
 	plat_gmount_cb_data_t cb;
@@ -1725,7 +1705,12 @@
 		goto bad;
 	}
 
-	if (zonecfg_setfsent(snap_hndl) != Z_OK) {
+	if ((handle = zonecfg_init_handle()) == NULL) {
+		zerror(zlogp, B_TRUE, "getting zone configuration handle");
+		goto bad;
+	}
+	if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK ||
+	    zonecfg_setfsent(handle) != Z_OK) {
 		zerror(zlogp, B_FALSE, "invalid configuration");
 		goto bad;
 	}
@@ -1743,6 +1728,7 @@
 	/* Get a handle to the brand info for this zone */
 	if ((bh = brand_open(brand)) == NULL) {
 		zerror(zlogp, B_FALSE, "unable to determine zone brand");
+		zonecfg_fini_handle(handle);
 		return (-1);
 	}
 
@@ -1757,6 +1743,7 @@
 	    plat_gmount_cb, &cb) != 0) {
 		zerror(zlogp, B_FALSE, "unable to mount filesystems");
 		brand_close(bh);
+		zonecfg_fini_handle(handle);
 		return (-1);
 	}
 	brand_close(bh);
@@ -1767,10 +1754,13 @@
 	 * higher level directories (e.g., /usr) get mounted before
 	 * any beneath them (e.g., /usr/local).
 	 */
-	if (mount_filesystems_fsent(snap_hndl, zlogp, &fs_ptr, &num_fs,
+	if (mount_filesystems_fsent(handle, zlogp, &fs_ptr, &num_fs,
 	    mount_cmd) != 0)
 		goto bad;
 
+	zonecfg_fini_handle(handle);
+	handle = NULL;
+
 	/*
 	 * Normally when we mount a zone all the zone filesystems
 	 * get mounted relative to rootpath, which is usually
@@ -1866,6 +1856,8 @@
 	return (0);
 
 bad:
+	if (handle != NULL)
+		zonecfg_fini_handle(handle);
 	free_fs_data(fs_ptr, num_fs);
 	return (-1);
 }
@@ -2221,7 +2213,13 @@
 	if (ioctl(s, SIOCLIFADDIF, (caddr_t)&lifr) < 0) {
 		/*
 		 * Here, we know that the interface can't be brought up.
+		 * A similar warning message was already printed out to
+		 * the console by zoneadm(1M) so instead we log the
+		 * message to syslog and continue.
 		 */
+		zerror(&logsys, B_TRUE, "WARNING: skipping network interface "
+		    "'%s' which may not be present/plumbed in the "
+		    "global zone.", lifr.lifr_name);
 		(void) close(s);
 		return (Z_OK);
 	}
@@ -2434,6 +2432,7 @@
 static int
 configure_shared_network_interfaces(zlog_t *zlogp)
 {
+	zone_dochandle_t handle;
 	struct zone_nwiftab nwiftab, loopback_iftab;
 	zoneid_t zoneid;
 
@@ -2442,19 +2441,29 @@
 		return (-1);
 	}
 
-	if (zonecfg_setnwifent(snap_hndl) == Z_OK) {
+	if ((handle = zonecfg_init_handle()) == NULL) {
+		zerror(zlogp, B_TRUE, "getting zone configuration handle");
+		return (-1);
+	}
+	if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) {
+		zerror(zlogp, B_FALSE, "invalid configuration");
+		zonecfg_fini_handle(handle);
+		return (-1);
+	}
+	if (zonecfg_setnwifent(handle) == Z_OK) {
 		for (;;) {
-			if (zonecfg_getnwifent(snap_hndl, &nwiftab) != Z_OK)
+			if (zonecfg_getnwifent(handle, &nwiftab) != Z_OK)
 				break;
-			nwifent_free_attrs(&nwiftab);
 			if (configure_one_interface(zlogp, zoneid, &nwiftab) !=
 			    Z_OK) {
-				(void) zonecfg_endnwifent(snap_hndl);
+				(void) zonecfg_endnwifent(handle);
+				zonecfg_fini_handle(handle);
 				return (-1);
 			}
 		}
-		(void) zonecfg_endnwifent(snap_hndl);
+		(void) zonecfg_endnwifent(handle);
 	}
+	zonecfg_fini_handle(handle);
 	if (is_system_labeled()) {
 		/*
 		 * Labeled zones share the loopback interface
@@ -2901,6 +2910,25 @@
 }
 
 /*
+ * For IP networking, we need to use the illumos-native device tree.  For most
+ * zones, this is $ZONEROOT/dev.  For LX ones, it's $ZONEROOT/native/dev.
+ * Return the appropriate post-$ZONEROOT path.
+ */
+static char *
+get_brand_dev(void)
+{
+	static char *lxpath = "/native/dev";
+	/* Cheesy hard-coding of strlen("/native") */
+	char *default_path = lxpath + 7;
+
+	/* LX zones are the exception... */
+	if (strcmp(brand_name, "lx") == 0)
+		return (lxpath);
+
+	return (default_path);
+}
+
+/*
  * Add the kernel access control information for the interface names.
  * If anything goes wrong, we log a general error message, attempt to tear down
  * whatever we set up, and return an error.
@@ -2908,6 +2936,7 @@
 static int
 configure_exclusive_network_interfaces(zlog_t *zlogp, zoneid_t zoneid)
 {
+	zone_dochandle_t handle;
 	struct zone_nwiftab nwiftab;
 	char rootpath[MAXPATHLEN];
 	char path[MAXPATHLEN];
@@ -2916,26 +2945,39 @@
 	boolean_t added = B_FALSE;
 	zone_addr_list_t *zalist = NULL, *new;
 
-	if (zonecfg_setnwifent(snap_hndl) != Z_OK)
+	if ((handle = zonecfg_init_handle()) == NULL) {
+		zerror(zlogp, B_TRUE, "getting zone configuration handle");
+		return (-1);
+	}
+	if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) {
+		zerror(zlogp, B_FALSE, "invalid configuration");
+		zonecfg_fini_handle(handle);
+		return (-1);
+	}
+
+	if (zonecfg_setnwifent(handle) != Z_OK) {
+		zonecfg_fini_handle(handle);
 		return (0);
+	}
 
 	for (;;) {
-		if (zonecfg_getnwifent(snap_hndl, &nwiftab) != Z_OK)
+		if (zonecfg_getnwifent(handle, &nwiftab) != Z_OK)
 			break;
 
-		nwifent_free_attrs(&nwiftab);
 		if (prof == NULL) {
 			if (zone_get_devroot(zone_name, rootpath,
 			    sizeof (rootpath)) != Z_OK) {
-				(void) zonecfg_endnwifent(snap_hndl);
+				(void) zonecfg_endnwifent(handle);
+				zonecfg_fini_handle(handle);
 				zerror(zlogp, B_TRUE,
 				    "unable to determine dev root");
 				return (-1);
 			}
 			(void) snprintf(path, sizeof (path), "%s%s", rootpath,
-			    "/dev");
+			    get_brand_dev());
 			if (di_prof_init(path, &prof) != 0) {
-				(void) zonecfg_endnwifent(snap_hndl);
+				(void) zonecfg_endnwifent(handle);
+				zonecfg_fini_handle(handle);
 				zerror(zlogp, B_TRUE,
 				    "failed to initialize profile");
 				return (-1);
@@ -2959,11 +3001,10 @@
 		    nwiftab.zone_nwif_physical) == 0) {
 			added = B_TRUE;
 		} else {
-			/*
-			 * Failed to add network device, but the brand hook
-			 * might be doing this for us, so keep silent.
-			 */
-			continue;
+			(void) zonecfg_endnwifent(handle);
+			zonecfg_fini_handle(handle);
+			zerror(zlogp, B_TRUE, "failed to add network device");
+			return (-1);
 		}
 		/* set up the new IP interface, and add them all later */
 		new = malloc(sizeof (*new));
@@ -2970,6 +3011,7 @@
 		if (new == NULL) {
 			zerror(zlogp, B_TRUE, "no memory for %s",
 			    nwiftab.zone_nwif_physical);
+			zonecfg_fini_handle(handle);
 			free_ip_interface(zalist);
 		}
 		bzero(new, sizeof (*new));
@@ -2979,7 +3021,8 @@
 	}
 	if (zalist != NULL) {
 		if ((errno = add_net(zlogp, zoneid, zalist)) != 0) {
-			(void) zonecfg_endnwifent(snap_hndl);
+			(void) zonecfg_endnwifent(handle);
+			zonecfg_fini_handle(handle);
 			zerror(zlogp, B_TRUE, "failed to add address");
 			free_ip_interface(zalist);
 			return (-1);
@@ -2986,7 +3029,8 @@
 		}
 		free_ip_interface(zalist);
 	}
-	(void) zonecfg_endnwifent(snap_hndl);
+	(void) zonecfg_endnwifent(handle);
+	zonecfg_fini_handle(handle);
 
 	if (prof != NULL && added) {
 		if (di_prof_commit(prof) != 0) {
@@ -3122,17 +3166,20 @@
 			/* 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);
@@ -3139,6 +3186,28 @@
 }
 
 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)
 {
@@ -3220,14 +3289,26 @@
 get_privset(zlog_t *zlogp, priv_set_t *privs, zone_mnt_t mount_cmd)
 {
 	int error = -1;
+	zone_dochandle_t handle;
 	char *privname = NULL;
 
+	if ((handle = zonecfg_init_handle()) == NULL) {
+		zerror(zlogp, B_TRUE, "getting zone configuration handle");
+		return (-1);
+	}
+	if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) {
+		zerror(zlogp, B_FALSE, "invalid configuration");
+		zonecfg_fini_handle(handle);
+		return (-1);
+	}
+
 	if (ALT_MOUNT(mount_cmd)) {
 		zone_iptype_t	iptype;
-		const char	*curr_iptype = NULL;
+		const char	*curr_iptype;
 
-		if (zonecfg_get_iptype(snap_hndl, &iptype) != Z_OK) {
+		if (zonecfg_get_iptype(handle, &iptype) != Z_OK) {
 			zerror(zlogp, B_TRUE, "unable to determine ip-type");
+			zonecfg_fini_handle(handle);
 			return (-1);
 		}
 
@@ -3240,15 +3321,17 @@
 			break;
 		}
 
-		if (zonecfg_default_privset(privs, curr_iptype) == Z_OK)
+		if (zonecfg_default_privset(privs, curr_iptype) == Z_OK) {
+			zonecfg_fini_handle(handle);
 			return (0);
-
+		}
 		zerror(zlogp, B_FALSE,
 		    "failed to determine the zone's default privilege set");
+		zonecfg_fini_handle(handle);
 		return (-1);
 	}
 
-	switch (zonecfg_get_privset(snap_hndl, privs, &privname)) {
+	switch (zonecfg_get_privset(handle, privs, &privname)) {
 	case Z_OK:
 		error = 0;
 		break;
@@ -3271,6 +3354,7 @@
 	}
 
 	free(privname);
+	zonecfg_fini_handle(handle);
 	return (error);
 }
 
@@ -3296,6 +3380,7 @@
 	nvlist_t **nvlv = NULL;
 	int rctlcount = 0;
 	int error = -1;
+	zone_dochandle_t handle;
 	struct zone_rctltab rctltab;
 	rctlblk_t *rctlblk = NULL;
 	uint64_t maxlwps;
@@ -3305,6 +3390,16 @@
 	*bufp = NULL;
 	*bufsizep = 0;
 
+	if ((handle = zonecfg_init_handle()) == NULL) {
+		zerror(zlogp, B_TRUE, "getting zone configuration handle");
+		return (-1);
+	}
+	if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) {
+		zerror(zlogp, B_FALSE, "invalid configuration");
+		zonecfg_fini_handle(handle);
+		return (-1);
+	}
+
 	rctltab.zone_rctl_valptr = NULL;
 	if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
 		zerror(zlogp, B_TRUE, "%s failed", "nvlist_alloc");
@@ -3337,7 +3432,7 @@
 		}
 	}
 
-	if (zonecfg_setrctlent(snap_hndl) != Z_OK) {
+	if (zonecfg_setrctlent(handle) != Z_OK) {
 		zerror(zlogp, B_FALSE, "%s failed", "zonecfg_setrctlent");
 		goto out;
 	}
@@ -3346,7 +3441,7 @@
 		zerror(zlogp, B_TRUE, "memory allocation failed");
 		goto out;
 	}
-	while (zonecfg_getrctlent(snap_hndl, &rctltab) == Z_OK) {
+	while (zonecfg_getrctlent(handle, &rctltab) == Z_OK) {
 		struct zone_rctlvaltab *rctlval;
 		uint_t i, count;
 		const char *name = rctltab.zone_rctl_name;
@@ -3449,7 +3544,7 @@
 		nvlv = NULL;
 		rctlcount++;
 	}
-	(void) zonecfg_endrctlent(snap_hndl);
+	(void) zonecfg_endrctlent(handle);
 
 	if (rctlcount == 0) {
 		error = 0;
@@ -3473,6 +3568,8 @@
 	nvlist_free(nvl);
 	if (nvlv != NULL)
 		free(nvlv);
+	if (handle != NULL)
+		zonecfg_fini_handle(handle);
 	return (error);
 }
 
@@ -3488,7 +3585,7 @@
 	    > sizeof (cmdbuf))
 		return (-1);
 
-	if (do_subproc(zlogp, cmdbuf, retstr, B_FALSE) != 0)
+	if (do_subproc(zlogp, cmdbuf, retstr) != 0)
 		return (-1);
 
 	return (0);
@@ -3497,6 +3594,7 @@
 static int
 get_datasets(zlog_t *zlogp, char **bufp, size_t *bufsizep)
 {
+	zone_dochandle_t handle;
 	struct zone_dstab dstab;
 	size_t total, offset, len;
 	int error = -1;
@@ -3507,20 +3605,30 @@
 	*bufp = NULL;
 	*bufsizep = 0;
 
+	if ((handle = zonecfg_init_handle()) == NULL) {
+		zerror(zlogp, B_TRUE, "getting zone configuration handle");
+		return (-1);
+	}
+	if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) {
+		zerror(zlogp, B_FALSE, "invalid configuration");
+		zonecfg_fini_handle(handle);
+		return (-1);
+	}
+
 	if (get_implicit_datasets(zlogp, &implicit_datasets) != 0) {
 		zerror(zlogp, B_FALSE, "getting implicit datasets failed");
 		goto out;
 	}
 
-	if (zonecfg_setdsent(snap_hndl) != Z_OK) {
+	if (zonecfg_setdsent(handle) != Z_OK) {
 		zerror(zlogp, B_FALSE, "%s failed", "zonecfg_setdsent");
 		goto out;
 	}
 
 	total = 0;
-	while (zonecfg_getdsent(snap_hndl, &dstab) == Z_OK)
+	while (zonecfg_getdsent(handle, &dstab) == Z_OK)
 		total += strlen(dstab.zone_dataset_name) + 1;
-	(void) zonecfg_enddsent(snap_hndl);
+	(void) zonecfg_enddsent(handle);
 
 	if (implicit_datasets != NULL)
 		implicit_len = strlen(implicit_datasets);
@@ -3537,12 +3645,12 @@
 		goto out;
 	}
 
-	if (zonecfg_setdsent(snap_hndl) != Z_OK) {
+	if (zonecfg_setdsent(handle) != Z_OK) {
 		zerror(zlogp, B_FALSE, "%s failed", "zonecfg_setdsent");
 		goto out;
 	}
 	offset = 0;
-	while (zonecfg_getdsent(snap_hndl, &dstab) == Z_OK) {
+	while (zonecfg_getdsent(handle, &dstab) == Z_OK) {
 		len = strlen(dstab.zone_dataset_name);
 		(void) strlcpy(str + offset, dstab.zone_dataset_name,
 		    total - offset);
@@ -3550,7 +3658,7 @@
 		if (offset < total - 1)
 			str[offset++] = ',';
 	}
-	(void) zonecfg_enddsent(snap_hndl);
+	(void) zonecfg_enddsent(handle);
 
 	if (implicit_len > 0)
 		(void) strlcpy(str + offset, implicit_datasets, total - offset);
@@ -3562,6 +3670,8 @@
 out:
 	if (error != 0 && str != NULL)
 		free(str);
+	if (handle != NULL)
+		zonecfg_fini_handle(handle);
 	if (implicit_datasets != NULL)
 		free(implicit_datasets);
 
@@ -3571,26 +3681,40 @@
 static int
 validate_datasets(zlog_t *zlogp)
 {
+	zone_dochandle_t handle;
 	struct zone_dstab dstab;
 	zfs_handle_t *zhp;
 	libzfs_handle_t *hdl;
 
-	if (zonecfg_setdsent(snap_hndl) != Z_OK) {
+	if ((handle = zonecfg_init_handle()) == NULL) {
+		zerror(zlogp, B_TRUE, "getting zone configuration handle");
+		return (-1);
+	}
+	if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) {
 		zerror(zlogp, B_FALSE, "invalid configuration");
+		zonecfg_fini_handle(handle);
 		return (-1);
 	}
 
+	if (zonecfg_setdsent(handle) != Z_OK) {
+		zerror(zlogp, B_FALSE, "invalid configuration");
+		zonecfg_fini_handle(handle);
+		return (-1);
+	}
+
 	if ((hdl = libzfs_init()) == NULL) {
 		zerror(zlogp, B_FALSE, "opening ZFS library");
+		zonecfg_fini_handle(handle);
 		return (-1);
 	}
 
-	while (zonecfg_getdsent(snap_hndl, &dstab) == Z_OK) {
+	while (zonecfg_getdsent(handle, &dstab) == Z_OK) {
 
 		if ((zhp = zfs_open(hdl, dstab.zone_dataset_name,
 		    ZFS_TYPE_FILESYSTEM)) == NULL) {
 			zerror(zlogp, B_FALSE, "cannot open ZFS dataset '%s'",
 			    dstab.zone_dataset_name);
+			zonecfg_fini_handle(handle);
 			libzfs_fini(hdl);
 			return (-1);
 		}
@@ -3605,6 +3729,7 @@
 			zerror(zlogp, B_FALSE, "cannot set 'zoned' "
 			    "property for ZFS dataset '%s'\n",
 			    dstab.zone_dataset_name);
+			zonecfg_fini_handle(handle);
 			zfs_close(zhp);
 			libzfs_fini(hdl);
 			return (-1);
@@ -3612,8 +3737,9 @@
 
 		zfs_close(zhp);
 	}
-	(void) zonecfg_enddsent(snap_hndl);
+	(void) zonecfg_enddsent(handle);
 
+	zonecfg_fini_handle(handle);
 	libzfs_fini(hdl);
 
 	return (0);
@@ -4350,10 +4476,22 @@
 	int res;
 	uint64_t tmp;
 	char sched[MAXNAMELEN];
+	zone_dochandle_t handle = NULL;
 	char pool_err[128];
 
+	if ((handle = zonecfg_init_handle()) == NULL) {
+		zerror(zlogp, B_TRUE, "getting zone configuration handle");
+		return (Z_BAD_HANDLE);
+	}
+
+	if ((res = zonecfg_get_snapshot_handle(zone_name, handle)) != Z_OK) {
+		zerror(zlogp, B_FALSE, "invalid configuration");
+		zonecfg_fini_handle(handle);
+		return (res);
+	}
+
 	/* Get the scheduling class set in the zone configuration. */
-	if (zonecfg_get_sched_class(snap_hndl, sched, sizeof (sched)) == Z_OK &&
+	if (zonecfg_get_sched_class(handle, sched, sizeof (sched)) == Z_OK &&
 	    strlen(sched) > 0) {
 		if (zone_setattr(zoneid, ZONE_ATTR_SCHED_CLASS, sched,
 		    strlen(sched)) == -1)
@@ -4398,7 +4536,7 @@
 		 */
 		char class_name[PC_CLNMSZ];
 
-		if (zonecfg_get_dflt_sched_class(snap_hndl, class_name,
+		if (zonecfg_get_dflt_sched_class(handle, class_name,
 		    sizeof (class_name)) != Z_OK) {
 			zerror(zlogp, B_FALSE, "WARNING: unable to determine "
 			    "the zone's scheduling class");
@@ -4431,7 +4569,7 @@
 	 * right thing in all cases (reuse or create) based on the current
 	 * zonecfg.
 	 */
-	if ((res = zonecfg_bind_tmp_pool(snap_hndl, zoneid, pool_err,
+	if ((res = zonecfg_bind_tmp_pool(handle, zoneid, pool_err,
 	    sizeof (pool_err))) != Z_OK) {
 		if (res == Z_POOL || res == Z_POOL_CREATE || res == Z_POOL_BIND)
 			zerror(zlogp, B_FALSE, "%s: %s\ndedicated-cpu setting "
@@ -4440,6 +4578,7 @@
 		else
 			zerror(zlogp, B_FALSE, "could not bind zone to "
 			    "temporary pool: %s", zonecfg_strerror(res));
+		zonecfg_fini_handle(handle);
 		return (Z_POOL_BIND);
 	}
 
@@ -4446,7 +4585,7 @@
 	/*
 	 * Check if we need to warn about poold not being enabled.
 	 */
-	if (zonecfg_warn_poold(snap_hndl)) {
+	if (zonecfg_warn_poold(handle)) {
 		zerror(zlogp, B_FALSE, "WARNING: A range of dedicated-cpus has "
 		    "been specified\nbut the dynamic pool service is not "
 		    "enabled.\nThe system will not dynamically adjust the\n"
@@ -4456,7 +4595,7 @@
 	}
 
 	/* The following is a warning, not an error. */
-	if ((res = zonecfg_bind_pool(snap_hndl, zoneid, pool_err,
+	if ((res = zonecfg_bind_pool(handle, zoneid, pool_err,
 	    sizeof (pool_err))) != Z_OK) {
 		if (res == Z_POOL_BIND)
 			zerror(zlogp, B_FALSE, "WARNING: unable to bind to "
@@ -4470,9 +4609,10 @@
 	}
 
 	/* Update saved pool name in case it has changed */
-	(void) zonecfg_get_poolname(snap_hndl, zone_name, pool_name,
+	(void) zonecfg_get_poolname(handle, zone_name, pool_name,
 	    sizeof (pool_name));
 
+	zonecfg_fini_handle(handle);
 	return (Z_OK);
 }
 
@@ -4573,28 +4713,33 @@
 }
 
 static int
-setup_zone_attrs(zlog_t *zlogp, zoneid_t zoneid)
+setup_zone_attrs(zlog_t *zlogp, char *zone_namep, zoneid_t zoneid)
 {
+	zone_dochandle_t handle;
 	int res = Z_OK;
 
-	if ((res = setup_zone_hostid(snap_hndl, zlogp, zoneid)) != Z_OK)
+	if ((handle = zonecfg_init_handle()) == NULL) {
+		zerror(zlogp, B_TRUE, "getting zone configuration handle");
+		return (Z_BAD_HANDLE);
+	}
+	if ((res = zonecfg_get_snapshot_handle(zone_namep, handle)) != Z_OK) {
+		zerror(zlogp, B_FALSE, "invalid configuration");
 		goto out;
+	}
 
-	if ((res = setup_zone_fs_allowed(snap_hndl, zlogp, zoneid)) != Z_OK)
+	if ((res = setup_zone_hostid(handle, zlogp, zoneid)) != Z_OK)
 		goto out;
 
+	if ((res = setup_zone_fs_allowed(handle, zlogp, zoneid)) != Z_OK)
+		goto out;
+
 out:
+	zonecfg_fini_handle(handle);
 	return (res);
 }
 
-/*
- * The zone_did is a persistent debug ID.  Each zone should have a unique ID
- * in the kernel.  This is used for things like DTrace which want to monitor
- * zones across reboots.  They can't use the zoneid since that changes on
- * each boot.
- */
 zoneid_t
-vplat_create(zlog_t *zlogp, zone_mnt_t mount_cmd, zoneid_t zone_did)
+vplat_create(zlog_t *zlogp, zone_mnt_t mount_cmd)
 {
 	zoneid_t rval = -1;
 	priv_set_t *privs;
@@ -4610,7 +4755,7 @@
 	tsol_zcent_t *zcent = NULL;
 	int match = 0;
 	int doi = 0;
-	int flags = -1;
+	int flags;
 	zone_iptype_t iptype;
 
 	if (zone_get_rootpath(zone_name, rootpath, sizeof (rootpath)) != Z_OK) {
@@ -4632,8 +4777,6 @@
 		flags = ZCF_NET_EXCL;
 		break;
 	}
-	if (flags == -1)
-		abort();
 
 	if ((privs = priv_allocset()) == NULL) {
 		zerror(zlogp, B_TRUE, "%s failed", "priv_allocset");
@@ -4737,7 +4880,7 @@
 	xerr = 0;
 	if ((zoneid = zone_create(kzone, rootpath, privs, rctlbuf,
 	    rctlbufsz, zfsbuf, zfsbufsz, &xerr, match, doi, zlabel,
-	    flags, zone_did)) == -1) {
+	    flags)) == -1) {
 		if (xerr == ZE_AREMOUNTS) {
 			if (zonecfg_find_mounts(rootpath, NULL, NULL) < 1) {
 				zerror(zlogp, B_FALSE,
@@ -4783,7 +4926,7 @@
 		struct brand_attr attr;
 		char modname[MAXPATHLEN];
 
-		if (setup_zone_attrs(zlogp, zoneid) != Z_OK)
+		if (setup_zone_attrs(zlogp, zone_name, zoneid) != Z_OK)
 			goto error;
 
 		if ((bh = brand_open(brand_name)) == NULL) {
@@ -4841,8 +4984,6 @@
 	}
 	if (rctlbuf != NULL)
 		free(rctlbuf);
-	if (zfsbuf != NULL)
-		free(zfsbuf);
 	priv_freeset(privs);
 	if (fp != NULL)
 		zonecfg_close_scratch(fp);
@@ -4981,8 +5122,6 @@
 				return (-1);
 			}
 			break;
-		default:
-			abort();
 		}
 	}
 
@@ -5058,8 +5197,7 @@
 }
 
 int
-vplat_teardown(zlog_t *zlogp, boolean_t unmount_cmd, boolean_t rebooting,
-    boolean_t debug)
+vplat_teardown(zlog_t *zlogp, boolean_t unmount_cmd, boolean_t rebooting)
 {
 	char *kzone;
 	zoneid_t zoneid;
@@ -5097,12 +5235,16 @@
 		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
@@ -5136,7 +5278,7 @@
 	brand_close(bh);
 
 	if ((strlen(cmdbuf) > EXEC_LEN) &&
-	    (do_subproc(zlogp, cmdbuf, NULL, debug) != Z_OK)) {
+	    (do_subproc(zlogp, cmdbuf, NULL) != Z_OK)) {
 		zerror(zlogp, B_FALSE, "%s failed", cmdbuf);
 		goto error;
 	}
@@ -5168,6 +5310,12 @@
 			}
 			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 "
@@ -5204,9 +5352,14 @@
 
 		if (rebooting) {
 			struct zone_psettab pset_tab;
+			zone_dochandle_t handle;
 
-			if (zonecfg_lookup_pset(snap_hndl, &pset_tab) == Z_OK)
+			if ((handle = zonecfg_init_handle()) != NULL &&
+			    zonecfg_get_handle(zone_name, handle) == Z_OK &&
+			    zonecfg_lookup_pset(handle, &pset_tab) == Z_OK)
 				destroy_tmp_pool = B_FALSE;
+
+			zonecfg_fini_handle(handle);
 		}
 
 		if (destroy_tmp_pool) {
