diff options
Diffstat (limited to 'usr/src/lib/libzonecfg/common')
-rw-r--r-- | usr/src/lib/libzonecfg/common/getzoneent.c | 14 | ||||
-rw-r--r-- | usr/src/lib/libzonecfg/common/libzonecfg.c | 647 | ||||
-rw-r--r-- | usr/src/lib/libzonecfg/common/mapfile-vers | 13 |
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; |