--- old/usr/src/cmd/zonecfg/zonecfg.c	Wed Oct  5 00:31:43 2016
+++ new/usr/src/cmd/zonecfg/zonecfg.c	Wed Oct  5 00:31:43 2016
@@ -23,6 +23,7 @@
  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
  * Copyright 2014 Gary Mills
+ * Copyright 2016, Joyent Inc.
  */
 
 /*
@@ -234,6 +235,11 @@
 	"fs-allowed",
 	ALIAS_MAXPROCS,
 	"allowed-address",
+	ALIAS_ZFSPRI,
+	"mac-addr",
+	"vlan-id",
+	"global-nic",
+	"property",
 	NULL
 };
 
@@ -406,9 +412,20 @@
 	"exit",
 	"help",
 	"info",
+	"add property ",
+	"clear allowed-address",
+	"clear defrouter",
+	"clear global-nic",
+	"clear mac-addr",
+	"clear vlan-id",
+	"remove property ",
 	"set address=",
-	"set physical=",
+	"set allowed-address=",
 	"set defrouter=",
+	"set global-nic=",
+	"set mac-addr=",
+	"set physical=",
+	"set vlan-id=",
 	NULL
 };
 
@@ -418,6 +435,7 @@
 	"exit",
 	"help",
 	"info",
+	"add property ",
 	"set match=",
 	NULL
 };
@@ -579,7 +597,6 @@
 static struct zone_attrtab	old_attrtab, in_progress_attrtab;
 static struct zone_dstab	old_dstab, in_progress_dstab;
 static struct zone_psettab	old_psettab, in_progress_psettab;
-static struct zone_mcaptab	old_mcaptab, in_progress_mcaptab;
 static struct zone_admintab	old_admintab, in_progress_admintab;
 
 static GetLine *gl;	/* The gl_get_line() resource object */
@@ -1078,11 +1095,20 @@
 			(void) fprintf(fp, gettext("Valid commands:\n"));
 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
 			    pt_to_str(PT_ADDRESS), gettext("<IP-address>"));
+			(void) fprintf(fp, "\t%s %s (%s=<value>,%s=<value>)\n",
+			    cmd_to_str(CMD_ADD), pt_to_str(PT_NPROP),
+			    pt_to_str(PT_NAME), pt_to_str(PT_VALUE));
 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
 			    pt_to_str(PT_ALLOWED_ADDRESS),
 			    gettext("<IP-address>"));
 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
 			    pt_to_str(PT_PHYSICAL), gettext("<interface>"));
+			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
+			    pt_to_str(PT_MAC), gettext("<mac-address>"));
+			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
+			    pt_to_str(PT_GNIC), gettext("<global zone NIC>"));
+			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
+			    pt_to_str(PT_VLANID), gettext("<vlan ID>"));
 			(void) fprintf(fp, gettext("See ifconfig(1M) for "
 			    "details of the <interface> string.\n"));
 			(void) fprintf(fp, gettext("%s %s is valid "
@@ -1090,10 +1116,12 @@
 			    "must not be set.\n"),
 			    cmd_to_str(CMD_SET), pt_to_str(PT_ADDRESS),
 			    pt_to_str(PT_IPTYPE), gettext("shared"));
-			(void) fprintf(fp, gettext("%s %s is valid "
-			    "if the %s property is set to %s, otherwise it "
-			    "must not be set.\n"),
-			    cmd_to_str(CMD_SET), pt_to_str(PT_ALLOWED_ADDRESS),
+			(void) fprintf(fp, gettext("%s (%s, %s, %s, %s) are "
+			    "valid if the %s property is set to %s, otherwise "
+			    "they must not be set.\n"),
+			    cmd_to_str(CMD_SET),
+			    pt_to_str(PT_ALLOWED_ADDRESS), pt_to_str(PT_MAC),
+			    pt_to_str(PT_VLANID), pt_to_str(PT_GNIC),
 			    pt_to_str(PT_IPTYPE), gettext("exclusive"));
 			(void) fprintf(fp, gettext("\t%s %s=%s\n%s %s "
 			    "is valid if the %s or %s property is set, "
@@ -1109,6 +1137,9 @@
 			    "used to configure a device node.\n"),
 			    rt_to_str(resource_scope));
 			(void) fprintf(fp, gettext("Valid commands:\n"));
+			(void) fprintf(fp, "\t%s %s (%s=<value>,%s=<value>)\n",
+			    cmd_to_str(CMD_ADD), pt_to_str(PT_NPROP),
+			    pt_to_str(PT_NAME), pt_to_str(PT_VALUE));
 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
 			    pt_to_str(PT_MATCH), gettext("<device-path>"));
 			break;
