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 }
|