Print this page




   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2014 Gary Mills
  24  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  25  * Copyright 2015 Joyent Inc.
  26  * Copyright 2015 Nexenta Systems, Inc. All rights reserved.

  27  */
  28 
  29 #include <libsysevent.h>
  30 #include <pthread.h>
  31 #include <stdlib.h>
  32 #include <errno.h>
  33 #include <fnmatch.h>
  34 #include <strings.h>
  35 #include <unistd.h>
  36 #include <assert.h>
  37 #include <libgen.h>
  38 #include <libintl.h>
  39 #include <alloca.h>
  40 #include <ctype.h>
  41 #include <sys/acl.h>
  42 #include <sys/stat.h>
  43 #include <sys/brand.h>
  44 #include <sys/mntio.h>
  45 #include <sys/mnttab.h>
  46 #include <sys/nvpair.h>


 174  */
 175 static struct alias {
 176         char *shortname;
 177         char *realname;
 178         char *priv;
 179         char *action;
 180         uint64_t low_limit;
 181 } aliases[] = {
 182         {ALIAS_MAXLWPS, "zone.max-lwps", "privileged", "deny", 100},
 183         {ALIAS_MAXSHMMEM, "zone.max-shm-memory", "privileged", "deny", 0},
 184         {ALIAS_MAXSHMIDS, "zone.max-shm-ids", "privileged", "deny", 0},
 185         {ALIAS_MAXMSGIDS, "zone.max-msg-ids", "privileged", "deny", 0},
 186         {ALIAS_MAXSEMIDS, "zone.max-sem-ids", "privileged", "deny", 0},
 187         {ALIAS_MAXLOCKEDMEM, "zone.max-locked-memory", "privileged", "deny", 0},
 188         {ALIAS_MAXSWAP, "zone.max-swap", "privileged", "deny", 0},
 189         {ALIAS_MAXPHYSMEM, "zone.max-physical-memory", "privileged", "deny",
 190             1048576},
 191         {ALIAS_SHARES, "zone.cpu-shares", "privileged", "none", 0},
 192         {ALIAS_CPUCAP, "zone.cpu-cap", "privileged", "deny", 0},
 193         {ALIAS_MAXPROCS, "zone.max-processes", "privileged", "deny", 100},
 194         {ALIAS_ZFSPRI, "zone.zfs-io-priority", "privileged", "none", 0},
 195         {NULL, NULL, NULL, NULL, 0}
 196 };
 197 
 198 /*
 199  * Structure for applying rctls to a running zone.  It allows important
 200  * process values to be passed together easily.
 201  */
 202 typedef struct pr_info_handle {
 203         struct ps_prochandle *pr;
 204         pid_t pid;
 205 } pr_info_handle_t;
 206 
 207 struct zone_dochandle {
 208         char            *zone_dh_rootdir;
 209         xmlDocPtr       zone_dh_doc;
 210         xmlNodePtr      zone_dh_cur;
 211         xmlNodePtr      zone_dh_top;
 212         boolean_t       zone_dh_newzone;
 213         boolean_t       zone_dh_snapshot;
 214         boolean_t       zone_dh_sw_inv;


 222         int (*zn_callback)(const  char *zonename, zoneid_t zid,
 223             const char *newstate, const char *oldstate, hrtime_t when, void *p);
 224         pthread_mutex_t zn_mutex;
 225         pthread_cond_t zn_cond;
 226         pthread_mutex_t zn_bigmutex;
 227         volatile enum {ZN_UNLOCKED, ZN_LOCKED, ZN_PING_INFLIGHT,
 228             ZN_PING_RECEIVED} zn_state;
 229         char zn_subscriber_id[MAX_SUBID_LEN];
 230         volatile boolean_t zn_failed;
 231         int zn_failure_count;
 232 };
 233 
 234 /* used to track nested zone-lock operations */
 235 static int zone_lock_cnt = 0;
 236 
 237 /* used to communicate lock status to children */
 238 #define LOCK_ENV_VAR    "_ZONEADM_LOCK_HELD"
 239 static char zoneadm_lock_held[] = LOCK_ENV_VAR"=1";
 240 static char zoneadm_lock_not_held[] = LOCK_ENV_VAR"=0";
 241 
 242 static void zonecfg_notify_delete(const char *);
 243 
 244 char *zonecfg_root = "";
 245 
 246 /*
 247  * For functions which return int, which is most of the functions herein,
 248  * the return values should be from the Z_foo set defined in <libzonecfg.h>.
 249  * In some instances, we take pains mapping some libc errno values to Z_foo
 250  * values from this set.
 251  */
 252 
 253 /*
 254  * Set the root (/) path for all zonecfg configuration files.  This is a
 255  * private interface used by Live Upgrade extensions to access zone
 256  * configuration inside mounted alternate boot environments.
 257  * This interface is also used by zoneadm mount and unmount subcommands.
 258  */
 259 void
 260 zonecfg_set_root(const char *rootpath)
 261 {
 262         if (*zonecfg_root != '\0')
 263                 free(zonecfg_root);


 413 
 414         if (!force && state > ZONE_STATE_CONFIGURED)
 415                 return (Z_BAD_ZONE_STATE);
 416 
 417         /*
 418          * Index deletion succeeds even if the entry doesn't exist.  So this
 419          * will fail only if we've had some more severe problem.
 420          */
 421         bzero(&ze, sizeof (ze));
 422         (void) strlcpy(ze.zone_name, zonename, sizeof (ze.zone_name));
 423         if ((err = putzoneent(&ze, PZE_REMOVE)) != Z_OK)
 424                 if (!force)
 425                         return (err);
 426 
 427         err = zonecfg_destroy_impl(path);
 428 
 429         /*
 430          * Treat failure to find the XML file silently, since, well, it's
 431          * gone, and with the index file cleaned up, we're done.
 432          */
 433         if (err == Z_OK || err == Z_NO_ZONE) {
 434                 zonecfg_notify_delete(zonename);
 435                 return (Z_OK);
 436         }
 437         return (err);
 438 }
 439 
 440 int
 441 zonecfg_destroy_snapshot(const char *zonename)
 442 {
 443         char path[MAXPATHLEN];
 444 
 445         if (!snap_file_path(zonename, path, sizeof (path)))
 446                 return (Z_MISC_FS);
 447         return (zonecfg_destroy_impl(path));
 448 }
 449 
 450 static int
 451 getroot(zone_dochandle_t handle, xmlNodePtr *root)
 452 {
 453         if (zonecfg_check_handle(handle) == Z_BAD_HANDLE)
 454                 return (Z_BAD_HANDLE);
 455 
 456         *root = xmlDocGetRootElement(handle->zone_dh_doc);


1113         return (getrootattr(handle, DTD_ATTR_SCHED, sched, schedsize));
1114 }
1115 
1116 int
1117 zonecfg_set_sched(zone_dochandle_t handle, char *sched)
1118 {
1119         return (setrootattr(handle, DTD_ATTR_SCHED, sched));
1120 }
1121 
1122 /*
1123  * /etc/zones/index caches a vital piece of information which is also
1124  * in the <zonename>.xml file: the path to the zone.  This is for performance,
1125  * since we need to walk all zonepath's in order to be able to detect conflicts
1126  * (see crosscheck_zonepaths() in the zoneadm command).
1127  *
1128  * An additional complexity is that when doing a rename, we'd like the entire
1129  * index update operation (rename, and potential state changes) to be atomic.
1130  * In general, the operation of this function should succeed or fail as
1131  * a unit.
1132  */
1133 static int
1134 zonecfg_refresh_index_file(zone_dochandle_t handle)
1135 {
1136         char name[ZONENAME_MAX], zonepath[MAXPATHLEN];
1137         struct zoneent ze;
1138         int err;
1139         int opcode;
1140         char *zn;
1141 
1142         bzero(&ze, sizeof (ze));
1143         ze.zone_state = -1;     /* Preserve existing state in index */
1144 
1145         if ((err = zonecfg_get_name(handle, name, sizeof (name))) != Z_OK)
1146                 return (err);
1147         (void) strlcpy(ze.zone_name, name, sizeof (ze.zone_name));
1148 
1149         if ((err = zonecfg_get_zonepath(handle, zonepath,
1150             sizeof (zonepath))) != Z_OK)
1151                 return (err);
1152         (void) strlcpy(ze.zone_path, zonepath + strlen(zonecfg_root),
1153             sizeof (ze.zone_path));
1154 
1155         if ((err = zonecfg_get_brand(handle, ze.zone_brand,
1156             sizeof (ze.zone_brand))) != 0)
1157                 return (err);
1158 
1159         if ((err = zonecfg_get_iptype(handle, &ze.zone_iptype)) != Z_OK)
1160                 return (err);
1161 
1162         ze.zone_did = zonecfg_get_did(handle);
1163 
1164         if (is_renaming(handle)) {
1165                 opcode = PZE_MODIFY;
1166                 (void) strlcpy(ze.zone_name, handle->zone_dh_delete_name,
1167                     sizeof (ze.zone_name));
1168                 (void) strlcpy(ze.zone_newname, name, sizeof (ze.zone_newname));
1169         } else if (is_new(handle)) {
1170                 FILE *cookie;
1171                 /*
1172                  * Be tolerant of the zone already existing in the index file,
1173                  * since we might be forcibly overwriting an existing
1174                  * configuration with a new one (for example 'create -F'
1175                  * in zonecfg).
1176                  */
1177                 opcode = PZE_ADD;
1178                 cookie = setzoneent();
1179                 while ((zn = getzoneent(cookie)) != NULL) {
1180                         if (strcmp(zn, name) == 0) {
1181                                 opcode = PZE_MODIFY;
1182                                 free(zn);
1183                                 break;


1486 
1487         if (zonecfg_get_name(handle, zname, sizeof (zname)) != Z_OK)
1488                 return;
1489 
1490         if (zone_get_zonepath(zname, path, sizeof (path)) != Z_OK)
1491                 return;
1492 
1493         (void) snprintf(detached, sizeof (detached), "%s/%s", path,
1494             ZONE_DETACHED);
1495         (void) snprintf(attached, sizeof (attached), "%s/%s", path,
1496             ATTACH_FORCED);
1497 
1498         if (forced) {
1499                 (void) rename(detached, attached);
1500         } else {
1501                 (void) unlink(attached);
1502                 (void) unlink(detached);
1503         }
1504 }
1505 
1506 static void
1507 zonecfg_notify_conf_change(const char *zname, char *os, char *ns)
1508 {
1509         evchan_t *ze_chan;
1510         struct timeval now;
1511         uint64_t t;
1512         nvlist_t *nvl = NULL;
1513 
1514         if (sysevent_evc_bind(ZONE_EVENT_CHANNEL, &ze_chan, 0) != 0)
1515                 return;
1516 
1517         /* Current time since Jan 1 1970 but consumers expect NS */
1518         gettimeofday(&now, NULL);
1519         t = (now.tv_sec * NANOSEC) + (now.tv_usec * 1000);
1520 
1521         if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP) == 0 &&
1522             nvlist_add_string(nvl, ZONE_CB_NAME, zname) == 0 &&
1523             nvlist_add_string(nvl, ZONE_CB_NEWSTATE, ns) == 0 &&
1524             nvlist_add_string(nvl, ZONE_CB_OLDSTATE, os) == 0 &&
1525             nvlist_add_int32(nvl, ZONE_CB_ZONEID, -1) == 0 &&
1526             nvlist_add_uint64(nvl, ZONE_CB_TIMESTAMP, t) == 0) {
1527                 (void) sysevent_evc_publish(ze_chan, ZONE_EVENT_STATUS_CLASS,
1528                     ZONE_EVENT_STATUS_SUBCLASS, "sun.com", "zonecfg", nvl,
1529                     EVCH_SLEEP);
1530         }
1531 
1532         nvlist_free(nvl);
1533         (void) sysevent_evc_unbind(ze_chan);
1534 }
1535 
1536 void
1537 zonecfg_notify_create(zone_dochandle_t handle)
1538 {
1539         char zname[ZONENAME_MAX];
1540 
1541         if (zonecfg_check_handle(handle) != Z_OK)
1542                 return;
1543 
1544         if (zonecfg_get_name(handle, zname, sizeof (zname)) != Z_OK)
1545                 return;
1546 
1547         zonecfg_notify_conf_change(zname, "", ZONE_STATE_STR_CONFIGURED);
1548 }
1549 
1550 static void
1551 zonecfg_notify_delete(const char *zname)
1552 {
1553         zonecfg_notify_conf_change(zname, ZONE_STATE_STR_CONFIGURED, "");
1554 }
1555 
1556 /*
1557  * Special case: if access(2) fails with ENOENT, then try again using
1558  * ZONE_CONFIG_ROOT instead of config_file_path(zonename).  This is how we
1559  * work around the case of a config file which has not been created yet:
1560  * the user will need access to the directory so use that as a heuristic.
1561  */
1562 
1563 int
1564 zonecfg_access(const char *zonename, int amode)
1565 {
1566         char path[MAXPATHLEN];
1567 
1568         if (!config_file_path(zonename, path, sizeof (path)))
1569                 return (Z_INVAL);
1570         if (access(path, amode) == 0)
1571                 return (Z_OK);
1572         if (errno == ENOENT) {
1573                 if (snprintf(path, sizeof (path), "%s%s", zonecfg_root,
1574                     ZONE_CONFIG_ROOT) >= sizeof (path))
1575                         return (Z_INVAL);


2126         int save_errno;
2127 
2128         (void) memset(&lifr, 0, sizeof (lifr));
2129         (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
2130         lifr.lifr_addr.ss_family = af;
2131         if ((so = socket(af, SOCK_DGRAM, 0)) < 0) {
2132                 /* Odd - can't tell if the ifname exists */
2133                 return (B_FALSE);
2134         }
2135         if (ioctl(so, SIOCGLIFFLAGS, (caddr_t)&lifr) < 0) {
2136                 save_errno = errno;
2137                 (void) close(so);
2138                 errno = save_errno;
2139                 return (B_FALSE);
2140         }
2141         (void) close(so);
2142         return (B_TRUE);
2143 }
2144 
2145 /*
2146  * Turn an addr that looks like f:2:0:44:5:6C into 0f:02:00:44:05:6c
2147  * We're expecting a dst of at least MAXMACADDRLEN size here.
2148  */
2149 static void
2150 normalize_mac_addr(char *dst, const char *src, int len)
2151 {
2152         char *p, *e, *sep = "";
2153         long n;
2154         char buf[MAXMACADDRLEN], tmp[4];
2155 
2156         *dst = '\0';
2157         (void) strlcpy(buf, src, sizeof (buf));
2158         p = strtok(buf, ":");
2159         while (p != NULL) {
2160                 n = strtol(p, &e, 16);
2161                 if (*e != NULL || n > 0xff)
2162                         return;
2163                 (void) snprintf(tmp, sizeof (tmp), "%s%02x", sep, n);
2164                 (void) strlcat(dst, tmp, len);
2165 
2166                 sep = ":";
2167                 p = strtok(NULL, ":");
2168         }
2169 }
2170 
2171 /*
2172  * Determines whether there is a net resource with the physical interface, IP
2173  * address, and default router specified by 'tabptr' in the zone configuration
2174  * to which 'handle' refers.  'tabptr' must have an interface, an address, a
2175  * default router, or a combination of the three.  This function returns Z_OK
2176  * iff there is exactly one net resource matching the query specified by
2177  * 'tabptr'.  The function returns Z_INSUFFICIENT_SPEC if there are multiple
2178  * matches or 'tabptr' does not specify a physical interface, address, or
2179  * default router.  The function returns Z_NO_RESOURCE_ID if are no matches.
2180  *
2181  * Errors might also be returned if the entry that exactly matches the
2182  * query lacks critical network resource information.
2183  *
2184  * If there is a single match, then the matching entry's physical interface, IP
2185  * address, and default router information are stored in 'tabptr'.
2186  */
2187 int
2188 zonecfg_lookup_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
2189 {
2190         xmlNodePtr cur, val;
2191         xmlNodePtr firstmatch;
2192         int err;
2193         char address[INET6_ADDRSTRLEN];
2194         char physical[LIFNAMSIZ];
2195         char mac[MAXMACADDRLEN];
2196         char norm_mac[MAXMACADDRLEN];
2197         char gnic[LIFNAMSIZ];
2198         size_t addrspec;                /* nonzero if tabptr has IP addr */
2199         size_t physspec;                /* nonzero if tabptr has interface */
2200         size_t macspec;                 /* nonzero if tabptr has mac addr */
2201         size_t gnicspec;                /* nonzero if tabptr has gnic */
2202         size_t defrouterspec;           /* nonzero if tabptr has def. router */
2203         size_t allowed_addrspec;
2204         zone_iptype_t iptype;
2205 
2206         if (tabptr == NULL)
2207                 return (Z_INVAL);
2208 
2209         /*
2210          * Determine the fields that will be searched.  There must be at least
2211          * one.
2212          *
2213          * zone_nwif_address, zone_nwif_physical, zone_nwif_defrouter,
2214          * zone_nwif_mac, zone_nwif_vlan_id and zone_nwif_gnic  are
2215          * arrays, so no NULL checks are necessary.
2216          */


2233                 return (err);
2234         /*
2235          * Iterate over the configuration's elements and look for net elements
2236          * that match the query.
2237          */
2238         firstmatch = NULL;
2239         cur = handle->zone_dh_cur;
2240         for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
2241                 /* Skip non-net elements */
2242                 if (xmlStrcmp(cur->name, DTD_ELEM_NET))
2243                         continue;
2244 
2245                 /*
2246                  * If any relevant fields don't match the query, then skip
2247                  * the current net element.
2248                  */
2249                 if (physspec != 0 && (fetchprop(cur, DTD_ATTR_PHYSICAL,
2250                     physical, sizeof (physical)) != Z_OK ||
2251                     strcmp(tabptr->zone_nwif_physical, physical) != 0))
2252                         continue;
2253                 if (iptype == ZS_EXCLUSIVE && macspec != 0) {
2254                         if (fetchprop(cur, DTD_ATTR_MAC, mac, sizeof (mac)) !=
2255                             Z_OK)
2256                                 continue;
2257                         normalize_mac_addr(norm_mac, mac, sizeof (norm_mac));
2258                         if (strcmp(tabptr->zone_nwif_mac, norm_mac) != 0)
2259                                 continue;
2260                 }
2261                 if (iptype == ZS_EXCLUSIVE && gnicspec != 0 &&
2262                     (fetchprop(cur, DTD_ATTR_GNIC, gnic,
2263                     sizeof (gnic)) != Z_OK ||
2264                     strcmp(tabptr->zone_nwif_gnic, gnic) != 0))
2265                         continue;
2266                 if (iptype == ZS_SHARED && addrspec != 0 &&
2267                     (fetchprop(cur, DTD_ATTR_ADDRESS, address,
2268                     sizeof (address)) != Z_OK ||
2269                     !zonecfg_same_net_address(tabptr->zone_nwif_address,
2270                     address)))
2271                         continue;
2272                 if (iptype == ZS_EXCLUSIVE && allowed_addrspec != 0 &&
2273                     (fetchprop(cur, DTD_ATTR_ALLOWED_ADDRESS, address,
2274                     sizeof (address)) != Z_OK ||
2275                     !zonecfg_same_net_address(tabptr->zone_nwif_allowed_address,
2276                     address)))
2277                         continue;
2278                 if (defrouterspec != 0 && (fetchprop(cur, DTD_ATTR_DEFROUTER,
2279                     address, sizeof (address)) != Z_OK ||
2280                     !zonecfg_same_net_address(tabptr->zone_nwif_defrouter,


2438 {
2439         xmlNodePtr cur = handle->zone_dh_cur;
2440         boolean_t addr_match, phys_match, allowed_addr_match, mac_match,
2441             gnic_match;
2442 
2443         for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
2444                 if (xmlStrcmp(cur->name, DTD_ELEM_NET))
2445                         continue;
2446 
2447                 addr_match = match_prop(cur, DTD_ATTR_ADDRESS,
2448                     tabptr->zone_nwif_address);
2449                 allowed_addr_match = match_prop(cur, DTD_ATTR_ALLOWED_ADDRESS,
2450                     tabptr->zone_nwif_allowed_address);
2451                 phys_match = match_prop(cur, DTD_ATTR_PHYSICAL,
2452                     tabptr->zone_nwif_physical);
2453                 mac_match = match_prop(cur, DTD_ATTR_MAC,
2454                     tabptr->zone_nwif_mac);
2455                 gnic_match = match_prop(cur, DTD_ATTR_GNIC,
2456                     tabptr->zone_nwif_gnic);
2457 
2458                 if (((addr_match && allowed_addr_match) || mac_match ||
2459                     gnic_match) && phys_match) {
2460                         xmlUnlinkNode(cur);
2461                         xmlFreeNode(cur);
2462                         return (Z_OK);
2463                 }
2464         }
2465         return (Z_NO_RESOURCE_ID);
2466 }
2467 
2468 int
2469 zonecfg_delete_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
2470 {
2471         int err;
2472 
2473         if (tabptr == NULL)
2474                 return (Z_INVAL);
2475 
2476         if ((err = operation_prep(handle)) != Z_OK)
2477                 return (err);
2478 


4850  * refer to the name of a configured resource pool.  The thread scheduling
4851  * class specified by the pool will be stored in the buffer to which 'class'
4852  * points.  'clsize' is the byte size of the buffer to which 'class' points.
4853  *
4854  * This function returns Z_OK if it successfully stored the specified pool's
4855  * thread scheduling class into the buffer to which 'class' points.  It returns
4856  * Z_NO_POOL if resource pools are not enabled, the function is unable to
4857  * access the system's resource pools configuration, or the specified pool
4858  * does not exist.  The function returns Z_TOO_BIG if the buffer to which
4859  * 'class' points is not large enough to contain the thread scheduling class'
4860  * name.  The function returns Z_NO_ENTRY if the pool does not specify a thread
4861  * scheduling class.
4862  */
4863 static int
4864 get_pool_sched_class(char *poolname, char *class, int clsize)
4865 {
4866         int status;
4867         pool_conf_t *poolconf;
4868         pool_t *pool;
4869         pool_elem_t *pe;
4870         pool_value_t *pv;
4871         const char *sched_str;
4872 
4873         if (pool_get_status(&status) != PO_SUCCESS || status != POOL_ENABLED)
4874                 return (Z_NO_POOL);
4875 
4876         if ((poolconf = pool_conf_alloc()) == NULL)
4877                 return (Z_NO_POOL);
4878 
4879         if (pool_conf_open(poolconf, pool_dynamic_location(), PO_RDONLY) !=
4880             PO_SUCCESS) {
4881                 pool_conf_free(poolconf);
4882                 return (Z_NO_POOL);
4883         }
4884 
4885         if ((pool = pool_get_pool(poolconf, poolname)) == NULL) {
4886                 (void) pool_conf_close(poolconf);
4887                 pool_conf_free(poolconf);
4888                 return (Z_NO_POOL);
4889         }
4890 
4891         if ((pv = pool_value_alloc()) == NULL) {
4892                 (void) pool_conf_close(poolconf);
4893                 pool_conf_free(poolconf);
4894                 return (Z_NO_POOL);
4895         }
4896 
4897         pe = pool_to_elem(poolconf, pool);
4898         if (pool_get_property(poolconf, pe, "pool.scheduler", pv) !=
4899             POC_STRING) {
4900                 (void) pool_conf_close(poolconf);
4901                 pool_value_free(pv);
4902                 pool_conf_free(poolconf);
4903                 return (Z_NO_ENTRY);
4904         }
4905         (void) pool_value_get_string(pv, &sched_str);
4906         (void) pool_conf_close(poolconf);
4907         pool_value_free(pv);
4908         pool_conf_free(poolconf);
4909         if (strlcpy(class, sched_str, clsize) >= clsize)
4910                 return (Z_TOO_BIG);
4911         return (Z_OK);
4912 }
4913 
4914 /*
4915  * Get the default scheduling class for the zone.  This will either be the
4916  * class set on the zone's pool or the system default scheduling class.
4917  */
4918 int
4919 zonecfg_get_dflt_sched_class(zone_dochandle_t handle, char *class, int clsize)
4920 {
4921         char poolname[MAXPATHLEN];
4922 
4923         if (zonecfg_get_pool(handle, poolname, sizeof (poolname)) == Z_OK) {
4924                 /* check if the zone's pool specified a sched class */
4925                 if (get_pool_sched_class(poolname, class, clsize) == Z_OK)
4926                         return (Z_OK);
4927         }


6157         }
6158 
6159         cookie = setzoneent();
6160         while ((ze = getzoneent_private(cookie)) != NULL) {
6161                 if (strcmp(ze->zone_name, zone_name) == 0) {
6162                         found = B_TRUE;
6163                         *state_num = ze->zone_state;
6164                 }
6165                 free(ze);
6166                 if (found)
6167                         break;
6168         }
6169         endzoneent(cookie);
6170         return ((found) ? Z_OK : Z_NO_ZONE);
6171 }
6172 
6173 int
6174 zone_set_state(char *zone, zone_state_t state)
6175 {
6176         struct zoneent ze;
6177         int res;
6178         zone_state_t oldst = (zone_state_t)-1;
6179 
6180         if (state != ZONE_STATE_CONFIGURED && state != ZONE_STATE_INSTALLED &&
6181             state != ZONE_STATE_INCOMPLETE)
6182                 return (Z_INVAL);
6183 
6184         (void) zone_get_state(zone, &oldst);
6185 
6186         bzero(&ze, sizeof (ze));
6187         (void) strlcpy(ze.zone_name, zone, sizeof (ze.zone_name));
6188         ze.zone_state = state;
6189         (void) strlcpy(ze.zone_path, "", sizeof (ze.zone_path));
6190         res = putzoneent(&ze, PZE_MODIFY);
6191 
6192         if (res == Z_OK) {
6193                 zonecfg_notify_conf_change(zone, zone_state_str(oldst),
6194                     zone_state_str(state));
6195         }
6196 
6197         return (res);
6198 }
6199 
6200 /*
6201  * Get id (if any) for specified zone.  There are four possible outcomes:
6202  * - If the string corresponds to the numeric id of an active (booted)
6203  *   zone, sets *zip to the zone id and returns 0.
6204  * - If the string corresponds to the name of an active (booted) zone,
6205  *   sets *zip to the zone id and returns 0.
6206  * - If the string is a name in the configuration but is not booted,
6207  *   sets *zip to ZONE_ID_UNDEFINED and returns 0.
6208  * - Otherwise, leaves *zip unchanged and returns -1.
6209  *
6210  * This function acts as an auxiliary filter on the function of the same
6211  * name in libc; the linker binds to this version if libzonecfg exists,
6212  * and the libc version if it doesn't.  Any changes to this version of
6213  * the function should probably be reflected in the libc version as well.
6214  */
6215 int
6216 zone_get_id(const char *str, zoneid_t *zip)
6217 {


6326         FILE *fp;
6327         struct zoneent *ze;
6328 
6329         if ((fp = setzoneent()) == NULL)
6330                 return (Z_NO_ZONE);
6331         while ((ze = getzoneent_private(fp)) != NULL) {
6332                 if (strcmp(ze->zone_name, zonename) == 0)
6333                         break;
6334                 free(ze);
6335         }
6336         endzoneent(fp);
6337         if (ze != NULL) {
6338                 uuid_copy(uuid, ze->zone_uuid);
6339                 free(ze);
6340                 return (Z_OK);
6341         } else {
6342                 return (Z_NO_ZONE);
6343         }
6344 }
6345 
6346 /*
6347  * Changes a zone's UUID to the given value. Returns an error if the UUID is
6348  * malformed or if the zone cannot be located.
6349  */
6350 int
6351 zonecfg_set_uuid(const char *zonename, const char *zonepath,
6352     const char *uuid)
6353 {
6354         int err;
6355         struct zoneent ze;
6356 
6357         bzero(&ze, sizeof (ze));
6358         ze.zone_state = -1;     /* Preserve existing state in index */
6359         (void) strlcpy(ze.zone_name, zonename, sizeof (ze.zone_name));
6360         (void) strlcpy(ze.zone_path, zonepath, sizeof (ze.zone_path));
6361         if (uuid_parse((char *)uuid, ze.zone_uuid) == -1)
6362                 return (Z_INVALID_PROPERTY);
6363 
6364         if ((err = putzoneent(&ze, PZE_MODIFY)) != Z_OK)
6365                 return (err);
6366 
6367         return (Z_OK);
6368 }
6369 
6370 /*
6371  * File-system convenience functions.
6372  */
6373 boolean_t
6374 zonecfg_valid_fs_type(const char *type)
6375 {
6376         /*
6377          * We already know which FS types don't work.
6378          */
6379         if (strcmp(type, "proc") == 0 ||
6380             strcmp(type, "mntfs") == 0 ||
6381             strcmp(type, "autofs") == 0 ||
6382             strncmp(type, "nfs", sizeof ("nfs") - 1) == 0)
6383                 return (B_FALSE);
6384         /*
6385          * The caller may do more detailed verification to make sure other
6386          * aspects of this filesystem type make sense.
6387          */
6388         return (B_TRUE);
6389 }




   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2014 Gary Mills
  24  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.

  25  * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
  26  * Copyright 2015 Joyent Inc.
  27  */
  28 
  29 #include <libsysevent.h>
  30 #include <pthread.h>
  31 #include <stdlib.h>
  32 #include <errno.h>
  33 #include <fnmatch.h>
  34 #include <strings.h>
  35 #include <unistd.h>
  36 #include <assert.h>
  37 #include <libgen.h>
  38 #include <libintl.h>
  39 #include <alloca.h>
  40 #include <ctype.h>
  41 #include <sys/acl.h>
  42 #include <sys/stat.h>
  43 #include <sys/brand.h>
  44 #include <sys/mntio.h>
  45 #include <sys/mnttab.h>
  46 #include <sys/nvpair.h>


 174  */
 175 static struct alias {
 176         char *shortname;
 177         char *realname;
 178         char *priv;
 179         char *action;
 180         uint64_t low_limit;
 181 } aliases[] = {
 182         {ALIAS_MAXLWPS, "zone.max-lwps", "privileged", "deny", 100},
 183         {ALIAS_MAXSHMMEM, "zone.max-shm-memory", "privileged", "deny", 0},
 184         {ALIAS_MAXSHMIDS, "zone.max-shm-ids", "privileged", "deny", 0},
 185         {ALIAS_MAXMSGIDS, "zone.max-msg-ids", "privileged", "deny", 0},
 186         {ALIAS_MAXSEMIDS, "zone.max-sem-ids", "privileged", "deny", 0},
 187         {ALIAS_MAXLOCKEDMEM, "zone.max-locked-memory", "privileged", "deny", 0},
 188         {ALIAS_MAXSWAP, "zone.max-swap", "privileged", "deny", 0},
 189         {ALIAS_MAXPHYSMEM, "zone.max-physical-memory", "privileged", "deny",
 190             1048576},
 191         {ALIAS_SHARES, "zone.cpu-shares", "privileged", "none", 0},
 192         {ALIAS_CPUCAP, "zone.cpu-cap", "privileged", "deny", 0},
 193         {ALIAS_MAXPROCS, "zone.max-processes", "privileged", "deny", 100},

 194         {NULL, NULL, NULL, NULL, 0}
 195 };
 196 
 197 /*
 198  * Structure for applying rctls to a running zone.  It allows important
 199  * process values to be passed together easily.
 200  */
 201 typedef struct pr_info_handle {
 202         struct ps_prochandle *pr;
 203         pid_t pid;
 204 } pr_info_handle_t;
 205 
 206 struct zone_dochandle {
 207         char            *zone_dh_rootdir;
 208         xmlDocPtr       zone_dh_doc;
 209         xmlNodePtr      zone_dh_cur;
 210         xmlNodePtr      zone_dh_top;
 211         boolean_t       zone_dh_newzone;
 212         boolean_t       zone_dh_snapshot;
 213         boolean_t       zone_dh_sw_inv;


 221         int (*zn_callback)(const  char *zonename, zoneid_t zid,
 222             const char *newstate, const char *oldstate, hrtime_t when, void *p);
 223         pthread_mutex_t zn_mutex;
 224         pthread_cond_t zn_cond;
 225         pthread_mutex_t zn_bigmutex;
 226         volatile enum {ZN_UNLOCKED, ZN_LOCKED, ZN_PING_INFLIGHT,
 227             ZN_PING_RECEIVED} zn_state;
 228         char zn_subscriber_id[MAX_SUBID_LEN];
 229         volatile boolean_t zn_failed;
 230         int zn_failure_count;
 231 };
 232 
 233 /* used to track nested zone-lock operations */
 234 static int zone_lock_cnt = 0;
 235 
 236 /* used to communicate lock status to children */
 237 #define LOCK_ENV_VAR    "_ZONEADM_LOCK_HELD"
 238 static char zoneadm_lock_held[] = LOCK_ENV_VAR"=1";
 239 static char zoneadm_lock_not_held[] = LOCK_ENV_VAR"=0";
 240 


 241 char *zonecfg_root = "";
 242 
 243 /*
 244  * For functions which return int, which is most of the functions herein,
 245  * the return values should be from the Z_foo set defined in <libzonecfg.h>.
 246  * In some instances, we take pains mapping some libc errno values to Z_foo
 247  * values from this set.
 248  */
 249 
 250 /*
 251  * Set the root (/) path for all zonecfg configuration files.  This is a
 252  * private interface used by Live Upgrade extensions to access zone
 253  * configuration inside mounted alternate boot environments.
 254  * This interface is also used by zoneadm mount and unmount subcommands.
 255  */
 256 void
 257 zonecfg_set_root(const char *rootpath)
 258 {
 259         if (*zonecfg_root != '\0')
 260                 free(zonecfg_root);


 410 
 411         if (!force && state > ZONE_STATE_CONFIGURED)
 412                 return (Z_BAD_ZONE_STATE);
 413 
 414         /*
 415          * Index deletion succeeds even if the entry doesn't exist.  So this
 416          * will fail only if we've had some more severe problem.
 417          */
 418         bzero(&ze, sizeof (ze));
 419         (void) strlcpy(ze.zone_name, zonename, sizeof (ze.zone_name));
 420         if ((err = putzoneent(&ze, PZE_REMOVE)) != Z_OK)
 421                 if (!force)
 422                         return (err);
 423 
 424         err = zonecfg_destroy_impl(path);
 425 
 426         /*
 427          * Treat failure to find the XML file silently, since, well, it's
 428          * gone, and with the index file cleaned up, we're done.
 429          */
 430         if (err == Z_OK || err == Z_NO_ZONE)

 431                 return (Z_OK);

 432         return (err);
 433 }
 434 
 435 int
 436 zonecfg_destroy_snapshot(const char *zonename)
 437 {
 438         char path[MAXPATHLEN];
 439 
 440         if (!snap_file_path(zonename, path, sizeof (path)))
 441                 return (Z_MISC_FS);
 442         return (zonecfg_destroy_impl(path));
 443 }
 444 
 445 static int
 446 getroot(zone_dochandle_t handle, xmlNodePtr *root)
 447 {
 448         if (zonecfg_check_handle(handle) == Z_BAD_HANDLE)
 449                 return (Z_BAD_HANDLE);
 450 
 451         *root = xmlDocGetRootElement(handle->zone_dh_doc);


1108         return (getrootattr(handle, DTD_ATTR_SCHED, sched, schedsize));
1109 }
1110 
1111 int
1112 zonecfg_set_sched(zone_dochandle_t handle, char *sched)
1113 {
1114         return (setrootattr(handle, DTD_ATTR_SCHED, sched));
1115 }
1116 
1117 /*
1118  * /etc/zones/index caches a vital piece of information which is also
1119  * in the <zonename>.xml file: the path to the zone.  This is for performance,
1120  * since we need to walk all zonepath's in order to be able to detect conflicts
1121  * (see crosscheck_zonepaths() in the zoneadm command).
1122  *
1123  * An additional complexity is that when doing a rename, we'd like the entire
1124  * index update operation (rename, and potential state changes) to be atomic.
1125  * In general, the operation of this function should succeed or fail as
1126  * a unit.
1127  */
1128 int
1129 zonecfg_refresh_index_file(zone_dochandle_t handle)
1130 {
1131         char name[ZONENAME_MAX], zonepath[MAXPATHLEN];
1132         struct zoneent ze;
1133         int err;
1134         int opcode;
1135         char *zn;
1136 
1137         bzero(&ze, sizeof (ze));
1138         ze.zone_state = -1;     /* Preserve existing state in index */
1139 
1140         if ((err = zonecfg_get_name(handle, name, sizeof (name))) != Z_OK)
1141                 return (err);
1142         (void) strlcpy(ze.zone_name, name, sizeof (ze.zone_name));
1143 
1144         if ((err = zonecfg_get_zonepath(handle, zonepath,
1145             sizeof (zonepath))) != Z_OK)
1146                 return (err);
1147         (void) strlcpy(ze.zone_path, zonepath + strlen(zonecfg_root),
1148             sizeof (ze.zone_path));
1149 









1150         if (is_renaming(handle)) {
1151                 opcode = PZE_MODIFY;
1152                 (void) strlcpy(ze.zone_name, handle->zone_dh_delete_name,
1153                     sizeof (ze.zone_name));
1154                 (void) strlcpy(ze.zone_newname, name, sizeof (ze.zone_newname));
1155         } else if (is_new(handle)) {
1156                 FILE *cookie;
1157                 /*
1158                  * Be tolerant of the zone already existing in the index file,
1159                  * since we might be forcibly overwriting an existing
1160                  * configuration with a new one (for example 'create -F'
1161                  * in zonecfg).
1162                  */
1163                 opcode = PZE_ADD;
1164                 cookie = setzoneent();
1165                 while ((zn = getzoneent(cookie)) != NULL) {
1166                         if (strcmp(zn, name) == 0) {
1167                                 opcode = PZE_MODIFY;
1168                                 free(zn);
1169                                 break;


1472 
1473         if (zonecfg_get_name(handle, zname, sizeof (zname)) != Z_OK)
1474                 return;
1475 
1476         if (zone_get_zonepath(zname, path, sizeof (path)) != Z_OK)
1477                 return;
1478 
1479         (void) snprintf(detached, sizeof (detached), "%s/%s", path,
1480             ZONE_DETACHED);
1481         (void) snprintf(attached, sizeof (attached), "%s/%s", path,
1482             ATTACH_FORCED);
1483 
1484         if (forced) {
1485                 (void) rename(detached, attached);
1486         } else {
1487                 (void) unlink(attached);
1488                 (void) unlink(detached);
1489         }
1490 }
1491 


















































1492 /*
1493  * Special case: if access(2) fails with ENOENT, then try again using
1494  * ZONE_CONFIG_ROOT instead of config_file_path(zonename).  This is how we
1495  * work around the case of a config file which has not been created yet:
1496  * the user will need access to the directory so use that as a heuristic.
1497  */
1498 
1499 int
1500 zonecfg_access(const char *zonename, int amode)
1501 {
1502         char path[MAXPATHLEN];
1503 
1504         if (!config_file_path(zonename, path, sizeof (path)))
1505                 return (Z_INVAL);
1506         if (access(path, amode) == 0)
1507                 return (Z_OK);
1508         if (errno == ENOENT) {
1509                 if (snprintf(path, sizeof (path), "%s%s", zonecfg_root,
1510                     ZONE_CONFIG_ROOT) >= sizeof (path))
1511                         return (Z_INVAL);


2062         int save_errno;
2063 
2064         (void) memset(&lifr, 0, sizeof (lifr));
2065         (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
2066         lifr.lifr_addr.ss_family = af;
2067         if ((so = socket(af, SOCK_DGRAM, 0)) < 0) {
2068                 /* Odd - can't tell if the ifname exists */
2069                 return (B_FALSE);
2070         }
2071         if (ioctl(so, SIOCGLIFFLAGS, (caddr_t)&lifr) < 0) {
2072                 save_errno = errno;
2073                 (void) close(so);
2074                 errno = save_errno;
2075                 return (B_FALSE);
2076         }
2077         (void) close(so);
2078         return (B_TRUE);
2079 }
2080 
2081 /*


























2082  * Determines whether there is a net resource with the physical interface, IP
2083  * address, and default router specified by 'tabptr' in the zone configuration
2084  * to which 'handle' refers.  'tabptr' must have an interface, an address, a
2085  * default router, or a combination of the three.  This function returns Z_OK
2086  * iff there is exactly one net resource matching the query specified by
2087  * 'tabptr'.  The function returns Z_INSUFFICIENT_SPEC if there are multiple
2088  * matches or 'tabptr' does not specify a physical interface, address, or
2089  * default router.  The function returns Z_NO_RESOURCE_ID if are no matches.
2090  *
2091  * Errors might also be returned if the entry that exactly matches the
2092  * query lacks critical network resource information.
2093  *
2094  * If there is a single match, then the matching entry's physical interface, IP
2095  * address, and default router information are stored in 'tabptr'.
2096  */
2097 int
2098 zonecfg_lookup_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
2099 {
2100         xmlNodePtr cur, val;
2101         xmlNodePtr firstmatch;
2102         int err;
2103         char address[INET6_ADDRSTRLEN];
2104         char physical[LIFNAMSIZ];
2105         char mac[MAXMACADDRLEN];

2106         char gnic[LIFNAMSIZ];
2107         size_t addrspec;                /* nonzero if tabptr has IP addr */
2108         size_t physspec;                /* nonzero if tabptr has interface */
2109         size_t macspec;                 /* nonzero if tabptr has mac addr */
2110         size_t gnicspec;                /* nonzero if tabptr has gnic */
2111         size_t defrouterspec;           /* nonzero if tabptr has def. router */
2112         size_t allowed_addrspec;
2113         zone_iptype_t iptype;
2114 
2115         if (tabptr == NULL)
2116                 return (Z_INVAL);
2117 
2118         /*
2119          * Determine the fields that will be searched.  There must be at least
2120          * one.
2121          *
2122          * zone_nwif_address, zone_nwif_physical, zone_nwif_defrouter,
2123          * zone_nwif_mac, zone_nwif_vlan_id and zone_nwif_gnic  are
2124          * arrays, so no NULL checks are necessary.
2125          */


2142                 return (err);
2143         /*
2144          * Iterate over the configuration's elements and look for net elements
2145          * that match the query.
2146          */
2147         firstmatch = NULL;
2148         cur = handle->zone_dh_cur;
2149         for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
2150                 /* Skip non-net elements */
2151                 if (xmlStrcmp(cur->name, DTD_ELEM_NET))
2152                         continue;
2153 
2154                 /*
2155                  * If any relevant fields don't match the query, then skip
2156                  * the current net element.
2157                  */
2158                 if (physspec != 0 && (fetchprop(cur, DTD_ATTR_PHYSICAL,
2159                     physical, sizeof (physical)) != Z_OK ||
2160                     strcmp(tabptr->zone_nwif_physical, physical) != 0))
2161                         continue;
2162                 if (iptype == ZS_EXCLUSIVE && macspec != 0 &&
2163                     (fetchprop(cur, DTD_ATTR_MAC, mac, sizeof (mac)) != Z_OK ||
2164                     strcmp(tabptr->zone_nwif_mac, mac) != 0))
2165                         continue;




2166                 if (iptype == ZS_EXCLUSIVE && gnicspec != 0 &&
2167                     (fetchprop(cur, DTD_ATTR_GNIC, gnic,
2168                     sizeof (gnic)) != Z_OK ||
2169                     strcmp(tabptr->zone_nwif_gnic, gnic) != 0))
2170                         continue;
2171                 if (iptype == ZS_SHARED && addrspec != 0 &&
2172                     (fetchprop(cur, DTD_ATTR_ADDRESS, address,
2173                     sizeof (address)) != Z_OK ||
2174                     !zonecfg_same_net_address(tabptr->zone_nwif_address,
2175                     address)))
2176                         continue;
2177                 if (iptype == ZS_EXCLUSIVE && allowed_addrspec != 0 &&
2178                     (fetchprop(cur, DTD_ATTR_ALLOWED_ADDRESS, address,
2179                     sizeof (address)) != Z_OK ||
2180                     !zonecfg_same_net_address(tabptr->zone_nwif_allowed_address,
2181                     address)))
2182                         continue;
2183                 if (defrouterspec != 0 && (fetchprop(cur, DTD_ATTR_DEFROUTER,
2184                     address, sizeof (address)) != Z_OK ||
2185                     !zonecfg_same_net_address(tabptr->zone_nwif_defrouter,


2343 {
2344         xmlNodePtr cur = handle->zone_dh_cur;
2345         boolean_t addr_match, phys_match, allowed_addr_match, mac_match,
2346             gnic_match;
2347 
2348         for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
2349                 if (xmlStrcmp(cur->name, DTD_ELEM_NET))
2350                         continue;
2351 
2352                 addr_match = match_prop(cur, DTD_ATTR_ADDRESS,
2353                     tabptr->zone_nwif_address);
2354                 allowed_addr_match = match_prop(cur, DTD_ATTR_ALLOWED_ADDRESS,
2355                     tabptr->zone_nwif_allowed_address);
2356                 phys_match = match_prop(cur, DTD_ATTR_PHYSICAL,
2357                     tabptr->zone_nwif_physical);
2358                 mac_match = match_prop(cur, DTD_ATTR_MAC,
2359                     tabptr->zone_nwif_mac);
2360                 gnic_match = match_prop(cur, DTD_ATTR_GNIC,
2361                     tabptr->zone_nwif_gnic);
2362 
2363                 if ((addr_match || allowed_addr_match || mac_match ||
2364                     gnic_match) && phys_match) {
2365                         xmlUnlinkNode(cur);
2366                         xmlFreeNode(cur);
2367                         return (Z_OK);
2368                 }
2369         }
2370         return (Z_NO_RESOURCE_ID);
2371 }
2372 
2373 int
2374 zonecfg_delete_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
2375 {
2376         int err;
2377 
2378         if (tabptr == NULL)
2379                 return (Z_INVAL);
2380 
2381         if ((err = operation_prep(handle)) != Z_OK)
2382                 return (err);
2383 


4755  * refer to the name of a configured resource pool.  The thread scheduling
4756  * class specified by the pool will be stored in the buffer to which 'class'
4757  * points.  'clsize' is the byte size of the buffer to which 'class' points.
4758  *
4759  * This function returns Z_OK if it successfully stored the specified pool's
4760  * thread scheduling class into the buffer to which 'class' points.  It returns
4761  * Z_NO_POOL if resource pools are not enabled, the function is unable to
4762  * access the system's resource pools configuration, or the specified pool
4763  * does not exist.  The function returns Z_TOO_BIG if the buffer to which
4764  * 'class' points is not large enough to contain the thread scheduling class'
4765  * name.  The function returns Z_NO_ENTRY if the pool does not specify a thread
4766  * scheduling class.
4767  */
4768 static int
4769 get_pool_sched_class(char *poolname, char *class, int clsize)
4770 {
4771         int status;
4772         pool_conf_t *poolconf;
4773         pool_t *pool;
4774         pool_elem_t *pe;
4775         pool_value_t *pv = pool_value_alloc();
4776         const char *sched_str;
4777 
4778         if (pool_get_status(&status) != PO_SUCCESS || status != POOL_ENABLED)
4779                 return (Z_NO_POOL);
4780 
4781         if ((poolconf = pool_conf_alloc()) == NULL)
4782                 return (Z_NO_POOL);
4783 
4784         if (pool_conf_open(poolconf, pool_dynamic_location(), PO_RDONLY) !=
4785             PO_SUCCESS) {
4786                 pool_conf_free(poolconf);
4787                 return (Z_NO_POOL);
4788         }
4789 
4790         if ((pool = pool_get_pool(poolconf, poolname)) == NULL) {
4791                 (void) pool_conf_close(poolconf);
4792                 pool_conf_free(poolconf);
4793                 return (Z_NO_POOL);
4794         }
4795 






4796         pe = pool_to_elem(poolconf, pool);
4797         if (pool_get_property(poolconf, pe, "pool.scheduler", pv) !=
4798             POC_STRING) {
4799                 (void) pool_conf_close(poolconf);

4800                 pool_conf_free(poolconf);
4801                 return (Z_NO_ENTRY);
4802         }
4803         (void) pool_value_get_string(pv, &sched_str);
4804         (void) pool_conf_close(poolconf);

4805         pool_conf_free(poolconf);
4806         if (strlcpy(class, sched_str, clsize) >= clsize)
4807                 return (Z_TOO_BIG);
4808         return (Z_OK);
4809 }
4810 
4811 /*
4812  * Get the default scheduling class for the zone.  This will either be the
4813  * class set on the zone's pool or the system default scheduling class.
4814  */
4815 int
4816 zonecfg_get_dflt_sched_class(zone_dochandle_t handle, char *class, int clsize)
4817 {
4818         char poolname[MAXPATHLEN];
4819 
4820         if (zonecfg_get_pool(handle, poolname, sizeof (poolname)) == Z_OK) {
4821                 /* check if the zone's pool specified a sched class */
4822                 if (get_pool_sched_class(poolname, class, clsize) == Z_OK)
4823                         return (Z_OK);
4824         }


6054         }
6055 
6056         cookie = setzoneent();
6057         while ((ze = getzoneent_private(cookie)) != NULL) {
6058                 if (strcmp(ze->zone_name, zone_name) == 0) {
6059                         found = B_TRUE;
6060                         *state_num = ze->zone_state;
6061                 }
6062                 free(ze);
6063                 if (found)
6064                         break;
6065         }
6066         endzoneent(cookie);
6067         return ((found) ? Z_OK : Z_NO_ZONE);
6068 }
6069 
6070 int
6071 zone_set_state(char *zone, zone_state_t state)
6072 {
6073         struct zoneent ze;


6074 
6075         if (state != ZONE_STATE_CONFIGURED && state != ZONE_STATE_INSTALLED &&
6076             state != ZONE_STATE_INCOMPLETE)
6077                 return (Z_INVAL);
6078 


6079         bzero(&ze, sizeof (ze));
6080         (void) strlcpy(ze.zone_name, zone, sizeof (ze.zone_name));
6081         ze.zone_state = state;
6082         (void) strlcpy(ze.zone_path, "", sizeof (ze.zone_path));
6083         return (putzoneent(&ze, PZE_MODIFY));







6084 }
6085 
6086 /*
6087  * Get id (if any) for specified zone.  There are four possible outcomes:
6088  * - If the string corresponds to the numeric id of an active (booted)
6089  *   zone, sets *zip to the zone id and returns 0.
6090  * - If the string corresponds to the name of an active (booted) zone,
6091  *   sets *zip to the zone id and returns 0.
6092  * - If the string is a name in the configuration but is not booted,
6093  *   sets *zip to ZONE_ID_UNDEFINED and returns 0.
6094  * - Otherwise, leaves *zip unchanged and returns -1.
6095  *
6096  * This function acts as an auxiliary filter on the function of the same
6097  * name in libc; the linker binds to this version if libzonecfg exists,
6098  * and the libc version if it doesn't.  Any changes to this version of
6099  * the function should probably be reflected in the libc version as well.
6100  */
6101 int
6102 zone_get_id(const char *str, zoneid_t *zip)
6103 {


6212         FILE *fp;
6213         struct zoneent *ze;
6214 
6215         if ((fp = setzoneent()) == NULL)
6216                 return (Z_NO_ZONE);
6217         while ((ze = getzoneent_private(fp)) != NULL) {
6218                 if (strcmp(ze->zone_name, zonename) == 0)
6219                         break;
6220                 free(ze);
6221         }
6222         endzoneent(fp);
6223         if (ze != NULL) {
6224                 uuid_copy(uuid, ze->zone_uuid);
6225                 free(ze);
6226                 return (Z_OK);
6227         } else {
6228                 return (Z_NO_ZONE);
6229         }
6230 }
6231 
























6232 /*
6233  * File-system convenience functions.
6234  */
6235 boolean_t
6236 zonecfg_valid_fs_type(const char *type)
6237 {
6238         /*
6239          * We already know which FS types don't work.
6240          */
6241         if (strcmp(type, "proc") == 0 ||
6242             strcmp(type, "mntfs") == 0 ||
6243             strcmp(type, "autofs") == 0 ||
6244             strncmp(type, "nfs", sizeof ("nfs") - 1) == 0)
6245                 return (B_FALSE);
6246         /*
6247          * The caller may do more detailed verification to make sure other
6248          * aspects of this filesystem type make sense.
6249          */
6250         return (B_TRUE);
6251 }