@@ -1336,11 +1367,14 @@
 		    rt_to_str(RT_FS), pt_to_str(PT_DIR),
 		    pt_to_str(PT_SPECIAL), pt_to_str(PT_RAW),
 		    pt_to_str(PT_TYPE), pt_to_str(PT_OPTIONS));
-		(void) fprintf(fp, "\t%s\t\t%s, %s, %s|%s\n", rt_to_str(RT_NET),
+		(void) fprintf(fp, "\t%s\t\t%s, %s, %s, %s, %s, %s, %s %s\n",
+		    rt_to_str(RT_NET),
 		    pt_to_str(PT_ADDRESS), pt_to_str(PT_ALLOWED_ADDRESS),
-		    pt_to_str(PT_PHYSICAL), pt_to_str(PT_DEFROUTER));
-		(void) fprintf(fp, "\t%s\t\t%s\n", rt_to_str(RT_DEVICE),
-		    pt_to_str(PT_MATCH));
+		    pt_to_str(PT_GNIC), pt_to_str(PT_MAC),
+		    pt_to_str(PT_PHYSICAL), pt_to_str(PT_NPROP),
+		    pt_to_str(PT_VLANID), pt_to_str(PT_DEFROUTER));
+		(void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_DEVICE),
+		    pt_to_str(PT_MATCH), pt_to_str(PT_NPROP));
 		(void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_RCTL),
 		    pt_to_str(PT_NAME), pt_to_str(PT_VALUE));
 		(void) fprintf(fp, "\t%s\t\t%s, %s, %s\n", rt_to_str(RT_ATTR),
@@ -1395,6 +1429,9 @@
 	if (zonecfg_check_handle(handle) != Z_OK) {
 		if ((err = zonecfg_get_handle(zone, handle)) == Z_OK) {
 			got_handle = B_TRUE;
+
+			(void) zonecfg_fix_obsolete(handle);
+
 			if (zonecfg_get_brand(handle, brandname,
 			    sizeof (brandname)) != Z_OK) {
 				zerr("Zone %s is inconsistent: missing "
@@ -1695,6 +1732,17 @@
 			(void) strlcpy(zone_template, optarg,
 			    sizeof (zone_template));
 			break;
+		case 'X':
+			(void) snprintf(zone_template, sizeof (zone_template),
+			    "%s/%s.xml", ZONE_CONFIG_ROOT, zone);
+			err = zonecfg_get_xml_handle(zone_template, handle);
+			if (err != Z_OK) {
+				zone_perror(execname, err, B_TRUE);
+				exit(Z_ERR);
+			}
+			got_handle = B_TRUE;
+			need_to_commit = B_TRUE;
+			return;
 		default:
 			short_usage(CMD_CREATE);
 			arg_err = B_TRUE;
@@ -1797,8 +1845,8 @@
 	struct zone_rctltab rctltab;
 	struct zone_dstab dstab;
 	struct zone_psettab psettab;
-	struct zone_mcaptab mcaptab;
 	struct zone_rctlvaltab *valptr;
+	struct zone_res_attrtab *rap;
 	struct zone_admintab admintab;
 	int err, arg;
 	char zonepath[MAXPATHLEN], outfile[MAXPATHLEN], pool[MAXNAMELEN];
@@ -1968,7 +2016,17 @@
 		export_prop(of, PT_ALLOWED_ADDRESS,
 		    nwiftab.zone_nwif_allowed_address);
 		export_prop(of, PT_PHYSICAL, nwiftab.zone_nwif_physical);
+		export_prop(of, PT_MAC, nwiftab.zone_nwif_mac);
+		export_prop(of, PT_VLANID, nwiftab.zone_nwif_vlan_id);
+		export_prop(of, PT_GNIC, nwiftab.zone_nwif_gnic);
 		export_prop(of, PT_DEFROUTER, nwiftab.zone_nwif_defrouter);
+		for (rap = nwiftab.zone_nwif_attrp; rap != NULL;
+		    rap = rap->zone_res_attr_next) {
+			fprintf(of, "%s %s (%s=%s,%s=\"%s\")\n",
+			    cmd_to_str(CMD_ADD), pt_to_str(PT_NPROP),
+			    pt_to_str(PT_NAME), rap->zone_res_attr_name,
+			    pt_to_str(PT_VALUE), rap->zone_res_attr_value);
+		}
 		(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
 	}
 	(void) zonecfg_endnwifent(handle);
@@ -1981,21 +2039,17 @@
 		(void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
 		    rt_to_str(RT_DEVICE));
 		export_prop(of, PT_MATCH, devtab.zone_dev_match);
+		for (rap = devtab.zone_dev_attrp; rap != NULL;
+		    rap = rap->zone_res_attr_next) {
+			fprintf(of, "%s %s (%s=%s,%s=\"%s\")\n",
+			    cmd_to_str(CMD_ADD), pt_to_str(PT_NPROP),
+			    pt_to_str(PT_NAME), rap->zone_res_attr_name,
+			    pt_to_str(PT_VALUE), rap->zone_res_attr_value);
+		}
 		(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
 	}
 	(void) zonecfg_enddevent(handle);
 
-	if (zonecfg_getmcapent(handle, &mcaptab) == Z_OK) {
-		char buf[128];
-
-		(void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
-		    rt_to_str(RT_MCAP));
-		bytes_to_units(mcaptab.zone_physmem_cap, buf, sizeof (buf));
-		(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
-		    pt_to_str(PT_PHYSICAL), buf);
-		(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
-	}
-
 	if ((err = zonecfg_setrctlent(handle)) != Z_OK) {
 		zone_perror(zone, err, B_FALSE);
 		goto done;
@@ -2149,7 +2203,6 @@
 {
 	int type;
 	struct zone_psettab tmp_psettab;
-	struct zone_mcaptab tmp_mcaptab;
 	uint64_t tmp;
 	uint64_t tmp_mcap;
 	char pool[MAXNAMELEN];
@@ -2241,9 +2294,10 @@
 		 * Make sure there isn't already a mem-cap entry or max-swap
 		 * or max-locked rctl.
 		 */
-		if (zonecfg_lookup_mcap(handle, &tmp_mcaptab) == Z_OK ||
-		    zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &tmp_mcap)
-		    == Z_OK ||
+		if (zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP,
+		    &tmp_mcap) == Z_OK ||
+		    zonecfg_get_aliased_rctl(handle, ALIAS_MAXPHYSMEM,
+		    &tmp_mcap) == Z_OK ||
 		    zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM,
 		    &tmp_mcap) == Z_OK) {
 			zerr(gettext("The %s resource or a related resource "
@@ -2256,7 +2310,6 @@
 			    "to even the root user; "
 			    "this could render the system impossible\n"
 			    "to administer.  Please use caution."));
-		bzero(&in_progress_mcaptab, sizeof (in_progress_mcaptab));
 		return;
 	case RT_ADMIN:
 		bzero(&in_progress_admintab, sizeof (in_progress_admintab));
@@ -2359,7 +2412,69 @@
 	zonecfg_free_rctl_value_list(rctlvaltab);
 }
 
+/*
+ * Resource attribute ("property" resource embedded on net or dev resource)
+ */
 static void
+do_res_attr(struct zone_res_attrtab **headp, complex_property_ptr_t cpp)
+{
+	complex_property_ptr_t cp;
+	struct zone_res_attrtab *np;
+	int err;
+	boolean_t seen_name = B_FALSE, seen_value = B_FALSE;
+
+	if ((np = calloc(1, sizeof (struct zone_res_attrtab))) == NULL) {
+		zone_perror(zone, Z_NOMEM, B_TRUE);
+		exit(Z_ERR);
+	}
+
+	for (cp = cpp; cp != NULL; cp = cp->cp_next) {
+		switch (cp->cp_type) {
+		case PT_NAME:
+			if (seen_name) {
+				zerr(gettext("%s already specified"),
+				    pt_to_str(PT_NAME));
+				goto bad;
+			}
+			(void) strlcpy(np->zone_res_attr_name, cp->cp_value,
+			    sizeof (np->zone_res_attr_name));
+			seen_name = B_TRUE;
+			break;
+		case PT_VALUE:
+			if (seen_value) {
+				zerr(gettext("%s already specified"),
+				    pt_to_str(PT_VALUE));
+				goto bad;
+			}
+			(void) strlcpy(np->zone_res_attr_value, cp->cp_value,
+			    sizeof (np->zone_res_attr_value));
+			seen_value = B_TRUE;
+			break;
+		default:
+			zone_perror(pt_to_str(PT_NPROP), Z_NO_PROPERTY_TYPE,
+			    B_TRUE);
+			long_usage(CMD_ADD, B_TRUE);
+			usage(B_FALSE, HELP_PROPS);
+			zonecfg_free_res_attr_list(np);
+			return;
+		}
+	}
+
+	if (!seen_name)
+		zerr(gettext("%s not specified"), pt_to_str(PT_NAME));
+	if (!seen_value)
+		zerr(gettext("%s not specified"), pt_to_str(PT_VALUE));
+
+	err = zonecfg_add_res_attr(headp, np);
+	if (err != Z_OK)
+		zone_perror(pt_to_str(PT_NPROP), err, B_TRUE);
+	return;
+
+bad:
+	zonecfg_free_res_attr_list(np);
+}
+
+static void
 add_property(cmd_t *cmd)
 {
 	char *prop_id;
@@ -2426,6 +2541,44 @@
 			}
 		}
 		return;
+	case RT_NET:
+		if (prop_type != PT_NPROP) {
+			zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
+			    B_TRUE);
+			long_usage(CMD_ADD, B_TRUE);
+			usage(B_FALSE, HELP_PROPS);
+			return;
+		}
+		pp = cmd->cmd_property_ptr[0];
+		if (pp->pv_type != PROP_VAL_COMPLEX) {
+			zerr(gettext("A %s value was expected here."),
+			    pvt_to_str(PROP_VAL_COMPLEX));
+			saw_error = B_TRUE;
+			return;
+		}
+
+		do_res_attr(&(in_progress_nwiftab.zone_nwif_attrp),
+		    pp->pv_complex);
+		return;
+	case RT_DEVICE:
+		if (prop_type != PT_NPROP) {
+			zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
+			    B_TRUE);
+			long_usage(CMD_ADD, B_TRUE);
+			usage(B_FALSE, HELP_PROPS);
+			return;
+		}
+		pp = cmd->cmd_property_ptr[0];
+		if (pp->pv_type != PROP_VAL_COMPLEX) {
+			zerr(gettext("A %s value was expected here."),
+			    pvt_to_str(PROP_VAL_COMPLEX));
+			saw_error = B_TRUE;
+			return;
+		}
+
+		do_res_attr(&(in_progress_devtab.zone_dev_attrp),
+		    pp->pv_complex);
+		return;
 	case RT_RCTL:
 		if (prop_type != PT_VALUE) {
 			zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
@@ -2530,8 +2683,9 @@
 		resource_scope = cmd->cmd_res_type;
 		end_op = CMD_ADD;
 		add_resource(cmd);
-	} else
+	} else {
 		add_property(cmd);
+	}
 }
 
 /*
@@ -2729,6 +2883,21 @@
 			    pp->pv_simple,
 			    sizeof (nwiftab->zone_nwif_physical));
 			break;
+		case PT_MAC:
+			(void) strlcpy(nwiftab->zone_nwif_mac,
+			    pp->pv_simple,
+			    sizeof (nwiftab->zone_nwif_mac));
+			break;
+		case PT_VLANID:
+			(void) strlcpy(nwiftab->zone_nwif_vlan_id,
+			    pp->pv_simple,
+			    sizeof (nwiftab->zone_nwif_vlan_id));
+			break;
+		case PT_GNIC:
+			(void) strlcpy(nwiftab->zone_nwif_gnic,
+			    pp->pv_simple,
+			    sizeof (nwiftab->zone_nwif_gnic));
+			break;
 		case PT_DEFROUTER:
 			(void) strlcpy(nwiftab->zone_nwif_defrouter,
 			    pp->pv_simple,
@@ -3246,10 +3415,9 @@
 {
 	int err, res1, res2, res3;
 	uint64_t tmp;
-	struct zone_mcaptab mcaptab;
 	boolean_t revert = B_FALSE;
 
-	res1 = zonecfg_lookup_mcap(handle, &mcaptab);
+	res1 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXPHYSMEM, &tmp);
 	res2 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &tmp);
 	res3 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM, &tmp);
 
@@ -3261,7 +3429,8 @@
 		return;
 	}
 	if (res1 == Z_OK) {
-		if ((err = zonecfg_delete_mcap(handle)) != Z_OK) {
+		if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_MAXPHYSMEM))
+		    != Z_OK) {
 			z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err, B_TRUE);
 			revert = B_TRUE;
 		} else {
@@ -3268,6 +3437,7 @@
 			need_to_commit = B_TRUE;
 		}
 	}
+
 	if (res2 == Z_OK) {
 		if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_MAXSWAP))
 		    != Z_OK) {
@@ -3410,6 +3580,7 @@
 	int err, res_type, prop_type;
 	property_value_ptr_t pp;
 	struct zone_rctlvaltab *rctlvaltab;
+	struct zone_res_attrtab *np;
 	complex_property_ptr_t cx;
 
 	res_type = resource_scope;
@@ -3470,6 +3641,56 @@
 			}
 		}
 		return;
+	case RT_NET:		/* FALLTHRU */
+	case RT_DEVICE:
+		if (prop_type != PT_NPROP) {
+			zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
+			    B_TRUE);
+			long_usage(CMD_REMOVE, B_TRUE);
+			usage(B_FALSE, HELP_PROPS);
+			return;
+		}
+		pp = cmd->cmd_property_ptr[0];
+		if (pp->pv_type != PROP_VAL_COMPLEX) {
+			zerr(gettext("A %s value was expected here."),
+			    pvt_to_str(PROP_VAL_COMPLEX));
+			saw_error = B_TRUE;
+			return;
+		}
+
+		np = alloca(sizeof (struct zone_res_attrtab));
+		for (cx = pp->pv_complex; cx != NULL; cx = cx->cp_next) {
+			switch (cx->cp_type) {
+			case PT_NAME:
+				(void) strlcpy(np->zone_res_attr_name,
+				    cx->cp_value,
+				    sizeof (np->zone_res_attr_name));
+				break;
+			case PT_VALUE:
+				(void) strlcpy(np->zone_res_attr_value,
+				    cx->cp_value,
+				    sizeof (np->zone_res_attr_value));
+				break;
+			default:
+				zone_perror(pt_to_str(prop_type),
+				    Z_NO_PROPERTY_TYPE, B_TRUE);
+				long_usage(CMD_REMOVE, B_TRUE);
+				usage(B_FALSE, HELP_PROPS);
+				return;
+			}
+		}
+		np->zone_res_attr_next = NULL;
+
+		if (res_type == RT_NET) {
+			err = zonecfg_remove_res_attr(
+			    &(in_progress_nwiftab.zone_nwif_attrp), np);
+		} else {				/* RT_DEVICE */
+			err = zonecfg_remove_res_attr(
+			    &(in_progress_devtab.zone_dev_attrp), np);
+		}
+		if (err != Z_OK)
+			zone_perror(pt_to_str(prop_type), err, B_TRUE);
+		return;
 	case RT_RCTL:
 		if (prop_type != PT_VALUE) {
 			zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
@@ -3522,18 +3743,6 @@
 			zone_perror(pt_to_str(prop_type), err, B_TRUE);
 		zonecfg_free_rctl_value_list(rctlvaltab);
 		return;
-	case RT_NET:
-		if (prop_type != PT_DEFROUTER) {
-			zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
-			    B_TRUE);
-			long_usage(CMD_REMOVE, B_TRUE);
-			usage(B_FALSE, HELP_PROPS);
-			return;
-		} else {
-			bzero(&in_progress_nwiftab.zone_nwif_defrouter,
-			    sizeof (in_progress_nwiftab.zone_nwif_defrouter));
-			return;
-		}
 	default:
 		zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, B_TRUE);
 		long_usage(CMD_REMOVE, B_TRUE);
