17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5ee519a1fSgjelinek * Common Development and Distribution License (the "License").
6ee519a1fSgjelinek * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
21ffbafc53Scomay
227c478bd9Sstevel@tonic-gate /*
23*cbca9407SGary Mills * Copyright 2014 Gary Mills
24a20ee416SGlenn Faden * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
27cf8f45c7Sdstaff #include <libsysevent.h>
28cf8f45c7Sdstaff #include <pthread.h>
29cf8f45c7Sdstaff #include <stdlib.h>
307c478bd9Sstevel@tonic-gate #include <errno.h>
317c478bd9Sstevel@tonic-gate #include <fnmatch.h>
327c478bd9Sstevel@tonic-gate #include <strings.h>
337c478bd9Sstevel@tonic-gate #include <unistd.h>
347c478bd9Sstevel@tonic-gate #include <assert.h>
357c478bd9Sstevel@tonic-gate #include <libgen.h>
367c478bd9Sstevel@tonic-gate #include <libintl.h>
377c478bd9Sstevel@tonic-gate #include <alloca.h>
387c478bd9Sstevel@tonic-gate #include <ctype.h>
399acbbeafSnn35248 #include <sys/acl.h>
409acbbeafSnn35248 #include <sys/stat.h>
419acbbeafSnn35248 #include <sys/brand.h>
427c478bd9Sstevel@tonic-gate #include <sys/mntio.h>
437c478bd9Sstevel@tonic-gate #include <sys/mnttab.h>
44cf8f45c7Sdstaff #include <sys/nvpair.h>
459acbbeafSnn35248 #include <sys/types.h>
46f4b3ec61Sdh155122 #include <sys/sockio.h>
475679c89fSjv227347 #include <sys/systeminfo.h>
48ee519a1fSgjelinek #include <ftw.h>
490209230bSgjelinek #include <pool.h>
500209230bSgjelinek #include <libscf.h>
510209230bSgjelinek #include <libproc.h>
520209230bSgjelinek #include <sys/priocntl.h>
5339935be5Sgjelinek #include <libuutil.h>
54ff17c8bfSgjelinek #include <wait.h>
55ff17c8bfSgjelinek #include <bsm/adt.h>
56cb8a054bSGlenn Faden #include <auth_attr.h>
57cb8a054bSGlenn Faden #include <auth_list.h>
58cb8a054bSGlenn Faden #include <secdb.h>
59cb8a054bSGlenn Faden #include <user_attr.h>
60cb8a054bSGlenn Faden #include <prof_attr.h>
617c478bd9Sstevel@tonic-gate
627c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
637c478bd9Sstevel@tonic-gate #include <netdb.h>
647c478bd9Sstevel@tonic-gate
657c478bd9Sstevel@tonic-gate #include <libxml/xmlmemory.h>
667c478bd9Sstevel@tonic-gate #include <libxml/parser.h>
677c478bd9Sstevel@tonic-gate
687c478bd9Sstevel@tonic-gate #include <libdevinfo.h>
69108322fbScarlsonj #include <uuid/uuid.h>
70ee519a1fSgjelinek #include <dirent.h>
719acbbeafSnn35248 #include <libbrand.h>
72ee519a1fSgjelinek
737c478bd9Sstevel@tonic-gate #include <libzonecfg.h>
747c478bd9Sstevel@tonic-gate #include "zonecfg_impl.h"
757c478bd9Sstevel@tonic-gate
767c478bd9Sstevel@tonic-gate #define _PATH_TMPFILE "/zonecfg.XXXXXX"
77cf8f45c7Sdstaff #define ZONE_CB_RETRY_COUNT 10
78cf8f45c7Sdstaff #define ZONE_EVENT_PING_SUBCLASS "ping"
79cf8f45c7Sdstaff #define ZONE_EVENT_PING_PUBLISHER "solaris"
807c478bd9Sstevel@tonic-gate
817c478bd9Sstevel@tonic-gate /* Hard-code the DTD element/attribute/entity names just once, here. */
827c478bd9Sstevel@tonic-gate #define DTD_ELEM_ATTR (const xmlChar *) "attr"
837c478bd9Sstevel@tonic-gate #define DTD_ELEM_COMMENT (const xmlChar *) "comment"
847c478bd9Sstevel@tonic-gate #define DTD_ELEM_DEVICE (const xmlChar *) "device"
857c478bd9Sstevel@tonic-gate #define DTD_ELEM_FS (const xmlChar *) "filesystem"
867c478bd9Sstevel@tonic-gate #define DTD_ELEM_FSOPTION (const xmlChar *) "fsoption"
877c478bd9Sstevel@tonic-gate #define DTD_ELEM_NET (const xmlChar *) "network"
887c478bd9Sstevel@tonic-gate #define DTD_ELEM_RCTL (const xmlChar *) "rctl"
897c478bd9Sstevel@tonic-gate #define DTD_ELEM_RCTLVALUE (const xmlChar *) "rctl-value"
907c478bd9Sstevel@tonic-gate #define DTD_ELEM_ZONE (const xmlChar *) "zone"
91fa9e4066Sahrens #define DTD_ELEM_DATASET (const xmlChar *) "dataset"
920209230bSgjelinek #define DTD_ELEM_TMPPOOL (const xmlChar *) "tmp_pool"
930209230bSgjelinek #define DTD_ELEM_PSET (const xmlChar *) "pset"
940209230bSgjelinek #define DTD_ELEM_MCAP (const xmlChar *) "mcap"
95ee519a1fSgjelinek #define DTD_ELEM_PACKAGE (const xmlChar *) "package"
966cfd72c6Sgjelinek #define DTD_ELEM_OBSOLETES (const xmlChar *) "obsoletes"
97ee519a1fSgjelinek #define DTD_ELEM_DEV_PERM (const xmlChar *) "dev-perm"
98cb8a054bSGlenn Faden #define DTD_ELEM_ADMIN (const xmlChar *) "admin"
997c478bd9Sstevel@tonic-gate
1007c478bd9Sstevel@tonic-gate #define DTD_ATTR_ACTION (const xmlChar *) "action"
1017c478bd9Sstevel@tonic-gate #define DTD_ATTR_ADDRESS (const xmlChar *) "address"
102550b6e40SSowmini Varadhan #define DTD_ATTR_ALLOWED_ADDRESS (const xmlChar *) "allowed-address"
1037c478bd9Sstevel@tonic-gate #define DTD_ATTR_AUTOBOOT (const xmlChar *) "autoboot"
104f4b3ec61Sdh155122 #define DTD_ATTR_IPTYPE (const xmlChar *) "ip-type"
105de860bd9Sgfaden #define DTD_ATTR_DEFROUTER (const xmlChar *) "defrouter"
1067c478bd9Sstevel@tonic-gate #define DTD_ATTR_DIR (const xmlChar *) "directory"
1077c478bd9Sstevel@tonic-gate #define DTD_ATTR_LIMIT (const xmlChar *) "limit"
108ffbafc53Scomay #define DTD_ATTR_LIMITPRIV (const xmlChar *) "limitpriv"
1093f2f09c1Sdp #define DTD_ATTR_BOOTARGS (const xmlChar *) "bootargs"
1100209230bSgjelinek #define DTD_ATTR_SCHED (const xmlChar *) "scheduling-class"
1117c478bd9Sstevel@tonic-gate #define DTD_ATTR_MATCH (const xmlChar *) "match"
1127c478bd9Sstevel@tonic-gate #define DTD_ATTR_NAME (const xmlChar *) "name"
1137c478bd9Sstevel@tonic-gate #define DTD_ATTR_PHYSICAL (const xmlChar *) "physical"
1147c478bd9Sstevel@tonic-gate #define DTD_ATTR_POOL (const xmlChar *) "pool"
1157c478bd9Sstevel@tonic-gate #define DTD_ATTR_PRIV (const xmlChar *) "priv"
1167c478bd9Sstevel@tonic-gate #define DTD_ATTR_RAW (const xmlChar *) "raw"
1177c478bd9Sstevel@tonic-gate #define DTD_ATTR_SPECIAL (const xmlChar *) "special"
1187c478bd9Sstevel@tonic-gate #define DTD_ATTR_TYPE (const xmlChar *) "type"
1197c478bd9Sstevel@tonic-gate #define DTD_ATTR_VALUE (const xmlChar *) "value"
1207c478bd9Sstevel@tonic-gate #define DTD_ATTR_ZONEPATH (const xmlChar *) "zonepath"
1210209230bSgjelinek #define DTD_ATTR_NCPU_MIN (const xmlChar *) "ncpu_min"
1220209230bSgjelinek #define DTD_ATTR_NCPU_MAX (const xmlChar *) "ncpu_max"
1230209230bSgjelinek #define DTD_ATTR_IMPORTANCE (const xmlChar *) "importance"
1240209230bSgjelinek #define DTD_ATTR_PHYSCAP (const xmlChar *) "physcap"
125ee519a1fSgjelinek #define DTD_ATTR_VERSION (const xmlChar *) "version"
126ee519a1fSgjelinek #define DTD_ATTR_ID (const xmlChar *) "id"
127ee519a1fSgjelinek #define DTD_ATTR_UID (const xmlChar *) "uid"
128ee519a1fSgjelinek #define DTD_ATTR_GID (const xmlChar *) "gid"
129ee519a1fSgjelinek #define DTD_ATTR_MODE (const xmlChar *) "mode"
130ee519a1fSgjelinek #define DTD_ATTR_ACL (const xmlChar *) "acl"
1319acbbeafSnn35248 #define DTD_ATTR_BRAND (const xmlChar *) "brand"
1325679c89fSjv227347 #define DTD_ATTR_HOSTID (const xmlChar *) "hostid"
133cb8a054bSGlenn Faden #define DTD_ATTR_USER (const xmlChar *) "user"
134cb8a054bSGlenn Faden #define DTD_ATTR_AUTHS (const xmlChar *) "auths"
1350fbb751dSJohn Levon #define DTD_ATTR_FS_ALLOWED (const xmlChar *) "fs-allowed"
1367c478bd9Sstevel@tonic-gate
1377c478bd9Sstevel@tonic-gate #define DTD_ENTITY_BOOLEAN "boolean"
1387c478bd9Sstevel@tonic-gate #define DTD_ENTITY_DEVPATH "devpath"
1397c478bd9Sstevel@tonic-gate #define DTD_ENTITY_DRIVER "driver"
1407c478bd9Sstevel@tonic-gate #define DTD_ENTITY_DRVMIN "drv_min"
1417c478bd9Sstevel@tonic-gate #define DTD_ENTITY_FALSE "false"
1427c478bd9Sstevel@tonic-gate #define DTD_ENTITY_INT "int"
1437c478bd9Sstevel@tonic-gate #define DTD_ENTITY_STRING "string"
1447c478bd9Sstevel@tonic-gate #define DTD_ENTITY_TRUE "true"
1457c478bd9Sstevel@tonic-gate #define DTD_ENTITY_UINT "uint"
1467c478bd9Sstevel@tonic-gate
147a1be23daSdp #define DTD_ENTITY_BOOL_LEN 6 /* "false" */
148a1be23daSdp
149ee519a1fSgjelinek #define ATTACH_FORCED "SUNWattached.xml"
150ee519a1fSgjelinek
1510209230bSgjelinek #define TMP_POOL_NAME "SUNWtmp_%s"
1520209230bSgjelinek #define MAX_TMP_POOL_NAME (ZONENAME_MAX + 9)
1530209230bSgjelinek #define RCAP_SERVICE "system/rcap:default"
1540209230bSgjelinek #define POOLD_SERVICE "system/pools/dynamic:default"
1550209230bSgjelinek
1560209230bSgjelinek /*
1570209230bSgjelinek * rctl alias definitions
1580209230bSgjelinek *
1590209230bSgjelinek * This holds the alias, the full rctl name, the default priv value, action
1600209230bSgjelinek * and lower limit. The functions that handle rctl aliases step through
1610209230bSgjelinek * this table, matching on the alias, and using the full values for setting
1620209230bSgjelinek * the rctl entry as well the limit for validation.
1630209230bSgjelinek */
1640209230bSgjelinek static struct alias {
1650209230bSgjelinek char *shortname;
1660209230bSgjelinek char *realname;
1670209230bSgjelinek char *priv;
1680209230bSgjelinek char *action;
1690209230bSgjelinek uint64_t low_limit;
1700209230bSgjelinek } aliases[] = {
1710209230bSgjelinek {ALIAS_MAXLWPS, "zone.max-lwps", "privileged", "deny", 100},
1720209230bSgjelinek {ALIAS_MAXSHMMEM, "zone.max-shm-memory", "privileged", "deny", 0},
1730209230bSgjelinek {ALIAS_MAXSHMIDS, "zone.max-shm-ids", "privileged", "deny", 0},
1740209230bSgjelinek {ALIAS_MAXMSGIDS, "zone.max-msg-ids", "privileged", "deny", 0},
1750209230bSgjelinek {ALIAS_MAXSEMIDS, "zone.max-sem-ids", "privileged", "deny", 0},
1760209230bSgjelinek {ALIAS_MAXLOCKEDMEM, "zone.max-locked-memory", "privileged", "deny", 0},
1770209230bSgjelinek {ALIAS_MAXSWAP, "zone.max-swap", "privileged", "deny", 0},
1780209230bSgjelinek {ALIAS_SHARES, "zone.cpu-shares", "privileged", "none", 0},
179c97ad5cdSakolb {ALIAS_CPUCAP, "zone.cpu-cap", "privileged", "deny", 0},
180ff19e029SMenno Lageman {ALIAS_MAXPROCS, "zone.max-processes", "privileged", "deny", 100},
1810209230bSgjelinek {NULL, NULL, NULL, NULL, 0}
1820209230bSgjelinek };
1830209230bSgjelinek
1840209230bSgjelinek /*
1850209230bSgjelinek * Structure for applying rctls to a running zone. It allows important
1860209230bSgjelinek * process values to be passed together easily.
1870209230bSgjelinek */
1880209230bSgjelinek typedef struct pr_info_handle {
1890209230bSgjelinek struct ps_prochandle *pr;
1900209230bSgjelinek pid_t pid;
1910209230bSgjelinek } pr_info_handle_t;
1920209230bSgjelinek
1937c478bd9Sstevel@tonic-gate struct zone_dochandle {
1947c478bd9Sstevel@tonic-gate char *zone_dh_rootdir;
1957c478bd9Sstevel@tonic-gate xmlDocPtr zone_dh_doc;
1967c478bd9Sstevel@tonic-gate xmlNodePtr zone_dh_cur;
1977c478bd9Sstevel@tonic-gate xmlNodePtr zone_dh_top;
198087719fdSdp boolean_t zone_dh_newzone;
199087719fdSdp boolean_t zone_dh_snapshot;
200ee519a1fSgjelinek boolean_t zone_dh_sw_inv;
201cb8a054bSGlenn Faden zone_userauths_t *zone_dh_userauths;
202087719fdSdp char zone_dh_delete_name[ZONENAME_MAX];
2037c478bd9Sstevel@tonic-gate };
2047c478bd9Sstevel@tonic-gate
205cf8f45c7Sdstaff struct znotify {
206cf8f45c7Sdstaff void * zn_private;
207cf8f45c7Sdstaff evchan_t *zn_eventchan;
208cf8f45c7Sdstaff int (*zn_callback)(const char *zonename, zoneid_t zid,
209cf8f45c7Sdstaff const char *newstate, const char *oldstate, hrtime_t when, void *p);
210cf8f45c7Sdstaff pthread_mutex_t zn_mutex;
211cf8f45c7Sdstaff pthread_cond_t zn_cond;
212cf8f45c7Sdstaff pthread_mutex_t zn_bigmutex;
213cf8f45c7Sdstaff volatile enum {ZN_UNLOCKED, ZN_LOCKED, ZN_PING_INFLIGHT,
214cf8f45c7Sdstaff ZN_PING_RECEIVED} zn_state;
215cf8f45c7Sdstaff char zn_subscriber_id[MAX_SUBID_LEN];
216cf8f45c7Sdstaff volatile boolean_t zn_failed;
217cf8f45c7Sdstaff int zn_failure_count;
218cf8f45c7Sdstaff };
219cf8f45c7Sdstaff
220ff17c8bfSgjelinek /* used to track nested zone-lock operations */
221ff17c8bfSgjelinek static int zone_lock_cnt = 0;
222ee519a1fSgjelinek
223ff17c8bfSgjelinek /* used to communicate lock status to children */
224ff17c8bfSgjelinek #define LOCK_ENV_VAR "_ZONEADM_LOCK_HELD"
225ff17c8bfSgjelinek static char zoneadm_lock_held[] = LOCK_ENV_VAR"=1";
226ff17c8bfSgjelinek static char zoneadm_lock_not_held[] = LOCK_ENV_VAR"=0";
22739935be5Sgjelinek
228108322fbScarlsonj char *zonecfg_root = "";
229108322fbScarlsonj
2307c478bd9Sstevel@tonic-gate /*
2317c478bd9Sstevel@tonic-gate * For functions which return int, which is most of the functions herein,
2327c478bd9Sstevel@tonic-gate * the return values should be from the Z_foo set defined in <libzonecfg.h>.
2337c478bd9Sstevel@tonic-gate * In some instances, we take pains mapping some libc errno values to Z_foo
2347c478bd9Sstevel@tonic-gate * values from this set.
2357c478bd9Sstevel@tonic-gate */
2367c478bd9Sstevel@tonic-gate
2377c478bd9Sstevel@tonic-gate /*
238108322fbScarlsonj * Set the root (/) path for all zonecfg configuration files. This is a
239108322fbScarlsonj * private interface used by Live Upgrade extensions to access zone
240108322fbScarlsonj * configuration inside mounted alternate boot environments.
2412a8b76b2SSusan Kamm-Worrell * This interface is also used by zoneadm mount and unmount subcommands.
242108322fbScarlsonj */
243108322fbScarlsonj void
zonecfg_set_root(const char * rootpath)244108322fbScarlsonj zonecfg_set_root(const char *rootpath)
245108322fbScarlsonj {
246108322fbScarlsonj if (*zonecfg_root != '\0')
247108322fbScarlsonj free(zonecfg_root);
248108322fbScarlsonj if (rootpath == NULL || rootpath[0] == '\0' || rootpath[1] == '\0' ||
249108322fbScarlsonj (zonecfg_root = strdup(rootpath)) == NULL)
250108322fbScarlsonj zonecfg_root = "";
251108322fbScarlsonj }
252108322fbScarlsonj
253108322fbScarlsonj const char *
zonecfg_get_root(void)254108322fbScarlsonj zonecfg_get_root(void)
255108322fbScarlsonj {
256108322fbScarlsonj return (zonecfg_root);
257108322fbScarlsonj }
258108322fbScarlsonj
259108322fbScarlsonj boolean_t
zonecfg_in_alt_root(void)260108322fbScarlsonj zonecfg_in_alt_root(void)
261108322fbScarlsonj {
262108322fbScarlsonj return (*zonecfg_root != '\0');
263108322fbScarlsonj }
264108322fbScarlsonj
265108322fbScarlsonj /*
2667c478bd9Sstevel@tonic-gate * Callers of the _file_path() functions are expected to have the second
2677c478bd9Sstevel@tonic-gate * parameter be a (char foo[MAXPATHLEN]).
2687c478bd9Sstevel@tonic-gate */
2697c478bd9Sstevel@tonic-gate
270108322fbScarlsonj static boolean_t
config_file_path(const char * zonename,char * answer)2717c478bd9Sstevel@tonic-gate config_file_path(const char *zonename, char *answer)
2727c478bd9Sstevel@tonic-gate {
273108322fbScarlsonj return (snprintf(answer, MAXPATHLEN, "%s%s/%s.xml", zonecfg_root,
274108322fbScarlsonj ZONE_CONFIG_ROOT, zonename) < MAXPATHLEN);
2757c478bd9Sstevel@tonic-gate }
2767c478bd9Sstevel@tonic-gate
277108322fbScarlsonj static boolean_t
snap_file_path(const char * zonename,char * answer)278108322fbScarlsonj snap_file_path(const char *zonename, char *answer)
2797c478bd9Sstevel@tonic-gate {
280108322fbScarlsonj return (snprintf(answer, MAXPATHLEN, "%s%s/%s.snapshot.xml",
281108322fbScarlsonj zonecfg_root, ZONE_SNAPSHOT_ROOT, zonename) < MAXPATHLEN);
2827c478bd9Sstevel@tonic-gate }
2837c478bd9Sstevel@tonic-gate
2847c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2857c478bd9Sstevel@tonic-gate static void
zonecfg_error_func(void * ctx,const char * msg,...)2867c478bd9Sstevel@tonic-gate zonecfg_error_func(void *ctx, const char *msg, ...)
2877c478bd9Sstevel@tonic-gate {
2887c478bd9Sstevel@tonic-gate /*
2897c478bd9Sstevel@tonic-gate * This function does nothing by design. Its purpose is to prevent
2907c478bd9Sstevel@tonic-gate * libxml from dumping unwanted messages to stdout/stderr.
2917c478bd9Sstevel@tonic-gate */
2927c478bd9Sstevel@tonic-gate }
2937c478bd9Sstevel@tonic-gate
2947c478bd9Sstevel@tonic-gate zone_dochandle_t
zonecfg_init_handle(void)2957c478bd9Sstevel@tonic-gate zonecfg_init_handle(void)
2967c478bd9Sstevel@tonic-gate {
297087719fdSdp zone_dochandle_t handle = calloc(1, sizeof (struct zone_dochandle));
2987c478bd9Sstevel@tonic-gate if (handle == NULL) {
2997c478bd9Sstevel@tonic-gate errno = Z_NOMEM;
3007c478bd9Sstevel@tonic-gate return (NULL);
3017c478bd9Sstevel@tonic-gate }
3027c478bd9Sstevel@tonic-gate
3037c478bd9Sstevel@tonic-gate /* generic libxml initialization */
304ced33dd6Sjv227347 (void) xmlLineNumbersDefault(1);
3057c478bd9Sstevel@tonic-gate xmlLoadExtDtdDefaultValue |= XML_DETECT_IDS;
3067c478bd9Sstevel@tonic-gate xmlDoValidityCheckingDefaultValue = 1;
3077c478bd9Sstevel@tonic-gate (void) xmlKeepBlanksDefault(0);
3087c478bd9Sstevel@tonic-gate xmlGetWarningsDefaultValue = 0;
3097c478bd9Sstevel@tonic-gate xmlSetGenericErrorFunc(NULL, zonecfg_error_func);
3107c478bd9Sstevel@tonic-gate
3117c478bd9Sstevel@tonic-gate return (handle);
3127c478bd9Sstevel@tonic-gate }
3137c478bd9Sstevel@tonic-gate
3147c478bd9Sstevel@tonic-gate int
zonecfg_check_handle(zone_dochandle_t handle)3157c478bd9Sstevel@tonic-gate zonecfg_check_handle(zone_dochandle_t handle)
3167c478bd9Sstevel@tonic-gate {
3177c478bd9Sstevel@tonic-gate if (handle == NULL || handle->zone_dh_doc == NULL)
3187c478bd9Sstevel@tonic-gate return (Z_BAD_HANDLE);
3197c478bd9Sstevel@tonic-gate return (Z_OK);
3207c478bd9Sstevel@tonic-gate }
3217c478bd9Sstevel@tonic-gate
3227c478bd9Sstevel@tonic-gate void
zonecfg_fini_handle(zone_dochandle_t handle)3237c478bd9Sstevel@tonic-gate zonecfg_fini_handle(zone_dochandle_t handle)
3247c478bd9Sstevel@tonic-gate {
3257c478bd9Sstevel@tonic-gate if (zonecfg_check_handle(handle) == Z_OK)
3267c478bd9Sstevel@tonic-gate xmlFreeDoc(handle->zone_dh_doc);
3277c478bd9Sstevel@tonic-gate if (handle != NULL)
3287c478bd9Sstevel@tonic-gate free(handle);
3297c478bd9Sstevel@tonic-gate }
3307c478bd9Sstevel@tonic-gate
3317c478bd9Sstevel@tonic-gate static int
zonecfg_destroy_impl(char * filename)3327c478bd9Sstevel@tonic-gate zonecfg_destroy_impl(char *filename)
3337c478bd9Sstevel@tonic-gate {
3347c478bd9Sstevel@tonic-gate if (unlink(filename) == -1) {
3357c478bd9Sstevel@tonic-gate if (errno == EACCES)
3367c478bd9Sstevel@tonic-gate return (Z_ACCES);
3377c478bd9Sstevel@tonic-gate if (errno == ENOENT)
3387c478bd9Sstevel@tonic-gate return (Z_NO_ZONE);
3397c478bd9Sstevel@tonic-gate return (Z_MISC_FS);
3407c478bd9Sstevel@tonic-gate }
3417c478bd9Sstevel@tonic-gate return (Z_OK);
3427c478bd9Sstevel@tonic-gate }
3437c478bd9Sstevel@tonic-gate
3447c478bd9Sstevel@tonic-gate int
zonecfg_destroy(const char * zonename,boolean_t force)345087719fdSdp zonecfg_destroy(const char *zonename, boolean_t force)
3467c478bd9Sstevel@tonic-gate {
3477c478bd9Sstevel@tonic-gate char path[MAXPATHLEN];
348087719fdSdp struct zoneent ze;
349087719fdSdp int err, state_err;
350087719fdSdp zone_state_t state;
3517c478bd9Sstevel@tonic-gate
352108322fbScarlsonj if (!config_file_path(zonename, path))
353108322fbScarlsonj return (Z_MISC_FS);
354087719fdSdp
355087719fdSdp state_err = zone_get_state((char *)zonename, &state);
356087719fdSdp err = access(path, W_OK);
357087719fdSdp
358087719fdSdp /*
359087719fdSdp * If there is no file, and no index entry, reliably indicate that no
360087719fdSdp * such zone exists.
361087719fdSdp */
362087719fdSdp if ((state_err == Z_NO_ZONE) && (err == -1) && (errno == ENOENT))
363087719fdSdp return (Z_NO_ZONE);
364087719fdSdp
365087719fdSdp /*
366087719fdSdp * Handle any other filesystem related errors (except if the XML
367087719fdSdp * file is missing, which we treat silently), unless we're forcing,
368087719fdSdp * in which case we plow on.
369087719fdSdp */
370087719fdSdp if (err == -1 && errno != ENOENT) {
371087719fdSdp if (errno == EACCES)
372087719fdSdp return (Z_ACCES);
373087719fdSdp else if (!force)
374087719fdSdp return (Z_MISC_FS);
375087719fdSdp }
376087719fdSdp
377087719fdSdp if (state > ZONE_STATE_INSTALLED)
378087719fdSdp return (Z_BAD_ZONE_STATE);
379087719fdSdp
380087719fdSdp if (!force && state > ZONE_STATE_CONFIGURED)
381087719fdSdp return (Z_BAD_ZONE_STATE);
382087719fdSdp
383087719fdSdp /*
384087719fdSdp * Index deletion succeeds even if the entry doesn't exist. So this
385087719fdSdp * will fail only if we've had some more severe problem.
386087719fdSdp */
387087719fdSdp bzero(&ze, sizeof (ze));
388087719fdSdp (void) strlcpy(ze.zone_name, zonename, sizeof (ze.zone_name));
389087719fdSdp if ((err = putzoneent(&ze, PZE_REMOVE)) != Z_OK)
390087719fdSdp if (!force)
391087719fdSdp return (err);
392087719fdSdp
393087719fdSdp err = zonecfg_destroy_impl(path);
394087719fdSdp
395087719fdSdp /*
396087719fdSdp * Treat failure to find the XML file silently, since, well, it's
397087719fdSdp * gone, and with the index file cleaned up, we're done.
398087719fdSdp */
399087719fdSdp if (err == Z_OK || err == Z_NO_ZONE)
400087719fdSdp return (Z_OK);
401087719fdSdp return (err);
4027c478bd9Sstevel@tonic-gate }
4037c478bd9Sstevel@tonic-gate
4047c478bd9Sstevel@tonic-gate int
zonecfg_destroy_snapshot(const char * zonename)405108322fbScarlsonj zonecfg_destroy_snapshot(const char *zonename)
4067c478bd9Sstevel@tonic-gate {
4077c478bd9Sstevel@tonic-gate char path[MAXPATHLEN];
4087c478bd9Sstevel@tonic-gate
409108322fbScarlsonj if (!snap_file_path(zonename, path))
410108322fbScarlsonj return (Z_MISC_FS);
4117c478bd9Sstevel@tonic-gate return (zonecfg_destroy_impl(path));
4127c478bd9Sstevel@tonic-gate }
4137c478bd9Sstevel@tonic-gate
4147c478bd9Sstevel@tonic-gate static int
getroot(zone_dochandle_t handle,xmlNodePtr * root)415a1be23daSdp getroot(zone_dochandle_t handle, xmlNodePtr *root)
4167c478bd9Sstevel@tonic-gate {
4177c478bd9Sstevel@tonic-gate if (zonecfg_check_handle(handle) == Z_BAD_HANDLE)
4187c478bd9Sstevel@tonic-gate return (Z_BAD_HANDLE);
4197c478bd9Sstevel@tonic-gate
420a1be23daSdp *root = xmlDocGetRootElement(handle->zone_dh_doc);
421a1be23daSdp
422a1be23daSdp if (*root == NULL)
4237c478bd9Sstevel@tonic-gate return (Z_EMPTY_DOCUMENT);
424a1be23daSdp
425a1be23daSdp if (xmlStrcmp((*root)->name, DTD_ELEM_ZONE))
426a1be23daSdp return (Z_WRONG_DOC_TYPE);
427a1be23daSdp
428a1be23daSdp return (Z_OK);
4297c478bd9Sstevel@tonic-gate }
4307c478bd9Sstevel@tonic-gate
431a1be23daSdp static int
operation_prep(zone_dochandle_t handle)432a1be23daSdp operation_prep(zone_dochandle_t handle)
433a1be23daSdp {
434a1be23daSdp xmlNodePtr root;
435a1be23daSdp int err;
436a1be23daSdp
437a1be23daSdp if ((err = getroot(handle, &root)) != 0)
438a1be23daSdp return (err);
439a1be23daSdp
440a1be23daSdp handle->zone_dh_cur = root;
441a1be23daSdp handle->zone_dh_top = root;
442a1be23daSdp return (Z_OK);
4437c478bd9Sstevel@tonic-gate }
444a1be23daSdp
445a1be23daSdp static int
fetchprop(xmlNodePtr cur,const xmlChar * propname,char * dst,size_t dstsize)446ffbafc53Scomay fetchprop(xmlNodePtr cur, const xmlChar *propname, char *dst, size_t dstsize)
447ffbafc53Scomay {
448ffbafc53Scomay xmlChar *property;
449ffbafc53Scomay size_t srcsize;
450ffbafc53Scomay
451ffbafc53Scomay if ((property = xmlGetProp(cur, propname)) == NULL)
452ffbafc53Scomay return (Z_BAD_PROPERTY);
453ffbafc53Scomay srcsize = strlcpy(dst, (char *)property, dstsize);
454ffbafc53Scomay xmlFree(property);
455ffbafc53Scomay if (srcsize >= dstsize)
456ffbafc53Scomay return (Z_TOO_BIG);
457ffbafc53Scomay return (Z_OK);
458ffbafc53Scomay }
459ffbafc53Scomay
460ffbafc53Scomay static int
fetch_alloc_prop(xmlNodePtr cur,const xmlChar * propname,char ** dst)461ffbafc53Scomay fetch_alloc_prop(xmlNodePtr cur, const xmlChar *propname, char **dst)
462ffbafc53Scomay {
463ffbafc53Scomay xmlChar *property;
464ffbafc53Scomay
465ffbafc53Scomay if ((property = xmlGetProp(cur, propname)) == NULL)
466ffbafc53Scomay return (Z_BAD_PROPERTY);
467ffbafc53Scomay if ((*dst = strdup((char *)property)) == NULL) {
468ffbafc53Scomay xmlFree(property);
469ffbafc53Scomay return (Z_NOMEM);
470ffbafc53Scomay }
471ffbafc53Scomay xmlFree(property);
472ffbafc53Scomay return (Z_OK);
473ffbafc53Scomay }
474ffbafc53Scomay
475ffbafc53Scomay static int
getrootattr(zone_dochandle_t handle,const xmlChar * propname,char * propval,size_t propsize)476a1be23daSdp getrootattr(zone_dochandle_t handle, const xmlChar *propname,
477a1be23daSdp char *propval, size_t propsize)
478a1be23daSdp {
479a1be23daSdp xmlNodePtr root;
480a1be23daSdp int err;
481a1be23daSdp
482a1be23daSdp if ((err = getroot(handle, &root)) != 0)
483a1be23daSdp return (err);
484a1be23daSdp
485ffbafc53Scomay return (fetchprop(root, propname, propval, propsize));
486ffbafc53Scomay }
487ffbafc53Scomay
488ffbafc53Scomay static int
get_alloc_rootattr(zone_dochandle_t handle,const xmlChar * propname,char ** propval)489ffbafc53Scomay get_alloc_rootattr(zone_dochandle_t handle, const xmlChar *propname,
490ffbafc53Scomay char **propval)
491ffbafc53Scomay {
492ffbafc53Scomay xmlNodePtr root;
493ffbafc53Scomay int err;
494ffbafc53Scomay
495ffbafc53Scomay if ((err = getroot(handle, &root)) != 0)
496ffbafc53Scomay return (err);
497ffbafc53Scomay
498ffbafc53Scomay return (fetch_alloc_prop(root, propname, propval));
499a1be23daSdp }
500a1be23daSdp
501a1be23daSdp static int
setrootattr(zone_dochandle_t handle,const xmlChar * propname,const char * propval)502108322fbScarlsonj setrootattr(zone_dochandle_t handle, const xmlChar *propname,
503108322fbScarlsonj const char *propval)
504a1be23daSdp {
505a1be23daSdp int err;
506a1be23daSdp xmlNodePtr root;
507a1be23daSdp
508a1be23daSdp if ((err = getroot(handle, &root)) != Z_OK)
509a1be23daSdp return (err);
510a1be23daSdp
5110209230bSgjelinek /*
5120209230bSgjelinek * If we get a null propval remove the property (ignore return since it
5130209230bSgjelinek * may not be set to begin with).
5140209230bSgjelinek */
5150209230bSgjelinek if (propval == NULL) {
5160209230bSgjelinek (void) xmlUnsetProp(root, propname);
5170209230bSgjelinek } else {
5180209230bSgjelinek if (xmlSetProp(root, propname, (const xmlChar *) propval)
5190209230bSgjelinek == NULL)
520a1be23daSdp return (Z_INVAL);
5210209230bSgjelinek }
5227c478bd9Sstevel@tonic-gate return (Z_OK);
5237c478bd9Sstevel@tonic-gate }
5247c478bd9Sstevel@tonic-gate
525087719fdSdp static void
addcomment(zone_dochandle_t handle,const char * comment)526087719fdSdp addcomment(zone_dochandle_t handle, const char *comment)
527087719fdSdp {
528087719fdSdp xmlNodePtr node;
529087719fdSdp node = xmlNewComment((xmlChar *) comment);
530087719fdSdp
531087719fdSdp if (node != NULL)
532087719fdSdp (void) xmlAddPrevSibling(handle->zone_dh_top, node);
533087719fdSdp }
534087719fdSdp
535087719fdSdp static void
stripcomments(zone_dochandle_t handle)536087719fdSdp stripcomments(zone_dochandle_t handle)
537087719fdSdp {
538087719fdSdp xmlDocPtr top;
539087719fdSdp xmlNodePtr child, next;
540087719fdSdp
541087719fdSdp top = handle->zone_dh_doc;
542087719fdSdp for (child = top->xmlChildrenNode; child != NULL; child = next) {
543087719fdSdp next = child->next;
544087719fdSdp if (child->name == NULL)
545087719fdSdp continue;
546087719fdSdp if (xmlStrcmp(child->name, DTD_ELEM_COMMENT) == 0) {
547087719fdSdp next = child->next;
548087719fdSdp xmlUnlinkNode(child);
549087719fdSdp xmlFreeNode(child);
550087719fdSdp }
551087719fdSdp }
552087719fdSdp }
553087719fdSdp
554ee519a1fSgjelinek static void
strip_sw_inv(zone_dochandle_t handle)555ee519a1fSgjelinek strip_sw_inv(zone_dochandle_t handle)
556ee519a1fSgjelinek {
557ee519a1fSgjelinek xmlNodePtr root, child, next;
558ee519a1fSgjelinek
559ee519a1fSgjelinek root = xmlDocGetRootElement(handle->zone_dh_doc);
560ee519a1fSgjelinek for (child = root->xmlChildrenNode; child != NULL; child = next) {
561ee519a1fSgjelinek next = child->next;
562ee519a1fSgjelinek if (child->name == NULL)
563ee519a1fSgjelinek continue;
5644656d474SGarrett D'Amore if (xmlStrcmp(child->name, DTD_ELEM_PACKAGE) == 0) {
565ee519a1fSgjelinek next = child->next;
566ee519a1fSgjelinek xmlUnlinkNode(child);
567ee519a1fSgjelinek xmlFreeNode(child);
568ee519a1fSgjelinek }
569ee519a1fSgjelinek }
570ee519a1fSgjelinek }
571ee519a1fSgjelinek
5727c478bd9Sstevel@tonic-gate static int
zonecfg_get_handle_impl(const char * zonename,const char * filename,zone_dochandle_t handle)573108322fbScarlsonj zonecfg_get_handle_impl(const char *zonename, const char *filename,
574108322fbScarlsonj zone_dochandle_t handle)
5757c478bd9Sstevel@tonic-gate {
5767c478bd9Sstevel@tonic-gate xmlValidCtxtPtr cvp;
5777c478bd9Sstevel@tonic-gate struct stat statbuf;
5787c478bd9Sstevel@tonic-gate int valid;
5797c478bd9Sstevel@tonic-gate
5807c478bd9Sstevel@tonic-gate if (zonename == NULL)
5817c478bd9Sstevel@tonic-gate return (Z_NO_ZONE);
5829acbbeafSnn35248
5837c478bd9Sstevel@tonic-gate if ((handle->zone_dh_doc = xmlParseFile(filename)) == NULL) {
5847c478bd9Sstevel@tonic-gate /* distinguish file not found vs. found but not parsed */
5857c478bd9Sstevel@tonic-gate if (stat(filename, &statbuf) == 0)
5867c478bd9Sstevel@tonic-gate return (Z_INVALID_DOCUMENT);
5877c478bd9Sstevel@tonic-gate return (Z_NO_ZONE);
5887c478bd9Sstevel@tonic-gate }
5897c478bd9Sstevel@tonic-gate if ((cvp = xmlNewValidCtxt()) == NULL)
5907c478bd9Sstevel@tonic-gate return (Z_NOMEM);
5917c478bd9Sstevel@tonic-gate cvp->error = zonecfg_error_func;
5927c478bd9Sstevel@tonic-gate cvp->warning = zonecfg_error_func;
5937c478bd9Sstevel@tonic-gate valid = xmlValidateDocument(cvp, handle->zone_dh_doc);
5947c478bd9Sstevel@tonic-gate xmlFreeValidCtxt(cvp);
5957c478bd9Sstevel@tonic-gate if (valid == 0)
5967c478bd9Sstevel@tonic-gate return (Z_INVALID_DOCUMENT);
597087719fdSdp
5987c478bd9Sstevel@tonic-gate /* delete any comments such as inherited Sun copyright / ident str */
599087719fdSdp stripcomments(handle);
6007c478bd9Sstevel@tonic-gate return (Z_OK);
6017c478bd9Sstevel@tonic-gate }
6027c478bd9Sstevel@tonic-gate
6037c478bd9Sstevel@tonic-gate int
zonecfg_get_handle(const char * zonename,zone_dochandle_t handle)604108322fbScarlsonj zonecfg_get_handle(const char *zonename, zone_dochandle_t handle)
6057c478bd9Sstevel@tonic-gate {
6067c478bd9Sstevel@tonic-gate char path[MAXPATHLEN];
6077c478bd9Sstevel@tonic-gate
608108322fbScarlsonj if (!config_file_path(zonename, path))
609108322fbScarlsonj return (Z_MISC_FS);
610087719fdSdp handle->zone_dh_newzone = B_FALSE;
611087719fdSdp
6127c478bd9Sstevel@tonic-gate return (zonecfg_get_handle_impl(zonename, path, handle));
6137c478bd9Sstevel@tonic-gate }
6147c478bd9Sstevel@tonic-gate
6157c478bd9Sstevel@tonic-gate int
zonecfg_get_attach_handle(const char * path,const char * fname,const char * zonename,boolean_t preserve_sw,zone_dochandle_t handle)61616ab8c7bSgjelinek zonecfg_get_attach_handle(const char *path, const char *fname,
61716ab8c7bSgjelinek const char *zonename, boolean_t preserve_sw, zone_dochandle_t handle)
618ee519a1fSgjelinek {
619ee519a1fSgjelinek char migpath[MAXPATHLEN];
620ee519a1fSgjelinek int err;
621ee519a1fSgjelinek struct stat buf;
622ee519a1fSgjelinek
623ee519a1fSgjelinek if (snprintf(migpath, sizeof (migpath), "%s/root", path) >=
624ee519a1fSgjelinek sizeof (migpath))
625ee519a1fSgjelinek return (Z_NOMEM);
626ee519a1fSgjelinek
627ee519a1fSgjelinek if (stat(migpath, &buf) == -1 || !S_ISDIR(buf.st_mode))
628ee519a1fSgjelinek return (Z_NO_ZONE);
629ee519a1fSgjelinek
63016ab8c7bSgjelinek if (snprintf(migpath, sizeof (migpath), "%s/%s", path, fname) >=
631ee519a1fSgjelinek sizeof (migpath))
632ee519a1fSgjelinek return (Z_NOMEM);
633ee519a1fSgjelinek
634ee519a1fSgjelinek if ((err = zonecfg_get_handle_impl(zonename, migpath, handle)) != Z_OK)
635ee519a1fSgjelinek return (err);
636ee519a1fSgjelinek
637ee519a1fSgjelinek if (!preserve_sw)
638ee519a1fSgjelinek strip_sw_inv(handle);
639ee519a1fSgjelinek
640ee519a1fSgjelinek handle->zone_dh_newzone = B_TRUE;
641ee519a1fSgjelinek if ((err = setrootattr(handle, DTD_ATTR_ZONEPATH, path)) != Z_OK)
642ee519a1fSgjelinek return (err);
643ee519a1fSgjelinek
644ee519a1fSgjelinek return (setrootattr(handle, DTD_ATTR_NAME, zonename));
645ee519a1fSgjelinek }
646ee519a1fSgjelinek
647ee519a1fSgjelinek int
zonecfg_get_snapshot_handle(const char * zonename,zone_dochandle_t handle)648108322fbScarlsonj zonecfg_get_snapshot_handle(const char *zonename, zone_dochandle_t handle)
6497c478bd9Sstevel@tonic-gate {
6507c478bd9Sstevel@tonic-gate char path[MAXPATHLEN];
6517c478bd9Sstevel@tonic-gate
652108322fbScarlsonj if (!snap_file_path(zonename, path))
653108322fbScarlsonj return (Z_MISC_FS);
654087719fdSdp handle->zone_dh_newzone = B_FALSE;
6557c478bd9Sstevel@tonic-gate return (zonecfg_get_handle_impl(zonename, path, handle));
6567c478bd9Sstevel@tonic-gate }
6577c478bd9Sstevel@tonic-gate
6587c478bd9Sstevel@tonic-gate int
zonecfg_get_template_handle(const char * template,const char * zonename,zone_dochandle_t handle)659108322fbScarlsonj zonecfg_get_template_handle(const char *template, const char *zonename,
660087719fdSdp zone_dochandle_t handle)
661087719fdSdp {
662087719fdSdp char path[MAXPATHLEN];
663087719fdSdp int err;
664087719fdSdp
665108322fbScarlsonj if (!config_file_path(template, path))
666108322fbScarlsonj return (Z_MISC_FS);
667087719fdSdp
668087719fdSdp if ((err = zonecfg_get_handle_impl(template, path, handle)) != Z_OK)
669087719fdSdp return (err);
670087719fdSdp handle->zone_dh_newzone = B_TRUE;
671087719fdSdp return (setrootattr(handle, DTD_ATTR_NAME, zonename));
672087719fdSdp }
673087719fdSdp
6749acbbeafSnn35248 int
zonecfg_get_xml_handle(const char * path,zone_dochandle_t handle)6759acbbeafSnn35248 zonecfg_get_xml_handle(const char *path, zone_dochandle_t handle)
6769acbbeafSnn35248 {
6779acbbeafSnn35248 struct stat buf;
6789acbbeafSnn35248 int err;
6799acbbeafSnn35248
6809acbbeafSnn35248 if (stat(path, &buf) == -1)
6819acbbeafSnn35248 return (Z_MISC_FS);
6829acbbeafSnn35248
6839acbbeafSnn35248 if ((err = zonecfg_get_handle_impl("xml", path, handle)) != Z_OK)
6849acbbeafSnn35248 return (err);
6859acbbeafSnn35248 handle->zone_dh_newzone = B_TRUE;
6869acbbeafSnn35248 return (Z_OK);
6879acbbeafSnn35248 }
6889acbbeafSnn35248
6898cd327d5Sgjelinek /*
6908cd327d5Sgjelinek * Initialize two handles from the manifest read on fd. The rem_handle
6918cd327d5Sgjelinek * is initialized from the input file, including the sw inventory. The
6928cd327d5Sgjelinek * local_handle is initialized with the same zone configuration but with
6938cd327d5Sgjelinek * no sw inventory.
6948cd327d5Sgjelinek */
6958cd327d5Sgjelinek int
zonecfg_attach_manifest(int fd,zone_dochandle_t local_handle,zone_dochandle_t rem_handle)6968cd327d5Sgjelinek zonecfg_attach_manifest(int fd, zone_dochandle_t local_handle,
6978cd327d5Sgjelinek zone_dochandle_t rem_handle)
6988cd327d5Sgjelinek {
6998cd327d5Sgjelinek xmlValidCtxtPtr cvp;
7008cd327d5Sgjelinek int valid;
7018cd327d5Sgjelinek
7028cd327d5Sgjelinek /* load the manifest into the handle for the remote system */
7038cd327d5Sgjelinek if ((rem_handle->zone_dh_doc = xmlReadFd(fd, NULL, NULL, 0)) == NULL) {
7048cd327d5Sgjelinek return (Z_INVALID_DOCUMENT);
7058cd327d5Sgjelinek }
7068cd327d5Sgjelinek if ((cvp = xmlNewValidCtxt()) == NULL)
7078cd327d5Sgjelinek return (Z_NOMEM);
7088cd327d5Sgjelinek cvp->error = zonecfg_error_func;
7098cd327d5Sgjelinek cvp->warning = zonecfg_error_func;
7108cd327d5Sgjelinek valid = xmlValidateDocument(cvp, rem_handle->zone_dh_doc);
7118cd327d5Sgjelinek xmlFreeValidCtxt(cvp);
7128cd327d5Sgjelinek if (valid == 0)
7138cd327d5Sgjelinek return (Z_INVALID_DOCUMENT);
7148cd327d5Sgjelinek
7158cd327d5Sgjelinek /* delete any comments such as inherited Sun copyright / ident str */
7168cd327d5Sgjelinek stripcomments(rem_handle);
7178cd327d5Sgjelinek
7188cd327d5Sgjelinek rem_handle->zone_dh_newzone = B_TRUE;
7198cd327d5Sgjelinek rem_handle->zone_dh_sw_inv = B_TRUE;
7208cd327d5Sgjelinek
7218cd327d5Sgjelinek /*
7228cd327d5Sgjelinek * Now use the remote system handle to generate a local system handle
7238cd327d5Sgjelinek * with an identical zones configuration but no sw inventory.
7248cd327d5Sgjelinek */
7258cd327d5Sgjelinek if ((local_handle->zone_dh_doc = xmlCopyDoc(rem_handle->zone_dh_doc,
7268cd327d5Sgjelinek 1)) == NULL) {
7278cd327d5Sgjelinek return (Z_INVALID_DOCUMENT);
7288cd327d5Sgjelinek }
7298cd327d5Sgjelinek
7308cd327d5Sgjelinek /*
7318cd327d5Sgjelinek * We need to re-run xmlValidateDocument on local_handle to properly
7328cd327d5Sgjelinek * update the in-core representation of the configuration.
7338cd327d5Sgjelinek */
7348cd327d5Sgjelinek if ((cvp = xmlNewValidCtxt()) == NULL)
7358cd327d5Sgjelinek return (Z_NOMEM);
7368cd327d5Sgjelinek cvp->error = zonecfg_error_func;
7378cd327d5Sgjelinek cvp->warning = zonecfg_error_func;
7388cd327d5Sgjelinek valid = xmlValidateDocument(cvp, local_handle->zone_dh_doc);
7398cd327d5Sgjelinek xmlFreeValidCtxt(cvp);
7408cd327d5Sgjelinek if (valid == 0)
7418cd327d5Sgjelinek return (Z_INVALID_DOCUMENT);
7428cd327d5Sgjelinek
7438cd327d5Sgjelinek strip_sw_inv(local_handle);
7448cd327d5Sgjelinek
7458cd327d5Sgjelinek local_handle->zone_dh_newzone = B_TRUE;
7468cd327d5Sgjelinek local_handle->zone_dh_sw_inv = B_FALSE;
7478cd327d5Sgjelinek
7488cd327d5Sgjelinek return (Z_OK);
7498cd327d5Sgjelinek }
7508cd327d5Sgjelinek
751087719fdSdp static boolean_t
is_renaming(zone_dochandle_t handle)752087719fdSdp is_renaming(zone_dochandle_t handle)
753087719fdSdp {
754087719fdSdp if (handle->zone_dh_newzone)
755087719fdSdp return (B_FALSE);
756087719fdSdp if (strlen(handle->zone_dh_delete_name) > 0)
757087719fdSdp return (B_TRUE);
758087719fdSdp return (B_FALSE);
759087719fdSdp }
760087719fdSdp
761087719fdSdp static boolean_t
is_new(zone_dochandle_t handle)762087719fdSdp is_new(zone_dochandle_t handle)
763087719fdSdp {
764087719fdSdp return (handle->zone_dh_newzone || handle->zone_dh_snapshot);
765087719fdSdp }
766087719fdSdp
767087719fdSdp static boolean_t
is_snapshot(zone_dochandle_t handle)768087719fdSdp is_snapshot(zone_dochandle_t handle)
769087719fdSdp {
770087719fdSdp return (handle->zone_dh_snapshot);
771087719fdSdp }
772087719fdSdp
773087719fdSdp /*
774087719fdSdp * It would be great to be able to use libc's ctype(3c) macros, but we
775087719fdSdp * can't, as they are locale sensitive, and it would break our limited thread
776087719fdSdp * safety if this routine had to change the app locale on the fly.
777087719fdSdp */
778087719fdSdp int
zonecfg_validate_zonename(const char * zone)779108322fbScarlsonj zonecfg_validate_zonename(const char *zone)
780087719fdSdp {
781087719fdSdp int i;
782087719fdSdp
783087719fdSdp if (strcmp(zone, GLOBAL_ZONENAME) == 0)
784087719fdSdp return (Z_BOGUS_ZONE_NAME);
785087719fdSdp
786087719fdSdp if (strlen(zone) >= ZONENAME_MAX)
787087719fdSdp return (Z_BOGUS_ZONE_NAME);
788087719fdSdp
789087719fdSdp if (!((zone[0] >= 'a' && zone[0] <= 'z') ||
790087719fdSdp (zone[0] >= 'A' && zone[0] <= 'Z') ||
791087719fdSdp (zone[0] >= '0' && zone[0] <= '9')))
792087719fdSdp return (Z_BOGUS_ZONE_NAME);
793087719fdSdp
794087719fdSdp for (i = 1; zone[i] != '\0'; i++) {
795087719fdSdp if (!((zone[i] >= 'a' && zone[i] <= 'z') ||
796087719fdSdp (zone[i] >= 'A' && zone[i] <= 'Z') ||
797087719fdSdp (zone[i] >= '0' && zone[i] <= '9') ||
798087719fdSdp (zone[i] == '-') || (zone[i] == '_') || (zone[i] == '.')))
799087719fdSdp return (Z_BOGUS_ZONE_NAME);
800087719fdSdp }
801087719fdSdp
802087719fdSdp return (Z_OK);
803087719fdSdp }
804087719fdSdp
805087719fdSdp /*
806087719fdSdp * Changing the zone name requires us to track both the old and new
807087719fdSdp * name of the zone until commit time.
808087719fdSdp */
809087719fdSdp int
zonecfg_get_name(zone_dochandle_t handle,char * name,size_t namesize)8107c478bd9Sstevel@tonic-gate zonecfg_get_name(zone_dochandle_t handle, char *name, size_t namesize)
8117c478bd9Sstevel@tonic-gate {
812a1be23daSdp return (getrootattr(handle, DTD_ATTR_NAME, name, namesize));
8137c478bd9Sstevel@tonic-gate }
8147c478bd9Sstevel@tonic-gate
815cb8a054bSGlenn Faden static int
insert_admins(zone_dochandle_t handle,char * zonename)816cb8a054bSGlenn Faden insert_admins(zone_dochandle_t handle, char *zonename)
817cb8a054bSGlenn Faden {
818cb8a054bSGlenn Faden int err;
819cb8a054bSGlenn Faden struct zone_admintab admintab;
820cb8a054bSGlenn Faden
821cb8a054bSGlenn Faden if ((err = zonecfg_setadminent(handle)) != Z_OK) {
822cb8a054bSGlenn Faden return (err);
823cb8a054bSGlenn Faden }
824cb8a054bSGlenn Faden while (zonecfg_getadminent(handle, &admintab) == Z_OK) {
825cb8a054bSGlenn Faden err = zonecfg_insert_userauths(handle,
826cb8a054bSGlenn Faden admintab.zone_admin_user, zonename);
827cb8a054bSGlenn Faden if (err != Z_OK) {
828cb8a054bSGlenn Faden (void) zonecfg_endadminent(handle);
829cb8a054bSGlenn Faden return (err);
830cb8a054bSGlenn Faden }
831cb8a054bSGlenn Faden }
832cb8a054bSGlenn Faden (void) zonecfg_endadminent(handle);
833cb8a054bSGlenn Faden return (Z_OK);
834cb8a054bSGlenn Faden }
835cb8a054bSGlenn Faden
836a1be23daSdp int
zonecfg_set_name(zone_dochandle_t handle,char * name)837a1be23daSdp zonecfg_set_name(zone_dochandle_t handle, char *name)
838a1be23daSdp {
839087719fdSdp zone_state_t state;
840087719fdSdp char curname[ZONENAME_MAX], old_delname[ZONENAME_MAX];
841087719fdSdp int err;
842087719fdSdp
843087719fdSdp if ((err = getrootattr(handle, DTD_ATTR_NAME, curname,
844087719fdSdp sizeof (curname))) != Z_OK)
845087719fdSdp return (err);
846087719fdSdp
847087719fdSdp if (strcmp(name, curname) == 0)
848087719fdSdp return (Z_OK);
849087719fdSdp
850087719fdSdp /*
851087719fdSdp * Switching zone names to one beginning with SUNW is not permitted.
852087719fdSdp */
853087719fdSdp if (strncmp(name, "SUNW", 4) == 0)
854087719fdSdp return (Z_BOGUS_ZONE_NAME);
855087719fdSdp
856087719fdSdp if ((err = zonecfg_validate_zonename(name)) != Z_OK)
857087719fdSdp return (err);
858087719fdSdp
859087719fdSdp /*
860087719fdSdp * Setting the name back to the original name (effectively a revert of
861087719fdSdp * the name) is fine. But if we carry on, we'll falsely identify the
862087719fdSdp * name as "in use," so special case here.
863087719fdSdp */
864087719fdSdp if (strcmp(name, handle->zone_dh_delete_name) == 0) {
865087719fdSdp err = setrootattr(handle, DTD_ATTR_NAME, name);
866087719fdSdp handle->zone_dh_delete_name[0] = '\0';
867087719fdSdp return (err);
868087719fdSdp }
869087719fdSdp
870087719fdSdp /* Check to see if new name chosen is already in use */
871087719fdSdp if (zone_get_state(name, &state) != Z_NO_ZONE)
872087719fdSdp return (Z_NAME_IN_USE);
873087719fdSdp
874087719fdSdp /*
875087719fdSdp * If this isn't already "new" or in a renaming transition, then
876087719fdSdp * we're initiating a rename here; so stash the "delete name"
877087719fdSdp * (i.e. the name of the zone we'll be removing) for the rename.
878087719fdSdp */
879087719fdSdp (void) strlcpy(old_delname, handle->zone_dh_delete_name,
880087719fdSdp sizeof (old_delname));
881087719fdSdp if (!is_new(handle) && !is_renaming(handle)) {
882087719fdSdp /*
883087719fdSdp * Name change is allowed only when the zone we're altering
884087719fdSdp * is not ready or running.
885087719fdSdp */
886087719fdSdp err = zone_get_state(curname, &state);
887087719fdSdp if (err == Z_OK) {
888087719fdSdp if (state > ZONE_STATE_INSTALLED)
889087719fdSdp return (Z_BAD_ZONE_STATE);
890087719fdSdp } else if (err != Z_NO_ZONE) {
891087719fdSdp return (err);
892087719fdSdp }
893087719fdSdp
894087719fdSdp (void) strlcpy(handle->zone_dh_delete_name, curname,
895087719fdSdp sizeof (handle->zone_dh_delete_name));
896087719fdSdp assert(is_renaming(handle));
897087719fdSdp } else if (is_renaming(handle)) {
898087719fdSdp err = zone_get_state(handle->zone_dh_delete_name, &state);
899087719fdSdp if (err == Z_OK) {
900087719fdSdp if (state > ZONE_STATE_INSTALLED)
901087719fdSdp return (Z_BAD_ZONE_STATE);
902087719fdSdp } else if (err != Z_NO_ZONE) {
903087719fdSdp return (err);
904087719fdSdp }
905087719fdSdp }
906087719fdSdp
907087719fdSdp if ((err = setrootattr(handle, DTD_ATTR_NAME, name)) != Z_OK) {
908087719fdSdp /*
909087719fdSdp * Restore the deletename to whatever it was at the
910087719fdSdp * top of the routine, since we've had a failure.
911087719fdSdp */
912087719fdSdp (void) strlcpy(handle->zone_dh_delete_name, old_delname,
913087719fdSdp sizeof (handle->zone_dh_delete_name));
914087719fdSdp return (err);
915087719fdSdp }
916087719fdSdp
917cb8a054bSGlenn Faden /*
918cb8a054bSGlenn Faden * Record the old admins from the old zonename
919cb8a054bSGlenn Faden * so that they can be deleted when the operation is committed.
920cb8a054bSGlenn Faden */
921cb8a054bSGlenn Faden if ((err = insert_admins(handle, curname)) != Z_OK)
922cb8a054bSGlenn Faden return (err);
923cb8a054bSGlenn Faden else
924087719fdSdp return (Z_OK);
9257c478bd9Sstevel@tonic-gate }
926a1be23daSdp
927a1be23daSdp int
zonecfg_get_zonepath(zone_dochandle_t handle,char * path,size_t pathsize)928a1be23daSdp zonecfg_get_zonepath(zone_dochandle_t handle, char *path, size_t pathsize)
929a1be23daSdp {
930108322fbScarlsonj size_t len;
931108322fbScarlsonj
932108322fbScarlsonj if ((len = strlcpy(path, zonecfg_root, pathsize)) >= pathsize)
933108322fbScarlsonj return (Z_TOO_BIG);
934108322fbScarlsonj return (getrootattr(handle, DTD_ATTR_ZONEPATH, path + len,
935108322fbScarlsonj pathsize - len));
936a1be23daSdp }
937a1be23daSdp
938a1be23daSdp int
zonecfg_set_zonepath(zone_dochandle_t handle,char * zonepath)939a1be23daSdp zonecfg_set_zonepath(zone_dochandle_t handle, char *zonepath)
940a1be23daSdp {
941555afedfScarlsonj size_t len;
9426fb06a2bSSusan Kamm-Worrell char *modpath, *copy_mp, *curr_mp; /* modified path ptrs */
9436fb06a2bSSusan Kamm-Worrell char last_copied;
9446fb06a2bSSusan Kamm-Worrell int ret;
9456fb06a2bSSusan Kamm-Worrell
9466fb06a2bSSusan Kamm-Worrell /*
9476fb06a2bSSusan Kamm-Worrell * Collapse multiple contiguous slashes and remove trailing slash.
9486fb06a2bSSusan Kamm-Worrell */
9496fb06a2bSSusan Kamm-Worrell modpath = strdup(zonepath);
9506fb06a2bSSusan Kamm-Worrell if (modpath == NULL)
9516fb06a2bSSusan Kamm-Worrell return (Z_NOMEM);
9526fb06a2bSSusan Kamm-Worrell last_copied = '\0';
9536fb06a2bSSusan Kamm-Worrell for (copy_mp = curr_mp = modpath; *curr_mp != '\0'; curr_mp++) {
9546fb06a2bSSusan Kamm-Worrell if (*curr_mp != '/' || last_copied != '/') {
9556fb06a2bSSusan Kamm-Worrell last_copied = *copy_mp = *curr_mp;
9566fb06a2bSSusan Kamm-Worrell copy_mp++;
9576fb06a2bSSusan Kamm-Worrell }
9586fb06a2bSSusan Kamm-Worrell }
9596fb06a2bSSusan Kamm-Worrell if (last_copied == '/')
9606fb06a2bSSusan Kamm-Worrell copy_mp--;
9616fb06a2bSSusan Kamm-Worrell *copy_mp = '\0';
962555afedfScarlsonj
963555afedfScarlsonj /*
964555afedfScarlsonj * The user deals in absolute paths in the running global zone, but the
965555afedfScarlsonj * internal configuration files deal with boot environment relative
966555afedfScarlsonj * paths. Strip out the alternate root when specified.
967555afedfScarlsonj */
968555afedfScarlsonj len = strlen(zonecfg_root);
9696fb06a2bSSusan Kamm-Worrell if (strncmp(modpath, zonecfg_root, len) != 0 || modpath[len] != '/') {
9706fb06a2bSSusan Kamm-Worrell free(modpath);
971555afedfScarlsonj return (Z_BAD_PROPERTY);
9726fb06a2bSSusan Kamm-Worrell }
9736fb06a2bSSusan Kamm-Worrell curr_mp = modpath + len;
9746fb06a2bSSusan Kamm-Worrell ret = setrootattr(handle, DTD_ATTR_ZONEPATH, curr_mp);
9756fb06a2bSSusan Kamm-Worrell free(modpath);
9766fb06a2bSSusan Kamm-Worrell return (ret);
977a1be23daSdp }
978a1be23daSdp
979e5816e35SEdward Pilatowicz static int
i_zonecfg_get_brand(zone_dochandle_t handle,char * brand,size_t brandsize,boolean_t default_query)980e5816e35SEdward Pilatowicz i_zonecfg_get_brand(zone_dochandle_t handle, char *brand, size_t brandsize,
981e5816e35SEdward Pilatowicz boolean_t default_query)
9829acbbeafSnn35248 {
9839acbbeafSnn35248 int ret, sz;
9849acbbeafSnn35248
9859acbbeafSnn35248 ret = getrootattr(handle, DTD_ATTR_BRAND, brand, brandsize);
9869acbbeafSnn35248
987e5816e35SEdward Pilatowicz /*
988e5816e35SEdward Pilatowicz * If the lookup failed, or succeeded in finding a non-null brand
989e5816e35SEdward Pilatowicz * string then return.
990e5816e35SEdward Pilatowicz */
991e5816e35SEdward Pilatowicz if (ret != Z_OK || brand[0] != '\0')
992e5816e35SEdward Pilatowicz return (ret);
993e5816e35SEdward Pilatowicz
994e5816e35SEdward Pilatowicz if (!default_query) {
995e5816e35SEdward Pilatowicz /* If the zone has no brand, it is the default brand. */
996b08d9f75SEdward Pilatowicz return (zonecfg_default_brand(brand, brandsize));
9979acbbeafSnn35248 }
9989acbbeafSnn35248
999e5816e35SEdward Pilatowicz /* if SUNWdefault didn't specify a brand, fallback to "native" */
1000e5816e35SEdward Pilatowicz sz = strlcpy(brand, NATIVE_BRAND_NAME, brandsize);
1001e5816e35SEdward Pilatowicz if (sz >= brandsize)
1002e5816e35SEdward Pilatowicz return (Z_TOO_BIG);
1003e5816e35SEdward Pilatowicz return (Z_OK);
1004e5816e35SEdward Pilatowicz }
1005e5816e35SEdward Pilatowicz
1006e5816e35SEdward Pilatowicz int
zonecfg_get_brand(zone_dochandle_t handle,char * brand,size_t brandsize)1007e5816e35SEdward Pilatowicz zonecfg_get_brand(zone_dochandle_t handle, char *brand, size_t brandsize)
1008e5816e35SEdward Pilatowicz {
1009e5816e35SEdward Pilatowicz return (i_zonecfg_get_brand(handle, brand, brandsize, B_FALSE));
10109acbbeafSnn35248 }
10119acbbeafSnn35248
10129acbbeafSnn35248 int
zonecfg_set_brand(zone_dochandle_t handle,char * brand)10139acbbeafSnn35248 zonecfg_set_brand(zone_dochandle_t handle, char *brand)
10149acbbeafSnn35248 {
10159acbbeafSnn35248 return (setrootattr(handle, DTD_ATTR_BRAND, brand));
10169acbbeafSnn35248 }
10179acbbeafSnn35248
10189acbbeafSnn35248 int
zonecfg_get_autoboot(zone_dochandle_t handle,boolean_t * autoboot)1019a1be23daSdp zonecfg_get_autoboot(zone_dochandle_t handle, boolean_t *autoboot)
1020a1be23daSdp {
1021a1be23daSdp char autobootstr[DTD_ENTITY_BOOL_LEN];
1022a1be23daSdp int ret;
1023a1be23daSdp
1024a1be23daSdp if ((ret = getrootattr(handle, DTD_ATTR_AUTOBOOT, autobootstr,
1025a1be23daSdp sizeof (autobootstr))) != Z_OK)
1026a1be23daSdp return (ret);
1027a1be23daSdp
1028a1be23daSdp if (strcmp(autobootstr, DTD_ENTITY_TRUE) == 0)
1029a1be23daSdp *autoboot = B_TRUE;
1030a1be23daSdp else if (strcmp(autobootstr, DTD_ENTITY_FALSE) == 0)
1031a1be23daSdp *autoboot = B_FALSE;
1032a1be23daSdp else
1033a1be23daSdp ret = Z_BAD_PROPERTY;
1034a1be23daSdp return (ret);
1035a1be23daSdp }
1036a1be23daSdp
1037a1be23daSdp int
zonecfg_set_autoboot(zone_dochandle_t handle,boolean_t autoboot)1038a1be23daSdp zonecfg_set_autoboot(zone_dochandle_t handle, boolean_t autoboot)
1039a1be23daSdp {
1040a1be23daSdp return (setrootattr(handle, DTD_ATTR_AUTOBOOT,
1041a1be23daSdp autoboot ? DTD_ENTITY_TRUE : DTD_ENTITY_FALSE));
1042a1be23daSdp }
1043a1be23daSdp
1044a1be23daSdp int
zonecfg_get_pool(zone_dochandle_t handle,char * pool,size_t poolsize)1045a1be23daSdp zonecfg_get_pool(zone_dochandle_t handle, char *pool, size_t poolsize)
1046a1be23daSdp {
1047a1be23daSdp return (getrootattr(handle, DTD_ATTR_POOL, pool, poolsize));
1048a1be23daSdp }
1049a1be23daSdp
1050a1be23daSdp int
zonecfg_set_pool(zone_dochandle_t handle,char * pool)1051a1be23daSdp zonecfg_set_pool(zone_dochandle_t handle, char *pool)
1052a1be23daSdp {
1053a1be23daSdp return (setrootattr(handle, DTD_ATTR_POOL, pool));
1054a1be23daSdp }
1055a1be23daSdp
1056ffbafc53Scomay int
zonecfg_get_limitpriv(zone_dochandle_t handle,char ** limitpriv)1057ffbafc53Scomay zonecfg_get_limitpriv(zone_dochandle_t handle, char **limitpriv)
1058ffbafc53Scomay {
1059ffbafc53Scomay return (get_alloc_rootattr(handle, DTD_ATTR_LIMITPRIV, limitpriv));
1060ffbafc53Scomay }
1061ffbafc53Scomay
1062ffbafc53Scomay int
zonecfg_set_limitpriv(zone_dochandle_t handle,char * limitpriv)10633f2f09c1Sdp zonecfg_set_limitpriv(zone_dochandle_t handle, char *limitpriv)
1064ffbafc53Scomay {
10653f2f09c1Sdp return (setrootattr(handle, DTD_ATTR_LIMITPRIV, limitpriv));
10663f2f09c1Sdp }
10673f2f09c1Sdp
10683f2f09c1Sdp int
zonecfg_get_bootargs(zone_dochandle_t handle,char * bargs,size_t bargssize)10693f2f09c1Sdp zonecfg_get_bootargs(zone_dochandle_t handle, char *bargs, size_t bargssize)
10703f2f09c1Sdp {
10713f2f09c1Sdp return (getrootattr(handle, DTD_ATTR_BOOTARGS, bargs, bargssize));
10723f2f09c1Sdp }
10733f2f09c1Sdp
10743f2f09c1Sdp int
zonecfg_set_bootargs(zone_dochandle_t handle,char * bargs)10753f2f09c1Sdp zonecfg_set_bootargs(zone_dochandle_t handle, char *bargs)
10763f2f09c1Sdp {
10773f2f09c1Sdp return (setrootattr(handle, DTD_ATTR_BOOTARGS, bargs));
1078ffbafc53Scomay }
1079ffbafc53Scomay
10800209230bSgjelinek int
zonecfg_get_sched_class(zone_dochandle_t handle,char * sched,size_t schedsize)10810209230bSgjelinek zonecfg_get_sched_class(zone_dochandle_t handle, char *sched, size_t schedsize)
10820209230bSgjelinek {
10830209230bSgjelinek return (getrootattr(handle, DTD_ATTR_SCHED, sched, schedsize));
10840209230bSgjelinek }
10850209230bSgjelinek
10860209230bSgjelinek int
zonecfg_set_sched(zone_dochandle_t handle,char * sched)10870209230bSgjelinek zonecfg_set_sched(zone_dochandle_t handle, char *sched)
10880209230bSgjelinek {
10890209230bSgjelinek return (setrootattr(handle, DTD_ATTR_SCHED, sched));
10900209230bSgjelinek }
10910209230bSgjelinek
1092a1be23daSdp /*
1093a1be23daSdp * /etc/zones/index caches a vital piece of information which is also
1094a1be23daSdp * in the <zonename>.xml file: the path to the zone. This is for performance,
1095a1be23daSdp * since we need to walk all zonepath's in order to be able to detect conflicts
1096a1be23daSdp * (see crosscheck_zonepaths() in the zoneadm command).
1097087719fdSdp *
1098087719fdSdp * An additional complexity is that when doing a rename, we'd like the entire
1099087719fdSdp * index update operation (rename, and potential state changes) to be atomic.
1100087719fdSdp * In general, the operation of this function should succeed or fail as
1101087719fdSdp * a unit.
1102a1be23daSdp */
1103a1be23daSdp int
zonecfg_refresh_index_file(zone_dochandle_t handle)1104a1be23daSdp zonecfg_refresh_index_file(zone_dochandle_t handle)
1105a1be23daSdp {
1106a1be23daSdp char name[ZONENAME_MAX], zonepath[MAXPATHLEN];
1107a1be23daSdp struct zoneent ze;
1108a1be23daSdp int err;
1109087719fdSdp int opcode;
1110087719fdSdp char *zn;
1111087719fdSdp
1112087719fdSdp bzero(&ze, sizeof (ze));
1113087719fdSdp ze.zone_state = -1; /* Preserve existing state in index */
1114a1be23daSdp
1115a1be23daSdp if ((err = zonecfg_get_name(handle, name, sizeof (name))) != Z_OK)
1116a1be23daSdp return (err);
1117087719fdSdp (void) strlcpy(ze.zone_name, name, sizeof (ze.zone_name));
1118087719fdSdp
1119a1be23daSdp if ((err = zonecfg_get_zonepath(handle, zonepath,
1120a1be23daSdp sizeof (zonepath))) != Z_OK)
1121a1be23daSdp return (err);
1122555afedfScarlsonj (void) strlcpy(ze.zone_path, zonepath + strlen(zonecfg_root),
1123555afedfScarlsonj sizeof (ze.zone_path));
1124087719fdSdp
1125087719fdSdp if (is_renaming(handle)) {
1126087719fdSdp opcode = PZE_MODIFY;
1127087719fdSdp (void) strlcpy(ze.zone_name, handle->zone_dh_delete_name,
1128087719fdSdp sizeof (ze.zone_name));
1129087719fdSdp (void) strlcpy(ze.zone_newname, name, sizeof (ze.zone_newname));
1130087719fdSdp } else if (is_new(handle)) {
1131087719fdSdp FILE *cookie;
1132087719fdSdp /*
1133087719fdSdp * Be tolerant of the zone already existing in the index file,
1134087719fdSdp * since we might be forcibly overwriting an existing
1135087719fdSdp * configuration with a new one (for example 'create -F'
1136087719fdSdp * in zonecfg).
1137087719fdSdp */
1138087719fdSdp opcode = PZE_ADD;
1139087719fdSdp cookie = setzoneent();
1140087719fdSdp while ((zn = getzoneent(cookie)) != NULL) {
1141087719fdSdp if (strcmp(zn, name) == 0) {
1142087719fdSdp opcode = PZE_MODIFY;
1143087719fdSdp free(zn);
1144087719fdSdp break;
1145087719fdSdp }
1146087719fdSdp free(zn);
1147087719fdSdp }
1148087719fdSdp endzoneent(cookie);
1149087719fdSdp ze.zone_state = ZONE_STATE_CONFIGURED;
1150087719fdSdp } else {
1151087719fdSdp opcode = PZE_MODIFY;
11527c478bd9Sstevel@tonic-gate }
11537c478bd9Sstevel@tonic-gate
1154087719fdSdp if ((err = putzoneent(&ze, opcode)) != Z_OK)
1155087719fdSdp return (err);
1156087719fdSdp
1157087719fdSdp return (Z_OK);
1158087719fdSdp }
1159087719fdSdp
1160087719fdSdp /*
1161087719fdSdp * The goal of this routine is to cause the index file update and the
1162087719fdSdp * document save to happen as an atomic operation. We do the document
1163087719fdSdp * first, saving a backup copy using a hard link; if that succeeds, we go
1164087719fdSdp * on to the index. If that fails, we roll the document back into place.
1165087719fdSdp *
1166087719fdSdp * Strategy:
1167087719fdSdp *
1168087719fdSdp * New zone 'foo' configuration:
1169087719fdSdp * Create tmpfile (zonecfg.xxxxxx)
1170087719fdSdp * Write XML to tmpfile
1171087719fdSdp * Rename tmpfile to xmlfile (zonecfg.xxxxxx -> foo.xml)
1172087719fdSdp * Add entry to index file
1173087719fdSdp * If it fails, delete foo.xml, leaving nothing behind.
1174087719fdSdp *
1175087719fdSdp * Save existing zone 'foo':
1176087719fdSdp * Make backup of foo.xml -> .backup
1177087719fdSdp * Create tmpfile (zonecfg.xxxxxx)
1178087719fdSdp * Write XML to tmpfile
1179087719fdSdp * Rename tmpfile to xmlfile (zonecfg.xxxxxx -> foo.xml)
1180087719fdSdp * Modify index file as needed
1181087719fdSdp * If it fails, recover from .backup -> foo.xml
1182087719fdSdp *
1183087719fdSdp * Rename 'foo' to 'bar':
1184087719fdSdp * Create tmpfile (zonecfg.xxxxxx)
1185087719fdSdp * Write XML to tmpfile
1186087719fdSdp * Rename tmpfile to xmlfile (zonecfg.xxxxxx -> bar.xml)
1187087719fdSdp * Add entry for 'bar' to index file, Remove entry for 'foo' (refresh)
1188087719fdSdp * If it fails, delete bar.xml; foo.xml is left behind.
1189087719fdSdp */
11907c478bd9Sstevel@tonic-gate static int
zonecfg_save_impl(zone_dochandle_t handle,char * filename)11917c478bd9Sstevel@tonic-gate zonecfg_save_impl(zone_dochandle_t handle, char *filename)
11927c478bd9Sstevel@tonic-gate {
11937c478bd9Sstevel@tonic-gate char tmpfile[MAXPATHLEN];
1194087719fdSdp char bakdir[MAXPATHLEN], bakbase[MAXPATHLEN], bakfile[MAXPATHLEN];
11959acbbeafSnn35248 int tmpfd, err, valid;
11967c478bd9Sstevel@tonic-gate xmlValidCtxt cvp = { NULL };
1197087719fdSdp boolean_t backup;
11987c478bd9Sstevel@tonic-gate
11997c478bd9Sstevel@tonic-gate (void) strlcpy(tmpfile, filename, sizeof (tmpfile));
12007c478bd9Sstevel@tonic-gate (void) dirname(tmpfile);
12017c478bd9Sstevel@tonic-gate (void) strlcat(tmpfile, _PATH_TMPFILE, sizeof (tmpfile));
12027c478bd9Sstevel@tonic-gate
12037c478bd9Sstevel@tonic-gate tmpfd = mkstemp(tmpfile);
12047c478bd9Sstevel@tonic-gate if (tmpfd == -1) {
12057c478bd9Sstevel@tonic-gate (void) unlink(tmpfile);
12067c478bd9Sstevel@tonic-gate return (Z_TEMP_FILE);
12077c478bd9Sstevel@tonic-gate }
12087c478bd9Sstevel@tonic-gate (void) close(tmpfd);
12097c478bd9Sstevel@tonic-gate
12107c478bd9Sstevel@tonic-gate cvp.error = zonecfg_error_func;
12117c478bd9Sstevel@tonic-gate cvp.warning = zonecfg_error_func;
12127c478bd9Sstevel@tonic-gate
1213087719fdSdp /*
12149acbbeafSnn35248 * We do a final validation of the document. Since the library has
12159acbbeafSnn35248 * malfunctioned if it fails to validate, we follow-up with an
12169acbbeafSnn35248 * assert() that the doc is valid.
1217087719fdSdp */
12189acbbeafSnn35248 valid = xmlValidateDocument(&cvp, handle->zone_dh_doc);
12199acbbeafSnn35248 assert(valid != 0);
12207c478bd9Sstevel@tonic-gate
12217c478bd9Sstevel@tonic-gate if (xmlSaveFormatFile(tmpfile, handle->zone_dh_doc, 1) <= 0)
12227c478bd9Sstevel@tonic-gate goto err;
1223087719fdSdp
12247c478bd9Sstevel@tonic-gate (void) chmod(tmpfile, 0644);
12257c478bd9Sstevel@tonic-gate
1226087719fdSdp /*
1227087719fdSdp * In the event we are doing a standard save, hard link a copy of the
1228087719fdSdp * original file in .backup.<pid>.filename so we can restore it if
1229087719fdSdp * something goes wrong.
1230087719fdSdp */
1231087719fdSdp if (!is_new(handle) && !is_renaming(handle)) {
1232087719fdSdp backup = B_TRUE;
1233087719fdSdp
1234087719fdSdp (void) strlcpy(bakdir, filename, sizeof (bakdir));
1235087719fdSdp (void) strlcpy(bakbase, filename, sizeof (bakbase));
1236087719fdSdp (void) snprintf(bakfile, sizeof (bakfile), "%s/.backup.%d.%s",
1237087719fdSdp dirname(bakdir), getpid(), basename(bakbase));
1238087719fdSdp
1239087719fdSdp if (link(filename, bakfile) == -1) {
1240087719fdSdp err = errno;
12417c478bd9Sstevel@tonic-gate (void) unlink(tmpfile);
12427c478bd9Sstevel@tonic-gate if (errno == EACCES)
12437c478bd9Sstevel@tonic-gate return (Z_ACCES);
12447c478bd9Sstevel@tonic-gate return (Z_MISC_FS);
12457c478bd9Sstevel@tonic-gate }
1246087719fdSdp }
1247a1be23daSdp
1248087719fdSdp /*
1249087719fdSdp * Move the new document over top of the old.
1250087719fdSdp * i.e.: zonecfg.XXXXXX -> myzone.xml
1251087719fdSdp */
1252087719fdSdp if (rename(tmpfile, filename) == -1) {
1253087719fdSdp err = errno;
1254087719fdSdp (void) unlink(tmpfile);
1255087719fdSdp if (backup)
1256087719fdSdp (void) unlink(bakfile);
1257087719fdSdp if (err == EACCES)
1258087719fdSdp return (Z_ACCES);
1259087719fdSdp return (Z_MISC_FS);
1260087719fdSdp }
1261087719fdSdp
1262087719fdSdp /*
1263087719fdSdp * If this is a snapshot, we're done-- don't add an index entry.
1264087719fdSdp */
1265087719fdSdp if (is_snapshot(handle))
1266087719fdSdp return (Z_OK);
1267087719fdSdp
1268087719fdSdp /* now update the index file to reflect whatever we just did */
1269087719fdSdp if ((err = zonecfg_refresh_index_file(handle)) != Z_OK) {
1270087719fdSdp if (backup) {
1271087719fdSdp /*
1272087719fdSdp * Try to restore from our backup.
1273087719fdSdp */
1274087719fdSdp (void) unlink(filename);
1275087719fdSdp (void) rename(bakfile, filename);
1276087719fdSdp } else {
1277087719fdSdp /*
1278087719fdSdp * Either the zone is new, in which case we can delete
1279087719fdSdp * new.xml, or we're doing a rename, so ditto.
1280087719fdSdp */
1281087719fdSdp assert(is_new(handle) || is_renaming(handle));
1282087719fdSdp (void) unlink(filename);
1283087719fdSdp }
1284087719fdSdp return (Z_UPDATING_INDEX);
1285087719fdSdp }
1286087719fdSdp
1287087719fdSdp if (backup)
1288087719fdSdp (void) unlink(bakfile);
1289087719fdSdp
1290087719fdSdp return (Z_OK);
12917c478bd9Sstevel@tonic-gate
12927c478bd9Sstevel@tonic-gate err:
12937c478bd9Sstevel@tonic-gate (void) unlink(tmpfile);
12947c478bd9Sstevel@tonic-gate return (Z_SAVING_FILE);
12957c478bd9Sstevel@tonic-gate }
12967c478bd9Sstevel@tonic-gate
12977c478bd9Sstevel@tonic-gate int
zonecfg_save(zone_dochandle_t handle)12987c478bd9Sstevel@tonic-gate zonecfg_save(zone_dochandle_t handle)
12997c478bd9Sstevel@tonic-gate {
1300087719fdSdp char zname[ZONENAME_MAX], path[MAXPATHLEN];
1301087719fdSdp char delpath[MAXPATHLEN];
1302087719fdSdp int err = Z_SAVING_FILE;
13037c478bd9Sstevel@tonic-gate
1304087719fdSdp if (zonecfg_check_handle(handle) != Z_OK)
1305087719fdSdp return (Z_BAD_HANDLE);
1306087719fdSdp
1307087719fdSdp /*
1308ee519a1fSgjelinek * We don't support saving snapshots or a tree containing a sw
1309ee519a1fSgjelinek * inventory at this time.
1310087719fdSdp */
1311ee519a1fSgjelinek if (handle->zone_dh_snapshot || handle->zone_dh_sw_inv)
1312087719fdSdp return (Z_INVAL);
1313087719fdSdp
1314087719fdSdp if ((err = zonecfg_get_name(handle, zname, sizeof (zname))) != Z_OK)
13157c478bd9Sstevel@tonic-gate return (err);
1316087719fdSdp
1317108322fbScarlsonj if (!config_file_path(zname, path))
1318108322fbScarlsonj return (Z_MISC_FS);
1319087719fdSdp
1320087719fdSdp addcomment(handle, "\n DO NOT EDIT THIS "
1321087719fdSdp "FILE. Use zonecfg(1M) instead.\n");
1322087719fdSdp
1323cb8a054bSGlenn Faden /*
1324cb8a054bSGlenn Faden * Update user_attr first so that it will be older
1325cb8a054bSGlenn Faden * than the config file.
1326cb8a054bSGlenn Faden */
1327cb8a054bSGlenn Faden (void) zonecfg_authorize_users(handle, zname);
1328087719fdSdp err = zonecfg_save_impl(handle, path);
1329087719fdSdp
1330087719fdSdp stripcomments(handle);
1331087719fdSdp
1332087719fdSdp if (err != Z_OK)
1333087719fdSdp return (err);
1334087719fdSdp
1335087719fdSdp handle->zone_dh_newzone = B_FALSE;
1336087719fdSdp
1337087719fdSdp if (is_renaming(handle)) {
1338108322fbScarlsonj if (config_file_path(handle->zone_dh_delete_name, delpath))
1339087719fdSdp (void) unlink(delpath);
1340087719fdSdp handle->zone_dh_delete_name[0] = '\0';
1341087719fdSdp }
1342087719fdSdp
1343087719fdSdp return (Z_OK);
13447c478bd9Sstevel@tonic-gate }
13457c478bd9Sstevel@tonic-gate
1346ee519a1fSgjelinek int
zonecfg_verify_save(zone_dochandle_t handle,char * filename)13479acbbeafSnn35248 zonecfg_verify_save(zone_dochandle_t handle, char *filename)
13489acbbeafSnn35248 {
13499acbbeafSnn35248 int valid;
13509acbbeafSnn35248
13519acbbeafSnn35248 xmlValidCtxt cvp = { NULL };
13529acbbeafSnn35248
13539acbbeafSnn35248 if (zonecfg_check_handle(handle) != Z_OK)
13549acbbeafSnn35248 return (Z_BAD_HANDLE);
13559acbbeafSnn35248
13569acbbeafSnn35248 cvp.error = zonecfg_error_func;
13579acbbeafSnn35248 cvp.warning = zonecfg_error_func;
13589acbbeafSnn35248
13599acbbeafSnn35248 /*
13609acbbeafSnn35248 * We do a final validation of the document. Since the library has
13619acbbeafSnn35248 * malfunctioned if it fails to validate, we follow-up with an
13629acbbeafSnn35248 * assert() that the doc is valid.
13639acbbeafSnn35248 */
13649acbbeafSnn35248 valid = xmlValidateDocument(&cvp, handle->zone_dh_doc);
13659acbbeafSnn35248 assert(valid != 0);
13669acbbeafSnn35248
13679acbbeafSnn35248 if (xmlSaveFormatFile(filename, handle->zone_dh_doc, 1) <= 0)
13689acbbeafSnn35248 return (Z_SAVING_FILE);
13699acbbeafSnn35248
13709acbbeafSnn35248 return (Z_OK);
13719acbbeafSnn35248 }
13729acbbeafSnn35248
13739acbbeafSnn35248 int
zonecfg_detach_save(zone_dochandle_t handle,uint_t flags)13748cd327d5Sgjelinek zonecfg_detach_save(zone_dochandle_t handle, uint_t flags)
1375ee519a1fSgjelinek {
1376ee519a1fSgjelinek char zname[ZONENAME_MAX];
1377ee519a1fSgjelinek char path[MAXPATHLEN];
1378ee519a1fSgjelinek char migpath[MAXPATHLEN];
1379ee519a1fSgjelinek xmlValidCtxt cvp = { NULL };
1380ee519a1fSgjelinek int err = Z_SAVING_FILE;
13819acbbeafSnn35248 int valid;
1382ee519a1fSgjelinek
1383ee519a1fSgjelinek if (zonecfg_check_handle(handle) != Z_OK)
1384ee519a1fSgjelinek return (Z_BAD_HANDLE);
1385ee519a1fSgjelinek
13868cd327d5Sgjelinek if (flags & ZONE_DRY_RUN) {
13878cd327d5Sgjelinek (void) strlcpy(migpath, "-", sizeof (migpath));
13888cd327d5Sgjelinek } else {
13898cd327d5Sgjelinek if ((err = zonecfg_get_name(handle, zname, sizeof (zname)))
13908cd327d5Sgjelinek != Z_OK)
1391ee519a1fSgjelinek return (err);
1392ee519a1fSgjelinek
13938cd327d5Sgjelinek if ((err = zone_get_zonepath(zname, path, sizeof (path)))
13948cd327d5Sgjelinek != Z_OK)
1395ee519a1fSgjelinek return (err);
1396ee519a1fSgjelinek
139716ab8c7bSgjelinek if (snprintf(migpath, sizeof (migpath), "%s/%s", path,
139816ab8c7bSgjelinek ZONE_DETACHED) >= sizeof (migpath))
1399ee519a1fSgjelinek return (Z_NOMEM);
14008cd327d5Sgjelinek }
1401ee519a1fSgjelinek
1402ee519a1fSgjelinek if ((err = operation_prep(handle)) != Z_OK)
1403ee519a1fSgjelinek return (err);
1404ee519a1fSgjelinek
1405ee519a1fSgjelinek addcomment(handle, "\n DO NOT EDIT THIS FILE. "
1406ee519a1fSgjelinek "Use zonecfg(1M) and zoneadm(1M) attach.\n");
1407ee519a1fSgjelinek
1408ee519a1fSgjelinek cvp.error = zonecfg_error_func;
1409ee519a1fSgjelinek cvp.warning = zonecfg_error_func;
1410ee519a1fSgjelinek
1411ee519a1fSgjelinek /*
14129acbbeafSnn35248 * We do a final validation of the document. Since the library has
14139acbbeafSnn35248 * malfunctioned if it fails to validate, we follow-up with an
14149acbbeafSnn35248 * assert() that the doc is valid.
1415ee519a1fSgjelinek */
14169acbbeafSnn35248 valid = xmlValidateDocument(&cvp, handle->zone_dh_doc);
14179acbbeafSnn35248 assert(valid != 0);
1418ee519a1fSgjelinek
1419ee519a1fSgjelinek if (xmlSaveFormatFile(migpath, handle->zone_dh_doc, 1) <= 0)
1420ee519a1fSgjelinek return (Z_SAVING_FILE);
1421ee519a1fSgjelinek
14228cd327d5Sgjelinek if (!(flags & ZONE_DRY_RUN))
1423ee519a1fSgjelinek (void) chmod(migpath, 0644);
1424ee519a1fSgjelinek
1425ee519a1fSgjelinek stripcomments(handle);
1426ee519a1fSgjelinek
1427ee519a1fSgjelinek handle->zone_dh_newzone = B_FALSE;
1428ee519a1fSgjelinek
1429ee519a1fSgjelinek return (Z_OK);
1430ee519a1fSgjelinek }
1431ee519a1fSgjelinek
1432ee519a1fSgjelinek boolean_t
zonecfg_detached(const char * path)1433ee519a1fSgjelinek zonecfg_detached(const char *path)
1434ee519a1fSgjelinek {
1435ee519a1fSgjelinek char migpath[MAXPATHLEN];
1436ee519a1fSgjelinek struct stat buf;
1437ee519a1fSgjelinek
143816ab8c7bSgjelinek if (snprintf(migpath, sizeof (migpath), "%s/%s", path, ZONE_DETACHED) >=
1439ee519a1fSgjelinek sizeof (migpath))
1440ee519a1fSgjelinek return (B_FALSE);
1441ee519a1fSgjelinek
1442ee519a1fSgjelinek if (stat(migpath, &buf) != -1)
1443ee519a1fSgjelinek return (B_TRUE);
1444ee519a1fSgjelinek
1445ee519a1fSgjelinek return (B_FALSE);
1446ee519a1fSgjelinek }
1447ee519a1fSgjelinek
1448ee519a1fSgjelinek void
zonecfg_rm_detached(zone_dochandle_t handle,boolean_t forced)1449ee519a1fSgjelinek zonecfg_rm_detached(zone_dochandle_t handle, boolean_t forced)
1450ee519a1fSgjelinek {
1451ee519a1fSgjelinek char zname[ZONENAME_MAX];
1452ee519a1fSgjelinek char path[MAXPATHLEN];
1453ee519a1fSgjelinek char detached[MAXPATHLEN];
1454ee519a1fSgjelinek char attached[MAXPATHLEN];
1455ee519a1fSgjelinek
1456ee519a1fSgjelinek if (zonecfg_check_handle(handle) != Z_OK)
1457ee519a1fSgjelinek return;
1458ee519a1fSgjelinek
1459ee519a1fSgjelinek if (zonecfg_get_name(handle, zname, sizeof (zname)) != Z_OK)
1460ee519a1fSgjelinek return;
1461ee519a1fSgjelinek
1462ee519a1fSgjelinek if (zone_get_zonepath(zname, path, sizeof (path)) != Z_OK)
1463ee519a1fSgjelinek return;
1464ee519a1fSgjelinek
146516ab8c7bSgjelinek (void) snprintf(detached, sizeof (detached), "%s/%s", path,
146616ab8c7bSgjelinek ZONE_DETACHED);
1467ee519a1fSgjelinek (void) snprintf(attached, sizeof (attached), "%s/%s", path,
1468ee519a1fSgjelinek ATTACH_FORCED);
1469ee519a1fSgjelinek
1470ee519a1fSgjelinek if (forced) {
1471ee519a1fSgjelinek (void) rename(detached, attached);
1472ee519a1fSgjelinek } else {
1473ee519a1fSgjelinek (void) unlink(attached);
1474ee519a1fSgjelinek (void) unlink(detached);
1475ee519a1fSgjelinek }
1476ee519a1fSgjelinek }
1477ee519a1fSgjelinek
14787c478bd9Sstevel@tonic-gate /*
14797c478bd9Sstevel@tonic-gate * Special case: if access(2) fails with ENOENT, then try again using
14807c478bd9Sstevel@tonic-gate * ZONE_CONFIG_ROOT instead of config_file_path(zonename). This is how we
14817c478bd9Sstevel@tonic-gate * work around the case of a config file which has not been created yet:
14827c478bd9Sstevel@tonic-gate * the user will need access to the directory so use that as a heuristic.
14837c478bd9Sstevel@tonic-gate */
14847c478bd9Sstevel@tonic-gate
14857c478bd9Sstevel@tonic-gate int
zonecfg_access(const char * zonename,int amode)14867c478bd9Sstevel@tonic-gate zonecfg_access(const char *zonename, int amode)
14877c478bd9Sstevel@tonic-gate {
14887c478bd9Sstevel@tonic-gate char path[MAXPATHLEN];
14897c478bd9Sstevel@tonic-gate
1490108322fbScarlsonj if (!config_file_path(zonename, path))
1491108322fbScarlsonj return (Z_INVAL);
14927c478bd9Sstevel@tonic-gate if (access(path, amode) == 0)
14937c478bd9Sstevel@tonic-gate return (Z_OK);
1494108322fbScarlsonj if (errno == ENOENT) {
1495108322fbScarlsonj if (snprintf(path, sizeof (path), "%s%s", zonecfg_root,
1496108322fbScarlsonj ZONE_CONFIG_ROOT) >= sizeof (path))
1497108322fbScarlsonj return (Z_INVAL);
1498108322fbScarlsonj if (access(path, amode) == 0)
14997c478bd9Sstevel@tonic-gate return (Z_OK);
1500108322fbScarlsonj }
15017c478bd9Sstevel@tonic-gate if (errno == EACCES)
15027c478bd9Sstevel@tonic-gate return (Z_ACCES);
15037c478bd9Sstevel@tonic-gate if (errno == EINVAL)
15047c478bd9Sstevel@tonic-gate return (Z_INVAL);
15057c478bd9Sstevel@tonic-gate return (Z_MISC_FS);
15067c478bd9Sstevel@tonic-gate }
15077c478bd9Sstevel@tonic-gate
15087c478bd9Sstevel@tonic-gate int
zonecfg_create_snapshot(const char * zonename)1509108322fbScarlsonj zonecfg_create_snapshot(const char *zonename)
15107c478bd9Sstevel@tonic-gate {
15117c478bd9Sstevel@tonic-gate zone_dochandle_t handle;
15127c478bd9Sstevel@tonic-gate char path[MAXPATHLEN], zonepath[MAXPATHLEN], rpath[MAXPATHLEN];
15137c478bd9Sstevel@tonic-gate int error = Z_OK, res;
15147c478bd9Sstevel@tonic-gate
15157c478bd9Sstevel@tonic-gate if ((handle = zonecfg_init_handle()) == NULL) {
15167c478bd9Sstevel@tonic-gate return (Z_NOMEM);
15177c478bd9Sstevel@tonic-gate }
15187c478bd9Sstevel@tonic-gate
1519087719fdSdp handle->zone_dh_newzone = B_TRUE;
1520087719fdSdp handle->zone_dh_snapshot = B_TRUE;
1521087719fdSdp
15227c478bd9Sstevel@tonic-gate if ((error = zonecfg_get_handle(zonename, handle)) != Z_OK)
15237c478bd9Sstevel@tonic-gate goto out;
15247c478bd9Sstevel@tonic-gate if ((error = operation_prep(handle)) != Z_OK)
15257c478bd9Sstevel@tonic-gate goto out;
15267c478bd9Sstevel@tonic-gate error = zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath));
15277c478bd9Sstevel@tonic-gate if (error != Z_OK)
15287c478bd9Sstevel@tonic-gate goto out;
15297c478bd9Sstevel@tonic-gate if ((res = resolvepath(zonepath, rpath, sizeof (rpath))) == -1) {
15307c478bd9Sstevel@tonic-gate error = Z_RESOLVED_PATH;
15317c478bd9Sstevel@tonic-gate goto out;
15327c478bd9Sstevel@tonic-gate }
15337c478bd9Sstevel@tonic-gate /*
15347c478bd9Sstevel@tonic-gate * If the resolved path is not the same as the original path, then
15357c478bd9Sstevel@tonic-gate * save the resolved path in the snapshot, thus preventing any
15367c478bd9Sstevel@tonic-gate * potential problems down the line when zoneadmd goes to unmount
15377c478bd9Sstevel@tonic-gate * file systems and depends on initial string matches with resolved
15387c478bd9Sstevel@tonic-gate * paths.
15397c478bd9Sstevel@tonic-gate */
15407c478bd9Sstevel@tonic-gate rpath[res] = '\0';
15417c478bd9Sstevel@tonic-gate if (strcmp(zonepath, rpath) != 0) {
15427c478bd9Sstevel@tonic-gate if ((error = zonecfg_set_zonepath(handle, rpath)) != Z_OK)
15437c478bd9Sstevel@tonic-gate goto out;
15447c478bd9Sstevel@tonic-gate }
1545108322fbScarlsonj if (snprintf(path, sizeof (path), "%s%s", zonecfg_root,
1546108322fbScarlsonj ZONE_SNAPSHOT_ROOT) >= sizeof (path)) {
1547108322fbScarlsonj error = Z_MISC_FS;
1548108322fbScarlsonj goto out;
1549108322fbScarlsonj }
1550108322fbScarlsonj if ((mkdir(path, S_IRWXU) == -1) && (errno != EEXIST)) {
15517c478bd9Sstevel@tonic-gate error = Z_MISC_FS;
15527c478bd9Sstevel@tonic-gate goto out;
15537c478bd9Sstevel@tonic-gate }
15547c478bd9Sstevel@tonic-gate
1555108322fbScarlsonj if (!snap_file_path(zonename, path)) {
1556108322fbScarlsonj error = Z_MISC_FS;
1557108322fbScarlsonj goto out;
1558108322fbScarlsonj }
1559087719fdSdp
1560087719fdSdp addcomment(handle, "\n DO NOT EDIT THIS FILE. "
1561087719fdSdp "It is a snapshot of running zone state.\n");
1562087719fdSdp
15637c478bd9Sstevel@tonic-gate error = zonecfg_save_impl(handle, path);
15647c478bd9Sstevel@tonic-gate
1565087719fdSdp stripcomments(handle);
1566087719fdSdp
15677c478bd9Sstevel@tonic-gate out:
15687c478bd9Sstevel@tonic-gate zonecfg_fini_handle(handle);
15697c478bd9Sstevel@tonic-gate return (error);
15707c478bd9Sstevel@tonic-gate }
15717c478bd9Sstevel@tonic-gate
1572f4b3ec61Sdh155122 int
zonecfg_get_iptype(zone_dochandle_t handle,zone_iptype_t * iptypep)1573f4b3ec61Sdh155122 zonecfg_get_iptype(zone_dochandle_t handle, zone_iptype_t *iptypep)
1574f4b3ec61Sdh155122 {
1575f4b3ec61Sdh155122 char property[10]; /* 10 is big enough for "shared"/"exclusive" */
1576f4b3ec61Sdh155122 int err;
1577f4b3ec61Sdh155122
1578f4b3ec61Sdh155122 err = getrootattr(handle, DTD_ATTR_IPTYPE, property, sizeof (property));
1579f4b3ec61Sdh155122 if (err == Z_BAD_PROPERTY) {
1580f4b3ec61Sdh155122 /* Return default value */
1581f4b3ec61Sdh155122 *iptypep = ZS_SHARED;
1582f4b3ec61Sdh155122 return (Z_OK);
1583f4b3ec61Sdh155122 } else if (err != Z_OK) {
1584f4b3ec61Sdh155122 return (err);
1585f4b3ec61Sdh155122 }
1586f4b3ec61Sdh155122
1587f4b3ec61Sdh155122 if (strlen(property) == 0 ||
1588f4b3ec61Sdh155122 strcmp(property, "shared") == 0)
1589f4b3ec61Sdh155122 *iptypep = ZS_SHARED;
1590f4b3ec61Sdh155122 else if (strcmp(property, "exclusive") == 0)
1591f4b3ec61Sdh155122 *iptypep = ZS_EXCLUSIVE;
1592f4b3ec61Sdh155122 else
1593f4b3ec61Sdh155122 return (Z_INVAL);
1594f4b3ec61Sdh155122
1595f4b3ec61Sdh155122 return (Z_OK);
1596f4b3ec61Sdh155122 }
1597f4b3ec61Sdh155122
1598f4b3ec61Sdh155122 int
zonecfg_set_iptype(zone_dochandle_t handle,zone_iptype_t iptype)1599f4b3ec61Sdh155122 zonecfg_set_iptype(zone_dochandle_t handle, zone_iptype_t iptype)
1600f4b3ec61Sdh155122 {
1601f4b3ec61Sdh155122 xmlNodePtr cur;
1602f4b3ec61Sdh155122
1603f4b3ec61Sdh155122 if (handle == NULL)
1604f4b3ec61Sdh155122 return (Z_INVAL);
1605f4b3ec61Sdh155122
1606f4b3ec61Sdh155122 cur = xmlDocGetRootElement(handle->zone_dh_doc);
1607f4b3ec61Sdh155122 if (cur == NULL) {
1608f4b3ec61Sdh155122 return (Z_EMPTY_DOCUMENT);
1609f4b3ec61Sdh155122 }
1610f4b3ec61Sdh155122
1611f4b3ec61Sdh155122 if (xmlStrcmp(cur->name, DTD_ELEM_ZONE) != 0) {
1612f4b3ec61Sdh155122 return (Z_WRONG_DOC_TYPE);
1613f4b3ec61Sdh155122 }
1614f4b3ec61Sdh155122 switch (iptype) {
1615f4b3ec61Sdh155122 case ZS_SHARED:
1616f4b3ec61Sdh155122 /*
1617f4b3ec61Sdh155122 * Since "shared" is the default, we don't write it to the
1618f4b3ec61Sdh155122 * configuration file, so that it's easier to migrate those
1619f4b3ec61Sdh155122 * zones elsewhere, eg., to systems which are not IP-Instances
1620f4b3ec61Sdh155122 * aware.
1621f4b3ec61Sdh155122 * xmlUnsetProp only fails when the attribute doesn't exist,
1622f4b3ec61Sdh155122 * which we don't care.
1623f4b3ec61Sdh155122 */
1624f4b3ec61Sdh155122 (void) xmlUnsetProp(cur, DTD_ATTR_IPTYPE);
1625f4b3ec61Sdh155122 break;
1626f4b3ec61Sdh155122 case ZS_EXCLUSIVE:
1627f4b3ec61Sdh155122 if (xmlSetProp(cur, DTD_ATTR_IPTYPE,
1628f4b3ec61Sdh155122 (const xmlChar *) "exclusive") == NULL)
1629f4b3ec61Sdh155122 return (Z_INVAL);
1630f4b3ec61Sdh155122 break;
1631f4b3ec61Sdh155122 }
1632f4b3ec61Sdh155122 return (Z_OK);
1633f4b3ec61Sdh155122 }
1634f4b3ec61Sdh155122
16357c478bd9Sstevel@tonic-gate static int
newprop(xmlNodePtr node,const xmlChar * attrname,char * src)1636a1be23daSdp newprop(xmlNodePtr node, const xmlChar *attrname, char *src)
16377c478bd9Sstevel@tonic-gate {
16387c478bd9Sstevel@tonic-gate xmlAttrPtr newattr;
16397c478bd9Sstevel@tonic-gate
16407c478bd9Sstevel@tonic-gate newattr = xmlNewProp(node, attrname, (xmlChar *)src);
16417c478bd9Sstevel@tonic-gate if (newattr == NULL) {
16427c478bd9Sstevel@tonic-gate xmlUnlinkNode(node);
16437c478bd9Sstevel@tonic-gate xmlFreeNode(node);
16447c478bd9Sstevel@tonic-gate return (Z_BAD_PROPERTY);
16457c478bd9Sstevel@tonic-gate }
16467c478bd9Sstevel@tonic-gate return (Z_OK);
16477c478bd9Sstevel@tonic-gate }
16487c478bd9Sstevel@tonic-gate
16497c478bd9Sstevel@tonic-gate static int
zonecfg_add_filesystem_core(zone_dochandle_t handle,struct zone_fstab * tabptr)16507c478bd9Sstevel@tonic-gate zonecfg_add_filesystem_core(zone_dochandle_t handle, struct zone_fstab *tabptr)
16517c478bd9Sstevel@tonic-gate {
16527c478bd9Sstevel@tonic-gate xmlNodePtr newnode, cur = handle->zone_dh_cur, options_node;
16537c478bd9Sstevel@tonic-gate zone_fsopt_t *ptr;
16547c478bd9Sstevel@tonic-gate int err;
16557c478bd9Sstevel@tonic-gate
16567c478bd9Sstevel@tonic-gate newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_FS, NULL);
1657a1be23daSdp if ((err = newprop(newnode, DTD_ATTR_SPECIAL,
16587c478bd9Sstevel@tonic-gate tabptr->zone_fs_special)) != Z_OK)
16597c478bd9Sstevel@tonic-gate return (err);
16607c478bd9Sstevel@tonic-gate if (tabptr->zone_fs_raw[0] != '\0' &&
1661a1be23daSdp (err = newprop(newnode, DTD_ATTR_RAW, tabptr->zone_fs_raw)) != Z_OK)
16627c478bd9Sstevel@tonic-gate return (err);
1663a1be23daSdp if ((err = newprop(newnode, DTD_ATTR_DIR, tabptr->zone_fs_dir)) != Z_OK)
16647c478bd9Sstevel@tonic-gate return (err);
1665a1be23daSdp if ((err = newprop(newnode, DTD_ATTR_TYPE,
16667c478bd9Sstevel@tonic-gate tabptr->zone_fs_type)) != Z_OK)
16677c478bd9Sstevel@tonic-gate return (err);
16687c478bd9Sstevel@tonic-gate if (tabptr->zone_fs_options != NULL) {
16697c478bd9Sstevel@tonic-gate for (ptr = tabptr->zone_fs_options; ptr != NULL;
16707c478bd9Sstevel@tonic-gate ptr = ptr->zone_fsopt_next) {
16717c478bd9Sstevel@tonic-gate options_node = xmlNewTextChild(newnode, NULL,
16727c478bd9Sstevel@tonic-gate DTD_ELEM_FSOPTION, NULL);
1673a1be23daSdp if ((err = newprop(options_node, DTD_ATTR_NAME,
16747c478bd9Sstevel@tonic-gate ptr->zone_fsopt_opt)) != Z_OK)
16757c478bd9Sstevel@tonic-gate return (err);
16767c478bd9Sstevel@tonic-gate }
16777c478bd9Sstevel@tonic-gate }
16787c478bd9Sstevel@tonic-gate return (Z_OK);
16797c478bd9Sstevel@tonic-gate }
16807c478bd9Sstevel@tonic-gate
16817c478bd9Sstevel@tonic-gate int
zonecfg_add_filesystem(zone_dochandle_t handle,struct zone_fstab * tabptr)16827c478bd9Sstevel@tonic-gate zonecfg_add_filesystem(zone_dochandle_t handle, struct zone_fstab *tabptr)
16837c478bd9Sstevel@tonic-gate {
16847c478bd9Sstevel@tonic-gate int err;
16857c478bd9Sstevel@tonic-gate
16867c478bd9Sstevel@tonic-gate if (tabptr == NULL)
16877c478bd9Sstevel@tonic-gate return (Z_INVAL);
16887c478bd9Sstevel@tonic-gate
16897c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK)
16907c478bd9Sstevel@tonic-gate return (err);
16917c478bd9Sstevel@tonic-gate
16927c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_filesystem_core(handle, tabptr)) != Z_OK)
16937c478bd9Sstevel@tonic-gate return (err);
16947c478bd9Sstevel@tonic-gate
16957c478bd9Sstevel@tonic-gate return (Z_OK);
16967c478bd9Sstevel@tonic-gate }
16977c478bd9Sstevel@tonic-gate
16987c478bd9Sstevel@tonic-gate int
zonecfg_add_fs_option(struct zone_fstab * tabptr,char * option)16997c478bd9Sstevel@tonic-gate zonecfg_add_fs_option(struct zone_fstab *tabptr, char *option)
17007c478bd9Sstevel@tonic-gate {
17017c478bd9Sstevel@tonic-gate zone_fsopt_t *last, *old, *new;
17027c478bd9Sstevel@tonic-gate
17037c478bd9Sstevel@tonic-gate last = tabptr->zone_fs_options;
17047c478bd9Sstevel@tonic-gate for (old = last; old != NULL; old = old->zone_fsopt_next)
17057c478bd9Sstevel@tonic-gate last = old; /* walk to the end of the list */
17067c478bd9Sstevel@tonic-gate new = (zone_fsopt_t *)malloc(sizeof (zone_fsopt_t));
17077c478bd9Sstevel@tonic-gate if (new == NULL)
17087c478bd9Sstevel@tonic-gate return (Z_NOMEM);
17097c478bd9Sstevel@tonic-gate (void) strlcpy(new->zone_fsopt_opt, option,
17107c478bd9Sstevel@tonic-gate sizeof (new->zone_fsopt_opt));
17117c478bd9Sstevel@tonic-gate new->zone_fsopt_next = NULL;
17127c478bd9Sstevel@tonic-gate if (last == NULL)
17137c478bd9Sstevel@tonic-gate tabptr->zone_fs_options = new;
17147c478bd9Sstevel@tonic-gate else
17157c478bd9Sstevel@tonic-gate last->zone_fsopt_next = new;
17167c478bd9Sstevel@tonic-gate return (Z_OK);
17177c478bd9Sstevel@tonic-gate }
17187c478bd9Sstevel@tonic-gate
17197c478bd9Sstevel@tonic-gate int
zonecfg_remove_fs_option(struct zone_fstab * tabptr,char * option)17207c478bd9Sstevel@tonic-gate zonecfg_remove_fs_option(struct zone_fstab *tabptr, char *option)
17217c478bd9Sstevel@tonic-gate {
17227c478bd9Sstevel@tonic-gate zone_fsopt_t *last, *this, *next;
17237c478bd9Sstevel@tonic-gate
17247c478bd9Sstevel@tonic-gate last = tabptr->zone_fs_options;
17257c478bd9Sstevel@tonic-gate for (this = last; this != NULL; this = this->zone_fsopt_next) {
17267c478bd9Sstevel@tonic-gate if (strcmp(this->zone_fsopt_opt, option) == 0) {
17277c478bd9Sstevel@tonic-gate next = this->zone_fsopt_next;
17287c478bd9Sstevel@tonic-gate if (this == tabptr->zone_fs_options)
17297c478bd9Sstevel@tonic-gate tabptr->zone_fs_options = next;
17307c478bd9Sstevel@tonic-gate else
17317c478bd9Sstevel@tonic-gate last->zone_fsopt_next = next;
17327c478bd9Sstevel@tonic-gate free(this);
17337c478bd9Sstevel@tonic-gate return (Z_OK);
17347c478bd9Sstevel@tonic-gate } else
17357c478bd9Sstevel@tonic-gate last = this;
17367c478bd9Sstevel@tonic-gate }
17377c478bd9Sstevel@tonic-gate return (Z_NO_PROPERTY_ID);
17387c478bd9Sstevel@tonic-gate }
17397c478bd9Sstevel@tonic-gate
17407c478bd9Sstevel@tonic-gate void
zonecfg_free_fs_option_list(zone_fsopt_t * list)17417c478bd9Sstevel@tonic-gate zonecfg_free_fs_option_list(zone_fsopt_t *list)
17427c478bd9Sstevel@tonic-gate {
17437c478bd9Sstevel@tonic-gate zone_fsopt_t *this, *next;
17447c478bd9Sstevel@tonic-gate
17457c478bd9Sstevel@tonic-gate for (this = list; this != NULL; this = next) {
17467c478bd9Sstevel@tonic-gate next = this->zone_fsopt_next;
17477c478bd9Sstevel@tonic-gate free(this);
17487c478bd9Sstevel@tonic-gate }
17497c478bd9Sstevel@tonic-gate }
17507c478bd9Sstevel@tonic-gate
17517c478bd9Sstevel@tonic-gate void
zonecfg_free_rctl_value_list(struct zone_rctlvaltab * valtab)17527c478bd9Sstevel@tonic-gate zonecfg_free_rctl_value_list(struct zone_rctlvaltab *valtab)
17537c478bd9Sstevel@tonic-gate {
17547c478bd9Sstevel@tonic-gate if (valtab == NULL)
17557c478bd9Sstevel@tonic-gate return;
17567c478bd9Sstevel@tonic-gate zonecfg_free_rctl_value_list(valtab->zone_rctlval_next);
17577c478bd9Sstevel@tonic-gate free(valtab);
17587c478bd9Sstevel@tonic-gate }
17597c478bd9Sstevel@tonic-gate
17607c478bd9Sstevel@tonic-gate static boolean_t
match_prop(xmlNodePtr cur,const xmlChar * attr,char * user_prop)17617c478bd9Sstevel@tonic-gate match_prop(xmlNodePtr cur, const xmlChar *attr, char *user_prop)
17627c478bd9Sstevel@tonic-gate {
17637c478bd9Sstevel@tonic-gate xmlChar *gotten_prop;
17647c478bd9Sstevel@tonic-gate int prop_result;
17657c478bd9Sstevel@tonic-gate
17667c478bd9Sstevel@tonic-gate gotten_prop = xmlGetProp(cur, attr);
17677c478bd9Sstevel@tonic-gate if (gotten_prop == NULL) /* shouldn't happen */
17687c478bd9Sstevel@tonic-gate return (B_FALSE);
17697c478bd9Sstevel@tonic-gate prop_result = xmlStrcmp(gotten_prop, (const xmlChar *) user_prop);
17707c478bd9Sstevel@tonic-gate xmlFree(gotten_prop);
1771*cbca9407SGary Mills return ((prop_result == 0)); /* empty strings will match */
17727c478bd9Sstevel@tonic-gate }
17737c478bd9Sstevel@tonic-gate
17747c478bd9Sstevel@tonic-gate static int
zonecfg_delete_filesystem_core(zone_dochandle_t handle,struct zone_fstab * tabptr)17757c478bd9Sstevel@tonic-gate zonecfg_delete_filesystem_core(zone_dochandle_t handle,
17767c478bd9Sstevel@tonic-gate struct zone_fstab *tabptr)
17777c478bd9Sstevel@tonic-gate {
17787c478bd9Sstevel@tonic-gate xmlNodePtr cur = handle->zone_dh_cur;
17797c478bd9Sstevel@tonic-gate boolean_t dir_match, spec_match, raw_match, type_match;
17807c478bd9Sstevel@tonic-gate
17817c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
17827c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_FS))
17837c478bd9Sstevel@tonic-gate continue;
17847c478bd9Sstevel@tonic-gate dir_match = match_prop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir);
17857c478bd9Sstevel@tonic-gate spec_match = match_prop(cur, DTD_ATTR_SPECIAL,
17867c478bd9Sstevel@tonic-gate tabptr->zone_fs_special);
17877c478bd9Sstevel@tonic-gate raw_match = match_prop(cur, DTD_ATTR_RAW,
17887c478bd9Sstevel@tonic-gate tabptr->zone_fs_raw);
17897c478bd9Sstevel@tonic-gate type_match = match_prop(cur, DTD_ATTR_TYPE,
17907c478bd9Sstevel@tonic-gate tabptr->zone_fs_type);
17917c478bd9Sstevel@tonic-gate if (dir_match && spec_match && raw_match && type_match) {
17927c478bd9Sstevel@tonic-gate xmlUnlinkNode(cur);
17937c478bd9Sstevel@tonic-gate xmlFreeNode(cur);
17947c478bd9Sstevel@tonic-gate return (Z_OK);
17957c478bd9Sstevel@tonic-gate }
17967c478bd9Sstevel@tonic-gate }
17977c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID);
17987c478bd9Sstevel@tonic-gate }
17997c478bd9Sstevel@tonic-gate
18007c478bd9Sstevel@tonic-gate int
zonecfg_delete_filesystem(zone_dochandle_t handle,struct zone_fstab * tabptr)18017c478bd9Sstevel@tonic-gate zonecfg_delete_filesystem(zone_dochandle_t handle, struct zone_fstab *tabptr)
18027c478bd9Sstevel@tonic-gate {
18037c478bd9Sstevel@tonic-gate int err;
18047c478bd9Sstevel@tonic-gate
18057c478bd9Sstevel@tonic-gate if (tabptr == NULL)
18067c478bd9Sstevel@tonic-gate return (Z_INVAL);
18077c478bd9Sstevel@tonic-gate
18087c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK)
18097c478bd9Sstevel@tonic-gate return (err);
18107c478bd9Sstevel@tonic-gate
18117c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_filesystem_core(handle, tabptr)) != Z_OK)
18127c478bd9Sstevel@tonic-gate return (err);
18137c478bd9Sstevel@tonic-gate
18147c478bd9Sstevel@tonic-gate return (Z_OK);
18157c478bd9Sstevel@tonic-gate }
18167c478bd9Sstevel@tonic-gate
18177c478bd9Sstevel@tonic-gate int
zonecfg_modify_filesystem(zone_dochandle_t handle,struct zone_fstab * oldtabptr,struct zone_fstab * newtabptr)18187c478bd9Sstevel@tonic-gate zonecfg_modify_filesystem(
18197c478bd9Sstevel@tonic-gate zone_dochandle_t handle,
18207c478bd9Sstevel@tonic-gate struct zone_fstab *oldtabptr,
18217c478bd9Sstevel@tonic-gate struct zone_fstab *newtabptr)
18227c478bd9Sstevel@tonic-gate {
18237c478bd9Sstevel@tonic-gate int err;
18247c478bd9Sstevel@tonic-gate
18257c478bd9Sstevel@tonic-gate if (oldtabptr == NULL || newtabptr == NULL)
18267c478bd9Sstevel@tonic-gate return (Z_INVAL);
18277c478bd9Sstevel@tonic-gate
18287c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK)
18297c478bd9Sstevel@tonic-gate return (err);
18307c478bd9Sstevel@tonic-gate
18317c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_filesystem_core(handle, oldtabptr)) != Z_OK)
18327c478bd9Sstevel@tonic-gate return (err);
18337c478bd9Sstevel@tonic-gate
18347c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_filesystem_core(handle, newtabptr)) != Z_OK)
18357c478bd9Sstevel@tonic-gate return (err);
18367c478bd9Sstevel@tonic-gate
18377c478bd9Sstevel@tonic-gate return (Z_OK);
18387c478bd9Sstevel@tonic-gate }
18397c478bd9Sstevel@tonic-gate
18407c478bd9Sstevel@tonic-gate int
zonecfg_lookup_filesystem(zone_dochandle_t handle,struct zone_fstab * tabptr)18417c478bd9Sstevel@tonic-gate zonecfg_lookup_filesystem(
18427c478bd9Sstevel@tonic-gate zone_dochandle_t handle,
18437c478bd9Sstevel@tonic-gate struct zone_fstab *tabptr)
18447c478bd9Sstevel@tonic-gate {
18457c478bd9Sstevel@tonic-gate xmlNodePtr cur, options, firstmatch;
18467c478bd9Sstevel@tonic-gate int err;
18477c478bd9Sstevel@tonic-gate char dirname[MAXPATHLEN], special[MAXPATHLEN], raw[MAXPATHLEN];
18487c478bd9Sstevel@tonic-gate char type[FSTYPSZ];
18497c478bd9Sstevel@tonic-gate char options_str[MAX_MNTOPT_STR];
18507c478bd9Sstevel@tonic-gate
18517c478bd9Sstevel@tonic-gate if (tabptr == NULL)
18527c478bd9Sstevel@tonic-gate return (Z_INVAL);
18537c478bd9Sstevel@tonic-gate
18547c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK)
18557c478bd9Sstevel@tonic-gate return (err);
18567c478bd9Sstevel@tonic-gate
18577c478bd9Sstevel@tonic-gate /*
18587c478bd9Sstevel@tonic-gate * Walk the list of children looking for matches on any properties
18597c478bd9Sstevel@tonic-gate * specified in the fstab parameter. If more than one resource
18607c478bd9Sstevel@tonic-gate * matches, we return Z_INSUFFICIENT_SPEC; if none match, we return
18617c478bd9Sstevel@tonic-gate * Z_NO_RESOURCE_ID.
18627c478bd9Sstevel@tonic-gate */
18637c478bd9Sstevel@tonic-gate cur = handle->zone_dh_cur;
18647c478bd9Sstevel@tonic-gate firstmatch = NULL;
18657c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
18667c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_FS))
18677c478bd9Sstevel@tonic-gate continue;
18687c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_fs_dir) > 0) {
18697c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_DIR, dirname,
18707c478bd9Sstevel@tonic-gate sizeof (dirname)) == Z_OK) &&
18717c478bd9Sstevel@tonic-gate (strcmp(tabptr->zone_fs_dir, dirname) == 0)) {
18727c478bd9Sstevel@tonic-gate if (firstmatch == NULL)
18737c478bd9Sstevel@tonic-gate firstmatch = cur;
18747c478bd9Sstevel@tonic-gate else
18757c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC);
18767c478bd9Sstevel@tonic-gate }
18777c478bd9Sstevel@tonic-gate }
18787c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_fs_special) > 0) {
18797c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_SPECIAL, special,
18807c478bd9Sstevel@tonic-gate sizeof (special)) == Z_OK)) {
18817c478bd9Sstevel@tonic-gate if (strcmp(tabptr->zone_fs_special,
18827c478bd9Sstevel@tonic-gate special) == 0) {
18837c478bd9Sstevel@tonic-gate if (firstmatch == NULL)
18847c478bd9Sstevel@tonic-gate firstmatch = cur;
18857c478bd9Sstevel@tonic-gate else if (firstmatch != cur)
18867c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC);
18877c478bd9Sstevel@tonic-gate } else {
18887c478bd9Sstevel@tonic-gate /*
18897c478bd9Sstevel@tonic-gate * If another property matched but this
18907c478bd9Sstevel@tonic-gate * one doesn't then reset firstmatch.
18917c478bd9Sstevel@tonic-gate */
18927c478bd9Sstevel@tonic-gate if (firstmatch == cur)
18937c478bd9Sstevel@tonic-gate firstmatch = NULL;
18947c478bd9Sstevel@tonic-gate }
18957c478bd9Sstevel@tonic-gate }
18967c478bd9Sstevel@tonic-gate }
18977c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_fs_raw) > 0) {
18987c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_RAW, raw,
18997c478bd9Sstevel@tonic-gate sizeof (raw)) == Z_OK)) {
19007c478bd9Sstevel@tonic-gate if (strcmp(tabptr->zone_fs_raw, raw) == 0) {
19017c478bd9Sstevel@tonic-gate if (firstmatch == NULL)
19027c478bd9Sstevel@tonic-gate firstmatch = cur;
19037c478bd9Sstevel@tonic-gate else if (firstmatch != cur)
19047c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC);
19057c478bd9Sstevel@tonic-gate } else {
19067c478bd9Sstevel@tonic-gate /*
19077c478bd9Sstevel@tonic-gate * If another property matched but this
19087c478bd9Sstevel@tonic-gate * one doesn't then reset firstmatch.
19097c478bd9Sstevel@tonic-gate */
19107c478bd9Sstevel@tonic-gate if (firstmatch == cur)
19117c478bd9Sstevel@tonic-gate firstmatch = NULL;
19127c478bd9Sstevel@tonic-gate }
19137c478bd9Sstevel@tonic-gate }
19147c478bd9Sstevel@tonic-gate }
19157c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_fs_type) > 0) {
19167c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_TYPE, type,
19177c478bd9Sstevel@tonic-gate sizeof (type)) == Z_OK)) {
19187c478bd9Sstevel@tonic-gate if (strcmp(tabptr->zone_fs_type, type) == 0) {
19197c478bd9Sstevel@tonic-gate if (firstmatch == NULL)
19207c478bd9Sstevel@tonic-gate firstmatch = cur;
19217c478bd9Sstevel@tonic-gate else if (firstmatch != cur)
19227c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC);
19237c478bd9Sstevel@tonic-gate } else {
19247c478bd9Sstevel@tonic-gate /*
19257c478bd9Sstevel@tonic-gate * If another property matched but this
19267c478bd9Sstevel@tonic-gate * one doesn't then reset firstmatch.
19277c478bd9Sstevel@tonic-gate */
19287c478bd9Sstevel@tonic-gate if (firstmatch == cur)
19297c478bd9Sstevel@tonic-gate firstmatch = NULL;
19307c478bd9Sstevel@tonic-gate }
19317c478bd9Sstevel@tonic-gate }
19327c478bd9Sstevel@tonic-gate }
19337c478bd9Sstevel@tonic-gate }
19347c478bd9Sstevel@tonic-gate
19357c478bd9Sstevel@tonic-gate if (firstmatch == NULL)
19367c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID);
19377c478bd9Sstevel@tonic-gate
19387c478bd9Sstevel@tonic-gate cur = firstmatch;
19397c478bd9Sstevel@tonic-gate
19407c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir,
19417c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_dir))) != Z_OK)
19427c478bd9Sstevel@tonic-gate return (err);
19437c478bd9Sstevel@tonic-gate
19447c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_SPECIAL, tabptr->zone_fs_special,
19457c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_special))) != Z_OK)
19467c478bd9Sstevel@tonic-gate return (err);
19477c478bd9Sstevel@tonic-gate
19487c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_RAW, tabptr->zone_fs_raw,
19497c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_raw))) != Z_OK)
19507c478bd9Sstevel@tonic-gate return (err);
19517c478bd9Sstevel@tonic-gate
19527c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_TYPE, tabptr->zone_fs_type,
19537c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_type))) != Z_OK)
19547c478bd9Sstevel@tonic-gate return (err);
19557c478bd9Sstevel@tonic-gate
19567c478bd9Sstevel@tonic-gate /* options are optional */
19577c478bd9Sstevel@tonic-gate tabptr->zone_fs_options = NULL;
19587c478bd9Sstevel@tonic-gate for (options = cur->xmlChildrenNode; options != NULL;
19597c478bd9Sstevel@tonic-gate options = options->next) {
19607c478bd9Sstevel@tonic-gate if ((fetchprop(options, DTD_ATTR_NAME, options_str,
19617c478bd9Sstevel@tonic-gate sizeof (options_str)) != Z_OK))
19627c478bd9Sstevel@tonic-gate break;
19637c478bd9Sstevel@tonic-gate if (zonecfg_add_fs_option(tabptr, options_str) != Z_OK)
19647c478bd9Sstevel@tonic-gate break;
19657c478bd9Sstevel@tonic-gate }
19667c478bd9Sstevel@tonic-gate return (Z_OK);
19677c478bd9Sstevel@tonic-gate }
19687c478bd9Sstevel@tonic-gate
19697c478bd9Sstevel@tonic-gate /*
19707c478bd9Sstevel@tonic-gate * Compare two IP addresses in string form. Allow for the possibility that
19717c478bd9Sstevel@tonic-gate * one might have "/<prefix-length>" at the end: allow a match on just the
19727c478bd9Sstevel@tonic-gate * IP address (or host name) part.
19737c478bd9Sstevel@tonic-gate */
19747c478bd9Sstevel@tonic-gate
19757c478bd9Sstevel@tonic-gate boolean_t
zonecfg_same_net_address(char * a1,char * a2)19767c478bd9Sstevel@tonic-gate zonecfg_same_net_address(char *a1, char *a2)
19777c478bd9Sstevel@tonic-gate {
19787c478bd9Sstevel@tonic-gate char *slashp, *slashp1, *slashp2;
19797c478bd9Sstevel@tonic-gate int result;
19807c478bd9Sstevel@tonic-gate
19817c478bd9Sstevel@tonic-gate if (strcmp(a1, a2) == 0)
19827c478bd9Sstevel@tonic-gate return (B_TRUE);
19837c478bd9Sstevel@tonic-gate
19847c478bd9Sstevel@tonic-gate /*
19857c478bd9Sstevel@tonic-gate * If neither has a slash or both do, they need to match to be
19867c478bd9Sstevel@tonic-gate * considered the same, but they did not match above, so fail.
19877c478bd9Sstevel@tonic-gate */
19887c478bd9Sstevel@tonic-gate slashp1 = strchr(a1, '/');
19897c478bd9Sstevel@tonic-gate slashp2 = strchr(a2, '/');
19907c478bd9Sstevel@tonic-gate if ((slashp1 == NULL && slashp2 == NULL) ||
19917c478bd9Sstevel@tonic-gate (slashp1 != NULL && slashp2 != NULL))
19927c478bd9Sstevel@tonic-gate return (B_FALSE);
19937c478bd9Sstevel@tonic-gate
19947c478bd9Sstevel@tonic-gate /*
19957c478bd9Sstevel@tonic-gate * Only one had a slash: pick that one, zero out the slash, compare
19967c478bd9Sstevel@tonic-gate * the "address only" strings, restore the slash, and return the
19977c478bd9Sstevel@tonic-gate * result of the comparison.
19987c478bd9Sstevel@tonic-gate */
19997c478bd9Sstevel@tonic-gate slashp = (slashp1 == NULL) ? slashp2 : slashp1;
20007c478bd9Sstevel@tonic-gate *slashp = '\0';
20017c478bd9Sstevel@tonic-gate result = strcmp(a1, a2);
20027c478bd9Sstevel@tonic-gate *slashp = '/';
20037c478bd9Sstevel@tonic-gate return ((result == 0));
20047c478bd9Sstevel@tonic-gate }
20057c478bd9Sstevel@tonic-gate
20067c478bd9Sstevel@tonic-gate int
zonecfg_valid_net_address(char * address,struct lifreq * lifr)20077c478bd9Sstevel@tonic-gate zonecfg_valid_net_address(char *address, struct lifreq *lifr)
20087c478bd9Sstevel@tonic-gate {
20097c478bd9Sstevel@tonic-gate struct sockaddr_in *sin4;
20107c478bd9Sstevel@tonic-gate struct sockaddr_in6 *sin6;
20117c478bd9Sstevel@tonic-gate struct addrinfo hints, *result;
20127c478bd9Sstevel@tonic-gate char *slashp = strchr(address, '/');
20137c478bd9Sstevel@tonic-gate
20147c478bd9Sstevel@tonic-gate bzero(lifr, sizeof (struct lifreq));
20157c478bd9Sstevel@tonic-gate sin4 = (struct sockaddr_in *)&lifr->lifr_addr;
20167c478bd9Sstevel@tonic-gate sin6 = (struct sockaddr_in6 *)&lifr->lifr_addr;
20177c478bd9Sstevel@tonic-gate if (slashp != NULL)
20187c478bd9Sstevel@tonic-gate *slashp = '\0';
20197c478bd9Sstevel@tonic-gate if (inet_pton(AF_INET, address, &sin4->sin_addr) == 1) {
20207c478bd9Sstevel@tonic-gate sin4->sin_family = AF_INET;
20217c478bd9Sstevel@tonic-gate } else if (inet_pton(AF_INET6, address, &sin6->sin6_addr) == 1) {
20227c478bd9Sstevel@tonic-gate if (slashp == NULL)
20237c478bd9Sstevel@tonic-gate return (Z_IPV6_ADDR_PREFIX_LEN);
20247c478bd9Sstevel@tonic-gate sin6->sin6_family = AF_INET6;
20257c478bd9Sstevel@tonic-gate } else {
20267c478bd9Sstevel@tonic-gate /* "address" may be a host name */
20277c478bd9Sstevel@tonic-gate (void) memset(&hints, 0, sizeof (hints));
20287c478bd9Sstevel@tonic-gate hints.ai_family = PF_INET;
20297c478bd9Sstevel@tonic-gate if (getaddrinfo(address, NULL, &hints, &result) != 0)
20307c478bd9Sstevel@tonic-gate return (Z_BOGUS_ADDRESS);
20317c478bd9Sstevel@tonic-gate sin4->sin_family = result->ai_family;
2032a1be23daSdp
20337c478bd9Sstevel@tonic-gate (void) memcpy(&sin4->sin_addr,
20347c478bd9Sstevel@tonic-gate /* LINTED E_BAD_PTR_CAST_ALIGN */
20357c478bd9Sstevel@tonic-gate &((struct sockaddr_in *)result->ai_addr)->sin_addr,
20367c478bd9Sstevel@tonic-gate sizeof (struct in_addr));
2037a1be23daSdp
20387c478bd9Sstevel@tonic-gate freeaddrinfo(result);
20397c478bd9Sstevel@tonic-gate }
20407c478bd9Sstevel@tonic-gate return (Z_OK);
20417c478bd9Sstevel@tonic-gate }
20427c478bd9Sstevel@tonic-gate
2043f4b3ec61Sdh155122 boolean_t
zonecfg_ifname_exists(sa_family_t af,char * ifname)2044f4b3ec61Sdh155122 zonecfg_ifname_exists(sa_family_t af, char *ifname)
2045f4b3ec61Sdh155122 {
2046f4b3ec61Sdh155122 struct lifreq lifr;
2047f4b3ec61Sdh155122 int so;
2048f4b3ec61Sdh155122 int save_errno;
2049f4b3ec61Sdh155122
2050f4b3ec61Sdh155122 (void) memset(&lifr, 0, sizeof (lifr));
2051f4b3ec61Sdh155122 (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
2052f4b3ec61Sdh155122 lifr.lifr_addr.ss_family = af;
2053f4b3ec61Sdh155122 if ((so = socket(af, SOCK_DGRAM, 0)) < 0) {
2054f4b3ec61Sdh155122 /* Odd - can't tell if the ifname exists */
2055f4b3ec61Sdh155122 return (B_FALSE);
2056f4b3ec61Sdh155122 }
2057f4b3ec61Sdh155122 if (ioctl(so, SIOCGLIFFLAGS, (caddr_t)&lifr) < 0) {
2058f4b3ec61Sdh155122 save_errno = errno;
2059f4b3ec61Sdh155122 (void) close(so);
2060f4b3ec61Sdh155122 errno = save_errno;
2061f4b3ec61Sdh155122 return (B_FALSE);
2062f4b3ec61Sdh155122 }
2063f4b3ec61Sdh155122 (void) close(so);
2064f4b3ec61Sdh155122 return (B_TRUE);
2065f4b3ec61Sdh155122 }
2066f4b3ec61Sdh155122
2067a8053275Sjv227347 /*
206834eb7836Sjv227347 * Determines whether there is a net resource with the physical interface, IP
206934eb7836Sjv227347 * address, and default router specified by 'tabptr' in the zone configuration
207034eb7836Sjv227347 * to which 'handle' refers. 'tabptr' must have an interface, an address, a
207134eb7836Sjv227347 * default router, or a combination of the three. This function returns Z_OK
207234eb7836Sjv227347 * iff there is exactly one net resource matching the query specified by
207334eb7836Sjv227347 * 'tabptr'. The function returns Z_INSUFFICIENT_SPEC if there are multiple
207434eb7836Sjv227347 * matches or 'tabptr' does not specify a physical interface, address, or
207534eb7836Sjv227347 * default router. The function returns Z_NO_RESOURCE_ID if are no matches.
2076a8053275Sjv227347 *
2077a8053275Sjv227347 * Errors might also be returned if the entry that exactly matches the
2078a8053275Sjv227347 * query lacks critical network resource information.
2079a8053275Sjv227347 *
208034eb7836Sjv227347 * If there is a single match, then the matching entry's physical interface, IP
208134eb7836Sjv227347 * address, and default router information are stored in 'tabptr'.
2082a8053275Sjv227347 */
20837c478bd9Sstevel@tonic-gate int
zonecfg_lookup_nwif(zone_dochandle_t handle,struct zone_nwiftab * tabptr)20847c478bd9Sstevel@tonic-gate zonecfg_lookup_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
20857c478bd9Sstevel@tonic-gate {
2086a8053275Sjv227347 xmlNodePtr cur;
2087a8053275Sjv227347 xmlNodePtr firstmatch;
20887c478bd9Sstevel@tonic-gate int err;
2089a8053275Sjv227347 char address[INET6_ADDRSTRLEN];
2090a8053275Sjv227347 char physical[LIFNAMSIZ];
2091a8053275Sjv227347 size_t addrspec; /* nonzero if tabptr has IP addr */
2092a8053275Sjv227347 size_t physspec; /* nonzero if tabptr has interface */
209334eb7836Sjv227347 size_t defrouterspec; /* nonzero if tabptr has def. router */
2094550b6e40SSowmini Varadhan size_t allowed_addrspec;
2095550b6e40SSowmini Varadhan zone_iptype_t iptype;
20967c478bd9Sstevel@tonic-gate
20977c478bd9Sstevel@tonic-gate if (tabptr == NULL)
20987c478bd9Sstevel@tonic-gate return (Z_INVAL);
20997c478bd9Sstevel@tonic-gate
2100a8053275Sjv227347 /*
210134eb7836Sjv227347 * Determine the fields that will be searched. There must be at least
210234eb7836Sjv227347 * one.
210334eb7836Sjv227347 *
210434eb7836Sjv227347 * zone_nwif_address, zone_nwif_physical, and zone_nwif_defrouter are
210534eb7836Sjv227347 * arrays, so no NULL checks are necessary.
2106a8053275Sjv227347 */
2107a8053275Sjv227347 addrspec = strlen(tabptr->zone_nwif_address);
2108a8053275Sjv227347 physspec = strlen(tabptr->zone_nwif_physical);
210934eb7836Sjv227347 defrouterspec = strlen(tabptr->zone_nwif_defrouter);
2110550b6e40SSowmini Varadhan allowed_addrspec = strlen(tabptr->zone_nwif_allowed_address);
2111550b6e40SSowmini Varadhan if (addrspec != 0 && allowed_addrspec != 0)
2112550b6e40SSowmini Varadhan return (Z_INVAL); /* can't specify both */
2113550b6e40SSowmini Varadhan if (addrspec == 0 && physspec == 0 && defrouterspec == 0 &&
2114550b6e40SSowmini Varadhan allowed_addrspec == 0)
211534eb7836Sjv227347 return (Z_INSUFFICIENT_SPEC);
2116a8053275Sjv227347
21177c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK)
21187c478bd9Sstevel@tonic-gate return (err);
21197c478bd9Sstevel@tonic-gate
2120550b6e40SSowmini Varadhan if ((err = zonecfg_get_iptype(handle, &iptype)) != Z_OK)
2121550b6e40SSowmini Varadhan return (err);
212234eb7836Sjv227347 /*
212334eb7836Sjv227347 * Iterate over the configuration's elements and look for net elements
212434eb7836Sjv227347 * that match the query.
212534eb7836Sjv227347 */
21267c478bd9Sstevel@tonic-gate firstmatch = NULL;
2127a8053275Sjv227347 cur = handle->zone_dh_cur;
21287c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
2129a8053275Sjv227347 /* Skip non-net elements */
21307c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_NET))
21317c478bd9Sstevel@tonic-gate continue;
2132a8053275Sjv227347
2133a8053275Sjv227347 /*
213434eb7836Sjv227347 * If any relevant fields don't match the query, then skip
213534eb7836Sjv227347 * the current net element.
2136a8053275Sjv227347 */
213734eb7836Sjv227347 if (physspec != 0 && (fetchprop(cur, DTD_ATTR_PHYSICAL,
213834eb7836Sjv227347 physical, sizeof (physical)) != Z_OK ||
213934eb7836Sjv227347 strcmp(tabptr->zone_nwif_physical, physical) != 0))
214034eb7836Sjv227347 continue;
2141550b6e40SSowmini Varadhan if (iptype == ZS_SHARED && addrspec != 0 &&
2142550b6e40SSowmini Varadhan (fetchprop(cur, DTD_ATTR_ADDRESS, address,
214334eb7836Sjv227347 sizeof (address)) != Z_OK ||
214434eb7836Sjv227347 !zonecfg_same_net_address(tabptr->zone_nwif_address,
214534eb7836Sjv227347 address)))
214634eb7836Sjv227347 continue;
2147550b6e40SSowmini Varadhan if (iptype == ZS_EXCLUSIVE && allowed_addrspec != 0 &&
2148550b6e40SSowmini Varadhan (fetchprop(cur, DTD_ATTR_ALLOWED_ADDRESS, address,
2149550b6e40SSowmini Varadhan sizeof (address)) != Z_OK ||
2150550b6e40SSowmini Varadhan !zonecfg_same_net_address(tabptr->zone_nwif_allowed_address,
2151550b6e40SSowmini Varadhan address)))
2152550b6e40SSowmini Varadhan continue;
215334eb7836Sjv227347 if (defrouterspec != 0 && (fetchprop(cur, DTD_ATTR_DEFROUTER,
215434eb7836Sjv227347 address, sizeof (address)) != Z_OK ||
215534eb7836Sjv227347 !zonecfg_same_net_address(tabptr->zone_nwif_defrouter,
215634eb7836Sjv227347 address)))
215734eb7836Sjv227347 continue;
215834eb7836Sjv227347
21597c478bd9Sstevel@tonic-gate /*
216034eb7836Sjv227347 * The current net element matches the query. Select it if
216134eb7836Sjv227347 * it's the first match; otherwise, abort the search.
2162a8053275Sjv227347 */
2163a8053275Sjv227347 if (firstmatch == NULL)
2164a8053275Sjv227347 firstmatch = cur;
2165a8053275Sjv227347 else
2166a8053275Sjv227347 return (Z_INSUFFICIENT_SPEC);
21677c478bd9Sstevel@tonic-gate }
21687c478bd9Sstevel@tonic-gate if (firstmatch == NULL)
21697c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID);
21707c478bd9Sstevel@tonic-gate
21717c478bd9Sstevel@tonic-gate cur = firstmatch;
21727c478bd9Sstevel@tonic-gate
21737c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_PHYSICAL, tabptr->zone_nwif_physical,
21747c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_nwif_physical))) != Z_OK)
21757c478bd9Sstevel@tonic-gate return (err);
21767c478bd9Sstevel@tonic-gate
2177550b6e40SSowmini Varadhan if (iptype == ZS_SHARED &&
2178550b6e40SSowmini Varadhan (err = fetchprop(cur, DTD_ATTR_ADDRESS, tabptr->zone_nwif_address,
21797c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_nwif_address))) != Z_OK)
21807c478bd9Sstevel@tonic-gate return (err);
21817c478bd9Sstevel@tonic-gate
2182550b6e40SSowmini Varadhan if (iptype == ZS_EXCLUSIVE &&
2183550b6e40SSowmini Varadhan (err = fetchprop(cur, DTD_ATTR_ALLOWED_ADDRESS,
2184550b6e40SSowmini Varadhan tabptr->zone_nwif_allowed_address,
2185550b6e40SSowmini Varadhan sizeof (tabptr->zone_nwif_allowed_address))) != Z_OK)
2186550b6e40SSowmini Varadhan return (err);
2187550b6e40SSowmini Varadhan
2188de860bd9Sgfaden if ((err = fetchprop(cur, DTD_ATTR_DEFROUTER,
2189de860bd9Sgfaden tabptr->zone_nwif_defrouter,
2190de860bd9Sgfaden sizeof (tabptr->zone_nwif_defrouter))) != Z_OK)
2191de860bd9Sgfaden return (err);
2192de860bd9Sgfaden
21937c478bd9Sstevel@tonic-gate return (Z_OK);
21947c478bd9Sstevel@tonic-gate }
21957c478bd9Sstevel@tonic-gate
21967c478bd9Sstevel@tonic-gate static int
zonecfg_add_nwif_core(zone_dochandle_t handle,struct zone_nwiftab * tabptr)21977c478bd9Sstevel@tonic-gate zonecfg_add_nwif_core(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
21987c478bd9Sstevel@tonic-gate {
21997c478bd9Sstevel@tonic-gate xmlNodePtr newnode, cur = handle->zone_dh_cur;
22007c478bd9Sstevel@tonic-gate int err;
22017c478bd9Sstevel@tonic-gate
22027c478bd9Sstevel@tonic-gate newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_NET, NULL);
2203550b6e40SSowmini Varadhan if (strlen(tabptr->zone_nwif_address) > 0 &&
2204550b6e40SSowmini Varadhan (err = newprop(newnode, DTD_ATTR_ADDRESS,
22057c478bd9Sstevel@tonic-gate tabptr->zone_nwif_address)) != Z_OK)
22067c478bd9Sstevel@tonic-gate return (err);
2207550b6e40SSowmini Varadhan if (strlen(tabptr->zone_nwif_allowed_address) > 0 &&
2208550b6e40SSowmini Varadhan (err = newprop(newnode, DTD_ATTR_ALLOWED_ADDRESS,
2209550b6e40SSowmini Varadhan tabptr->zone_nwif_allowed_address)) != Z_OK)
2210550b6e40SSowmini Varadhan return (err);
2211a1be23daSdp if ((err = newprop(newnode, DTD_ATTR_PHYSICAL,
22127c478bd9Sstevel@tonic-gate tabptr->zone_nwif_physical)) != Z_OK)
22137c478bd9Sstevel@tonic-gate return (err);
221444ce818bSjparcel /*
221544ce818bSjparcel * Do not add this property when it is not set, for backwards
221644ce818bSjparcel * compatibility and because it is optional.
221744ce818bSjparcel */
221844ce818bSjparcel if ((strlen(tabptr->zone_nwif_defrouter) > 0) &&
221944ce818bSjparcel ((err = newprop(newnode, DTD_ATTR_DEFROUTER,
222044ce818bSjparcel tabptr->zone_nwif_defrouter)) != Z_OK))
2221de860bd9Sgfaden return (err);
22227c478bd9Sstevel@tonic-gate return (Z_OK);
22237c478bd9Sstevel@tonic-gate }
22247c478bd9Sstevel@tonic-gate
22257c478bd9Sstevel@tonic-gate int
zonecfg_add_nwif(zone_dochandle_t handle,struct zone_nwiftab * tabptr)22267c478bd9Sstevel@tonic-gate zonecfg_add_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
22277c478bd9Sstevel@tonic-gate {
22287c478bd9Sstevel@tonic-gate int err;
22297c478bd9Sstevel@tonic-gate
22307c478bd9Sstevel@tonic-gate if (tabptr == NULL)
22317c478bd9Sstevel@tonic-gate return (Z_INVAL);
22327c478bd9Sstevel@tonic-gate
22337c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK)
22347c478bd9Sstevel@tonic-gate return (err);
22357c478bd9Sstevel@tonic-gate
22367c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_nwif_core(handle, tabptr)) != Z_OK)
22377c478bd9Sstevel@tonic-gate return (err);
22387c478bd9Sstevel@tonic-gate
22397c478bd9Sstevel@tonic-gate return (Z_OK);
22407c478bd9Sstevel@tonic-gate }
22417c478bd9Sstevel@tonic-gate
22427c478bd9Sstevel@tonic-gate static int
zonecfg_delete_nwif_core(zone_dochandle_t handle,struct zone_nwiftab * tabptr)22437c478bd9Sstevel@tonic-gate zonecfg_delete_nwif_core(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
22447c478bd9Sstevel@tonic-gate {
22457c478bd9Sstevel@tonic-gate xmlNodePtr cur = handle->zone_dh_cur;
2246550b6e40SSowmini Varadhan boolean_t addr_match, phys_match, allowed_addr_match;
22477c478bd9Sstevel@tonic-gate
22487c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
22497c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_NET))
22507c478bd9Sstevel@tonic-gate continue;
22517c478bd9Sstevel@tonic-gate
22527c478bd9Sstevel@tonic-gate addr_match = match_prop(cur, DTD_ATTR_ADDRESS,
22537c478bd9Sstevel@tonic-gate tabptr->zone_nwif_address);
2254550b6e40SSowmini Varadhan allowed_addr_match = match_prop(cur, DTD_ATTR_ALLOWED_ADDRESS,
2255550b6e40SSowmini Varadhan tabptr->zone_nwif_allowed_address);
22567c478bd9Sstevel@tonic-gate phys_match = match_prop(cur, DTD_ATTR_PHYSICAL,
22577c478bd9Sstevel@tonic-gate tabptr->zone_nwif_physical);
22587c478bd9Sstevel@tonic-gate
2259*cbca9407SGary Mills if (addr_match && allowed_addr_match && phys_match) {
22607c478bd9Sstevel@tonic-gate xmlUnlinkNode(cur);
22617c478bd9Sstevel@tonic-gate xmlFreeNode(cur);
22627c478bd9Sstevel@tonic-gate return (Z_OK);
22637c478bd9Sstevel@tonic-gate }
22647c478bd9Sstevel@tonic-gate }
22657c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID);
22667c478bd9Sstevel@tonic-gate }
22677c478bd9Sstevel@tonic-gate
22687c478bd9Sstevel@tonic-gate int
zonecfg_delete_nwif(zone_dochandle_t handle,struct zone_nwiftab * tabptr)22697c478bd9Sstevel@tonic-gate zonecfg_delete_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
22707c478bd9Sstevel@tonic-gate {
22717c478bd9Sstevel@tonic-gate int err;
22727c478bd9Sstevel@tonic-gate
22737c478bd9Sstevel@tonic-gate if (tabptr == NULL)
22747c478bd9Sstevel@tonic-gate return (Z_INVAL);
22757c478bd9Sstevel@tonic-gate
22767c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK)
22777c478bd9Sstevel@tonic-gate return (err);
22787c478bd9Sstevel@tonic-gate
22797c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_nwif_core(handle, tabptr)) != Z_OK)
22807c478bd9Sstevel@tonic-gate return (err);
22817c478bd9Sstevel@tonic-gate
22827c478bd9Sstevel@tonic-gate return (Z_OK);
22837c478bd9Sstevel@tonic-gate }
22847c478bd9Sstevel@tonic-gate
22857c478bd9Sstevel@tonic-gate int
zonecfg_modify_nwif(zone_dochandle_t handle,struct zone_nwiftab * oldtabptr,struct zone_nwiftab * newtabptr)22867c478bd9Sstevel@tonic-gate zonecfg_modify_nwif(
22877c478bd9Sstevel@tonic-gate zone_dochandle_t handle,
22887c478bd9Sstevel@tonic-gate struct zone_nwiftab *oldtabptr,
22897c478bd9Sstevel@tonic-gate struct zone_nwiftab *newtabptr)
22907c478bd9Sstevel@tonic-gate {
22917c478bd9Sstevel@tonic-gate int err;
22927c478bd9Sstevel@tonic-gate
22937c478bd9Sstevel@tonic-gate if (oldtabptr == NULL || newtabptr == NULL)
22947c478bd9Sstevel@tonic-gate return (Z_INVAL);
22957c478bd9Sstevel@tonic-gate
22967c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK)
22977c478bd9Sstevel@tonic-gate return (err);
22987c478bd9Sstevel@tonic-gate
22997c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_nwif_core(handle, oldtabptr)) != Z_OK)
23007c478bd9Sstevel@tonic-gate return (err);
23017c478bd9Sstevel@tonic-gate
23027c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_nwif_core(handle, newtabptr)) != Z_OK)
23037c478bd9Sstevel@tonic-gate return (err);
23047c478bd9Sstevel@tonic-gate
23057c478bd9Sstevel@tonic-gate return (Z_OK);
23067c478bd9Sstevel@tonic-gate }
23077c478bd9Sstevel@tonic-gate
23085679c89fSjv227347 /*
23090fbb751dSJohn Levon * Must be a comma-separated list of alpha-numeric file system names.
23100fbb751dSJohn Levon */
23110fbb751dSJohn Levon static int
zonecfg_valid_fs_allowed(const char * fsallowedp)23120fbb751dSJohn Levon zonecfg_valid_fs_allowed(const char *fsallowedp)
23130fbb751dSJohn Levon {
23140fbb751dSJohn Levon char tmp[ZONE_FS_ALLOWED_MAX];
23150fbb751dSJohn Levon char *cp = tmp;
23160fbb751dSJohn Levon char *p;
23170fbb751dSJohn Levon
23180fbb751dSJohn Levon if (strlen(fsallowedp) > ZONE_FS_ALLOWED_MAX)
23190fbb751dSJohn Levon return (Z_TOO_BIG);
23200fbb751dSJohn Levon
23210fbb751dSJohn Levon (void) strlcpy(tmp, fsallowedp, sizeof (tmp));
23220fbb751dSJohn Levon
23230fbb751dSJohn Levon while (*cp != '\0') {
23240fbb751dSJohn Levon p = cp;
23250fbb751dSJohn Levon while (*p != '\0' && *p != ',') {
2326db0d7085SJerry Jelinek if (!isalnum(*p) && *p != '-')
23270fbb751dSJohn Levon return (Z_INVALID_PROPERTY);
23280fbb751dSJohn Levon p++;
23290fbb751dSJohn Levon }
23300fbb751dSJohn Levon
23310fbb751dSJohn Levon if (*p == ',') {
23320fbb751dSJohn Levon if (p == cp)
23330fbb751dSJohn Levon return (Z_INVALID_PROPERTY);
23340fbb751dSJohn Levon
23350fbb751dSJohn Levon p++;
23360fbb751dSJohn Levon
23370fbb751dSJohn Levon if (*p == '\0')
23380fbb751dSJohn Levon return (Z_INVALID_PROPERTY);
23390fbb751dSJohn Levon }
23400fbb751dSJohn Levon
23410fbb751dSJohn Levon cp = p;
23420fbb751dSJohn Levon }
23430fbb751dSJohn Levon
23440fbb751dSJohn Levon return (Z_OK);
23450fbb751dSJohn Levon }
23460fbb751dSJohn Levon
23470fbb751dSJohn Levon int
zonecfg_get_fs_allowed(zone_dochandle_t handle,char * bufp,size_t buflen)23480fbb751dSJohn Levon zonecfg_get_fs_allowed(zone_dochandle_t handle, char *bufp, size_t buflen)
23490fbb751dSJohn Levon {
23500fbb751dSJohn Levon int err;
23510fbb751dSJohn Levon
23520fbb751dSJohn Levon if ((err = getrootattr(handle, DTD_ATTR_FS_ALLOWED,
23530fbb751dSJohn Levon bufp, buflen)) != Z_OK)
23540fbb751dSJohn Levon return (err);
23550fbb751dSJohn Levon if (bufp[0] == '\0')
23560fbb751dSJohn Levon return (Z_BAD_PROPERTY);
23570fbb751dSJohn Levon return (zonecfg_valid_fs_allowed(bufp));
23580fbb751dSJohn Levon }
23590fbb751dSJohn Levon
23600fbb751dSJohn Levon int
zonecfg_set_fs_allowed(zone_dochandle_t handle,const char * bufp)23610fbb751dSJohn Levon zonecfg_set_fs_allowed(zone_dochandle_t handle, const char *bufp)
23620fbb751dSJohn Levon {
23630fbb751dSJohn Levon int err;
23640fbb751dSJohn Levon
23650fbb751dSJohn Levon if (bufp == NULL || (err = zonecfg_valid_fs_allowed(bufp)) == Z_OK)
23660fbb751dSJohn Levon return (setrootattr(handle, DTD_ATTR_FS_ALLOWED, bufp));
23670fbb751dSJohn Levon return (err);
23680fbb751dSJohn Levon }
23690fbb751dSJohn Levon
23700fbb751dSJohn Levon /*
23710fbb751dSJohn Levon * Determines if the specified string is a valid hostid string. This function
23720fbb751dSJohn Levon * returns Z_OK if the string is a valid hostid string. It returns Z_INVAL if
23730fbb751dSJohn Levon * 'hostidp' is NULL, Z_TOO_BIG if 'hostidp' refers to a string buffer
23740fbb751dSJohn Levon * containing a hex string with more than 8 digits, and Z_INVALID_PROPERTY if
23750fbb751dSJohn Levon * the string has an invalid format.
23760fbb751dSJohn Levon */
23770fbb751dSJohn Levon static int
zonecfg_valid_hostid(const char * hostidp)23780fbb751dSJohn Levon zonecfg_valid_hostid(const char *hostidp)
23790fbb751dSJohn Levon {
23800fbb751dSJohn Levon char *currentp;
23810fbb751dSJohn Levon u_longlong_t hostidval;
23820fbb751dSJohn Levon size_t len;
23830fbb751dSJohn Levon
23840fbb751dSJohn Levon if (hostidp == NULL)
23850fbb751dSJohn Levon return (Z_INVAL);
23860fbb751dSJohn Levon
23870fbb751dSJohn Levon /* Empty strings and strings with whitespace are invalid. */
23880fbb751dSJohn Levon if (*hostidp == '\0')
23890fbb751dSJohn Levon return (Z_INVALID_PROPERTY);
23900fbb751dSJohn Levon for (currentp = (char *)hostidp; *currentp != '\0'; ++currentp) {
23910fbb751dSJohn Levon if (isspace(*currentp))
23920fbb751dSJohn Levon return (Z_INVALID_PROPERTY);
23930fbb751dSJohn Levon }
23940fbb751dSJohn Levon len = (size_t)(currentp - hostidp);
23950fbb751dSJohn Levon
23960fbb751dSJohn Levon /*
23970fbb751dSJohn Levon * The caller might pass a hostid that is larger than the maximum
23980fbb751dSJohn Levon * unsigned 32-bit integral value. Check for this! Also, make sure
23990fbb751dSJohn Levon * that the whole string is converted (this helps us find illegal
24000fbb751dSJohn Levon * characters) and that the whole string fits within a buffer of size
24010fbb751dSJohn Levon * HW_HOSTID_LEN.
24020fbb751dSJohn Levon */
24030fbb751dSJohn Levon currentp = (char *)hostidp;
24040fbb751dSJohn Levon if (strncmp(hostidp, "0x", 2) == 0 || strncmp(hostidp, "0X", 2) == 0)
24050fbb751dSJohn Levon currentp += 2;
24060fbb751dSJohn Levon hostidval = strtoull(currentp, ¤tp, 16);
24070fbb751dSJohn Levon if ((size_t)(currentp - hostidp) >= HW_HOSTID_LEN)
24080fbb751dSJohn Levon return (Z_TOO_BIG);
24090fbb751dSJohn Levon if (hostidval > UINT_MAX || hostidval == HW_INVALID_HOSTID ||
24100fbb751dSJohn Levon currentp != hostidp + len)
24110fbb751dSJohn Levon return (Z_INVALID_PROPERTY);
24120fbb751dSJohn Levon return (Z_OK);
24130fbb751dSJohn Levon }
24140fbb751dSJohn Levon
24150fbb751dSJohn Levon /*
24165679c89fSjv227347 * Gets the zone hostid string stored in the specified zone configuration
24175679c89fSjv227347 * document. This function returns Z_OK on success. Z_BAD_PROPERTY is returned
24185679c89fSjv227347 * if the config file doesn't specify a hostid or if the hostid is blank.
24195679c89fSjv227347 *
24205679c89fSjv227347 * Note that buflen should be at least HW_HOSTID_LEN.
24215679c89fSjv227347 */
24225679c89fSjv227347 int
zonecfg_get_hostid(zone_dochandle_t handle,char * bufp,size_t buflen)24235679c89fSjv227347 zonecfg_get_hostid(zone_dochandle_t handle, char *bufp, size_t buflen)
24245679c89fSjv227347 {
24255679c89fSjv227347 int err;
24265679c89fSjv227347
24275679c89fSjv227347 if ((err = getrootattr(handle, DTD_ATTR_HOSTID, bufp, buflen)) != Z_OK)
24285679c89fSjv227347 return (err);
24295679c89fSjv227347 if (bufp[0] == '\0')
24305679c89fSjv227347 return (Z_BAD_PROPERTY);
24310fbb751dSJohn Levon return (zonecfg_valid_hostid(bufp));
24325679c89fSjv227347 }
24335679c89fSjv227347
24345679c89fSjv227347 /*
24355679c89fSjv227347 * Sets the hostid string in the specified zone config document to the given
24365679c89fSjv227347 * string value. If 'hostidp' is NULL, then the config document's hostid
24375679c89fSjv227347 * attribute is cleared. Non-NULL hostids are validated. This function returns
24385679c89fSjv227347 * Z_OK on success. Any other return value indicates failure.
24395679c89fSjv227347 */
24405679c89fSjv227347 int
zonecfg_set_hostid(zone_dochandle_t handle,const char * hostidp)24415679c89fSjv227347 zonecfg_set_hostid(zone_dochandle_t handle, const char *hostidp)
24425679c89fSjv227347 {
24435679c89fSjv227347 int err;
24445679c89fSjv227347
24455679c89fSjv227347 /*
24465679c89fSjv227347 * A NULL hostid string is interpreted as a request to clear the
24475679c89fSjv227347 * hostid.
24485679c89fSjv227347 */
24495679c89fSjv227347 if (hostidp == NULL || (err = zonecfg_valid_hostid(hostidp)) == Z_OK)
24505679c89fSjv227347 return (setrootattr(handle, DTD_ATTR_HOSTID, hostidp));
24515679c89fSjv227347 return (err);
24525679c89fSjv227347 }
24535679c89fSjv227347
24547c478bd9Sstevel@tonic-gate int
zonecfg_lookup_dev(zone_dochandle_t handle,struct zone_devtab * tabptr)24557c478bd9Sstevel@tonic-gate zonecfg_lookup_dev(zone_dochandle_t handle, struct zone_devtab *tabptr)
24567c478bd9Sstevel@tonic-gate {
24577c478bd9Sstevel@tonic-gate xmlNodePtr cur, firstmatch;
24587c478bd9Sstevel@tonic-gate int err;
24597c478bd9Sstevel@tonic-gate char match[MAXPATHLEN];
24607c478bd9Sstevel@tonic-gate
24617c478bd9Sstevel@tonic-gate if (tabptr == NULL)
24627c478bd9Sstevel@tonic-gate return (Z_INVAL);
24637c478bd9Sstevel@tonic-gate
24647c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK)
24657c478bd9Sstevel@tonic-gate return (err);
24667c478bd9Sstevel@tonic-gate
24677c478bd9Sstevel@tonic-gate cur = handle->zone_dh_cur;
24687c478bd9Sstevel@tonic-gate firstmatch = NULL;
24697c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
24707c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_DEVICE))
24717c478bd9Sstevel@tonic-gate continue;
24727c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_dev_match) == 0)
24737c478bd9Sstevel@tonic-gate continue;
24747c478bd9Sstevel@tonic-gate
24757c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_MATCH, match,
24767c478bd9Sstevel@tonic-gate sizeof (match)) == Z_OK)) {
24777c478bd9Sstevel@tonic-gate if (strcmp(tabptr->zone_dev_match,
24787c478bd9Sstevel@tonic-gate match) == 0) {
24797c478bd9Sstevel@tonic-gate if (firstmatch == NULL)
24807c478bd9Sstevel@tonic-gate firstmatch = cur;
24817c478bd9Sstevel@tonic-gate else if (firstmatch != cur)
24827c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC);
24837c478bd9Sstevel@tonic-gate } else {
24847c478bd9Sstevel@tonic-gate /*
24857c478bd9Sstevel@tonic-gate * If another property matched but this
24867c478bd9Sstevel@tonic-gate * one doesn't then reset firstmatch.
24877c478bd9Sstevel@tonic-gate */
24887c478bd9Sstevel@tonic-gate if (firstmatch == cur)
24897c478bd9Sstevel@tonic-gate firstmatch = NULL;
24907c478bd9Sstevel@tonic-gate }
24917c478bd9Sstevel@tonic-gate }
24927c478bd9Sstevel@tonic-gate }
24937c478bd9Sstevel@tonic-gate if (firstmatch == NULL)
24947c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID);
24957c478bd9Sstevel@tonic-gate
24967c478bd9Sstevel@tonic-gate cur = firstmatch;
24977c478bd9Sstevel@tonic-gate
24987c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_MATCH, tabptr->zone_dev_match,
24997c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_dev_match))) != Z_OK)
25007c478bd9Sstevel@tonic-gate return (err);
25017c478bd9Sstevel@tonic-gate
25027c478bd9Sstevel@tonic-gate return (Z_OK);
25037c478bd9Sstevel@tonic-gate }
25047c478bd9Sstevel@tonic-gate
25057c478bd9Sstevel@tonic-gate static int
zonecfg_add_dev_core(zone_dochandle_t handle,struct zone_devtab * tabptr)25067c478bd9Sstevel@tonic-gate zonecfg_add_dev_core(zone_dochandle_t handle, struct zone_devtab *tabptr)
25077c478bd9Sstevel@tonic-gate {
25087c478bd9Sstevel@tonic-gate xmlNodePtr newnode, cur = handle->zone_dh_cur;
25097c478bd9Sstevel@tonic-gate int err;
25107c478bd9Sstevel@tonic-gate
25117c478bd9Sstevel@tonic-gate newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_DEVICE, NULL);
25127c478bd9Sstevel@tonic-gate
2513a1be23daSdp if ((err = newprop(newnode, DTD_ATTR_MATCH,
25147c478bd9Sstevel@tonic-gate tabptr->zone_dev_match)) != Z_OK)
25157c478bd9Sstevel@tonic-gate return (err);
25167c478bd9Sstevel@tonic-gate
25177c478bd9Sstevel@tonic-gate return (Z_OK);
25187c478bd9Sstevel@tonic-gate }
25197c478bd9Sstevel@tonic-gate
25207c478bd9Sstevel@tonic-gate int
zonecfg_add_dev(zone_dochandle_t handle,struct zone_devtab * tabptr)25217c478bd9Sstevel@tonic-gate zonecfg_add_dev(zone_dochandle_t handle, struct zone_devtab *tabptr)
25227c478bd9Sstevel@tonic-gate {
25237c478bd9Sstevel@tonic-gate int err;
25247c478bd9Sstevel@tonic-gate
25257c478bd9Sstevel@tonic-gate if (tabptr == NULL)
25267c478bd9Sstevel@tonic-gate return (Z_INVAL);
25277c478bd9Sstevel@tonic-gate
25287c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK)
25297c478bd9Sstevel@tonic-gate return (err);
25307c478bd9Sstevel@tonic-gate
25317c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_dev_core(handle, tabptr)) != Z_OK)
25327c478bd9Sstevel@tonic-gate return (err);
25337c478bd9Sstevel@tonic-gate
25347c478bd9Sstevel@tonic-gate return (Z_OK);
25357c478bd9Sstevel@tonic-gate }
25367c478bd9Sstevel@tonic-gate
25377c478bd9Sstevel@tonic-gate static int
zonecfg_delete_dev_core(zone_dochandle_t handle,struct zone_devtab * tabptr)25387c478bd9Sstevel@tonic-gate zonecfg_delete_dev_core(zone_dochandle_t handle, struct zone_devtab *tabptr)
25397c478bd9Sstevel@tonic-gate {
2540facf4a8dSllai1 xmlNodePtr cur = handle->zone_dh_cur;
25417c478bd9Sstevel@tonic-gate int match_match;
25427c478bd9Sstevel@tonic-gate
25437c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
25447c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_DEVICE))
25457c478bd9Sstevel@tonic-gate continue;
25467c478bd9Sstevel@tonic-gate
25477c478bd9Sstevel@tonic-gate match_match = match_prop(cur, DTD_ATTR_MATCH,
25487c478bd9Sstevel@tonic-gate tabptr->zone_dev_match);
25497c478bd9Sstevel@tonic-gate
25507c478bd9Sstevel@tonic-gate if (match_match) {
25517c478bd9Sstevel@tonic-gate xmlUnlinkNode(cur);
25527c478bd9Sstevel@tonic-gate xmlFreeNode(cur);
25537c478bd9Sstevel@tonic-gate return (Z_OK);
25547c478bd9Sstevel@tonic-gate }
25557c478bd9Sstevel@tonic-gate }
25567c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID);
25577c478bd9Sstevel@tonic-gate }
25587c478bd9Sstevel@tonic-gate
25597c478bd9Sstevel@tonic-gate int
zonecfg_delete_dev(zone_dochandle_t handle,struct zone_devtab * tabptr)25607c478bd9Sstevel@tonic-gate zonecfg_delete_dev(zone_dochandle_t handle, struct zone_devtab *tabptr)
25617c478bd9Sstevel@tonic-gate {
25627c478bd9Sstevel@tonic-gate int err;
25637c478bd9Sstevel@tonic-gate
25647c478bd9Sstevel@tonic-gate if (tabptr == NULL)
25657c478bd9Sstevel@tonic-gate return (Z_INVAL);
25667c478bd9Sstevel@tonic-gate
25677c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK)
25687c478bd9Sstevel@tonic-gate return (err);
25697c478bd9Sstevel@tonic-gate
25707c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_dev_core(handle, tabptr)) != Z_OK)
25717c478bd9Sstevel@tonic-gate return (err);
25727c478bd9Sstevel@tonic-gate
25737c478bd9Sstevel@tonic-gate return (Z_OK);
25747c478bd9Sstevel@tonic-gate }
25757c478bd9Sstevel@tonic-gate
25767c478bd9Sstevel@tonic-gate int
zonecfg_modify_dev(zone_dochandle_t handle,struct zone_devtab * oldtabptr,struct zone_devtab * newtabptr)25777c478bd9Sstevel@tonic-gate zonecfg_modify_dev(
25787c478bd9Sstevel@tonic-gate zone_dochandle_t handle,
25797c478bd9Sstevel@tonic-gate struct zone_devtab *oldtabptr,
25807c478bd9Sstevel@tonic-gate struct zone_devtab *newtabptr)
25817c478bd9Sstevel@tonic-gate {
25827c478bd9Sstevel@tonic-gate int err;
25837c478bd9Sstevel@tonic-gate
25847c478bd9Sstevel@tonic-gate if (oldtabptr == NULL || newtabptr == NULL)
25857c478bd9Sstevel@tonic-gate return (Z_INVAL);
25867c478bd9Sstevel@tonic-gate
25877c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK)
25887c478bd9Sstevel@tonic-gate return (err);
25897c478bd9Sstevel@tonic-gate
25907c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_dev_core(handle, oldtabptr)) != Z_OK)
25917c478bd9Sstevel@tonic-gate return (err);
25927c478bd9Sstevel@tonic-gate
25937c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_dev_core(handle, newtabptr)) != Z_OK)
25947c478bd9Sstevel@tonic-gate return (err);
25957c478bd9Sstevel@tonic-gate
25967c478bd9Sstevel@tonic-gate return (Z_OK);
25977c478bd9Sstevel@tonic-gate }
25987c478bd9Sstevel@tonic-gate
2599cb8a054bSGlenn Faden static int
zonecfg_add_auth_core(zone_dochandle_t handle,struct zone_admintab * tabptr,char * zonename)2600cb8a054bSGlenn Faden zonecfg_add_auth_core(zone_dochandle_t handle, struct zone_admintab *tabptr,
2601cb8a054bSGlenn Faden char *zonename)
2602cb8a054bSGlenn Faden {
2603cb8a054bSGlenn Faden xmlNodePtr newnode, cur = handle->zone_dh_cur;
2604cb8a054bSGlenn Faden int err;
2605cb8a054bSGlenn Faden
2606cb8a054bSGlenn Faden newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_ADMIN, NULL);
2607cb8a054bSGlenn Faden err = newprop(newnode, DTD_ATTR_USER, tabptr->zone_admin_user);
2608cb8a054bSGlenn Faden if (err != Z_OK)
2609cb8a054bSGlenn Faden return (err);
2610cb8a054bSGlenn Faden err = newprop(newnode, DTD_ATTR_AUTHS, tabptr->zone_admin_auths);
2611cb8a054bSGlenn Faden if (err != Z_OK)
2612cb8a054bSGlenn Faden return (err);
2613cb8a054bSGlenn Faden if ((err = zonecfg_remove_userauths(
2614cb8a054bSGlenn Faden handle, tabptr->zone_admin_user, zonename, B_FALSE)) != Z_OK)
2615cb8a054bSGlenn Faden return (err);
2616cb8a054bSGlenn Faden return (Z_OK);
2617cb8a054bSGlenn Faden }
2618cb8a054bSGlenn Faden
2619cb8a054bSGlenn Faden int
zonecfg_add_admin(zone_dochandle_t handle,struct zone_admintab * tabptr,char * zonename)2620cb8a054bSGlenn Faden zonecfg_add_admin(zone_dochandle_t handle, struct zone_admintab *tabptr,
2621cb8a054bSGlenn Faden char *zonename)
2622cb8a054bSGlenn Faden {
2623cb8a054bSGlenn Faden int err;
2624cb8a054bSGlenn Faden
2625cb8a054bSGlenn Faden if (tabptr == NULL)
2626cb8a054bSGlenn Faden return (Z_INVAL);
2627cb8a054bSGlenn Faden
2628cb8a054bSGlenn Faden if ((err = operation_prep(handle)) != Z_OK)
2629cb8a054bSGlenn Faden return (err);
2630cb8a054bSGlenn Faden
2631cb8a054bSGlenn Faden if ((err = zonecfg_add_auth_core(handle, tabptr,
2632cb8a054bSGlenn Faden zonename)) != Z_OK)
2633cb8a054bSGlenn Faden return (err);
2634cb8a054bSGlenn Faden
2635cb8a054bSGlenn Faden return (Z_OK);
2636cb8a054bSGlenn Faden }
2637cb8a054bSGlenn Faden static int
zonecfg_delete_auth_core(zone_dochandle_t handle,struct zone_admintab * tabptr,char * zonename)2638cb8a054bSGlenn Faden zonecfg_delete_auth_core(zone_dochandle_t handle, struct zone_admintab *tabptr,
2639cb8a054bSGlenn Faden char *zonename)
2640cb8a054bSGlenn Faden {
2641cb8a054bSGlenn Faden xmlNodePtr cur = handle->zone_dh_cur;
2642cb8a054bSGlenn Faden boolean_t auth_match;
2643cb8a054bSGlenn Faden int err;
2644cb8a054bSGlenn Faden
2645cb8a054bSGlenn Faden for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
2646cb8a054bSGlenn Faden if (xmlStrcmp(cur->name, DTD_ELEM_ADMIN))
2647cb8a054bSGlenn Faden continue;
2648cb8a054bSGlenn Faden auth_match = match_prop(cur, DTD_ATTR_USER,
2649cb8a054bSGlenn Faden tabptr->zone_admin_user);
2650cb8a054bSGlenn Faden if (auth_match) {
2651cb8a054bSGlenn Faden if ((err = zonecfg_insert_userauths(
2652cb8a054bSGlenn Faden handle, tabptr->zone_admin_user,
2653cb8a054bSGlenn Faden zonename)) != Z_OK)
2654cb8a054bSGlenn Faden return (err);
2655cb8a054bSGlenn Faden xmlUnlinkNode(cur);
2656cb8a054bSGlenn Faden xmlFreeNode(cur);
2657cb8a054bSGlenn Faden return (Z_OK);
2658cb8a054bSGlenn Faden }
2659cb8a054bSGlenn Faden }
2660cb8a054bSGlenn Faden return (Z_NO_RESOURCE_ID);
2661cb8a054bSGlenn Faden }
2662cb8a054bSGlenn Faden
2663cb8a054bSGlenn Faden int
zonecfg_delete_admin(zone_dochandle_t handle,struct zone_admintab * tabptr,char * zonename)2664cb8a054bSGlenn Faden zonecfg_delete_admin(zone_dochandle_t handle, struct zone_admintab *tabptr,
2665cb8a054bSGlenn Faden char *zonename)
2666cb8a054bSGlenn Faden {
2667cb8a054bSGlenn Faden int err;
2668cb8a054bSGlenn Faden
2669cb8a054bSGlenn Faden if (tabptr == NULL)
2670cb8a054bSGlenn Faden return (Z_INVAL);
2671cb8a054bSGlenn Faden
2672cb8a054bSGlenn Faden if ((err = operation_prep(handle)) != Z_OK)
2673cb8a054bSGlenn Faden return (err);
2674cb8a054bSGlenn Faden
2675cb8a054bSGlenn Faden if ((err = zonecfg_delete_auth_core(handle, tabptr, zonename)) != Z_OK)
2676cb8a054bSGlenn Faden return (err);
2677cb8a054bSGlenn Faden
2678cb8a054bSGlenn Faden return (Z_OK);
2679cb8a054bSGlenn Faden }
2680cb8a054bSGlenn Faden
2681cb8a054bSGlenn Faden int
zonecfg_modify_admin(zone_dochandle_t handle,struct zone_admintab * oldtabptr,struct zone_admintab * newtabptr,char * zonename)2682cb8a054bSGlenn Faden zonecfg_modify_admin(zone_dochandle_t handle, struct zone_admintab *oldtabptr,
2683cb8a054bSGlenn Faden struct zone_admintab *newtabptr, char *zonename)
2684cb8a054bSGlenn Faden {
2685cb8a054bSGlenn Faden int err;
2686cb8a054bSGlenn Faden
2687cb8a054bSGlenn Faden if (oldtabptr == NULL || newtabptr == NULL)
2688cb8a054bSGlenn Faden return (Z_INVAL);
2689cb8a054bSGlenn Faden
2690cb8a054bSGlenn Faden if ((err = operation_prep(handle)) != Z_OK)
2691cb8a054bSGlenn Faden return (err);
2692cb8a054bSGlenn Faden
2693cb8a054bSGlenn Faden if ((err = zonecfg_delete_auth_core(handle, oldtabptr, zonename))
2694cb8a054bSGlenn Faden != Z_OK)
2695cb8a054bSGlenn Faden return (err);
2696cb8a054bSGlenn Faden
2697cb8a054bSGlenn Faden if ((err = zonecfg_add_auth_core(handle, newtabptr,
2698cb8a054bSGlenn Faden zonename)) != Z_OK)
2699cb8a054bSGlenn Faden return (err);
2700cb8a054bSGlenn Faden
2701cb8a054bSGlenn Faden return (Z_OK);
2702cb8a054bSGlenn Faden }
2703cb8a054bSGlenn Faden
2704cb8a054bSGlenn Faden int
zonecfg_lookup_admin(zone_dochandle_t handle,struct zone_admintab * tabptr)2705cb8a054bSGlenn Faden zonecfg_lookup_admin(zone_dochandle_t handle, struct zone_admintab *tabptr)
2706cb8a054bSGlenn Faden {
2707cb8a054bSGlenn Faden xmlNodePtr cur, firstmatch;
2708cb8a054bSGlenn Faden int err;
2709cb8a054bSGlenn Faden char user[MAXUSERNAME];
2710cb8a054bSGlenn Faden
2711cb8a054bSGlenn Faden if (tabptr == NULL)
2712cb8a054bSGlenn Faden return (Z_INVAL);
2713cb8a054bSGlenn Faden
2714cb8a054bSGlenn Faden if ((err = operation_prep(handle)) != Z_OK)
2715cb8a054bSGlenn Faden return (err);
2716cb8a054bSGlenn Faden
2717cb8a054bSGlenn Faden cur = handle->zone_dh_cur;
2718cb8a054bSGlenn Faden firstmatch = NULL;
2719cb8a054bSGlenn Faden for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
2720cb8a054bSGlenn Faden if (xmlStrcmp(cur->name, DTD_ELEM_ADMIN))
2721cb8a054bSGlenn Faden continue;
2722cb8a054bSGlenn Faden if (strlen(tabptr->zone_admin_user) > 0) {
2723cb8a054bSGlenn Faden if ((fetchprop(cur, DTD_ATTR_USER, user,
2724cb8a054bSGlenn Faden sizeof (user)) == Z_OK) &&
2725cb8a054bSGlenn Faden (strcmp(tabptr->zone_admin_user, user) == 0)) {
2726cb8a054bSGlenn Faden if (firstmatch == NULL)
2727cb8a054bSGlenn Faden firstmatch = cur;
2728cb8a054bSGlenn Faden else
2729cb8a054bSGlenn Faden return (Z_INSUFFICIENT_SPEC);
2730cb8a054bSGlenn Faden }
2731cb8a054bSGlenn Faden }
2732cb8a054bSGlenn Faden }
2733cb8a054bSGlenn Faden if (firstmatch == NULL)
2734cb8a054bSGlenn Faden return (Z_NO_RESOURCE_ID);
2735cb8a054bSGlenn Faden
2736cb8a054bSGlenn Faden cur = firstmatch;
2737cb8a054bSGlenn Faden
2738cb8a054bSGlenn Faden if ((err = fetchprop(cur, DTD_ATTR_USER, tabptr->zone_admin_user,
2739cb8a054bSGlenn Faden sizeof (tabptr->zone_admin_user))) != Z_OK)
2740cb8a054bSGlenn Faden return (err);
2741cb8a054bSGlenn Faden
2742cb8a054bSGlenn Faden if ((err = fetchprop(cur, DTD_ATTR_AUTHS, tabptr->zone_admin_auths,
2743cb8a054bSGlenn Faden sizeof (tabptr->zone_admin_auths))) != Z_OK)
2744cb8a054bSGlenn Faden return (err);
2745cb8a054bSGlenn Faden
2746cb8a054bSGlenn Faden return (Z_OK);
2747cb8a054bSGlenn Faden }
2748cb8a054bSGlenn Faden
2749cb8a054bSGlenn Faden
2750ff17c8bfSgjelinek /* Lock to serialize all devwalks */
2751ee519a1fSgjelinek static pthread_mutex_t zonecfg_devwalk_lock = PTHREAD_MUTEX_INITIALIZER;
2752ee519a1fSgjelinek /*
2753ff17c8bfSgjelinek * Global variables used to pass data from zonecfg_dev_manifest to the nftw
2754ee519a1fSgjelinek * call-back (zonecfg_devwalk_cb). g_devwalk_data is really the void*
2755ff17c8bfSgjelinek * parameter and g_devwalk_cb is really the *cb parameter from
2756ff17c8bfSgjelinek * zonecfg_dev_manifest.
2757ee519a1fSgjelinek */
2758ff17c8bfSgjelinek typedef struct __g_devwalk_data *g_devwalk_data_t;
2759ff17c8bfSgjelinek static g_devwalk_data_t g_devwalk_data;
2760ee519a1fSgjelinek static int (*g_devwalk_cb)(const char *, uid_t, gid_t, mode_t, const char *,
2761ee519a1fSgjelinek void *);
2762ee519a1fSgjelinek static size_t g_devwalk_skip_prefix;
2763ee519a1fSgjelinek
2764ee519a1fSgjelinek /*
2765ff17c8bfSgjelinek * zonecfg_dev_manifest call-back function used during detach to generate the
2766ff17c8bfSgjelinek * dev info in the manifest.
2767ff17c8bfSgjelinek */
2768ff17c8bfSgjelinek static int
get_detach_dev_entry(const char * name,uid_t uid,gid_t gid,mode_t mode,const char * acl,void * hdl)2769ff17c8bfSgjelinek get_detach_dev_entry(const char *name, uid_t uid, gid_t gid, mode_t mode,
2770ff17c8bfSgjelinek const char *acl, void *hdl)
2771ff17c8bfSgjelinek {
2772ff17c8bfSgjelinek zone_dochandle_t handle = (zone_dochandle_t)hdl;
2773ff17c8bfSgjelinek xmlNodePtr newnode;
2774ff17c8bfSgjelinek xmlNodePtr cur;
2775ff17c8bfSgjelinek int err;
2776ff17c8bfSgjelinek char buf[128];
2777ff17c8bfSgjelinek
2778ff17c8bfSgjelinek if ((err = operation_prep(handle)) != Z_OK)
2779ff17c8bfSgjelinek return (err);
2780ff17c8bfSgjelinek
2781ff17c8bfSgjelinek cur = handle->zone_dh_cur;
2782ff17c8bfSgjelinek newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_DEV_PERM, NULL);
2783ff17c8bfSgjelinek if ((err = newprop(newnode, DTD_ATTR_NAME, (char *)name)) != Z_OK)
2784ff17c8bfSgjelinek return (err);
2785ff17c8bfSgjelinek (void) snprintf(buf, sizeof (buf), "%lu", uid);
2786ff17c8bfSgjelinek if ((err = newprop(newnode, DTD_ATTR_UID, buf)) != Z_OK)
2787ff17c8bfSgjelinek return (err);
2788ff17c8bfSgjelinek (void) snprintf(buf, sizeof (buf), "%lu", gid);
2789ff17c8bfSgjelinek if ((err = newprop(newnode, DTD_ATTR_GID, buf)) != Z_OK)
2790ff17c8bfSgjelinek return (err);
2791ff17c8bfSgjelinek (void) snprintf(buf, sizeof (buf), "%o", mode);
2792ff17c8bfSgjelinek if ((err = newprop(newnode, DTD_ATTR_MODE, buf)) != Z_OK)
2793ff17c8bfSgjelinek return (err);
2794ff17c8bfSgjelinek if ((err = newprop(newnode, DTD_ATTR_ACL, (char *)acl)) != Z_OK)
2795ff17c8bfSgjelinek return (err);
2796ff17c8bfSgjelinek return (Z_OK);
2797ff17c8bfSgjelinek }
2798ff17c8bfSgjelinek
2799ff17c8bfSgjelinek /*
2800ff17c8bfSgjelinek * This is the nftw call-back function used by zonecfg_dev_manifest. It is
2801ff17c8bfSgjelinek * responsible for calling the actual call-back.
2802ee519a1fSgjelinek */
2803ee519a1fSgjelinek /* ARGSUSED2 */
2804ee519a1fSgjelinek static int
zonecfg_devwalk_cb(const char * path,const struct stat * st,int f,struct FTW * ftw)2805ee519a1fSgjelinek zonecfg_devwalk_cb(const char *path, const struct stat *st, int f,
2806ee519a1fSgjelinek struct FTW *ftw)
2807ee519a1fSgjelinek {
2808ee519a1fSgjelinek acl_t *acl;
2809ee519a1fSgjelinek char *acl_txt = NULL;
2810ee519a1fSgjelinek
2811ee519a1fSgjelinek /* skip all but character and block devices */
2812ee519a1fSgjelinek if (!S_ISBLK(st->st_mode) && !S_ISCHR(st->st_mode))
2813ee519a1fSgjelinek return (0);
2814ee519a1fSgjelinek
2815ee519a1fSgjelinek if ((acl_get(path, ACL_NO_TRIVIAL, &acl) == 0) &&
2816ee519a1fSgjelinek acl != NULL) {
2817ee519a1fSgjelinek acl_txt = acl_totext(acl, ACL_NORESOLVE);
2818ee519a1fSgjelinek acl_free(acl);
2819ee519a1fSgjelinek }
2820ee519a1fSgjelinek
2821ee519a1fSgjelinek if (strlen(path) <= g_devwalk_skip_prefix)
2822ee519a1fSgjelinek return (0);
2823ee519a1fSgjelinek
2824ee519a1fSgjelinek g_devwalk_cb(path + g_devwalk_skip_prefix, st->st_uid, st->st_gid,
2825ee519a1fSgjelinek st->st_mode & S_IAMB, acl_txt != NULL ? acl_txt : "",
2826ee519a1fSgjelinek g_devwalk_data);
2827ee519a1fSgjelinek free(acl_txt);
2828ee519a1fSgjelinek return (0);
2829ee519a1fSgjelinek }
2830ee519a1fSgjelinek
2831ee519a1fSgjelinek /*
2832ff17c8bfSgjelinek * Walk the dev tree for the zone specified by hdl and call the
2833ff17c8bfSgjelinek * get_detach_dev_entry call-back function for each entry in the tree. The
2834ff17c8bfSgjelinek * call-back will be passed the name, uid, gid, mode, acl string and the
2835ff17c8bfSgjelinek * handle input parameter for each dev entry.
2836ee519a1fSgjelinek *
2837ff17c8bfSgjelinek * Data is passed to get_detach_dev_entry through the global variables
2838ee519a1fSgjelinek * g_devwalk_data, *g_devwalk_cb, and g_devwalk_skip_prefix. The
2839ff17c8bfSgjelinek * zonecfg_devwalk_cb function will actually call get_detach_dev_entry.
2840ee519a1fSgjelinek */
2841ee519a1fSgjelinek int
zonecfg_dev_manifest(zone_dochandle_t hdl)2842ff17c8bfSgjelinek zonecfg_dev_manifest(zone_dochandle_t hdl)
2843ee519a1fSgjelinek {
2844ee519a1fSgjelinek char path[MAXPATHLEN];
2845ee519a1fSgjelinek int ret;
2846ee519a1fSgjelinek
2847ee519a1fSgjelinek if ((ret = zonecfg_get_zonepath(hdl, path, sizeof (path))) != Z_OK)
2848ee519a1fSgjelinek return (ret);
2849ee519a1fSgjelinek
2850ee519a1fSgjelinek if (strlcat(path, "/dev", sizeof (path)) >= sizeof (path))
2851ee519a1fSgjelinek return (Z_TOO_BIG);
2852ee519a1fSgjelinek
2853ee519a1fSgjelinek /*
2854ff17c8bfSgjelinek * We have to serialize all devwalks in the same process
2855ee519a1fSgjelinek * (which should be fine), since nftw() is so badly designed.
2856ee519a1fSgjelinek */
2857ee519a1fSgjelinek (void) pthread_mutex_lock(&zonecfg_devwalk_lock);
2858ee519a1fSgjelinek
2859ff17c8bfSgjelinek g_devwalk_skip_prefix = strlen(path) + 1;
2860ff17c8bfSgjelinek g_devwalk_data = (g_devwalk_data_t)hdl;
2861ff17c8bfSgjelinek g_devwalk_cb = get_detach_dev_entry;
2862ee519a1fSgjelinek (void) nftw(path, zonecfg_devwalk_cb, 0, FTW_PHYS);
2863ee519a1fSgjelinek
2864ee519a1fSgjelinek (void) pthread_mutex_unlock(&zonecfg_devwalk_lock);
2865ee519a1fSgjelinek return (Z_OK);
2866ee519a1fSgjelinek }
2867ee519a1fSgjelinek
2868ee519a1fSgjelinek /*
2869ee519a1fSgjelinek * Update the owner, group, mode and acl on the specified dev (inpath) for
2870ee519a1fSgjelinek * the zone (hdl). This function can be used to fix up the dev tree after
2871ee519a1fSgjelinek * attaching a migrated zone.
2872ee519a1fSgjelinek */
2873ee519a1fSgjelinek int
zonecfg_devperms_apply(zone_dochandle_t hdl,const char * inpath,uid_t owner,gid_t group,mode_t mode,const char * acltxt)2874ee519a1fSgjelinek zonecfg_devperms_apply(zone_dochandle_t hdl, const char *inpath, uid_t owner,
2875ee519a1fSgjelinek gid_t group, mode_t mode, const char *acltxt)
2876ee519a1fSgjelinek {
2877ee519a1fSgjelinek int ret;
2878ee519a1fSgjelinek char path[MAXPATHLEN];
2879ee519a1fSgjelinek struct stat st;
2880ee519a1fSgjelinek acl_t *aclp;
2881ee519a1fSgjelinek
2882ee519a1fSgjelinek if ((ret = zonecfg_get_zonepath(hdl, path, sizeof (path))) != Z_OK)
2883ee519a1fSgjelinek return (ret);
2884ee519a1fSgjelinek
2885ee519a1fSgjelinek if (strlcat(path, "/dev/", sizeof (path)) >= sizeof (path))
2886ee519a1fSgjelinek return (Z_TOO_BIG);
2887ee519a1fSgjelinek if (strlcat(path, inpath, sizeof (path)) >= sizeof (path))
2888ee519a1fSgjelinek return (Z_TOO_BIG);
2889ee519a1fSgjelinek
2890ee519a1fSgjelinek if (stat(path, &st) == -1)
2891ee519a1fSgjelinek return (Z_INVAL);
2892ee519a1fSgjelinek
2893ee519a1fSgjelinek /* make sure we're only touching device nodes */
2894ee519a1fSgjelinek if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode))
2895ee519a1fSgjelinek return (Z_INVAL);
2896ee519a1fSgjelinek
2897ee519a1fSgjelinek if (chown(path, owner, group) == -1)
2898ee519a1fSgjelinek return (Z_SYSTEM);
2899ee519a1fSgjelinek
2900ee519a1fSgjelinek if (chmod(path, mode) == -1)
2901ee519a1fSgjelinek return (Z_SYSTEM);
2902ee519a1fSgjelinek
2903ee519a1fSgjelinek if ((acltxt == NULL) || (strcmp(acltxt, "") == 0))
2904ee519a1fSgjelinek return (Z_OK);
2905ee519a1fSgjelinek
29062ad45a84Sjv227347 if (acl_fromtext(acltxt, &aclp) != 0) {
29072ad45a84Sjv227347 errno = EINVAL;
2908ee519a1fSgjelinek return (Z_SYSTEM);
29092ad45a84Sjv227347 }
2910ee519a1fSgjelinek
2911ee519a1fSgjelinek errno = 0;
2912ee519a1fSgjelinek if (acl_set(path, aclp) == -1) {
2913ee519a1fSgjelinek free(aclp);
2914ee519a1fSgjelinek return (Z_SYSTEM);
2915ee519a1fSgjelinek }
2916ee519a1fSgjelinek
2917ee519a1fSgjelinek free(aclp);
2918ee519a1fSgjelinek return (Z_OK);
2919ee519a1fSgjelinek }
2920ee519a1fSgjelinek
29217c478bd9Sstevel@tonic-gate /*
29227c478bd9Sstevel@tonic-gate * This function finds everything mounted under a zone's rootpath.
29237c478bd9Sstevel@tonic-gate * This returns the number of mounts under rootpath, or -1 on error.
29247c478bd9Sstevel@tonic-gate * callback is called once per mount found with the first argument
29250094b373Sjv227347 * pointing to a mnttab structure containing the mount's information.
29267c478bd9Sstevel@tonic-gate *
29277c478bd9Sstevel@tonic-gate * If the callback function returns non-zero zonecfg_find_mounts
29287c478bd9Sstevel@tonic-gate * aborts with an error.
29297c478bd9Sstevel@tonic-gate */
29307c478bd9Sstevel@tonic-gate int
zonecfg_find_mounts(char * rootpath,int (* callback)(const struct mnttab *,void *),void * priv)29310094b373Sjv227347 zonecfg_find_mounts(char *rootpath, int (*callback)(const struct mnttab *,
29320094b373Sjv227347 void *), void *priv) {
29337c478bd9Sstevel@tonic-gate FILE *mnttab;
29347c478bd9Sstevel@tonic-gate struct mnttab m;
29357c478bd9Sstevel@tonic-gate size_t l;
293607b574eeSgjelinek int zfsl;
29377c478bd9Sstevel@tonic-gate int rv = 0;
293807b574eeSgjelinek char zfs_path[MAXPATHLEN];
29397c478bd9Sstevel@tonic-gate
29407c478bd9Sstevel@tonic-gate assert(rootpath != NULL);
29417c478bd9Sstevel@tonic-gate
294207b574eeSgjelinek if ((zfsl = snprintf(zfs_path, sizeof (zfs_path), "%s/.zfs/", rootpath))
294307b574eeSgjelinek >= sizeof (zfs_path))
294407b574eeSgjelinek return (-1);
294507b574eeSgjelinek
29467c478bd9Sstevel@tonic-gate l = strlen(rootpath);
29477c478bd9Sstevel@tonic-gate
29487c478bd9Sstevel@tonic-gate mnttab = fopen("/etc/mnttab", "r");
29497c478bd9Sstevel@tonic-gate
29507c478bd9Sstevel@tonic-gate if (mnttab == NULL)
29517c478bd9Sstevel@tonic-gate return (-1);
29527c478bd9Sstevel@tonic-gate
29537c478bd9Sstevel@tonic-gate if (ioctl(fileno(mnttab), MNTIOC_SHOWHIDDEN, NULL) < 0) {
29547c478bd9Sstevel@tonic-gate rv = -1;
29557c478bd9Sstevel@tonic-gate goto out;
29567c478bd9Sstevel@tonic-gate }
29577c478bd9Sstevel@tonic-gate
29587c478bd9Sstevel@tonic-gate while (!getmntent(mnttab, &m)) {
29597c478bd9Sstevel@tonic-gate if ((strncmp(rootpath, m.mnt_mountp, l) == 0) &&
296007b574eeSgjelinek (m.mnt_mountp[l] == '/') &&
296107b574eeSgjelinek (strncmp(zfs_path, m.mnt_mountp, zfsl) != 0)) {
29627c478bd9Sstevel@tonic-gate rv++;
29637c478bd9Sstevel@tonic-gate if (callback == NULL)
29647c478bd9Sstevel@tonic-gate continue;
29650094b373Sjv227347 if (callback(&m, priv)) {
29667c478bd9Sstevel@tonic-gate rv = -1;
29677c478bd9Sstevel@tonic-gate goto out;
29687c478bd9Sstevel@tonic-gate
29697c478bd9Sstevel@tonic-gate }
29707c478bd9Sstevel@tonic-gate }
29717c478bd9Sstevel@tonic-gate }
29727c478bd9Sstevel@tonic-gate
29737c478bd9Sstevel@tonic-gate out:
29747c478bd9Sstevel@tonic-gate (void) fclose(mnttab);
29757c478bd9Sstevel@tonic-gate return (rv);
29767c478bd9Sstevel@tonic-gate }
29777c478bd9Sstevel@tonic-gate
29787c478bd9Sstevel@tonic-gate int
zonecfg_lookup_attr(zone_dochandle_t handle,struct zone_attrtab * tabptr)29797c478bd9Sstevel@tonic-gate zonecfg_lookup_attr(zone_dochandle_t handle, struct zone_attrtab *tabptr)
29807c478bd9Sstevel@tonic-gate {
29817c478bd9Sstevel@tonic-gate xmlNodePtr cur, firstmatch;
29827c478bd9Sstevel@tonic-gate int err;
29837c478bd9Sstevel@tonic-gate char name[MAXNAMELEN], type[MAXNAMELEN], value[MAXNAMELEN];
29847c478bd9Sstevel@tonic-gate
29857c478bd9Sstevel@tonic-gate if (tabptr == NULL)
29867c478bd9Sstevel@tonic-gate return (Z_INVAL);
29877c478bd9Sstevel@tonic-gate
29887c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK)
29897c478bd9Sstevel@tonic-gate return (err);
29907c478bd9Sstevel@tonic-gate
29917c478bd9Sstevel@tonic-gate cur = handle->zone_dh_cur;
29927c478bd9Sstevel@tonic-gate firstmatch = NULL;
29937c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
29947c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_ATTR))
29957c478bd9Sstevel@tonic-gate continue;
29967c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_attr_name) > 0) {
29977c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_NAME, name,
29987c478bd9Sstevel@tonic-gate sizeof (name)) == Z_OK) &&
29997c478bd9Sstevel@tonic-gate (strcmp(tabptr->zone_attr_name, name) == 0)) {
30007c478bd9Sstevel@tonic-gate if (firstmatch == NULL)
30017c478bd9Sstevel@tonic-gate firstmatch = cur;
30027c478bd9Sstevel@tonic-gate else
30037c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC);
30047c478bd9Sstevel@tonic-gate }
30057c478bd9Sstevel@tonic-gate }
30067c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_attr_type) > 0) {
30077c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_TYPE, type,
30087c478bd9Sstevel@tonic-gate sizeof (type)) == Z_OK)) {
30097c478bd9Sstevel@tonic-gate if (strcmp(tabptr->zone_attr_type, type) == 0) {
30107c478bd9Sstevel@tonic-gate if (firstmatch == NULL)
30117c478bd9Sstevel@tonic-gate firstmatch = cur;
30127c478bd9Sstevel@tonic-gate else if (firstmatch != cur)
30137c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC);
30147c478bd9Sstevel@tonic-gate } else {
30157c478bd9Sstevel@tonic-gate /*
30167c478bd9Sstevel@tonic-gate * If another property matched but this
30177c478bd9Sstevel@tonic-gate * one doesn't then reset firstmatch.
30187c478bd9Sstevel@tonic-gate */
30197c478bd9Sstevel@tonic-gate if (firstmatch == cur)
30207c478bd9Sstevel@tonic-gate firstmatch = NULL;
30217c478bd9Sstevel@tonic-gate }
30227c478bd9Sstevel@tonic-gate }
30237c478bd9Sstevel@tonic-gate }
30247c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_attr_value) > 0) {
30257c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_VALUE, value,
30267c478bd9Sstevel@tonic-gate sizeof (value)) == Z_OK)) {
30277c478bd9Sstevel@tonic-gate if (strcmp(tabptr->zone_attr_value, value) ==
30287c478bd9Sstevel@tonic-gate 0) {
30297c478bd9Sstevel@tonic-gate if (firstmatch == NULL)
30307c478bd9Sstevel@tonic-gate firstmatch = cur;
30317c478bd9Sstevel@tonic-gate else if (firstmatch != cur)
30327c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC);
30337c478bd9Sstevel@tonic-gate } else {
30347c478bd9Sstevel@tonic-gate /*
30357c478bd9Sstevel@tonic-gate * If another property matched but this
30367c478bd9Sstevel@tonic-gate * one doesn't then reset firstmatch.
30377c478bd9Sstevel@tonic-gate */
30387c478bd9Sstevel@tonic-gate if (firstmatch == cur)
30397c478bd9Sstevel@tonic-gate firstmatch = NULL;
30407c478bd9Sstevel@tonic-gate }
30417c478bd9Sstevel@tonic-gate }
30427c478bd9Sstevel@tonic-gate }
30437c478bd9Sstevel@tonic-gate }
30447c478bd9Sstevel@tonic-gate if (firstmatch == NULL)
30457c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID);
30467c478bd9Sstevel@tonic-gate
30477c478bd9Sstevel@tonic-gate cur = firstmatch;
30487c478bd9Sstevel@tonic-gate
30497c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_NAME, tabptr->zone_attr_name,
30507c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_attr_name))) != Z_OK)
30517c478bd9Sstevel@tonic-gate return (err);
30527c478bd9Sstevel@tonic-gate
30537c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_TYPE, tabptr->zone_attr_type,
30547c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_attr_type))) != Z_OK)
30557c478bd9Sstevel@tonic-gate return (err);
30567c478bd9Sstevel@tonic-gate
30577c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_VALUE, tabptr->zone_attr_value,
30587c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_attr_value))) != Z_OK)
30597c478bd9Sstevel@tonic-gate return (err);
30607c478bd9Sstevel@tonic-gate
30617c478bd9Sstevel@tonic-gate return (Z_OK);
30627c478bd9Sstevel@tonic-gate }
30637c478bd9Sstevel@tonic-gate
30647c478bd9Sstevel@tonic-gate static int
zonecfg_add_attr_core(zone_dochandle_t handle,struct zone_attrtab * tabptr)30657c478bd9Sstevel@tonic-gate zonecfg_add_attr_core(zone_dochandle_t handle, struct zone_attrtab *tabptr)
30667c478bd9Sstevel@tonic-gate {
30677c478bd9Sstevel@tonic-gate xmlNodePtr newnode, cur = handle->zone_dh_cur;
30687c478bd9Sstevel@tonic-gate int err;
30697c478bd9Sstevel@tonic-gate
30707c478bd9Sstevel@tonic-gate newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_ATTR, NULL);
3071a1be23daSdp err = newprop(newnode, DTD_ATTR_NAME, tabptr->zone_attr_name);
30727c478bd9Sstevel@tonic-gate if (err != Z_OK)
30737c478bd9Sstevel@tonic-gate return (err);
3074a1be23daSdp err = newprop(newnode, DTD_ATTR_TYPE, tabptr->zone_attr_type);
30757c478bd9Sstevel@tonic-gate if (err != Z_OK)
30767c478bd9Sstevel@tonic-gate return (err);
3077a1be23daSdp err = newprop(newnode, DTD_ATTR_VALUE, tabptr->zone_attr_value);
30787c478bd9Sstevel@tonic-gate if (err != Z_OK)
30797c478bd9Sstevel@tonic-gate return (err);
30807c478bd9Sstevel@tonic-gate return (Z_OK);
30817c478bd9Sstevel@tonic-gate }
30827c478bd9Sstevel@tonic-gate
30837c478bd9Sstevel@tonic-gate int
zonecfg_add_attr(zone_dochandle_t handle,struct zone_attrtab * tabptr)30847c478bd9Sstevel@tonic-gate zonecfg_add_attr(zone_dochandle_t handle, struct zone_attrtab *tabptr)
30857c478bd9Sstevel@tonic-gate {
30867c478bd9Sstevel@tonic-gate int err;
30877c478bd9Sstevel@tonic-gate
30887c478bd9Sstevel@tonic-gate if (tabptr == NULL)
30897c478bd9Sstevel@tonic-gate return (Z_INVAL);
30907c478bd9Sstevel@tonic-gate
30917c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK)
30927c478bd9Sstevel@tonic-gate return (err);
30937c478bd9Sstevel@tonic-gate
30947c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_attr_core(handle, tabptr)) != Z_OK)
30957c478bd9Sstevel@tonic-gate return (err);
30967c478bd9Sstevel@tonic-gate
30977c478bd9Sstevel@tonic-gate return (Z_OK);
30987c478bd9Sstevel@tonic-gate }
30997c478bd9Sstevel@tonic-gate
31007c478bd9Sstevel@tonic-gate static int
zonecfg_delete_attr_core(zone_dochandle_t handle,struct zone_attrtab * tabptr)31017c478bd9Sstevel@tonic-gate zonecfg_delete_attr_core(zone_dochandle_t handle, struct zone_attrtab *tabptr)
31027c478bd9Sstevel@tonic-gate {
31037c478bd9Sstevel@tonic-gate xmlNodePtr cur = handle->zone_dh_cur;
31047c478bd9Sstevel@tonic-gate int name_match, type_match, value_match;
31057c478bd9Sstevel@tonic-gate
31067c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
31077c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_ATTR))
31087c478bd9Sstevel@tonic-gate continue;
31097c478bd9Sstevel@tonic-gate
31107c478bd9Sstevel@tonic-gate name_match = match_prop(cur, DTD_ATTR_NAME,
31117c478bd9Sstevel@tonic-gate tabptr->zone_attr_name);
31127c478bd9Sstevel@tonic-gate type_match = match_prop(cur, DTD_ATTR_TYPE,
31137c478bd9Sstevel@tonic-gate tabptr->zone_attr_type);
31147c478bd9Sstevel@tonic-gate value_match = match_prop(cur, DTD_ATTR_VALUE,
31157c478bd9Sstevel@tonic-gate tabptr->zone_attr_value);
31167c478bd9Sstevel@tonic-gate
31177c478bd9Sstevel@tonic-gate if (name_match && type_match && value_match) {
31187c478bd9Sstevel@tonic-gate xmlUnlinkNode(cur);
31197c478bd9Sstevel@tonic-gate xmlFreeNode(cur);
31207c478bd9Sstevel@tonic-gate return (Z_OK);
31217c478bd9Sstevel@tonic-gate }
31227c478bd9Sstevel@tonic-gate }
31237c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID);
31247c478bd9Sstevel@tonic-gate }
31257c478bd9Sstevel@tonic-gate
31267c478bd9Sstevel@tonic-gate int
zonecfg_delete_attr(zone_dochandle_t handle,struct zone_attrtab * tabptr)31277c478bd9Sstevel@tonic-gate zonecfg_delete_attr(zone_dochandle_t handle, struct zone_attrtab *tabptr)
31287c478bd9Sstevel@tonic-gate {
31297c478bd9Sstevel@tonic-gate int err;
31307c478bd9Sstevel@tonic-gate
31317c478bd9Sstevel@tonic-gate if (tabptr == NULL)
31327c478bd9Sstevel@tonic-gate return (Z_INVAL);
31337c478bd9Sstevel@tonic-gate
31347c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK)
31357c478bd9Sstevel@tonic-gate return (err);
31367c478bd9Sstevel@tonic-gate
31377c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_attr_core(handle, tabptr)) != Z_OK)
31387c478bd9Sstevel@tonic-gate return (err);
31397c478bd9Sstevel@tonic-gate
31407c478bd9Sstevel@tonic-gate return (Z_OK);
31417c478bd9Sstevel@tonic-gate }
31427c478bd9Sstevel@tonic-gate
31437c478bd9Sstevel@tonic-gate int
zonecfg_modify_attr(zone_dochandle_t handle,struct zone_attrtab * oldtabptr,struct zone_attrtab * newtabptr)31447c478bd9Sstevel@tonic-gate zonecfg_modify_attr(
31457c478bd9Sstevel@tonic-gate zone_dochandle_t handle,
31467c478bd9Sstevel@tonic-gate struct zone_attrtab *oldtabptr,
31477c478bd9Sstevel@tonic-gate struct zone_attrtab *newtabptr)
31487c478bd9Sstevel@tonic-gate {
31497c478bd9Sstevel@tonic-gate int err;
31507c478bd9Sstevel@tonic-gate
31517c478bd9Sstevel@tonic-gate if (oldtabptr == NULL || newtabptr == NULL)
31527c478bd9Sstevel@tonic-gate return (Z_INVAL);
31537c478bd9Sstevel@tonic-gate
31547c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK)
31557c478bd9Sstevel@tonic-gate return (err);
31567c478bd9Sstevel@tonic-gate
31577c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_attr_core(handle, oldtabptr)) != Z_OK)
31587c478bd9Sstevel@tonic-gate return (err);
31597c478bd9Sstevel@tonic-gate
31607c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_attr_core(handle, newtabptr)) != Z_OK)
31617c478bd9Sstevel@tonic-gate return (err);
31627c478bd9Sstevel@tonic-gate
31637c478bd9Sstevel@tonic-gate return (Z_OK);
31647c478bd9Sstevel@tonic-gate }
31657c478bd9Sstevel@tonic-gate
31667c478bd9Sstevel@tonic-gate int
zonecfg_get_attr_boolean(const struct zone_attrtab * attr,boolean_t * value)31677c478bd9Sstevel@tonic-gate zonecfg_get_attr_boolean(const struct zone_attrtab *attr, boolean_t *value)
31687c478bd9Sstevel@tonic-gate {
31697c478bd9Sstevel@tonic-gate if (attr == NULL)
31707c478bd9Sstevel@tonic-gate return (Z_INVAL);
31717c478bd9Sstevel@tonic-gate
31727c478bd9Sstevel@tonic-gate if (strcmp(attr->zone_attr_type, DTD_ENTITY_BOOLEAN) != 0)
31737c478bd9Sstevel@tonic-gate return (Z_INVAL);
31747c478bd9Sstevel@tonic-gate
31757c478bd9Sstevel@tonic-gate if (strcmp(attr->zone_attr_value, DTD_ENTITY_TRUE) == 0) {
31767c478bd9Sstevel@tonic-gate *value = B_TRUE;
31777c478bd9Sstevel@tonic-gate return (Z_OK);
31787c478bd9Sstevel@tonic-gate }
31797c478bd9Sstevel@tonic-gate if (strcmp(attr->zone_attr_value, DTD_ENTITY_FALSE) == 0) {
31807c478bd9Sstevel@tonic-gate *value = B_FALSE;
31817c478bd9Sstevel@tonic-gate return (Z_OK);
31827c478bd9Sstevel@tonic-gate }
31837c478bd9Sstevel@tonic-gate return (Z_INVAL);
31847c478bd9Sstevel@tonic-gate }
31857c478bd9Sstevel@tonic-gate
31867c478bd9Sstevel@tonic-gate int
zonecfg_get_attr_int(const struct zone_attrtab * attr,int64_t * value)31877c478bd9Sstevel@tonic-gate zonecfg_get_attr_int(const struct zone_attrtab *attr, int64_t *value)
31887c478bd9Sstevel@tonic-gate {
31897c478bd9Sstevel@tonic-gate long long result;
31907c478bd9Sstevel@tonic-gate char *endptr;
31917c478bd9Sstevel@tonic-gate
31927c478bd9Sstevel@tonic-gate if (attr == NULL)
31937c478bd9Sstevel@tonic-gate return (Z_INVAL);
31947c478bd9Sstevel@tonic-gate
31957c478bd9Sstevel@tonic-gate if (strcmp(attr->zone_attr_type, DTD_ENTITY_INT) != 0)
31967c478bd9Sstevel@tonic-gate return (Z_INVAL);
31977c478bd9Sstevel@tonic-gate
31987c478bd9Sstevel@tonic-gate errno = 0;
31997c478bd9Sstevel@tonic-gate result = strtoll(attr->zone_attr_value, &endptr, 10);
32007c478bd9Sstevel@tonic-gate if (errno != 0 || *endptr != '\0')
32017c478bd9Sstevel@tonic-gate return (Z_INVAL);
32027c478bd9Sstevel@tonic-gate *value = result;
32037c478bd9Sstevel@tonic-gate return (Z_OK);
32047c478bd9Sstevel@tonic-gate }
32057c478bd9Sstevel@tonic-gate
32067c478bd9Sstevel@tonic-gate int
zonecfg_get_attr_string(const struct zone_attrtab * attr,char * value,size_t val_sz)32077c478bd9Sstevel@tonic-gate zonecfg_get_attr_string(const struct zone_attrtab *attr, char *value,
32087c478bd9Sstevel@tonic-gate size_t val_sz)
32097c478bd9Sstevel@tonic-gate {
32107c478bd9Sstevel@tonic-gate if (attr == NULL)
32117c478bd9Sstevel@tonic-gate return (Z_INVAL);
32127c478bd9Sstevel@tonic-gate
32137c478bd9Sstevel@tonic-gate if (strcmp(attr->zone_attr_type, DTD_ENTITY_STRING) != 0)
32147c478bd9Sstevel@tonic-gate return (Z_INVAL);
32157c478bd9Sstevel@tonic-gate
32167c478bd9Sstevel@tonic-gate if (strlcpy(value, attr->zone_attr_value, val_sz) >= val_sz)
32177c478bd9Sstevel@tonic-gate return (Z_TOO_BIG);
32187c478bd9Sstevel@tonic-gate return (Z_OK);
32197c478bd9Sstevel@tonic-gate }
32207c478bd9Sstevel@tonic-gate
32217c478bd9Sstevel@tonic-gate int
zonecfg_get_attr_uint(const struct zone_attrtab * attr,uint64_t * value)32227c478bd9Sstevel@tonic-gate zonecfg_get_attr_uint(const struct zone_attrtab *attr, uint64_t *value)
32237c478bd9Sstevel@tonic-gate {
32247c478bd9Sstevel@tonic-gate unsigned long long result;
32257c478bd9Sstevel@tonic-gate long long neg_result;
32267c478bd9Sstevel@tonic-gate char *endptr;
32277c478bd9Sstevel@tonic-gate
32287c478bd9Sstevel@tonic-gate if (attr == NULL)
32297c478bd9Sstevel@tonic-gate return (Z_INVAL);
32307c478bd9Sstevel@tonic-gate
32317c478bd9Sstevel@tonic-gate if (strcmp(attr->zone_attr_type, DTD_ENTITY_UINT) != 0)
32327c478bd9Sstevel@tonic-gate return (Z_INVAL);
32337c478bd9Sstevel@tonic-gate
32347c478bd9Sstevel@tonic-gate errno = 0;
32357c478bd9Sstevel@tonic-gate result = strtoull(attr->zone_attr_value, &endptr, 10);
32367c478bd9Sstevel@tonic-gate if (errno != 0 || *endptr != '\0')
32377c478bd9Sstevel@tonic-gate return (Z_INVAL);
32387c478bd9Sstevel@tonic-gate errno = 0;
32397c478bd9Sstevel@tonic-gate neg_result = strtoll(attr->zone_attr_value, &endptr, 10);
32407c478bd9Sstevel@tonic-gate /*
32417c478bd9Sstevel@tonic-gate * Incredibly, strtoull("<negative number>", ...) will not fail but
32427c478bd9Sstevel@tonic-gate * return whatever (negative) number cast as a u_longlong_t, so we
32437c478bd9Sstevel@tonic-gate * need to look for this here.
32447c478bd9Sstevel@tonic-gate */
32457c478bd9Sstevel@tonic-gate if (errno == 0 && neg_result < 0)
32467c478bd9Sstevel@tonic-gate return (Z_INVAL);
32477c478bd9Sstevel@tonic-gate *value = result;
32487c478bd9Sstevel@tonic-gate return (Z_OK);
32497c478bd9Sstevel@tonic-gate }
32507c478bd9Sstevel@tonic-gate
32517c478bd9Sstevel@tonic-gate int
zonecfg_lookup_rctl(zone_dochandle_t handle,struct zone_rctltab * tabptr)32527c478bd9Sstevel@tonic-gate zonecfg_lookup_rctl(zone_dochandle_t handle, struct zone_rctltab *tabptr)
32537c478bd9Sstevel@tonic-gate {
32547c478bd9Sstevel@tonic-gate xmlNodePtr cur, val;
32557c478bd9Sstevel@tonic-gate char savedname[MAXNAMELEN];
32567c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *valptr;
32577c478bd9Sstevel@tonic-gate int err;
32587c478bd9Sstevel@tonic-gate
32592ad45a84Sjv227347 if (strlen(tabptr->zone_rctl_name) == 0)
32607c478bd9Sstevel@tonic-gate return (Z_INVAL);
32617c478bd9Sstevel@tonic-gate
32627c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK)
32637c478bd9Sstevel@tonic-gate return (err);
32647c478bd9Sstevel@tonic-gate
32657c478bd9Sstevel@tonic-gate cur = handle->zone_dh_cur;
32667c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
32677c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_RCTL))
32687c478bd9Sstevel@tonic-gate continue;
32697c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_NAME, savedname,
32707c478bd9Sstevel@tonic-gate sizeof (savedname)) == Z_OK) &&
32717c478bd9Sstevel@tonic-gate (strcmp(savedname, tabptr->zone_rctl_name) == 0)) {
32727c478bd9Sstevel@tonic-gate tabptr->zone_rctl_valptr = NULL;
32737c478bd9Sstevel@tonic-gate for (val = cur->xmlChildrenNode; val != NULL;
32747c478bd9Sstevel@tonic-gate val = val->next) {
32757c478bd9Sstevel@tonic-gate valptr = (struct zone_rctlvaltab *)malloc(
32767c478bd9Sstevel@tonic-gate sizeof (struct zone_rctlvaltab));
32777c478bd9Sstevel@tonic-gate if (valptr == NULL)
32787c478bd9Sstevel@tonic-gate return (Z_NOMEM);
32797c478bd9Sstevel@tonic-gate if ((fetchprop(val, DTD_ATTR_PRIV,
32807c478bd9Sstevel@tonic-gate valptr->zone_rctlval_priv,
32817c478bd9Sstevel@tonic-gate sizeof (valptr->zone_rctlval_priv)) !=
32827c478bd9Sstevel@tonic-gate Z_OK))
32837c478bd9Sstevel@tonic-gate break;
32847c478bd9Sstevel@tonic-gate if ((fetchprop(val, DTD_ATTR_LIMIT,
32857c478bd9Sstevel@tonic-gate valptr->zone_rctlval_limit,
32867c478bd9Sstevel@tonic-gate sizeof (valptr->zone_rctlval_limit)) !=
32877c478bd9Sstevel@tonic-gate Z_OK))
32887c478bd9Sstevel@tonic-gate break;
32897c478bd9Sstevel@tonic-gate if ((fetchprop(val, DTD_ATTR_ACTION,
32907c478bd9Sstevel@tonic-gate valptr->zone_rctlval_action,
32917c478bd9Sstevel@tonic-gate sizeof (valptr->zone_rctlval_action)) !=
32927c478bd9Sstevel@tonic-gate Z_OK))
32937c478bd9Sstevel@tonic-gate break;
32947c478bd9Sstevel@tonic-gate if (zonecfg_add_rctl_value(tabptr, valptr) !=
32957c478bd9Sstevel@tonic-gate Z_OK)
32967c478bd9Sstevel@tonic-gate break;
32977c478bd9Sstevel@tonic-gate }
32987c478bd9Sstevel@tonic-gate return (Z_OK);
32997c478bd9Sstevel@tonic-gate }
33007c478bd9Sstevel@tonic-gate }
33017c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID);
33027c478bd9Sstevel@tonic-gate }
33037c478bd9Sstevel@tonic-gate
33047c478bd9Sstevel@tonic-gate static int
zonecfg_add_rctl_core(zone_dochandle_t handle,struct zone_rctltab * tabptr)33057c478bd9Sstevel@tonic-gate zonecfg_add_rctl_core(zone_dochandle_t handle, struct zone_rctltab *tabptr)
33067c478bd9Sstevel@tonic-gate {
33077c478bd9Sstevel@tonic-gate xmlNodePtr newnode, cur = handle->zone_dh_cur, valnode;
33087c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *valptr;
33097c478bd9Sstevel@tonic-gate int err;
33107c478bd9Sstevel@tonic-gate
33117c478bd9Sstevel@tonic-gate newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_RCTL, NULL);
3312a1be23daSdp err = newprop(newnode, DTD_ATTR_NAME, tabptr->zone_rctl_name);
33137c478bd9Sstevel@tonic-gate if (err != Z_OK)
33147c478bd9Sstevel@tonic-gate return (err);
33157c478bd9Sstevel@tonic-gate for (valptr = tabptr->zone_rctl_valptr; valptr != NULL;
33167c478bd9Sstevel@tonic-gate valptr = valptr->zone_rctlval_next) {
33177c478bd9Sstevel@tonic-gate valnode = xmlNewTextChild(newnode, NULL,
33187c478bd9Sstevel@tonic-gate DTD_ELEM_RCTLVALUE, NULL);
3319a1be23daSdp err = newprop(valnode, DTD_ATTR_PRIV,
33207c478bd9Sstevel@tonic-gate valptr->zone_rctlval_priv);
33217c478bd9Sstevel@tonic-gate if (err != Z_OK)
33227c478bd9Sstevel@tonic-gate return (err);
3323a1be23daSdp err = newprop(valnode, DTD_ATTR_LIMIT,
33247c478bd9Sstevel@tonic-gate valptr->zone_rctlval_limit);
33257c478bd9Sstevel@tonic-gate if (err != Z_OK)
33267c478bd9Sstevel@tonic-gate return (err);
3327a1be23daSdp err = newprop(valnode, DTD_ATTR_ACTION,
33287c478bd9Sstevel@tonic-gate valptr->zone_rctlval_action);
33297c478bd9Sstevel@tonic-gate if (err != Z_OK)
33307c478bd9Sstevel@tonic-gate return (err);
33317c478bd9Sstevel@tonic-gate }
33327c478bd9Sstevel@tonic-gate return (Z_OK);
33337c478bd9Sstevel@tonic-gate }
33347c478bd9Sstevel@tonic-gate
33357c478bd9Sstevel@tonic-gate int
zonecfg_add_rctl(zone_dochandle_t handle,struct zone_rctltab * tabptr)33367c478bd9Sstevel@tonic-gate zonecfg_add_rctl(zone_dochandle_t handle, struct zone_rctltab *tabptr)
33377c478bd9Sstevel@tonic-gate {
33387c478bd9Sstevel@tonic-gate int err;
33397c478bd9Sstevel@tonic-gate
33402ad45a84Sjv227347 if (tabptr == NULL)
33417c478bd9Sstevel@tonic-gate return (Z_INVAL);
33427c478bd9Sstevel@tonic-gate
33437c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK)
33447c478bd9Sstevel@tonic-gate return (err);
33457c478bd9Sstevel@tonic-gate
33467c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_rctl_core(handle, tabptr)) != Z_OK)
33477c478bd9Sstevel@tonic-gate return (err);
33487c478bd9Sstevel@tonic-gate
33497c478bd9Sstevel@tonic-gate return (Z_OK);
33507c478bd9Sstevel@tonic-gate }
33517c478bd9Sstevel@tonic-gate
33527c478bd9Sstevel@tonic-gate static int
zonecfg_delete_rctl_core(zone_dochandle_t handle,struct zone_rctltab * tabptr)33537c478bd9Sstevel@tonic-gate zonecfg_delete_rctl_core(zone_dochandle_t handle, struct zone_rctltab *tabptr)
33547c478bd9Sstevel@tonic-gate {
33557c478bd9Sstevel@tonic-gate xmlNodePtr cur = handle->zone_dh_cur;
33567c478bd9Sstevel@tonic-gate xmlChar *savedname;
33577c478bd9Sstevel@tonic-gate int name_result;
33587c478bd9Sstevel@tonic-gate
33597c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
33607c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_RCTL))
33617c478bd9Sstevel@tonic-gate continue;
33627c478bd9Sstevel@tonic-gate
33637c478bd9Sstevel@tonic-gate savedname = xmlGetProp(cur, DTD_ATTR_NAME);
33647c478bd9Sstevel@tonic-gate if (savedname == NULL) /* shouldn't happen */
33657c478bd9Sstevel@tonic-gate continue;
33667c478bd9Sstevel@tonic-gate name_result = xmlStrcmp(savedname,
33677c478bd9Sstevel@tonic-gate (const xmlChar *) tabptr->zone_rctl_name);
33687c478bd9Sstevel@tonic-gate xmlFree(savedname);
33697c478bd9Sstevel@tonic-gate
33707c478bd9Sstevel@tonic-gate if (name_result == 0) {
33717c478bd9Sstevel@tonic-gate xmlUnlinkNode(cur);
33727c478bd9Sstevel@tonic-gate xmlFreeNode(cur);
33737c478bd9Sstevel@tonic-gate return (Z_OK);
33747c478bd9Sstevel@tonic-gate }
33757c478bd9Sstevel@tonic-gate }
33767c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID);
33777c478bd9Sstevel@tonic-gate }
33787c478bd9Sstevel@tonic-gate
33797c478bd9Sstevel@tonic-gate int
zonecfg_delete_rctl(zone_dochandle_t handle,struct zone_rctltab * tabptr)33807c478bd9Sstevel@tonic-gate zonecfg_delete_rctl(zone_dochandle_t handle, struct zone_rctltab *tabptr)
33817c478bd9Sstevel@tonic-gate {
33827c478bd9Sstevel@tonic-gate int err;
33837c478bd9Sstevel@tonic-gate
33842ad45a84Sjv227347 if (tabptr == NULL)
33857c478bd9Sstevel@tonic-gate return (Z_INVAL);
33867c478bd9Sstevel@tonic-gate
33877c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK)
33887c478bd9Sstevel@tonic-gate return (err);
33897c478bd9Sstevel@tonic-gate
33907c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_rctl_core(handle, tabptr)) != Z_OK)
33917c478bd9Sstevel@tonic-gate return (err);
33927c478bd9Sstevel@tonic-gate
33937c478bd9Sstevel@tonic-gate return (Z_OK);
33947c478bd9Sstevel@tonic-gate }
33957c478bd9Sstevel@tonic-gate
33967c478bd9Sstevel@tonic-gate int
zonecfg_modify_rctl(zone_dochandle_t handle,struct zone_rctltab * oldtabptr,struct zone_rctltab * newtabptr)33977c478bd9Sstevel@tonic-gate zonecfg_modify_rctl(
33987c478bd9Sstevel@tonic-gate zone_dochandle_t handle,
33997c478bd9Sstevel@tonic-gate struct zone_rctltab *oldtabptr,
34007c478bd9Sstevel@tonic-gate struct zone_rctltab *newtabptr)
34017c478bd9Sstevel@tonic-gate {
34027c478bd9Sstevel@tonic-gate int err;
34037c478bd9Sstevel@tonic-gate
34042ad45a84Sjv227347 if (oldtabptr == NULL || newtabptr == NULL)
34057c478bd9Sstevel@tonic-gate return (Z_INVAL);
34067c478bd9Sstevel@tonic-gate
34077c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK)
34087c478bd9Sstevel@tonic-gate return (err);
34097c478bd9Sstevel@tonic-gate
34107c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_rctl_core(handle, oldtabptr)) != Z_OK)
34117c478bd9Sstevel@tonic-gate return (err);
34127c478bd9Sstevel@tonic-gate
34137c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_rctl_core(handle, newtabptr)) != Z_OK)
34147c478bd9Sstevel@tonic-gate return (err);
34157c478bd9Sstevel@tonic-gate
34167c478bd9Sstevel@tonic-gate return (Z_OK);
34177c478bd9Sstevel@tonic-gate }
34187c478bd9Sstevel@tonic-gate
34197c478bd9Sstevel@tonic-gate int
zonecfg_add_rctl_value(struct zone_rctltab * tabptr,struct zone_rctlvaltab * valtabptr)34207c478bd9Sstevel@tonic-gate zonecfg_add_rctl_value(
34217c478bd9Sstevel@tonic-gate struct zone_rctltab *tabptr,
34227c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *valtabptr)
34237c478bd9Sstevel@tonic-gate {
34247c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *last, *old, *new;
34257c478bd9Sstevel@tonic-gate rctlblk_t *rctlblk = alloca(rctlblk_size());
34267c478bd9Sstevel@tonic-gate
34277c478bd9Sstevel@tonic-gate last = tabptr->zone_rctl_valptr;
34287c478bd9Sstevel@tonic-gate for (old = last; old != NULL; old = old->zone_rctlval_next)
34297c478bd9Sstevel@tonic-gate last = old; /* walk to the end of the list */
34307c478bd9Sstevel@tonic-gate new = valtabptr; /* alloc'd by caller */
34317c478bd9Sstevel@tonic-gate new->zone_rctlval_next = NULL;
34327c478bd9Sstevel@tonic-gate if (zonecfg_construct_rctlblk(valtabptr, rctlblk) != Z_OK)
34337c478bd9Sstevel@tonic-gate return (Z_INVAL);
34347c478bd9Sstevel@tonic-gate if (!zonecfg_valid_rctlblk(rctlblk))
34357c478bd9Sstevel@tonic-gate return (Z_INVAL);
34367c478bd9Sstevel@tonic-gate if (last == NULL)
34377c478bd9Sstevel@tonic-gate tabptr->zone_rctl_valptr = new;
34387c478bd9Sstevel@tonic-gate else
34397c478bd9Sstevel@tonic-gate last->zone_rctlval_next = new;
34407c478bd9Sstevel@tonic-gate return (Z_OK);
34417c478bd9Sstevel@tonic-gate }
34427c478bd9Sstevel@tonic-gate
34437c478bd9Sstevel@tonic-gate int
zonecfg_remove_rctl_value(struct zone_rctltab * tabptr,struct zone_rctlvaltab * valtabptr)34447c478bd9Sstevel@tonic-gate zonecfg_remove_rctl_value(
34457c478bd9Sstevel@tonic-gate struct zone_rctltab *tabptr,
34467c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *valtabptr)
34477c478bd9Sstevel@tonic-gate {
34487c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *last, *this, *next;
34497c478bd9Sstevel@tonic-gate
34507c478bd9Sstevel@tonic-gate last = tabptr->zone_rctl_valptr;
34517c478bd9Sstevel@tonic-gate for (this = last; this != NULL; this = this->zone_rctlval_next) {
34527c478bd9Sstevel@tonic-gate if (strcmp(this->zone_rctlval_priv,
34537c478bd9Sstevel@tonic-gate valtabptr->zone_rctlval_priv) == 0 &&
34547c478bd9Sstevel@tonic-gate strcmp(this->zone_rctlval_limit,
34557c478bd9Sstevel@tonic-gate valtabptr->zone_rctlval_limit) == 0 &&
34567c478bd9Sstevel@tonic-gate strcmp(this->zone_rctlval_action,
34577c478bd9Sstevel@tonic-gate valtabptr->zone_rctlval_action) == 0) {
34587c478bd9Sstevel@tonic-gate next = this->zone_rctlval_next;
34597c478bd9Sstevel@tonic-gate if (this == tabptr->zone_rctl_valptr)
34607c478bd9Sstevel@tonic-gate tabptr->zone_rctl_valptr = next;
34617c478bd9Sstevel@tonic-gate else
34627c478bd9Sstevel@tonic-gate last->zone_rctlval_next = next;
34637c478bd9Sstevel@tonic-gate free(this);
34647c478bd9Sstevel@tonic-gate return (Z_OK);
34657c478bd9Sstevel@tonic-gate } else
34667c478bd9Sstevel@tonic-gate last = this;
34677c478bd9Sstevel@tonic-gate }
34687c478bd9Sstevel@tonic-gate return (Z_NO_PROPERTY_ID);
34697c478bd9Sstevel@tonic-gate }
34707c478bd9Sstevel@tonic-gate
3471ff17c8bfSgjelinek void
zonecfg_set_swinv(zone_dochandle_t handle)3472ff17c8bfSgjelinek zonecfg_set_swinv(zone_dochandle_t handle)
3473ff17c8bfSgjelinek {
3474ff17c8bfSgjelinek handle->zone_dh_sw_inv = B_TRUE;
3475ff17c8bfSgjelinek }
3476ff17c8bfSgjelinek
3477ff17c8bfSgjelinek /*
3478ff17c8bfSgjelinek * Add the pkg to the sw inventory on the handle.
3479ff17c8bfSgjelinek */
3480ff17c8bfSgjelinek int
zonecfg_add_pkg(zone_dochandle_t handle,char * name,char * version)3481ff17c8bfSgjelinek zonecfg_add_pkg(zone_dochandle_t handle, char *name, char *version)
3482ff17c8bfSgjelinek {
3483ff17c8bfSgjelinek xmlNodePtr newnode;
3484ff17c8bfSgjelinek xmlNodePtr cur;
3485ff17c8bfSgjelinek int err;
3486ff17c8bfSgjelinek
3487ff17c8bfSgjelinek if ((err = operation_prep(handle)) != Z_OK)
3488ff17c8bfSgjelinek return (err);
3489ff17c8bfSgjelinek
3490ff17c8bfSgjelinek cur = handle->zone_dh_cur;
3491ff17c8bfSgjelinek newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_PACKAGE, NULL);
3492ff17c8bfSgjelinek if ((err = newprop(newnode, DTD_ATTR_NAME, name)) != Z_OK)
3493ff17c8bfSgjelinek return (err);
3494ff17c8bfSgjelinek if ((err = newprop(newnode, DTD_ATTR_VERSION, version)) != Z_OK)
3495ff17c8bfSgjelinek return (err);
3496ff17c8bfSgjelinek return (Z_OK);
3497ff17c8bfSgjelinek }
3498ff17c8bfSgjelinek
34997c478bd9Sstevel@tonic-gate char *
zonecfg_strerror(int errnum)35007c478bd9Sstevel@tonic-gate zonecfg_strerror(int errnum)
35017c478bd9Sstevel@tonic-gate {
35027c478bd9Sstevel@tonic-gate switch (errnum) {
35037c478bd9Sstevel@tonic-gate case Z_OK:
35047c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "OK"));
35057c478bd9Sstevel@tonic-gate case Z_EMPTY_DOCUMENT:
35067c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Empty document"));
35077c478bd9Sstevel@tonic-gate case Z_WRONG_DOC_TYPE:
35087c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Wrong document type"));
35097c478bd9Sstevel@tonic-gate case Z_BAD_PROPERTY:
35107c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Bad document property"));
35117c478bd9Sstevel@tonic-gate case Z_TEMP_FILE:
35127c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN,
35137c478bd9Sstevel@tonic-gate "Problem creating temporary file"));
35147c478bd9Sstevel@tonic-gate case Z_SAVING_FILE:
35157c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Problem saving file"));
35167c478bd9Sstevel@tonic-gate case Z_NO_ENTRY:
35177c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "No such entry"));
35187c478bd9Sstevel@tonic-gate case Z_BOGUS_ZONE_NAME:
35197c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Bogus zone name"));
35207c478bd9Sstevel@tonic-gate case Z_REQD_RESOURCE_MISSING:
35217c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Required resource missing"));
35227c478bd9Sstevel@tonic-gate case Z_REQD_PROPERTY_MISSING:
35237c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Required property missing"));
35247c478bd9Sstevel@tonic-gate case Z_BAD_HANDLE:
35257c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Bad handle"));
35267c478bd9Sstevel@tonic-gate case Z_NOMEM:
35277c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Out of memory"));
35287c478bd9Sstevel@tonic-gate case Z_INVAL:
35297c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Invalid argument"));
35307c478bd9Sstevel@tonic-gate case Z_ACCES:
35317c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Permission denied"));
35327c478bd9Sstevel@tonic-gate case Z_TOO_BIG:
35337c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Argument list too long"));
35347c478bd9Sstevel@tonic-gate case Z_MISC_FS:
35357c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN,
35367c478bd9Sstevel@tonic-gate "Miscellaneous file system error"));
35377c478bd9Sstevel@tonic-gate case Z_NO_ZONE:
35387c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "No such zone configured"));
35397c478bd9Sstevel@tonic-gate case Z_NO_RESOURCE_TYPE:
35407c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "No such resource type"));
35417c478bd9Sstevel@tonic-gate case Z_NO_RESOURCE_ID:
35427c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "No such resource with that id"));
35437c478bd9Sstevel@tonic-gate case Z_NO_PROPERTY_TYPE:
35447c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "No such property type"));
35457c478bd9Sstevel@tonic-gate case Z_NO_PROPERTY_ID:
35467c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "No such property with that id"));
3547087719fdSdp case Z_BAD_ZONE_STATE:
35487c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN,
3549087719fdSdp "Zone state is invalid for the requested operation"));
35507c478bd9Sstevel@tonic-gate case Z_INVALID_DOCUMENT:
35517c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Invalid document"));
3552087719fdSdp case Z_NAME_IN_USE:
3553087719fdSdp return (dgettext(TEXT_DOMAIN, "Zone name already in use"));
35547c478bd9Sstevel@tonic-gate case Z_NO_SUCH_ID:
35557c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "No such zone ID"));
35567c478bd9Sstevel@tonic-gate case Z_UPDATING_INDEX:
35577c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Problem updating index file"));
35587c478bd9Sstevel@tonic-gate case Z_LOCKING_FILE:
35597c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Locking index file"));
35607c478bd9Sstevel@tonic-gate case Z_UNLOCKING_FILE:
35617c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Unlocking index file"));
35627c478bd9Sstevel@tonic-gate case Z_INSUFFICIENT_SPEC:
35637c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Insufficient specification"));
35647c478bd9Sstevel@tonic-gate case Z_RESOLVED_PATH:
35657c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Resolved path mismatch"));
35667c478bd9Sstevel@tonic-gate case Z_IPV6_ADDR_PREFIX_LEN:
35677c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN,
35687c478bd9Sstevel@tonic-gate "IPv6 address missing required prefix length"));
35697c478bd9Sstevel@tonic-gate case Z_BOGUS_ADDRESS:
35707c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN,
35717c478bd9Sstevel@tonic-gate "Neither an IPv4 nor an IPv6 address nor a host name"));
3572ffbafc53Scomay case Z_PRIV_PROHIBITED:
3573ffbafc53Scomay return (dgettext(TEXT_DOMAIN,
3574ffbafc53Scomay "Specified privilege is prohibited"));
3575ffbafc53Scomay case Z_PRIV_REQUIRED:
3576ffbafc53Scomay return (dgettext(TEXT_DOMAIN,
3577ffbafc53Scomay "Required privilege is missing"));
3578ffbafc53Scomay case Z_PRIV_UNKNOWN:
3579ffbafc53Scomay return (dgettext(TEXT_DOMAIN,
3580ffbafc53Scomay "Specified privilege is unknown"));
35819acbbeafSnn35248 case Z_BRAND_ERROR:
35829acbbeafSnn35248 return (dgettext(TEXT_DOMAIN,
35839acbbeafSnn35248 "Brand-specific error"));
35840209230bSgjelinek case Z_INCOMPATIBLE:
35850209230bSgjelinek return (dgettext(TEXT_DOMAIN, "Incompatible settings"));
35860209230bSgjelinek case Z_ALIAS_DISALLOW:
35870209230bSgjelinek return (dgettext(TEXT_DOMAIN,
35880209230bSgjelinek "An incompatible rctl already exists for this property"));
35890209230bSgjelinek case Z_CLEAR_DISALLOW:
35900209230bSgjelinek return (dgettext(TEXT_DOMAIN,
35910209230bSgjelinek "Clearing this property is not allowed"));
35920209230bSgjelinek case Z_POOL:
35930209230bSgjelinek return (dgettext(TEXT_DOMAIN, "libpool(3LIB) error"));
35940209230bSgjelinek case Z_POOLS_NOT_ACTIVE:
35950209230bSgjelinek return (dgettext(TEXT_DOMAIN, "Pools facility not active; "
35960209230bSgjelinek "zone will not be bound to pool"));
35970209230bSgjelinek case Z_POOL_ENABLE:
35980209230bSgjelinek return (dgettext(TEXT_DOMAIN,
35990209230bSgjelinek "Could not enable pools facility"));
36000209230bSgjelinek case Z_NO_POOL:
36010209230bSgjelinek return (dgettext(TEXT_DOMAIN,
36020209230bSgjelinek "Pool not found; using default pool"));
36030209230bSgjelinek case Z_POOL_CREATE:
36040209230bSgjelinek return (dgettext(TEXT_DOMAIN,
36050209230bSgjelinek "Could not create a temporary pool"));
36060209230bSgjelinek case Z_POOL_BIND:
36070209230bSgjelinek return (dgettext(TEXT_DOMAIN, "Could not bind zone to pool"));
36080fbb751dSJohn Levon case Z_INVALID_PROPERTY:
36090fbb751dSJohn Levon return (dgettext(TEXT_DOMAIN, "Specified property is invalid"));
36102ad45a84Sjv227347 case Z_SYSTEM:
36112ad45a84Sjv227347 return (strerror(errno));
36127c478bd9Sstevel@tonic-gate default:
36137c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Unknown error"));
36147c478bd9Sstevel@tonic-gate }
36157c478bd9Sstevel@tonic-gate }
36167c478bd9Sstevel@tonic-gate
36177c478bd9Sstevel@tonic-gate /*
36187c478bd9Sstevel@tonic-gate * Note that the zonecfg_setXent() and zonecfg_endXent() calls are all the
36197c478bd9Sstevel@tonic-gate * same, as they just turn around and call zonecfg_setent() / zonecfg_endent().
36207c478bd9Sstevel@tonic-gate */
36217c478bd9Sstevel@tonic-gate
36227c478bd9Sstevel@tonic-gate static int
zonecfg_setent(zone_dochandle_t handle)36237c478bd9Sstevel@tonic-gate zonecfg_setent(zone_dochandle_t handle)
36247c478bd9Sstevel@tonic-gate {
36257c478bd9Sstevel@tonic-gate xmlNodePtr cur;
36267c478bd9Sstevel@tonic-gate int err;
36277c478bd9Sstevel@tonic-gate
36287c478bd9Sstevel@tonic-gate if (handle == NULL)
36297c478bd9Sstevel@tonic-gate return (Z_INVAL);
36307c478bd9Sstevel@tonic-gate
36317c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) {
36327c478bd9Sstevel@tonic-gate handle->zone_dh_cur = NULL;
36337c478bd9Sstevel@tonic-gate return (err);
36347c478bd9Sstevel@tonic-gate }
36357c478bd9Sstevel@tonic-gate cur = handle->zone_dh_cur;
36367c478bd9Sstevel@tonic-gate cur = cur->xmlChildrenNode;
36377c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur;
36387c478bd9Sstevel@tonic-gate return (Z_OK);
36397c478bd9Sstevel@tonic-gate }
36407c478bd9Sstevel@tonic-gate
36417c478bd9Sstevel@tonic-gate static int
zonecfg_endent(zone_dochandle_t handle)36427c478bd9Sstevel@tonic-gate zonecfg_endent(zone_dochandle_t handle)
36437c478bd9Sstevel@tonic-gate {
36447c478bd9Sstevel@tonic-gate if (handle == NULL)
36457c478bd9Sstevel@tonic-gate return (Z_INVAL);
36467c478bd9Sstevel@tonic-gate
36477c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top;
36487c478bd9Sstevel@tonic-gate return (Z_OK);
36497c478bd9Sstevel@tonic-gate }
36507c478bd9Sstevel@tonic-gate
36510209230bSgjelinek /*
36520209230bSgjelinek * Do the work required to manipulate a process through libproc.
36530209230bSgjelinek * If grab_process() returns no errors (0), then release_process()
36540209230bSgjelinek * must eventually be called.
36550209230bSgjelinek *
36560209230bSgjelinek * Return values:
36570209230bSgjelinek * 0 Successful creation of agent thread
36580209230bSgjelinek * 1 Error grabbing
36590209230bSgjelinek * 2 Error creating agent
36600209230bSgjelinek */
36610209230bSgjelinek static int
grab_process(pr_info_handle_t * p)36620209230bSgjelinek grab_process(pr_info_handle_t *p)
36630209230bSgjelinek {
36640209230bSgjelinek int ret;
36650209230bSgjelinek
36660209230bSgjelinek if ((p->pr = Pgrab(p->pid, 0, &ret)) != NULL) {
36670209230bSgjelinek
36680209230bSgjelinek if (Psetflags(p->pr, PR_RLC) != 0) {
36690209230bSgjelinek Prelease(p->pr, 0);
36700209230bSgjelinek return (1);
36710209230bSgjelinek }
36720209230bSgjelinek if (Pcreate_agent(p->pr) == 0) {
36730209230bSgjelinek return (0);
36740209230bSgjelinek
36750209230bSgjelinek } else {
36760209230bSgjelinek Prelease(p->pr, 0);
36770209230bSgjelinek return (2);
36780209230bSgjelinek }
36790209230bSgjelinek } else {
36800209230bSgjelinek return (1);
36810209230bSgjelinek }
36820209230bSgjelinek }
36830209230bSgjelinek
36840209230bSgjelinek /*
36850209230bSgjelinek * Release the specified process. This destroys the agent
36860209230bSgjelinek * and releases the process. If the process is NULL, nothing
36870209230bSgjelinek * is done. This function should only be called if grab_process()
36880209230bSgjelinek * has previously been called and returned success.
36890209230bSgjelinek *
36900209230bSgjelinek * This function is Pgrab-safe.
36910209230bSgjelinek */
36920209230bSgjelinek static void
release_process(struct ps_prochandle * Pr)36930209230bSgjelinek release_process(struct ps_prochandle *Pr)
36940209230bSgjelinek {
36950209230bSgjelinek if (Pr == NULL)
36960209230bSgjelinek return;
36970209230bSgjelinek
36980209230bSgjelinek Pdestroy_agent(Pr);
36990209230bSgjelinek Prelease(Pr, 0);
37000209230bSgjelinek }
37010209230bSgjelinek
37020209230bSgjelinek static boolean_t
grab_zone_proc(char * zonename,pr_info_handle_t * p)37030209230bSgjelinek grab_zone_proc(char *zonename, pr_info_handle_t *p)
37040209230bSgjelinek {
37050209230bSgjelinek DIR *dirp;
37060209230bSgjelinek struct dirent *dentp;
37070209230bSgjelinek zoneid_t zoneid;
37080209230bSgjelinek int pid_self;
37090209230bSgjelinek psinfo_t psinfo;
37100209230bSgjelinek
37110209230bSgjelinek if (zone_get_id(zonename, &zoneid) != 0)
37120209230bSgjelinek return (B_FALSE);
37130209230bSgjelinek
37140209230bSgjelinek pid_self = getpid();
37150209230bSgjelinek
37160209230bSgjelinek if ((dirp = opendir("/proc")) == NULL)
37170209230bSgjelinek return (B_FALSE);
37180209230bSgjelinek
37190209230bSgjelinek while (dentp = readdir(dirp)) {
37200209230bSgjelinek p->pid = atoi(dentp->d_name);
37210209230bSgjelinek
37220209230bSgjelinek /* Skip self */
37230209230bSgjelinek if (p->pid == pid_self)
37240209230bSgjelinek continue;
37250209230bSgjelinek
37260209230bSgjelinek if (proc_get_psinfo(p->pid, &psinfo) != 0)
37270209230bSgjelinek continue;
37280209230bSgjelinek
37290209230bSgjelinek if (psinfo.pr_zoneid != zoneid)
37300209230bSgjelinek continue;
37310209230bSgjelinek
37320209230bSgjelinek /* attempt to grab process */
37330209230bSgjelinek if (grab_process(p) != 0)
37340209230bSgjelinek continue;
37350209230bSgjelinek
37360209230bSgjelinek if (pr_getzoneid(p->pr) != zoneid) {
37370209230bSgjelinek release_process(p->pr);
37380209230bSgjelinek continue;
37390209230bSgjelinek }
37400209230bSgjelinek
37410209230bSgjelinek (void) closedir(dirp);
37420209230bSgjelinek return (B_TRUE);
37430209230bSgjelinek }
37440209230bSgjelinek
37450209230bSgjelinek (void) closedir(dirp);
37460209230bSgjelinek return (B_FALSE);
37470209230bSgjelinek }
37480209230bSgjelinek
37490209230bSgjelinek static boolean_t
get_priv_rctl(struct ps_prochandle * pr,char * name,rctlblk_t * rblk)37500209230bSgjelinek get_priv_rctl(struct ps_prochandle *pr, char *name, rctlblk_t *rblk)
37510209230bSgjelinek {
37520209230bSgjelinek if (pr_getrctl(pr, name, NULL, rblk, RCTL_FIRST))
37530209230bSgjelinek return (B_FALSE);
37540209230bSgjelinek
37550209230bSgjelinek if (rctlblk_get_privilege(rblk) == RCPRIV_PRIVILEGED)
37560209230bSgjelinek return (B_TRUE);
37570209230bSgjelinek
37580209230bSgjelinek while (pr_getrctl(pr, name, rblk, rblk, RCTL_NEXT) == 0) {
37590209230bSgjelinek if (rctlblk_get_privilege(rblk) == RCPRIV_PRIVILEGED)
37600209230bSgjelinek return (B_TRUE);
37610209230bSgjelinek }
37620209230bSgjelinek
37630209230bSgjelinek return (B_FALSE);
37640209230bSgjelinek }
37650209230bSgjelinek
37660209230bSgjelinek /*
37670209230bSgjelinek * Apply the current rctl settings to the specified, running zone.
37680209230bSgjelinek */
37690209230bSgjelinek int
zonecfg_apply_rctls(char * zone_name,zone_dochandle_t handle)37700209230bSgjelinek zonecfg_apply_rctls(char *zone_name, zone_dochandle_t handle)
37710209230bSgjelinek {
37720209230bSgjelinek int err;
37730209230bSgjelinek int res = Z_OK;
37740209230bSgjelinek rctlblk_t *rblk;
37750209230bSgjelinek pr_info_handle_t p;
37760209230bSgjelinek struct zone_rctltab rctl;
37770209230bSgjelinek
37780209230bSgjelinek if ((err = zonecfg_setrctlent(handle)) != Z_OK)
37790209230bSgjelinek return (err);
37800209230bSgjelinek
37810209230bSgjelinek if ((rblk = (rctlblk_t *)malloc(rctlblk_size())) == NULL) {
37820209230bSgjelinek (void) zonecfg_endrctlent(handle);
37830209230bSgjelinek return (Z_NOMEM);
37840209230bSgjelinek }
37850209230bSgjelinek
37860209230bSgjelinek if (!grab_zone_proc(zone_name, &p)) {
37870209230bSgjelinek (void) zonecfg_endrctlent(handle);
37880209230bSgjelinek free(rblk);
37890209230bSgjelinek return (Z_SYSTEM);
37900209230bSgjelinek }
37910209230bSgjelinek
37920209230bSgjelinek while (zonecfg_getrctlent(handle, &rctl) == Z_OK) {
37930209230bSgjelinek char *rname;
37940209230bSgjelinek struct zone_rctlvaltab *valptr;
37950209230bSgjelinek
37960209230bSgjelinek rname = rctl.zone_rctl_name;
37970209230bSgjelinek
37980209230bSgjelinek /* first delete all current privileged settings for this rctl */
37990209230bSgjelinek while (get_priv_rctl(p.pr, rname, rblk)) {
38000209230bSgjelinek if (pr_setrctl(p.pr, rname, NULL, rblk, RCTL_DELETE) !=
38010209230bSgjelinek 0) {
38020209230bSgjelinek res = Z_SYSTEM;
38030209230bSgjelinek goto done;
38040209230bSgjelinek }
38050209230bSgjelinek }
38060209230bSgjelinek
38070209230bSgjelinek /* now set each new value for the rctl */
38080209230bSgjelinek for (valptr = rctl.zone_rctl_valptr; valptr != NULL;
38090209230bSgjelinek valptr = valptr->zone_rctlval_next) {
38100209230bSgjelinek if ((err = zonecfg_construct_rctlblk(valptr, rblk))
38110209230bSgjelinek != Z_OK) {
38120209230bSgjelinek res = errno = err;
38130209230bSgjelinek goto done;
38140209230bSgjelinek }
38150209230bSgjelinek
38160209230bSgjelinek if (pr_setrctl(p.pr, rname, NULL, rblk, RCTL_INSERT)) {
38170209230bSgjelinek res = Z_SYSTEM;
38180209230bSgjelinek goto done;
38190209230bSgjelinek }
38200209230bSgjelinek }
38210209230bSgjelinek }
38220209230bSgjelinek
38230209230bSgjelinek done:
38240209230bSgjelinek release_process(p.pr);
38250209230bSgjelinek free(rblk);
38260209230bSgjelinek (void) zonecfg_endrctlent(handle);
38270209230bSgjelinek
38280209230bSgjelinek return (res);
38290209230bSgjelinek }
38300209230bSgjelinek
38310209230bSgjelinek static const xmlChar *
nm_to_dtd(char * nm)38320209230bSgjelinek nm_to_dtd(char *nm)
38330209230bSgjelinek {
38340209230bSgjelinek if (strcmp(nm, "device") == 0)
38350209230bSgjelinek return (DTD_ELEM_DEVICE);
38360209230bSgjelinek if (strcmp(nm, "fs") == 0)
38370209230bSgjelinek return (DTD_ELEM_FS);
38380209230bSgjelinek if (strcmp(nm, "net") == 0)
38390209230bSgjelinek return (DTD_ELEM_NET);
38400209230bSgjelinek if (strcmp(nm, "attr") == 0)
38410209230bSgjelinek return (DTD_ELEM_ATTR);
38420209230bSgjelinek if (strcmp(nm, "rctl") == 0)
38430209230bSgjelinek return (DTD_ELEM_RCTL);
38440209230bSgjelinek if (strcmp(nm, "dataset") == 0)
38450209230bSgjelinek return (DTD_ELEM_DATASET);
3846cb8a054bSGlenn Faden if (strcmp(nm, "admin") == 0)
3847cb8a054bSGlenn Faden return (DTD_ELEM_ADMIN);
38480209230bSgjelinek
38490209230bSgjelinek return (NULL);
38500209230bSgjelinek }
38510209230bSgjelinek
38520209230bSgjelinek int
zonecfg_num_resources(zone_dochandle_t handle,char * rsrc)38530209230bSgjelinek zonecfg_num_resources(zone_dochandle_t handle, char *rsrc)
38540209230bSgjelinek {
38550209230bSgjelinek int num = 0;
38560209230bSgjelinek const xmlChar *dtd;
38570209230bSgjelinek xmlNodePtr cur;
38580209230bSgjelinek
38590209230bSgjelinek if ((dtd = nm_to_dtd(rsrc)) == NULL)
38600209230bSgjelinek return (num);
38610209230bSgjelinek
38620209230bSgjelinek if (zonecfg_setent(handle) != Z_OK)
38630209230bSgjelinek return (num);
38640209230bSgjelinek
38650209230bSgjelinek for (cur = handle->zone_dh_cur; cur != NULL; cur = cur->next)
38660209230bSgjelinek if (xmlStrcmp(cur->name, dtd) == 0)
38670209230bSgjelinek num++;
38680209230bSgjelinek
38690209230bSgjelinek (void) zonecfg_endent(handle);
38700209230bSgjelinek
38710209230bSgjelinek return (num);
38720209230bSgjelinek }
38730209230bSgjelinek
38740209230bSgjelinek int
zonecfg_del_all_resources(zone_dochandle_t handle,char * rsrc)38750209230bSgjelinek zonecfg_del_all_resources(zone_dochandle_t handle, char *rsrc)
38760209230bSgjelinek {
38770209230bSgjelinek int err;
38780209230bSgjelinek const xmlChar *dtd;
38790209230bSgjelinek xmlNodePtr cur;
38800209230bSgjelinek
38810209230bSgjelinek if ((dtd = nm_to_dtd(rsrc)) == NULL)
38820209230bSgjelinek return (Z_NO_RESOURCE_TYPE);
38830209230bSgjelinek
38840209230bSgjelinek if ((err = zonecfg_setent(handle)) != Z_OK)
38850209230bSgjelinek return (err);
38860209230bSgjelinek
38870209230bSgjelinek cur = handle->zone_dh_cur;
38880209230bSgjelinek while (cur != NULL) {
38890209230bSgjelinek xmlNodePtr tmp;
38900209230bSgjelinek
38910209230bSgjelinek if (xmlStrcmp(cur->name, dtd)) {
38920209230bSgjelinek cur = cur->next;
38930209230bSgjelinek continue;
38940209230bSgjelinek }
38950209230bSgjelinek
38960209230bSgjelinek tmp = cur->next;
38970209230bSgjelinek xmlUnlinkNode(cur);
38980209230bSgjelinek xmlFreeNode(cur);
38990209230bSgjelinek cur = tmp;
39000209230bSgjelinek }
39010209230bSgjelinek
39020209230bSgjelinek (void) zonecfg_endent(handle);
39030209230bSgjelinek return (Z_OK);
39040209230bSgjelinek }
39050209230bSgjelinek
39060209230bSgjelinek static boolean_t
valid_uint(char * s,uint64_t * n)39070209230bSgjelinek valid_uint(char *s, uint64_t *n)
39080209230bSgjelinek {
39090209230bSgjelinek char *endp;
39100209230bSgjelinek
39110209230bSgjelinek /* strtoull accepts '-'?! so we want to flag that as an error */
39120209230bSgjelinek if (strchr(s, '-') != NULL)
39130209230bSgjelinek return (B_FALSE);
39140209230bSgjelinek
39150209230bSgjelinek errno = 0;
39160209230bSgjelinek *n = strtoull(s, &endp, 10);
39170209230bSgjelinek
39180209230bSgjelinek if (errno != 0 || *endp != '\0')
39190209230bSgjelinek return (B_FALSE);
39200209230bSgjelinek return (B_TRUE);
39210209230bSgjelinek }
39220209230bSgjelinek
39230209230bSgjelinek /*
39240209230bSgjelinek * Convert a string representing a number (possibly a fraction) into an integer.
39250209230bSgjelinek * The string can have a modifier (K, M, G or T). The modifiers are treated
39260209230bSgjelinek * as powers of two (not 10).
39270209230bSgjelinek */
39280209230bSgjelinek int
zonecfg_str_to_bytes(char * str,uint64_t * bytes)39290209230bSgjelinek zonecfg_str_to_bytes(char *str, uint64_t *bytes)
39300209230bSgjelinek {
39310209230bSgjelinek long double val;
39320209230bSgjelinek char *unitp;
39330209230bSgjelinek uint64_t scale;
39340209230bSgjelinek
39350209230bSgjelinek if ((val = strtold(str, &unitp)) < 0)
39360209230bSgjelinek return (-1);
39370209230bSgjelinek
39380209230bSgjelinek /* remove any leading white space from units string */
39390209230bSgjelinek while (isspace(*unitp) != 0)
39400209230bSgjelinek ++unitp;
39410209230bSgjelinek
39420209230bSgjelinek /* if no units explicitly set, error */
39430209230bSgjelinek if (unitp == NULL || *unitp == '\0') {
39440209230bSgjelinek scale = 1;
39450209230bSgjelinek } else {
39460209230bSgjelinek int i;
39470209230bSgjelinek char *units[] = {"K", "M", "G", "T", NULL};
39480209230bSgjelinek
39490209230bSgjelinek scale = 1024;
39500209230bSgjelinek
39510209230bSgjelinek /* update scale based on units */
39520209230bSgjelinek for (i = 0; units[i] != NULL; i++) {
39530209230bSgjelinek if (strcasecmp(unitp, units[i]) == 0)
39540209230bSgjelinek break;
39550209230bSgjelinek scale <<= 10;
39560209230bSgjelinek }
39570209230bSgjelinek
39580209230bSgjelinek if (units[i] == NULL)
39590209230bSgjelinek return (-1);
39600209230bSgjelinek }
39610209230bSgjelinek
39620209230bSgjelinek *bytes = (uint64_t)(val * scale);
39630209230bSgjelinek return (0);
39640209230bSgjelinek }
39650209230bSgjelinek
39660209230bSgjelinek boolean_t
zonecfg_valid_ncpus(char * lowstr,char * highstr)39670209230bSgjelinek zonecfg_valid_ncpus(char *lowstr, char *highstr)
39680209230bSgjelinek {
39690209230bSgjelinek uint64_t low, high;
39700209230bSgjelinek
39710209230bSgjelinek if (!valid_uint(lowstr, &low) || !valid_uint(highstr, &high) ||
39720209230bSgjelinek low < 1 || low > high)
39730209230bSgjelinek return (B_FALSE);
39740209230bSgjelinek
39750209230bSgjelinek return (B_TRUE);
39760209230bSgjelinek }
39770209230bSgjelinek
39780209230bSgjelinek boolean_t
zonecfg_valid_importance(char * impstr)39790209230bSgjelinek zonecfg_valid_importance(char *impstr)
39800209230bSgjelinek {
39810209230bSgjelinek uint64_t num;
39820209230bSgjelinek
39830209230bSgjelinek if (!valid_uint(impstr, &num))
39840209230bSgjelinek return (B_FALSE);
39850209230bSgjelinek
39860209230bSgjelinek return (B_TRUE);
39870209230bSgjelinek }
39880209230bSgjelinek
39890209230bSgjelinek boolean_t
zonecfg_valid_alias_limit(char * name,char * limitstr,uint64_t * limit)39900209230bSgjelinek zonecfg_valid_alias_limit(char *name, char *limitstr, uint64_t *limit)
39910209230bSgjelinek {
39920209230bSgjelinek int i;
39930209230bSgjelinek
39940209230bSgjelinek for (i = 0; aliases[i].shortname != NULL; i++)
39950209230bSgjelinek if (strcmp(name, aliases[i].shortname) == 0)
39960209230bSgjelinek break;
39970209230bSgjelinek
39980209230bSgjelinek if (aliases[i].shortname == NULL)
39990209230bSgjelinek return (B_FALSE);
40000209230bSgjelinek
40010209230bSgjelinek if (!valid_uint(limitstr, limit) || *limit < aliases[i].low_limit)
40020209230bSgjelinek return (B_FALSE);
40030209230bSgjelinek
40040209230bSgjelinek return (B_TRUE);
40050209230bSgjelinek }
40060209230bSgjelinek
40070209230bSgjelinek boolean_t
zonecfg_valid_memlimit(char * memstr,uint64_t * mem_val)40080209230bSgjelinek zonecfg_valid_memlimit(char *memstr, uint64_t *mem_val)
40090209230bSgjelinek {
40100209230bSgjelinek if (zonecfg_str_to_bytes(memstr, mem_val) != 0)
40110209230bSgjelinek return (B_FALSE);
40120209230bSgjelinek
40130209230bSgjelinek return (B_TRUE);
40140209230bSgjelinek }
40150209230bSgjelinek
40160209230bSgjelinek static int
zerr_pool(char * pool_err,int err_size,int res)40170209230bSgjelinek zerr_pool(char *pool_err, int err_size, int res)
40180209230bSgjelinek {
40190209230bSgjelinek (void) strlcpy(pool_err, pool_strerror(pool_error()), err_size);
40200209230bSgjelinek return (res);
40210209230bSgjelinek }
40220209230bSgjelinek
40230209230bSgjelinek static int
create_tmp_pset(char * pool_err,int err_size,pool_conf_t * pconf,pool_t * pool,char * name,int min,int max)40240209230bSgjelinek create_tmp_pset(char *pool_err, int err_size, pool_conf_t *pconf, pool_t *pool,
40250209230bSgjelinek char *name, int min, int max)
40260209230bSgjelinek {
40270209230bSgjelinek pool_resource_t *res;
40280209230bSgjelinek pool_elem_t *elem;
40290209230bSgjelinek pool_value_t *val;
40300209230bSgjelinek
40310209230bSgjelinek if ((res = pool_resource_create(pconf, "pset", name)) == NULL)
40320209230bSgjelinek return (zerr_pool(pool_err, err_size, Z_POOL));
40330209230bSgjelinek
40340209230bSgjelinek if (pool_associate(pconf, pool, res) != PO_SUCCESS)
40350209230bSgjelinek return (zerr_pool(pool_err, err_size, Z_POOL));
40360209230bSgjelinek
40370209230bSgjelinek if ((elem = pool_resource_to_elem(pconf, res)) == NULL)
40380209230bSgjelinek return (zerr_pool(pool_err, err_size, Z_POOL));
40390209230bSgjelinek
40400209230bSgjelinek if ((val = pool_value_alloc()) == NULL)
40410209230bSgjelinek return (zerr_pool(pool_err, err_size, Z_POOL));
40420209230bSgjelinek
40430209230bSgjelinek /* set the maximum number of cpus for the pset */
40440209230bSgjelinek pool_value_set_uint64(val, (uint64_t)max);
40450209230bSgjelinek
40460209230bSgjelinek if (pool_put_property(pconf, elem, "pset.max", val) != PO_SUCCESS) {
40470209230bSgjelinek pool_value_free(val);
40480209230bSgjelinek return (zerr_pool(pool_err, err_size, Z_POOL));
40490209230bSgjelinek }
40500209230bSgjelinek
40510209230bSgjelinek /* set the minimum number of cpus for the pset */
40520209230bSgjelinek pool_value_set_uint64(val, (uint64_t)min);
40530209230bSgjelinek
40540209230bSgjelinek if (pool_put_property(pconf, elem, "pset.min", val) != PO_SUCCESS) {
40550209230bSgjelinek pool_value_free(val);
40560209230bSgjelinek return (zerr_pool(pool_err, err_size, Z_POOL));
40570209230bSgjelinek }
40580209230bSgjelinek
40590209230bSgjelinek pool_value_free(val);
40600209230bSgjelinek
40610209230bSgjelinek return (Z_OK);
40620209230bSgjelinek }
40630209230bSgjelinek
40640209230bSgjelinek static int
create_tmp_pool(char * pool_err,int err_size,pool_conf_t * pconf,char * name,struct zone_psettab * pset_tab)40650209230bSgjelinek create_tmp_pool(char *pool_err, int err_size, pool_conf_t *pconf, char *name,
40660209230bSgjelinek struct zone_psettab *pset_tab)
40670209230bSgjelinek {
40680209230bSgjelinek pool_t *pool;
40690209230bSgjelinek int res = Z_OK;
40700209230bSgjelinek
40710209230bSgjelinek /* create a temporary pool configuration */
40720209230bSgjelinek if (pool_conf_open(pconf, NULL, PO_TEMP) != PO_SUCCESS) {
40730209230bSgjelinek res = zerr_pool(pool_err, err_size, Z_POOL);
40740209230bSgjelinek return (res);
40750209230bSgjelinek }
40760209230bSgjelinek
40770209230bSgjelinek if ((pool = pool_create(pconf, name)) == NULL) {
40780209230bSgjelinek res = zerr_pool(pool_err, err_size, Z_POOL_CREATE);
40790209230bSgjelinek goto done;
40800209230bSgjelinek }
40810209230bSgjelinek
40820209230bSgjelinek /* set pool importance */
40830209230bSgjelinek if (pset_tab->zone_importance[0] != '\0') {
40840209230bSgjelinek pool_elem_t *elem;
40850209230bSgjelinek pool_value_t *val;
40860209230bSgjelinek
40870209230bSgjelinek if ((elem = pool_to_elem(pconf, pool)) == NULL) {
40880209230bSgjelinek res = zerr_pool(pool_err, err_size, Z_POOL);
40890209230bSgjelinek goto done;
40900209230bSgjelinek }
40910209230bSgjelinek
40920209230bSgjelinek if ((val = pool_value_alloc()) == NULL) {
40930209230bSgjelinek res = zerr_pool(pool_err, err_size, Z_POOL);
40940209230bSgjelinek goto done;
40950209230bSgjelinek }
40960209230bSgjelinek
40970209230bSgjelinek pool_value_set_int64(val,
40980209230bSgjelinek (int64_t)atoi(pset_tab->zone_importance));
40990209230bSgjelinek
41000209230bSgjelinek if (pool_put_property(pconf, elem, "pool.importance", val)
41010209230bSgjelinek != PO_SUCCESS) {
41020209230bSgjelinek res = zerr_pool(pool_err, err_size, Z_POOL);
41030209230bSgjelinek pool_value_free(val);
41040209230bSgjelinek goto done;
41050209230bSgjelinek }
41060209230bSgjelinek
41070209230bSgjelinek pool_value_free(val);
41080209230bSgjelinek }
41090209230bSgjelinek
41100209230bSgjelinek if ((res = create_tmp_pset(pool_err, err_size, pconf, pool, name,
41110209230bSgjelinek atoi(pset_tab->zone_ncpu_min),
41120209230bSgjelinek atoi(pset_tab->zone_ncpu_max))) != Z_OK)
41130209230bSgjelinek goto done;
41140209230bSgjelinek
41150209230bSgjelinek /* validation */
41160209230bSgjelinek if (pool_conf_status(pconf) == POF_INVALID) {
41170209230bSgjelinek res = zerr_pool(pool_err, err_size, Z_POOL);
41180209230bSgjelinek goto done;
41190209230bSgjelinek }
41200209230bSgjelinek
41210209230bSgjelinek /*
41220209230bSgjelinek * This validation is the one we expect to fail if the user specified
41230209230bSgjelinek * an invalid configuration (too many cpus) for this system.
41240209230bSgjelinek */
41250209230bSgjelinek if (pool_conf_validate(pconf, POV_RUNTIME) != PO_SUCCESS) {
41260209230bSgjelinek res = zerr_pool(pool_err, err_size, Z_POOL_CREATE);
41270209230bSgjelinek goto done;
41280209230bSgjelinek }
41290209230bSgjelinek
41300209230bSgjelinek /*
41310209230bSgjelinek * Commit the dynamic configuration but not the pool configuration
41320209230bSgjelinek * file.
41330209230bSgjelinek */
41340209230bSgjelinek if (pool_conf_commit(pconf, 1) != PO_SUCCESS)
41350209230bSgjelinek res = zerr_pool(pool_err, err_size, Z_POOL);
41360209230bSgjelinek
41370209230bSgjelinek done:
41380209230bSgjelinek (void) pool_conf_close(pconf);
41390209230bSgjelinek return (res);
41400209230bSgjelinek }
41410209230bSgjelinek
41420209230bSgjelinek static int
get_running_tmp_pset(pool_conf_t * pconf,pool_t * pool,pool_resource_t * pset,struct zone_psettab * pset_tab)41430209230bSgjelinek get_running_tmp_pset(pool_conf_t *pconf, pool_t *pool, pool_resource_t *pset,
41440209230bSgjelinek struct zone_psettab *pset_tab)
41450209230bSgjelinek {
41460209230bSgjelinek int nfound = 0;
41470209230bSgjelinek pool_elem_t *pe;
41480209230bSgjelinek pool_value_t *pv = pool_value_alloc();
41490209230bSgjelinek uint64_t val_uint;
41500209230bSgjelinek
41510209230bSgjelinek if (pool != NULL) {
41520209230bSgjelinek pe = pool_to_elem(pconf, pool);
41530209230bSgjelinek if (pool_get_property(pconf, pe, "pool.importance", pv)
41540209230bSgjelinek != POC_INVAL) {
41550209230bSgjelinek int64_t val_int;
41560209230bSgjelinek
41570209230bSgjelinek (void) pool_value_get_int64(pv, &val_int);
41580209230bSgjelinek (void) snprintf(pset_tab->zone_importance,
41590209230bSgjelinek sizeof (pset_tab->zone_importance), "%d", val_int);
41600209230bSgjelinek nfound++;
41610209230bSgjelinek }
41620209230bSgjelinek }
41630209230bSgjelinek
41640209230bSgjelinek if (pset != NULL) {
41650209230bSgjelinek pe = pool_resource_to_elem(pconf, pset);
41660209230bSgjelinek if (pool_get_property(pconf, pe, "pset.min", pv) != POC_INVAL) {
41670209230bSgjelinek (void) pool_value_get_uint64(pv, &val_uint);
41680209230bSgjelinek (void) snprintf(pset_tab->zone_ncpu_min,
41690209230bSgjelinek sizeof (pset_tab->zone_ncpu_min), "%u", val_uint);
41700209230bSgjelinek nfound++;
41710209230bSgjelinek }
41720209230bSgjelinek
41730209230bSgjelinek if (pool_get_property(pconf, pe, "pset.max", pv) != POC_INVAL) {
41740209230bSgjelinek (void) pool_value_get_uint64(pv, &val_uint);
41750209230bSgjelinek (void) snprintf(pset_tab->zone_ncpu_max,
41760209230bSgjelinek sizeof (pset_tab->zone_ncpu_max), "%u", val_uint);
41770209230bSgjelinek nfound++;
41780209230bSgjelinek }
41790209230bSgjelinek }
41800209230bSgjelinek
41810209230bSgjelinek pool_value_free(pv);
41820209230bSgjelinek
41830209230bSgjelinek if (nfound == 3)
41840209230bSgjelinek return (PO_SUCCESS);
41850209230bSgjelinek
41860209230bSgjelinek return (PO_FAIL);
41870209230bSgjelinek }
41880209230bSgjelinek
41890209230bSgjelinek /*
41900209230bSgjelinek * Determine if a tmp pool is configured and if so, if the configuration is
41910209230bSgjelinek * still valid or if it has been changed since the tmp pool was created.
41920209230bSgjelinek * If the tmp pool configuration is no longer valid, delete the tmp pool.
41930209230bSgjelinek *
41940209230bSgjelinek * Set *valid=B_TRUE if there is an existing, valid tmp pool configuration.
41950209230bSgjelinek */
41960209230bSgjelinek static int
verify_del_tmp_pool(pool_conf_t * pconf,char * tmp_name,char * pool_err,int err_size,struct zone_psettab * pset_tab,boolean_t * exists)41970209230bSgjelinek verify_del_tmp_pool(pool_conf_t *pconf, char *tmp_name, char *pool_err,
41980209230bSgjelinek int err_size, struct zone_psettab *pset_tab, boolean_t *exists)
41990209230bSgjelinek {
42000209230bSgjelinek int res = Z_OK;
42010209230bSgjelinek pool_t *pool;
42020209230bSgjelinek pool_resource_t *pset;
42030209230bSgjelinek struct zone_psettab pset_current;
42040209230bSgjelinek
42050209230bSgjelinek *exists = B_FALSE;
42060209230bSgjelinek
42070209230bSgjelinek if (pool_conf_open(pconf, pool_dynamic_location(), PO_RDWR)
42080209230bSgjelinek != PO_SUCCESS) {
42090209230bSgjelinek res = zerr_pool(pool_err, err_size, Z_POOL);
42100209230bSgjelinek return (res);
42110209230bSgjelinek }
42120209230bSgjelinek
42130209230bSgjelinek pool = pool_get_pool(pconf, tmp_name);
42140209230bSgjelinek pset = pool_get_resource(pconf, "pset", tmp_name);
42150209230bSgjelinek
42160209230bSgjelinek if (pool == NULL && pset == NULL) {
42170209230bSgjelinek /* no tmp pool configured */
42180209230bSgjelinek goto done;
42190209230bSgjelinek }
42200209230bSgjelinek
42210209230bSgjelinek /*
42220209230bSgjelinek * If an existing tmp pool for this zone is configured with the proper
42230209230bSgjelinek * settings, then the tmp pool is valid.
42240209230bSgjelinek */
42250209230bSgjelinek if (get_running_tmp_pset(pconf, pool, pset, &pset_current)
42260209230bSgjelinek == PO_SUCCESS &&
42270209230bSgjelinek strcmp(pset_tab->zone_ncpu_min,
42280209230bSgjelinek pset_current.zone_ncpu_min) == 0 &&
42290209230bSgjelinek strcmp(pset_tab->zone_ncpu_max,
42300209230bSgjelinek pset_current.zone_ncpu_max) == 0 &&
42310209230bSgjelinek strcmp(pset_tab->zone_importance,
42320209230bSgjelinek pset_current.zone_importance) == 0) {
42330209230bSgjelinek *exists = B_TRUE;
42340209230bSgjelinek
42350209230bSgjelinek } else {
42360209230bSgjelinek /*
42370209230bSgjelinek * An out-of-date tmp pool configuration exists. Delete it
42380209230bSgjelinek * so that we can create the correct tmp pool config.
42390209230bSgjelinek */
42400209230bSgjelinek if (pset != NULL &&
42410209230bSgjelinek pool_resource_destroy(pconf, pset) != PO_SUCCESS) {
42420209230bSgjelinek res = zerr_pool(pool_err, err_size, Z_POOL);
42430209230bSgjelinek goto done;
42440209230bSgjelinek }
42450209230bSgjelinek
42460209230bSgjelinek if (pool != NULL &&
42470209230bSgjelinek pool_destroy(pconf, pool) != PO_SUCCESS) {
42480209230bSgjelinek res = zerr_pool(pool_err, err_size, Z_POOL);
42490209230bSgjelinek goto done;
42500209230bSgjelinek }
42510209230bSgjelinek
42520209230bSgjelinek /* commit dynamic config */
42530209230bSgjelinek if (pool_conf_commit(pconf, 0) != PO_SUCCESS)
42540209230bSgjelinek res = zerr_pool(pool_err, err_size, Z_POOL);
42550209230bSgjelinek }
42560209230bSgjelinek
42570209230bSgjelinek done:
42580209230bSgjelinek (void) pool_conf_close(pconf);
42590209230bSgjelinek
42600209230bSgjelinek return (res);
42610209230bSgjelinek }
42620209230bSgjelinek
42630209230bSgjelinek /*
42640209230bSgjelinek * Destroy any existing tmp pool.
42650209230bSgjelinek */
42660209230bSgjelinek int
zonecfg_destroy_tmp_pool(char * zone_name,char * pool_err,int err_size)42670209230bSgjelinek zonecfg_destroy_tmp_pool(char *zone_name, char *pool_err, int err_size)
42680209230bSgjelinek {
42690209230bSgjelinek int status;
42700209230bSgjelinek int res = Z_OK;
42710209230bSgjelinek pool_conf_t *pconf;
42720209230bSgjelinek pool_t *pool;
42730209230bSgjelinek pool_resource_t *pset;
42740209230bSgjelinek char tmp_name[MAX_TMP_POOL_NAME];
42750209230bSgjelinek
42760209230bSgjelinek /* if pools not enabled then nothing to do */
42770209230bSgjelinek if (pool_get_status(&status) != PO_SUCCESS || status != POOL_ENABLED)
42780209230bSgjelinek return (Z_OK);
42790209230bSgjelinek
42800209230bSgjelinek if ((pconf = pool_conf_alloc()) == NULL)
42810209230bSgjelinek return (zerr_pool(pool_err, err_size, Z_POOL));
42820209230bSgjelinek
42830209230bSgjelinek (void) snprintf(tmp_name, sizeof (tmp_name), TMP_POOL_NAME, zone_name);
42840209230bSgjelinek
42850209230bSgjelinek if (pool_conf_open(pconf, pool_dynamic_location(), PO_RDWR)
42860209230bSgjelinek != PO_SUCCESS) {
42870209230bSgjelinek res = zerr_pool(pool_err, err_size, Z_POOL);
42880209230bSgjelinek pool_conf_free(pconf);
42890209230bSgjelinek return (res);
42900209230bSgjelinek }
42910209230bSgjelinek
42920209230bSgjelinek pool = pool_get_pool(pconf, tmp_name);
42930209230bSgjelinek pset = pool_get_resource(pconf, "pset", tmp_name);
42940209230bSgjelinek
42950209230bSgjelinek if (pool == NULL && pset == NULL) {
42960209230bSgjelinek /* nothing to destroy, we're done */
42970209230bSgjelinek goto done;
42980209230bSgjelinek }
42990209230bSgjelinek
43000209230bSgjelinek if (pset != NULL && pool_resource_destroy(pconf, pset) != PO_SUCCESS) {
43010209230bSgjelinek res = zerr_pool(pool_err, err_size, Z_POOL);
43020209230bSgjelinek goto done;
43030209230bSgjelinek }
43040209230bSgjelinek
43050209230bSgjelinek if (pool != NULL && pool_destroy(pconf, pool) != PO_SUCCESS) {
43060209230bSgjelinek res = zerr_pool(pool_err, err_size, Z_POOL);
43070209230bSgjelinek goto done;
43080209230bSgjelinek }
43090209230bSgjelinek
43100209230bSgjelinek /* commit dynamic config */
43110209230bSgjelinek if (pool_conf_commit(pconf, 0) != PO_SUCCESS)
43120209230bSgjelinek res = zerr_pool(pool_err, err_size, Z_POOL);
43130209230bSgjelinek
43140209230bSgjelinek done:
43150209230bSgjelinek (void) pool_conf_close(pconf);
43160209230bSgjelinek pool_conf_free(pconf);
43170209230bSgjelinek
43180209230bSgjelinek return (res);
43190209230bSgjelinek }
43200209230bSgjelinek
43210209230bSgjelinek /*
43220209230bSgjelinek * Attempt to bind to a tmp pool for this zone. If there is no tmp pool
43230209230bSgjelinek * configured, we just return Z_OK.
43240209230bSgjelinek *
43250209230bSgjelinek * We either attempt to create the tmp pool for this zone or rebind to an
43260209230bSgjelinek * existing tmp pool for this zone.
43270209230bSgjelinek *
43280209230bSgjelinek * Rebinding is used when a zone with a tmp pool reboots so that we don't have
43290209230bSgjelinek * to recreate the tmp pool. To do this we need to be sure we work correctly
43300209230bSgjelinek * for the following cases:
43310209230bSgjelinek *
43320209230bSgjelinek * - there is an existing, properly configured tmp pool.
43330209230bSgjelinek * - zonecfg added tmp pool after zone was booted, must now create.
43340209230bSgjelinek * - zonecfg updated tmp pool config after zone was booted, in this case
43350209230bSgjelinek * we destroy the old tmp pool and create a new one.
43360209230bSgjelinek */
43370209230bSgjelinek int
zonecfg_bind_tmp_pool(zone_dochandle_t handle,zoneid_t zoneid,char * pool_err,int err_size)43380209230bSgjelinek zonecfg_bind_tmp_pool(zone_dochandle_t handle, zoneid_t zoneid, char *pool_err,
43390209230bSgjelinek int err_size)
43400209230bSgjelinek {
43410209230bSgjelinek struct zone_psettab pset_tab;
43420209230bSgjelinek int err;
43430209230bSgjelinek int status;
43440209230bSgjelinek pool_conf_t *pconf;
43450209230bSgjelinek boolean_t exists;
43460209230bSgjelinek char zone_name[ZONENAME_MAX];
43470209230bSgjelinek char tmp_name[MAX_TMP_POOL_NAME];
43480209230bSgjelinek
43490209230bSgjelinek (void) getzonenamebyid(zoneid, zone_name, sizeof (zone_name));
43500209230bSgjelinek
43510209230bSgjelinek err = zonecfg_lookup_pset(handle, &pset_tab);
43520209230bSgjelinek
43530209230bSgjelinek /* if no temporary pool configured, we're done */
43540209230bSgjelinek if (err == Z_NO_ENTRY)
43550209230bSgjelinek return (Z_OK);
43560209230bSgjelinek
43570209230bSgjelinek /*
43580209230bSgjelinek * importance might not have a value but we need to validate it here,
43590209230bSgjelinek * so set the default.
43600209230bSgjelinek */
43610209230bSgjelinek if (pset_tab.zone_importance[0] == '\0')
43620209230bSgjelinek (void) strlcpy(pset_tab.zone_importance, "1",
43630209230bSgjelinek sizeof (pset_tab.zone_importance));
43640209230bSgjelinek
43650209230bSgjelinek /* if pools not enabled, enable them now */
43660209230bSgjelinek if (pool_get_status(&status) != PO_SUCCESS || status != POOL_ENABLED) {
43670209230bSgjelinek if (pool_set_status(POOL_ENABLED) != PO_SUCCESS)
43680209230bSgjelinek return (Z_POOL_ENABLE);
43690209230bSgjelinek }
43700209230bSgjelinek
43710209230bSgjelinek if ((pconf = pool_conf_alloc()) == NULL)
43720209230bSgjelinek return (zerr_pool(pool_err, err_size, Z_POOL));
43730209230bSgjelinek
43740209230bSgjelinek (void) snprintf(tmp_name, sizeof (tmp_name), TMP_POOL_NAME, zone_name);
43750209230bSgjelinek
43760209230bSgjelinek /*
43770209230bSgjelinek * Check if a valid tmp pool/pset already exists. If so, we just
43780209230bSgjelinek * reuse it.
43790209230bSgjelinek */
43800209230bSgjelinek if ((err = verify_del_tmp_pool(pconf, tmp_name, pool_err, err_size,
43810209230bSgjelinek &pset_tab, &exists)) != Z_OK) {
43820209230bSgjelinek pool_conf_free(pconf);
43830209230bSgjelinek return (err);
43840209230bSgjelinek }
43850209230bSgjelinek
43860209230bSgjelinek if (!exists)
43870209230bSgjelinek err = create_tmp_pool(pool_err, err_size, pconf, tmp_name,
43880209230bSgjelinek &pset_tab);
43890209230bSgjelinek
43900209230bSgjelinek pool_conf_free(pconf);
43910209230bSgjelinek
43920209230bSgjelinek if (err != Z_OK)
43930209230bSgjelinek return (err);
43940209230bSgjelinek
43950209230bSgjelinek /* Bind the zone to the pool. */
43960209230bSgjelinek if (pool_set_binding(tmp_name, P_ZONEID, zoneid) != PO_SUCCESS)
43970209230bSgjelinek return (zerr_pool(pool_err, err_size, Z_POOL_BIND));
43980209230bSgjelinek
43990209230bSgjelinek return (Z_OK);
44000209230bSgjelinek }
44010209230bSgjelinek
44020209230bSgjelinek /*
44030209230bSgjelinek * Attempt to bind to a permanent pool for this zone. If there is no
44040209230bSgjelinek * permanent pool configured, we just return Z_OK.
44050209230bSgjelinek */
44060209230bSgjelinek int
zonecfg_bind_pool(zone_dochandle_t handle,zoneid_t zoneid,char * pool_err,int err_size)44070209230bSgjelinek zonecfg_bind_pool(zone_dochandle_t handle, zoneid_t zoneid, char *pool_err,
44080209230bSgjelinek int err_size)
44090209230bSgjelinek {
44100209230bSgjelinek pool_conf_t *poolconf;
44110209230bSgjelinek pool_t *pool;
44120209230bSgjelinek char poolname[MAXPATHLEN];
44130209230bSgjelinek int status;
44140209230bSgjelinek int error;
44150209230bSgjelinek
44160209230bSgjelinek /*
44170209230bSgjelinek * Find the pool mentioned in the zone configuration, and bind to it.
44180209230bSgjelinek */
44190209230bSgjelinek error = zonecfg_get_pool(handle, poolname, sizeof (poolname));
44200209230bSgjelinek if (error == Z_NO_ENTRY || (error == Z_OK && strlen(poolname) == 0)) {
44210209230bSgjelinek /*
44220209230bSgjelinek * The property is not set on the zone, so the pool
44230209230bSgjelinek * should be bound to the default pool. But that's
44240209230bSgjelinek * already done by the kernel, so we can just return.
44250209230bSgjelinek */
44260209230bSgjelinek return (Z_OK);
44270209230bSgjelinek }
44280209230bSgjelinek if (error != Z_OK) {
44290209230bSgjelinek /*
44300209230bSgjelinek * Not an error, even though it shouldn't be happening.
44310209230bSgjelinek */
44320209230bSgjelinek return (Z_OK);
44330209230bSgjelinek }
44340209230bSgjelinek /*
44350209230bSgjelinek * Don't do anything if pools aren't enabled.
44360209230bSgjelinek */
44370209230bSgjelinek if (pool_get_status(&status) != PO_SUCCESS || status != POOL_ENABLED)
44380209230bSgjelinek return (Z_POOLS_NOT_ACTIVE);
44390209230bSgjelinek
44400209230bSgjelinek /*
44410209230bSgjelinek * Try to provide a sane error message if the requested pool doesn't
44420209230bSgjelinek * exist.
44430209230bSgjelinek */
44440209230bSgjelinek if ((poolconf = pool_conf_alloc()) == NULL)
44450209230bSgjelinek return (zerr_pool(pool_err, err_size, Z_POOL));
44460209230bSgjelinek
44470209230bSgjelinek if (pool_conf_open(poolconf, pool_dynamic_location(), PO_RDONLY) !=
44480209230bSgjelinek PO_SUCCESS) {
44490209230bSgjelinek pool_conf_free(poolconf);
44500209230bSgjelinek return (zerr_pool(pool_err, err_size, Z_POOL));
44510209230bSgjelinek }
44520209230bSgjelinek pool = pool_get_pool(poolconf, poolname);
44530209230bSgjelinek (void) pool_conf_close(poolconf);
44540209230bSgjelinek pool_conf_free(poolconf);
44550209230bSgjelinek if (pool == NULL)
44560209230bSgjelinek return (Z_NO_POOL);
44570209230bSgjelinek
44580209230bSgjelinek /*
44590209230bSgjelinek * Bind the zone to the pool.
44600209230bSgjelinek */
44610209230bSgjelinek if (pool_set_binding(poolname, P_ZONEID, zoneid) != PO_SUCCESS) {
44620209230bSgjelinek /* if bind fails, return poolname for the error msg */
44630209230bSgjelinek (void) strlcpy(pool_err, poolname, err_size);
44640209230bSgjelinek return (Z_POOL_BIND);
44650209230bSgjelinek }
44660209230bSgjelinek
44670209230bSgjelinek return (Z_OK);
44680209230bSgjelinek }
44690209230bSgjelinek
44700dc2366fSVenugopal Iyer int
zonecfg_get_poolname(zone_dochandle_t handle,char * zone,char * pool,size_t poolsize)44710dc2366fSVenugopal Iyer zonecfg_get_poolname(zone_dochandle_t handle, char *zone, char *pool,
44720dc2366fSVenugopal Iyer size_t poolsize)
44730dc2366fSVenugopal Iyer {
44740dc2366fSVenugopal Iyer int err;
44750dc2366fSVenugopal Iyer struct zone_psettab pset_tab;
44760dc2366fSVenugopal Iyer
44770dc2366fSVenugopal Iyer err = zonecfg_lookup_pset(handle, &pset_tab);
44780dc2366fSVenugopal Iyer if ((err != Z_NO_ENTRY) && (err != Z_OK))
44790dc2366fSVenugopal Iyer return (err);
44800dc2366fSVenugopal Iyer
44810dc2366fSVenugopal Iyer /* pset was found so a temporary pool was created */
44820dc2366fSVenugopal Iyer if (err == Z_OK) {
44830dc2366fSVenugopal Iyer (void) snprintf(pool, poolsize, TMP_POOL_NAME, zone);
44840dc2366fSVenugopal Iyer return (Z_OK);
44850dc2366fSVenugopal Iyer }
44860dc2366fSVenugopal Iyer
44870dc2366fSVenugopal Iyer /* lookup the poolname in zonecfg */
44880dc2366fSVenugopal Iyer return (zonecfg_get_pool(handle, pool, poolsize));
44890dc2366fSVenugopal Iyer }
44900209230bSgjelinek
44910209230bSgjelinek static boolean_t
svc_enabled(char * svc_name)44920209230bSgjelinek svc_enabled(char *svc_name)
44930209230bSgjelinek {
44940209230bSgjelinek scf_simple_prop_t *prop;
44950209230bSgjelinek boolean_t found = B_FALSE;
44960209230bSgjelinek
44970209230bSgjelinek prop = scf_simple_prop_get(NULL, svc_name, SCF_PG_GENERAL,
44980209230bSgjelinek SCF_PROPERTY_ENABLED);
44990209230bSgjelinek
45000209230bSgjelinek if (scf_simple_prop_numvalues(prop) == 1 &&
45010209230bSgjelinek *scf_simple_prop_next_boolean(prop) != 0)
45020209230bSgjelinek found = B_TRUE;
45030209230bSgjelinek
45040209230bSgjelinek scf_simple_prop_free(prop);
45050209230bSgjelinek
45060209230bSgjelinek return (found);
45070209230bSgjelinek }
45080209230bSgjelinek
45090209230bSgjelinek /*
45100209230bSgjelinek * If the zone has capped-memory, make sure the rcap service is enabled.
45110209230bSgjelinek */
45120209230bSgjelinek int
zonecfg_enable_rcapd(char * err,int size)45130209230bSgjelinek zonecfg_enable_rcapd(char *err, int size)
45140209230bSgjelinek {
45150209230bSgjelinek if (!svc_enabled(RCAP_SERVICE) &&
45160209230bSgjelinek smf_enable_instance(RCAP_SERVICE, 0) == -1) {
45170209230bSgjelinek (void) strlcpy(err, scf_strerror(scf_error()), size);
45180209230bSgjelinek return (Z_SYSTEM);
45190209230bSgjelinek }
45200209230bSgjelinek
45210209230bSgjelinek return (Z_OK);
45220209230bSgjelinek }
45230209230bSgjelinek
45240209230bSgjelinek /*
45250209230bSgjelinek * Return true if pset has cpu range specified and poold is not enabled.
45260209230bSgjelinek */
45270209230bSgjelinek boolean_t
zonecfg_warn_poold(zone_dochandle_t handle)45280209230bSgjelinek zonecfg_warn_poold(zone_dochandle_t handle)
45290209230bSgjelinek {
45300209230bSgjelinek struct zone_psettab pset_tab;
45310209230bSgjelinek int min, max;
45320209230bSgjelinek int err;
45330209230bSgjelinek
45340209230bSgjelinek err = zonecfg_lookup_pset(handle, &pset_tab);
45350209230bSgjelinek
45360209230bSgjelinek /* if no temporary pool configured, we're done */
45370209230bSgjelinek if (err == Z_NO_ENTRY)
45380209230bSgjelinek return (B_FALSE);
45390209230bSgjelinek
45400209230bSgjelinek min = atoi(pset_tab.zone_ncpu_min);
45410209230bSgjelinek max = atoi(pset_tab.zone_ncpu_max);
45420209230bSgjelinek
45430209230bSgjelinek /* range not specified, no need for poold */
45440209230bSgjelinek if (min == max)
45450209230bSgjelinek return (B_FALSE);
45460209230bSgjelinek
45470209230bSgjelinek /* we have a range, check if poold service is enabled */
45480209230bSgjelinek if (svc_enabled(POOLD_SERVICE))
45490209230bSgjelinek return (B_FALSE);
45500209230bSgjelinek
45510209230bSgjelinek return (B_TRUE);
45520209230bSgjelinek }
45530209230bSgjelinek
455434eb7836Sjv227347 /*
455534eb7836Sjv227347 * Retrieve the specified pool's thread scheduling class. 'poolname' must
455634eb7836Sjv227347 * refer to the name of a configured resource pool. The thread scheduling
455734eb7836Sjv227347 * class specified by the pool will be stored in the buffer to which 'class'
455834eb7836Sjv227347 * points. 'clsize' is the byte size of the buffer to which 'class' points.
455934eb7836Sjv227347 *
456034eb7836Sjv227347 * This function returns Z_OK if it successfully stored the specified pool's
456134eb7836Sjv227347 * thread scheduling class into the buffer to which 'class' points. It returns
456234eb7836Sjv227347 * Z_NO_POOL if resource pools are not enabled, the function is unable to
456334eb7836Sjv227347 * access the system's resource pools configuration, or the specified pool
456434eb7836Sjv227347 * does not exist. The function returns Z_TOO_BIG if the buffer to which
456534eb7836Sjv227347 * 'class' points is not large enough to contain the thread scheduling class'
456634eb7836Sjv227347 * name. The function returns Z_NO_ENTRY if the pool does not specify a thread
456734eb7836Sjv227347 * scheduling class.
456834eb7836Sjv227347 */
45690209230bSgjelinek static int
get_pool_sched_class(char * poolname,char * class,int clsize)45700209230bSgjelinek get_pool_sched_class(char *poolname, char *class, int clsize)
45710209230bSgjelinek {
45720209230bSgjelinek int status;
45730209230bSgjelinek pool_conf_t *poolconf;
45740209230bSgjelinek pool_t *pool;
45750209230bSgjelinek pool_elem_t *pe;
45760209230bSgjelinek pool_value_t *pv = pool_value_alloc();
45770209230bSgjelinek const char *sched_str;
45780209230bSgjelinek
45790209230bSgjelinek if (pool_get_status(&status) != PO_SUCCESS || status != POOL_ENABLED)
45800209230bSgjelinek return (Z_NO_POOL);
45810209230bSgjelinek
45820209230bSgjelinek if ((poolconf = pool_conf_alloc()) == NULL)
45830209230bSgjelinek return (Z_NO_POOL);
45840209230bSgjelinek
45850209230bSgjelinek if (pool_conf_open(poolconf, pool_dynamic_location(), PO_RDONLY) !=
45860209230bSgjelinek PO_SUCCESS) {
45870209230bSgjelinek pool_conf_free(poolconf);
45880209230bSgjelinek return (Z_NO_POOL);
45890209230bSgjelinek }
45900209230bSgjelinek
45910209230bSgjelinek if ((pool = pool_get_pool(poolconf, poolname)) == NULL) {
45920209230bSgjelinek (void) pool_conf_close(poolconf);
45930209230bSgjelinek pool_conf_free(poolconf);
45940209230bSgjelinek return (Z_NO_POOL);
45950209230bSgjelinek }
45960209230bSgjelinek
45970209230bSgjelinek pe = pool_to_elem(poolconf, pool);
459834eb7836Sjv227347 if (pool_get_property(poolconf, pe, "pool.scheduler", pv) !=
459934eb7836Sjv227347 POC_STRING) {
46000209230bSgjelinek (void) pool_conf_close(poolconf);
46010209230bSgjelinek pool_conf_free(poolconf);
460234eb7836Sjv227347 return (Z_NO_ENTRY);
460334eb7836Sjv227347 }
460434eb7836Sjv227347 (void) pool_value_get_string(pv, &sched_str);
460534eb7836Sjv227347 (void) pool_conf_close(poolconf);
460634eb7836Sjv227347 pool_conf_free(poolconf);
460734eb7836Sjv227347 if (strlcpy(class, sched_str, clsize) >= clsize)
460834eb7836Sjv227347 return (Z_TOO_BIG);
46090209230bSgjelinek return (Z_OK);
46100209230bSgjelinek }
46110209230bSgjelinek
46120209230bSgjelinek /*
46130209230bSgjelinek * Get the default scheduling class for the zone. This will either be the
46140209230bSgjelinek * class set on the zone's pool or the system default scheduling class.
46150209230bSgjelinek */
46160209230bSgjelinek int
zonecfg_get_dflt_sched_class(zone_dochandle_t handle,char * class,int clsize)46170209230bSgjelinek zonecfg_get_dflt_sched_class(zone_dochandle_t handle, char *class, int clsize)
46180209230bSgjelinek {
46190209230bSgjelinek char poolname[MAXPATHLEN];
46200209230bSgjelinek
46210209230bSgjelinek if (zonecfg_get_pool(handle, poolname, sizeof (poolname)) == Z_OK) {
46220209230bSgjelinek /* check if the zone's pool specified a sched class */
46230209230bSgjelinek if (get_pool_sched_class(poolname, class, clsize) == Z_OK)
46240209230bSgjelinek return (Z_OK);
46250209230bSgjelinek }
46260209230bSgjelinek
46270209230bSgjelinek if (priocntl(0, 0, PC_GETDFLCL, class, (uint64_t)clsize) == -1)
46280209230bSgjelinek return (Z_TOO_BIG);
46290209230bSgjelinek
46300209230bSgjelinek return (Z_OK);
46310209230bSgjelinek }
46320209230bSgjelinek
46337c478bd9Sstevel@tonic-gate int
zonecfg_setfsent(zone_dochandle_t handle)46347c478bd9Sstevel@tonic-gate zonecfg_setfsent(zone_dochandle_t handle)
46357c478bd9Sstevel@tonic-gate {
46367c478bd9Sstevel@tonic-gate return (zonecfg_setent(handle));
46377c478bd9Sstevel@tonic-gate }
46387c478bd9Sstevel@tonic-gate
46397c478bd9Sstevel@tonic-gate int
zonecfg_getfsent(zone_dochandle_t handle,struct zone_fstab * tabptr)46407c478bd9Sstevel@tonic-gate zonecfg_getfsent(zone_dochandle_t handle, struct zone_fstab *tabptr)
46417c478bd9Sstevel@tonic-gate {
46427c478bd9Sstevel@tonic-gate xmlNodePtr cur, options;
46437c478bd9Sstevel@tonic-gate char options_str[MAX_MNTOPT_STR];
46447c478bd9Sstevel@tonic-gate int err;
46457c478bd9Sstevel@tonic-gate
46467c478bd9Sstevel@tonic-gate if (handle == NULL)
46477c478bd9Sstevel@tonic-gate return (Z_INVAL);
46487c478bd9Sstevel@tonic-gate
46497c478bd9Sstevel@tonic-gate if ((cur = handle->zone_dh_cur) == NULL)
46507c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY);
46517c478bd9Sstevel@tonic-gate
46527c478bd9Sstevel@tonic-gate for (; cur != NULL; cur = cur->next)
46537c478bd9Sstevel@tonic-gate if (!xmlStrcmp(cur->name, DTD_ELEM_FS))
46547c478bd9Sstevel@tonic-gate break;
46557c478bd9Sstevel@tonic-gate if (cur == NULL) {
46567c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top;
46577c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY);
46587c478bd9Sstevel@tonic-gate }
46597c478bd9Sstevel@tonic-gate
46607c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_SPECIAL, tabptr->zone_fs_special,
46617c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_special))) != Z_OK) {
46627c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top;
46637c478bd9Sstevel@tonic-gate return (err);
46647c478bd9Sstevel@tonic-gate }
46657c478bd9Sstevel@tonic-gate
46667c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_RAW, tabptr->zone_fs_raw,
46677c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_raw))) != Z_OK) {
46687c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top;
46697c478bd9Sstevel@tonic-gate return (err);
46707c478bd9Sstevel@tonic-gate }
46717c478bd9Sstevel@tonic-gate
46727c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir,
46737c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_dir))) != Z_OK) {
46747c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top;
46757c478bd9Sstevel@tonic-gate return (err);
46767c478bd9Sstevel@tonic-gate }
46777c478bd9Sstevel@tonic-gate
46787c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_TYPE, tabptr->zone_fs_type,
46797c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_type))) != Z_OK) {
46807c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top;
46817c478bd9Sstevel@tonic-gate return (err);
46827c478bd9Sstevel@tonic-gate }
46837c478bd9Sstevel@tonic-gate
46847c478bd9Sstevel@tonic-gate /* OK for options to be NULL */
46857c478bd9Sstevel@tonic-gate tabptr->zone_fs_options = NULL;
46867c478bd9Sstevel@tonic-gate for (options = cur->xmlChildrenNode; options != NULL;
46877c478bd9Sstevel@tonic-gate options = options->next) {
46887c478bd9Sstevel@tonic-gate if (fetchprop(options, DTD_ATTR_NAME, options_str,
46897c478bd9Sstevel@tonic-gate sizeof (options_str)) != Z_OK)
46907c478bd9Sstevel@tonic-gate break;
46917c478bd9Sstevel@tonic-gate if (zonecfg_add_fs_option(tabptr, options_str) != Z_OK)
46927c478bd9Sstevel@tonic-gate break;
46937c478bd9Sstevel@tonic-gate }
46947c478bd9Sstevel@tonic-gate
46957c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur->next;
46967c478bd9Sstevel@tonic-gate return (Z_OK);
46977c478bd9Sstevel@tonic-gate }
46987c478bd9Sstevel@tonic-gate
46997c478bd9Sstevel@tonic-gate int
zonecfg_endfsent(zone_dochandle_t handle)47007c478bd9Sstevel@tonic-gate zonecfg_endfsent(zone_dochandle_t handle)
47017c478bd9Sstevel@tonic-gate {
47027c478bd9Sstevel@tonic-gate return (zonecfg_endent(handle));
47037c478bd9Sstevel@tonic-gate }
47047c478bd9Sstevel@tonic-gate
47057c478bd9Sstevel@tonic-gate int
zonecfg_setnwifent(zone_dochandle_t handle)47067c478bd9Sstevel@tonic-gate zonecfg_setnwifent(zone_dochandle_t handle)
47077c478bd9Sstevel@tonic-gate {
47087c478bd9Sstevel@tonic-gate return (zonecfg_setent(handle));
47097c478bd9Sstevel@tonic-gate }
47107c478bd9Sstevel@tonic-gate
47117c478bd9Sstevel@tonic-gate int
zonecfg_getnwifent(zone_dochandle_t handle,struct zone_nwiftab * tabptr)47127c478bd9Sstevel@tonic-gate zonecfg_getnwifent(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
47137c478bd9Sstevel@tonic-gate {
47147c478bd9Sstevel@tonic-gate xmlNodePtr cur;
47157c478bd9Sstevel@tonic-gate int err;
47167c478bd9Sstevel@tonic-gate
47177c478bd9Sstevel@tonic-gate if (handle == NULL)
47187c478bd9Sstevel@tonic-gate return (Z_INVAL);
47197c478bd9Sstevel@tonic-gate
47207c478bd9Sstevel@tonic-gate if ((cur = handle->zone_dh_cur) == NULL)
47217c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY);
47227c478bd9Sstevel@tonic-gate
47237c478bd9Sstevel@tonic-gate for (; cur != NULL; cur = cur->next)
47247c478bd9Sstevel@tonic-gate if (!xmlStrcmp(cur->name, DTD_ELEM_NET))
47257c478bd9Sstevel@tonic-gate break;
47267c478bd9Sstevel@tonic-gate if (cur == NULL) {
47277c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top;
47287c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY);
47297c478bd9Sstevel@tonic-gate }
47307c478bd9Sstevel@tonic-gate
47317c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_ADDRESS, tabptr->zone_nwif_address,
47327c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_nwif_address))) != Z_OK) {
47337c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top;
47347c478bd9Sstevel@tonic-gate return (err);
47357c478bd9Sstevel@tonic-gate }
47367c478bd9Sstevel@tonic-gate
4737550b6e40SSowmini Varadhan if ((err = fetchprop(cur, DTD_ATTR_ALLOWED_ADDRESS,
4738550b6e40SSowmini Varadhan tabptr->zone_nwif_allowed_address,
4739550b6e40SSowmini Varadhan sizeof (tabptr->zone_nwif_allowed_address))) != Z_OK) {
4740550b6e40SSowmini Varadhan handle->zone_dh_cur = handle->zone_dh_top;
4741550b6e40SSowmini Varadhan return (err);
4742550b6e40SSowmini Varadhan }
4743550b6e40SSowmini Varadhan
47447c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_PHYSICAL, tabptr->zone_nwif_physical,
47457c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_nwif_physical))) != Z_OK) {
47467c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top;
47477c478bd9Sstevel@tonic-gate return (err);
47487c478bd9Sstevel@tonic-gate }
47497c478bd9Sstevel@tonic-gate
4750de860bd9Sgfaden if ((err = fetchprop(cur, DTD_ATTR_DEFROUTER,
4751de860bd9Sgfaden tabptr->zone_nwif_defrouter,
4752de860bd9Sgfaden sizeof (tabptr->zone_nwif_defrouter))) != Z_OK) {
4753de860bd9Sgfaden handle->zone_dh_cur = handle->zone_dh_top;
4754de860bd9Sgfaden return (err);
4755de860bd9Sgfaden }
4756de860bd9Sgfaden
47577c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur->next;
47587c478bd9Sstevel@tonic-gate return (Z_OK);
47597c478bd9Sstevel@tonic-gate }
47607c478bd9Sstevel@tonic-gate
47617c478bd9Sstevel@tonic-gate int
zonecfg_endnwifent(zone_dochandle_t handle)47627c478bd9Sstevel@tonic-gate zonecfg_endnwifent(zone_dochandle_t handle)
47637c478bd9Sstevel@tonic-gate {
47647c478bd9Sstevel@tonic-gate return (zonecfg_endent(handle));
47657c478bd9Sstevel@tonic-gate }
47667c478bd9Sstevel@tonic-gate
47677c478bd9Sstevel@tonic-gate int
zonecfg_setdevent(zone_dochandle_t handle)47687c478bd9Sstevel@tonic-gate zonecfg_setdevent(zone_dochandle_t handle)
47697c478bd9Sstevel@tonic-gate {
47707c478bd9Sstevel@tonic-gate return (zonecfg_setent(handle));
47717c478bd9Sstevel@tonic-gate }
47727c478bd9Sstevel@tonic-gate
47737c478bd9Sstevel@tonic-gate int
zonecfg_getdevent(zone_dochandle_t handle,struct zone_devtab * tabptr)47747c478bd9Sstevel@tonic-gate zonecfg_getdevent(zone_dochandle_t handle, struct zone_devtab *tabptr)
47757c478bd9Sstevel@tonic-gate {
47767c478bd9Sstevel@tonic-gate xmlNodePtr cur;
47777c478bd9Sstevel@tonic-gate int err;
47787c478bd9Sstevel@tonic-gate
47797c478bd9Sstevel@tonic-gate if (handle == NULL)
47807c478bd9Sstevel@tonic-gate return (Z_INVAL);
47817c478bd9Sstevel@tonic-gate
47827c478bd9Sstevel@tonic-gate if ((cur = handle->zone_dh_cur) == NULL)
47837c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY);
47847c478bd9Sstevel@tonic-gate
47857c478bd9Sstevel@tonic-gate for (; cur != NULL; cur = cur->next)
47867c478bd9Sstevel@tonic-gate if (!xmlStrcmp(cur->name, DTD_ELEM_DEVICE))
47877c478bd9Sstevel@tonic-gate break;
47887c478bd9Sstevel@tonic-gate if (cur == NULL) {
47897c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top;
47907c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY);
47917c478bd9Sstevel@tonic-gate }
47927c478bd9Sstevel@tonic-gate
47937c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_MATCH, tabptr->zone_dev_match,
47947c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_dev_match))) != Z_OK) {
47957c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top;
47967c478bd9Sstevel@tonic-gate return (err);
47977c478bd9Sstevel@tonic-gate }
47987c478bd9Sstevel@tonic-gate
47997c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur->next;
48007c478bd9Sstevel@tonic-gate return (Z_OK);
48017c478bd9Sstevel@tonic-gate }
48027c478bd9Sstevel@tonic-gate
48037c478bd9Sstevel@tonic-gate int
zonecfg_enddevent(zone_dochandle_t handle)48047c478bd9Sstevel@tonic-gate zonecfg_enddevent(zone_dochandle_t handle)
48057c478bd9Sstevel@tonic-gate {
48067c478bd9Sstevel@tonic-gate return (zonecfg_endent(handle));
48077c478bd9Sstevel@tonic-gate }
48087c478bd9Sstevel@tonic-gate
48097c478bd9Sstevel@tonic-gate int
zonecfg_setrctlent(zone_dochandle_t handle)48107c478bd9Sstevel@tonic-gate zonecfg_setrctlent(zone_dochandle_t handle)
48117c478bd9Sstevel@tonic-gate {
48127c478bd9Sstevel@tonic-gate return (zonecfg_setent(handle));
48137c478bd9Sstevel@tonic-gate }
48147c478bd9Sstevel@tonic-gate
48157c478bd9Sstevel@tonic-gate int
zonecfg_getrctlent(zone_dochandle_t handle,struct zone_rctltab * tabptr)48167c478bd9Sstevel@tonic-gate zonecfg_getrctlent(zone_dochandle_t handle, struct zone_rctltab *tabptr)
48177c478bd9Sstevel@tonic-gate {
48187c478bd9Sstevel@tonic-gate xmlNodePtr cur, val;
48197c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *valptr;
48207c478bd9Sstevel@tonic-gate int err;
48217c478bd9Sstevel@tonic-gate
48227c478bd9Sstevel@tonic-gate if (handle == NULL)
48237c478bd9Sstevel@tonic-gate return (Z_INVAL);
48247c478bd9Sstevel@tonic-gate
48257c478bd9Sstevel@tonic-gate if ((cur = handle->zone_dh_cur) == NULL)
48267c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY);
48277c478bd9Sstevel@tonic-gate
48287c478bd9Sstevel@tonic-gate for (; cur != NULL; cur = cur->next)
48297c478bd9Sstevel@tonic-gate if (!xmlStrcmp(cur->name, DTD_ELEM_RCTL))
48307c478bd9Sstevel@tonic-gate break;
48317c478bd9Sstevel@tonic-gate if (cur == NULL) {
48327c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top;
48337c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY);
48347c478bd9Sstevel@tonic-gate }
48357c478bd9Sstevel@tonic-gate
48367c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_NAME, tabptr->zone_rctl_name,
48377c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_rctl_name))) != Z_OK) {
48387c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top;
48397c478bd9Sstevel@tonic-gate return (err);
48407c478bd9Sstevel@tonic-gate }
48417c478bd9Sstevel@tonic-gate
48427c478bd9Sstevel@tonic-gate tabptr->zone_rctl_valptr = NULL;
48437c478bd9Sstevel@tonic-gate for (val = cur->xmlChildrenNode; val != NULL; val = val->next) {
48447c478bd9Sstevel@tonic-gate valptr = (struct zone_rctlvaltab *)malloc(
48457c478bd9Sstevel@tonic-gate sizeof (struct zone_rctlvaltab));
48467c478bd9Sstevel@tonic-gate if (valptr == NULL)
48477c478bd9Sstevel@tonic-gate return (Z_NOMEM);
48487c478bd9Sstevel@tonic-gate if (fetchprop(val, DTD_ATTR_PRIV, valptr->zone_rctlval_priv,
48497c478bd9Sstevel@tonic-gate sizeof (valptr->zone_rctlval_priv)) != Z_OK)
48507c478bd9Sstevel@tonic-gate break;
48517c478bd9Sstevel@tonic-gate if (fetchprop(val, DTD_ATTR_LIMIT, valptr->zone_rctlval_limit,
48527c478bd9Sstevel@tonic-gate sizeof (valptr->zone_rctlval_limit)) != Z_OK)
48537c478bd9Sstevel@tonic-gate break;
48547c478bd9Sstevel@tonic-gate if (fetchprop(val, DTD_ATTR_ACTION, valptr->zone_rctlval_action,
48557c478bd9Sstevel@tonic-gate sizeof (valptr->zone_rctlval_action)) != Z_OK)
48567c478bd9Sstevel@tonic-gate break;
48577c478bd9Sstevel@tonic-gate if (zonecfg_add_rctl_value(tabptr, valptr) != Z_OK)
48587c478bd9Sstevel@tonic-gate break;
48597c478bd9Sstevel@tonic-gate }
48607c478bd9Sstevel@tonic-gate
48617c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur->next;
48627c478bd9Sstevel@tonic-gate return (Z_OK);
48637c478bd9Sstevel@tonic-gate }
48647c478bd9Sstevel@tonic-gate
48657c478bd9Sstevel@tonic-gate int
zonecfg_endrctlent(zone_dochandle_t handle)48667c478bd9Sstevel@tonic-gate zonecfg_endrctlent(zone_dochandle_t handle)
48677c478bd9Sstevel@tonic-gate {
48687c478bd9Sstevel@tonic-gate return (zonecfg_endent(handle));
48697c478bd9Sstevel@tonic-gate }
48707c478bd9Sstevel@tonic-gate
48717c478bd9Sstevel@tonic-gate int
zonecfg_setattrent(zone_dochandle_t handle)48727c478bd9Sstevel@tonic-gate zonecfg_setattrent(zone_dochandle_t handle)
48737c478bd9Sstevel@tonic-gate {
48747c478bd9Sstevel@tonic-gate return (zonecfg_setent(handle));
48757c478bd9Sstevel@tonic-gate }
48767c478bd9Sstevel@tonic-gate
48777c478bd9Sstevel@tonic-gate int
zonecfg_getattrent(zone_dochandle_t handle,struct zone_attrtab * tabptr)48787c478bd9Sstevel@tonic-gate zonecfg_getattrent(zone_dochandle_t handle, struct zone_attrtab *tabptr)
48797c478bd9Sstevel@tonic-gate {
48807c478bd9Sstevel@tonic-gate xmlNodePtr cur;
48817c478bd9Sstevel@tonic-gate int err;
48827c478bd9Sstevel@tonic-gate
48837c478bd9Sstevel@tonic-gate if (handle == NULL)
48847c478bd9Sstevel@tonic-gate return (Z_INVAL);
48857c478bd9Sstevel@tonic-gate
48867c478bd9Sstevel@tonic-gate if ((cur = handle->zone_dh_cur) == NULL)
48877c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY);
48887c478bd9Sstevel@tonic-gate
48897c478bd9Sstevel@tonic-gate for (; cur != NULL; cur = cur->next)
48907c478bd9Sstevel@tonic-gate if (!xmlStrcmp(cur->name, DTD_ELEM_ATTR))
48917c478bd9Sstevel@tonic-gate break;
48927c478bd9Sstevel@tonic-gate if (cur == NULL) {
48937c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top;
48947c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY);
48957c478bd9Sstevel@tonic-gate }
48967c478bd9Sstevel@tonic-gate
48977c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_NAME, tabptr->zone_attr_name,
48987c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_attr_name))) != Z_OK) {
48997c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top;
49007c478bd9Sstevel@tonic-gate return (err);
49017c478bd9Sstevel@tonic-gate }
49027c478bd9Sstevel@tonic-gate
49037c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_TYPE, tabptr->zone_attr_type,
49047c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_attr_type))) != Z_OK) {
49057c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top;
49067c478bd9Sstevel@tonic-gate return (err);
49077c478bd9Sstevel@tonic-gate }
49087c478bd9Sstevel@tonic-gate
49097c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_VALUE, tabptr->zone_attr_value,
49107c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_attr_value))) != Z_OK) {
49117c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top;
49127c478bd9Sstevel@tonic-gate return (err);
49137c478bd9Sstevel@tonic-gate }
49147c478bd9Sstevel@tonic-gate
49157c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur->next;
49167c478bd9Sstevel@tonic-gate return (Z_OK);
49177c478bd9Sstevel@tonic-gate }
49187c478bd9Sstevel@tonic-gate
49197c478bd9Sstevel@tonic-gate int
zonecfg_endattrent(zone_dochandle_t handle)49207c478bd9Sstevel@tonic-gate zonecfg_endattrent(zone_dochandle_t handle)
49217c478bd9Sstevel@tonic-gate {
49227c478bd9Sstevel@tonic-gate return (zonecfg_endent(handle));
49237c478bd9Sstevel@tonic-gate }
49247c478bd9Sstevel@tonic-gate
4925cb8a054bSGlenn Faden int
zonecfg_setadminent(zone_dochandle_t handle)4926cb8a054bSGlenn Faden zonecfg_setadminent(zone_dochandle_t handle)
4927cb8a054bSGlenn Faden {
4928cb8a054bSGlenn Faden return (zonecfg_setent(handle));
4929cb8a054bSGlenn Faden }
4930cb8a054bSGlenn Faden
4931cb8a054bSGlenn Faden int
zonecfg_getadminent(zone_dochandle_t handle,struct zone_admintab * tabptr)4932cb8a054bSGlenn Faden zonecfg_getadminent(zone_dochandle_t handle, struct zone_admintab *tabptr)
4933cb8a054bSGlenn Faden {
4934cb8a054bSGlenn Faden xmlNodePtr cur;
4935cb8a054bSGlenn Faden int err;
4936cb8a054bSGlenn Faden
4937cb8a054bSGlenn Faden if (handle == NULL)
4938cb8a054bSGlenn Faden return (Z_INVAL);
4939cb8a054bSGlenn Faden
4940cb8a054bSGlenn Faden if ((cur = handle->zone_dh_cur) == NULL)
4941cb8a054bSGlenn Faden return (Z_NO_ENTRY);
4942cb8a054bSGlenn Faden
4943cb8a054bSGlenn Faden for (; cur != NULL; cur = cur->next)
4944cb8a054bSGlenn Faden if (!xmlStrcmp(cur->name, DTD_ELEM_ADMIN))
4945cb8a054bSGlenn Faden break;
4946cb8a054bSGlenn Faden if (cur == NULL) {
4947cb8a054bSGlenn Faden handle->zone_dh_cur = handle->zone_dh_top;
4948cb8a054bSGlenn Faden return (Z_NO_ENTRY);
4949cb8a054bSGlenn Faden }
4950cb8a054bSGlenn Faden
4951cb8a054bSGlenn Faden if ((err = fetchprop(cur, DTD_ATTR_USER, tabptr->zone_admin_user,
4952cb8a054bSGlenn Faden sizeof (tabptr->zone_admin_user))) != Z_OK) {
4953cb8a054bSGlenn Faden handle->zone_dh_cur = handle->zone_dh_top;
4954cb8a054bSGlenn Faden return (err);
4955cb8a054bSGlenn Faden }
4956cb8a054bSGlenn Faden
4957cb8a054bSGlenn Faden
4958cb8a054bSGlenn Faden if ((err = fetchprop(cur, DTD_ATTR_AUTHS, tabptr->zone_admin_auths,
4959cb8a054bSGlenn Faden sizeof (tabptr->zone_admin_auths))) != Z_OK) {
4960cb8a054bSGlenn Faden handle->zone_dh_cur = handle->zone_dh_top;
4961cb8a054bSGlenn Faden return (err);
4962cb8a054bSGlenn Faden }
4963cb8a054bSGlenn Faden
4964cb8a054bSGlenn Faden handle->zone_dh_cur = cur->next;
4965cb8a054bSGlenn Faden return (Z_OK);
4966cb8a054bSGlenn Faden }
4967cb8a054bSGlenn Faden
4968cb8a054bSGlenn Faden int
zonecfg_endadminent(zone_dochandle_t handle)4969cb8a054bSGlenn Faden zonecfg_endadminent(zone_dochandle_t handle)
4970cb8a054bSGlenn Faden {
4971cb8a054bSGlenn Faden return (zonecfg_endent(handle));
4972cb8a054bSGlenn Faden }
4973cb8a054bSGlenn Faden
4974ffbafc53Scomay /*
4975ffbafc53Scomay * The privileges available on the system and described in privileges(5)
49769acbbeafSnn35248 * fall into four categories with respect to non-global zones:
49779acbbeafSnn35248 *
49789acbbeafSnn35248 * Default set of privileges considered safe for all non-global
49799acbbeafSnn35248 * zones. These privileges are "safe" in the sense that a
49809acbbeafSnn35248 * privileged process in the zone cannot affect processes in any
49819acbbeafSnn35248 * other zone on the system.
49829acbbeafSnn35248 *
49839acbbeafSnn35248 * Set of privileges not currently permitted within a non-global
49849acbbeafSnn35248 * zone. These privileges are considered by default, "unsafe,"
49859acbbeafSnn35248 * and include ones which affect global resources (such as the
49869acbbeafSnn35248 * system clock or physical memory) or are overly broad and cover
49879acbbeafSnn35248 * more than one mechanism in the system. In other cases, there
49889acbbeafSnn35248 * has not been sufficient virtualization in the parts of the
49899acbbeafSnn35248 * system the privilege covers to allow its use within a
49909acbbeafSnn35248 * non-global zone.
49919acbbeafSnn35248 *
49929acbbeafSnn35248 * Set of privileges required in order to get a zone booted and
49939acbbeafSnn35248 * init(1M) started. These cannot be removed from the zone's
49949acbbeafSnn35248 * privilege set.
49959acbbeafSnn35248 *
49969acbbeafSnn35248 * All other privileges are optional and are potentially useful for
4997ffbafc53Scomay * processes executing inside a non-global zone.
4998ffbafc53Scomay *
4999ffbafc53Scomay * When privileges are added to the system, a determination needs to be
5000ffbafc53Scomay * made as to which category the privilege belongs to. Ideally,
5001ffbafc53Scomay * privileges should be fine-grained enough and the mechanisms they cover
5002ffbafc53Scomay * virtualized enough so that they can be made available to non-global
5003ffbafc53Scomay * zones.
5004ffbafc53Scomay */
5005ffbafc53Scomay
5006ffbafc53Scomay /*
5007ffbafc53Scomay * Define some of the tokens that priv_str_to_set(3C) recognizes. Since
5008ffbafc53Scomay * the privilege string separator can be any character, although it is
5009ffbafc53Scomay * usually a comma character, define these here as well in the event that
5010ffbafc53Scomay * they change or are augmented in the future.
5011ffbafc53Scomay */
5012ffbafc53Scomay #define BASIC_TOKEN "basic"
5013ffbafc53Scomay #define DEFAULT_TOKEN "default"
5014ffbafc53Scomay #define ZONE_TOKEN "zone"
5015ffbafc53Scomay #define TOKEN_PRIV_CHAR ','
5016ffbafc53Scomay #define TOKEN_PRIV_STR ","
5017ffbafc53Scomay
50189acbbeafSnn35248 typedef struct priv_node {
50199acbbeafSnn35248 struct priv_node *pn_next; /* Next privilege */
50209acbbeafSnn35248 char *pn_priv; /* Privileges name */
50219acbbeafSnn35248 } priv_node_t;
50229acbbeafSnn35248
50239acbbeafSnn35248 /* Privileges lists can differ across brands */
50249acbbeafSnn35248 typedef struct priv_lists {
50259acbbeafSnn35248 /* Privileges considered safe for all non-global zones of a brand */
50269acbbeafSnn35248 struct priv_node *pl_default;
50279acbbeafSnn35248
50289acbbeafSnn35248 /* Privileges not permitted for all non-global zones of a brand */
50299acbbeafSnn35248 struct priv_node *pl_prohibited;
50309acbbeafSnn35248
50319acbbeafSnn35248 /* Privileges required for all non-global zones of a brand */
50329acbbeafSnn35248 struct priv_node *pl_required;
5033bf1d7e28Sdh155122
5034bf1d7e28Sdh155122 /*
5035bf1d7e28Sdh155122 * ip-type of the zone these privileges lists apply to.
5036bf1d7e28Sdh155122 * It is used to pass ip-type to the callback function,
5037bf1d7e28Sdh155122 * priv_lists_cb, which has no way of getting the ip-type.
5038bf1d7e28Sdh155122 */
5039bf1d7e28Sdh155122 const char *pl_iptype;
50409acbbeafSnn35248 } priv_lists_t;
50419acbbeafSnn35248
50429acbbeafSnn35248 static int
priv_lists_cb(void * data,priv_iter_t * priv_iter)5043bf1d7e28Sdh155122 priv_lists_cb(void *data, priv_iter_t *priv_iter)
50447c478bd9Sstevel@tonic-gate {
50459acbbeafSnn35248 priv_lists_t *plp = (priv_lists_t *)data;
50469acbbeafSnn35248 priv_node_t *pnp;
50479acbbeafSnn35248
5048bf1d7e28Sdh155122 /* Skip this privilege if ip-type does not match */
5049bf1d7e28Sdh155122 if ((strcmp(priv_iter->pi_iptype, "all") != 0) &&
5050bf1d7e28Sdh155122 (strcmp(priv_iter->pi_iptype, plp->pl_iptype) != 0))
5051bf1d7e28Sdh155122 return (0);
5052bf1d7e28Sdh155122
50539acbbeafSnn35248 /* Allocate a new priv list node. */
50549acbbeafSnn35248 if ((pnp = malloc(sizeof (*pnp))) == NULL)
50559acbbeafSnn35248 return (-1);
5056bf1d7e28Sdh155122 if ((pnp->pn_priv = strdup(priv_iter->pi_name)) == NULL) {
50579acbbeafSnn35248 free(pnp);
50589acbbeafSnn35248 return (-1);
50599acbbeafSnn35248 }
50609acbbeafSnn35248
50619acbbeafSnn35248 /* Insert the new priv list node into the right list */
5062bf1d7e28Sdh155122 if (strcmp(priv_iter->pi_set, "default") == 0) {
50639acbbeafSnn35248 pnp->pn_next = plp->pl_default;
50649acbbeafSnn35248 plp->pl_default = pnp;
5065bf1d7e28Sdh155122 } else if (strcmp(priv_iter->pi_set, "prohibited") == 0) {
50669acbbeafSnn35248 pnp->pn_next = plp->pl_prohibited;
50679acbbeafSnn35248 plp->pl_prohibited = pnp;
5068bf1d7e28Sdh155122 } else if (strcmp(priv_iter->pi_set, "required") == 0) {
50699acbbeafSnn35248 pnp->pn_next = plp->pl_required;
50709acbbeafSnn35248 plp->pl_required = pnp;
50719acbbeafSnn35248 } else {
50729acbbeafSnn35248 free(pnp->pn_priv);
50739acbbeafSnn35248 free(pnp);
50749acbbeafSnn35248 return (-1);
50759acbbeafSnn35248 }
50769acbbeafSnn35248 return (0);
50779acbbeafSnn35248 }
50789acbbeafSnn35248
50799acbbeafSnn35248 static void
priv_lists_destroy(priv_lists_t * plp)50809acbbeafSnn35248 priv_lists_destroy(priv_lists_t *plp)
50819acbbeafSnn35248 {
50829acbbeafSnn35248 priv_node_t *pnp;
50839acbbeafSnn35248
50849acbbeafSnn35248 assert(plp != NULL);
50859acbbeafSnn35248
50869acbbeafSnn35248 while ((pnp = plp->pl_default) != NULL) {
50879acbbeafSnn35248 plp->pl_default = pnp->pn_next;
50889acbbeafSnn35248 free(pnp->pn_priv);
50899acbbeafSnn35248 free(pnp);
50909acbbeafSnn35248 }
50919acbbeafSnn35248 while ((pnp = plp->pl_prohibited) != NULL) {
50929acbbeafSnn35248 plp->pl_prohibited = pnp->pn_next;
50939acbbeafSnn35248 free(pnp->pn_priv);
50949acbbeafSnn35248 free(pnp);
50959acbbeafSnn35248 }
50969acbbeafSnn35248 while ((pnp = plp->pl_required) != NULL) {
50979acbbeafSnn35248 plp->pl_required = pnp->pn_next;
50989acbbeafSnn35248 free(pnp->pn_priv);
50999acbbeafSnn35248 free(pnp);
51009acbbeafSnn35248 }
51019acbbeafSnn35248 free(plp);
51029acbbeafSnn35248 }
51039acbbeafSnn35248
51049acbbeafSnn35248 static int
priv_lists_create(zone_dochandle_t handle,char * brand,priv_lists_t ** plpp,const char * curr_iptype)5105e5816e35SEdward Pilatowicz priv_lists_create(zone_dochandle_t handle, char *brand, priv_lists_t **plpp,
5106bf1d7e28Sdh155122 const char *curr_iptype)
51079acbbeafSnn35248 {
51089acbbeafSnn35248 priv_lists_t *plp;
5109123807fbSedp brand_handle_t bh;
5110e5816e35SEdward Pilatowicz char brand_str[MAXNAMELEN];
5111e5816e35SEdward Pilatowicz
5112e5816e35SEdward Pilatowicz /* handle or brand must be set, but never both */
5113e5816e35SEdward Pilatowicz assert((handle != NULL) || (brand != NULL));
5114e5816e35SEdward Pilatowicz assert((handle == NULL) || (brand == NULL));
51159acbbeafSnn35248
51169acbbeafSnn35248 if (handle != NULL) {
5117e5816e35SEdward Pilatowicz brand = brand_str;
5118e5816e35SEdward Pilatowicz if (zonecfg_get_brand(handle, brand, sizeof (brand_str)) != 0)
51199acbbeafSnn35248 return (Z_BRAND_ERROR);
51209acbbeafSnn35248 }
51219acbbeafSnn35248
5122123807fbSedp if ((bh = brand_open(brand)) == NULL)
51239acbbeafSnn35248 return (Z_BRAND_ERROR);
51249acbbeafSnn35248
51259acbbeafSnn35248 if ((plp = calloc(1, sizeof (priv_lists_t))) == NULL) {
5126123807fbSedp brand_close(bh);
51279acbbeafSnn35248 return (Z_NOMEM);
51289acbbeafSnn35248 }
51299acbbeafSnn35248
5130bf1d7e28Sdh155122 plp->pl_iptype = curr_iptype;
5131bf1d7e28Sdh155122
51329acbbeafSnn35248 /* construct the privilege lists */
5133123807fbSedp if (brand_config_iter_privilege(bh, priv_lists_cb, plp) != 0) {
51349acbbeafSnn35248 priv_lists_destroy(plp);
5135123807fbSedp brand_close(bh);
51369acbbeafSnn35248 return (Z_BRAND_ERROR);
51379acbbeafSnn35248 }
51389acbbeafSnn35248
5139123807fbSedp brand_close(bh);
51409acbbeafSnn35248 *plpp = plp;
51419acbbeafSnn35248 return (Z_OK);
51429acbbeafSnn35248 }
51439acbbeafSnn35248
51449acbbeafSnn35248 static int
get_default_privset(priv_set_t * privs,priv_lists_t * plp)51459acbbeafSnn35248 get_default_privset(priv_set_t *privs, priv_lists_t *plp)
51469acbbeafSnn35248 {
51479acbbeafSnn35248 priv_node_t *pnp;
5148ffbafc53Scomay priv_set_t *basic;
51497c478bd9Sstevel@tonic-gate
5150ffbafc53Scomay basic = priv_str_to_set(BASIC_TOKEN, TOKEN_PRIV_STR, NULL);
51517c478bd9Sstevel@tonic-gate if (basic == NULL)
5152ffbafc53Scomay return (errno == ENOMEM ? Z_NOMEM : Z_INVAL);
51537c478bd9Sstevel@tonic-gate
51547c478bd9Sstevel@tonic-gate priv_union(basic, privs);
51557c478bd9Sstevel@tonic-gate priv_freeset(basic);
51567c478bd9Sstevel@tonic-gate
51579acbbeafSnn35248 for (pnp = plp->pl_default; pnp != NULL; pnp = pnp->pn_next) {
51589acbbeafSnn35248 if (priv_addset(privs, pnp->pn_priv) != 0)
51597c478bd9Sstevel@tonic-gate return (Z_INVAL);
51607c478bd9Sstevel@tonic-gate }
51619acbbeafSnn35248
51627c478bd9Sstevel@tonic-gate return (Z_OK);
51637c478bd9Sstevel@tonic-gate }
51647c478bd9Sstevel@tonic-gate
51659acbbeafSnn35248 int
zonecfg_default_brand(char * brand,size_t brandsize)5166e5816e35SEdward Pilatowicz zonecfg_default_brand(char *brand, size_t brandsize)
5167e5816e35SEdward Pilatowicz {
5168e5816e35SEdward Pilatowicz zone_dochandle_t handle;
51697522f2fcSEdward Pilatowicz int myzoneid = getzoneid();
5170e5816e35SEdward Pilatowicz int ret;
5171e5816e35SEdward Pilatowicz
51727522f2fcSEdward Pilatowicz /*
51737522f2fcSEdward Pilatowicz * If we're running within a zone, then the default brand is the
51747522f2fcSEdward Pilatowicz * current zone's brand.
51757522f2fcSEdward Pilatowicz */
51767522f2fcSEdward Pilatowicz if (myzoneid != GLOBAL_ZONEID) {
51777522f2fcSEdward Pilatowicz ret = zone_getattr(myzoneid, ZONE_ATTR_BRAND, brand, brandsize);
51787522f2fcSEdward Pilatowicz if (ret < 0)
51797522f2fcSEdward Pilatowicz return ((errno == EFAULT) ? Z_TOO_BIG : Z_INVAL);
51807522f2fcSEdward Pilatowicz return (Z_OK);
51817522f2fcSEdward Pilatowicz }
51827522f2fcSEdward Pilatowicz
5183e5816e35SEdward Pilatowicz if ((handle = zonecfg_init_handle()) == NULL)
5184e5816e35SEdward Pilatowicz return (Z_NOMEM);
5185e5816e35SEdward Pilatowicz if ((ret = zonecfg_get_handle("SUNWdefault", handle)) == Z_OK) {
5186e5816e35SEdward Pilatowicz ret = i_zonecfg_get_brand(handle, brand, brandsize, B_TRUE);
5187e5816e35SEdward Pilatowicz zonecfg_fini_handle(handle);
5188e5816e35SEdward Pilatowicz return (ret);
5189e5816e35SEdward Pilatowicz }
5190e5816e35SEdward Pilatowicz return (ret);
5191e5816e35SEdward Pilatowicz }
5192e5816e35SEdward Pilatowicz
5193e5816e35SEdward Pilatowicz int
zonecfg_default_privset(priv_set_t * privs,const char * curr_iptype)5194bf1d7e28Sdh155122 zonecfg_default_privset(priv_set_t *privs, const char *curr_iptype)
51959acbbeafSnn35248 {
51969acbbeafSnn35248 priv_lists_t *plp;
5197e5816e35SEdward Pilatowicz char buf[MAXNAMELEN];
51989acbbeafSnn35248 int ret;
51999acbbeafSnn35248
5200e5816e35SEdward Pilatowicz if ((ret = zonecfg_default_brand(buf, sizeof (buf))) != Z_OK)
5201e5816e35SEdward Pilatowicz return (ret);
5202e5816e35SEdward Pilatowicz if ((ret = priv_lists_create(NULL, buf, &plp, curr_iptype)) != Z_OK)
52039acbbeafSnn35248 return (ret);
52049acbbeafSnn35248 ret = get_default_privset(privs, plp);
52059acbbeafSnn35248 priv_lists_destroy(plp);
52069acbbeafSnn35248 return (ret);
52079acbbeafSnn35248 }
52089acbbeafSnn35248
5209ffbafc53Scomay void
append_priv_token(char * priv,char * str,size_t strlen)5210ffbafc53Scomay append_priv_token(char *priv, char *str, size_t strlen)
5211ffbafc53Scomay {
5212ffbafc53Scomay if (*str != '\0')
5213ffbafc53Scomay (void) strlcat(str, TOKEN_PRIV_STR, strlen);
5214ffbafc53Scomay (void) strlcat(str, priv, strlen);
5215ffbafc53Scomay }
5216ffbafc53Scomay
5217ffbafc53Scomay /*
5218ffbafc53Scomay * Verify that the supplied string is a valid privilege limit set for a
5219ffbafc53Scomay * non-global zone. This string must not only be acceptable to
5220ffbafc53Scomay * priv_str_to_set(3C) which parses it, but it also must resolve to a
5221ffbafc53Scomay * privilege set that includes certain required privileges and lacks
5222ffbafc53Scomay * certain prohibited privileges.
5223ffbafc53Scomay */
5224ffbafc53Scomay static int
verify_privset(char * privbuf,priv_set_t * privs,char ** privname,boolean_t add_default,priv_lists_t * plp)5225ffbafc53Scomay verify_privset(char *privbuf, priv_set_t *privs, char **privname,
52269acbbeafSnn35248 boolean_t add_default, priv_lists_t *plp)
5227ffbafc53Scomay {
52289acbbeafSnn35248 priv_node_t *pnp;
52299acbbeafSnn35248 char *tmp, *cp, *lasts;
5230ffbafc53Scomay size_t len;
5231ffbafc53Scomay priv_set_t *mergeset;
5232ffbafc53Scomay const char *token;
5233ffbafc53Scomay
5234ffbafc53Scomay /*
5235ffbafc53Scomay * The verification of the privilege string occurs in several
5236ffbafc53Scomay * phases. In the first phase, the supplied string is scanned for
5237ffbafc53Scomay * the ZONE_TOKEN token which is not support as part of the
5238ffbafc53Scomay * "limitpriv" property.
5239ffbafc53Scomay *
5240ffbafc53Scomay * Duplicate the supplied privilege string since strtok_r(3C)
5241ffbafc53Scomay * tokenizes its input by null-terminating the tokens.
5242ffbafc53Scomay */
5243ffbafc53Scomay if ((tmp = strdup(privbuf)) == NULL)
5244ffbafc53Scomay return (Z_NOMEM);
5245ffbafc53Scomay for (cp = strtok_r(tmp, TOKEN_PRIV_STR, &lasts); cp != NULL;
5246ffbafc53Scomay cp = strtok_r(NULL, TOKEN_PRIV_STR, &lasts)) {
5247ffbafc53Scomay if (strcmp(cp, ZONE_TOKEN) == 0) {
5248ffbafc53Scomay free(tmp);
5249ffbafc53Scomay if ((*privname = strdup(ZONE_TOKEN)) == NULL)
5250ffbafc53Scomay return (Z_NOMEM);
5251ffbafc53Scomay else
5252ffbafc53Scomay return (Z_PRIV_UNKNOWN);
5253ffbafc53Scomay }
5254ffbafc53Scomay }
5255ffbafc53Scomay free(tmp);
5256ffbafc53Scomay
5257ffbafc53Scomay if (add_default) {
5258ffbafc53Scomay /*
5259ffbafc53Scomay * If DEFAULT_TOKEN was specified, a string needs to be
5260ffbafc53Scomay * built containing the privileges from the default, safe
5261ffbafc53Scomay * set along with those of the "limitpriv" property.
5262ffbafc53Scomay */
5263ffbafc53Scomay len = strlen(privbuf) + sizeof (BASIC_TOKEN) + 2;
52649acbbeafSnn35248
52659acbbeafSnn35248 for (pnp = plp->pl_default; pnp != NULL; pnp = pnp->pn_next)
52669acbbeafSnn35248 len += strlen(pnp->pn_priv) + 1;
5267ffbafc53Scomay tmp = alloca(len);
5268ffbafc53Scomay *tmp = '\0';
5269ffbafc53Scomay
5270ffbafc53Scomay append_priv_token(BASIC_TOKEN, tmp, len);
52719acbbeafSnn35248 for (pnp = plp->pl_default; pnp != NULL; pnp = pnp->pn_next)
52729acbbeafSnn35248 append_priv_token(pnp->pn_priv, tmp, len);
5273ffbafc53Scomay (void) strlcat(tmp, TOKEN_PRIV_STR, len);
5274ffbafc53Scomay (void) strlcat(tmp, privbuf, len);
5275ffbafc53Scomay } else {
5276ffbafc53Scomay tmp = privbuf;
5277ffbafc53Scomay }
5278ffbafc53Scomay
5279ffbafc53Scomay
5280ffbafc53Scomay /*
5281ffbafc53Scomay * In the next phase, attempt to convert the merged privilege
5282ffbafc53Scomay * string into a privilege set. In the case of an error, either
5283ffbafc53Scomay * there was a memory allocation failure or there was an invalid
5284ffbafc53Scomay * privilege token in the string. In either case, return an
5285ffbafc53Scomay * appropriate error code but in the event of an invalid token,
5286ffbafc53Scomay * allocate a string containing its name and return that back to
5287ffbafc53Scomay * the caller.
5288ffbafc53Scomay */
5289ffbafc53Scomay mergeset = priv_str_to_set(tmp, TOKEN_PRIV_STR, &token);
5290ffbafc53Scomay if (mergeset == NULL) {
5291ffbafc53Scomay if (token == NULL)
5292ffbafc53Scomay return (Z_NOMEM);
5293ffbafc53Scomay if ((cp = strchr(token, TOKEN_PRIV_CHAR)) != NULL)
5294ffbafc53Scomay *cp = '\0';
5295ffbafc53Scomay if ((*privname = strdup(token)) == NULL)
5296ffbafc53Scomay return (Z_NOMEM);
5297ffbafc53Scomay else
5298ffbafc53Scomay return (Z_PRIV_UNKNOWN);
5299ffbafc53Scomay }
5300ffbafc53Scomay
5301ffbafc53Scomay /*
5302ffbafc53Scomay * Next, verify that none of the prohibited zone privileges are
5303ffbafc53Scomay * present in the merged privilege set.
5304ffbafc53Scomay */
53059acbbeafSnn35248 for (pnp = plp->pl_prohibited; pnp != NULL; pnp = pnp->pn_next) {
53069acbbeafSnn35248 if (priv_ismember(mergeset, pnp->pn_priv)) {
5307ffbafc53Scomay priv_freeset(mergeset);
53089acbbeafSnn35248 if ((*privname = strdup(pnp->pn_priv)) == NULL)
5309ffbafc53Scomay return (Z_NOMEM);
5310ffbafc53Scomay else
5311ffbafc53Scomay return (Z_PRIV_PROHIBITED);
5312ffbafc53Scomay }
5313ffbafc53Scomay }
5314ffbafc53Scomay
5315ffbafc53Scomay /*
5316ffbafc53Scomay * Finally, verify that all of the required zone privileges are
5317ffbafc53Scomay * present in the merged privilege set.
5318ffbafc53Scomay */
53199acbbeafSnn35248 for (pnp = plp->pl_required; pnp != NULL; pnp = pnp->pn_next) {
53209acbbeafSnn35248 if (!priv_ismember(mergeset, pnp->pn_priv)) {
5321ffbafc53Scomay priv_freeset(mergeset);
53229acbbeafSnn35248 if ((*privname = strdup(pnp->pn_priv)) == NULL)
5323ffbafc53Scomay return (Z_NOMEM);
5324ffbafc53Scomay else
5325ffbafc53Scomay return (Z_PRIV_REQUIRED);
5326ffbafc53Scomay }
5327ffbafc53Scomay }
5328ffbafc53Scomay
5329ffbafc53Scomay priv_copyset(mergeset, privs);
5330ffbafc53Scomay priv_freeset(mergeset);
5331ffbafc53Scomay return (Z_OK);
5332ffbafc53Scomay }
5333ffbafc53Scomay
5334ffbafc53Scomay /*
5335ffbafc53Scomay * Fill in the supplied privilege set with either the default, safe set of
5336ffbafc53Scomay * privileges suitable for a non-global zone, or one based on the
5337ffbafc53Scomay * "limitpriv" property in the zone's configuration.
5338ffbafc53Scomay *
5339ffbafc53Scomay * In the event of an invalid privilege specification in the
5340ffbafc53Scomay * configuration, a string is allocated and returned containing the
5341ffbafc53Scomay * "privilege" causing the issue. It is the caller's responsibility to
5342ffbafc53Scomay * free this memory when it is done with it.
5343ffbafc53Scomay */
5344ffbafc53Scomay int
zonecfg_get_privset(zone_dochandle_t handle,priv_set_t * privs,char ** privname)5345ffbafc53Scomay zonecfg_get_privset(zone_dochandle_t handle, priv_set_t *privs,
5346ffbafc53Scomay char **privname)
5347ffbafc53Scomay {
53489acbbeafSnn35248 priv_lists_t *plp;
53499acbbeafSnn35248 char *cp, *limitpriv = NULL;
53509acbbeafSnn35248 int err, limitlen;
5351bf1d7e28Sdh155122 zone_iptype_t iptype;
5352bf1d7e28Sdh155122 const char *curr_iptype;
5353ffbafc53Scomay
5354ffbafc53Scomay /*
5355ffbafc53Scomay * Attempt to lookup the "limitpriv" property. If it does not
5356ffbafc53Scomay * exist or matches the string DEFAULT_TOKEN exactly, then the
5357ffbafc53Scomay * default, safe privilege set is returned.
5358ffbafc53Scomay */
53599acbbeafSnn35248 if ((err = zonecfg_get_limitpriv(handle, &limitpriv)) != Z_OK)
5360ffbafc53Scomay return (err);
53619acbbeafSnn35248
5362bf1d7e28Sdh155122 if ((err = zonecfg_get_iptype(handle, &iptype)) != Z_OK)
5363bf1d7e28Sdh155122 return (err);
5364bf1d7e28Sdh155122
5365bf1d7e28Sdh155122 switch (iptype) {
5366bf1d7e28Sdh155122 case ZS_SHARED:
5367bf1d7e28Sdh155122 curr_iptype = "shared";
5368bf1d7e28Sdh155122 break;
5369bf1d7e28Sdh155122 case ZS_EXCLUSIVE:
5370bf1d7e28Sdh155122 curr_iptype = "exclusive";
5371bf1d7e28Sdh155122 break;
5372bf1d7e28Sdh155122 }
5373bf1d7e28Sdh155122
5374e5816e35SEdward Pilatowicz if ((err = priv_lists_create(handle, NULL, &plp, curr_iptype)) != Z_OK)
53759acbbeafSnn35248 return (err);
53769acbbeafSnn35248
5377ffbafc53Scomay limitlen = strlen(limitpriv);
5378ffbafc53Scomay if (limitlen == 0 || strcmp(limitpriv, DEFAULT_TOKEN) == 0) {
5379ffbafc53Scomay free(limitpriv);
53809acbbeafSnn35248 err = get_default_privset(privs, plp);
53819acbbeafSnn35248 priv_lists_destroy(plp);
53829acbbeafSnn35248 return (err);
5383ffbafc53Scomay }
5384ffbafc53Scomay
5385ffbafc53Scomay /*
5386ffbafc53Scomay * Check if the string DEFAULT_TOKEN is the first token in a list
5387ffbafc53Scomay * of privileges.
5388ffbafc53Scomay */
5389ffbafc53Scomay cp = strchr(limitpriv, TOKEN_PRIV_CHAR);
5390ffbafc53Scomay if (cp != NULL &&
5391ffbafc53Scomay strncmp(limitpriv, DEFAULT_TOKEN, cp - limitpriv) == 0)
53929acbbeafSnn35248 err = verify_privset(cp + 1, privs, privname, B_TRUE, plp);
5393ffbafc53Scomay else
53949acbbeafSnn35248 err = verify_privset(limitpriv, privs, privname, B_FALSE, plp);
5395ffbafc53Scomay
5396ffbafc53Scomay free(limitpriv);
53979acbbeafSnn35248 priv_lists_destroy(plp);
5398ffbafc53Scomay return (err);
5399ffbafc53Scomay }
5400ffbafc53Scomay
54017c478bd9Sstevel@tonic-gate int
zone_get_zonepath(char * zone_name,char * zonepath,size_t rp_sz)54027c478bd9Sstevel@tonic-gate zone_get_zonepath(char *zone_name, char *zonepath, size_t rp_sz)
54037c478bd9Sstevel@tonic-gate {
54047c478bd9Sstevel@tonic-gate zone_dochandle_t handle;
54057c478bd9Sstevel@tonic-gate boolean_t found = B_FALSE;
54067c478bd9Sstevel@tonic-gate struct zoneent *ze;
54077c478bd9Sstevel@tonic-gate FILE *cookie;
54087c478bd9Sstevel@tonic-gate int err;
5409108322fbScarlsonj char *cp;
54107c478bd9Sstevel@tonic-gate
54117c478bd9Sstevel@tonic-gate if (zone_name == NULL)
54127c478bd9Sstevel@tonic-gate return (Z_INVAL);
54137c478bd9Sstevel@tonic-gate
5414108322fbScarlsonj (void) strlcpy(zonepath, zonecfg_root, rp_sz);
5415108322fbScarlsonj cp = zonepath + strlen(zonepath);
5416108322fbScarlsonj while (cp > zonepath && cp[-1] == '/')
5417108322fbScarlsonj *--cp = '\0';
5418108322fbScarlsonj
54197c478bd9Sstevel@tonic-gate if (strcmp(zone_name, GLOBAL_ZONENAME) == 0) {
5420108322fbScarlsonj if (zonepath[0] == '\0')
54217c478bd9Sstevel@tonic-gate (void) strlcpy(zonepath, "/", rp_sz);
54227c478bd9Sstevel@tonic-gate return (Z_OK);
54237c478bd9Sstevel@tonic-gate }
54247c478bd9Sstevel@tonic-gate
54257c478bd9Sstevel@tonic-gate /*
54267c478bd9Sstevel@tonic-gate * First check the index file. Because older versions did not have
54277c478bd9Sstevel@tonic-gate * a copy of the zone path, allow for it to be zero length, in which
54287c478bd9Sstevel@tonic-gate * case we ignore this result and fall back to the XML files.
54297c478bd9Sstevel@tonic-gate */
54307c478bd9Sstevel@tonic-gate cookie = setzoneent();
54317c478bd9Sstevel@tonic-gate while ((ze = getzoneent_private(cookie)) != NULL) {
54327c478bd9Sstevel@tonic-gate if (strcmp(ze->zone_name, zone_name) == 0) {
54337c478bd9Sstevel@tonic-gate found = B_TRUE;
5434108322fbScarlsonj if (ze->zone_path[0] != '\0')
5435108322fbScarlsonj (void) strlcpy(cp, ze->zone_path,
5436108322fbScarlsonj rp_sz - (cp - zonepath));
54377c478bd9Sstevel@tonic-gate }
54387c478bd9Sstevel@tonic-gate free(ze);
54397c478bd9Sstevel@tonic-gate if (found)
54407c478bd9Sstevel@tonic-gate break;
54417c478bd9Sstevel@tonic-gate }
54427c478bd9Sstevel@tonic-gate endzoneent(cookie);
5443108322fbScarlsonj if (found && *cp != '\0')
54447c478bd9Sstevel@tonic-gate return (Z_OK);
54457c478bd9Sstevel@tonic-gate
54467c478bd9Sstevel@tonic-gate /* Fall back to the XML files. */
54477c478bd9Sstevel@tonic-gate if ((handle = zonecfg_init_handle()) == NULL)
54487c478bd9Sstevel@tonic-gate return (Z_NOMEM);
54497c478bd9Sstevel@tonic-gate
54507c478bd9Sstevel@tonic-gate /*
54517c478bd9Sstevel@tonic-gate * Check the snapshot first: if a zone is running, its zonepath
54527c478bd9Sstevel@tonic-gate * may have changed.
54537c478bd9Sstevel@tonic-gate */
54547c478bd9Sstevel@tonic-gate if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) {
5455e767a340Sgjelinek if ((err = zonecfg_get_handle(zone_name, handle)) != Z_OK) {
5456e767a340Sgjelinek zonecfg_fini_handle(handle);
54577c478bd9Sstevel@tonic-gate return (err);
54587c478bd9Sstevel@tonic-gate }
5459e767a340Sgjelinek }
54607c478bd9Sstevel@tonic-gate err = zonecfg_get_zonepath(handle, zonepath, rp_sz);
54617c478bd9Sstevel@tonic-gate zonecfg_fini_handle(handle);
54627c478bd9Sstevel@tonic-gate return (err);
54637c478bd9Sstevel@tonic-gate }
54647c478bd9Sstevel@tonic-gate
54657c478bd9Sstevel@tonic-gate int
zone_get_rootpath(char * zone_name,char * rootpath,size_t rp_sz)54667c478bd9Sstevel@tonic-gate zone_get_rootpath(char *zone_name, char *rootpath, size_t rp_sz)
54677c478bd9Sstevel@tonic-gate {
54687c478bd9Sstevel@tonic-gate int err;
54697c478bd9Sstevel@tonic-gate
54707c478bd9Sstevel@tonic-gate /* This function makes sense for non-global zones only. */
54717c478bd9Sstevel@tonic-gate if (strcmp(zone_name, GLOBAL_ZONENAME) == 0)
54727c478bd9Sstevel@tonic-gate return (Z_BOGUS_ZONE_NAME);
54737c478bd9Sstevel@tonic-gate if ((err = zone_get_zonepath(zone_name, rootpath, rp_sz)) != Z_OK)
54747c478bd9Sstevel@tonic-gate return (err);
54757c478bd9Sstevel@tonic-gate if (strlcat(rootpath, "/root", rp_sz) >= rp_sz)
54767c478bd9Sstevel@tonic-gate return (Z_TOO_BIG);
54777c478bd9Sstevel@tonic-gate return (Z_OK);
54787c478bd9Sstevel@tonic-gate }
54797c478bd9Sstevel@tonic-gate
54809acbbeafSnn35248 int
zone_get_brand(char * zone_name,char * brandname,size_t rp_sz)54819acbbeafSnn35248 zone_get_brand(char *zone_name, char *brandname, size_t rp_sz)
54829acbbeafSnn35248 {
54839acbbeafSnn35248 int err;
54849acbbeafSnn35248 zone_dochandle_t handle;
54859acbbeafSnn35248 char myzone[MAXNAMELEN];
54869acbbeafSnn35248 int myzoneid = getzoneid();
54879acbbeafSnn35248
54889acbbeafSnn35248 /*
54899acbbeafSnn35248 * If we are not in the global zone, then we don't have the zone
54909acbbeafSnn35248 * .xml files with the brand name available. Thus, we are going to
54919acbbeafSnn35248 * have to ask the kernel for the information.
54929acbbeafSnn35248 */
54939acbbeafSnn35248 if (myzoneid != GLOBAL_ZONEID) {
54942ec67e04Sgjelinek if (is_system_labeled()) {
54952ec67e04Sgjelinek (void) strlcpy(brandname, NATIVE_BRAND_NAME, rp_sz);
54962ec67e04Sgjelinek return (Z_OK);
54972ec67e04Sgjelinek }
54989acbbeafSnn35248 if (zone_getattr(myzoneid, ZONE_ATTR_NAME, myzone,
54999acbbeafSnn35248 sizeof (myzone)) < 0)
55009acbbeafSnn35248 return (Z_NO_ZONE);
55011d6979b7Ssaurabh vyas - Sun Microsystems - Bangalore India if (!zonecfg_is_scratch(myzone)) {
55021d6979b7Ssaurabh vyas - Sun Microsystems - Bangalore India if (strncmp(zone_name, myzone, MAXNAMELEN) != 0)
55039acbbeafSnn35248 return (Z_NO_ZONE);
55041d6979b7Ssaurabh vyas - Sun Microsystems - Bangalore India }
55059acbbeafSnn35248 err = zone_getattr(myzoneid, ZONE_ATTR_BRAND, brandname, rp_sz);
55069acbbeafSnn35248 if (err < 0)
55079acbbeafSnn35248 return ((errno == EFAULT) ? Z_TOO_BIG : Z_INVAL);
55081d6979b7Ssaurabh vyas - Sun Microsystems - Bangalore India
55099acbbeafSnn35248 return (Z_OK);
55109acbbeafSnn35248 }
55119acbbeafSnn35248
5512e5816e35SEdward Pilatowicz if (strcmp(zone_name, "global") == 0)
5513e5816e35SEdward Pilatowicz return (zonecfg_default_brand(brandname, rp_sz));
5514e5816e35SEdward Pilatowicz
55159acbbeafSnn35248 if ((handle = zonecfg_init_handle()) == NULL)
55169acbbeafSnn35248 return (Z_NOMEM);
55179acbbeafSnn35248
55189acbbeafSnn35248 err = zonecfg_get_handle((char *)zone_name, handle);
55199acbbeafSnn35248 if (err == Z_OK)
55209acbbeafSnn35248 err = zonecfg_get_brand(handle, brandname, rp_sz);
55219acbbeafSnn35248
55229acbbeafSnn35248 zonecfg_fini_handle(handle);
55239acbbeafSnn35248 return (err);
55249acbbeafSnn35248 }
55259acbbeafSnn35248
5526facf4a8dSllai1 /*
5527facf4a8dSllai1 * Return the appropriate root for the active /dev.
5528facf4a8dSllai1 * For normal zone, the path is $ZONEPATH/root;
5529facf4a8dSllai1 * for scratch zone, the dev path is $ZONEPATH/lu.
5530facf4a8dSllai1 */
5531facf4a8dSllai1 int
zone_get_devroot(char * zone_name,char * devroot,size_t rp_sz)5532facf4a8dSllai1 zone_get_devroot(char *zone_name, char *devroot, size_t rp_sz)
5533facf4a8dSllai1 {
5534facf4a8dSllai1 int err;
5535facf4a8dSllai1 char *suffix;
5536facf4a8dSllai1 zone_state_t state;
5537facf4a8dSllai1
5538facf4a8dSllai1 /* This function makes sense for non-global zones only. */
5539facf4a8dSllai1 if (strcmp(zone_name, GLOBAL_ZONENAME) == 0)
5540facf4a8dSllai1 return (Z_BOGUS_ZONE_NAME);
5541facf4a8dSllai1 if ((err = zone_get_zonepath(zone_name, devroot, rp_sz)) != Z_OK)
5542facf4a8dSllai1 return (err);
5543facf4a8dSllai1
5544facf4a8dSllai1 if (zone_get_state(zone_name, &state) == Z_OK &&
5545facf4a8dSllai1 state == ZONE_STATE_MOUNTED)
5546facf4a8dSllai1 suffix = "/lu";
5547facf4a8dSllai1 else
5548facf4a8dSllai1 suffix = "/root";
5549facf4a8dSllai1 if (strlcat(devroot, suffix, rp_sz) >= rp_sz)
5550facf4a8dSllai1 return (Z_TOO_BIG);
5551facf4a8dSllai1 return (Z_OK);
5552facf4a8dSllai1 }
5553facf4a8dSllai1
55547c478bd9Sstevel@tonic-gate static zone_state_t
kernel_state_to_user_state(zoneid_t zoneid,zone_status_t kernel_state)5555108322fbScarlsonj kernel_state_to_user_state(zoneid_t zoneid, zone_status_t kernel_state)
55567c478bd9Sstevel@tonic-gate {
5557108322fbScarlsonj char zoneroot[MAXPATHLEN];
5558108322fbScarlsonj size_t zlen;
5559108322fbScarlsonj
55607c478bd9Sstevel@tonic-gate assert(kernel_state <= ZONE_MAX_STATE);
55617c478bd9Sstevel@tonic-gate switch (kernel_state) {
55627c478bd9Sstevel@tonic-gate case ZONE_IS_UNINITIALIZED:
5563bd41d0a8Snordmark case ZONE_IS_INITIALIZED:
5564bd41d0a8Snordmark /* The kernel will not return these two states */
5565108322fbScarlsonj return (ZONE_STATE_READY);
55667c478bd9Sstevel@tonic-gate case ZONE_IS_READY:
5567108322fbScarlsonj /*
5568108322fbScarlsonj * If the zone's root is mounted on $ZONEPATH/lu, then
5569108322fbScarlsonj * it's a mounted scratch zone.
5570108322fbScarlsonj */
5571108322fbScarlsonj if (zone_getattr(zoneid, ZONE_ATTR_ROOT, zoneroot,
5572108322fbScarlsonj sizeof (zoneroot)) >= 0) {
5573108322fbScarlsonj zlen = strlen(zoneroot);
5574108322fbScarlsonj if (zlen > 3 &&
5575108322fbScarlsonj strcmp(zoneroot + zlen - 3, "/lu") == 0)
5576108322fbScarlsonj return (ZONE_STATE_MOUNTED);
5577108322fbScarlsonj }
55787c478bd9Sstevel@tonic-gate return (ZONE_STATE_READY);
55797c478bd9Sstevel@tonic-gate case ZONE_IS_BOOTING:
55807c478bd9Sstevel@tonic-gate case ZONE_IS_RUNNING:
55817c478bd9Sstevel@tonic-gate return (ZONE_STATE_RUNNING);
55827c478bd9Sstevel@tonic-gate case ZONE_IS_SHUTTING_DOWN:
55837c478bd9Sstevel@tonic-gate case ZONE_IS_EMPTY:
55847c478bd9Sstevel@tonic-gate return (ZONE_STATE_SHUTTING_DOWN);
55857c478bd9Sstevel@tonic-gate case ZONE_IS_DOWN:
55867c478bd9Sstevel@tonic-gate case ZONE_IS_DYING:
55877c478bd9Sstevel@tonic-gate case ZONE_IS_DEAD:
55887c478bd9Sstevel@tonic-gate default:
55897c478bd9Sstevel@tonic-gate return (ZONE_STATE_DOWN);
55907c478bd9Sstevel@tonic-gate }
55917c478bd9Sstevel@tonic-gate /* NOTREACHED */
55927c478bd9Sstevel@tonic-gate }
55937c478bd9Sstevel@tonic-gate
55947c478bd9Sstevel@tonic-gate int
zone_get_state(char * zone_name,zone_state_t * state_num)55957c478bd9Sstevel@tonic-gate zone_get_state(char *zone_name, zone_state_t *state_num)
55967c478bd9Sstevel@tonic-gate {
55977c478bd9Sstevel@tonic-gate zone_status_t status;
55987c478bd9Sstevel@tonic-gate zoneid_t zone_id;
55997c478bd9Sstevel@tonic-gate struct zoneent *ze;
56007c478bd9Sstevel@tonic-gate boolean_t found = B_FALSE;
56017c478bd9Sstevel@tonic-gate FILE *cookie;
5602108322fbScarlsonj char kernzone[ZONENAME_MAX];
5603108322fbScarlsonj FILE *fp;
56047c478bd9Sstevel@tonic-gate
56057c478bd9Sstevel@tonic-gate if (zone_name == NULL)
56067c478bd9Sstevel@tonic-gate return (Z_INVAL);
56077c478bd9Sstevel@tonic-gate
5608108322fbScarlsonj /*
5609108322fbScarlsonj * If we're looking at an alternate root, then we need to query the
5610108322fbScarlsonj * kernel using the scratch zone name.
5611108322fbScarlsonj */
5612108322fbScarlsonj zone_id = -1;
5613108322fbScarlsonj if (*zonecfg_root != '\0' && !zonecfg_is_scratch(zone_name)) {
5614108322fbScarlsonj if ((fp = zonecfg_open_scratch("", B_FALSE)) != NULL) {
5615108322fbScarlsonj if (zonecfg_find_scratch(fp, zone_name, zonecfg_root,
5616108322fbScarlsonj kernzone, sizeof (kernzone)) == 0)
5617108322fbScarlsonj zone_id = getzoneidbyname(kernzone);
5618108322fbScarlsonj zonecfg_close_scratch(fp);
5619108322fbScarlsonj }
5620108322fbScarlsonj } else {
5621108322fbScarlsonj zone_id = getzoneidbyname(zone_name);
5622108322fbScarlsonj }
5623108322fbScarlsonj
56247c478bd9Sstevel@tonic-gate /* check to see if zone is running */
5625108322fbScarlsonj if (zone_id != -1 &&
56267c478bd9Sstevel@tonic-gate zone_getattr(zone_id, ZONE_ATTR_STATUS, &status,
56277c478bd9Sstevel@tonic-gate sizeof (status)) >= 0) {
5628108322fbScarlsonj *state_num = kernel_state_to_user_state(zone_id, status);
56297c478bd9Sstevel@tonic-gate return (Z_OK);
56307c478bd9Sstevel@tonic-gate }
56317c478bd9Sstevel@tonic-gate
56327c478bd9Sstevel@tonic-gate cookie = setzoneent();
56337c478bd9Sstevel@tonic-gate while ((ze = getzoneent_private(cookie)) != NULL) {
56347c478bd9Sstevel@tonic-gate if (strcmp(ze->zone_name, zone_name) == 0) {
56357c478bd9Sstevel@tonic-gate found = B_TRUE;
56367c478bd9Sstevel@tonic-gate *state_num = ze->zone_state;
56377c478bd9Sstevel@tonic-gate }
56387c478bd9Sstevel@tonic-gate free(ze);
56397c478bd9Sstevel@tonic-gate if (found)
56407c478bd9Sstevel@tonic-gate break;
56417c478bd9Sstevel@tonic-gate }
56427c478bd9Sstevel@tonic-gate endzoneent(cookie);
56437c478bd9Sstevel@tonic-gate return ((found) ? Z_OK : Z_NO_ZONE);
56447c478bd9Sstevel@tonic-gate }
56457c478bd9Sstevel@tonic-gate
56467c478bd9Sstevel@tonic-gate int
zone_set_state(char * zone,zone_state_t state)56477c478bd9Sstevel@tonic-gate zone_set_state(char *zone, zone_state_t state)
56487c478bd9Sstevel@tonic-gate {
56497c478bd9Sstevel@tonic-gate struct zoneent ze;
56507c478bd9Sstevel@tonic-gate
56517c478bd9Sstevel@tonic-gate if (state != ZONE_STATE_CONFIGURED && state != ZONE_STATE_INSTALLED &&
56527c478bd9Sstevel@tonic-gate state != ZONE_STATE_INCOMPLETE)
56537c478bd9Sstevel@tonic-gate return (Z_INVAL);
56547c478bd9Sstevel@tonic-gate
5655087719fdSdp bzero(&ze, sizeof (ze));
56567c478bd9Sstevel@tonic-gate (void) strlcpy(ze.zone_name, zone, sizeof (ze.zone_name));
56577c478bd9Sstevel@tonic-gate ze.zone_state = state;
56587c478bd9Sstevel@tonic-gate (void) strlcpy(ze.zone_path, "", sizeof (ze.zone_path));
56597c478bd9Sstevel@tonic-gate return (putzoneent(&ze, PZE_MODIFY));
56607c478bd9Sstevel@tonic-gate }
56617c478bd9Sstevel@tonic-gate
56627c478bd9Sstevel@tonic-gate /*
56637c478bd9Sstevel@tonic-gate * Get id (if any) for specified zone. There are four possible outcomes:
56647c478bd9Sstevel@tonic-gate * - If the string corresponds to the numeric id of an active (booted)
56657c478bd9Sstevel@tonic-gate * zone, sets *zip to the zone id and returns 0.
56667c478bd9Sstevel@tonic-gate * - If the string corresponds to the name of an active (booted) zone,
56677c478bd9Sstevel@tonic-gate * sets *zip to the zone id and returns 0.
56687c478bd9Sstevel@tonic-gate * - If the string is a name in the configuration but is not booted,
56697c478bd9Sstevel@tonic-gate * sets *zip to ZONE_ID_UNDEFINED and returns 0.
56707c478bd9Sstevel@tonic-gate * - Otherwise, leaves *zip unchanged and returns -1.
56717c478bd9Sstevel@tonic-gate *
56727c478bd9Sstevel@tonic-gate * This function acts as an auxiliary filter on the function of the same
56737c478bd9Sstevel@tonic-gate * name in libc; the linker binds to this version if libzonecfg exists,
56747c478bd9Sstevel@tonic-gate * and the libc version if it doesn't. Any changes to this version of
56757c478bd9Sstevel@tonic-gate * the function should probably be reflected in the libc version as well.
56767c478bd9Sstevel@tonic-gate */
56777c478bd9Sstevel@tonic-gate int
zone_get_id(const char * str,zoneid_t * zip)56787c478bd9Sstevel@tonic-gate zone_get_id(const char *str, zoneid_t *zip)
56797c478bd9Sstevel@tonic-gate {
56807c478bd9Sstevel@tonic-gate zone_dochandle_t hdl;
56817c478bd9Sstevel@tonic-gate zoneid_t zoneid;
56827c478bd9Sstevel@tonic-gate char *cp;
56837c478bd9Sstevel@tonic-gate int err;
56847c478bd9Sstevel@tonic-gate
56857c478bd9Sstevel@tonic-gate /* first try looking for active zone by id */
56867c478bd9Sstevel@tonic-gate errno = 0;
56877c478bd9Sstevel@tonic-gate zoneid = (zoneid_t)strtol(str, &cp, 0);
56887c478bd9Sstevel@tonic-gate if (errno == 0 && cp != str && *cp == '\0' &&
56897c478bd9Sstevel@tonic-gate getzonenamebyid(zoneid, NULL, 0) != -1) {
56907c478bd9Sstevel@tonic-gate *zip = zoneid;
56917c478bd9Sstevel@tonic-gate return (0);
56927c478bd9Sstevel@tonic-gate }
56937c478bd9Sstevel@tonic-gate
56947c478bd9Sstevel@tonic-gate /* then look for active zone by name */
56957c478bd9Sstevel@tonic-gate if ((zoneid = getzoneidbyname(str)) != -1) {
56967c478bd9Sstevel@tonic-gate *zip = zoneid;
56977c478bd9Sstevel@tonic-gate return (0);
56987c478bd9Sstevel@tonic-gate }
56997c478bd9Sstevel@tonic-gate
57007c478bd9Sstevel@tonic-gate /* if in global zone, try looking up name in configuration database */
57017c478bd9Sstevel@tonic-gate if (getzoneid() != GLOBAL_ZONEID ||
57027c478bd9Sstevel@tonic-gate (hdl = zonecfg_init_handle()) == NULL)
57037c478bd9Sstevel@tonic-gate return (-1);
57047c478bd9Sstevel@tonic-gate
5705108322fbScarlsonj if (zonecfg_get_handle(str, hdl) == Z_OK) {
57067c478bd9Sstevel@tonic-gate /* zone exists but isn't active */
57077c478bd9Sstevel@tonic-gate *zip = ZONE_ID_UNDEFINED;
57087c478bd9Sstevel@tonic-gate err = 0;
57097c478bd9Sstevel@tonic-gate } else {
57107c478bd9Sstevel@tonic-gate err = -1;
57117c478bd9Sstevel@tonic-gate }
57127c478bd9Sstevel@tonic-gate
57137c478bd9Sstevel@tonic-gate zonecfg_fini_handle(hdl);
57147c478bd9Sstevel@tonic-gate return (err);
57157c478bd9Sstevel@tonic-gate }
57167c478bd9Sstevel@tonic-gate
57177c478bd9Sstevel@tonic-gate char *
zone_state_str(zone_state_t state_num)57187c478bd9Sstevel@tonic-gate zone_state_str(zone_state_t state_num)
57197c478bd9Sstevel@tonic-gate {
57207c478bd9Sstevel@tonic-gate switch (state_num) {
57217c478bd9Sstevel@tonic-gate case ZONE_STATE_CONFIGURED:
57227c478bd9Sstevel@tonic-gate return (ZONE_STATE_STR_CONFIGURED);
57237c478bd9Sstevel@tonic-gate case ZONE_STATE_INCOMPLETE:
57247c478bd9Sstevel@tonic-gate return (ZONE_STATE_STR_INCOMPLETE);
57257c478bd9Sstevel@tonic-gate case ZONE_STATE_INSTALLED:
57267c478bd9Sstevel@tonic-gate return (ZONE_STATE_STR_INSTALLED);
57277c478bd9Sstevel@tonic-gate case ZONE_STATE_READY:
57287c478bd9Sstevel@tonic-gate return (ZONE_STATE_STR_READY);
5729108322fbScarlsonj case ZONE_STATE_MOUNTED:
5730108322fbScarlsonj return (ZONE_STATE_STR_MOUNTED);
57317c478bd9Sstevel@tonic-gate case ZONE_STATE_RUNNING:
57327c478bd9Sstevel@tonic-gate return (ZONE_STATE_STR_RUNNING);
57337c478bd9Sstevel@tonic-gate case ZONE_STATE_SHUTTING_DOWN:
57347c478bd9Sstevel@tonic-gate return (ZONE_STATE_STR_SHUTTING_DOWN);
57357c478bd9Sstevel@tonic-gate case ZONE_STATE_DOWN:
57367c478bd9Sstevel@tonic-gate return (ZONE_STATE_STR_DOWN);
57377c478bd9Sstevel@tonic-gate default:
57387c478bd9Sstevel@tonic-gate return ("unknown");
57397c478bd9Sstevel@tonic-gate }
57407c478bd9Sstevel@tonic-gate }
57417c478bd9Sstevel@tonic-gate
57427c478bd9Sstevel@tonic-gate /*
5743108322fbScarlsonj * Given a UUID value, find an associated zone name. This is intended to be
5744108322fbScarlsonj * used by callers who set up some 'default' name (corresponding to the
5745108322fbScarlsonj * expected name for the zone) in the zonename buffer, and thus the function
5746108322fbScarlsonj * doesn't touch this buffer on failure.
5747108322fbScarlsonj */
5748108322fbScarlsonj int
zonecfg_get_name_by_uuid(const uuid_t uuidin,char * zonename,size_t namelen)5749555afedfScarlsonj zonecfg_get_name_by_uuid(const uuid_t uuidin, char *zonename, size_t namelen)
5750108322fbScarlsonj {
5751108322fbScarlsonj FILE *fp;
5752108322fbScarlsonj struct zoneent *ze;
5753555afedfScarlsonj uchar_t *uuid;
5754108322fbScarlsonj
5755108322fbScarlsonj /*
5756108322fbScarlsonj * A small amount of subterfuge via casts is necessary here because
5757108322fbScarlsonj * libuuid doesn't use const correctly, but we don't want to export
5758108322fbScarlsonj * this brokenness to our clients.
5759108322fbScarlsonj */
5760555afedfScarlsonj uuid = (uchar_t *)uuidin;
5761555afedfScarlsonj if (uuid_is_null(uuid))
5762108322fbScarlsonj return (Z_NO_ZONE);
5763108322fbScarlsonj if ((fp = setzoneent()) == NULL)
5764108322fbScarlsonj return (Z_NO_ZONE);
5765108322fbScarlsonj while ((ze = getzoneent_private(fp)) != NULL) {
5766555afedfScarlsonj if (uuid_compare(uuid, ze->zone_uuid) == 0)
5767108322fbScarlsonj break;
5768108322fbScarlsonj free(ze);
5769108322fbScarlsonj }
5770108322fbScarlsonj endzoneent(fp);
5771108322fbScarlsonj if (ze != NULL) {
5772108322fbScarlsonj (void) strlcpy(zonename, ze->zone_name, namelen);
5773108322fbScarlsonj free(ze);
5774108322fbScarlsonj return (Z_OK);
5775108322fbScarlsonj } else {
5776108322fbScarlsonj return (Z_NO_ZONE);
5777108322fbScarlsonj }
5778108322fbScarlsonj }
5779108322fbScarlsonj
5780108322fbScarlsonj /*
5781108322fbScarlsonj * Given a zone name, get its UUID. Returns a "NULL" UUID value if the zone
5782108322fbScarlsonj * exists but the file doesn't have a value set yet. Returns an error if the
5783108322fbScarlsonj * zone cannot be located.
5784108322fbScarlsonj */
5785108322fbScarlsonj int
zonecfg_get_uuid(const char * zonename,uuid_t uuid)5786108322fbScarlsonj zonecfg_get_uuid(const char *zonename, uuid_t uuid)
5787108322fbScarlsonj {
5788108322fbScarlsonj FILE *fp;
5789108322fbScarlsonj struct zoneent *ze;
5790108322fbScarlsonj
5791108322fbScarlsonj if ((fp = setzoneent()) == NULL)
5792108322fbScarlsonj return (Z_NO_ZONE);
5793108322fbScarlsonj while ((ze = getzoneent_private(fp)) != NULL) {
5794108322fbScarlsonj if (strcmp(ze->zone_name, zonename) == 0)
5795108322fbScarlsonj break;
5796108322fbScarlsonj free(ze);
5797108322fbScarlsonj }
5798108322fbScarlsonj endzoneent(fp);
5799108322fbScarlsonj if (ze != NULL) {
5800108322fbScarlsonj uuid_copy(uuid, ze->zone_uuid);
5801108322fbScarlsonj free(ze);
5802108322fbScarlsonj return (Z_OK);
5803108322fbScarlsonj } else {
5804108322fbScarlsonj return (Z_NO_ZONE);
5805108322fbScarlsonj }
5806108322fbScarlsonj }
5807108322fbScarlsonj
5808108322fbScarlsonj /*
58097c478bd9Sstevel@tonic-gate * File-system convenience functions.
58107c478bd9Sstevel@tonic-gate */
58117c478bd9Sstevel@tonic-gate boolean_t
zonecfg_valid_fs_type(const char * type)58127c478bd9Sstevel@tonic-gate zonecfg_valid_fs_type(const char *type)
58137c478bd9Sstevel@tonic-gate {
58147c478bd9Sstevel@tonic-gate /*
58157c478bd9Sstevel@tonic-gate * We already know which FS types don't work.
58167c478bd9Sstevel@tonic-gate */
58177c478bd9Sstevel@tonic-gate if (strcmp(type, "proc") == 0 ||
58187c478bd9Sstevel@tonic-gate strcmp(type, "mntfs") == 0 ||
58197c478bd9Sstevel@tonic-gate strcmp(type, "autofs") == 0 ||
58207c478bd9Sstevel@tonic-gate strncmp(type, "nfs", sizeof ("nfs") - 1) == 0 ||
58217c478bd9Sstevel@tonic-gate strcmp(type, "cachefs") == 0)
58227c478bd9Sstevel@tonic-gate return (B_FALSE);
58237c478bd9Sstevel@tonic-gate /*
58247c478bd9Sstevel@tonic-gate * The caller may do more detailed verification to make sure other
58257c478bd9Sstevel@tonic-gate * aspects of this filesystem type make sense.
58267c478bd9Sstevel@tonic-gate */
58277c478bd9Sstevel@tonic-gate return (B_TRUE);
58287c478bd9Sstevel@tonic-gate }
58297c478bd9Sstevel@tonic-gate
58307c478bd9Sstevel@tonic-gate /*
58317c478bd9Sstevel@tonic-gate * Generally uninteresting rctl convenience functions.
58327c478bd9Sstevel@tonic-gate */
58337c478bd9Sstevel@tonic-gate
58347c478bd9Sstevel@tonic-gate int
zonecfg_construct_rctlblk(const struct zone_rctlvaltab * rctlval,rctlblk_t * rctlblk)58357c478bd9Sstevel@tonic-gate zonecfg_construct_rctlblk(const struct zone_rctlvaltab *rctlval,
58367c478bd9Sstevel@tonic-gate rctlblk_t *rctlblk)
58377c478bd9Sstevel@tonic-gate {
58387c478bd9Sstevel@tonic-gate unsigned long long ull;
58397c478bd9Sstevel@tonic-gate char *endp;
58407c478bd9Sstevel@tonic-gate rctl_priv_t priv;
58417c478bd9Sstevel@tonic-gate rctl_qty_t limit;
58427c478bd9Sstevel@tonic-gate uint_t action;
58437c478bd9Sstevel@tonic-gate
58447c478bd9Sstevel@tonic-gate /* Get the privilege */
58457c478bd9Sstevel@tonic-gate if (strcmp(rctlval->zone_rctlval_priv, "basic") == 0) {
58467c478bd9Sstevel@tonic-gate priv = RCPRIV_BASIC;
58477c478bd9Sstevel@tonic-gate } else if (strcmp(rctlval->zone_rctlval_priv, "privileged") == 0) {
58487c478bd9Sstevel@tonic-gate priv = RCPRIV_PRIVILEGED;
58497c478bd9Sstevel@tonic-gate } else {
58507c478bd9Sstevel@tonic-gate /* Invalid privilege */
58517c478bd9Sstevel@tonic-gate return (Z_INVAL);
58527c478bd9Sstevel@tonic-gate }
58537c478bd9Sstevel@tonic-gate
58547c478bd9Sstevel@tonic-gate /* deal with negative input; strtoull(3c) doesn't do what we want */
58557c478bd9Sstevel@tonic-gate if (rctlval->zone_rctlval_limit[0] == '-')
58567c478bd9Sstevel@tonic-gate return (Z_INVAL);
58577c478bd9Sstevel@tonic-gate /* Get the limit */
58587c478bd9Sstevel@tonic-gate errno = 0;
58597c478bd9Sstevel@tonic-gate ull = strtoull(rctlval->zone_rctlval_limit, &endp, 0);
58607c478bd9Sstevel@tonic-gate if (errno != 0 || *endp != '\0') {
58617c478bd9Sstevel@tonic-gate /* parse failed */
58627c478bd9Sstevel@tonic-gate return (Z_INVAL);
58637c478bd9Sstevel@tonic-gate }
58647c478bd9Sstevel@tonic-gate limit = (rctl_qty_t)ull;
58657c478bd9Sstevel@tonic-gate
58667c478bd9Sstevel@tonic-gate /* Get the action */
58677c478bd9Sstevel@tonic-gate if (strcmp(rctlval->zone_rctlval_action, "none") == 0) {
58687c478bd9Sstevel@tonic-gate action = RCTL_LOCAL_NOACTION;
58697c478bd9Sstevel@tonic-gate } else if (strcmp(rctlval->zone_rctlval_action, "signal") == 0) {
58707c478bd9Sstevel@tonic-gate action = RCTL_LOCAL_SIGNAL;
58717c478bd9Sstevel@tonic-gate } else if (strcmp(rctlval->zone_rctlval_action, "deny") == 0) {
58727c478bd9Sstevel@tonic-gate action = RCTL_LOCAL_DENY;
58737c478bd9Sstevel@tonic-gate } else {
58747c478bd9Sstevel@tonic-gate /* Invalid Action */
58757c478bd9Sstevel@tonic-gate return (Z_INVAL);
58767c478bd9Sstevel@tonic-gate }
58777c478bd9Sstevel@tonic-gate rctlblk_set_local_action(rctlblk, action, 0);
58787c478bd9Sstevel@tonic-gate rctlblk_set_privilege(rctlblk, priv);
58797c478bd9Sstevel@tonic-gate rctlblk_set_value(rctlblk, limit);
58807c478bd9Sstevel@tonic-gate return (Z_OK);
58817c478bd9Sstevel@tonic-gate }
58827c478bd9Sstevel@tonic-gate
58837c478bd9Sstevel@tonic-gate static int
rctl_check(const char * rctlname,void * arg)58847c478bd9Sstevel@tonic-gate rctl_check(const char *rctlname, void *arg)
58857c478bd9Sstevel@tonic-gate {
58867c478bd9Sstevel@tonic-gate const char *attrname = arg;
58877c478bd9Sstevel@tonic-gate
58887c478bd9Sstevel@tonic-gate /*
58897c478bd9Sstevel@tonic-gate * Returning 1 here is our signal to zonecfg_is_rctl() that it is
58907c478bd9Sstevel@tonic-gate * indeed an rctl name recognized by the system.
58917c478bd9Sstevel@tonic-gate */
58927c478bd9Sstevel@tonic-gate return (strcmp(rctlname, attrname) == 0 ? 1 : 0);
58937c478bd9Sstevel@tonic-gate }
58947c478bd9Sstevel@tonic-gate
58957c478bd9Sstevel@tonic-gate boolean_t
zonecfg_is_rctl(const char * name)58967c478bd9Sstevel@tonic-gate zonecfg_is_rctl(const char *name)
58977c478bd9Sstevel@tonic-gate {
58987c478bd9Sstevel@tonic-gate return (rctl_walk(rctl_check, (void *)name) == 1);
58997c478bd9Sstevel@tonic-gate }
59007c478bd9Sstevel@tonic-gate
59017c478bd9Sstevel@tonic-gate boolean_t
zonecfg_valid_rctlname(const char * name)59027c478bd9Sstevel@tonic-gate zonecfg_valid_rctlname(const char *name)
59037c478bd9Sstevel@tonic-gate {
59047c478bd9Sstevel@tonic-gate const char *c;
59057c478bd9Sstevel@tonic-gate
59067c478bd9Sstevel@tonic-gate if (strncmp(name, "zone.", sizeof ("zone.") - 1) != 0)
59077c478bd9Sstevel@tonic-gate return (B_FALSE);
59087c478bd9Sstevel@tonic-gate if (strlen(name) == sizeof ("zone.") - 1)
59097c478bd9Sstevel@tonic-gate return (B_FALSE);
59107c478bd9Sstevel@tonic-gate for (c = name + sizeof ("zone.") - 1; *c != '\0'; c++) {
59117c478bd9Sstevel@tonic-gate if (!isalpha(*c) && *c != '-')
59127c478bd9Sstevel@tonic-gate return (B_FALSE);
59137c478bd9Sstevel@tonic-gate }
59147c478bd9Sstevel@tonic-gate return (B_TRUE);
59157c478bd9Sstevel@tonic-gate }
59167c478bd9Sstevel@tonic-gate
59177c478bd9Sstevel@tonic-gate boolean_t
zonecfg_valid_rctlblk(const rctlblk_t * rctlblk)59187c478bd9Sstevel@tonic-gate zonecfg_valid_rctlblk(const rctlblk_t *rctlblk)
59197c478bd9Sstevel@tonic-gate {
59207c478bd9Sstevel@tonic-gate rctl_priv_t priv = rctlblk_get_privilege((rctlblk_t *)rctlblk);
59217c478bd9Sstevel@tonic-gate uint_t action = rctlblk_get_local_action((rctlblk_t *)rctlblk, NULL);
59227c478bd9Sstevel@tonic-gate
59237c478bd9Sstevel@tonic-gate if (priv != RCPRIV_PRIVILEGED)
59247c478bd9Sstevel@tonic-gate return (B_FALSE);
59257c478bd9Sstevel@tonic-gate if (action != RCTL_LOCAL_NOACTION && action != RCTL_LOCAL_DENY)
59267c478bd9Sstevel@tonic-gate return (B_FALSE);
59277c478bd9Sstevel@tonic-gate return (B_TRUE);
59287c478bd9Sstevel@tonic-gate }
59297c478bd9Sstevel@tonic-gate
59307c478bd9Sstevel@tonic-gate boolean_t
zonecfg_valid_rctl(const char * name,const rctlblk_t * rctlblk)59317c478bd9Sstevel@tonic-gate zonecfg_valid_rctl(const char *name, const rctlblk_t *rctlblk)
59327c478bd9Sstevel@tonic-gate {
59337c478bd9Sstevel@tonic-gate rctlblk_t *current, *next;
59347c478bd9Sstevel@tonic-gate rctl_qty_t limit = rctlblk_get_value((rctlblk_t *)rctlblk);
59357c478bd9Sstevel@tonic-gate uint_t action = rctlblk_get_local_action((rctlblk_t *)rctlblk, NULL);
59367c478bd9Sstevel@tonic-gate uint_t global_flags;
59377c478bd9Sstevel@tonic-gate
59387c478bd9Sstevel@tonic-gate if (!zonecfg_valid_rctlblk(rctlblk))
59397c478bd9Sstevel@tonic-gate return (B_FALSE);
59407c478bd9Sstevel@tonic-gate if (!zonecfg_valid_rctlname(name))
59417c478bd9Sstevel@tonic-gate return (B_FALSE);
59427c478bd9Sstevel@tonic-gate
59437c478bd9Sstevel@tonic-gate current = alloca(rctlblk_size());
59447c478bd9Sstevel@tonic-gate if (getrctl(name, NULL, current, RCTL_FIRST) != 0)
59457c478bd9Sstevel@tonic-gate return (B_TRUE); /* not an rctl on this system */
59467c478bd9Sstevel@tonic-gate /*
59477c478bd9Sstevel@tonic-gate * Make sure the proposed value isn't greater than the current system
59487c478bd9Sstevel@tonic-gate * value.
59497c478bd9Sstevel@tonic-gate */
59507c478bd9Sstevel@tonic-gate next = alloca(rctlblk_size());
59517c478bd9Sstevel@tonic-gate while (rctlblk_get_privilege(current) != RCPRIV_SYSTEM) {
59527c478bd9Sstevel@tonic-gate rctlblk_t *tmp;
59537c478bd9Sstevel@tonic-gate
59547c478bd9Sstevel@tonic-gate if (getrctl(name, current, next, RCTL_NEXT) != 0)
59557c478bd9Sstevel@tonic-gate return (B_FALSE); /* shouldn't happen */
59567c478bd9Sstevel@tonic-gate tmp = current;
59577c478bd9Sstevel@tonic-gate current = next;
59587c478bd9Sstevel@tonic-gate next = tmp;
59597c478bd9Sstevel@tonic-gate }
59607c478bd9Sstevel@tonic-gate if (limit > rctlblk_get_value(current))
59617c478bd9Sstevel@tonic-gate return (B_FALSE);
59627c478bd9Sstevel@tonic-gate
59637c478bd9Sstevel@tonic-gate /*
59647c478bd9Sstevel@tonic-gate * Make sure the proposed action is allowed.
59657c478bd9Sstevel@tonic-gate */
59667c478bd9Sstevel@tonic-gate global_flags = rctlblk_get_global_flags(current);
59677c478bd9Sstevel@tonic-gate if ((global_flags & RCTL_GLOBAL_DENY_NEVER) &&
59687c478bd9Sstevel@tonic-gate action == RCTL_LOCAL_DENY)
59697c478bd9Sstevel@tonic-gate return (B_FALSE);
59707c478bd9Sstevel@tonic-gate if ((global_flags & RCTL_GLOBAL_DENY_ALWAYS) &&
59717c478bd9Sstevel@tonic-gate action == RCTL_LOCAL_NOACTION)
59727c478bd9Sstevel@tonic-gate return (B_FALSE);
59737c478bd9Sstevel@tonic-gate
59747c478bd9Sstevel@tonic-gate return (B_TRUE);
59757c478bd9Sstevel@tonic-gate }
5976fa9e4066Sahrens
5977cf8f45c7Sdstaff /*
5978cf8f45c7Sdstaff * There is always a race condition between reading the initial copy of
5979cf8f45c7Sdstaff * a zones state and its state changing. We address this by providing
5980cf8f45c7Sdstaff * zonecfg_notify_critical_enter and zonecfg_noticy_critical_exit functions.
5981cf8f45c7Sdstaff * When zonecfg_critical_enter is called, sets the state field to LOCKED
5982cf8f45c7Sdstaff * and aquires biglock. Biglock protects against other threads executing
5983cf8f45c7Sdstaff * critical_enter and the state field protects against state changes during
5984cf8f45c7Sdstaff * the critical period.
5985cf8f45c7Sdstaff *
5986cf8f45c7Sdstaff * If any state changes occur, zn_cb will set the failed field of the znotify
5987cf8f45c7Sdstaff * structure. This will cause the critical_exit function to re-lock the
5988cf8f45c7Sdstaff * channel and return an error. Since evsnts may be delayed, the critical_exit
5989cf8f45c7Sdstaff * function "flushes" the queue by putting an event on the queue and waiting for
5990cf8f45c7Sdstaff * zn_cb to notify critical_exit that it received the ping event.
5991cf8f45c7Sdstaff */
5992cf8f45c7Sdstaff static const char *
string_get_tok(const char * in,char delim,int num)5993cf8f45c7Sdstaff string_get_tok(const char *in, char delim, int num)
5994cf8f45c7Sdstaff {
5995cf8f45c7Sdstaff int i = 0;
5996cf8f45c7Sdstaff
5997cf8f45c7Sdstaff for (; i < num; in++) {
5998cf8f45c7Sdstaff if (*in == delim)
5999cf8f45c7Sdstaff i++;
6000cf8f45c7Sdstaff if (*in == 0)
6001cf8f45c7Sdstaff return (NULL);
6002cf8f45c7Sdstaff }
6003cf8f45c7Sdstaff return (in);
6004cf8f45c7Sdstaff }
6005cf8f45c7Sdstaff
6006cf8f45c7Sdstaff static boolean_t
is_ping(sysevent_t * ev)6007cf8f45c7Sdstaff is_ping(sysevent_t *ev)
6008cf8f45c7Sdstaff {
6009cf8f45c7Sdstaff if (strcmp(sysevent_get_subclass_name(ev),
6010cf8f45c7Sdstaff ZONE_EVENT_PING_SUBCLASS) == 0) {
6011cf8f45c7Sdstaff return (B_TRUE);
6012cf8f45c7Sdstaff } else {
6013cf8f45c7Sdstaff return (B_FALSE);
6014cf8f45c7Sdstaff }
6015cf8f45c7Sdstaff }
6016cf8f45c7Sdstaff
6017cf8f45c7Sdstaff static boolean_t
is_my_ping(sysevent_t * ev)6018cf8f45c7Sdstaff is_my_ping(sysevent_t *ev)
6019cf8f45c7Sdstaff {
6020cf8f45c7Sdstaff const char *sender;
6021cf8f45c7Sdstaff char mypid[sizeof (pid_t) * 3 + 1];
6022cf8f45c7Sdstaff
6023cf8f45c7Sdstaff (void) snprintf(mypid, sizeof (mypid), "%i", getpid());
6024cf8f45c7Sdstaff sender = string_get_tok(sysevent_get_pub(ev), ':', 3);
6025cf8f45c7Sdstaff if (sender == NULL)
6026cf8f45c7Sdstaff return (B_FALSE);
6027cf8f45c7Sdstaff if (strcmp(sender, mypid) != 0)
6028cf8f45c7Sdstaff return (B_FALSE);
6029cf8f45c7Sdstaff return (B_TRUE);
6030cf8f45c7Sdstaff }
6031cf8f45c7Sdstaff
6032cf8f45c7Sdstaff static int
do_callback(struct znotify * zevtchan,sysevent_t * ev)6033cf8f45c7Sdstaff do_callback(struct znotify *zevtchan, sysevent_t *ev)
6034cf8f45c7Sdstaff {
6035cf8f45c7Sdstaff nvlist_t *l;
6036cf8f45c7Sdstaff int zid;
6037cf8f45c7Sdstaff char *zonename;
6038cf8f45c7Sdstaff char *newstate;
6039cf8f45c7Sdstaff char *oldstate;
6040cf8f45c7Sdstaff int ret;
6041cf8f45c7Sdstaff hrtime_t when;
6042cf8f45c7Sdstaff
6043cf8f45c7Sdstaff if (strcmp(sysevent_get_subclass_name(ev),
6044cf8f45c7Sdstaff ZONE_EVENT_STATUS_SUBCLASS) == 0) {
6045cf8f45c7Sdstaff
6046cf8f45c7Sdstaff if (sysevent_get_attr_list(ev, &l) != 0) {
6047cf8f45c7Sdstaff if (errno == ENOMEM) {
6048cf8f45c7Sdstaff zevtchan->zn_failure_count++;
6049cf8f45c7Sdstaff return (EAGAIN);
6050cf8f45c7Sdstaff }
6051cf8f45c7Sdstaff return (0);
6052cf8f45c7Sdstaff }
6053cf8f45c7Sdstaff ret = 0;
6054cf8f45c7Sdstaff
6055cf8f45c7Sdstaff if ((nvlist_lookup_string(l, ZONE_CB_NAME, &zonename) == 0) &&
6056cf8f45c7Sdstaff (nvlist_lookup_string(l, ZONE_CB_NEWSTATE, &newstate)
6057cf8f45c7Sdstaff == 0) &&
6058cf8f45c7Sdstaff (nvlist_lookup_string(l, ZONE_CB_OLDSTATE, &oldstate)
6059cf8f45c7Sdstaff == 0) &&
6060cf8f45c7Sdstaff (nvlist_lookup_uint64(l, ZONE_CB_TIMESTAMP,
6061cf8f45c7Sdstaff (uint64_t *)&when) == 0) &&
6062cf8f45c7Sdstaff (nvlist_lookup_int32(l, ZONE_CB_ZONEID, &zid) == 0)) {
6063cf8f45c7Sdstaff ret = zevtchan->zn_callback(zonename, zid, newstate,
6064cf8f45c7Sdstaff oldstate, when, zevtchan->zn_private);
6065cf8f45c7Sdstaff }
6066cf8f45c7Sdstaff
6067cf8f45c7Sdstaff zevtchan->zn_failure_count = 0;
6068cf8f45c7Sdstaff nvlist_free(l);
6069cf8f45c7Sdstaff return (ret);
6070cf8f45c7Sdstaff } else {
6071cf8f45c7Sdstaff /*
6072cf8f45c7Sdstaff * We have received an event in an unknown subclass. Ignore.
6073cf8f45c7Sdstaff */
6074cf8f45c7Sdstaff zevtchan->zn_failure_count = 0;
6075cf8f45c7Sdstaff return (0);
6076cf8f45c7Sdstaff }
6077cf8f45c7Sdstaff }
6078cf8f45c7Sdstaff
6079cf8f45c7Sdstaff static int
zn_cb(sysevent_t * ev,void * p)6080cf8f45c7Sdstaff zn_cb(sysevent_t *ev, void *p)
6081cf8f45c7Sdstaff {
6082cf8f45c7Sdstaff struct znotify *zevtchan = p;
6083cf8f45c7Sdstaff int error;
6084cf8f45c7Sdstaff
6085cf8f45c7Sdstaff (void) pthread_mutex_lock(&(zevtchan->zn_mutex));
6086cf8f45c7Sdstaff
6087cf8f45c7Sdstaff if (is_ping(ev) && !is_my_ping(ev)) {
6088cf8f45c7Sdstaff (void) pthread_mutex_unlock((&zevtchan->zn_mutex));
6089cf8f45c7Sdstaff return (0);
6090cf8f45c7Sdstaff }
6091cf8f45c7Sdstaff
6092cf8f45c7Sdstaff if (zevtchan->zn_state == ZN_LOCKED) {
6093cf8f45c7Sdstaff assert(!is_ping(ev));
6094cf8f45c7Sdstaff zevtchan->zn_failed = B_TRUE;
6095cf8f45c7Sdstaff (void) pthread_mutex_unlock(&(zevtchan->zn_mutex));
6096cf8f45c7Sdstaff return (0);
6097cf8f45c7Sdstaff }
6098cf8f45c7Sdstaff
6099cf8f45c7Sdstaff if (zevtchan->zn_state == ZN_PING_INFLIGHT) {
6100cf8f45c7Sdstaff if (is_ping(ev)) {
6101cf8f45c7Sdstaff zevtchan->zn_state = ZN_PING_RECEIVED;
6102cf8f45c7Sdstaff (void) pthread_cond_signal(&(zevtchan->zn_cond));
6103cf8f45c7Sdstaff (void) pthread_mutex_unlock(&(zevtchan->zn_mutex));
6104cf8f45c7Sdstaff return (0);
6105cf8f45c7Sdstaff } else {
6106cf8f45c7Sdstaff zevtchan->zn_failed = B_TRUE;
6107cf8f45c7Sdstaff (void) pthread_mutex_unlock(&(zevtchan->zn_mutex));
6108cf8f45c7Sdstaff return (0);
6109cf8f45c7Sdstaff }
6110cf8f45c7Sdstaff }
6111cf8f45c7Sdstaff
6112cf8f45c7Sdstaff if (zevtchan->zn_state == ZN_UNLOCKED) {
6113cf8f45c7Sdstaff
6114cf8f45c7Sdstaff error = do_callback(zevtchan, ev);
6115cf8f45c7Sdstaff (void) pthread_mutex_unlock(&(zevtchan->zn_mutex));
6116cf8f45c7Sdstaff /*
6117cf8f45c7Sdstaff * Every ENOMEM failure causes do_callback to increment
6118cf8f45c7Sdstaff * zn_failure_count and every success causes it to
6119cf8f45c7Sdstaff * set zn_failure_count to zero. If we got EAGAIN,
6120cf8f45c7Sdstaff * we will sleep for zn_failure_count seconds and return
6121cf8f45c7Sdstaff * EAGAIN to gpec to try again.
6122cf8f45c7Sdstaff *
6123cf8f45c7Sdstaff * After 55 seconds, or 10 try's we give up and drop the
6124cf8f45c7Sdstaff * event.
6125cf8f45c7Sdstaff */
6126cf8f45c7Sdstaff if (error == EAGAIN) {
6127cf8f45c7Sdstaff if (zevtchan->zn_failure_count > ZONE_CB_RETRY_COUNT) {
6128cf8f45c7Sdstaff return (0);
6129cf8f45c7Sdstaff }
6130cf8f45c7Sdstaff (void) sleep(zevtchan->zn_failure_count);
6131cf8f45c7Sdstaff }
6132cf8f45c7Sdstaff return (error);
6133cf8f45c7Sdstaff }
6134cf8f45c7Sdstaff
6135cf8f45c7Sdstaff if (zevtchan->zn_state == ZN_PING_RECEIVED) {
6136cf8f45c7Sdstaff (void) pthread_mutex_unlock(&(zevtchan->zn_mutex));
6137cf8f45c7Sdstaff return (0);
6138cf8f45c7Sdstaff }
6139cf8f45c7Sdstaff
6140cf8f45c7Sdstaff abort();
6141cf8f45c7Sdstaff return (0);
6142cf8f45c7Sdstaff }
6143cf8f45c7Sdstaff
6144cf8f45c7Sdstaff void
zonecfg_notify_critical_enter(void * h)6145cf8f45c7Sdstaff zonecfg_notify_critical_enter(void *h)
6146cf8f45c7Sdstaff {
6147cf8f45c7Sdstaff struct znotify *zevtchan = h;
6148cf8f45c7Sdstaff
6149cf8f45c7Sdstaff (void) pthread_mutex_lock(&(zevtchan->zn_bigmutex));
6150cf8f45c7Sdstaff zevtchan->zn_state = ZN_LOCKED;
6151cf8f45c7Sdstaff }
6152cf8f45c7Sdstaff
6153cf8f45c7Sdstaff int
zonecfg_notify_critical_exit(void * h)6154cf8f45c7Sdstaff zonecfg_notify_critical_exit(void * h)
6155cf8f45c7Sdstaff {
6156cf8f45c7Sdstaff
6157cf8f45c7Sdstaff struct znotify *zevtchan = h;
6158cf8f45c7Sdstaff
6159cf8f45c7Sdstaff if (zevtchan->zn_state == ZN_UNLOCKED)
6160cf8f45c7Sdstaff return (0);
6161cf8f45c7Sdstaff
6162cf8f45c7Sdstaff (void) pthread_mutex_lock(&(zevtchan->zn_mutex));
6163cf8f45c7Sdstaff zevtchan->zn_state = ZN_PING_INFLIGHT;
6164cf8f45c7Sdstaff
6165ee519a1fSgjelinek (void) sysevent_evc_publish(zevtchan->zn_eventchan,
6166ee519a1fSgjelinek ZONE_EVENT_STATUS_CLASS,
6167cf8f45c7Sdstaff ZONE_EVENT_PING_SUBCLASS, ZONE_EVENT_PING_PUBLISHER,
6168cf8f45c7Sdstaff zevtchan->zn_subscriber_id, NULL, EVCH_SLEEP);
6169cf8f45c7Sdstaff
6170cf8f45c7Sdstaff while (zevtchan->zn_state != ZN_PING_RECEIVED) {
6171cf8f45c7Sdstaff (void) pthread_cond_wait(&(zevtchan->zn_cond),
6172cf8f45c7Sdstaff &(zevtchan->zn_mutex));
6173cf8f45c7Sdstaff }
6174cf8f45c7Sdstaff
6175cf8f45c7Sdstaff if (zevtchan->zn_failed == B_TRUE) {
6176cf8f45c7Sdstaff zevtchan->zn_state = ZN_LOCKED;
6177cf8f45c7Sdstaff zevtchan->zn_failed = B_FALSE;
6178cf8f45c7Sdstaff (void) pthread_mutex_unlock(&(zevtchan->zn_mutex));
6179cf8f45c7Sdstaff return (1);
6180cf8f45c7Sdstaff }
6181cf8f45c7Sdstaff
6182cf8f45c7Sdstaff zevtchan->zn_state = ZN_UNLOCKED;
6183cf8f45c7Sdstaff (void) pthread_mutex_unlock(&(zevtchan->zn_mutex));
6184cf8f45c7Sdstaff (void) pthread_mutex_unlock(&(zevtchan->zn_bigmutex));
6185cf8f45c7Sdstaff return (0);
6186cf8f45c7Sdstaff }
6187cf8f45c7Sdstaff
6188cf8f45c7Sdstaff void
zonecfg_notify_critical_abort(void * h)6189cf8f45c7Sdstaff zonecfg_notify_critical_abort(void *h)
6190cf8f45c7Sdstaff {
6191cf8f45c7Sdstaff struct znotify *zevtchan = h;
6192cf8f45c7Sdstaff
6193cf8f45c7Sdstaff zevtchan->zn_state = ZN_UNLOCKED;
6194cf8f45c7Sdstaff zevtchan->zn_failed = B_FALSE;
6195cf8f45c7Sdstaff /*
6196cf8f45c7Sdstaff * Don't do anything about zn_lock. If it is held, it could only be
6197cf8f45c7Sdstaff * held by zn_cb and it will be unlocked soon.
6198cf8f45c7Sdstaff */
6199cf8f45c7Sdstaff (void) pthread_mutex_unlock(&(zevtchan->zn_bigmutex));
6200cf8f45c7Sdstaff }
6201cf8f45c7Sdstaff
6202cf8f45c7Sdstaff void *
zonecfg_notify_bind(int (* func)(const char * zonename,zoneid_t zid,const char * newstate,const char * oldstate,hrtime_t when,void * p),void * p)6203cf8f45c7Sdstaff zonecfg_notify_bind(int(*func)(const char *zonename, zoneid_t zid,
6204cf8f45c7Sdstaff const char *newstate, const char *oldstate, hrtime_t when, void *p),
6205cf8f45c7Sdstaff void *p)
6206cf8f45c7Sdstaff {
6207cf8f45c7Sdstaff struct znotify *zevtchan;
6208cf8f45c7Sdstaff int i = 1;
6209cf8f45c7Sdstaff int r;
6210cf8f45c7Sdstaff
6211cf8f45c7Sdstaff zevtchan = malloc(sizeof (struct znotify));
6212cf8f45c7Sdstaff
6213cf8f45c7Sdstaff if (zevtchan == NULL)
6214cf8f45c7Sdstaff return (NULL);
6215cf8f45c7Sdstaff
6216cf8f45c7Sdstaff zevtchan->zn_private = p;
6217cf8f45c7Sdstaff zevtchan->zn_callback = func;
6218cf8f45c7Sdstaff zevtchan->zn_state = ZN_UNLOCKED;
6219cf8f45c7Sdstaff zevtchan->zn_failed = B_FALSE;
6220cf8f45c7Sdstaff
6221cf8f45c7Sdstaff if (pthread_mutex_init(&(zevtchan->zn_mutex), NULL))
62229d4be64eSdstaff goto out3;
6223cf8f45c7Sdstaff if (pthread_cond_init(&(zevtchan->zn_cond), NULL)) {
6224cf8f45c7Sdstaff (void) pthread_mutex_destroy(&(zevtchan->zn_mutex));
62259d4be64eSdstaff goto out3;
6226cf8f45c7Sdstaff }
6227cf8f45c7Sdstaff if (pthread_mutex_init(&(zevtchan->zn_bigmutex), NULL)) {
6228cf8f45c7Sdstaff (void) pthread_mutex_destroy(&(zevtchan->zn_mutex));
6229cf8f45c7Sdstaff (void) pthread_cond_destroy(&(zevtchan->zn_cond));
62309d4be64eSdstaff goto out3;
6231cf8f45c7Sdstaff }
6232cf8f45c7Sdstaff
6233cf8f45c7Sdstaff if (sysevent_evc_bind(ZONE_EVENT_CHANNEL, &(zevtchan->zn_eventchan),
6234cf8f45c7Sdstaff 0) != 0)
6235cf8f45c7Sdstaff goto out2;
6236cf8f45c7Sdstaff
6237cf8f45c7Sdstaff do {
6238cf8f45c7Sdstaff /*
6239cf8f45c7Sdstaff * At 4 digits the subscriber ID gets too long and we have
6240cf8f45c7Sdstaff * no chance of successfully registering.
6241cf8f45c7Sdstaff */
6242cf8f45c7Sdstaff if (i > 999)
62439d4be64eSdstaff goto out1;
6244cf8f45c7Sdstaff
6245cf8f45c7Sdstaff (void) sprintf(zevtchan->zn_subscriber_id, "zone_%li_%i",
6246cf8f45c7Sdstaff getpid() % 999999l, i);
6247cf8f45c7Sdstaff
6248cf8f45c7Sdstaff r = sysevent_evc_subscribe(zevtchan->zn_eventchan,
6249cf8f45c7Sdstaff zevtchan->zn_subscriber_id, ZONE_EVENT_STATUS_CLASS, zn_cb,
6250cf8f45c7Sdstaff zevtchan, 0);
6251cf8f45c7Sdstaff
6252cf8f45c7Sdstaff i++;
6253cf8f45c7Sdstaff
6254cf8f45c7Sdstaff } while (r);
6255cf8f45c7Sdstaff
6256cf8f45c7Sdstaff return (zevtchan);
62579d4be64eSdstaff out1:
625849b225e1SGavin Maltby (void) sysevent_evc_unbind(zevtchan->zn_eventchan);
62599d4be64eSdstaff out2:
6260cf8f45c7Sdstaff (void) pthread_mutex_destroy(&zevtchan->zn_mutex);
6261cf8f45c7Sdstaff (void) pthread_cond_destroy(&zevtchan->zn_cond);
6262cf8f45c7Sdstaff (void) pthread_mutex_destroy(&(zevtchan->zn_bigmutex));
62639d4be64eSdstaff out3:
6264cf8f45c7Sdstaff free(zevtchan);
6265cf8f45c7Sdstaff
6266cf8f45c7Sdstaff return (NULL);
6267cf8f45c7Sdstaff }
6268cf8f45c7Sdstaff
6269cf8f45c7Sdstaff void
zonecfg_notify_unbind(void * handle)6270cf8f45c7Sdstaff zonecfg_notify_unbind(void *handle)
6271cf8f45c7Sdstaff {
6272cf8f45c7Sdstaff
6273cf8f45c7Sdstaff int ret;
6274cf8f45c7Sdstaff
627549b225e1SGavin Maltby (void) sysevent_evc_unbind(((struct znotify *)handle)->zn_eventchan);
6276cf8f45c7Sdstaff /*
6277cf8f45c7Sdstaff * Check that all evc threads have gone away. This should be
6278cf8f45c7Sdstaff * enforced by sysevent_evc_unbind.
6279cf8f45c7Sdstaff */
6280cf8f45c7Sdstaff ret = pthread_mutex_trylock(&((struct znotify *)handle)->zn_mutex);
6281cf8f45c7Sdstaff
6282cf8f45c7Sdstaff if (ret)
6283cf8f45c7Sdstaff abort();
6284cf8f45c7Sdstaff
6285cf8f45c7Sdstaff (void) pthread_mutex_unlock(&((struct znotify *)handle)->zn_mutex);
6286cf8f45c7Sdstaff (void) pthread_mutex_destroy(&((struct znotify *)handle)->zn_mutex);
6287cf8f45c7Sdstaff (void) pthread_cond_destroy(&((struct znotify *)handle)->zn_cond);
6288cf8f45c7Sdstaff (void) pthread_mutex_destroy(&((struct znotify *)handle)->zn_bigmutex);
6289cf8f45c7Sdstaff
6290cf8f45c7Sdstaff free(handle);
6291cf8f45c7Sdstaff }
6292cf8f45c7Sdstaff
6293fa9e4066Sahrens static int
zonecfg_add_ds_core(zone_dochandle_t handle,struct zone_dstab * tabptr)6294fa9e4066Sahrens zonecfg_add_ds_core(zone_dochandle_t handle, struct zone_dstab *tabptr)
6295fa9e4066Sahrens {
6296fa9e4066Sahrens xmlNodePtr newnode, cur = handle->zone_dh_cur;
6297fa9e4066Sahrens int err;
6298fa9e4066Sahrens
6299fa9e4066Sahrens newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_DATASET, NULL);
6300fa9e4066Sahrens if ((err = newprop(newnode, DTD_ATTR_NAME,
6301fa9e4066Sahrens tabptr->zone_dataset_name)) != Z_OK)
6302fa9e4066Sahrens return (err);
6303fa9e4066Sahrens return (Z_OK);
6304fa9e4066Sahrens }
6305fa9e4066Sahrens
6306fa9e4066Sahrens int
zonecfg_add_ds(zone_dochandle_t handle,struct zone_dstab * tabptr)6307fa9e4066Sahrens zonecfg_add_ds(zone_dochandle_t handle, struct zone_dstab *tabptr)
6308fa9e4066Sahrens {
6309fa9e4066Sahrens int err;
6310fa9e4066Sahrens
6311fa9e4066Sahrens if (tabptr == NULL)
6312fa9e4066Sahrens return (Z_INVAL);
6313fa9e4066Sahrens
6314fa9e4066Sahrens if ((err = operation_prep(handle)) != Z_OK)
6315fa9e4066Sahrens return (err);
6316fa9e4066Sahrens
6317fa9e4066Sahrens if ((err = zonecfg_add_ds_core(handle, tabptr)) != Z_OK)
6318fa9e4066Sahrens return (err);
6319fa9e4066Sahrens
6320fa9e4066Sahrens return (Z_OK);
6321fa9e4066Sahrens }
6322fa9e4066Sahrens
6323fa9e4066Sahrens static int
zonecfg_delete_ds_core(zone_dochandle_t handle,struct zone_dstab * tabptr)6324fa9e4066Sahrens zonecfg_delete_ds_core(zone_dochandle_t handle, struct zone_dstab *tabptr)
6325fa9e4066Sahrens {
6326fa9e4066Sahrens xmlNodePtr cur = handle->zone_dh_cur;
6327fa9e4066Sahrens
6328fa9e4066Sahrens for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
6329fa9e4066Sahrens if (xmlStrcmp(cur->name, DTD_ELEM_DATASET))
6330fa9e4066Sahrens continue;
6331fa9e4066Sahrens
6332fa9e4066Sahrens if (match_prop(cur, DTD_ATTR_NAME,
6333fa9e4066Sahrens tabptr->zone_dataset_name)) {
6334fa9e4066Sahrens xmlUnlinkNode(cur);
6335fa9e4066Sahrens xmlFreeNode(cur);
6336fa9e4066Sahrens return (Z_OK);
6337fa9e4066Sahrens }
6338fa9e4066Sahrens }
6339fa9e4066Sahrens return (Z_NO_RESOURCE_ID);
6340fa9e4066Sahrens }
6341fa9e4066Sahrens
6342fa9e4066Sahrens int
zonecfg_delete_ds(zone_dochandle_t handle,struct zone_dstab * tabptr)6343fa9e4066Sahrens zonecfg_delete_ds(zone_dochandle_t handle, struct zone_dstab *tabptr)
6344fa9e4066Sahrens {
6345fa9e4066Sahrens int err;
6346fa9e4066Sahrens
6347fa9e4066Sahrens if (tabptr == NULL)
6348fa9e4066Sahrens return (Z_INVAL);
6349fa9e4066Sahrens
6350fa9e4066Sahrens if ((err = operation_prep(handle)) != Z_OK)
6351fa9e4066Sahrens return (err);
6352fa9e4066Sahrens
6353fa9e4066Sahrens if ((err = zonecfg_delete_ds_core(handle, tabptr)) != Z_OK)
6354fa9e4066Sahrens return (err);
6355fa9e4066Sahrens
6356fa9e4066Sahrens return (Z_OK);
6357fa9e4066Sahrens }
6358fa9e4066Sahrens
6359fa9e4066Sahrens int
zonecfg_modify_ds(zone_dochandle_t handle,struct zone_dstab * oldtabptr,struct zone_dstab * newtabptr)6360fa9e4066Sahrens zonecfg_modify_ds(
6361fa9e4066Sahrens zone_dochandle_t handle,
6362fa9e4066Sahrens struct zone_dstab *oldtabptr,
6363fa9e4066Sahrens struct zone_dstab *newtabptr)
6364fa9e4066Sahrens {
6365fa9e4066Sahrens int err;
6366fa9e4066Sahrens
6367fa9e4066Sahrens if (oldtabptr == NULL || newtabptr == NULL)
6368fa9e4066Sahrens return (Z_INVAL);
6369fa9e4066Sahrens
6370fa9e4066Sahrens if ((err = operation_prep(handle)) != Z_OK)
6371fa9e4066Sahrens return (err);
6372fa9e4066Sahrens
6373fa9e4066Sahrens if ((err = zonecfg_delete_ds_core(handle, oldtabptr)) != Z_OK)
6374fa9e4066Sahrens return (err);
6375fa9e4066Sahrens
6376fa9e4066Sahrens if ((err = zonecfg_add_ds_core(handle, newtabptr)) != Z_OK)
6377fa9e4066Sahrens return (err);
6378fa9e4066Sahrens
6379fa9e4066Sahrens return (Z_OK);
6380fa9e4066Sahrens }
6381fa9e4066Sahrens
6382fa9e4066Sahrens int
zonecfg_lookup_ds(zone_dochandle_t handle,struct zone_dstab * tabptr)6383fa9e4066Sahrens zonecfg_lookup_ds(zone_dochandle_t handle, struct zone_dstab *tabptr)
6384fa9e4066Sahrens {
6385fa9e4066Sahrens xmlNodePtr cur, firstmatch;
6386fa9e4066Sahrens int err;
6387fa9e4066Sahrens char dataset[MAXNAMELEN];
6388fa9e4066Sahrens
6389fa9e4066Sahrens if (tabptr == NULL)
6390fa9e4066Sahrens return (Z_INVAL);
6391fa9e4066Sahrens
6392fa9e4066Sahrens if ((err = operation_prep(handle)) != Z_OK)
6393fa9e4066Sahrens return (err);
6394fa9e4066Sahrens
6395fa9e4066Sahrens cur = handle->zone_dh_cur;
6396fa9e4066Sahrens firstmatch = NULL;
6397fa9e4066Sahrens for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
6398fa9e4066Sahrens if (xmlStrcmp(cur->name, DTD_ELEM_DATASET))
6399fa9e4066Sahrens continue;
6400fa9e4066Sahrens if (strlen(tabptr->zone_dataset_name) > 0) {
6401fa9e4066Sahrens if ((fetchprop(cur, DTD_ATTR_NAME, dataset,
6402fa9e4066Sahrens sizeof (dataset)) == Z_OK) &&
6403fa9e4066Sahrens (strcmp(tabptr->zone_dataset_name,
6404fa9e4066Sahrens dataset) == 0)) {
6405fa9e4066Sahrens if (firstmatch == NULL)
6406fa9e4066Sahrens firstmatch = cur;
6407fa9e4066Sahrens else
6408fa9e4066Sahrens return (Z_INSUFFICIENT_SPEC);
6409fa9e4066Sahrens }
6410fa9e4066Sahrens }
6411fa9e4066Sahrens }
6412fa9e4066Sahrens if (firstmatch == NULL)
6413fa9e4066Sahrens return (Z_NO_RESOURCE_ID);
6414fa9e4066Sahrens
6415fa9e4066Sahrens cur = firstmatch;
6416fa9e4066Sahrens
6417fa9e4066Sahrens if ((err = fetchprop(cur, DTD_ATTR_NAME, tabptr->zone_dataset_name,
6418fa9e4066Sahrens sizeof (tabptr->zone_dataset_name))) != Z_OK)
6419fa9e4066Sahrens return (err);
6420fa9e4066Sahrens
6421fa9e4066Sahrens return (Z_OK);
6422fa9e4066Sahrens }
6423fa9e4066Sahrens
6424fa9e4066Sahrens int
zonecfg_setdsent(zone_dochandle_t handle)6425fa9e4066Sahrens zonecfg_setdsent(zone_dochandle_t handle)
6426fa9e4066Sahrens {
6427fa9e4066Sahrens return (zonecfg_setent(handle));
6428fa9e4066Sahrens }
6429fa9e4066Sahrens
6430fa9e4066Sahrens int
zonecfg_getdsent(zone_dochandle_t handle,struct zone_dstab * tabptr)6431fa9e4066Sahrens zonecfg_getdsent(zone_dochandle_t handle, struct zone_dstab *tabptr)
6432fa9e4066Sahrens {
6433fa9e4066Sahrens xmlNodePtr cur;
6434fa9e4066Sahrens int err;
6435fa9e4066Sahrens
6436fa9e4066Sahrens if (handle == NULL)
6437fa9e4066Sahrens return (Z_INVAL);
6438fa9e4066Sahrens
6439fa9e4066Sahrens if ((cur = handle->zone_dh_cur) == NULL)
6440fa9e4066Sahrens return (Z_NO_ENTRY);
6441fa9e4066Sahrens
6442fa9e4066Sahrens for (; cur != NULL; cur = cur->next)
6443fa9e4066Sahrens if (!xmlStrcmp(cur->name, DTD_ELEM_DATASET))
6444fa9e4066Sahrens break;
6445fa9e4066Sahrens if (cur == NULL) {
6446fa9e4066Sahrens handle->zone_dh_cur = handle->zone_dh_top;
6447fa9e4066Sahrens return (Z_NO_ENTRY);
6448fa9e4066Sahrens }
6449fa9e4066Sahrens
6450fa9e4066Sahrens if ((err = fetchprop(cur, DTD_ATTR_NAME, tabptr->zone_dataset_name,
6451fa9e4066Sahrens sizeof (tabptr->zone_dataset_name))) != Z_OK) {
6452fa9e4066Sahrens handle->zone_dh_cur = handle->zone_dh_top;
6453fa9e4066Sahrens return (err);
6454fa9e4066Sahrens }
6455fa9e4066Sahrens
6456fa9e4066Sahrens handle->zone_dh_cur = cur->next;
6457fa9e4066Sahrens return (Z_OK);
6458fa9e4066Sahrens }
6459fa9e4066Sahrens
6460fa9e4066Sahrens int
zonecfg_enddsent(zone_dochandle_t handle)6461fa9e4066Sahrens zonecfg_enddsent(zone_dochandle_t handle)
6462fa9e4066Sahrens {
6463fa9e4066Sahrens return (zonecfg_endent(handle));
6464fa9e4066Sahrens }
6465ee519a1fSgjelinek
64660209230bSgjelinek /*
64670209230bSgjelinek * Support for aliased rctls; that is, rctls that have simplified names in
64680209230bSgjelinek * zonecfg. For example, max-lwps is an alias for a well defined zone.max-lwps
64690209230bSgjelinek * rctl. If there are multiple existing values for one of these rctls or if
64700209230bSgjelinek * there is a single value that does not match the well defined template (i.e.
64710209230bSgjelinek * it has a different action) then we cannot treat the rctl as having an alias
64720209230bSgjelinek * so we return Z_ALIAS_DISALLOW. That means that the rctl cannot be
64730209230bSgjelinek * managed in zonecfg via an alias and that the standard rctl syntax must be
64740209230bSgjelinek * used.
64750209230bSgjelinek *
64760209230bSgjelinek * The possible return values are:
64770209230bSgjelinek * Z_NO_PROPERTY_ID - invalid alias name
64780209230bSgjelinek * Z_ALIAS_DISALLOW - pre-existing, incompatible rctl definition
64790209230bSgjelinek * Z_NO_ENTRY - no rctl is configured for this alias
64800209230bSgjelinek * Z_OK - we got a valid rctl for the specified alias
64810209230bSgjelinek */
64820209230bSgjelinek int
zonecfg_get_aliased_rctl(zone_dochandle_t handle,char * name,uint64_t * rval)64830209230bSgjelinek zonecfg_get_aliased_rctl(zone_dochandle_t handle, char *name, uint64_t *rval)
64840209230bSgjelinek {
64850209230bSgjelinek boolean_t found = B_FALSE;
64860209230bSgjelinek boolean_t found_val = B_FALSE;
64870209230bSgjelinek xmlNodePtr cur, val;
64880209230bSgjelinek char savedname[MAXNAMELEN];
64890209230bSgjelinek struct zone_rctlvaltab rctl;
64900209230bSgjelinek int i;
64910209230bSgjelinek int err;
64920209230bSgjelinek
64930209230bSgjelinek for (i = 0; aliases[i].shortname != NULL; i++)
64940209230bSgjelinek if (strcmp(name, aliases[i].shortname) == 0)
64950209230bSgjelinek break;
64960209230bSgjelinek
64970209230bSgjelinek if (aliases[i].shortname == NULL)
64980209230bSgjelinek return (Z_NO_PROPERTY_ID);
64990209230bSgjelinek
65000209230bSgjelinek if ((err = operation_prep(handle)) != Z_OK)
65010209230bSgjelinek return (err);
65020209230bSgjelinek
65030209230bSgjelinek cur = handle->zone_dh_cur;
65040209230bSgjelinek for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
65050209230bSgjelinek if (xmlStrcmp(cur->name, DTD_ELEM_RCTL) != 0)
65060209230bSgjelinek continue;
65070209230bSgjelinek if ((fetchprop(cur, DTD_ATTR_NAME, savedname,
65080209230bSgjelinek sizeof (savedname)) == Z_OK) &&
65090209230bSgjelinek (strcmp(savedname, aliases[i].realname) == 0)) {
65100209230bSgjelinek
65110209230bSgjelinek /*
65120209230bSgjelinek * If we already saw one of these, we can't have an
65130209230bSgjelinek * alias since we just found another.
65140209230bSgjelinek */
65150209230bSgjelinek if (found)
65160209230bSgjelinek return (Z_ALIAS_DISALLOW);
65170209230bSgjelinek found = B_TRUE;
65180209230bSgjelinek
65190209230bSgjelinek for (val = cur->xmlChildrenNode; val != NULL;
65200209230bSgjelinek val = val->next) {
65210209230bSgjelinek /*
65220209230bSgjelinek * If we already have one value, we can't have
65230209230bSgjelinek * an alias since we just found another.
65240209230bSgjelinek */
65250209230bSgjelinek if (found_val)
65260209230bSgjelinek return (Z_ALIAS_DISALLOW);
65270209230bSgjelinek found_val = B_TRUE;
65280209230bSgjelinek
65290209230bSgjelinek if ((fetchprop(val, DTD_ATTR_PRIV,
65300209230bSgjelinek rctl.zone_rctlval_priv,
65310209230bSgjelinek sizeof (rctl.zone_rctlval_priv)) != Z_OK))
65320209230bSgjelinek break;
65330209230bSgjelinek if ((fetchprop(val, DTD_ATTR_LIMIT,
65340209230bSgjelinek rctl.zone_rctlval_limit,
65350209230bSgjelinek sizeof (rctl.zone_rctlval_limit)) != Z_OK))
65360209230bSgjelinek break;
65370209230bSgjelinek if ((fetchprop(val, DTD_ATTR_ACTION,
65380209230bSgjelinek rctl.zone_rctlval_action,
65390209230bSgjelinek sizeof (rctl.zone_rctlval_action)) != Z_OK))
65400209230bSgjelinek break;
65410209230bSgjelinek }
65420209230bSgjelinek
65430209230bSgjelinek /* check priv and action match the expected vals */
65440209230bSgjelinek if (strcmp(rctl.zone_rctlval_priv,
65450209230bSgjelinek aliases[i].priv) != 0 ||
65460209230bSgjelinek strcmp(rctl.zone_rctlval_action,
65470209230bSgjelinek aliases[i].action) != 0)
65480209230bSgjelinek return (Z_ALIAS_DISALLOW);
65490209230bSgjelinek }
65500209230bSgjelinek }
65510209230bSgjelinek
65520209230bSgjelinek if (found) {
65530209230bSgjelinek *rval = strtoull(rctl.zone_rctlval_limit, NULL, 10);
65540209230bSgjelinek return (Z_OK);
65550209230bSgjelinek }
65560209230bSgjelinek
65570209230bSgjelinek return (Z_NO_ENTRY);
65580209230bSgjelinek }
65590209230bSgjelinek
65600209230bSgjelinek int
zonecfg_rm_aliased_rctl(zone_dochandle_t handle,char * name)65610209230bSgjelinek zonecfg_rm_aliased_rctl(zone_dochandle_t handle, char *name)
65620209230bSgjelinek {
65630209230bSgjelinek int i;
65640209230bSgjelinek uint64_t val;
65650209230bSgjelinek struct zone_rctltab rctltab;
65660209230bSgjelinek
65670209230bSgjelinek /*
65680209230bSgjelinek * First check that we have a valid aliased rctl to remove.
65690209230bSgjelinek * This will catch an rctl entry with non-standard values or
65700209230bSgjelinek * multiple rctl values for this name. We need to ignore those
65710209230bSgjelinek * rctl entries.
65720209230bSgjelinek */
65730209230bSgjelinek if (zonecfg_get_aliased_rctl(handle, name, &val) != Z_OK)
65740209230bSgjelinek return (Z_OK);
65750209230bSgjelinek
65760209230bSgjelinek for (i = 0; aliases[i].shortname != NULL; i++)
65770209230bSgjelinek if (strcmp(name, aliases[i].shortname) == 0)
65780209230bSgjelinek break;
65790209230bSgjelinek
65800209230bSgjelinek if (aliases[i].shortname == NULL)
65810209230bSgjelinek return (Z_NO_RESOURCE_ID);
65820209230bSgjelinek
65830209230bSgjelinek (void) strlcpy(rctltab.zone_rctl_name, aliases[i].realname,
65840209230bSgjelinek sizeof (rctltab.zone_rctl_name));
65850209230bSgjelinek
65860209230bSgjelinek return (zonecfg_delete_rctl(handle, &rctltab));
65870209230bSgjelinek }
65880209230bSgjelinek
65890209230bSgjelinek boolean_t
zonecfg_aliased_rctl_ok(zone_dochandle_t handle,char * name)65900209230bSgjelinek zonecfg_aliased_rctl_ok(zone_dochandle_t handle, char *name)
65910209230bSgjelinek {
65920209230bSgjelinek uint64_t tmp_val;
65930209230bSgjelinek
65940209230bSgjelinek switch (zonecfg_get_aliased_rctl(handle, name, &tmp_val)) {
65950209230bSgjelinek case Z_OK:
65960209230bSgjelinek /*FALLTHRU*/
65970209230bSgjelinek case Z_NO_ENTRY:
65980209230bSgjelinek return (B_TRUE);
65990209230bSgjelinek default:
66000209230bSgjelinek return (B_FALSE);
66010209230bSgjelinek }
66020209230bSgjelinek }
66030209230bSgjelinek
66040209230bSgjelinek int
zonecfg_set_aliased_rctl(zone_dochandle_t handle,char * name,uint64_t val)66050209230bSgjelinek zonecfg_set_aliased_rctl(zone_dochandle_t handle, char *name, uint64_t val)
66060209230bSgjelinek {
66070209230bSgjelinek int i;
66080209230bSgjelinek int err;
66090209230bSgjelinek struct zone_rctltab rctltab;
66100209230bSgjelinek struct zone_rctlvaltab *rctlvaltab;
66110209230bSgjelinek char buf[128];
66120209230bSgjelinek
66130209230bSgjelinek if (!zonecfg_aliased_rctl_ok(handle, name))
66140209230bSgjelinek return (Z_ALIAS_DISALLOW);
66150209230bSgjelinek
66160209230bSgjelinek for (i = 0; aliases[i].shortname != NULL; i++)
66170209230bSgjelinek if (strcmp(name, aliases[i].shortname) == 0)
66180209230bSgjelinek break;
66190209230bSgjelinek
66200209230bSgjelinek if (aliases[i].shortname == NULL)
66210209230bSgjelinek return (Z_NO_RESOURCE_ID);
66220209230bSgjelinek
66230209230bSgjelinek /* remove any pre-existing definition for this rctl */
66240209230bSgjelinek (void) zonecfg_rm_aliased_rctl(handle, name);
66250209230bSgjelinek
66260209230bSgjelinek (void) strlcpy(rctltab.zone_rctl_name, aliases[i].realname,
66270209230bSgjelinek sizeof (rctltab.zone_rctl_name));
66280209230bSgjelinek
66290209230bSgjelinek rctltab.zone_rctl_valptr = NULL;
66300209230bSgjelinek
66310209230bSgjelinek if ((rctlvaltab = calloc(1, sizeof (struct zone_rctlvaltab))) == NULL)
66320209230bSgjelinek return (Z_NOMEM);
66330209230bSgjelinek
66340209230bSgjelinek (void) snprintf(buf, sizeof (buf), "%llu", (long long)val);
66350209230bSgjelinek
66360209230bSgjelinek (void) strlcpy(rctlvaltab->zone_rctlval_priv, aliases[i].priv,
66370209230bSgjelinek sizeof (rctlvaltab->zone_rctlval_priv));
66380209230bSgjelinek (void) strlcpy(rctlvaltab->zone_rctlval_limit, buf,
66390209230bSgjelinek sizeof (rctlvaltab->zone_rctlval_limit));
66400209230bSgjelinek (void) strlcpy(rctlvaltab->zone_rctlval_action, aliases[i].action,
66410209230bSgjelinek sizeof (rctlvaltab->zone_rctlval_action));
66420209230bSgjelinek
66430209230bSgjelinek rctlvaltab->zone_rctlval_next = NULL;
66440209230bSgjelinek
66450209230bSgjelinek if ((err = zonecfg_add_rctl_value(&rctltab, rctlvaltab)) != Z_OK)
66460209230bSgjelinek return (err);
66470209230bSgjelinek
66480209230bSgjelinek return (zonecfg_add_rctl(handle, &rctltab));
66490209230bSgjelinek }
66500209230bSgjelinek
66510209230bSgjelinek static int
delete_tmp_pool(zone_dochandle_t handle)66520209230bSgjelinek delete_tmp_pool(zone_dochandle_t handle)
66530209230bSgjelinek {
66540209230bSgjelinek int err;
66550209230bSgjelinek xmlNodePtr cur = handle->zone_dh_cur;
66560209230bSgjelinek
66570209230bSgjelinek if ((err = operation_prep(handle)) != Z_OK)
66580209230bSgjelinek return (err);
66590209230bSgjelinek
66600209230bSgjelinek for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
66610209230bSgjelinek if (xmlStrcmp(cur->name, DTD_ELEM_TMPPOOL) == 0) {
66620209230bSgjelinek xmlUnlinkNode(cur);
66630209230bSgjelinek xmlFreeNode(cur);
66640209230bSgjelinek return (Z_OK);
66650209230bSgjelinek }
66660209230bSgjelinek }
66670209230bSgjelinek
66680209230bSgjelinek return (Z_NO_RESOURCE_ID);
66690209230bSgjelinek }
66700209230bSgjelinek
66710209230bSgjelinek static int
modify_tmp_pool(zone_dochandle_t handle,char * pool_importance)66720209230bSgjelinek modify_tmp_pool(zone_dochandle_t handle, char *pool_importance)
66730209230bSgjelinek {
66740209230bSgjelinek int err;
66750209230bSgjelinek xmlNodePtr cur = handle->zone_dh_cur;
66760209230bSgjelinek xmlNodePtr newnode;
66770209230bSgjelinek
66780209230bSgjelinek err = delete_tmp_pool(handle);
66790209230bSgjelinek if (err != Z_OK && err != Z_NO_RESOURCE_ID)
66800209230bSgjelinek return (err);
66810209230bSgjelinek
66820209230bSgjelinek if (*pool_importance != '\0') {
66830209230bSgjelinek if ((err = operation_prep(handle)) != Z_OK)
66840209230bSgjelinek return (err);
66850209230bSgjelinek
66860209230bSgjelinek newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_TMPPOOL, NULL);
66870209230bSgjelinek if ((err = newprop(newnode, DTD_ATTR_IMPORTANCE,
66880209230bSgjelinek pool_importance)) != Z_OK)
66890209230bSgjelinek return (err);
66900209230bSgjelinek }
66910209230bSgjelinek
66920209230bSgjelinek return (Z_OK);
66930209230bSgjelinek }
66940209230bSgjelinek
66950209230bSgjelinek static int
add_pset_core(zone_dochandle_t handle,struct zone_psettab * tabptr)66960209230bSgjelinek add_pset_core(zone_dochandle_t handle, struct zone_psettab *tabptr)
66970209230bSgjelinek {
66980209230bSgjelinek xmlNodePtr newnode, cur = handle->zone_dh_cur;
66990209230bSgjelinek int err;
67000209230bSgjelinek
67010209230bSgjelinek newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_PSET, NULL);
67020209230bSgjelinek if ((err = newprop(newnode, DTD_ATTR_NCPU_MIN,
67030209230bSgjelinek tabptr->zone_ncpu_min)) != Z_OK)
67040209230bSgjelinek return (err);
67050209230bSgjelinek if ((err = newprop(newnode, DTD_ATTR_NCPU_MAX,
67060209230bSgjelinek tabptr->zone_ncpu_max)) != Z_OK)
67070209230bSgjelinek return (err);
67080209230bSgjelinek
67090209230bSgjelinek if ((err = modify_tmp_pool(handle, tabptr->zone_importance)) != Z_OK)
67100209230bSgjelinek return (err);
67110209230bSgjelinek
67120209230bSgjelinek return (Z_OK);
67130209230bSgjelinek }
67140209230bSgjelinek
67150209230bSgjelinek int
zonecfg_add_pset(zone_dochandle_t handle,struct zone_psettab * tabptr)67160209230bSgjelinek zonecfg_add_pset(zone_dochandle_t handle, struct zone_psettab *tabptr)
67170209230bSgjelinek {
67180209230bSgjelinek int err;
67190209230bSgjelinek
67200209230bSgjelinek if (tabptr == NULL)
67210209230bSgjelinek return (Z_INVAL);
67220209230bSgjelinek
67230209230bSgjelinek if ((err = operation_prep(handle)) != Z_OK)
67240209230bSgjelinek return (err);
67250209230bSgjelinek
67260209230bSgjelinek if ((err = add_pset_core(handle, tabptr)) != Z_OK)
67270209230bSgjelinek return (err);
67280209230bSgjelinek
67290209230bSgjelinek return (Z_OK);
67300209230bSgjelinek }
67310209230bSgjelinek
67320209230bSgjelinek int
zonecfg_delete_pset(zone_dochandle_t handle)67330209230bSgjelinek zonecfg_delete_pset(zone_dochandle_t handle)
67340209230bSgjelinek {
67350209230bSgjelinek int err;
67360209230bSgjelinek int res = Z_NO_RESOURCE_ID;
67370209230bSgjelinek xmlNodePtr cur = handle->zone_dh_cur;
67380209230bSgjelinek
67390209230bSgjelinek if ((err = operation_prep(handle)) != Z_OK)
67400209230bSgjelinek return (err);
67410209230bSgjelinek
67420209230bSgjelinek for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
67430209230bSgjelinek if (xmlStrcmp(cur->name, DTD_ELEM_PSET) == 0) {
67440209230bSgjelinek xmlUnlinkNode(cur);
67450209230bSgjelinek xmlFreeNode(cur);
67460209230bSgjelinek res = Z_OK;
67470209230bSgjelinek break;
67480209230bSgjelinek }
67490209230bSgjelinek }
67500209230bSgjelinek
67510209230bSgjelinek /*
67520209230bSgjelinek * Once we have msets, we should check that a mset
67530209230bSgjelinek * do not exist before we delete the tmp_pool data.
67540209230bSgjelinek */
67550209230bSgjelinek err = delete_tmp_pool(handle);
67560209230bSgjelinek if (err != Z_OK && err != Z_NO_RESOURCE_ID)
67570209230bSgjelinek return (err);
67580209230bSgjelinek
67590209230bSgjelinek return (res);
67600209230bSgjelinek }
67610209230bSgjelinek
67620209230bSgjelinek int
zonecfg_modify_pset(zone_dochandle_t handle,struct zone_psettab * tabptr)67630209230bSgjelinek zonecfg_modify_pset(zone_dochandle_t handle, struct zone_psettab *tabptr)
67640209230bSgjelinek {
67650209230bSgjelinek int err;
67660209230bSgjelinek
67670209230bSgjelinek if (tabptr == NULL)
67680209230bSgjelinek return (Z_INVAL);
67690209230bSgjelinek
67700209230bSgjelinek if ((err = zonecfg_delete_pset(handle)) != Z_OK)
67710209230bSgjelinek return (err);
67720209230bSgjelinek
67730209230bSgjelinek if ((err = add_pset_core(handle, tabptr)) != Z_OK)
67740209230bSgjelinek return (err);
67750209230bSgjelinek
67760209230bSgjelinek return (Z_OK);
67770209230bSgjelinek }
67780209230bSgjelinek
67790209230bSgjelinek int
zonecfg_lookup_pset(zone_dochandle_t handle,struct zone_psettab * tabptr)67800209230bSgjelinek zonecfg_lookup_pset(zone_dochandle_t handle, struct zone_psettab *tabptr)
67810209230bSgjelinek {
67820209230bSgjelinek xmlNodePtr cur;
67830209230bSgjelinek int err;
67840209230bSgjelinek int res = Z_NO_ENTRY;
67850209230bSgjelinek
67860209230bSgjelinek if (tabptr == NULL)
67870209230bSgjelinek return (Z_INVAL);
67880209230bSgjelinek
67890209230bSgjelinek if ((err = operation_prep(handle)) != Z_OK)
67900209230bSgjelinek return (err);
67910209230bSgjelinek
67920209230bSgjelinek /* this is an optional component */
67930209230bSgjelinek tabptr->zone_importance[0] = '\0';
67940209230bSgjelinek
67950209230bSgjelinek cur = handle->zone_dh_cur;
67960209230bSgjelinek for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
67970209230bSgjelinek if (xmlStrcmp(cur->name, DTD_ELEM_PSET) == 0) {
67980209230bSgjelinek if ((err = fetchprop(cur, DTD_ATTR_NCPU_MIN,
67990209230bSgjelinek tabptr->zone_ncpu_min,
68000209230bSgjelinek sizeof (tabptr->zone_ncpu_min))) != Z_OK) {
68010209230bSgjelinek handle->zone_dh_cur = handle->zone_dh_top;
68020209230bSgjelinek return (err);
68030209230bSgjelinek }
68040209230bSgjelinek
68050209230bSgjelinek if ((err = fetchprop(cur, DTD_ATTR_NCPU_MAX,
68060209230bSgjelinek tabptr->zone_ncpu_max,
68070209230bSgjelinek sizeof (tabptr->zone_ncpu_max))) != Z_OK) {
68080209230bSgjelinek handle->zone_dh_cur = handle->zone_dh_top;
68090209230bSgjelinek return (err);
68100209230bSgjelinek }
68110209230bSgjelinek
68120209230bSgjelinek res = Z_OK;
68130209230bSgjelinek
68140209230bSgjelinek } else if (xmlStrcmp(cur->name, DTD_ELEM_TMPPOOL) == 0) {
68150209230bSgjelinek if ((err = fetchprop(cur, DTD_ATTR_IMPORTANCE,
68160209230bSgjelinek tabptr->zone_importance,
68170209230bSgjelinek sizeof (tabptr->zone_importance))) != Z_OK) {
68180209230bSgjelinek handle->zone_dh_cur = handle->zone_dh_top;
68190209230bSgjelinek return (err);
68200209230bSgjelinek }
68210209230bSgjelinek }
68220209230bSgjelinek }
68230209230bSgjelinek
68240209230bSgjelinek return (res);
68250209230bSgjelinek }
68260209230bSgjelinek
68270209230bSgjelinek int
zonecfg_getpsetent(zone_dochandle_t handle,struct zone_psettab * tabptr)68280209230bSgjelinek zonecfg_getpsetent(zone_dochandle_t handle, struct zone_psettab *tabptr)
68290209230bSgjelinek {
68300209230bSgjelinek int err;
68310209230bSgjelinek
68320209230bSgjelinek if ((err = zonecfg_setent(handle)) != Z_OK)
68330209230bSgjelinek return (err);
68340209230bSgjelinek
68350209230bSgjelinek err = zonecfg_lookup_pset(handle, tabptr);
68360209230bSgjelinek
68370209230bSgjelinek (void) zonecfg_endent(handle);
68380209230bSgjelinek
68390209230bSgjelinek return (err);
68400209230bSgjelinek }
68410209230bSgjelinek
68420209230bSgjelinek static int
add_mcap(zone_dochandle_t handle,struct zone_mcaptab * tabptr)68430209230bSgjelinek add_mcap(zone_dochandle_t handle, struct zone_mcaptab *tabptr)
68440209230bSgjelinek {
68450209230bSgjelinek xmlNodePtr newnode, cur = handle->zone_dh_cur;
68460209230bSgjelinek int err;
68470209230bSgjelinek
68480209230bSgjelinek newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_MCAP, NULL);
68490209230bSgjelinek if ((err = newprop(newnode, DTD_ATTR_PHYSCAP, tabptr->zone_physmem_cap))
68500209230bSgjelinek != Z_OK)
68510209230bSgjelinek return (err);
68520209230bSgjelinek
68530209230bSgjelinek return (Z_OK);
68540209230bSgjelinek }
68550209230bSgjelinek
68560209230bSgjelinek int
zonecfg_delete_mcap(zone_dochandle_t handle)68570209230bSgjelinek zonecfg_delete_mcap(zone_dochandle_t handle)
68580209230bSgjelinek {
68590209230bSgjelinek int err;
68600209230bSgjelinek xmlNodePtr cur = handle->zone_dh_cur;
68610209230bSgjelinek
68620209230bSgjelinek if ((err = operation_prep(handle)) != Z_OK)
68630209230bSgjelinek return (err);
68640209230bSgjelinek
68650209230bSgjelinek for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
68660209230bSgjelinek if (xmlStrcmp(cur->name, DTD_ELEM_MCAP) != 0)
68670209230bSgjelinek continue;
68680209230bSgjelinek
68690209230bSgjelinek xmlUnlinkNode(cur);
68700209230bSgjelinek xmlFreeNode(cur);
68710209230bSgjelinek return (Z_OK);
68720209230bSgjelinek }
68730209230bSgjelinek return (Z_NO_RESOURCE_ID);
68740209230bSgjelinek }
68750209230bSgjelinek
68760209230bSgjelinek int
zonecfg_modify_mcap(zone_dochandle_t handle,struct zone_mcaptab * tabptr)68770209230bSgjelinek zonecfg_modify_mcap(zone_dochandle_t handle, struct zone_mcaptab *tabptr)
68780209230bSgjelinek {
68790209230bSgjelinek int err;
68800209230bSgjelinek
68810209230bSgjelinek if (tabptr == NULL)
68820209230bSgjelinek return (Z_INVAL);
68830209230bSgjelinek
68840209230bSgjelinek err = zonecfg_delete_mcap(handle);
68850209230bSgjelinek /* it is ok if there is no mcap entry */
68860209230bSgjelinek if (err != Z_OK && err != Z_NO_RESOURCE_ID)
68870209230bSgjelinek return (err);
68880209230bSgjelinek
68890209230bSgjelinek if ((err = add_mcap(handle, tabptr)) != Z_OK)
68900209230bSgjelinek return (err);
68910209230bSgjelinek
68920209230bSgjelinek return (Z_OK);
68930209230bSgjelinek }
68940209230bSgjelinek
68950209230bSgjelinek int
zonecfg_lookup_mcap(zone_dochandle_t handle,struct zone_mcaptab * tabptr)68960209230bSgjelinek zonecfg_lookup_mcap(zone_dochandle_t handle, struct zone_mcaptab *tabptr)
68970209230bSgjelinek {
68980209230bSgjelinek xmlNodePtr cur;
68990209230bSgjelinek int err;
69000209230bSgjelinek
69010209230bSgjelinek if (tabptr == NULL)
69020209230bSgjelinek return (Z_INVAL);
69030209230bSgjelinek
69040209230bSgjelinek if ((err = operation_prep(handle)) != Z_OK)
69050209230bSgjelinek return (err);
69060209230bSgjelinek
69070209230bSgjelinek cur = handle->zone_dh_cur;
69080209230bSgjelinek for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
69090209230bSgjelinek if (xmlStrcmp(cur->name, DTD_ELEM_MCAP) != 0)
69100209230bSgjelinek continue;
69110209230bSgjelinek if ((err = fetchprop(cur, DTD_ATTR_PHYSCAP,
69120209230bSgjelinek tabptr->zone_physmem_cap,
69130209230bSgjelinek sizeof (tabptr->zone_physmem_cap))) != Z_OK) {
69140209230bSgjelinek handle->zone_dh_cur = handle->zone_dh_top;
69150209230bSgjelinek return (err);
69160209230bSgjelinek }
69170209230bSgjelinek
69180209230bSgjelinek return (Z_OK);
69190209230bSgjelinek }
69200209230bSgjelinek
69210209230bSgjelinek return (Z_NO_ENTRY);
69220209230bSgjelinek }
69230209230bSgjelinek
69240209230bSgjelinek static int
getmcapent_core(zone_dochandle_t handle,struct zone_mcaptab * tabptr)69250209230bSgjelinek getmcapent_core(zone_dochandle_t handle, struct zone_mcaptab *tabptr)
69260209230bSgjelinek {
69270209230bSgjelinek xmlNodePtr cur;
69280209230bSgjelinek int err;
69290209230bSgjelinek
69300209230bSgjelinek if (handle == NULL)
69310209230bSgjelinek return (Z_INVAL);
69320209230bSgjelinek
69330209230bSgjelinek if ((cur = handle->zone_dh_cur) == NULL)
69340209230bSgjelinek return (Z_NO_ENTRY);
69350209230bSgjelinek
69360209230bSgjelinek for (; cur != NULL; cur = cur->next)
69370209230bSgjelinek if (xmlStrcmp(cur->name, DTD_ELEM_MCAP) == 0)
69380209230bSgjelinek break;
69390209230bSgjelinek if (cur == NULL) {
69400209230bSgjelinek handle->zone_dh_cur = handle->zone_dh_top;
69410209230bSgjelinek return (Z_NO_ENTRY);
69420209230bSgjelinek }
69430209230bSgjelinek
69440209230bSgjelinek if ((err = fetchprop(cur, DTD_ATTR_PHYSCAP, tabptr->zone_physmem_cap,
69450209230bSgjelinek sizeof (tabptr->zone_physmem_cap))) != Z_OK) {
69460209230bSgjelinek handle->zone_dh_cur = handle->zone_dh_top;
69470209230bSgjelinek return (err);
69480209230bSgjelinek }
69490209230bSgjelinek
69500209230bSgjelinek handle->zone_dh_cur = cur->next;
69510209230bSgjelinek return (Z_OK);
69520209230bSgjelinek }
69530209230bSgjelinek
69540209230bSgjelinek int
zonecfg_getmcapent(zone_dochandle_t handle,struct zone_mcaptab * tabptr)69550209230bSgjelinek zonecfg_getmcapent(zone_dochandle_t handle, struct zone_mcaptab *tabptr)
69560209230bSgjelinek {
69570209230bSgjelinek int err;
69580209230bSgjelinek
69590209230bSgjelinek if ((err = zonecfg_setent(handle)) != Z_OK)
69600209230bSgjelinek return (err);
69610209230bSgjelinek
69620209230bSgjelinek err = getmcapent_core(handle, tabptr);
69630209230bSgjelinek
69640209230bSgjelinek (void) zonecfg_endent(handle);
69650209230bSgjelinek
69660209230bSgjelinek return (err);
69670209230bSgjelinek }
69680209230bSgjelinek
69696cfd72c6Sgjelinek /*
69704656d474SGarrett D'Amore * Get the full tree of pkg metadata in a set of nested AVL trees.
69714656d474SGarrett D'Amore * pkgs_avl is an AVL tree of pkgs.
69726cfd72c6Sgjelinek *
69734656d474SGarrett D'Amore * The zone xml data contains DTD_ELEM_PACKAGE elements.
69746cfd72c6Sgjelinek */
6975ee519a1fSgjelinek int
zonecfg_getpkgdata(zone_dochandle_t handle,uu_avl_pool_t * pkg_pool,uu_avl_t * pkgs_avl)69766cfd72c6Sgjelinek zonecfg_getpkgdata(zone_dochandle_t handle, uu_avl_pool_t *pkg_pool,
69776cfd72c6Sgjelinek uu_avl_t *pkgs_avl)
6978ee519a1fSgjelinek {
6979ee519a1fSgjelinek xmlNodePtr cur;
69806cfd72c6Sgjelinek int res;
69816cfd72c6Sgjelinek zone_pkg_entry_t *pkg;
69826cfd72c6Sgjelinek char name[MAXNAMELEN];
69836cfd72c6Sgjelinek char version[ZONE_PKG_VERSMAX];
6984ee519a1fSgjelinek
6985ee519a1fSgjelinek if (handle == NULL)
6986ee519a1fSgjelinek return (Z_INVAL);
6987ee519a1fSgjelinek
69886cfd72c6Sgjelinek if ((res = zonecfg_setent(handle)) != Z_OK)
69896cfd72c6Sgjelinek return (res);
6990ee519a1fSgjelinek
69916cfd72c6Sgjelinek if ((cur = handle->zone_dh_cur) == NULL) {
69926cfd72c6Sgjelinek res = Z_NO_ENTRY;
69936cfd72c6Sgjelinek goto done;
6994ee519a1fSgjelinek }
6995ee519a1fSgjelinek
69966cfd72c6Sgjelinek for (; cur != NULL; cur = cur->next) {
69976cfd72c6Sgjelinek if (xmlStrcmp(cur->name, DTD_ELEM_PACKAGE) == 0) {
69986cfd72c6Sgjelinek uu_avl_index_t where;
69996cfd72c6Sgjelinek
70006cfd72c6Sgjelinek if ((res = fetchprop(cur, DTD_ATTR_NAME, name,
70016cfd72c6Sgjelinek sizeof (name))) != Z_OK)
70026cfd72c6Sgjelinek goto done;
70036cfd72c6Sgjelinek
70046cfd72c6Sgjelinek if ((res = fetchprop(cur, DTD_ATTR_VERSION, version,
70056cfd72c6Sgjelinek sizeof (version))) != Z_OK)
70066cfd72c6Sgjelinek goto done;
70076cfd72c6Sgjelinek
70086cfd72c6Sgjelinek if ((pkg = (zone_pkg_entry_t *)
70096cfd72c6Sgjelinek malloc(sizeof (zone_pkg_entry_t))) == NULL) {
70106cfd72c6Sgjelinek res = Z_NOMEM;
70116cfd72c6Sgjelinek goto done;
7012ee519a1fSgjelinek }
7013ee519a1fSgjelinek
70146cfd72c6Sgjelinek if ((pkg->zpe_name = strdup(name)) == NULL) {
70156cfd72c6Sgjelinek free(pkg);
70166cfd72c6Sgjelinek res = Z_NOMEM;
70176cfd72c6Sgjelinek goto done;
7018ee519a1fSgjelinek }
7019ee519a1fSgjelinek
70206cfd72c6Sgjelinek if ((pkg->zpe_vers = strdup(version)) == NULL) {
70216cfd72c6Sgjelinek free(pkg->zpe_name);
70226cfd72c6Sgjelinek free(pkg);
70236cfd72c6Sgjelinek res = Z_NOMEM;
70246cfd72c6Sgjelinek goto done;
7025ee519a1fSgjelinek }
7026ee519a1fSgjelinek
70276cfd72c6Sgjelinek uu_avl_node_init(pkg, &pkg->zpe_entry, pkg_pool);
70286cfd72c6Sgjelinek if (uu_avl_find(pkgs_avl, pkg, NULL, &where) != NULL) {
70296cfd72c6Sgjelinek free(pkg->zpe_name);
70306cfd72c6Sgjelinek free(pkg->zpe_vers);
70316cfd72c6Sgjelinek free(pkg);
70326cfd72c6Sgjelinek } else {
70336cfd72c6Sgjelinek uu_avl_insert(pkgs_avl, pkg, where);
7034ee519a1fSgjelinek }
70356cfd72c6Sgjelinek }
70366cfd72c6Sgjelinek }
70376cfd72c6Sgjelinek
70386cfd72c6Sgjelinek done:
70396cfd72c6Sgjelinek (void) zonecfg_endent(handle);
70406cfd72c6Sgjelinek return (res);
7041ee519a1fSgjelinek }
7042ee519a1fSgjelinek
7043ee519a1fSgjelinek int
zonecfg_setdevperment(zone_dochandle_t handle)7044ee519a1fSgjelinek zonecfg_setdevperment(zone_dochandle_t handle)
7045ee519a1fSgjelinek {
7046ee519a1fSgjelinek return (zonecfg_setent(handle));
7047ee519a1fSgjelinek }
7048ee519a1fSgjelinek
7049ee519a1fSgjelinek int
zonecfg_getdevperment(zone_dochandle_t handle,struct zone_devpermtab * tabptr)7050ee519a1fSgjelinek zonecfg_getdevperment(zone_dochandle_t handle, struct zone_devpermtab *tabptr)
7051ee519a1fSgjelinek {
7052ee519a1fSgjelinek xmlNodePtr cur;
7053ee519a1fSgjelinek int err;
7054ee519a1fSgjelinek char buf[128];
7055ee519a1fSgjelinek
7056ee519a1fSgjelinek tabptr->zone_devperm_acl = NULL;
7057ee519a1fSgjelinek
7058ee519a1fSgjelinek if (handle == NULL)
7059ee519a1fSgjelinek return (Z_INVAL);
7060ee519a1fSgjelinek
7061ee519a1fSgjelinek if ((cur = handle->zone_dh_cur) == NULL)
7062ee519a1fSgjelinek return (Z_NO_ENTRY);
7063ee519a1fSgjelinek
7064ee519a1fSgjelinek for (; cur != NULL; cur = cur->next)
7065ee519a1fSgjelinek if (!xmlStrcmp(cur->name, DTD_ELEM_DEV_PERM))
7066ee519a1fSgjelinek break;
7067ee519a1fSgjelinek if (cur == NULL) {
7068ee519a1fSgjelinek handle->zone_dh_cur = handle->zone_dh_top;
7069ee519a1fSgjelinek return (Z_NO_ENTRY);
7070ee519a1fSgjelinek }
7071ee519a1fSgjelinek
7072ee519a1fSgjelinek if ((err = fetchprop(cur, DTD_ATTR_NAME, tabptr->zone_devperm_name,
7073ee519a1fSgjelinek sizeof (tabptr->zone_devperm_name))) != Z_OK) {
7074ee519a1fSgjelinek handle->zone_dh_cur = handle->zone_dh_top;
7075ee519a1fSgjelinek return (err);
7076ee519a1fSgjelinek }
7077ee519a1fSgjelinek
7078ee519a1fSgjelinek if ((err = fetchprop(cur, DTD_ATTR_UID, buf, sizeof (buf))) != Z_OK) {
7079ee519a1fSgjelinek handle->zone_dh_cur = handle->zone_dh_top;
7080ee519a1fSgjelinek return (err);
7081ee519a1fSgjelinek }
7082ee519a1fSgjelinek tabptr->zone_devperm_uid = (uid_t)atol(buf);
7083ee519a1fSgjelinek
7084ee519a1fSgjelinek if ((err = fetchprop(cur, DTD_ATTR_GID, buf, sizeof (buf))) != Z_OK) {
7085ee519a1fSgjelinek handle->zone_dh_cur = handle->zone_dh_top;
7086ee519a1fSgjelinek return (err);
7087ee519a1fSgjelinek }
7088ee519a1fSgjelinek tabptr->zone_devperm_gid = (gid_t)atol(buf);
7089ee519a1fSgjelinek
7090ee519a1fSgjelinek if ((err = fetchprop(cur, DTD_ATTR_MODE, buf, sizeof (buf))) != Z_OK) {
7091ee519a1fSgjelinek handle->zone_dh_cur = handle->zone_dh_top;
7092ee519a1fSgjelinek return (err);
7093ee519a1fSgjelinek }
7094ee519a1fSgjelinek tabptr->zone_devperm_mode = (mode_t)strtol(buf, (char **)NULL, 8);
7095ee519a1fSgjelinek
7096ee519a1fSgjelinek if ((err = fetch_alloc_prop(cur, DTD_ATTR_ACL,
7097ee519a1fSgjelinek &(tabptr->zone_devperm_acl))) != Z_OK) {
7098ee519a1fSgjelinek handle->zone_dh_cur = handle->zone_dh_top;
7099ee519a1fSgjelinek return (err);
7100ee519a1fSgjelinek }
7101ee519a1fSgjelinek
7102ee519a1fSgjelinek handle->zone_dh_cur = cur->next;
7103ee519a1fSgjelinek return (Z_OK);
7104ee519a1fSgjelinek }
7105ee519a1fSgjelinek
7106ee519a1fSgjelinek int
zonecfg_enddevperment(zone_dochandle_t handle)7107ee519a1fSgjelinek zonecfg_enddevperment(zone_dochandle_t handle)
7108ee519a1fSgjelinek {
7109ee519a1fSgjelinek return (zonecfg_endent(handle));
7110ee519a1fSgjelinek }
7111ee519a1fSgjelinek
7112ff17c8bfSgjelinek /* PRINTFLIKE1 */
7113ff17c8bfSgjelinek static void
zerror(const char * zone_name,const char * fmt,...)7114ff17c8bfSgjelinek zerror(const char *zone_name, const char *fmt, ...)
711539935be5Sgjelinek {
7116ff17c8bfSgjelinek va_list alist;
711739935be5Sgjelinek
7118ff17c8bfSgjelinek va_start(alist, fmt);
7119ff17c8bfSgjelinek (void) fprintf(stderr, "zone '%s': ", zone_name);
7120ff17c8bfSgjelinek (void) vfprintf(stderr, fmt, alist);
7121ff17c8bfSgjelinek (void) fprintf(stderr, "\n");
7122ff17c8bfSgjelinek va_end(alist);
7123ee519a1fSgjelinek }
7124ee519a1fSgjelinek
7125ee519a1fSgjelinek static void
zperror(const char * str)7126ff17c8bfSgjelinek zperror(const char *str)
7127ee519a1fSgjelinek {
7128ff17c8bfSgjelinek (void) fprintf(stderr, "%s: %s\n", str, strerror(errno));
7129ee519a1fSgjelinek }
7130ee519a1fSgjelinek
7131ee519a1fSgjelinek /*
7132ff17c8bfSgjelinek * The following three routines implement a simple locking mechanism to
7133ff17c8bfSgjelinek * ensure that only one instance of zoneadm at a time is able to manipulate
7134ff17c8bfSgjelinek * a given zone. The lock is built on top of an fcntl(2) lock of
7135ff17c8bfSgjelinek * [<altroot>]/var/run/zones/<zonename>.zoneadm.lock. If a zoneadm instance
7136ff17c8bfSgjelinek * can grab that lock, it is allowed to manipulate the zone.
7137ff17c8bfSgjelinek *
7138ff17c8bfSgjelinek * Since zoneadm may call external applications which in turn invoke
7139ff17c8bfSgjelinek * zoneadm again, we introduce the notion of "lock inheritance". Any
7140ff17c8bfSgjelinek * instance of zoneadm that has another instance in its ancestry is assumed
7141ff17c8bfSgjelinek * to be acting on behalf of the original zoneadm, and is thus allowed to
7142ff17c8bfSgjelinek * manipulate its zone.
7143ff17c8bfSgjelinek *
7144ff17c8bfSgjelinek * This inheritance is implemented via the _ZONEADM_LOCK_HELD environment
7145ff17c8bfSgjelinek * variable. When zoneadm is granted a lock on its zone, this environment
7146ff17c8bfSgjelinek * variable is set to 1. When it releases the lock, the variable is set to
7147ff17c8bfSgjelinek * 0. Since a child process inherits its parent's environment, checking
7148ff17c8bfSgjelinek * the state of this variable indicates whether or not any ancestor owns
7149ff17c8bfSgjelinek * the lock.
715039935be5Sgjelinek */
7151ff17c8bfSgjelinek void
zonecfg_init_lock_file(const char * zone_name,char ** lock_env)7152ff17c8bfSgjelinek zonecfg_init_lock_file(const char *zone_name, char **lock_env)
715339935be5Sgjelinek {
7154ff17c8bfSgjelinek *lock_env = getenv(LOCK_ENV_VAR);
7155ff17c8bfSgjelinek if (*lock_env == NULL) {
7156ff17c8bfSgjelinek if (putenv(zoneadm_lock_not_held) != 0) {
7157ff17c8bfSgjelinek zerror(zone_name, gettext("could not set env: %s"),
7158ff17c8bfSgjelinek strerror(errno));
7159ff17c8bfSgjelinek exit(1);
7160ff17c8bfSgjelinek }
716139935be5Sgjelinek } else {
7162ff17c8bfSgjelinek if (atoi(*lock_env) == 1)
7163ff17c8bfSgjelinek zone_lock_cnt = 1;
716439935be5Sgjelinek }
716539935be5Sgjelinek }
716639935be5Sgjelinek
7167ff17c8bfSgjelinek void
zonecfg_release_lock_file(const char * zone_name,int lockfd)7168ff17c8bfSgjelinek zonecfg_release_lock_file(const char *zone_name, int lockfd)
7169ff17c8bfSgjelinek {
7170ff17c8bfSgjelinek /*
7171ff17c8bfSgjelinek * If we are cleaning up from a failed attempt to lock the zone for
7172ff17c8bfSgjelinek * the first time, we might have a zone_lock_cnt of 0. In that
7173ff17c8bfSgjelinek * error case, we don't want to do anything but close the lock
7174ff17c8bfSgjelinek * file.
7175ff17c8bfSgjelinek */
7176ff17c8bfSgjelinek assert(zone_lock_cnt >= 0);
7177ff17c8bfSgjelinek if (zone_lock_cnt > 0) {
7178ff17c8bfSgjelinek assert(getenv(LOCK_ENV_VAR) != NULL);
7179ff17c8bfSgjelinek assert(atoi(getenv(LOCK_ENV_VAR)) == 1);
7180ff17c8bfSgjelinek if (--zone_lock_cnt > 0) {
7181ff17c8bfSgjelinek assert(lockfd == -1);
7182ff17c8bfSgjelinek return;
718339935be5Sgjelinek }
7184ff17c8bfSgjelinek if (putenv(zoneadm_lock_not_held) != 0) {
7185ff17c8bfSgjelinek zerror(zone_name, gettext("could not set env: %s"),
7186ff17c8bfSgjelinek strerror(errno));
7187ff17c8bfSgjelinek exit(1);
7188ff17c8bfSgjelinek }
7189ff17c8bfSgjelinek }
7190ff17c8bfSgjelinek assert(lockfd >= 0);
7191ff17c8bfSgjelinek (void) close(lockfd);
719239935be5Sgjelinek }
719339935be5Sgjelinek
7194ff17c8bfSgjelinek int
zonecfg_grab_lock_file(const char * zone_name,int * lockfd)7195ff17c8bfSgjelinek zonecfg_grab_lock_file(const char *zone_name, int *lockfd)
7196ff17c8bfSgjelinek {
7197ff17c8bfSgjelinek char pathbuf[PATH_MAX];
7198ff17c8bfSgjelinek struct flock flock;
7199ff17c8bfSgjelinek
7200ff17c8bfSgjelinek /*
7201ff17c8bfSgjelinek * If we already have the lock, we can skip this expensive song
7202ff17c8bfSgjelinek * and dance.
7203ff17c8bfSgjelinek */
7204ff17c8bfSgjelinek assert(zone_lock_cnt >= 0);
7205ff17c8bfSgjelinek assert(getenv(LOCK_ENV_VAR) != NULL);
7206ff17c8bfSgjelinek if (zone_lock_cnt > 0) {
7207ff17c8bfSgjelinek assert(atoi(getenv(LOCK_ENV_VAR)) == 1);
7208ff17c8bfSgjelinek zone_lock_cnt++;
7209ff17c8bfSgjelinek *lockfd = -1;
721039935be5Sgjelinek return (Z_OK);
721139935be5Sgjelinek }
7212ff17c8bfSgjelinek assert(getenv(LOCK_ENV_VAR) != NULL);
7213ff17c8bfSgjelinek assert(atoi(getenv(LOCK_ENV_VAR)) == 0);
721439935be5Sgjelinek
7215ff17c8bfSgjelinek if (snprintf(pathbuf, sizeof (pathbuf), "%s%s", zonecfg_get_root(),
7216ff17c8bfSgjelinek ZONES_TMPDIR) >= sizeof (pathbuf)) {
7217ff17c8bfSgjelinek zerror(zone_name, gettext("alternate root path is too long"));
721839935be5Sgjelinek return (-1);
721939935be5Sgjelinek }
7220ff17c8bfSgjelinek if (mkdir(pathbuf, S_IRWXU) < 0 && errno != EEXIST) {
7221ff17c8bfSgjelinek zerror(zone_name, gettext("could not mkdir %s: %s"), pathbuf,
7222ff17c8bfSgjelinek strerror(errno));
7223ff17c8bfSgjelinek return (-1);
7224ff17c8bfSgjelinek }
7225ff17c8bfSgjelinek (void) chmod(pathbuf, S_IRWXU);
722639935be5Sgjelinek
722739935be5Sgjelinek /*
7228ff17c8bfSgjelinek * One of these lock files is created for each zone (when needed).
7229ff17c8bfSgjelinek * The lock files are not cleaned up (except on system reboot),
7230ff17c8bfSgjelinek * but since there is only one per zone, there is no resource
7231ff17c8bfSgjelinek * starvation issue.
723239935be5Sgjelinek */
7233ff17c8bfSgjelinek if (snprintf(pathbuf, sizeof (pathbuf), "%s%s/%s.zoneadm.lock",
7234ff17c8bfSgjelinek zonecfg_get_root(), ZONES_TMPDIR, zone_name) >= sizeof (pathbuf)) {
7235ff17c8bfSgjelinek zerror(zone_name, gettext("alternate root path is too long"));
7236ff17c8bfSgjelinek return (-1);
7237ff17c8bfSgjelinek }
7238ff17c8bfSgjelinek if ((*lockfd = open(pathbuf, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR)) < 0) {
7239ff17c8bfSgjelinek zerror(zone_name, gettext("could not open %s: %s"), pathbuf,
7240ff17c8bfSgjelinek strerror(errno));
7241ff17c8bfSgjelinek return (-1);
7242ff17c8bfSgjelinek }
7243ff17c8bfSgjelinek /*
7244ff17c8bfSgjelinek * Lock the file to synchronize with other zoneadmds
7245ff17c8bfSgjelinek */
7246ff17c8bfSgjelinek flock.l_type = F_WRLCK;
7247ff17c8bfSgjelinek flock.l_whence = SEEK_SET;
7248ff17c8bfSgjelinek flock.l_start = (off_t)0;
7249ff17c8bfSgjelinek flock.l_len = (off_t)0;
7250ff17c8bfSgjelinek if ((fcntl(*lockfd, F_SETLKW, &flock) < 0) ||
7251ff17c8bfSgjelinek (putenv(zoneadm_lock_held) != 0)) {
7252ff17c8bfSgjelinek zerror(zone_name, gettext("unable to lock %s: %s"), pathbuf,
7253ff17c8bfSgjelinek strerror(errno));
7254ff17c8bfSgjelinek zonecfg_release_lock_file(zone_name, *lockfd);
7255ff17c8bfSgjelinek return (-1);
7256ff17c8bfSgjelinek }
7257ff17c8bfSgjelinek zone_lock_cnt = 1;
7258ff17c8bfSgjelinek return (Z_OK);
7259ff17c8bfSgjelinek }
7260ff17c8bfSgjelinek
7261edfa49ffS boolean_t
zonecfg_lock_file_held(int * lockfd)7262edfa49ffS zonecfg_lock_file_held(int *lockfd)
7263edfa49ffS {
7264edfa49ffS if (*lockfd >= 0 || zone_lock_cnt > 0)
7265edfa49ffS return (B_TRUE);
7266edfa49ffS return (B_FALSE);
7267edfa49ffS }
7268edfa49ffS
7269ff17c8bfSgjelinek static boolean_t
get_doorname(const char * zone_name,char * buffer)7270ff17c8bfSgjelinek get_doorname(const char *zone_name, char *buffer)
727139935be5Sgjelinek {
7272ff17c8bfSgjelinek return (snprintf(buffer, PATH_MAX, "%s" ZONE_DOOR_PATH,
7273ff17c8bfSgjelinek zonecfg_get_root(), zone_name) < PATH_MAX);
7274e66285fdSgjelinek }
7275ee519a1fSgjelinek
7276ee519a1fSgjelinek /*
7277ff17c8bfSgjelinek * system daemons are not audited. For the global zone, this occurs
7278ff17c8bfSgjelinek * "naturally" since init is started with the default audit
7279ff17c8bfSgjelinek * characteristics. Since zoneadmd is a system daemon and it starts
7280ff17c8bfSgjelinek * init for a zone, it is necessary to clear out the audit
7281ff17c8bfSgjelinek * characteristics inherited from whomever started zoneadmd. This is
7282ff17c8bfSgjelinek * indicated by the audit id, which is set from the ruid parameter of
7283ff17c8bfSgjelinek * adt_set_user(), below.
7284ee519a1fSgjelinek */
7285ff17c8bfSgjelinek
7286ff17c8bfSgjelinek static void
prepare_audit_context(const char * zone_name)7287ff17c8bfSgjelinek prepare_audit_context(const char *zone_name)
7288ff17c8bfSgjelinek {
7289ff17c8bfSgjelinek adt_session_data_t *ah;
7290ff17c8bfSgjelinek char *failure = gettext("audit failure: %s");
7291ff17c8bfSgjelinek
7292ff17c8bfSgjelinek if (adt_start_session(&ah, NULL, 0)) {
7293ff17c8bfSgjelinek zerror(zone_name, failure, strerror(errno));
7294ff17c8bfSgjelinek return;
7295ff17c8bfSgjelinek }
7296ff17c8bfSgjelinek if (adt_set_user(ah, ADT_NO_AUDIT, ADT_NO_AUDIT,
7297ff17c8bfSgjelinek ADT_NO_AUDIT, ADT_NO_AUDIT, NULL, ADT_NEW)) {
7298ff17c8bfSgjelinek zerror(zone_name, failure, strerror(errno));
7299ff17c8bfSgjelinek (void) adt_end_session(ah);
7300ff17c8bfSgjelinek return;
7301ff17c8bfSgjelinek }
7302ff17c8bfSgjelinek if (adt_set_proc(ah))
7303ff17c8bfSgjelinek zerror(zone_name, failure, strerror(errno));
7304ff17c8bfSgjelinek
7305ff17c8bfSgjelinek (void) adt_end_session(ah);
7306ff17c8bfSgjelinek }
7307ff17c8bfSgjelinek
7308ff17c8bfSgjelinek static int
start_zoneadmd(const char * zone_name,boolean_t lock)7309ff17c8bfSgjelinek start_zoneadmd(const char *zone_name, boolean_t lock)
7310ff17c8bfSgjelinek {
7311ff17c8bfSgjelinek char doorpath[PATH_MAX];
7312ff17c8bfSgjelinek pid_t child_pid;
7313ff17c8bfSgjelinek int error = -1;
7314ff17c8bfSgjelinek int doorfd, lockfd;
7315ff17c8bfSgjelinek struct door_info info;
7316ff17c8bfSgjelinek
7317ff17c8bfSgjelinek if (!get_doorname(zone_name, doorpath))
7318ff17c8bfSgjelinek return (-1);
7319ff17c8bfSgjelinek
7320ff17c8bfSgjelinek if (lock)
7321ff17c8bfSgjelinek if (zonecfg_grab_lock_file(zone_name, &lockfd) != Z_OK)
7322ff17c8bfSgjelinek return (-1);
7323ff17c8bfSgjelinek
7324ff17c8bfSgjelinek /*
7325ff17c8bfSgjelinek * Now that we have the lock, re-confirm that the daemon is
7326ff17c8bfSgjelinek * *not* up and working fine. If it is still down, we have a green
7327ff17c8bfSgjelinek * light to start it.
7328ff17c8bfSgjelinek */
7329ff17c8bfSgjelinek if ((doorfd = open(doorpath, O_RDONLY)) < 0) {
7330ff17c8bfSgjelinek if (errno != ENOENT) {
7331ff17c8bfSgjelinek zperror(doorpath);
7332ff17c8bfSgjelinek goto out;
7333ff17c8bfSgjelinek }
7334ff17c8bfSgjelinek } else {
7335ff17c8bfSgjelinek if (door_info(doorfd, &info) == 0 &&
7336ff17c8bfSgjelinek ((info.di_attributes & DOOR_REVOKED) == 0)) {
7337ff17c8bfSgjelinek error = Z_OK;
7338ff17c8bfSgjelinek (void) close(doorfd);
7339ff17c8bfSgjelinek goto out;
7340ff17c8bfSgjelinek }
7341ff17c8bfSgjelinek (void) close(doorfd);
7342ff17c8bfSgjelinek }
7343ff17c8bfSgjelinek
7344ff17c8bfSgjelinek if ((child_pid = fork()) == -1) {
7345ff17c8bfSgjelinek zperror(gettext("could not fork"));
7346ff17c8bfSgjelinek goto out;
7347ff17c8bfSgjelinek }
7348ff17c8bfSgjelinek
7349ff17c8bfSgjelinek if (child_pid == 0) {
7350ff17c8bfSgjelinek const char *argv[6], **ap;
7351ff17c8bfSgjelinek
7352ff17c8bfSgjelinek /* child process */
7353ff17c8bfSgjelinek prepare_audit_context(zone_name);
7354ff17c8bfSgjelinek
7355ff17c8bfSgjelinek ap = argv;
7356ff17c8bfSgjelinek *ap++ = "zoneadmd";
7357ff17c8bfSgjelinek *ap++ = "-z";
7358ff17c8bfSgjelinek *ap++ = zone_name;
7359ff17c8bfSgjelinek if (zonecfg_in_alt_root()) {
7360ff17c8bfSgjelinek *ap++ = "-R";
7361ff17c8bfSgjelinek *ap++ = zonecfg_get_root();
7362ff17c8bfSgjelinek }
7363ff17c8bfSgjelinek *ap = NULL;
7364ff17c8bfSgjelinek
7365ff17c8bfSgjelinek (void) execv("/usr/lib/zones/zoneadmd", (char * const *)argv);
7366ff17c8bfSgjelinek /*
7367ff17c8bfSgjelinek * TRANSLATION_NOTE
7368ff17c8bfSgjelinek * zoneadmd is a literal that should not be translated.
7369ff17c8bfSgjelinek */
7370ff17c8bfSgjelinek zperror(gettext("could not exec zoneadmd"));
7371ff17c8bfSgjelinek _exit(1);
7372ff17c8bfSgjelinek } else {
7373ff17c8bfSgjelinek /* parent process */
7374ff17c8bfSgjelinek pid_t retval;
7375ff17c8bfSgjelinek int pstatus = 0;
7376ee519a1fSgjelinek
7377ee519a1fSgjelinek do {
7378ff17c8bfSgjelinek retval = waitpid(child_pid, &pstatus, 0);
7379ff17c8bfSgjelinek } while (retval != child_pid);
7380ff17c8bfSgjelinek if (WIFSIGNALED(pstatus) || (WIFEXITED(pstatus) &&
7381ff17c8bfSgjelinek WEXITSTATUS(pstatus) != 0)) {
7382ff17c8bfSgjelinek zerror(zone_name, gettext("could not start %s"),
7383ff17c8bfSgjelinek "zoneadmd");
7384ff17c8bfSgjelinek goto out;
73856cfd72c6Sgjelinek }
73866cfd72c6Sgjelinek }
7387ff17c8bfSgjelinek error = Z_OK;
7388ff17c8bfSgjelinek out:
7389ff17c8bfSgjelinek if (lock)
7390ff17c8bfSgjelinek zonecfg_release_lock_file(zone_name, lockfd);
7391ff17c8bfSgjelinek return (error);
7392ee519a1fSgjelinek }
7393ee519a1fSgjelinek
7394ee519a1fSgjelinek int
zonecfg_ping_zoneadmd(const char * zone_name)7395ff17c8bfSgjelinek zonecfg_ping_zoneadmd(const char *zone_name)
7396ee519a1fSgjelinek {
7397ff17c8bfSgjelinek char doorpath[PATH_MAX];
7398ff17c8bfSgjelinek int doorfd;
7399ff17c8bfSgjelinek struct door_info info;
7400ee519a1fSgjelinek
7401ff17c8bfSgjelinek if (!get_doorname(zone_name, doorpath))
7402ff17c8bfSgjelinek return (-1);
7403ee519a1fSgjelinek
7404ff17c8bfSgjelinek if ((doorfd = open(doorpath, O_RDONLY)) < 0) {
7405ff17c8bfSgjelinek return (-1);
7406ff17c8bfSgjelinek }
7407ff17c8bfSgjelinek if (door_info(doorfd, &info) == 0 &&
7408ff17c8bfSgjelinek ((info.di_attributes & DOOR_REVOKED) == 0)) {
7409ff17c8bfSgjelinek (void) close(doorfd);
7410ff17c8bfSgjelinek return (Z_OK);
7411ff17c8bfSgjelinek }
7412ff17c8bfSgjelinek (void) close(doorfd);
7413ff17c8bfSgjelinek return (-1);
7414ff17c8bfSgjelinek }
7415ee519a1fSgjelinek
7416ff17c8bfSgjelinek int
zonecfg_call_zoneadmd(const char * zone_name,zone_cmd_arg_t * arg,char * locale,boolean_t lock)7417ff17c8bfSgjelinek zonecfg_call_zoneadmd(const char *zone_name, zone_cmd_arg_t *arg, char *locale,
7418ff17c8bfSgjelinek boolean_t lock)
7419ff17c8bfSgjelinek {
7420ff17c8bfSgjelinek char doorpath[PATH_MAX];
7421ff17c8bfSgjelinek int doorfd, result;
7422ff17c8bfSgjelinek door_arg_t darg;
7423ff17c8bfSgjelinek
7424ff17c8bfSgjelinek zoneid_t zoneid;
7425ff17c8bfSgjelinek uint64_t uniqid = 0;
7426ff17c8bfSgjelinek
7427ff17c8bfSgjelinek zone_cmd_rval_t *rvalp;
7428ff17c8bfSgjelinek size_t rlen;
7429ff17c8bfSgjelinek char *cp, *errbuf;
7430ff17c8bfSgjelinek
7431ff17c8bfSgjelinek rlen = getpagesize();
7432ff17c8bfSgjelinek if ((rvalp = malloc(rlen)) == NULL) {
7433ff17c8bfSgjelinek zerror(zone_name, gettext("failed to allocate %lu bytes: %s"),
7434ff17c8bfSgjelinek rlen, strerror(errno));
7435ff17c8bfSgjelinek return (-1);
7436ff17c8bfSgjelinek }
7437ff17c8bfSgjelinek
7438ff17c8bfSgjelinek if ((zoneid = getzoneidbyname(zone_name)) != ZONE_ID_UNDEFINED) {
7439ff17c8bfSgjelinek (void) zone_getattr(zoneid, ZONE_ATTR_UNIQID, &uniqid,
7440ff17c8bfSgjelinek sizeof (uniqid));
7441ff17c8bfSgjelinek }
7442ff17c8bfSgjelinek arg->uniqid = uniqid;
7443ff17c8bfSgjelinek (void) strlcpy(arg->locale, locale, sizeof (arg->locale));
7444ff17c8bfSgjelinek if (!get_doorname(zone_name, doorpath)) {
7445ff17c8bfSgjelinek zerror(zone_name, gettext("alternate root path is too long"));
7446ff17c8bfSgjelinek free(rvalp);
7447ff17c8bfSgjelinek return (-1);
7448ff17c8bfSgjelinek }
7449ff17c8bfSgjelinek
7450ff17c8bfSgjelinek /*
7451ff17c8bfSgjelinek * Loop trying to start zoneadmd; if something goes seriously
7452ff17c8bfSgjelinek * wrong we break out and fail.
7453ff17c8bfSgjelinek */
7454ff17c8bfSgjelinek for (;;) {
7455ff17c8bfSgjelinek if (start_zoneadmd(zone_name, lock) != Z_OK)
7456ff17c8bfSgjelinek break;
7457ff17c8bfSgjelinek
7458ff17c8bfSgjelinek if ((doorfd = open(doorpath, O_RDONLY)) < 0) {
7459ff17c8bfSgjelinek zperror(gettext("failed to open zone door"));
7460ff17c8bfSgjelinek break;
7461ff17c8bfSgjelinek }
7462ff17c8bfSgjelinek
7463ff17c8bfSgjelinek darg.data_ptr = (char *)arg;
7464ff17c8bfSgjelinek darg.data_size = sizeof (*arg);
7465ff17c8bfSgjelinek darg.desc_ptr = NULL;
7466ff17c8bfSgjelinek darg.desc_num = 0;
7467ff17c8bfSgjelinek darg.rbuf = (char *)rvalp;
7468ff17c8bfSgjelinek darg.rsize = rlen;
7469ff17c8bfSgjelinek if (door_call(doorfd, &darg) != 0) {
7470ff17c8bfSgjelinek (void) close(doorfd);
7471ff17c8bfSgjelinek /*
7472ff17c8bfSgjelinek * We'll get EBADF if the door has been revoked.
7473ff17c8bfSgjelinek */
7474ff17c8bfSgjelinek if (errno != EBADF) {
7475ff17c8bfSgjelinek zperror(gettext("door_call failed"));
7476ff17c8bfSgjelinek break;
7477ff17c8bfSgjelinek }
7478ff17c8bfSgjelinek continue; /* take another lap */
7479ff17c8bfSgjelinek }
7480ff17c8bfSgjelinek (void) close(doorfd);
7481ff17c8bfSgjelinek
7482ff17c8bfSgjelinek if (darg.data_size == 0) {
7483ff17c8bfSgjelinek /* Door server is going away; kick it again. */
7484ff17c8bfSgjelinek continue;
7485ff17c8bfSgjelinek }
7486ff17c8bfSgjelinek
7487ff17c8bfSgjelinek errbuf = rvalp->errbuf;
7488ff17c8bfSgjelinek while (*errbuf != '\0') {
7489ff17c8bfSgjelinek /*
7490ff17c8bfSgjelinek * Remove any newlines since zerror()
7491ff17c8bfSgjelinek * will append one automatically.
7492ff17c8bfSgjelinek */
7493ff17c8bfSgjelinek cp = strchr(errbuf, '\n');
7494ff17c8bfSgjelinek if (cp != NULL)
7495ff17c8bfSgjelinek *cp = '\0';
7496ff17c8bfSgjelinek zerror(zone_name, "%s", errbuf);
7497ff17c8bfSgjelinek if (cp == NULL)
7498ff17c8bfSgjelinek break;
7499ff17c8bfSgjelinek errbuf = cp + 1;
7500ff17c8bfSgjelinek }
7501ff17c8bfSgjelinek result = rvalp->rval == 0 ? 0 : -1;
7502ff17c8bfSgjelinek free(rvalp);
7503ff17c8bfSgjelinek return (result);
7504ff17c8bfSgjelinek }
7505ff17c8bfSgjelinek
7506ff17c8bfSgjelinek free(rvalp);
7507ff17c8bfSgjelinek return (-1);
7508ee519a1fSgjelinek }
7509cb8a054bSGlenn Faden
7510cb8a054bSGlenn Faden boolean_t
zonecfg_valid_auths(const char * auths,const char * zonename)7511cb8a054bSGlenn Faden zonecfg_valid_auths(const char *auths, const char *zonename)
7512cb8a054bSGlenn Faden {
7513cb8a054bSGlenn Faden char *right;
7514cb8a054bSGlenn Faden char *tmpauths;
7515cb8a054bSGlenn Faden char *lasts;
7516cb8a054bSGlenn Faden char authname[MAXAUTHS];
7517cb8a054bSGlenn Faden boolean_t status = B_TRUE;
7518cb8a054bSGlenn Faden
7519cb8a054bSGlenn Faden tmpauths = strdup(auths);
7520cb8a054bSGlenn Faden if (tmpauths == NULL) {
7521cb8a054bSGlenn Faden zerror(zonename, gettext("Out of memory"));
7522cb8a054bSGlenn Faden return (B_FALSE);
7523cb8a054bSGlenn Faden }
7524cb8a054bSGlenn Faden right = strtok_r(tmpauths, ",", &lasts);
7525cb8a054bSGlenn Faden while (right != NULL) {
7526cb8a054bSGlenn Faden (void) snprintf(authname, MAXAUTHS, "%s%s",
7527cb8a054bSGlenn Faden ZONE_AUTH_PREFIX, right);
7528cb8a054bSGlenn Faden if (getauthnam(authname) == NULL) {
7529cb8a054bSGlenn Faden status = B_FALSE;
7530a20ee416SGlenn Faden zerror(zonename,
7531d77d83efSGlenn Faden gettext("'%s' is not a valid authorization"),
7532cb8a054bSGlenn Faden right);
7533cb8a054bSGlenn Faden }
7534cb8a054bSGlenn Faden right = strtok_r(NULL, ",", &lasts);
7535cb8a054bSGlenn Faden }
7536cb8a054bSGlenn Faden free(tmpauths);
7537cb8a054bSGlenn Faden return (status);
7538cb8a054bSGlenn Faden }
7539cb8a054bSGlenn Faden
7540cb8a054bSGlenn Faden int
zonecfg_delete_admins(zone_dochandle_t handle,char * zonename)7541cb8a054bSGlenn Faden zonecfg_delete_admins(zone_dochandle_t handle, char *zonename)
7542cb8a054bSGlenn Faden {
7543cb8a054bSGlenn Faden int err;
7544cb8a054bSGlenn Faden struct zone_admintab admintab;
7545cb8a054bSGlenn Faden boolean_t changed = B_FALSE;
7546cb8a054bSGlenn Faden
7547cb8a054bSGlenn Faden if ((err = zonecfg_setadminent(handle)) != Z_OK) {
7548cb8a054bSGlenn Faden return (err);
7549cb8a054bSGlenn Faden }
7550cb8a054bSGlenn Faden while (zonecfg_getadminent(handle, &admintab) == Z_OK) {
7551cb8a054bSGlenn Faden err = zonecfg_delete_admin(handle, &admintab,
7552cb8a054bSGlenn Faden zonename);
7553cb8a054bSGlenn Faden if (err != Z_OK) {
7554cb8a054bSGlenn Faden (void) zonecfg_endadminent(handle);
7555cb8a054bSGlenn Faden return (err);
7556cb8a054bSGlenn Faden } else {
7557cb8a054bSGlenn Faden changed = B_TRUE;
7558cb8a054bSGlenn Faden }
7559cb8a054bSGlenn Faden if ((err = zonecfg_setadminent(handle)) != Z_OK) {
7560cb8a054bSGlenn Faden return (err);
7561cb8a054bSGlenn Faden }
7562cb8a054bSGlenn Faden }
7563cb8a054bSGlenn Faden (void) zonecfg_endadminent(handle);
7564cb8a054bSGlenn Faden return (changed? Z_OK:Z_NO_ENTRY);
7565cb8a054bSGlenn Faden }
7566cb8a054bSGlenn Faden
7567cb8a054bSGlenn Faden /*
7568cb8a054bSGlenn Faden * Checks if a long authorization applies to this zone.
7569cb8a054bSGlenn Faden * If so, it returns true, after destructively stripping
7570cb8a054bSGlenn Faden * the authorization of its prefix and zone suffix.
7571cb8a054bSGlenn Faden */
7572cb8a054bSGlenn Faden static boolean_t
is_zone_auth(char ** auth,char * zonename,char * oldzonename)7573cb8a054bSGlenn Faden is_zone_auth(char **auth, char *zonename, char *oldzonename)
7574cb8a054bSGlenn Faden {
7575cb8a054bSGlenn Faden char *suffix;
7576cb8a054bSGlenn Faden size_t offset;
7577cb8a054bSGlenn Faden
7578cb8a054bSGlenn Faden offset = strlen(ZONE_AUTH_PREFIX);
7579cb8a054bSGlenn Faden if ((strncmp(*auth, ZONE_AUTH_PREFIX, offset) == 0) &&
7580cb8a054bSGlenn Faden ((suffix = strchr(*auth, '/')) != NULL)) {
7581d77d83efSGlenn Faden if (strcmp(suffix + 1, zonename) == 0) {
7582cb8a054bSGlenn Faden *auth += offset;
7583cb8a054bSGlenn Faden suffix[0] = '\0';
7584cb8a054bSGlenn Faden return (B_TRUE);
7585cb8a054bSGlenn Faden } else if ((oldzonename != NULL) &&
7586d77d83efSGlenn Faden (strcmp(suffix + 1, oldzonename) == 0)) {
7587cb8a054bSGlenn Faden *auth += offset;
7588cb8a054bSGlenn Faden suffix[0] = '\0';
7589cb8a054bSGlenn Faden return (B_TRUE);
7590cb8a054bSGlenn Faden }
7591cb8a054bSGlenn Faden }
7592cb8a054bSGlenn Faden return (B_FALSE);
7593cb8a054bSGlenn Faden }
7594cb8a054bSGlenn Faden
7595cb8a054bSGlenn Faden /*
7596cb8a054bSGlenn Faden * This function determines whether the zone-specific authorization
7597cb8a054bSGlenn Faden * assignments in /etc/user_attr have been changed more recently
7598cb8a054bSGlenn Faden * than the equivalent data stored in the zone's configuration file.
7599cb8a054bSGlenn Faden * This should only happen if the zone-specific authorizations in
7600cb8a054bSGlenn Faden * the user_attr file were modified using a tool other than zonecfg.
7601cb8a054bSGlenn Faden * If the configuration file is out-of-date with respect to these
7602cb8a054bSGlenn Faden * authorization assignments, it is updated to match those specified
7603cb8a054bSGlenn Faden * in /etc/user_attr.
7604cb8a054bSGlenn Faden */
7605cb8a054bSGlenn Faden
7606cb8a054bSGlenn Faden int
zonecfg_update_userauths(zone_dochandle_t handle,char * zonename)7607cb8a054bSGlenn Faden zonecfg_update_userauths(zone_dochandle_t handle, char *zonename)
7608cb8a054bSGlenn Faden {
7609cb8a054bSGlenn Faden userattr_t *ua_ptr;
7610cb8a054bSGlenn Faden char *authlist;
7611cb8a054bSGlenn Faden char *lasts;
7612cb8a054bSGlenn Faden FILE *uaf;
7613cb8a054bSGlenn Faden struct zone_admintab admintab;
7614cb8a054bSGlenn Faden struct stat config_st, ua_st;
7615cb8a054bSGlenn Faden char config_file[MAXPATHLEN];
7616cb8a054bSGlenn Faden boolean_t changed = B_FALSE;
7617cb8a054bSGlenn Faden int err;
7618cb8a054bSGlenn Faden
7619cb8a054bSGlenn Faden if ((uaf = fopen(USERATTR_FILENAME, "r")) == NULL) {
7620cb8a054bSGlenn Faden zerror(zonename, gettext("could not open file %s: %s"),
7621cb8a054bSGlenn Faden USERATTR_FILENAME, strerror(errno));
7622cb8a054bSGlenn Faden if (errno == EACCES)
7623cb8a054bSGlenn Faden return (Z_ACCES);
7624cb8a054bSGlenn Faden if (errno == ENOENT)
7625cb8a054bSGlenn Faden return (Z_NO_ZONE);
7626cb8a054bSGlenn Faden return (Z_MISC_FS);
7627cb8a054bSGlenn Faden }
7628cb8a054bSGlenn Faden if ((err = fstat(fileno(uaf), &ua_st)) != 0) {
7629cb8a054bSGlenn Faden zerror(zonename, gettext("could not stat file %s: %s"),
7630cb8a054bSGlenn Faden USERATTR_FILENAME, strerror(errno));
7631cb8a054bSGlenn Faden (void) fclose(uaf);
7632cb8a054bSGlenn Faden return (Z_MISC_FS);
7633cb8a054bSGlenn Faden }
7634cb8a054bSGlenn Faden if (!config_file_path(zonename, config_file)) {
7635cb8a054bSGlenn Faden (void) fclose(uaf);
7636cb8a054bSGlenn Faden return (Z_MISC_FS);
7637cb8a054bSGlenn Faden }
7638cb8a054bSGlenn Faden
7639cb8a054bSGlenn Faden if ((err = stat(config_file, &config_st)) != 0) {
7640cb8a054bSGlenn Faden zerror(zonename, gettext("could not stat file %s: %s"),
7641cb8a054bSGlenn Faden config_file, strerror(errno));
7642cb8a054bSGlenn Faden (void) fclose(uaf);
7643cb8a054bSGlenn Faden return (Z_MISC_FS);
7644cb8a054bSGlenn Faden }
7645cb8a054bSGlenn Faden if (config_st.st_mtime >= ua_st.st_mtime) {
7646cb8a054bSGlenn Faden (void) fclose(uaf);
7647cb8a054bSGlenn Faden return (Z_NO_ENTRY);
7648cb8a054bSGlenn Faden }
7649cb8a054bSGlenn Faden if ((err = zonecfg_delete_admins(handle, zonename)) == Z_OK) {
7650cb8a054bSGlenn Faden changed = B_TRUE;
7651cb8a054bSGlenn Faden } else if (err != Z_NO_ENTRY) {
7652cb8a054bSGlenn Faden (void) fclose(uaf);
7653cb8a054bSGlenn Faden return (err);
7654cb8a054bSGlenn Faden }
7655cb8a054bSGlenn Faden while ((ua_ptr = fgetuserattr(uaf)) != NULL) {
7656cb8a054bSGlenn Faden if (ua_ptr->name[0] == '#') {
7657cb8a054bSGlenn Faden continue;
7658cb8a054bSGlenn Faden }
7659cb8a054bSGlenn Faden authlist = kva_match(ua_ptr->attr, USERATTR_AUTHS_KW);
7660cb8a054bSGlenn Faden if (authlist != NULL) {
7661cb8a054bSGlenn Faden char *cur_auth;
7662cb8a054bSGlenn Faden boolean_t first;
7663cb8a054bSGlenn Faden
7664cb8a054bSGlenn Faden first = B_TRUE;
7665cb8a054bSGlenn Faden bzero(&admintab.zone_admin_auths, MAXAUTHS);
7666cb8a054bSGlenn Faden cur_auth = strtok_r(authlist, ",", &lasts);
7667cb8a054bSGlenn Faden while (cur_auth != NULL) {
7668cb8a054bSGlenn Faden if (is_zone_auth(&cur_auth, zonename,
7669cb8a054bSGlenn Faden NULL)) {
7670cb8a054bSGlenn Faden /*
7671cb8a054bSGlenn Faden * Add auths for this zone
7672cb8a054bSGlenn Faden */
7673cb8a054bSGlenn Faden if (first) {
7674cb8a054bSGlenn Faden first = B_FALSE;
7675cb8a054bSGlenn Faden } else {
7676cb8a054bSGlenn Faden (void) strlcat(
7677cb8a054bSGlenn Faden admintab.zone_admin_auths,
7678cb8a054bSGlenn Faden ",", MAXAUTHS);
7679cb8a054bSGlenn Faden }
7680cb8a054bSGlenn Faden (void) strlcat(
7681cb8a054bSGlenn Faden admintab.zone_admin_auths,
7682cb8a054bSGlenn Faden cur_auth, MAXAUTHS);
7683cb8a054bSGlenn Faden }
7684cb8a054bSGlenn Faden cur_auth = strtok_r(NULL, ",", &lasts);
7685cb8a054bSGlenn Faden }
7686cb8a054bSGlenn Faden if (!first) {
7687cb8a054bSGlenn Faden /*
7688cb8a054bSGlenn Faden * Add this right to config file
7689cb8a054bSGlenn Faden */
7690cb8a054bSGlenn Faden (void) strlcpy(admintab.zone_admin_user,
7691cb8a054bSGlenn Faden ua_ptr->name,
7692cb8a054bSGlenn Faden sizeof (admintab.zone_admin_user));
7693cb8a054bSGlenn Faden err = zonecfg_add_admin(handle,
7694cb8a054bSGlenn Faden &admintab, zonename);
7695cb8a054bSGlenn Faden if (err != Z_OK) {
7696cb8a054bSGlenn Faden (void) fclose(uaf);
7697cb8a054bSGlenn Faden return (err);
7698cb8a054bSGlenn Faden } else {
7699cb8a054bSGlenn Faden changed = B_TRUE;
7700cb8a054bSGlenn Faden }
7701cb8a054bSGlenn Faden }
7702cb8a054bSGlenn Faden }
7703cb8a054bSGlenn Faden } /* end-of-while-loop */
7704cb8a054bSGlenn Faden (void) fclose(uaf);
7705cb8a054bSGlenn Faden return (changed? Z_OK: Z_NO_ENTRY);
7706cb8a054bSGlenn Faden }
7707cb8a054bSGlenn Faden
7708cb8a054bSGlenn Faden static void
update_profiles(char * rbac_profs,boolean_t add)7709cb8a054bSGlenn Faden update_profiles(char *rbac_profs, boolean_t add)
7710cb8a054bSGlenn Faden {
7711cb8a054bSGlenn Faden char new_profs[MAXPROFS];
7712cb8a054bSGlenn Faden char *cur_prof;
7713cb8a054bSGlenn Faden boolean_t first = B_TRUE;
7714cb8a054bSGlenn Faden boolean_t found = B_FALSE;
7715cb8a054bSGlenn Faden char *lasts;
7716cb8a054bSGlenn Faden
7717cb8a054bSGlenn Faden cur_prof = strtok_r(rbac_profs, ",", &lasts);
7718cb8a054bSGlenn Faden while (cur_prof != NULL) {
7719cb8a054bSGlenn Faden if (strcmp(cur_prof, ZONE_MGMT_PROF) == 0) {
7720cb8a054bSGlenn Faden found = B_TRUE;
7721cb8a054bSGlenn Faden if (!add) {
7722cb8a054bSGlenn Faden cur_prof = strtok_r(NULL, ",", &lasts);
7723cb8a054bSGlenn Faden continue;
7724cb8a054bSGlenn Faden }
7725cb8a054bSGlenn Faden }
7726cb8a054bSGlenn Faden if (first) {
7727cb8a054bSGlenn Faden first = B_FALSE;
7728cb8a054bSGlenn Faden } else {
7729cb8a054bSGlenn Faden (void) strlcat(new_profs, ",",
7730cb8a054bSGlenn Faden MAXPROFS);
7731cb8a054bSGlenn Faden }
7732cb8a054bSGlenn Faden (void) strlcat(new_profs, cur_prof,
7733cb8a054bSGlenn Faden MAXPROFS);
7734cb8a054bSGlenn Faden cur_prof = strtok_r(NULL, ",", &lasts);
7735cb8a054bSGlenn Faden }
7736cb8a054bSGlenn Faden /*
7737cb8a054bSGlenn Faden * Now prepend the Zone Management profile at the beginning
7738cb8a054bSGlenn Faden * of the list if it is needed, and append the rest.
7739cb8a054bSGlenn Faden * Return the updated list in the original buffer.
7740cb8a054bSGlenn Faden */
7741cb8a054bSGlenn Faden if (add && !found) {
7742cb8a054bSGlenn Faden first = B_FALSE;
7743cb8a054bSGlenn Faden (void) strlcpy(rbac_profs, ZONE_MGMT_PROF, MAXPROFS);
7744cb8a054bSGlenn Faden } else {
7745cb8a054bSGlenn Faden first = B_TRUE;
7746cb8a054bSGlenn Faden rbac_profs[0] = '\0';
7747cb8a054bSGlenn Faden }
7748cb8a054bSGlenn Faden if (strlen(new_profs) > 0) {
7749cb8a054bSGlenn Faden if (!first)
7750cb8a054bSGlenn Faden (void) strlcat(rbac_profs, ",", MAXPROFS);
7751cb8a054bSGlenn Faden (void) strlcat(rbac_profs, new_profs, MAXPROFS);
7752cb8a054bSGlenn Faden }
7753cb8a054bSGlenn Faden }
7754cb8a054bSGlenn Faden
7755cb8a054bSGlenn Faden #define MAX_CMD_LEN 1024
7756cb8a054bSGlenn Faden
7757cb8a054bSGlenn Faden static int
do_subproc(char * zonename,char * cmdbuf)7758cb8a054bSGlenn Faden do_subproc(char *zonename, char *cmdbuf)
7759cb8a054bSGlenn Faden {
7760cb8a054bSGlenn Faden char inbuf[MAX_CMD_LEN];
7761cb8a054bSGlenn Faden FILE *file;
7762cb8a054bSGlenn Faden int status;
7763cb8a054bSGlenn Faden
7764cb8a054bSGlenn Faden file = popen(cmdbuf, "r");
7765cb8a054bSGlenn Faden if (file == NULL) {
7766cb8a054bSGlenn Faden zerror(zonename, gettext("Could not launch: %s"), cmdbuf);
7767cb8a054bSGlenn Faden return (-1);
7768cb8a054bSGlenn Faden }
7769cb8a054bSGlenn Faden
7770cb8a054bSGlenn Faden while (fgets(inbuf, sizeof (inbuf), file) != NULL)
7771cb8a054bSGlenn Faden (void) fprintf(stderr, "%s", inbuf);
7772cb8a054bSGlenn Faden status = pclose(file);
7773cb8a054bSGlenn Faden
7774cb8a054bSGlenn Faden if (WIFSIGNALED(status)) {
7775cb8a054bSGlenn Faden zerror(zonename, gettext("%s unexpectedly terminated "
7776cb8a054bSGlenn Faden "due to signal %d"),
7777cb8a054bSGlenn Faden cmdbuf, WTERMSIG(status));
7778cb8a054bSGlenn Faden return (-1);
7779cb8a054bSGlenn Faden }
7780cb8a054bSGlenn Faden assert(WIFEXITED(status));
7781cb8a054bSGlenn Faden return (WEXITSTATUS(status));
7782cb8a054bSGlenn Faden }
7783cb8a054bSGlenn Faden
7784cb8a054bSGlenn Faden /*
7785cb8a054bSGlenn Faden * This function updates the local /etc/user_attr file to
7786cb8a054bSGlenn Faden * correspond to the admin settings that are currently being
7787cb8a054bSGlenn Faden * committed. The updates are done via usermod and/or rolemod
7788cb8a054bSGlenn Faden * depending on the type of the specified user. It is also
7789cb8a054bSGlenn Faden * invoked to remove entries from user_attr corresponding to
7790cb8a054bSGlenn Faden * removed admin assignments, using an empty auths string.
7791cb8a054bSGlenn Faden *
7792cb8a054bSGlenn Faden * Because the removed entries are no longer included in the
7793cb8a054bSGlenn Faden * cofiguration that is being committed, a linked list of
7794cb8a054bSGlenn Faden * removed admin entries is maintained to keep track of such
7795cb8a054bSGlenn Faden * transactions. The head of the list is stored in the zone_dh_userauths
7796cb8a054bSGlenn Faden * element of the handle strcture.
7797cb8a054bSGlenn Faden */
7798cb8a054bSGlenn Faden static int
zonecfg_authorize_user_impl(zone_dochandle_t handle,char * user,char * auths,char * zonename)7799cb8a054bSGlenn Faden zonecfg_authorize_user_impl(zone_dochandle_t handle, char *user,
7800cb8a054bSGlenn Faden char *auths, char *zonename)
7801cb8a054bSGlenn Faden {
7802cb8a054bSGlenn Faden char *right;
7803cb8a054bSGlenn Faden char old_auths[MAXAUTHS];
7804cb8a054bSGlenn Faden char new_auths[MAXAUTHS];
7805cb8a054bSGlenn Faden char rbac_profs[MAXPROFS];
7806cb8a054bSGlenn Faden char *lasts;
7807cb8a054bSGlenn Faden userattr_t *u;
7808cb8a054bSGlenn Faden boolean_t first = B_TRUE;
7809cb8a054bSGlenn Faden boolean_t is_zone_admin = B_FALSE;
7810cb8a054bSGlenn Faden char user_cmd[] = "/usr/sbin/usermod";
7811cb8a054bSGlenn Faden char role_cmd[] = "/usr/sbin/rolemod";
7812d77d83efSGlenn Faden char *auths_cmd = user_cmd; /* either usermod or rolemod */
7813d77d83efSGlenn Faden char *new_auth_start; /* string containing the new auths */
7814d77d83efSGlenn Faden int new_auth_cnt = 0; /* delta of changed authorizations */
7815cb8a054bSGlenn Faden
7816cb8a054bSGlenn Faden /*
7817cb8a054bSGlenn Faden * First get the existing authorizations for this user
7818cb8a054bSGlenn Faden */
7819cb8a054bSGlenn Faden
7820cb8a054bSGlenn Faden bzero(&old_auths, sizeof (old_auths));
7821cb8a054bSGlenn Faden bzero(&new_auths, sizeof (new_auths));
7822cb8a054bSGlenn Faden bzero(&rbac_profs, sizeof (rbac_profs));
7823cb8a054bSGlenn Faden if ((u = getusernam(user)) != NULL) {
7824cb8a054bSGlenn Faden char *current_auths;
7825cb8a054bSGlenn Faden char *current_profs;
7826cb8a054bSGlenn Faden char *type;
7827cb8a054bSGlenn Faden
7828cb8a054bSGlenn Faden type = kva_match(u->attr, USERATTR_TYPE_KW);
7829cb8a054bSGlenn Faden if (type != NULL) {
7830cb8a054bSGlenn Faden if (strcmp(type, USERATTR_TYPE_NONADMIN_KW) == 0)
7831cb8a054bSGlenn Faden auths_cmd = role_cmd;
7832cb8a054bSGlenn Faden }
7833cb8a054bSGlenn Faden
7834cb8a054bSGlenn Faden current_auths = kva_match(u->attr, USERATTR_AUTHS_KW);
7835cb8a054bSGlenn Faden if (current_auths != NULL) {
7836cb8a054bSGlenn Faden char *cur_auth;
7837cb8a054bSGlenn Faden char *delete_name;
7838cb8a054bSGlenn Faden size_t offset;
7839cb8a054bSGlenn Faden
7840cb8a054bSGlenn Faden offset = strlen(ZONE_AUTH_PREFIX);
7841cb8a054bSGlenn Faden
7842cb8a054bSGlenn Faden (void) strlcpy(old_auths, current_auths, MAXAUTHS);
7843cb8a054bSGlenn Faden cur_auth = strtok_r(current_auths, ",", &lasts);
7844cb8a054bSGlenn Faden
7845cb8a054bSGlenn Faden /*
7846cb8a054bSGlenn Faden * Next, remove any existing authorizations
7847cb8a054bSGlenn Faden * for this zone, and determine if the
7848cb8a054bSGlenn Faden * user still needs the Zone Management Profile.
7849cb8a054bSGlenn Faden */
7850cb8a054bSGlenn Faden if (is_renaming(handle))
7851cb8a054bSGlenn Faden delete_name = handle->zone_dh_delete_name;
7852cb8a054bSGlenn Faden else
7853cb8a054bSGlenn Faden delete_name = NULL;
7854cb8a054bSGlenn Faden while (cur_auth != NULL) {
7855cb8a054bSGlenn Faden if (!is_zone_auth(&cur_auth, zonename,
7856cb8a054bSGlenn Faden delete_name)) {
7857cb8a054bSGlenn Faden if (first) {
7858cb8a054bSGlenn Faden first = B_FALSE;
7859cb8a054bSGlenn Faden } else {
7860cb8a054bSGlenn Faden (void) strlcat(new_auths, ",",
7861cb8a054bSGlenn Faden MAXAUTHS);
7862cb8a054bSGlenn Faden }
7863cb8a054bSGlenn Faden (void) strlcat(new_auths, cur_auth,
7864cb8a054bSGlenn Faden MAXAUTHS);
7865cb8a054bSGlenn Faden /*
7866cb8a054bSGlenn Faden * If the user has authorizations
7867cb8a054bSGlenn Faden * for other zones, then set a
7868cb8a054bSGlenn Faden * flag indicate that the Zone
7869cb8a054bSGlenn Faden * Management profile should be
7870cb8a054bSGlenn Faden * preserved in user_attr.
7871cb8a054bSGlenn Faden */
7872cb8a054bSGlenn Faden if (strncmp(cur_auth,
7873cb8a054bSGlenn Faden ZONE_AUTH_PREFIX, offset) == 0)
7874cb8a054bSGlenn Faden is_zone_admin = B_TRUE;
7875d77d83efSGlenn Faden } else {
7876d77d83efSGlenn Faden new_auth_cnt++;
7877cb8a054bSGlenn Faden }
7878cb8a054bSGlenn Faden cur_auth = strtok_r(NULL, ",", &lasts);
7879cb8a054bSGlenn Faden }
7880cb8a054bSGlenn Faden }
7881cb8a054bSGlenn Faden current_profs = kva_match(u->attr, USERATTR_PROFILES_KW);
7882cb8a054bSGlenn Faden if (current_profs != NULL) {
7883cb8a054bSGlenn Faden (void) strlcpy(rbac_profs, current_profs, MAXPROFS);
7884cb8a054bSGlenn Faden }
7885cb8a054bSGlenn Faden free_userattr(u);
7886cb8a054bSGlenn Faden }
7887cb8a054bSGlenn Faden /*
7888cb8a054bSGlenn Faden * The following is done to avoid revisiting the
7889cb8a054bSGlenn Faden * user_attr entry for this user
7890cb8a054bSGlenn Faden */
7891cb8a054bSGlenn Faden (void) zonecfg_remove_userauths(handle, user, "", B_FALSE);
7892cb8a054bSGlenn Faden
7893cb8a054bSGlenn Faden /*
7894cb8a054bSGlenn Faden * Convert each right into a properly formatted authorization
7895cb8a054bSGlenn Faden */
7896d77d83efSGlenn Faden new_auth_start = new_auths + strlen(new_auths);
7897d77d83efSGlenn Faden if (!first)
7898d77d83efSGlenn Faden new_auth_start++;
7899cb8a054bSGlenn Faden right = strtok_r(auths, ",", &lasts);
7900cb8a054bSGlenn Faden while (right != NULL) {
7901cb8a054bSGlenn Faden char auth[MAXAUTHS];
7902cb8a054bSGlenn Faden
7903cb8a054bSGlenn Faden (void) snprintf(auth, MAXAUTHS, "%s%s/%s",
7904cb8a054bSGlenn Faden ZONE_AUTH_PREFIX, right, zonename);
7905cb8a054bSGlenn Faden if (first) {
7906cb8a054bSGlenn Faden first = B_FALSE;
7907cb8a054bSGlenn Faden } else {
7908cb8a054bSGlenn Faden (void) strlcat(new_auths, ",", MAXAUTHS);
7909cb8a054bSGlenn Faden }
7910cb8a054bSGlenn Faden (void) strlcat(new_auths, auth, MAXAUTHS);
7911cb8a054bSGlenn Faden is_zone_admin = B_TRUE;
7912d77d83efSGlenn Faden new_auth_cnt--;
7913cb8a054bSGlenn Faden right = strtok_r(NULL, ",", &lasts);
7914cb8a054bSGlenn Faden }
7915cb8a054bSGlenn Faden
7916cb8a054bSGlenn Faden /*
7917d77d83efSGlenn Faden * Need to update the authorizations in user_attr unless
7918d77d83efSGlenn Faden * the number of old and new authorizations is unchanged
7919d77d83efSGlenn Faden * and the new auths are a substrings of the old auths.
7920d77d83efSGlenn Faden *
7921cb8a054bSGlenn Faden * If the user's previous authorizations have changed
7922d77d83efSGlenn Faden * execute the usermod progam to update them in user_attr.
7923cb8a054bSGlenn Faden */
7924d77d83efSGlenn Faden if ((new_auth_cnt != 0) ||
7925d77d83efSGlenn Faden (strstr(old_auths, new_auth_start) == NULL)) {
7926cb8a054bSGlenn Faden char *cmdbuf;
7927cb8a054bSGlenn Faden size_t cmd_len;
7928cb8a054bSGlenn Faden
7929cb8a054bSGlenn Faden update_profiles(rbac_profs, is_zone_admin);
7930cb8a054bSGlenn Faden cmd_len = snprintf(NULL, 0, "%s -A \"%s\" -P \"%s\" %s",
7931cb8a054bSGlenn Faden auths_cmd, new_auths, rbac_profs, user) + 1;
7932cb8a054bSGlenn Faden if ((cmdbuf = malloc(cmd_len)) == NULL) {
7933cb8a054bSGlenn Faden return (Z_NOMEM);
7934cb8a054bSGlenn Faden }
7935cb8a054bSGlenn Faden (void) snprintf(cmdbuf, cmd_len, "%s -A \"%s\" -P \"%s\" %s",
7936cb8a054bSGlenn Faden auths_cmd, new_auths, rbac_profs, user);
7937cb8a054bSGlenn Faden if (do_subproc(zonename, cmdbuf) != 0) {
7938cb8a054bSGlenn Faden free(cmdbuf);
7939cb8a054bSGlenn Faden return (Z_SYSTEM);
7940cb8a054bSGlenn Faden }
7941cb8a054bSGlenn Faden free(cmdbuf);
7942cb8a054bSGlenn Faden }
7943cb8a054bSGlenn Faden
7944cb8a054bSGlenn Faden return (Z_OK);
7945cb8a054bSGlenn Faden }
7946cb8a054bSGlenn Faden
7947cb8a054bSGlenn Faden int
zonecfg_authorize_users(zone_dochandle_t handle,char * zonename)7948cb8a054bSGlenn Faden zonecfg_authorize_users(zone_dochandle_t handle, char *zonename)
7949cb8a054bSGlenn Faden {
7950cb8a054bSGlenn Faden xmlNodePtr cur;
7951cb8a054bSGlenn Faden int err;
7952cb8a054bSGlenn Faden char user[MAXUSERNAME];
7953cb8a054bSGlenn Faden char auths[MAXAUTHS];
7954cb8a054bSGlenn Faden
7955cb8a054bSGlenn Faden if ((err = operation_prep(handle)) != Z_OK)
7956cb8a054bSGlenn Faden return (err);
7957cb8a054bSGlenn Faden
7958cb8a054bSGlenn Faden cur = handle->zone_dh_cur;
7959cb8a054bSGlenn Faden for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
7960cb8a054bSGlenn Faden if (xmlStrcmp(cur->name, DTD_ELEM_ADMIN))
7961cb8a054bSGlenn Faden continue;
7962cb8a054bSGlenn Faden if (fetchprop(cur, DTD_ATTR_USER, user,
7963cb8a054bSGlenn Faden sizeof (user)) != Z_OK)
7964cb8a054bSGlenn Faden continue;
7965cb8a054bSGlenn Faden if (fetchprop(cur, DTD_ATTR_AUTHS, auths,
7966cb8a054bSGlenn Faden sizeof (auths)) != Z_OK)
7967cb8a054bSGlenn Faden continue;
7968cb8a054bSGlenn Faden if (zonecfg_authorize_user_impl(handle, user, auths, zonename)
7969cb8a054bSGlenn Faden != Z_OK)
7970cb8a054bSGlenn Faden return (Z_SYSTEM);
7971cb8a054bSGlenn Faden }
7972cb8a054bSGlenn Faden (void) zonecfg_remove_userauths(handle, "", "", B_TRUE);
7973cb8a054bSGlenn Faden
7974cb8a054bSGlenn Faden return (Z_OK);
7975cb8a054bSGlenn Faden }
7976cb8a054bSGlenn Faden
7977cb8a054bSGlenn Faden int
zonecfg_deauthorize_user(zone_dochandle_t handle,char * user,char * zonename)7978cb8a054bSGlenn Faden zonecfg_deauthorize_user(zone_dochandle_t handle, char *user, char *zonename)
7979cb8a054bSGlenn Faden {
7980cb8a054bSGlenn Faden return (zonecfg_authorize_user_impl(handle, user, "", zonename));
7981cb8a054bSGlenn Faden }
7982cb8a054bSGlenn Faden
7983cb8a054bSGlenn Faden int
zonecfg_deauthorize_users(zone_dochandle_t handle,char * zonename)7984cb8a054bSGlenn Faden zonecfg_deauthorize_users(zone_dochandle_t handle, char *zonename)
7985cb8a054bSGlenn Faden {
7986cb8a054bSGlenn Faden xmlNodePtr cur;
7987cb8a054bSGlenn Faden int err;
7988cb8a054bSGlenn Faden char user[MAXUSERNAME];
7989cb8a054bSGlenn Faden
7990cb8a054bSGlenn Faden if ((err = operation_prep(handle)) != Z_OK)
7991cb8a054bSGlenn Faden return (err);
7992cb8a054bSGlenn Faden
7993cb8a054bSGlenn Faden cur = handle->zone_dh_cur;
7994cb8a054bSGlenn Faden for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
7995cb8a054bSGlenn Faden if (xmlStrcmp(cur->name, DTD_ELEM_ADMIN))
7996cb8a054bSGlenn Faden continue;
7997cb8a054bSGlenn Faden if (fetchprop(cur, DTD_ATTR_USER, user,
7998cb8a054bSGlenn Faden sizeof (user)) != Z_OK)
7999cb8a054bSGlenn Faden continue;
8000cb8a054bSGlenn Faden if ((err = zonecfg_deauthorize_user(handle, user,
8001cb8a054bSGlenn Faden zonename)) != Z_OK)
8002cb8a054bSGlenn Faden return (err);
8003cb8a054bSGlenn Faden }
8004cb8a054bSGlenn Faden return (Z_OK);
8005cb8a054bSGlenn Faden }
8006cb8a054bSGlenn Faden
8007cb8a054bSGlenn Faden int
zonecfg_insert_userauths(zone_dochandle_t handle,char * user,char * zonename)8008cb8a054bSGlenn Faden zonecfg_insert_userauths(zone_dochandle_t handle, char *user, char *zonename)
8009cb8a054bSGlenn Faden {
8010cb8a054bSGlenn Faden zone_userauths_t *new, **prev, *next;
8011cb8a054bSGlenn Faden
8012cb8a054bSGlenn Faden prev = &handle->zone_dh_userauths;
8013cb8a054bSGlenn Faden next = *prev;
8014cb8a054bSGlenn Faden while (next) {
8015cb8a054bSGlenn Faden if ((strncmp(next->user, user, MAXUSERNAME) == 0) &&
8016cb8a054bSGlenn Faden (strncmp(next->zonename, zonename,
8017cb8a054bSGlenn Faden ZONENAME_MAX) == 0)) {
8018cb8a054bSGlenn Faden /*
8019cb8a054bSGlenn Faden * user is already in list
8020cb8a054bSGlenn Faden * which isn't supposed to happen!
8021cb8a054bSGlenn Faden */
8022cb8a054bSGlenn Faden return (Z_OK);
8023cb8a054bSGlenn Faden }
8024cb8a054bSGlenn Faden prev = &next->next;
8025cb8a054bSGlenn Faden next = *prev;
8026cb8a054bSGlenn Faden }
8027cb8a054bSGlenn Faden new = (zone_userauths_t *)malloc(sizeof (zone_userauths_t));
8028cb8a054bSGlenn Faden if (new == NULL)
8029cb8a054bSGlenn Faden return (Z_NOMEM);
8030cb8a054bSGlenn Faden
8031cb8a054bSGlenn Faden (void) strlcpy(new->user, user, sizeof (new->user));
8032cb8a054bSGlenn Faden (void) strlcpy(new->zonename, zonename, sizeof (new->zonename));
8033cb8a054bSGlenn Faden new->next = NULL;
8034cb8a054bSGlenn Faden *prev = new;
8035cb8a054bSGlenn Faden return (Z_OK);
8036cb8a054bSGlenn Faden }
8037cb8a054bSGlenn Faden
8038cb8a054bSGlenn Faden int
zonecfg_remove_userauths(zone_dochandle_t handle,char * user,char * zonename,boolean_t deauthorize)8039cb8a054bSGlenn Faden zonecfg_remove_userauths(zone_dochandle_t handle, char *user, char *zonename,
8040cb8a054bSGlenn Faden boolean_t deauthorize)
8041cb8a054bSGlenn Faden {
8042cb8a054bSGlenn Faden zone_userauths_t *new, **prev, *next;
8043cb8a054bSGlenn Faden
8044cb8a054bSGlenn Faden prev = &handle->zone_dh_userauths;
8045cb8a054bSGlenn Faden next = *prev;
8046cb8a054bSGlenn Faden
8047cb8a054bSGlenn Faden while (next) {
8048cb8a054bSGlenn Faden if ((strlen(user) == 0 ||
8049cb8a054bSGlenn Faden strncmp(next->user, user, MAXUSERNAME) == 0) &&
8050cb8a054bSGlenn Faden (strlen(zonename) == 0 ||
8051cb8a054bSGlenn Faden (strncmp(next->zonename, zonename, ZONENAME_MAX) == 0))) {
8052cb8a054bSGlenn Faden new = next;
8053cb8a054bSGlenn Faden *prev = next->next;
8054cb8a054bSGlenn Faden next = *prev;
8055cb8a054bSGlenn Faden if (deauthorize)
8056cb8a054bSGlenn Faden (void) zonecfg_deauthorize_user(handle,
8057cb8a054bSGlenn Faden new->user, new->zonename);
8058cb8a054bSGlenn Faden free(new);
8059cb8a054bSGlenn Faden continue;
8060cb8a054bSGlenn Faden }
8061cb8a054bSGlenn Faden prev = &next->next;
8062cb8a054bSGlenn Faden next = *prev;
8063cb8a054bSGlenn Faden }
8064cb8a054bSGlenn Faden return (Z_OK);
8065cb8a054bSGlenn Faden }
8066