summaryrefslogtreecommitdiff
path: root/usr/src/lib/libzonecfg/common
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libzonecfg/common')
-rw-r--r--usr/src/lib/libzonecfg/common/getzoneent.c14
-rw-r--r--usr/src/lib/libzonecfg/common/libzonecfg.c647
-rw-r--r--usr/src/lib/libzonecfg/common/mapfile-vers13
3 files changed, 539 insertions, 135 deletions
diff --git a/usr/src/lib/libzonecfg/common/getzoneent.c b/usr/src/lib/libzonecfg/common/getzoneent.c
index 8155f7272a..76664fcc92 100644
--- a/usr/src/lib/libzonecfg/common/getzoneent.c
+++ b/usr/src/lib/libzonecfg/common/getzoneent.c
@@ -403,14 +403,6 @@ putzoneent(struct zoneent *ze, zoneent_op_t operation)
*/
if (ze->zone_state >= 0) {
zone_state = zone_state_str(ze->zone_state);
-
- /*
- * If the caller is uninstalling this zone,
- * then wipe out the uuid. The zone's contents
- * are no longer known.
- */
- if (ze->zone_state < ZONE_STATE_INSTALLED)
- zone_uuid = "";
}
/* If a new name is supplied, use it. */
@@ -419,6 +411,12 @@ putzoneent(struct zoneent *ze, zoneent_op_t operation)
if (ze->zone_path[0] != '\0')
zone_path = ze->zone_path;
+
+ /* If new UUID provided, replace it */
+ if (!uuid_is_null(ze->zone_uuid)) {
+ uuid_unparse(ze->zone_uuid, uuidstr);
+ zone_uuid = uuidstr;
+ }
break;
case PZE_REMOVE:
diff --git a/usr/src/lib/libzonecfg/common/libzonecfg.c b/usr/src/lib/libzonecfg/common/libzonecfg.c
index 6ae73b9f3b..3162390931 100644
--- a/usr/src/lib/libzonecfg/common/libzonecfg.c
+++ b/usr/src/lib/libzonecfg/common/libzonecfg.c
@@ -22,6 +22,7 @@
/*
* Copyright 2014 Gary Mills
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2015, Joyent Inc. All rights reserved.
*/
#include <libsysevent.h>
@@ -78,6 +79,8 @@
#define ZONE_EVENT_PING_SUBCLASS "ping"
#define ZONE_EVENT_PING_PUBLISHER "solaris"
+#define DEBUGID_FILE "/etc/zones/did.txt"
+
/* Hard-code the DTD element/attribute/entity names just once, here. */
#define DTD_ELEM_ATTR (const xmlChar *) "attr"
#define DTD_ELEM_COMMENT (const xmlChar *) "comment"
@@ -85,6 +88,7 @@
#define DTD_ELEM_FS (const xmlChar *) "filesystem"
#define DTD_ELEM_FSOPTION (const xmlChar *) "fsoption"
#define DTD_ELEM_NET (const xmlChar *) "network"
+#define DTD_ELEM_NETATTR (const xmlChar *) "net-attr"
#define DTD_ELEM_RCTL (const xmlChar *) "rctl"
#define DTD_ELEM_RCTLVALUE (const xmlChar *) "rctl-value"
#define DTD_ELEM_ZONE (const xmlChar *) "zone"
@@ -104,10 +108,12 @@
#define DTD_ATTR_IPTYPE (const xmlChar *) "ip-type"
#define DTD_ATTR_DEFROUTER (const xmlChar *) "defrouter"
#define DTD_ATTR_DIR (const xmlChar *) "directory"
+#define DTD_ATTR_GNIC (const xmlChar *) "global-nic"
#define DTD_ATTR_LIMIT (const xmlChar *) "limit"
#define DTD_ATTR_LIMITPRIV (const xmlChar *) "limitpriv"
#define DTD_ATTR_BOOTARGS (const xmlChar *) "bootargs"
#define DTD_ATTR_SCHED (const xmlChar *) "scheduling-class"
+#define DTD_ATTR_MAC (const xmlChar *) "mac-addr"
#define DTD_ATTR_MATCH (const xmlChar *) "match"
#define DTD_ATTR_NAME (const xmlChar *) "name"
#define DTD_ATTR_PHYSICAL (const xmlChar *) "physical"
@@ -117,6 +123,7 @@
#define DTD_ATTR_SPECIAL (const xmlChar *) "special"
#define DTD_ATTR_TYPE (const xmlChar *) "type"
#define DTD_ATTR_VALUE (const xmlChar *) "value"
+#define DTD_ATTR_VLANID (const xmlChar *) "vlan-id"
#define DTD_ATTR_ZONEPATH (const xmlChar *) "zonepath"
#define DTD_ATTR_NCPU_MIN (const xmlChar *) "ncpu_min"
#define DTD_ATTR_NCPU_MAX (const xmlChar *) "ncpu_max"
@@ -129,6 +136,7 @@
#define DTD_ATTR_MODE (const xmlChar *) "mode"
#define DTD_ATTR_ACL (const xmlChar *) "acl"
#define DTD_ATTR_BRAND (const xmlChar *) "brand"
+#define DTD_ATTR_DID (const xmlChar *) "debugid"
#define DTD_ATTR_HOSTID (const xmlChar *) "hostid"
#define DTD_ATTR_USER (const xmlChar *) "user"
#define DTD_ATTR_AUTHS (const xmlChar *) "auths"
@@ -175,9 +183,12 @@ static struct alias {
{ALIAS_MAXSEMIDS, "zone.max-sem-ids", "privileged", "deny", 0},
{ALIAS_MAXLOCKEDMEM, "zone.max-locked-memory", "privileged", "deny", 0},
{ALIAS_MAXSWAP, "zone.max-swap", "privileged", "deny", 0},
+ {ALIAS_MAXPHYSMEM, "zone.max-physical-memory", "privileged", "deny",
+ 1048576},
{ALIAS_SHARES, "zone.cpu-shares", "privileged", "none", 0},
{ALIAS_CPUCAP, "zone.cpu-cap", "privileged", "deny", 0},
{ALIAS_MAXPROCS, "zone.max-processes", "privileged", "deny", 100},
+ {ALIAS_ZFSPRI, "zone.zfs-io-priority", "privileged", "none", 0},
{NULL, NULL, NULL, NULL, 0}
};
@@ -1271,7 +1282,6 @@ zonecfg_save_impl(zone_dochandle_t handle, char *filename)
/*
* Try to restore from our backup.
*/
- (void) unlink(filename);
(void) rename(bakfile, filename);
} else {
/*
@@ -2065,6 +2075,32 @@ zonecfg_ifname_exists(sa_family_t af, char *ifname)
}
/*
+ * Turn an addr that looks like f:2:0:44:5:6C into 0f:02:00:44:05:6c
+ * We're expecting a dst of at least MAXMACADDRLEN size here.
+ */
+static void
+normalize_mac_addr(char *dst, const char *src, int len)
+{
+ char *p, *e, *sep = "";
+ long n;
+ char buf[MAXMACADDRLEN], tmp[4];
+
+ *dst = '\0';
+ (void) strlcpy(buf, src, sizeof (buf));
+ p = strtok(buf, ":");
+ while (p != NULL) {
+ n = strtol(p, &e, 16);
+ if (*e != NULL || n > 0xff)
+ return;
+ (void) snprintf(tmp, sizeof (tmp), "%s%02x", sep, n);
+ (void) strlcat(dst, tmp, len);
+
+ sep = ":";
+ p = strtok(NULL, ":");
+ }
+}
+
+/*
* Determines whether there is a net resource with the physical interface, IP
* address, and default router specified by 'tabptr' in the zone configuration
* to which 'handle' refers. 'tabptr' must have an interface, an address, a
@@ -2083,13 +2119,18 @@ zonecfg_ifname_exists(sa_family_t af, char *ifname)
int
zonecfg_lookup_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
{
- xmlNodePtr cur;
+ xmlNodePtr cur, val;
xmlNodePtr firstmatch;
int err;
char address[INET6_ADDRSTRLEN];
char physical[LIFNAMSIZ];
+ char mac[MAXMACADDRLEN];
+ char norm_mac[MAXMACADDRLEN];
+ char gnic[LIFNAMSIZ];
size_t addrspec; /* nonzero if tabptr has IP addr */
size_t physspec; /* nonzero if tabptr has interface */
+ size_t macspec; /* nonzero if tabptr has mac addr */
+ size_t gnicspec; /* nonzero if tabptr has gnic */
size_t defrouterspec; /* nonzero if tabptr has def. router */
size_t allowed_addrspec;
zone_iptype_t iptype;
@@ -2101,17 +2142,20 @@ zonecfg_lookup_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
* Determine the fields that will be searched. There must be at least
* one.
*
- * zone_nwif_address, zone_nwif_physical, and zone_nwif_defrouter are
+ * zone_nwif_address, zone_nwif_physical, zone_nwif_defrouter,
+ * zone_nwif_mac, zone_nwif_vlan_id and zone_nwif_gnic are
* arrays, so no NULL checks are necessary.
*/
addrspec = strlen(tabptr->zone_nwif_address);
physspec = strlen(tabptr->zone_nwif_physical);
+ macspec = strlen(tabptr->zone_nwif_mac);
+ gnicspec = strlen(tabptr->zone_nwif_gnic);
defrouterspec = strlen(tabptr->zone_nwif_defrouter);
allowed_addrspec = strlen(tabptr->zone_nwif_allowed_address);
if (addrspec != 0 && allowed_addrspec != 0)
return (Z_INVAL); /* can't specify both */
if (addrspec == 0 && physspec == 0 && defrouterspec == 0 &&
- allowed_addrspec == 0)
+ allowed_addrspec == 0 && macspec == 0 && gnicspec == 0)
return (Z_INSUFFICIENT_SPEC);
if ((err = operation_prep(handle)) != Z_OK)
@@ -2138,6 +2182,19 @@ zonecfg_lookup_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
physical, sizeof (physical)) != Z_OK ||
strcmp(tabptr->zone_nwif_physical, physical) != 0))
continue;
+ if (iptype == ZS_EXCLUSIVE && macspec != 0) {
+ if (fetchprop(cur, DTD_ATTR_MAC, mac, sizeof (mac)) !=
+ Z_OK)
+ continue;
+ normalize_mac_addr(norm_mac, mac, sizeof (norm_mac));
+ if (strcmp(tabptr->zone_nwif_mac, norm_mac) != 0)
+ continue;
+ }
+ if (iptype == ZS_EXCLUSIVE && gnicspec != 0 &&
+ (fetchprop(cur, DTD_ATTR_GNIC, gnic,
+ sizeof (gnic)) != Z_OK ||
+ strcmp(tabptr->zone_nwif_gnic, gnic) != 0))
+ continue;
if (iptype == ZS_SHARED && addrspec != 0 &&
(fetchprop(cur, DTD_ATTR_ADDRESS, address,
sizeof (address)) != Z_OK ||
@@ -2180,6 +2237,21 @@ zonecfg_lookup_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
return (err);
if (iptype == ZS_EXCLUSIVE &&
+ (err = fetchprop(cur, DTD_ATTR_MAC, tabptr->zone_nwif_mac,
+ sizeof (tabptr->zone_nwif_mac))) != Z_OK)
+ return (err);
+
+ if (iptype == ZS_EXCLUSIVE &&
+ (err = fetchprop(cur, DTD_ATTR_VLANID, tabptr->zone_nwif_vlan_id,
+ sizeof (tabptr->zone_nwif_vlan_id))) != Z_OK)
+ return (err);
+
+ if (iptype == ZS_EXCLUSIVE &&
+ (err = fetchprop(cur, DTD_ATTR_GNIC, tabptr->zone_nwif_gnic,
+ sizeof (tabptr->zone_nwif_gnic))) != Z_OK)
+ return (err);
+
+ if (iptype == ZS_EXCLUSIVE &&
(err = fetchprop(cur, DTD_ATTR_ALLOWED_ADDRESS,
tabptr->zone_nwif_allowed_address,
sizeof (tabptr->zone_nwif_allowed_address))) != Z_OK)
@@ -2190,13 +2262,40 @@ zonecfg_lookup_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
sizeof (tabptr->zone_nwif_defrouter))) != Z_OK)
return (err);
+ tabptr->zone_nwif_attrp = NULL;
+ for (val = cur->xmlChildrenNode; val != NULL; val = val->next) {
+ struct zone_res_attrtab *valptr;
+
+ valptr = (struct zone_res_attrtab *)malloc(
+ sizeof (struct zone_res_attrtab));
+ if (valptr == NULL)
+ return (Z_NOMEM);
+
+ valptr->zone_res_attr_name[0] =
+ valptr->zone_res_attr_value[0] = '\0';
+ if (zonecfg_add_res_attr(&(tabptr->zone_nwif_attrp), valptr)
+ != Z_OK) {
+ free(valptr);
+ break;
+ }
+
+ if ((fetchprop(val, DTD_ATTR_NAME, valptr->zone_res_attr_name,
+ sizeof (valptr->zone_res_attr_name)) != Z_OK))
+ break;
+ if ((fetchprop(val, DTD_ATTR_VALUE,
+ valptr->zone_res_attr_value,
+ sizeof (valptr->zone_res_attr_value)) != Z_OK))
+ break;
+ }
+
return (Z_OK);
}
static int
zonecfg_add_nwif_core(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
{
- xmlNodePtr newnode, cur = handle->zone_dh_cur;
+ xmlNodePtr newnode, cur = handle->zone_dh_cur, valnode;
+ struct zone_res_attrtab *valptr;
int err;
newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_NET, NULL);
@@ -2212,13 +2311,40 @@ zonecfg_add_nwif_core(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
tabptr->zone_nwif_physical)) != Z_OK)
return (err);
/*
- * Do not add this property when it is not set, for backwards
- * compatibility and because it is optional.
+ * Do not add these properties when they are not set, for backwards
+ * compatibility and because they are optional.
*/
if ((strlen(tabptr->zone_nwif_defrouter) > 0) &&
((err = newprop(newnode, DTD_ATTR_DEFROUTER,
tabptr->zone_nwif_defrouter)) != Z_OK))
return (err);
+ if (strlen(tabptr->zone_nwif_mac) > 0 &&
+ (err = newprop(newnode, DTD_ATTR_MAC,
+ tabptr->zone_nwif_mac)) != Z_OK)
+ return (err);
+ if (strlen(tabptr->zone_nwif_vlan_id) > 0 &&
+ (err = newprop(newnode, DTD_ATTR_VLANID,
+ tabptr->zone_nwif_vlan_id)) != Z_OK)
+ return (err);
+ if (strlen(tabptr->zone_nwif_gnic) > 0 &&
+ (err = newprop(newnode, DTD_ATTR_GNIC,
+ tabptr->zone_nwif_gnic)) != Z_OK)
+ return (err);
+
+ for (valptr = tabptr->zone_nwif_attrp; valptr != NULL;
+ valptr = valptr->zone_res_attr_next) {
+ valnode = xmlNewTextChild(newnode, NULL, DTD_ELEM_NETATTR,
+ NULL);
+ err = newprop(valnode, DTD_ATTR_NAME,
+ valptr->zone_res_attr_name);
+ if (err != Z_OK)
+ return (err);
+ err = newprop(valnode, DTD_ATTR_VALUE,
+ valptr->zone_res_attr_value);
+ if (err != Z_OK)
+ return (err);
+ }
+
return (Z_OK);
}
@@ -2243,7 +2369,8 @@ static int
zonecfg_delete_nwif_core(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
{
xmlNodePtr cur = handle->zone_dh_cur;
- boolean_t addr_match, phys_match, allowed_addr_match;
+ boolean_t addr_match, phys_match, allowed_addr_match, mac_match,
+ gnic_match;
for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
if (xmlStrcmp(cur->name, DTD_ELEM_NET))
@@ -2255,8 +2382,13 @@ zonecfg_delete_nwif_core(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
tabptr->zone_nwif_allowed_address);
phys_match = match_prop(cur, DTD_ATTR_PHYSICAL,
tabptr->zone_nwif_physical);
+ mac_match = match_prop(cur, DTD_ATTR_MAC,
+ tabptr->zone_nwif_mac);
+ gnic_match = match_prop(cur, DTD_ATTR_GNIC,
+ tabptr->zone_nwif_gnic);
- if (addr_match && allowed_addr_match && phys_match) {
+ if (((addr_match && allowed_addr_match) || mac_match ||
+ gnic_match) && phys_match) {
xmlUnlinkNode(cur);
xmlFreeNode(cur);
return (Z_OK);
@@ -2305,6 +2437,58 @@ zonecfg_modify_nwif(
return (Z_OK);
}
+void
+zonecfg_free_res_attr_list(struct zone_res_attrtab *valtab)
+{
+ if (valtab == NULL)
+ return;
+ zonecfg_free_res_attr_list(valtab->zone_res_attr_next);
+ free(valtab);
+}
+
+int
+zonecfg_add_res_attr(struct zone_res_attrtab **headptr,
+ struct zone_res_attrtab *valtabptr)
+{
+ struct zone_res_attrtab *last, *old, *new;
+
+ last = *headptr;
+ for (old = last; old != NULL; old = old->zone_res_attr_next)
+ last = old; /* walk to the end of the list */
+ new = valtabptr; /* alloc'd by caller */
+ new->zone_res_attr_next = NULL;
+ if (last == NULL)
+ *headptr = new;
+ else
+ last->zone_res_attr_next = new;
+ return (Z_OK);
+}
+
+int
+zonecfg_remove_res_attr(struct zone_res_attrtab **headptr,
+ struct zone_res_attrtab *valtabptr)
+{
+ struct zone_res_attrtab *last, *this, *next;
+
+ last = *headptr;
+ for (this = last; this != NULL; this = this->zone_res_attr_next) {
+ if (strcmp(this->zone_res_attr_name,
+ valtabptr->zone_res_attr_name) == 0 &&
+ strcmp(this->zone_res_attr_value,
+ valtabptr->zone_res_attr_value) == 0) {
+ next = this->zone_res_attr_next;
+ if (this == *headptr)
+ *headptr = next;
+ else
+ last->zone_res_attr_next = next;
+ free(this);
+ return (Z_OK);
+ } else
+ last = this;
+ }
+ return (Z_NO_PROPERTY_ID);
+}
+
/*
* Must be a comma-separated list of alpha-numeric file system names.
*/
@@ -2454,7 +2638,7 @@ zonecfg_set_hostid(zone_dochandle_t handle, const char *hostidp)
int
zonecfg_lookup_dev(zone_dochandle_t handle, struct zone_devtab *tabptr)
{
- xmlNodePtr cur, firstmatch;
+ xmlNodePtr cur, val, firstmatch;
int err;
char match[MAXPATHLEN];
@@ -2499,13 +2683,40 @@ zonecfg_lookup_dev(zone_dochandle_t handle, struct zone_devtab *tabptr)
sizeof (tabptr->zone_dev_match))) != Z_OK)
return (err);
+ tabptr->zone_dev_attrp = NULL;
+ for (val = cur->xmlChildrenNode; val != NULL; val = val->next) {
+ struct zone_res_attrtab *valptr;
+
+ valptr = (struct zone_res_attrtab *)malloc(
+ sizeof (struct zone_res_attrtab));
+ if (valptr == NULL)
+ return (Z_NOMEM);
+
+ valptr->zone_res_attr_name[0] =
+ valptr->zone_res_attr_value[0] = '\0';
+ if (zonecfg_add_res_attr(&(tabptr->zone_dev_attrp), valptr)
+ != Z_OK) {
+ free(valptr);
+ break;
+ }
+
+ if ((fetchprop(val, DTD_ATTR_NAME, valptr->zone_res_attr_name,
+ sizeof (valptr->zone_res_attr_name)) != Z_OK))
+ break;
+ if ((fetchprop(val, DTD_ATTR_VALUE,
+ valptr->zone_res_attr_value,
+ sizeof (valptr->zone_res_attr_value)) != Z_OK))
+ break;
+ }
+
return (Z_OK);
}
static int
zonecfg_add_dev_core(zone_dochandle_t handle, struct zone_devtab *tabptr)
{
- xmlNodePtr newnode, cur = handle->zone_dh_cur;
+ xmlNodePtr newnode, cur = handle->zone_dh_cur, valnode;
+ struct zone_res_attrtab *valptr;
int err;
newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_DEVICE, NULL);
@@ -2514,6 +2725,21 @@ zonecfg_add_dev_core(zone_dochandle_t handle, struct zone_devtab *tabptr)
tabptr->zone_dev_match)) != Z_OK)
return (err);
+ for (valptr = tabptr->zone_dev_attrp; valptr != NULL;
+ valptr = valptr->zone_res_attr_next) {
+ valnode = xmlNewTextChild(newnode, NULL, DTD_ELEM_NETATTR,
+ NULL);
+ err = newprop(valnode, DTD_ATTR_NAME,
+ valptr->zone_res_attr_name);
+ if (err != Z_OK)
+ return (err);
+ err = newprop(valnode, DTD_ATTR_VALUE,
+ valptr->zone_res_attr_value);
+ if (err != Z_OK)
+ return (err);
+ }
+
+
return (Z_OK);
}
@@ -4573,7 +4799,7 @@ get_pool_sched_class(char *poolname, char *class, int clsize)
pool_conf_t *poolconf;
pool_t *pool;
pool_elem_t *pe;
- pool_value_t *pv = pool_value_alloc();
+ pool_value_t *pv;
const char *sched_str;
if (pool_get_status(&status) != PO_SUCCESS || status != POOL_ENABLED)
@@ -4594,15 +4820,23 @@ get_pool_sched_class(char *poolname, char *class, int clsize)
return (Z_NO_POOL);
}
+ if ((pv = pool_value_alloc()) == NULL) {
+ (void) pool_conf_close(poolconf);
+ pool_conf_free(poolconf);
+ return (Z_NO_POOL);
+ }
+
pe = pool_to_elem(poolconf, pool);
if (pool_get_property(poolconf, pe, "pool.scheduler", pv) !=
POC_STRING) {
(void) pool_conf_close(poolconf);
+ pool_value_free(pv);
pool_conf_free(poolconf);
return (Z_NO_ENTRY);
}
(void) pool_value_get_string(pv, &sched_str);
(void) pool_conf_close(poolconf);
+ pool_value_free(pv);
pool_conf_free(poolconf);
if (strlcpy(class, sched_str, clsize) >= clsize)
return (Z_TOO_BIG);
@@ -4711,7 +4945,8 @@ zonecfg_setnwifent(zone_dochandle_t handle)
int
zonecfg_getnwifent(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
{
- xmlNodePtr cur;
+ xmlNodePtr cur, val;
+ struct zone_res_attrtab *valptr;
int err;
if (handle == NULL)
@@ -4747,6 +4982,24 @@ zonecfg_getnwifent(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
return (err);
}
+ if ((err = fetchprop(cur, DTD_ATTR_MAC, tabptr->zone_nwif_mac,
+ sizeof (tabptr->zone_nwif_mac))) != Z_OK) {
+ handle->zone_dh_cur = handle->zone_dh_top;
+ return (err);
+ }
+
+ if ((err = fetchprop(cur, DTD_ATTR_VLANID, tabptr->zone_nwif_vlan_id,
+ sizeof (tabptr->zone_nwif_vlan_id))) != Z_OK) {
+ handle->zone_dh_cur = handle->zone_dh_top;
+ return (err);
+ }
+
+ if ((err = fetchprop(cur, DTD_ATTR_GNIC, tabptr->zone_nwif_gnic,
+ sizeof (tabptr->zone_nwif_gnic))) != Z_OK) {
+ handle->zone_dh_cur = handle->zone_dh_top;
+ return (err);
+ }
+
if ((err = fetchprop(cur, DTD_ATTR_DEFROUTER,
tabptr->zone_nwif_defrouter,
sizeof (tabptr->zone_nwif_defrouter))) != Z_OK) {
@@ -4754,6 +5007,29 @@ zonecfg_getnwifent(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
return (err);
}
+ tabptr->zone_nwif_attrp = NULL;
+ for (val = cur->xmlChildrenNode; val != NULL; val = val->next) {
+ valptr = (struct zone_res_attrtab *)malloc(
+ sizeof (struct zone_res_attrtab));
+ if (valptr == NULL)
+ return (Z_NOMEM);
+
+ valptr->zone_res_attr_name[0] =
+ valptr->zone_res_attr_value[0] = '\0';
+ if (zonecfg_add_res_attr(&(tabptr->zone_nwif_attrp), valptr)
+ != Z_OK) {
+ free(valptr);
+ break;
+ }
+
+ if (fetchprop(val, DTD_ATTR_NAME, valptr->zone_res_attr_name,
+ sizeof (valptr->zone_res_attr_name)) != Z_OK)
+ break;
+ if (fetchprop(val, DTD_ATTR_VALUE, valptr->zone_res_attr_value,
+ sizeof (valptr->zone_res_attr_value)) != Z_OK)
+ break;
+ }
+
handle->zone_dh_cur = cur->next;
return (Z_OK);
}
@@ -4773,7 +5049,7 @@ zonecfg_setdevent(zone_dochandle_t handle)
int
zonecfg_getdevent(zone_dochandle_t handle, struct zone_devtab *tabptr)
{
- xmlNodePtr cur;
+ xmlNodePtr cur, val;
int err;
if (handle == NULL)
@@ -4796,6 +5072,31 @@ zonecfg_getdevent(zone_dochandle_t handle, struct zone_devtab *tabptr)
return (err);
}
+ tabptr->zone_dev_attrp = NULL;
+ for (val = cur->xmlChildrenNode; val != NULL; val = val->next) {
+ struct zone_res_attrtab *valptr;
+
+ valptr = (struct zone_res_attrtab *)malloc(
+ sizeof (struct zone_res_attrtab));
+ if (valptr == NULL)
+ return (Z_NOMEM);
+
+ valptr->zone_res_attr_name[0] =
+ valptr->zone_res_attr_value[0] = '\0';
+ if (zonecfg_add_res_attr(&(tabptr->zone_dev_attrp), valptr)
+ != Z_OK) {
+ free(valptr);
+ break;
+ }
+
+ if ((fetchprop(val, DTD_ATTR_NAME, valptr->zone_res_attr_name,
+ sizeof (valptr->zone_res_attr_name)) != Z_OK))
+ break;
+ if ((fetchprop(val, DTD_ATTR_VALUE, valptr->zone_res_attr_value,
+ sizeof (valptr->zone_res_attr_value)) != Z_OK))
+ break;
+ }
+
handle->zone_dh_cur = cur->next;
return (Z_OK);
}
@@ -5524,6 +5825,164 @@ zone_get_brand(char *zone_name, char *brandname, size_t rp_sz)
}
/*
+ * Atomically get a new zone_did value. The currently allocated value
+ * is stored in /etc/zones/did.txt. Lock the file, read the current value,
+ * increment, save the new value and unlock the file. Return the new value
+ * or -1 if there was an error. The ID namespace is large enough that we
+ * don't worry about recycling an ID when a zone is deleted.
+ */
+static zoneid_t
+new_zone_did()
+{
+ int fd;
+ int len;
+ int val;
+ struct flock lck;
+ char buf[80];
+
+ if ((fd = open(DEBUGID_FILE, O_RDWR | O_CREAT,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0) {
+ perror("new_zone_did open failed");
+ return (-1);
+ }
+
+ /* Initialize the lock. */
+ lck.l_whence = SEEK_SET;
+ lck.l_start = 0;
+ lck.l_len = 0;
+
+ /* Wait until we acquire an exclusive lock on the file. */
+ lck.l_type = F_WRLCK;
+ if (fcntl(fd, F_SETLKW, &lck) == -1) {
+ perror("new_zone_did lock failed");
+ (void) close(fd);
+ return (-1);
+ }
+
+ /* Get currently allocated value */
+ len = read(fd, buf, sizeof (buf));
+ if (len == -1) {
+ perror("new_zone_did read failed");
+ val = -1;
+ } else {
+ if (lseek(fd, 0L, SEEK_SET) == -1) {
+ perror("new_zone_did seek failed");
+ val = -1;
+ } else {
+ if (len == 0) {
+ /* Just created the file, initialize at 1 */
+ val = 1;
+ } else {
+ val = atoi(buf);
+ val++;
+ }
+
+ (void) snprintf(buf, sizeof (buf), "%d\n", val);
+ len = strlen(buf);
+
+ /* Save newly allocated value */
+ if (write(fd, buf, len) == -1) {
+ perror("new_zone_did write failed");
+ val = -1;
+ }
+ }
+ }
+
+ /* Release the file lock. */
+ lck.l_type = F_UNLCK;
+ if (fcntl(fd, F_SETLK, &lck) == -1) {
+ perror("new_zone_did unlock failed");
+ val = -1;
+ }
+
+ if (close(fd) != 0)
+ perror("new_zone_did close failed");
+
+ return (val);
+}
+
+/*
+ * Called by zoneadmd to get the zone's debug ID.
+ * If the zone doesn't already have an ID, a new one is generated and
+ * persistently saved onto the zone. Normally either zoneadm or zonecfg
+ * will assign a new ID for the zone, so zoneadmd should never have to
+ * generate one, but we also handle that here just to be paranoid.
+ */
+zoneid_t
+zone_get_did(char *zone_name)
+{
+ int res;
+ zoneid_t new_did;
+ zone_dochandle_t handle;
+ char did_str[80];
+
+ if ((handle = zonecfg_init_handle()) == NULL)
+ return (getpid());
+
+ if (zonecfg_get_handle((char *)zone_name, handle) != Z_OK)
+ return (getpid());
+
+ res = getrootattr(handle, DTD_ATTR_DID, did_str, sizeof (did_str));
+
+ /* If the zone already has an assigned debug ID, return it. */
+ if (res == Z_OK && did_str[0] != '\0') {
+ zonecfg_fini_handle(handle);
+ return (atoi(did_str));
+ }
+
+ /*
+ * The zone doesn't have an assigned debug ID yet, generate one and
+ * save it as part of the zone definition.
+ */
+ if ((new_did = new_zone_did()) == -1) {
+ /*
+ * We should really never hit this block of code.
+ * Generating a new ID failed for some reason. Use the current
+ * pid as a temporary ID so that the zone can continue to boot
+ * but we don't persistently save this temporary ID on the zone.
+ */
+ zonecfg_fini_handle(handle);
+ return (getpid());
+ }
+
+ /* Now persistently save this new ID onto the zone. */
+ (void) snprintf(did_str, sizeof (did_str), "%d", new_did);
+ (void) setrootattr(handle, DTD_ATTR_DID, did_str);
+ (void) zonecfg_save(handle);
+
+ zonecfg_fini_handle(handle);
+ return (new_did);
+}
+
+zoneid_t
+zonecfg_get_did(zone_dochandle_t handle)
+{
+ char did_str[80];
+ int err;
+ zoneid_t did;
+
+ err = getrootattr(handle, DTD_ATTR_DID, did_str, sizeof (did_str));
+ if (err == Z_OK && did_str[0] != '\0')
+ did = atoi(did_str);
+ else
+ did = -1;
+
+ return (did);
+}
+
+void
+zonecfg_set_did(zone_dochandle_t handle)
+{
+ zoneid_t new_did;
+ char did_str[80];
+
+ if ((new_did = new_zone_did()) == -1)
+ return;
+ (void) snprintf(did_str, sizeof (did_str), "%d", new_did);
+ (void) setrootattr(handle, DTD_ATTR_DID, did_str);
+}
+
+/*
* Return the appropriate root for the active /dev.
* For normal zone, the path is $ZONEPATH/root;
* for scratch zone, the dev path is $ZONEPATH/lu.
@@ -5806,6 +6265,30 @@ zonecfg_get_uuid(const char *zonename, uuid_t uuid)
}
/*
+ * Changes a zone's UUID to the given value. Returns an error if the UUID is
+ * malformed or if the zone cannot be located.
+ */
+int
+zonecfg_set_uuid(const char *zonename, const char *zonepath,
+ const char *uuid)
+{
+ int err;
+ struct zoneent ze;
+
+ bzero(&ze, sizeof (ze));
+ ze.zone_state = -1; /* Preserve existing state in index */
+ (void) strlcpy(ze.zone_name, zonename, sizeof (ze.zone_name));
+ (void) strlcpy(ze.zone_path, zonepath, sizeof (ze.zone_path));
+ if (uuid_parse((char *)uuid, ze.zone_uuid) == -1)
+ return (Z_INVALID_PROPERTY);
+
+ if ((err = putzoneent(&ze, PZE_MODIFY)) != Z_OK)
+ return (err);
+
+ return (Z_OK);
+}
+
+/*
* File-system convenience functions.
*/
boolean_t
@@ -6839,131 +7322,49 @@ zonecfg_getpsetent(zone_dochandle_t handle, struct zone_psettab *tabptr)
return (err);
}
-static int
-add_mcap(zone_dochandle_t handle, struct zone_mcaptab *tabptr)
-{
- xmlNodePtr newnode, cur = handle->zone_dh_cur;
- int err;
-
- newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_MCAP, NULL);
- if ((err = newprop(newnode, DTD_ATTR_PHYSCAP, tabptr->zone_physmem_cap))
- != Z_OK)
- return (err);
-
- return (Z_OK);
-}
-
-int
-zonecfg_delete_mcap(zone_dochandle_t handle)
-{
- int err;
- xmlNodePtr cur = handle->zone_dh_cur;
-
- if ((err = operation_prep(handle)) != Z_OK)
- return (err);
-
- for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
- if (xmlStrcmp(cur->name, DTD_ELEM_MCAP) != 0)
- continue;
-
- xmlUnlinkNode(cur);
- xmlFreeNode(cur);
- return (Z_OK);
- }
- return (Z_NO_RESOURCE_ID);
-}
-
-int
-zonecfg_modify_mcap(zone_dochandle_t handle, struct zone_mcaptab *tabptr)
-{
- int err;
-
- if (tabptr == NULL)
- return (Z_INVAL);
-
- err = zonecfg_delete_mcap(handle);
- /* it is ok if there is no mcap entry */
- if (err != Z_OK && err != Z_NO_RESOURCE_ID)
- return (err);
-
- if ((err = add_mcap(handle, tabptr)) != Z_OK)
- return (err);
-
- return (Z_OK);
-}
-
+/*
+ * Cleanup obsolete constructs in the configuration.
+ * Return true of the config has been updated and must be commited.
+ */
int
-zonecfg_lookup_mcap(zone_dochandle_t handle, struct zone_mcaptab *tabptr)
+zonecfg_fix_obsolete(zone_dochandle_t handle)
{
+ int res = 0;
+ int add_physmem_rctl = 0;
xmlNodePtr cur;
- int err;
-
- if (tabptr == NULL)
- return (Z_INVAL);
+ char zone_physmem_cap[MAXNAMELEN];
- if ((err = operation_prep(handle)) != Z_OK)
- return (err);
+ if (operation_prep(handle) != Z_OK)
+ return (res);
+ /*
+ * If an obsolete mcap entry exists, convert it to the rctl.
+ */
cur = handle->zone_dh_cur;
for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
if (xmlStrcmp(cur->name, DTD_ELEM_MCAP) != 0)
continue;
- if ((err = fetchprop(cur, DTD_ATTR_PHYSCAP,
- tabptr->zone_physmem_cap,
- sizeof (tabptr->zone_physmem_cap))) != Z_OK) {
- handle->zone_dh_cur = handle->zone_dh_top;
- return (err);
+
+ if (fetchprop(cur, DTD_ATTR_PHYSCAP,
+ zone_physmem_cap, sizeof (zone_physmem_cap)) == Z_OK) {
+ res = 1;
+ add_physmem_rctl = 1;
}
- return (Z_OK);
+ xmlUnlinkNode(cur);
+ xmlFreeNode(cur);
+ break;
}
- return (Z_NO_ENTRY);
-}
-
-static int
-getmcapent_core(zone_dochandle_t handle, struct zone_mcaptab *tabptr)
-{
- xmlNodePtr cur;
- int err;
-
- if (handle == NULL)
- return (Z_INVAL);
-
- if ((cur = handle->zone_dh_cur) == NULL)
- return (Z_NO_ENTRY);
-
- for (; cur != NULL; cur = cur->next)
- if (xmlStrcmp(cur->name, DTD_ELEM_MCAP) == 0)
- break;
- if (cur == NULL) {
- handle->zone_dh_cur = handle->zone_dh_top;
- return (Z_NO_ENTRY);
- }
+ if (add_physmem_rctl) {
+ uint64_t cap;
+ char *endp;
- if ((err = fetchprop(cur, DTD_ATTR_PHYSCAP, tabptr->zone_physmem_cap,
- sizeof (tabptr->zone_physmem_cap))) != Z_OK) {
- handle->zone_dh_cur = handle->zone_dh_top;
- return (err);
+ cap = strtoull(zone_physmem_cap, &endp, 10);
+ (void) zonecfg_set_aliased_rctl(handle, ALIAS_MAXPHYSMEM, cap);
}
- handle->zone_dh_cur = cur->next;
- return (Z_OK);
-}
-
-int
-zonecfg_getmcapent(zone_dochandle_t handle, struct zone_mcaptab *tabptr)
-{
- int err;
-
- if ((err = zonecfg_setent(handle)) != Z_OK)
- return (err);
-
- err = getmcapent_core(handle, tabptr);
-
- (void) zonecfg_endent(handle);
-
- return (err);
+ return (res);
}
/*
diff --git a/usr/src/lib/libzonecfg/common/mapfile-vers b/usr/src/lib/libzonecfg/common/mapfile-vers
index b908a28174..7265b06a1f 100644
--- a/usr/src/lib/libzonecfg/common/mapfile-vers
+++ b/usr/src/lib/libzonecfg/common/mapfile-vers
@@ -20,6 +20,7 @@
#
#
# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, Joyent Inc. All rights reserved.
#
#
@@ -53,6 +54,7 @@ SYMBOL_VERSION SUNWprivate_1.1 {
zonecfg_add_fs_option;
zonecfg_add_admin;
zonecfg_add_nwif;
+ zonecfg_add_res_attr;
zonecfg_add_pkg;
zonecfg_add_pset;
zonecfg_add_rctl;
@@ -79,7 +81,6 @@ SYMBOL_VERSION SUNWprivate_1.1 {
zonecfg_delete_dev;
zonecfg_delete_ds;
zonecfg_delete_filesystem;
- zonecfg_delete_mcap;
zonecfg_delete_nwif;
zonecfg_delete_pset;
zonecfg_delete_rctl;
@@ -104,7 +105,9 @@ SYMBOL_VERSION SUNWprivate_1.1 {
zonecfg_find_mounts;
zonecfg_find_scratch;
zonecfg_fini_handle;
+ zonecfg_fix_obsolete;
zonecfg_free_fs_option_list;
+ zonecfg_free_res_attr_list;
zonecfg_free_rctl_value_list;
zonecfg_get_aliased_rctl;
zonecfg_get_attach_handle;
@@ -118,6 +121,7 @@ SYMBOL_VERSION SUNWprivate_1.1 {
zonecfg_get_bootargs;
zonecfg_get_brand;
zonecfg_get_dflt_sched_class;
+ zonecfg_get_did;
zonecfg_getdevent;
zonecfg_getdevperment;
zonecfg_getdsent;
@@ -127,7 +131,6 @@ SYMBOL_VERSION SUNWprivate_1.1 {
zonecfg_get_hostid;
zonecfg_get_iptype;
zonecfg_get_limitpriv;
- zonecfg_getmcapent;
zonecfg_get_name;
zonecfg_get_name_by_uuid;
zonecfg_getnwifent;
@@ -160,7 +163,6 @@ SYMBOL_VERSION SUNWprivate_1.1 {
zonecfg_lookup_dev;
zonecfg_lookup_ds;
zonecfg_lookup_filesystem;
- zonecfg_lookup_mcap;
zonecfg_lookup_nwif;
zonecfg_lookup_pset;
zonecfg_lookup_rctl;
@@ -169,7 +171,6 @@ SYMBOL_VERSION SUNWprivate_1.1 {
zonecfg_modify_dev;
zonecfg_modify_ds;
zonecfg_modify_filesystem;
- zonecfg_modify_mcap;
zonecfg_modify_nwif;
zonecfg_modify_pset;
zonecfg_modify_rctl;
@@ -183,6 +184,7 @@ SYMBOL_VERSION SUNWprivate_1.1 {
zonecfg_ping_zoneadmd;
zonecfg_release_lock_file;
zonecfg_remove_fs_option;
+ zonecfg_remove_res_attr;
zonecfg_remove_rctl_value;
zonecfg_remove_userauths;
zonecfg_reverse_scratch;
@@ -196,6 +198,7 @@ SYMBOL_VERSION SUNWprivate_1.1 {
zonecfg_set_autoboot;
zonecfg_set_bootargs;
zonecfg_set_brand;
+ zonecfg_set_did;
zonecfg_setdevent;
zonecfg_setdevperment;
zonecfg_setdsent;
@@ -211,6 +214,7 @@ SYMBOL_VERSION SUNWprivate_1.1 {
zonecfg_set_root;
zonecfg_set_sched;
zonecfg_set_swinv;
+ zonecfg_set_uuid;
zonecfg_set_zonepath;
zonecfg_strerror;
zonecfg_str_to_bytes;
@@ -229,6 +233,7 @@ SYMBOL_VERSION SUNWprivate_1.1 {
zonecfg_verify_save;
zonecfg_warn_poold;
zone_get_brand;
+ zone_get_did;
zone_get_devroot;
zone_get_id;
zone_get_rootpath;