@@ -3596,8 +3805,7 @@
 	case RT_MCAP:
 		switch (prop_type) {
 		case PT_PHYSICAL:
-			in_progress_mcaptab.zone_physmem_cap[0] = '\0';
-			need_to_commit = B_TRUE;
+			remove_aliased_rctl(PT_PHYSICAL, ALIAS_MAXPHYSMEM);
 			return;
 		case PT_SWAP:
 			remove_aliased_rctl(PT_SWAP, ALIAS_MAXSWAP);
@@ -3607,6 +3815,30 @@
 			return;
 		}
 		break;
+	case RT_NET:
+		switch (prop_type) {
+		case PT_ALLOWED_ADDRESS:
+			in_progress_nwiftab.zone_nwif_allowed_address[0] = '\0';
+			need_to_commit = B_TRUE;
+			return;
+		case PT_DEFROUTER:
+			in_progress_nwiftab.zone_nwif_defrouter[0] = '\0';
+			need_to_commit = B_TRUE;
+			return;
+		case PT_GNIC:
+			in_progress_nwiftab.zone_nwif_gnic[0] = '\0';
+			need_to_commit = B_TRUE;
+			return;
+		case PT_MAC:
+			in_progress_nwiftab.zone_nwif_mac[0] = '\0';
+			need_to_commit = B_TRUE;
+			return;
+		case PT_VLANID:
+			in_progress_nwiftab.zone_nwif_vlan_id[0] = '\0';
+			need_to_commit = B_TRUE;
+			return;
+		}
+		break;
 	default:
 		break;
 	}
@@ -3739,7 +3971,7 @@
 void
 select_func(cmd_t *cmd)
 {
-	int type, err, res;
+	int type, err;
 	uint64_t limit;
 	uint64_t tmp;
 
@@ -3834,7 +4066,8 @@
 		return;
 	case RT_MCAP:
 		/* if none of these exist, there is no resource to select */
-		if ((res = zonecfg_lookup_mcap(handle, &old_mcaptab)) != Z_OK &&
+		if (zonecfg_get_aliased_rctl(handle, ALIAS_MAXPHYSMEM, &limit)
+		    != Z_OK &&
 		    zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &limit)
 		    != Z_OK &&
 		    zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM, &limit)
@@ -3843,12 +4076,6 @@
 			    B_TRUE);
 			global_scope = B_TRUE;
 		}
-		if (res == Z_OK)
-			bcopy(&old_mcaptab, &in_progress_mcaptab,
-			    sizeof (struct zone_mcaptab));
-		else
-			bzero(&in_progress_mcaptab,
-			    sizeof (in_progress_mcaptab));
 		return;
 	case RT_ADMIN:
 		if ((err = fill_in_admintab(cmd, &old_admintab, B_FALSE))
@@ -4115,9 +4342,8 @@
 	boolean_t autoboot;
 	zone_iptype_t iptype;
 	boolean_t force_set = B_FALSE;
-	size_t physmem_size = sizeof (in_progress_mcaptab.zone_physmem_cap);
 	uint64_t mem_cap, mem_limit;
-	float cap;
+	double cap;
 	char *unitp;
 	struct zone_psettab tmp_psettab;
 	boolean_t arg_err = B_FALSE;
@@ -4219,10 +4445,12 @@
 	 * A nasty expression but not that complicated:
 	 * 1. fs options are simple or list (tested below)
 	 * 2. rctl value's are complex or list (tested below)
+	 * 3. net attr's are complex (tested below)
 	 * Anything else should be simple.
 	 */
 	if (!(res_type == RT_FS && prop_type == PT_OPTIONS) &&
 	    !(res_type == RT_RCTL && prop_type == PT_VALUE) &&
+	    !(res_type == RT_NET && prop_type == PT_NPROP) &&
 	    (pp->pv_type != PROP_VAL_SIMPLE ||
 	    (prop_id = pp->pv_simple) == NULL)) {
 		zerr(gettext("A %s value was expected here."),
@@ -4482,6 +4710,21 @@
 			    prop_id,
 			    sizeof (in_progress_nwiftab.zone_nwif_physical));
 			break;
+		case PT_MAC:
+			(void) strlcpy(in_progress_nwiftab.zone_nwif_mac,
+			    prop_id,
+			    sizeof (in_progress_nwiftab.zone_nwif_mac));
+			break;
+		case PT_VLANID:
+			(void) strlcpy(in_progress_nwiftab.zone_nwif_vlan_id,
+			    prop_id,
+			    sizeof (in_progress_nwiftab.zone_nwif_vlan_id));
+			break;
+		case PT_GNIC:
+			(void) strlcpy(in_progress_nwiftab.zone_nwif_gnic,
+			    prop_id,
+			    sizeof (in_progress_nwiftab.zone_nwif_gnic));
+			break;
 		case PT_DEFROUTER:
 			if (validate_net_address_syntax(prop_id, B_TRUE)
 			    != Z_OK) {
@@ -4492,6 +4735,20 @@
 			    prop_id,
 			    sizeof (in_progress_nwiftab.zone_nwif_defrouter));
 			break;
+		case PT_NPROP:
+			if (pp->pv_type != PROP_VAL_COMPLEX) {
+				zerr(gettext("A %s value was expected here."),
+				    pvt_to_str(PROP_VAL_COMPLEX));
+				saw_error = B_TRUE;
+				return;
+			}
+			zonecfg_free_res_attr_list(
+			    in_progress_nwiftab.zone_nwif_attrp);
+			in_progress_nwiftab.zone_nwif_attrp = NULL;
+			if (!(pp->pv_type == PROP_VAL_LIST &&
+			    pp->pv_list == NULL))
+				add_property(cmd);
+			break;
 		default:
 			zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
 			    B_TRUE);
@@ -4507,6 +4764,20 @@
 			    prop_id,
 			    sizeof (in_progress_devtab.zone_dev_match));
 			break;
+		case PT_NPROP:
+			if (pp->pv_type != PROP_VAL_COMPLEX) {
+				zerr(gettext("A %s value was expected here."),
+				    pvt_to_str(PROP_VAL_COMPLEX));
+				saw_error = B_TRUE;
+				return;
+			}
+			zonecfg_free_res_attr_list(
+			    in_progress_devtab.zone_dev_attrp);
+			in_progress_devtab.zone_dev_attrp = NULL;
+			if (!(pp->pv_type == PROP_VAL_LIST &&
+			    pp->pv_list == NULL))
+				add_property(cmd);
+			break;
 		default:
 			zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
 			    B_TRUE);
@@ -4650,35 +4921,50 @@
 		 * the add_resource() function.
 		 */
 
-		if ((cap = strtof(prop_id, &unitp)) <= 0 || *unitp != '\0' ||
-		    (int)(cap * 100) < 1) {
+		if ((cap = strtod(prop_id, &unitp)) <= 0 || *unitp != '\0' ||
+		    (cap * 100.0) < 1) {
 			zerr(gettext("%s property is out of range."),
 			    pt_to_str(PT_NCPUS));
 			saw_error = B_TRUE;
 			return;
 		}
+		cap *= 100.0;
 
+		/* To avoid rounding issues add .5 to force correct value. */
 		if ((err = zonecfg_set_aliased_rctl(handle, ALIAS_CPUCAP,
-		    (int)(cap * 100))) != Z_OK)
+		    (uint_t)(cap + 0.5))) != Z_OK) {
 			zone_perror(zone, err, B_TRUE);
-		else
+		} else {
 			need_to_commit = B_TRUE;
+		}
 		return;
 	case RT_MCAP:
 		switch (prop_type) {
 		case PT_PHYSICAL:
+			/*
+			 * We have to check if an rctl is allowed here since
+			 * there might already be a rctl defined that blocks
+			 * the alias.
+			 */
+			if (!zonecfg_aliased_rctl_ok(handle,
+			    ALIAS_MAXPHYSMEM)) {
+				zone_perror(pt_to_str(PT_LOCKED),
+				    Z_ALIAS_DISALLOW, B_FALSE);
+				saw_error = B_TRUE;
+				return;
+			}
+
 			if (!zonecfg_valid_memlimit(prop_id, &mem_cap)) {
-				zerr(gettext("A positive number with a "
+				zerr(gettext("A non-negative number with a "
 				    "required scale suffix (K, M, G or T) was "
-				    "expected here."));
+				    "expected\nhere."));
 				saw_error = B_TRUE;
-			} else if (mem_cap < ONE_MB) {
-				zerr(gettext("%s value is too small.  It must "
-				    "be at least 1M."), pt_to_str(PT_PHYSICAL));
-				saw_error = B_TRUE;
 			} else {
-				snprintf(in_progress_mcaptab.zone_physmem_cap,
-				    physmem_size, "%llu", mem_cap);
+				if ((err = zonecfg_set_aliased_rctl(handle,
+				    ALIAS_MAXPHYSMEM, mem_cap)) != Z_OK)
+					zone_perror(zone, err, B_TRUE);
+				else
+					need_to_commit = B_TRUE;
 			}
 			break;
 		case PT_SWAP:
@@ -5031,12 +5317,25 @@
 static void
 output_net(FILE *fp, struct zone_nwiftab *nwiftab)
 {
+	struct zone_res_attrtab *np;
+
 	(void) fprintf(fp, "%s:\n", rt_to_str(RT_NET));
 	output_prop(fp, PT_ADDRESS, nwiftab->zone_nwif_address, B_TRUE);
 	output_prop(fp, PT_ALLOWED_ADDRESS,
 	    nwiftab->zone_nwif_allowed_address, B_TRUE);
-	output_prop(fp, PT_PHYSICAL, nwiftab->zone_nwif_physical, B_TRUE);
 	output_prop(fp, PT_DEFROUTER, nwiftab->zone_nwif_defrouter, B_TRUE);
+	output_prop(fp, PT_GNIC, nwiftab->zone_nwif_gnic, B_TRUE);
+	output_prop(fp, PT_MAC, nwiftab->zone_nwif_mac, B_TRUE);
+	output_prop(fp, PT_PHYSICAL, nwiftab->zone_nwif_physical, B_TRUE);
+	output_prop(fp, PT_VLANID, nwiftab->zone_nwif_vlan_id, B_TRUE);
+
+	for (np = nwiftab->zone_nwif_attrp; np != NULL;
+	    np = np->zone_res_attr_next) {
+		fprintf(fp, "\t%s: (%s=%s,%s=\"%s\")\n",
+		    pt_to_str(PT_NPROP),
+		    pt_to_str(PT_NAME), np->zone_res_attr_name,
+		    pt_to_str(PT_VALUE), np->zone_res_attr_value);
+	}
 }
 
 static void
@@ -5079,8 +5378,18 @@
 static void
 output_dev(FILE *fp, struct zone_devtab *devtab)
 {
+	struct zone_res_attrtab *np;
+
 	(void) fprintf(fp, "%s:\n", rt_to_str(RT_DEVICE));
 	output_prop(fp, PT_MATCH, devtab->zone_dev_match, B_TRUE);
+
+	for (np = devtab->zone_dev_attrp; np != NULL;
+	    np = np->zone_res_attr_next) {
+		fprintf(fp, "\t%s: (%s=%s,%s=\"%s\")\n",
+		    pt_to_str(PT_NPROP),
+		    pt_to_str(PT_NAME), np->zone_res_attr_name,
+		    pt_to_str(PT_VALUE), np->zone_res_attr_value);
+	}
 }
 
 static void
@@ -5339,15 +5648,18 @@
 }
 
 static void
-output_mcap(FILE *fp, struct zone_mcaptab *mcaptab, int showswap,
+output_mcap(FILE *fp, int showphys, uint64_t maxphys, int showswap,
     uint64_t maxswap, int showlocked, uint64_t maxlocked)
 {
 	char buf[128];
 
 	(void) fprintf(fp, "%s:\n", rt_to_str(RT_MCAP));
-	if (mcaptab->zone_physmem_cap[0] != '\0') {
-		bytes_to_units(mcaptab->zone_physmem_cap, buf, sizeof (buf));
-		output_prop(fp, PT_PHYSICAL, buf, B_TRUE);
+
+	if (showphys == Z_OK) {
+		(void) snprintf(buf, sizeof (buf), "%llu", maxphys);
+		bytes_to_units(buf, buf, sizeof (buf));
+		/* Print directly since "physical" also is a net property. */
+		(void) fprintf(fp, "\t[%s: %s]\n", pt_to_str(PT_PHYSICAL), buf);
 	}
 
 	if (showswap == Z_OK) {
@@ -5369,16 +5681,16 @@
 	int res1, res2, res3;
 	uint64_t swap_limit;
 	uint64_t locked_limit;
-	struct zone_mcaptab lookup;
+	uint64_t phys_limit;
 
-	bzero(&lookup, sizeof (lookup));
-	res1 = zonecfg_getmcapent(handle, &lookup);
+	res1 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXPHYSMEM, &phys_limit);
 	res2 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &swap_limit);
 	res3 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM,
 	    &locked_limit);
 
 	if (res1 == Z_OK || res2 == Z_OK || res3 == Z_OK)
-		output_mcap(fp, &lookup, res2, swap_limit, res3, locked_limit);
+		output_mcap(fp, res1, phys_limit, res2, swap_limit,
+		    res3, locked_limit);
 }
 
 static void
@@ -5429,9 +5741,10 @@
 	FILE *fp = stdout;
 	boolean_t need_to_close = B_FALSE;
 	int type;
-	int res1, res2;
+	int res1, res2, res3;
 	uint64_t swap_limit;
 	uint64_t locked_limit;
+	uint64_t phys_limit;
 
 	assert(cmd != NULL);
 
@@ -5479,7 +5792,9 @@
 			    &swap_limit);
 			res2 = zonecfg_get_aliased_rctl(handle,
 			    ALIAS_MAXLOCKEDMEM, &locked_limit);
-			output_mcap(fp, &in_progress_mcaptab, res1, swap_limit,
+			res3 = zonecfg_get_aliased_rctl(handle,
+			    ALIAS_MAXPHYSMEM, &phys_limit);
+			output_mcap(fp, res3, phys_limit, res1, swap_limit,
 			    res2, locked_limit);
 			break;
 		case RT_ADMIN:
@@ -6101,6 +6416,12 @@
 
 	if (save) {
 		if (ret_val == Z_OK) {
+			/*
+			 * If the zone doesn't yet have a debug ID, set one now.
+			 */
+			if (zonecfg_get_did(handle) == -1)
+				zonecfg_set_did(handle);
+
 			if ((ret_val = zonecfg_save(handle)) == Z_OK) {
 				need_to_commit = B_FALSE;
 				(void) strlcpy(revert_zone, zone,
@@ -6275,6 +6596,7 @@
 	int err, arg, res1, res2, res3;
 	uint64_t swap_limit;
 	uint64_t locked_limit;
+	uint64_t phys_limit;
 	uint64_t proc_cap;
 
 	assert(cmd != NULL);
@@ -6578,8 +6900,8 @@
 		break;
 	case RT_MCAP:
 		/* Make sure everything was filled in. */
-		res1 = strlen(in_progress_mcaptab.zone_physmem_cap) == 0 ?
-		    Z_ERR : Z_OK;
+		res1 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXPHYSMEM,
+		    &phys_limit);
 		res2 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP,
 		    &swap_limit);
 		res3 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM,
@@ -6595,11 +6917,6 @@
 
 		/* if phys & locked are both set, verify locked <= phys */
 		if (res1 == Z_OK && res3 == Z_OK) {
-			uint64_t phys_limit;
-			char *endp;
-
-			phys_limit = strtoull(
-			    in_progress_mcaptab.zone_physmem_cap, &endp, 10);
 			if (phys_limit < locked_limit) {
 				zerr(gettext("The %s cap must be less than or "
 				    "equal to the %s cap."),
@@ -6611,23 +6928,6 @@
 		}
 
 		err = Z_OK;
-		if (res1 == Z_OK) {
-			/*
-			 * We could be ending from either an add operation
-			 * or a select operation.  Since all of the properties
-			 * within this resource are optional, we always use
-			 * modify on the mcap entry.  zonecfg_modify_mcap()
-			 * will handle both adding and modifying a memory cap.
-			 */
-			err = zonecfg_modify_mcap(handle, &in_progress_mcaptab);
-		} else if (end_op == CMD_SELECT) {
-			/*
-			 * If we're ending from a select and the physical
-			 * memory cap is empty then the user could have cleared
-			 * the physical cap value, so try to delete the entry.
-			 */
-			(void) zonecfg_delete_mcap(handle);
-		}
 		break;
 	case RT_ADMIN:
 		/* First make sure everything was filled in. */
