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 /* 239d4be64eSdstaff * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 29cf8f45c7Sdstaff #include <libsysevent.h> 30cf8f45c7Sdstaff #include <pthread.h> 31cf8f45c7Sdstaff #include <stdlib.h> 327c478bd9Sstevel@tonic-gate #include <errno.h> 337c478bd9Sstevel@tonic-gate #include <fnmatch.h> 347c478bd9Sstevel@tonic-gate #include <strings.h> 357c478bd9Sstevel@tonic-gate #include <unistd.h> 367c478bd9Sstevel@tonic-gate #include <sys/stat.h> 377c478bd9Sstevel@tonic-gate #include <assert.h> 387c478bd9Sstevel@tonic-gate #include <libgen.h> 397c478bd9Sstevel@tonic-gate #include <libintl.h> 407c478bd9Sstevel@tonic-gate #include <alloca.h> 417c478bd9Sstevel@tonic-gate #include <ctype.h> 427c478bd9Sstevel@tonic-gate #include <sys/mntio.h> 437c478bd9Sstevel@tonic-gate #include <sys/mnttab.h> 44087719fdSdp #include <sys/types.h> 45cf8f45c7Sdstaff #include <sys/nvpair.h> 46ee519a1fSgjelinek #include <sys/acl.h> 47ee519a1fSgjelinek #include <ftw.h> 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 507c478bd9Sstevel@tonic-gate #include <netdb.h> 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate #include <libxml/xmlmemory.h> 537c478bd9Sstevel@tonic-gate #include <libxml/parser.h> 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate #include <libdevinfo.h> 56108322fbScarlsonj #include <uuid/uuid.h> 577c478bd9Sstevel@tonic-gate 58ee519a1fSgjelinek #include <dirent.h> 59ee519a1fSgjelinek 607c478bd9Sstevel@tonic-gate #include <libzonecfg.h> 617c478bd9Sstevel@tonic-gate #include "zonecfg_impl.h" 627c478bd9Sstevel@tonic-gate 63cf8f45c7Sdstaff 647c478bd9Sstevel@tonic-gate #define _PATH_TMPFILE "/zonecfg.XXXXXX" 65cf8f45c7Sdstaff #define ZONE_CB_RETRY_COUNT 10 66cf8f45c7Sdstaff #define ZONE_EVENT_PING_SUBCLASS "ping" 67cf8f45c7Sdstaff #define ZONE_EVENT_PING_PUBLISHER "solaris" 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate /* Hard-code the DTD element/attribute/entity names just once, here. */ 707c478bd9Sstevel@tonic-gate #define DTD_ELEM_ATTR (const xmlChar *) "attr" 717c478bd9Sstevel@tonic-gate #define DTD_ELEM_COMMENT (const xmlChar *) "comment" 727c478bd9Sstevel@tonic-gate #define DTD_ELEM_DEVICE (const xmlChar *) "device" 737c478bd9Sstevel@tonic-gate #define DTD_ELEM_FS (const xmlChar *) "filesystem" 747c478bd9Sstevel@tonic-gate #define DTD_ELEM_FSOPTION (const xmlChar *) "fsoption" 757c478bd9Sstevel@tonic-gate #define DTD_ELEM_IPD (const xmlChar *) "inherited-pkg-dir" 767c478bd9Sstevel@tonic-gate #define DTD_ELEM_NET (const xmlChar *) "network" 777c478bd9Sstevel@tonic-gate #define DTD_ELEM_RCTL (const xmlChar *) "rctl" 787c478bd9Sstevel@tonic-gate #define DTD_ELEM_RCTLVALUE (const xmlChar *) "rctl-value" 797c478bd9Sstevel@tonic-gate #define DTD_ELEM_ZONE (const xmlChar *) "zone" 80fa9e4066Sahrens #define DTD_ELEM_DATASET (const xmlChar *) "dataset" 81ee519a1fSgjelinek #define DTD_ELEM_PACKAGE (const xmlChar *) "package" 82ee519a1fSgjelinek #define DTD_ELEM_PATCH (const xmlChar *) "patch" 83ee519a1fSgjelinek #define DTD_ELEM_OBSOLETES (const xmlChar *) "obsoletes" 84ee519a1fSgjelinek #define DTD_ELEM_INCOMPATIBLE (const xmlChar *) "incompatible" 85ee519a1fSgjelinek #define DTD_ELEM_DEV_PERM (const xmlChar *) "dev-perm" 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate #define DTD_ATTR_ACTION (const xmlChar *) "action" 887c478bd9Sstevel@tonic-gate #define DTD_ATTR_ADDRESS (const xmlChar *) "address" 897c478bd9Sstevel@tonic-gate #define DTD_ATTR_AUTOBOOT (const xmlChar *) "autoboot" 907c478bd9Sstevel@tonic-gate #define DTD_ATTR_DIR (const xmlChar *) "directory" 917c478bd9Sstevel@tonic-gate #define DTD_ATTR_LIMIT (const xmlChar *) "limit" 92ffbafc53Scomay #define DTD_ATTR_LIMITPRIV (const xmlChar *) "limitpriv" 937c478bd9Sstevel@tonic-gate #define DTD_ATTR_MATCH (const xmlChar *) "match" 947c478bd9Sstevel@tonic-gate #define DTD_ATTR_NAME (const xmlChar *) "name" 957c478bd9Sstevel@tonic-gate #define DTD_ATTR_PHYSICAL (const xmlChar *) "physical" 967c478bd9Sstevel@tonic-gate #define DTD_ATTR_POOL (const xmlChar *) "pool" 977c478bd9Sstevel@tonic-gate #define DTD_ATTR_PRIV (const xmlChar *) "priv" 987c478bd9Sstevel@tonic-gate #define DTD_ATTR_RAW (const xmlChar *) "raw" 997c478bd9Sstevel@tonic-gate #define DTD_ATTR_SPECIAL (const xmlChar *) "special" 1007c478bd9Sstevel@tonic-gate #define DTD_ATTR_TYPE (const xmlChar *) "type" 1017c478bd9Sstevel@tonic-gate #define DTD_ATTR_VALUE (const xmlChar *) "value" 1027c478bd9Sstevel@tonic-gate #define DTD_ATTR_ZONEPATH (const xmlChar *) "zonepath" 103ee519a1fSgjelinek #define DTD_ATTR_VERSION (const xmlChar *) "version" 104ee519a1fSgjelinek #define DTD_ATTR_ID (const xmlChar *) "id" 105ee519a1fSgjelinek #define DTD_ATTR_UID (const xmlChar *) "uid" 106ee519a1fSgjelinek #define DTD_ATTR_GID (const xmlChar *) "gid" 107ee519a1fSgjelinek #define DTD_ATTR_MODE (const xmlChar *) "mode" 108ee519a1fSgjelinek #define DTD_ATTR_ACL (const xmlChar *) "acl" 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate #define DTD_ENTITY_BOOLEAN "boolean" 1117c478bd9Sstevel@tonic-gate #define DTD_ENTITY_DEVPATH "devpath" 1127c478bd9Sstevel@tonic-gate #define DTD_ENTITY_DRIVER "driver" 1137c478bd9Sstevel@tonic-gate #define DTD_ENTITY_DRVMIN "drv_min" 1147c478bd9Sstevel@tonic-gate #define DTD_ENTITY_FALSE "false" 1157c478bd9Sstevel@tonic-gate #define DTD_ENTITY_INT "int" 1167c478bd9Sstevel@tonic-gate #define DTD_ENTITY_STRING "string" 1177c478bd9Sstevel@tonic-gate #define DTD_ENTITY_TRUE "true" 1187c478bd9Sstevel@tonic-gate #define DTD_ENTITY_UINT "uint" 1197c478bd9Sstevel@tonic-gate 120a1be23daSdp #define DTD_ENTITY_BOOL_LEN 6 /* "false" */ 121a1be23daSdp 122ee519a1fSgjelinek #define DETACHED "SUNWdetached.xml" 123ee519a1fSgjelinek #define ATTACH_FORCED "SUNWattached.xml" 124ee519a1fSgjelinek #define PKG_PATH "/var/sadm/pkg" 125ee519a1fSgjelinek #define CONTENTS_FILE "/var/sadm/install/contents" 12645916cd2Sjpk #define SUNW_PKG_ALL_ZONES "SUNW_PKG_ALLZONES=true\n" 12745916cd2Sjpk #define SUNW_PKG_THIS_ZONE "SUNW_PKG_THISZONE=true\n" 128ee519a1fSgjelinek #define VERSION "VERSION=" 129ee519a1fSgjelinek #define PATCHLIST "PATCHLIST=" 130ee519a1fSgjelinek #define PATCHINFO "PATCH_INFO_" 131ee519a1fSgjelinek #define PKGINFO_RD_LEN 128 132ee519a1fSgjelinek 1337c478bd9Sstevel@tonic-gate struct zone_dochandle { 1347c478bd9Sstevel@tonic-gate char *zone_dh_rootdir; 1357c478bd9Sstevel@tonic-gate xmlDocPtr zone_dh_doc; 1367c478bd9Sstevel@tonic-gate xmlNodePtr zone_dh_cur; 1377c478bd9Sstevel@tonic-gate xmlNodePtr zone_dh_top; 138087719fdSdp boolean_t zone_dh_newzone; 139087719fdSdp boolean_t zone_dh_snapshot; 140ee519a1fSgjelinek boolean_t zone_dh_sw_inv; 141087719fdSdp char zone_dh_delete_name[ZONENAME_MAX]; 1427c478bd9Sstevel@tonic-gate }; 1437c478bd9Sstevel@tonic-gate 144cf8f45c7Sdstaff struct znotify { 145cf8f45c7Sdstaff void * zn_private; 146cf8f45c7Sdstaff evchan_t *zn_eventchan; 147cf8f45c7Sdstaff int (*zn_callback)(const char *zonename, zoneid_t zid, 148cf8f45c7Sdstaff const char *newstate, const char *oldstate, hrtime_t when, void *p); 149cf8f45c7Sdstaff pthread_mutex_t zn_mutex; 150cf8f45c7Sdstaff pthread_cond_t zn_cond; 151cf8f45c7Sdstaff pthread_mutex_t zn_bigmutex; 152cf8f45c7Sdstaff volatile enum {ZN_UNLOCKED, ZN_LOCKED, ZN_PING_INFLIGHT, 153cf8f45c7Sdstaff ZN_PING_RECEIVED} zn_state; 154cf8f45c7Sdstaff char zn_subscriber_id[MAX_SUBID_LEN]; 155cf8f45c7Sdstaff volatile boolean_t zn_failed; 156cf8f45c7Sdstaff int zn_failure_count; 157cf8f45c7Sdstaff }; 158cf8f45c7Sdstaff 159ee519a1fSgjelinek struct zone_pkginfo { 160ee519a1fSgjelinek boolean_t zpi_all_zones; 161ee519a1fSgjelinek boolean_t zpi_this_zone; 162ee519a1fSgjelinek int zpi_patch_cnt; 163ee519a1fSgjelinek char *zpi_version; 164ee519a1fSgjelinek char **zpi_patchinfo; 165ee519a1fSgjelinek }; 166ee519a1fSgjelinek 167108322fbScarlsonj char *zonecfg_root = ""; 168108322fbScarlsonj 1697c478bd9Sstevel@tonic-gate /* 1707c478bd9Sstevel@tonic-gate * For functions which return int, which is most of the functions herein, 1717c478bd9Sstevel@tonic-gate * the return values should be from the Z_foo set defined in <libzonecfg.h>. 1727c478bd9Sstevel@tonic-gate * In some instances, we take pains mapping some libc errno values to Z_foo 1737c478bd9Sstevel@tonic-gate * values from this set. 1747c478bd9Sstevel@tonic-gate */ 1757c478bd9Sstevel@tonic-gate 176108322fbScarlsonj /* 177108322fbScarlsonj * Set the root (/) path for all zonecfg configuration files. This is a 178108322fbScarlsonj * private interface used by Live Upgrade extensions to access zone 179108322fbScarlsonj * configuration inside mounted alternate boot environments. 180108322fbScarlsonj */ 181108322fbScarlsonj void 182108322fbScarlsonj zonecfg_set_root(const char *rootpath) 183108322fbScarlsonj { 184108322fbScarlsonj if (*zonecfg_root != '\0') 185108322fbScarlsonj free(zonecfg_root); 186108322fbScarlsonj if (rootpath == NULL || rootpath[0] == '\0' || rootpath[1] == '\0' || 187108322fbScarlsonj (zonecfg_root = strdup(rootpath)) == NULL) 188108322fbScarlsonj zonecfg_root = ""; 189108322fbScarlsonj } 190108322fbScarlsonj 191108322fbScarlsonj const char * 192108322fbScarlsonj zonecfg_get_root(void) 193108322fbScarlsonj { 194108322fbScarlsonj return (zonecfg_root); 195108322fbScarlsonj } 196108322fbScarlsonj 197108322fbScarlsonj boolean_t 198108322fbScarlsonj zonecfg_in_alt_root(void) 199108322fbScarlsonj { 200108322fbScarlsonj return (*zonecfg_root != '\0'); 201108322fbScarlsonj } 202108322fbScarlsonj 2037c478bd9Sstevel@tonic-gate /* 2047c478bd9Sstevel@tonic-gate * Callers of the _file_path() functions are expected to have the second 2057c478bd9Sstevel@tonic-gate * parameter be a (char foo[MAXPATHLEN]). 2067c478bd9Sstevel@tonic-gate */ 2077c478bd9Sstevel@tonic-gate 208108322fbScarlsonj static boolean_t 2097c478bd9Sstevel@tonic-gate config_file_path(const char *zonename, char *answer) 2107c478bd9Sstevel@tonic-gate { 211108322fbScarlsonj return (snprintf(answer, MAXPATHLEN, "%s%s/%s.xml", zonecfg_root, 212108322fbScarlsonj ZONE_CONFIG_ROOT, zonename) < MAXPATHLEN); 2137c478bd9Sstevel@tonic-gate } 2147c478bd9Sstevel@tonic-gate 215108322fbScarlsonj static boolean_t 216108322fbScarlsonj snap_file_path(const char *zonename, char *answer) 2177c478bd9Sstevel@tonic-gate { 218108322fbScarlsonj return (snprintf(answer, MAXPATHLEN, "%s%s/%s.snapshot.xml", 219108322fbScarlsonj zonecfg_root, ZONE_SNAPSHOT_ROOT, zonename) < MAXPATHLEN); 2207c478bd9Sstevel@tonic-gate } 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2237c478bd9Sstevel@tonic-gate static void 2247c478bd9Sstevel@tonic-gate zonecfg_error_func(void *ctx, const char *msg, ...) 2257c478bd9Sstevel@tonic-gate { 2267c478bd9Sstevel@tonic-gate /* 2277c478bd9Sstevel@tonic-gate * This function does nothing by design. Its purpose is to prevent 2287c478bd9Sstevel@tonic-gate * libxml from dumping unwanted messages to stdout/stderr. 2297c478bd9Sstevel@tonic-gate */ 2307c478bd9Sstevel@tonic-gate } 2317c478bd9Sstevel@tonic-gate 2327c478bd9Sstevel@tonic-gate zone_dochandle_t 2337c478bd9Sstevel@tonic-gate zonecfg_init_handle(void) 2347c478bd9Sstevel@tonic-gate { 235087719fdSdp zone_dochandle_t handle = calloc(1, sizeof (struct zone_dochandle)); 2367c478bd9Sstevel@tonic-gate if (handle == NULL) { 2377c478bd9Sstevel@tonic-gate errno = Z_NOMEM; 2387c478bd9Sstevel@tonic-gate return (NULL); 2397c478bd9Sstevel@tonic-gate } 2407c478bd9Sstevel@tonic-gate 2417c478bd9Sstevel@tonic-gate /* generic libxml initialization */ 2427c478bd9Sstevel@tonic-gate xmlLineNumbersDefault(1); 2437c478bd9Sstevel@tonic-gate xmlLoadExtDtdDefaultValue |= XML_DETECT_IDS; 2447c478bd9Sstevel@tonic-gate xmlDoValidityCheckingDefaultValue = 1; 2457c478bd9Sstevel@tonic-gate (void) xmlKeepBlanksDefault(0); 2467c478bd9Sstevel@tonic-gate xmlGetWarningsDefaultValue = 0; 2477c478bd9Sstevel@tonic-gate xmlSetGenericErrorFunc(NULL, zonecfg_error_func); 2487c478bd9Sstevel@tonic-gate 2497c478bd9Sstevel@tonic-gate return (handle); 2507c478bd9Sstevel@tonic-gate } 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate int 2537c478bd9Sstevel@tonic-gate zonecfg_check_handle(zone_dochandle_t handle) 2547c478bd9Sstevel@tonic-gate { 2557c478bd9Sstevel@tonic-gate if (handle == NULL || handle->zone_dh_doc == NULL) 2567c478bd9Sstevel@tonic-gate return (Z_BAD_HANDLE); 2577c478bd9Sstevel@tonic-gate return (Z_OK); 2587c478bd9Sstevel@tonic-gate } 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate void 2617c478bd9Sstevel@tonic-gate zonecfg_fini_handle(zone_dochandle_t handle) 2627c478bd9Sstevel@tonic-gate { 2637c478bd9Sstevel@tonic-gate if (zonecfg_check_handle(handle) == Z_OK) 2647c478bd9Sstevel@tonic-gate xmlFreeDoc(handle->zone_dh_doc); 2657c478bd9Sstevel@tonic-gate if (handle != NULL) 2667c478bd9Sstevel@tonic-gate free(handle); 2677c478bd9Sstevel@tonic-gate } 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate static int 2707c478bd9Sstevel@tonic-gate zonecfg_destroy_impl(char *filename) 2717c478bd9Sstevel@tonic-gate { 2727c478bd9Sstevel@tonic-gate if (unlink(filename) == -1) { 2737c478bd9Sstevel@tonic-gate if (errno == EACCES) 2747c478bd9Sstevel@tonic-gate return (Z_ACCES); 2757c478bd9Sstevel@tonic-gate if (errno == ENOENT) 2767c478bd9Sstevel@tonic-gate return (Z_NO_ZONE); 2777c478bd9Sstevel@tonic-gate return (Z_MISC_FS); 2787c478bd9Sstevel@tonic-gate } 2797c478bd9Sstevel@tonic-gate return (Z_OK); 2807c478bd9Sstevel@tonic-gate } 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate int 283087719fdSdp zonecfg_destroy(const char *zonename, boolean_t force) 2847c478bd9Sstevel@tonic-gate { 2857c478bd9Sstevel@tonic-gate char path[MAXPATHLEN]; 286087719fdSdp struct zoneent ze; 287087719fdSdp int err, state_err; 288087719fdSdp zone_state_t state; 2897c478bd9Sstevel@tonic-gate 290108322fbScarlsonj if (!config_file_path(zonename, path)) 291108322fbScarlsonj return (Z_MISC_FS); 292087719fdSdp 293087719fdSdp state_err = zone_get_state((char *)zonename, &state); 294087719fdSdp err = access(path, W_OK); 295087719fdSdp 296087719fdSdp /* 297087719fdSdp * If there is no file, and no index entry, reliably indicate that no 298087719fdSdp * such zone exists. 299087719fdSdp */ 300087719fdSdp if ((state_err == Z_NO_ZONE) && (err == -1) && (errno == ENOENT)) 301087719fdSdp return (Z_NO_ZONE); 302087719fdSdp 303087719fdSdp /* 304087719fdSdp * Handle any other filesystem related errors (except if the XML 305087719fdSdp * file is missing, which we treat silently), unless we're forcing, 306087719fdSdp * in which case we plow on. 307087719fdSdp */ 308087719fdSdp if (err == -1 && errno != ENOENT) { 309087719fdSdp if (errno == EACCES) 310087719fdSdp return (Z_ACCES); 311087719fdSdp else if (!force) 312087719fdSdp return (Z_MISC_FS); 313087719fdSdp } 314087719fdSdp 315087719fdSdp if (state > ZONE_STATE_INSTALLED) 316087719fdSdp return (Z_BAD_ZONE_STATE); 317087719fdSdp 318087719fdSdp if (!force && state > ZONE_STATE_CONFIGURED) 319087719fdSdp return (Z_BAD_ZONE_STATE); 320087719fdSdp 321087719fdSdp /* 322087719fdSdp * Index deletion succeeds even if the entry doesn't exist. So this 323087719fdSdp * will fail only if we've had some more severe problem. 324087719fdSdp */ 325087719fdSdp bzero(&ze, sizeof (ze)); 326087719fdSdp (void) strlcpy(ze.zone_name, zonename, sizeof (ze.zone_name)); 327087719fdSdp if ((err = putzoneent(&ze, PZE_REMOVE)) != Z_OK) 328087719fdSdp if (!force) 329087719fdSdp return (err); 330087719fdSdp 331087719fdSdp err = zonecfg_destroy_impl(path); 332087719fdSdp 333087719fdSdp /* 334087719fdSdp * Treat failure to find the XML file silently, since, well, it's 335087719fdSdp * gone, and with the index file cleaned up, we're done. 336087719fdSdp */ 337087719fdSdp if (err == Z_OK || err == Z_NO_ZONE) 338087719fdSdp return (Z_OK); 339087719fdSdp return (err); 3407c478bd9Sstevel@tonic-gate } 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate int 343108322fbScarlsonj zonecfg_destroy_snapshot(const char *zonename) 3447c478bd9Sstevel@tonic-gate { 3457c478bd9Sstevel@tonic-gate char path[MAXPATHLEN]; 3467c478bd9Sstevel@tonic-gate 347108322fbScarlsonj if (!snap_file_path(zonename, path)) 348108322fbScarlsonj return (Z_MISC_FS); 3497c478bd9Sstevel@tonic-gate return (zonecfg_destroy_impl(path)); 3507c478bd9Sstevel@tonic-gate } 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate static int 353a1be23daSdp getroot(zone_dochandle_t handle, xmlNodePtr *root) 3547c478bd9Sstevel@tonic-gate { 3557c478bd9Sstevel@tonic-gate if (zonecfg_check_handle(handle) == Z_BAD_HANDLE) 3567c478bd9Sstevel@tonic-gate return (Z_BAD_HANDLE); 3577c478bd9Sstevel@tonic-gate 358a1be23daSdp *root = xmlDocGetRootElement(handle->zone_dh_doc); 359a1be23daSdp 360a1be23daSdp if (*root == NULL) 3617c478bd9Sstevel@tonic-gate return (Z_EMPTY_DOCUMENT); 3627c478bd9Sstevel@tonic-gate 363a1be23daSdp if (xmlStrcmp((*root)->name, DTD_ELEM_ZONE)) 3647c478bd9Sstevel@tonic-gate return (Z_WRONG_DOC_TYPE); 365a1be23daSdp 366a1be23daSdp return (Z_OK); 367a1be23daSdp } 368a1be23daSdp 369a1be23daSdp static int 370a1be23daSdp operation_prep(zone_dochandle_t handle) 371a1be23daSdp { 372a1be23daSdp xmlNodePtr root; 373a1be23daSdp int err; 374a1be23daSdp 375a1be23daSdp if ((err = getroot(handle, &root)) != 0) 376a1be23daSdp return (err); 377a1be23daSdp 378a1be23daSdp handle->zone_dh_cur = root; 379a1be23daSdp handle->zone_dh_top = root; 380a1be23daSdp return (Z_OK); 381a1be23daSdp } 382a1be23daSdp 383ffbafc53Scomay static int 384ffbafc53Scomay fetchprop(xmlNodePtr cur, const xmlChar *propname, char *dst, size_t dstsize) 385ffbafc53Scomay { 386ffbafc53Scomay xmlChar *property; 387ffbafc53Scomay size_t srcsize; 388ffbafc53Scomay 389ffbafc53Scomay if ((property = xmlGetProp(cur, propname)) == NULL) 390ffbafc53Scomay return (Z_BAD_PROPERTY); 391ffbafc53Scomay srcsize = strlcpy(dst, (char *)property, dstsize); 392ffbafc53Scomay xmlFree(property); 393ffbafc53Scomay if (srcsize >= dstsize) 394ffbafc53Scomay return (Z_TOO_BIG); 395ffbafc53Scomay return (Z_OK); 396ffbafc53Scomay } 397ffbafc53Scomay 398ffbafc53Scomay static int 399ffbafc53Scomay fetch_alloc_prop(xmlNodePtr cur, const xmlChar *propname, char **dst) 400ffbafc53Scomay { 401ffbafc53Scomay xmlChar *property; 402ffbafc53Scomay 403ffbafc53Scomay if ((property = xmlGetProp(cur, propname)) == NULL) 404ffbafc53Scomay return (Z_BAD_PROPERTY); 405ffbafc53Scomay if ((*dst = strdup((char *)property)) == NULL) { 406ffbafc53Scomay xmlFree(property); 407ffbafc53Scomay return (Z_NOMEM); 408ffbafc53Scomay } 409ffbafc53Scomay xmlFree(property); 410ffbafc53Scomay return (Z_OK); 411ffbafc53Scomay } 412ffbafc53Scomay 413a1be23daSdp static int 414a1be23daSdp getrootattr(zone_dochandle_t handle, const xmlChar *propname, 415a1be23daSdp char *propval, size_t propsize) 416a1be23daSdp { 417a1be23daSdp xmlNodePtr root; 418a1be23daSdp int err; 419a1be23daSdp 420a1be23daSdp if ((err = getroot(handle, &root)) != 0) 421a1be23daSdp return (err); 422a1be23daSdp 423ffbafc53Scomay return (fetchprop(root, propname, propval, propsize)); 424ffbafc53Scomay } 425ffbafc53Scomay 426ffbafc53Scomay static int 427ffbafc53Scomay get_alloc_rootattr(zone_dochandle_t handle, const xmlChar *propname, 428ffbafc53Scomay char **propval) 429ffbafc53Scomay { 430ffbafc53Scomay xmlNodePtr root; 431ffbafc53Scomay int err; 432ffbafc53Scomay 433ffbafc53Scomay if ((err = getroot(handle, &root)) != 0) 434ffbafc53Scomay return (err); 435ffbafc53Scomay 436ffbafc53Scomay return (fetch_alloc_prop(root, propname, propval)); 437a1be23daSdp } 438a1be23daSdp 439a1be23daSdp static int 440108322fbScarlsonj setrootattr(zone_dochandle_t handle, const xmlChar *propname, 441108322fbScarlsonj const char *propval) 442a1be23daSdp { 443a1be23daSdp int err; 444a1be23daSdp xmlNodePtr root; 445a1be23daSdp 446a1be23daSdp if (propval == NULL) 447a1be23daSdp return (Z_INVAL); 448a1be23daSdp 449a1be23daSdp if ((err = getroot(handle, &root)) != Z_OK) 450a1be23daSdp return (err); 451a1be23daSdp 452a1be23daSdp if (xmlSetProp(root, propname, (const xmlChar *) propval) == NULL) 453a1be23daSdp return (Z_INVAL); 4547c478bd9Sstevel@tonic-gate return (Z_OK); 4557c478bd9Sstevel@tonic-gate } 4567c478bd9Sstevel@tonic-gate 457087719fdSdp static void 458087719fdSdp addcomment(zone_dochandle_t handle, const char *comment) 459087719fdSdp { 460087719fdSdp xmlNodePtr node; 461087719fdSdp node = xmlNewComment((xmlChar *) comment); 462087719fdSdp 463087719fdSdp if (node != NULL) 464087719fdSdp (void) xmlAddPrevSibling(handle->zone_dh_top, node); 465087719fdSdp } 466087719fdSdp 467087719fdSdp static void 468087719fdSdp stripcomments(zone_dochandle_t handle) 469087719fdSdp { 470087719fdSdp xmlDocPtr top; 471087719fdSdp xmlNodePtr child, next; 472087719fdSdp 473087719fdSdp top = handle->zone_dh_doc; 474087719fdSdp for (child = top->xmlChildrenNode; child != NULL; child = next) { 475087719fdSdp next = child->next; 476087719fdSdp if (child->name == NULL) 477087719fdSdp continue; 478087719fdSdp if (xmlStrcmp(child->name, DTD_ELEM_COMMENT) == 0) { 479087719fdSdp next = child->next; 480087719fdSdp xmlUnlinkNode(child); 481087719fdSdp xmlFreeNode(child); 482087719fdSdp } 483087719fdSdp } 484087719fdSdp } 485087719fdSdp 486ee519a1fSgjelinek static void 487ee519a1fSgjelinek strip_sw_inv(zone_dochandle_t handle) 488ee519a1fSgjelinek { 489ee519a1fSgjelinek xmlNodePtr root, child, next; 490ee519a1fSgjelinek 491ee519a1fSgjelinek root = xmlDocGetRootElement(handle->zone_dh_doc); 492ee519a1fSgjelinek for (child = root->xmlChildrenNode; child != NULL; child = next) { 493ee519a1fSgjelinek next = child->next; 494ee519a1fSgjelinek if (child->name == NULL) 495ee519a1fSgjelinek continue; 496ee519a1fSgjelinek if (xmlStrcmp(child->name, DTD_ELEM_PACKAGE) == 0 || 497ee519a1fSgjelinek xmlStrcmp(child->name, DTD_ELEM_PATCH) == 0) { 498ee519a1fSgjelinek next = child->next; 499ee519a1fSgjelinek xmlUnlinkNode(child); 500ee519a1fSgjelinek xmlFreeNode(child); 501ee519a1fSgjelinek } 502ee519a1fSgjelinek } 503ee519a1fSgjelinek } 504ee519a1fSgjelinek 5057c478bd9Sstevel@tonic-gate static int 506108322fbScarlsonj zonecfg_get_handle_impl(const char *zonename, const char *filename, 507108322fbScarlsonj zone_dochandle_t handle) 5087c478bd9Sstevel@tonic-gate { 5097c478bd9Sstevel@tonic-gate xmlValidCtxtPtr cvp; 5107c478bd9Sstevel@tonic-gate struct stat statbuf; 5117c478bd9Sstevel@tonic-gate int valid; 5127c478bd9Sstevel@tonic-gate 5137c478bd9Sstevel@tonic-gate if (zonename == NULL) 5147c478bd9Sstevel@tonic-gate return (Z_NO_ZONE); 5157c478bd9Sstevel@tonic-gate if ((handle->zone_dh_doc = xmlParseFile(filename)) == NULL) { 5167c478bd9Sstevel@tonic-gate /* distinguish file not found vs. found but not parsed */ 5177c478bd9Sstevel@tonic-gate if (stat(filename, &statbuf) == 0) 5187c478bd9Sstevel@tonic-gate return (Z_INVALID_DOCUMENT); 5197c478bd9Sstevel@tonic-gate return (Z_NO_ZONE); 5207c478bd9Sstevel@tonic-gate } 5217c478bd9Sstevel@tonic-gate if ((cvp = xmlNewValidCtxt()) == NULL) 5227c478bd9Sstevel@tonic-gate return (Z_NOMEM); 5237c478bd9Sstevel@tonic-gate cvp->error = zonecfg_error_func; 5247c478bd9Sstevel@tonic-gate cvp->warning = zonecfg_error_func; 5257c478bd9Sstevel@tonic-gate valid = xmlValidateDocument(cvp, handle->zone_dh_doc); 5267c478bd9Sstevel@tonic-gate xmlFreeValidCtxt(cvp); 5277c478bd9Sstevel@tonic-gate if (valid == 0) 5287c478bd9Sstevel@tonic-gate return (Z_INVALID_DOCUMENT); 529087719fdSdp 5307c478bd9Sstevel@tonic-gate /* delete any comments such as inherited Sun copyright / ident str */ 531087719fdSdp stripcomments(handle); 5327c478bd9Sstevel@tonic-gate return (Z_OK); 5337c478bd9Sstevel@tonic-gate } 5347c478bd9Sstevel@tonic-gate 5357c478bd9Sstevel@tonic-gate int 536108322fbScarlsonj zonecfg_get_handle(const char *zonename, zone_dochandle_t handle) 5377c478bd9Sstevel@tonic-gate { 5387c478bd9Sstevel@tonic-gate char path[MAXPATHLEN]; 5397c478bd9Sstevel@tonic-gate 540108322fbScarlsonj if (!config_file_path(zonename, path)) 541108322fbScarlsonj return (Z_MISC_FS); 542087719fdSdp handle->zone_dh_newzone = B_FALSE; 543087719fdSdp 5447c478bd9Sstevel@tonic-gate return (zonecfg_get_handle_impl(zonename, path, handle)); 5457c478bd9Sstevel@tonic-gate } 5467c478bd9Sstevel@tonic-gate 547ee519a1fSgjelinek int 548ee519a1fSgjelinek zonecfg_get_attach_handle(const char *path, const char *zonename, 549ee519a1fSgjelinek boolean_t preserve_sw, zone_dochandle_t handle) 550ee519a1fSgjelinek { 551ee519a1fSgjelinek char migpath[MAXPATHLEN]; 552ee519a1fSgjelinek int err; 553ee519a1fSgjelinek struct stat buf; 554ee519a1fSgjelinek 555ee519a1fSgjelinek if (snprintf(migpath, sizeof (migpath), "%s/root", path) >= 556ee519a1fSgjelinek sizeof (migpath)) 557ee519a1fSgjelinek return (Z_NOMEM); 558ee519a1fSgjelinek 559ee519a1fSgjelinek if (stat(migpath, &buf) == -1 || !S_ISDIR(buf.st_mode)) 560ee519a1fSgjelinek return (Z_NO_ZONE); 561ee519a1fSgjelinek 562ee519a1fSgjelinek if (snprintf(migpath, sizeof (migpath), "%s/%s", path, DETACHED) >= 563ee519a1fSgjelinek sizeof (migpath)) 564ee519a1fSgjelinek return (Z_NOMEM); 565ee519a1fSgjelinek 566ee519a1fSgjelinek if ((err = zonecfg_get_handle_impl(zonename, migpath, handle)) != Z_OK) 567ee519a1fSgjelinek return (err); 568ee519a1fSgjelinek 569ee519a1fSgjelinek if (!preserve_sw) 570ee519a1fSgjelinek strip_sw_inv(handle); 571ee519a1fSgjelinek 572ee519a1fSgjelinek handle->zone_dh_newzone = B_TRUE; 573ee519a1fSgjelinek if ((err = setrootattr(handle, DTD_ATTR_ZONEPATH, path)) != Z_OK) 574ee519a1fSgjelinek return (err); 575ee519a1fSgjelinek 576ee519a1fSgjelinek return (setrootattr(handle, DTD_ATTR_NAME, zonename)); 577ee519a1fSgjelinek } 578ee519a1fSgjelinek 5797c478bd9Sstevel@tonic-gate int 580108322fbScarlsonj zonecfg_get_snapshot_handle(const char *zonename, zone_dochandle_t handle) 5817c478bd9Sstevel@tonic-gate { 5827c478bd9Sstevel@tonic-gate char path[MAXPATHLEN]; 5837c478bd9Sstevel@tonic-gate 584108322fbScarlsonj if (!snap_file_path(zonename, path)) 585108322fbScarlsonj return (Z_MISC_FS); 586087719fdSdp handle->zone_dh_newzone = B_FALSE; 5877c478bd9Sstevel@tonic-gate return (zonecfg_get_handle_impl(zonename, path, handle)); 5887c478bd9Sstevel@tonic-gate } 5897c478bd9Sstevel@tonic-gate 590087719fdSdp int 591108322fbScarlsonj zonecfg_get_template_handle(const char *template, const char *zonename, 592087719fdSdp zone_dochandle_t handle) 593087719fdSdp { 594087719fdSdp char path[MAXPATHLEN]; 595087719fdSdp int err; 596087719fdSdp 597108322fbScarlsonj if (!config_file_path(template, path)) 598108322fbScarlsonj return (Z_MISC_FS); 599087719fdSdp 600087719fdSdp if ((err = zonecfg_get_handle_impl(template, path, handle)) != Z_OK) 601087719fdSdp return (err); 602087719fdSdp handle->zone_dh_newzone = B_TRUE; 603087719fdSdp return (setrootattr(handle, DTD_ATTR_NAME, zonename)); 604087719fdSdp } 605087719fdSdp 606*8cd327d5Sgjelinek /* 607*8cd327d5Sgjelinek * Initialize two handles from the manifest read on fd. The rem_handle 608*8cd327d5Sgjelinek * is initialized from the input file, including the sw inventory. The 609*8cd327d5Sgjelinek * local_handle is initialized with the same zone configuration but with 610*8cd327d5Sgjelinek * no sw inventory. 611*8cd327d5Sgjelinek */ 612*8cd327d5Sgjelinek int 613*8cd327d5Sgjelinek zonecfg_attach_manifest(int fd, zone_dochandle_t local_handle, 614*8cd327d5Sgjelinek zone_dochandle_t rem_handle) 615*8cd327d5Sgjelinek { 616*8cd327d5Sgjelinek xmlValidCtxtPtr cvp; 617*8cd327d5Sgjelinek int valid; 618*8cd327d5Sgjelinek 619*8cd327d5Sgjelinek /* load the manifest into the handle for the remote system */ 620*8cd327d5Sgjelinek if ((rem_handle->zone_dh_doc = xmlReadFd(fd, NULL, NULL, 0)) == NULL) { 621*8cd327d5Sgjelinek return (Z_INVALID_DOCUMENT); 622*8cd327d5Sgjelinek } 623*8cd327d5Sgjelinek if ((cvp = xmlNewValidCtxt()) == NULL) 624*8cd327d5Sgjelinek return (Z_NOMEM); 625*8cd327d5Sgjelinek cvp->error = zonecfg_error_func; 626*8cd327d5Sgjelinek cvp->warning = zonecfg_error_func; 627*8cd327d5Sgjelinek valid = xmlValidateDocument(cvp, rem_handle->zone_dh_doc); 628*8cd327d5Sgjelinek xmlFreeValidCtxt(cvp); 629*8cd327d5Sgjelinek if (valid == 0) 630*8cd327d5Sgjelinek return (Z_INVALID_DOCUMENT); 631*8cd327d5Sgjelinek 632*8cd327d5Sgjelinek /* delete any comments such as inherited Sun copyright / ident str */ 633*8cd327d5Sgjelinek stripcomments(rem_handle); 634*8cd327d5Sgjelinek 635*8cd327d5Sgjelinek rem_handle->zone_dh_newzone = B_TRUE; 636*8cd327d5Sgjelinek rem_handle->zone_dh_sw_inv = B_TRUE; 637*8cd327d5Sgjelinek 638*8cd327d5Sgjelinek /* 639*8cd327d5Sgjelinek * Now use the remote system handle to generate a local system handle 640*8cd327d5Sgjelinek * with an identical zones configuration but no sw inventory. 641*8cd327d5Sgjelinek */ 642*8cd327d5Sgjelinek if ((local_handle->zone_dh_doc = xmlCopyDoc(rem_handle->zone_dh_doc, 643*8cd327d5Sgjelinek 1)) == NULL) { 644*8cd327d5Sgjelinek return (Z_INVALID_DOCUMENT); 645*8cd327d5Sgjelinek } 646*8cd327d5Sgjelinek 647*8cd327d5Sgjelinek /* 648*8cd327d5Sgjelinek * We need to re-run xmlValidateDocument on local_handle to properly 649*8cd327d5Sgjelinek * update the in-core representation of the configuration. 650*8cd327d5Sgjelinek */ 651*8cd327d5Sgjelinek if ((cvp = xmlNewValidCtxt()) == NULL) 652*8cd327d5Sgjelinek return (Z_NOMEM); 653*8cd327d5Sgjelinek cvp->error = zonecfg_error_func; 654*8cd327d5Sgjelinek cvp->warning = zonecfg_error_func; 655*8cd327d5Sgjelinek valid = xmlValidateDocument(cvp, local_handle->zone_dh_doc); 656*8cd327d5Sgjelinek xmlFreeValidCtxt(cvp); 657*8cd327d5Sgjelinek if (valid == 0) 658*8cd327d5Sgjelinek return (Z_INVALID_DOCUMENT); 659*8cd327d5Sgjelinek 660*8cd327d5Sgjelinek strip_sw_inv(local_handle); 661*8cd327d5Sgjelinek 662*8cd327d5Sgjelinek local_handle->zone_dh_newzone = B_TRUE; 663*8cd327d5Sgjelinek local_handle->zone_dh_sw_inv = B_FALSE; 664*8cd327d5Sgjelinek 665*8cd327d5Sgjelinek return (Z_OK); 666*8cd327d5Sgjelinek } 667*8cd327d5Sgjelinek 668087719fdSdp static boolean_t 669087719fdSdp is_renaming(zone_dochandle_t handle) 670087719fdSdp { 671087719fdSdp if (handle->zone_dh_newzone) 672087719fdSdp return (B_FALSE); 673087719fdSdp if (strlen(handle->zone_dh_delete_name) > 0) 674087719fdSdp return (B_TRUE); 675087719fdSdp return (B_FALSE); 676087719fdSdp } 677087719fdSdp 678087719fdSdp static boolean_t 679087719fdSdp is_new(zone_dochandle_t handle) 680087719fdSdp { 681087719fdSdp return (handle->zone_dh_newzone || handle->zone_dh_snapshot); 682087719fdSdp } 683087719fdSdp 684087719fdSdp static boolean_t 685087719fdSdp is_snapshot(zone_dochandle_t handle) 686087719fdSdp { 687087719fdSdp return (handle->zone_dh_snapshot); 688087719fdSdp } 689087719fdSdp 690087719fdSdp /* 691087719fdSdp * It would be great to be able to use libc's ctype(3c) macros, but we 692087719fdSdp * can't, as they are locale sensitive, and it would break our limited thread 693087719fdSdp * safety if this routine had to change the app locale on the fly. 694087719fdSdp */ 695087719fdSdp int 696108322fbScarlsonj zonecfg_validate_zonename(const char *zone) 697087719fdSdp { 698087719fdSdp int i; 699087719fdSdp 700087719fdSdp if (strcmp(zone, GLOBAL_ZONENAME) == 0) 701087719fdSdp return (Z_BOGUS_ZONE_NAME); 702087719fdSdp 703087719fdSdp if (strlen(zone) >= ZONENAME_MAX) 704087719fdSdp return (Z_BOGUS_ZONE_NAME); 705087719fdSdp 706087719fdSdp if (!((zone[0] >= 'a' && zone[0] <= 'z') || 707087719fdSdp (zone[0] >= 'A' && zone[0] <= 'Z') || 708087719fdSdp (zone[0] >= '0' && zone[0] <= '9'))) 709087719fdSdp return (Z_BOGUS_ZONE_NAME); 710087719fdSdp 711087719fdSdp for (i = 1; zone[i] != '\0'; i++) { 712087719fdSdp if (!((zone[i] >= 'a' && zone[i] <= 'z') || 713087719fdSdp (zone[i] >= 'A' && zone[i] <= 'Z') || 714087719fdSdp (zone[i] >= '0' && zone[i] <= '9') || 715087719fdSdp (zone[i] == '-') || (zone[i] == '_') || (zone[i] == '.'))) 716087719fdSdp return (Z_BOGUS_ZONE_NAME); 717087719fdSdp } 718087719fdSdp 719087719fdSdp return (Z_OK); 720087719fdSdp } 721087719fdSdp 722087719fdSdp /* 723087719fdSdp * Changing the zone name requires us to track both the old and new 724087719fdSdp * name of the zone until commit time. 725087719fdSdp */ 7267c478bd9Sstevel@tonic-gate int 7277c478bd9Sstevel@tonic-gate zonecfg_get_name(zone_dochandle_t handle, char *name, size_t namesize) 7287c478bd9Sstevel@tonic-gate { 729a1be23daSdp return (getrootattr(handle, DTD_ATTR_NAME, name, namesize)); 730a1be23daSdp } 7317c478bd9Sstevel@tonic-gate 732a1be23daSdp int 733a1be23daSdp zonecfg_set_name(zone_dochandle_t handle, char *name) 734a1be23daSdp { 735087719fdSdp zone_state_t state; 736087719fdSdp char curname[ZONENAME_MAX], old_delname[ZONENAME_MAX]; 737087719fdSdp int err; 738087719fdSdp 739087719fdSdp if ((err = getrootattr(handle, DTD_ATTR_NAME, curname, 740087719fdSdp sizeof (curname))) != Z_OK) 741087719fdSdp return (err); 742087719fdSdp 743087719fdSdp if (strcmp(name, curname) == 0) 744087719fdSdp return (Z_OK); 745087719fdSdp 746087719fdSdp /* 747087719fdSdp * Switching zone names to one beginning with SUNW is not permitted. 748087719fdSdp */ 749087719fdSdp if (strncmp(name, "SUNW", 4) == 0) 750087719fdSdp return (Z_BOGUS_ZONE_NAME); 751087719fdSdp 752087719fdSdp if ((err = zonecfg_validate_zonename(name)) != Z_OK) 753087719fdSdp return (err); 754087719fdSdp 755087719fdSdp /* 756087719fdSdp * Setting the name back to the original name (effectively a revert of 757087719fdSdp * the name) is fine. But if we carry on, we'll falsely identify the 758087719fdSdp * name as "in use," so special case here. 759087719fdSdp */ 760087719fdSdp if (strcmp(name, handle->zone_dh_delete_name) == 0) { 761087719fdSdp err = setrootattr(handle, DTD_ATTR_NAME, name); 762087719fdSdp handle->zone_dh_delete_name[0] = '\0'; 763087719fdSdp return (err); 764087719fdSdp } 765087719fdSdp 766087719fdSdp /* Check to see if new name chosen is already in use */ 767087719fdSdp if (zone_get_state(name, &state) != Z_NO_ZONE) 768087719fdSdp return (Z_NAME_IN_USE); 769087719fdSdp 770087719fdSdp /* 771087719fdSdp * If this isn't already "new" or in a renaming transition, then 772087719fdSdp * we're initiating a rename here; so stash the "delete name" 773087719fdSdp * (i.e. the name of the zone we'll be removing) for the rename. 774087719fdSdp */ 775087719fdSdp (void) strlcpy(old_delname, handle->zone_dh_delete_name, 776087719fdSdp sizeof (old_delname)); 777087719fdSdp if (!is_new(handle) && !is_renaming(handle)) { 778087719fdSdp /* 779087719fdSdp * Name change is allowed only when the zone we're altering 780087719fdSdp * is not ready or running. 781087719fdSdp */ 782087719fdSdp err = zone_get_state(curname, &state); 783087719fdSdp if (err == Z_OK) { 784087719fdSdp if (state > ZONE_STATE_INSTALLED) 785087719fdSdp return (Z_BAD_ZONE_STATE); 786087719fdSdp } else if (err != Z_NO_ZONE) { 787087719fdSdp return (err); 788087719fdSdp } 789087719fdSdp 790087719fdSdp (void) strlcpy(handle->zone_dh_delete_name, curname, 791087719fdSdp sizeof (handle->zone_dh_delete_name)); 792087719fdSdp assert(is_renaming(handle)); 793087719fdSdp } else if (is_renaming(handle)) { 794087719fdSdp err = zone_get_state(handle->zone_dh_delete_name, &state); 795087719fdSdp if (err == Z_OK) { 796087719fdSdp if (state > ZONE_STATE_INSTALLED) 797087719fdSdp return (Z_BAD_ZONE_STATE); 798087719fdSdp } else if (err != Z_NO_ZONE) { 799087719fdSdp return (err); 800087719fdSdp } 801087719fdSdp } 802087719fdSdp 803087719fdSdp if ((err = setrootattr(handle, DTD_ATTR_NAME, name)) != Z_OK) { 804087719fdSdp /* 805087719fdSdp * Restore the deletename to whatever it was at the 806087719fdSdp * top of the routine, since we've had a failure. 807087719fdSdp */ 808087719fdSdp (void) strlcpy(handle->zone_dh_delete_name, old_delname, 809087719fdSdp sizeof (handle->zone_dh_delete_name)); 810087719fdSdp return (err); 811087719fdSdp } 812087719fdSdp 813087719fdSdp return (Z_OK); 814a1be23daSdp } 8157c478bd9Sstevel@tonic-gate 816a1be23daSdp int 817a1be23daSdp zonecfg_get_zonepath(zone_dochandle_t handle, char *path, size_t pathsize) 818a1be23daSdp { 819108322fbScarlsonj size_t len; 820108322fbScarlsonj 821108322fbScarlsonj if ((len = strlcpy(path, zonecfg_root, pathsize)) >= pathsize) 822108322fbScarlsonj return (Z_TOO_BIG); 823108322fbScarlsonj return (getrootattr(handle, DTD_ATTR_ZONEPATH, path + len, 824108322fbScarlsonj pathsize - len)); 825a1be23daSdp } 8267c478bd9Sstevel@tonic-gate 827a1be23daSdp int 828a1be23daSdp zonecfg_set_zonepath(zone_dochandle_t handle, char *zonepath) 829a1be23daSdp { 830a1be23daSdp return (setrootattr(handle, DTD_ATTR_ZONEPATH, zonepath)); 831a1be23daSdp } 832a1be23daSdp 833a1be23daSdp int 834a1be23daSdp zonecfg_get_autoboot(zone_dochandle_t handle, boolean_t *autoboot) 835a1be23daSdp { 836a1be23daSdp char autobootstr[DTD_ENTITY_BOOL_LEN]; 837a1be23daSdp int ret; 838a1be23daSdp 839a1be23daSdp if ((ret = getrootattr(handle, DTD_ATTR_AUTOBOOT, autobootstr, 840a1be23daSdp sizeof (autobootstr))) != Z_OK) 841a1be23daSdp return (ret); 842a1be23daSdp 843a1be23daSdp if (strcmp(autobootstr, DTD_ENTITY_TRUE) == 0) 844a1be23daSdp *autoboot = B_TRUE; 845a1be23daSdp else if (strcmp(autobootstr, DTD_ENTITY_FALSE) == 0) 846a1be23daSdp *autoboot = B_FALSE; 847a1be23daSdp else 848a1be23daSdp ret = Z_BAD_PROPERTY; 849a1be23daSdp return (ret); 850a1be23daSdp } 851a1be23daSdp 852a1be23daSdp int 853a1be23daSdp zonecfg_set_autoboot(zone_dochandle_t handle, boolean_t autoboot) 854a1be23daSdp { 855a1be23daSdp return (setrootattr(handle, DTD_ATTR_AUTOBOOT, 856a1be23daSdp autoboot ? DTD_ENTITY_TRUE : DTD_ENTITY_FALSE)); 857a1be23daSdp } 858a1be23daSdp 859a1be23daSdp int 860a1be23daSdp zonecfg_get_pool(zone_dochandle_t handle, char *pool, size_t poolsize) 861a1be23daSdp { 862a1be23daSdp return (getrootattr(handle, DTD_ATTR_POOL, pool, poolsize)); 863a1be23daSdp } 864a1be23daSdp 865a1be23daSdp int 866a1be23daSdp zonecfg_set_pool(zone_dochandle_t handle, char *pool) 867a1be23daSdp { 868a1be23daSdp return (setrootattr(handle, DTD_ATTR_POOL, pool)); 869a1be23daSdp } 870a1be23daSdp 871ffbafc53Scomay int 872ffbafc53Scomay zonecfg_get_limitpriv(zone_dochandle_t handle, char **limitpriv) 873ffbafc53Scomay { 874ffbafc53Scomay return (get_alloc_rootattr(handle, DTD_ATTR_LIMITPRIV, limitpriv)); 875ffbafc53Scomay } 876ffbafc53Scomay 877ffbafc53Scomay int 878ffbafc53Scomay zonecfg_set_limitpriv(zone_dochandle_t handle, char *limitprivsize) 879ffbafc53Scomay { 880ffbafc53Scomay return (setrootattr(handle, DTD_ATTR_LIMITPRIV, limitprivsize)); 881ffbafc53Scomay } 882ffbafc53Scomay 883a1be23daSdp /* 884a1be23daSdp * /etc/zones/index caches a vital piece of information which is also 885a1be23daSdp * in the <zonename>.xml file: the path to the zone. This is for performance, 886a1be23daSdp * since we need to walk all zonepath's in order to be able to detect conflicts 887a1be23daSdp * (see crosscheck_zonepaths() in the zoneadm command). 888087719fdSdp * 889087719fdSdp * An additional complexity is that when doing a rename, we'd like the entire 890087719fdSdp * index update operation (rename, and potential state changes) to be atomic. 891087719fdSdp * In general, the operation of this function should succeed or fail as 892087719fdSdp * a unit. 893a1be23daSdp */ 894a1be23daSdp int 895a1be23daSdp zonecfg_refresh_index_file(zone_dochandle_t handle) 896a1be23daSdp { 897a1be23daSdp char name[ZONENAME_MAX], zonepath[MAXPATHLEN]; 898a1be23daSdp struct zoneent ze; 899a1be23daSdp int err; 900087719fdSdp int opcode; 901087719fdSdp char *zn; 902087719fdSdp 903087719fdSdp bzero(&ze, sizeof (ze)); 904087719fdSdp ze.zone_state = -1; /* Preserve existing state in index */ 905a1be23daSdp 906a1be23daSdp if ((err = zonecfg_get_name(handle, name, sizeof (name))) != Z_OK) 907a1be23daSdp return (err); 908087719fdSdp (void) strlcpy(ze.zone_name, name, sizeof (ze.zone_name)); 909087719fdSdp 910a1be23daSdp if ((err = zonecfg_get_zonepath(handle, zonepath, 911a1be23daSdp sizeof (zonepath))) != Z_OK) 912a1be23daSdp return (err); 913a1be23daSdp (void) strlcpy(ze.zone_path, zonepath, sizeof (ze.zone_path)); 914087719fdSdp 915087719fdSdp if (is_renaming(handle)) { 916087719fdSdp opcode = PZE_MODIFY; 917087719fdSdp (void) strlcpy(ze.zone_name, handle->zone_dh_delete_name, 918087719fdSdp sizeof (ze.zone_name)); 919087719fdSdp (void) strlcpy(ze.zone_newname, name, sizeof (ze.zone_newname)); 920087719fdSdp } else if (is_new(handle)) { 921087719fdSdp FILE *cookie; 922087719fdSdp /* 923087719fdSdp * Be tolerant of the zone already existing in the index file, 924087719fdSdp * since we might be forcibly overwriting an existing 925087719fdSdp * configuration with a new one (for example 'create -F' 926087719fdSdp * in zonecfg). 927087719fdSdp */ 928087719fdSdp opcode = PZE_ADD; 929087719fdSdp cookie = setzoneent(); 930087719fdSdp while ((zn = getzoneent(cookie)) != NULL) { 931087719fdSdp if (strcmp(zn, name) == 0) { 932087719fdSdp opcode = PZE_MODIFY; 933087719fdSdp free(zn); 934087719fdSdp break; 935087719fdSdp } 936087719fdSdp free(zn); 937087719fdSdp } 938087719fdSdp endzoneent(cookie); 939087719fdSdp ze.zone_state = ZONE_STATE_CONFIGURED; 940087719fdSdp } else { 941087719fdSdp opcode = PZE_MODIFY; 942087719fdSdp } 943087719fdSdp 944087719fdSdp if ((err = putzoneent(&ze, opcode)) != Z_OK) 945087719fdSdp return (err); 946087719fdSdp 947087719fdSdp return (Z_OK); 9487c478bd9Sstevel@tonic-gate } 9497c478bd9Sstevel@tonic-gate 950087719fdSdp /* 951087719fdSdp * The goal of this routine is to cause the index file update and the 952087719fdSdp * document save to happen as an atomic operation. We do the document 953087719fdSdp * first, saving a backup copy using a hard link; if that succeeds, we go 954087719fdSdp * on to the index. If that fails, we roll the document back into place. 955087719fdSdp * 956087719fdSdp * Strategy: 957087719fdSdp * 958087719fdSdp * New zone 'foo' configuration: 959087719fdSdp * Create tmpfile (zonecfg.xxxxxx) 960087719fdSdp * Write XML to tmpfile 961087719fdSdp * Rename tmpfile to xmlfile (zonecfg.xxxxxx -> foo.xml) 962087719fdSdp * Add entry to index file 963087719fdSdp * If it fails, delete foo.xml, leaving nothing behind. 964087719fdSdp * 965087719fdSdp * Save existing zone 'foo': 966087719fdSdp * Make backup of foo.xml -> .backup 967087719fdSdp * Create tmpfile (zonecfg.xxxxxx) 968087719fdSdp * Write XML to tmpfile 969087719fdSdp * Rename tmpfile to xmlfile (zonecfg.xxxxxx -> foo.xml) 970087719fdSdp * Modify index file as needed 971087719fdSdp * If it fails, recover from .backup -> foo.xml 972087719fdSdp * 973087719fdSdp * Rename 'foo' to 'bar': 974087719fdSdp * Create tmpfile (zonecfg.xxxxxx) 975087719fdSdp * Write XML to tmpfile 976087719fdSdp * Rename tmpfile to xmlfile (zonecfg.xxxxxx -> bar.xml) 977087719fdSdp * Add entry for 'bar' to index file, Remove entry for 'foo' (refresh) 978087719fdSdp * If it fails, delete bar.xml; foo.xml is left behind. 979087719fdSdp */ 9807c478bd9Sstevel@tonic-gate static int 9817c478bd9Sstevel@tonic-gate zonecfg_save_impl(zone_dochandle_t handle, char *filename) 9827c478bd9Sstevel@tonic-gate { 9837c478bd9Sstevel@tonic-gate char tmpfile[MAXPATHLEN]; 984087719fdSdp char bakdir[MAXPATHLEN], bakbase[MAXPATHLEN], bakfile[MAXPATHLEN]; 985087719fdSdp int tmpfd, err; 9867c478bd9Sstevel@tonic-gate xmlValidCtxt cvp = { NULL }; 987087719fdSdp boolean_t backup; 9887c478bd9Sstevel@tonic-gate 9897c478bd9Sstevel@tonic-gate (void) strlcpy(tmpfile, filename, sizeof (tmpfile)); 9907c478bd9Sstevel@tonic-gate (void) dirname(tmpfile); 9917c478bd9Sstevel@tonic-gate (void) strlcat(tmpfile, _PATH_TMPFILE, sizeof (tmpfile)); 9927c478bd9Sstevel@tonic-gate 9937c478bd9Sstevel@tonic-gate tmpfd = mkstemp(tmpfile); 9947c478bd9Sstevel@tonic-gate if (tmpfd == -1) { 9957c478bd9Sstevel@tonic-gate (void) unlink(tmpfile); 9967c478bd9Sstevel@tonic-gate return (Z_TEMP_FILE); 9977c478bd9Sstevel@tonic-gate } 9987c478bd9Sstevel@tonic-gate (void) close(tmpfd); 9997c478bd9Sstevel@tonic-gate 10007c478bd9Sstevel@tonic-gate cvp.error = zonecfg_error_func; 10017c478bd9Sstevel@tonic-gate cvp.warning = zonecfg_error_func; 10027c478bd9Sstevel@tonic-gate 1003087719fdSdp /* 1004087719fdSdp * We do a final validation of the document-- but the library has 1005087719fdSdp * malfunctioned if it fails to validate, so it's an assert. 1006087719fdSdp */ 1007087719fdSdp assert(xmlValidateDocument(&cvp, handle->zone_dh_doc) != 0); 10087c478bd9Sstevel@tonic-gate 10097c478bd9Sstevel@tonic-gate if (xmlSaveFormatFile(tmpfile, handle->zone_dh_doc, 1) <= 0) 10107c478bd9Sstevel@tonic-gate goto err; 1011087719fdSdp 10127c478bd9Sstevel@tonic-gate (void) chmod(tmpfile, 0644); 10137c478bd9Sstevel@tonic-gate 1014087719fdSdp /* 1015087719fdSdp * In the event we are doing a standard save, hard link a copy of the 1016087719fdSdp * original file in .backup.<pid>.filename so we can restore it if 1017087719fdSdp * something goes wrong. 1018087719fdSdp */ 1019087719fdSdp if (!is_new(handle) && !is_renaming(handle)) { 1020087719fdSdp backup = B_TRUE; 1021087719fdSdp 1022087719fdSdp (void) strlcpy(bakdir, filename, sizeof (bakdir)); 1023087719fdSdp (void) strlcpy(bakbase, filename, sizeof (bakbase)); 1024087719fdSdp (void) snprintf(bakfile, sizeof (bakfile), "%s/.backup.%d.%s", 1025087719fdSdp dirname(bakdir), getpid(), basename(bakbase)); 1026087719fdSdp 1027087719fdSdp if (link(filename, bakfile) == -1) { 1028087719fdSdp err = errno; 1029087719fdSdp (void) unlink(tmpfile); 1030087719fdSdp if (errno == EACCES) 1031087719fdSdp return (Z_ACCES); 1032087719fdSdp return (Z_MISC_FS); 1033087719fdSdp } 1034087719fdSdp } 1035087719fdSdp 1036087719fdSdp /* 1037087719fdSdp * Move the new document over top of the old. 1038087719fdSdp * i.e.: zonecfg.XXXXXX -> myzone.xml 1039087719fdSdp */ 10407c478bd9Sstevel@tonic-gate if (rename(tmpfile, filename) == -1) { 1041087719fdSdp err = errno; 10427c478bd9Sstevel@tonic-gate (void) unlink(tmpfile); 1043087719fdSdp if (backup) 1044087719fdSdp (void) unlink(bakfile); 1045087719fdSdp if (err == EACCES) 10467c478bd9Sstevel@tonic-gate return (Z_ACCES); 10477c478bd9Sstevel@tonic-gate return (Z_MISC_FS); 10487c478bd9Sstevel@tonic-gate } 1049a1be23daSdp 1050087719fdSdp /* 1051087719fdSdp * If this is a snapshot, we're done-- don't add an index entry. 1052087719fdSdp */ 1053087719fdSdp if (is_snapshot(handle)) 1054087719fdSdp return (Z_OK); 1055087719fdSdp 1056087719fdSdp /* now update the index file to reflect whatever we just did */ 1057087719fdSdp if ((err = zonecfg_refresh_index_file(handle)) != Z_OK) { 1058087719fdSdp if (backup) { 1059087719fdSdp /* 1060087719fdSdp * Try to restore from our backup. 1061087719fdSdp */ 1062087719fdSdp (void) unlink(filename); 1063087719fdSdp (void) rename(bakfile, filename); 1064087719fdSdp } else { 1065087719fdSdp /* 1066087719fdSdp * Either the zone is new, in which case we can delete 1067087719fdSdp * new.xml, or we're doing a rename, so ditto. 1068087719fdSdp */ 1069087719fdSdp assert(is_new(handle) || is_renaming(handle)); 1070087719fdSdp (void) unlink(filename); 1071087719fdSdp } 1072087719fdSdp return (Z_UPDATING_INDEX); 1073087719fdSdp } 1074087719fdSdp 1075087719fdSdp if (backup) 1076087719fdSdp (void) unlink(bakfile); 1077087719fdSdp 1078087719fdSdp return (Z_OK); 10797c478bd9Sstevel@tonic-gate 10807c478bd9Sstevel@tonic-gate err: 10817c478bd9Sstevel@tonic-gate (void) unlink(tmpfile); 10827c478bd9Sstevel@tonic-gate return (Z_SAVING_FILE); 10837c478bd9Sstevel@tonic-gate } 10847c478bd9Sstevel@tonic-gate 10857c478bd9Sstevel@tonic-gate int 10867c478bd9Sstevel@tonic-gate zonecfg_save(zone_dochandle_t handle) 10877c478bd9Sstevel@tonic-gate { 1088087719fdSdp char zname[ZONENAME_MAX], path[MAXPATHLEN]; 1089087719fdSdp char delpath[MAXPATHLEN]; 1090087719fdSdp int err = Z_SAVING_FILE; 1091087719fdSdp 1092087719fdSdp if (zonecfg_check_handle(handle) != Z_OK) 1093087719fdSdp return (Z_BAD_HANDLE); 10947c478bd9Sstevel@tonic-gate 1095087719fdSdp /* 1096ee519a1fSgjelinek * We don't support saving snapshots or a tree containing a sw 1097ee519a1fSgjelinek * inventory at this time. 1098087719fdSdp */ 1099ee519a1fSgjelinek if (handle->zone_dh_snapshot || handle->zone_dh_sw_inv) 1100087719fdSdp return (Z_INVAL); 1101087719fdSdp 1102087719fdSdp if ((err = zonecfg_get_name(handle, zname, sizeof (zname))) != Z_OK) 11037c478bd9Sstevel@tonic-gate return (err); 1104087719fdSdp 1105108322fbScarlsonj if (!config_file_path(zname, path)) 1106108322fbScarlsonj return (Z_MISC_FS); 1107087719fdSdp 1108087719fdSdp addcomment(handle, "\n DO NOT EDIT THIS " 1109087719fdSdp "FILE. Use zonecfg(1M) instead.\n"); 1110087719fdSdp 1111087719fdSdp err = zonecfg_save_impl(handle, path); 1112087719fdSdp 1113087719fdSdp stripcomments(handle); 1114087719fdSdp 1115087719fdSdp if (err != Z_OK) 1116087719fdSdp return (err); 1117087719fdSdp 1118087719fdSdp handle->zone_dh_newzone = B_FALSE; 1119087719fdSdp 1120087719fdSdp if (is_renaming(handle)) { 1121108322fbScarlsonj if (config_file_path(handle->zone_dh_delete_name, delpath)) 1122108322fbScarlsonj (void) unlink(delpath); 1123087719fdSdp handle->zone_dh_delete_name[0] = '\0'; 1124087719fdSdp } 1125087719fdSdp 1126087719fdSdp return (Z_OK); 11277c478bd9Sstevel@tonic-gate } 11287c478bd9Sstevel@tonic-gate 1129ee519a1fSgjelinek int 1130*8cd327d5Sgjelinek zonecfg_detach_save(zone_dochandle_t handle, uint_t flags) 1131ee519a1fSgjelinek { 1132ee519a1fSgjelinek char zname[ZONENAME_MAX]; 1133ee519a1fSgjelinek char path[MAXPATHLEN]; 1134ee519a1fSgjelinek char migpath[MAXPATHLEN]; 1135ee519a1fSgjelinek xmlValidCtxt cvp = { NULL }; 1136ee519a1fSgjelinek int err = Z_SAVING_FILE; 1137ee519a1fSgjelinek 1138ee519a1fSgjelinek if (zonecfg_check_handle(handle) != Z_OK) 1139ee519a1fSgjelinek return (Z_BAD_HANDLE); 1140ee519a1fSgjelinek 1141ee519a1fSgjelinek /* 1142ee519a1fSgjelinek * We can only detach if we have taken a sw inventory. 1143ee519a1fSgjelinek */ 1144ee519a1fSgjelinek if (!handle->zone_dh_sw_inv) 1145ee519a1fSgjelinek return (Z_INVAL); 1146ee519a1fSgjelinek 1147*8cd327d5Sgjelinek if (flags & ZONE_DRY_RUN) { 1148*8cd327d5Sgjelinek (void) strlcpy(migpath, "-", sizeof (migpath)); 1149*8cd327d5Sgjelinek } else { 1150*8cd327d5Sgjelinek if ((err = zonecfg_get_name(handle, zname, sizeof (zname))) 1151*8cd327d5Sgjelinek != Z_OK) 1152*8cd327d5Sgjelinek return (err); 1153ee519a1fSgjelinek 1154*8cd327d5Sgjelinek if ((err = zone_get_zonepath(zname, path, sizeof (path))) 1155*8cd327d5Sgjelinek != Z_OK) 1156*8cd327d5Sgjelinek return (err); 1157ee519a1fSgjelinek 1158*8cd327d5Sgjelinek if (snprintf(migpath, sizeof (migpath), "%s/%s", path, DETACHED) 1159*8cd327d5Sgjelinek >= sizeof (migpath)) 1160*8cd327d5Sgjelinek return (Z_NOMEM); 1161*8cd327d5Sgjelinek } 1162ee519a1fSgjelinek 1163ee519a1fSgjelinek if ((err = operation_prep(handle)) != Z_OK) 1164ee519a1fSgjelinek return (err); 1165ee519a1fSgjelinek 1166ee519a1fSgjelinek addcomment(handle, "\n DO NOT EDIT THIS FILE. " 1167ee519a1fSgjelinek "Use zonecfg(1M) and zoneadm(1M) attach.\n"); 1168ee519a1fSgjelinek 1169ee519a1fSgjelinek cvp.error = zonecfg_error_func; 1170ee519a1fSgjelinek cvp.warning = zonecfg_error_func; 1171ee519a1fSgjelinek 1172ee519a1fSgjelinek /* 1173ee519a1fSgjelinek * We do a final validation of the document-- but the library has 1174ee519a1fSgjelinek * malfunctioned if it fails to validate, so it's an assert. 1175ee519a1fSgjelinek */ 1176ee519a1fSgjelinek assert(xmlValidateDocument(&cvp, handle->zone_dh_doc) != 0); 1177ee519a1fSgjelinek 1178ee519a1fSgjelinek if (xmlSaveFormatFile(migpath, handle->zone_dh_doc, 1) <= 0) 1179ee519a1fSgjelinek return (Z_SAVING_FILE); 1180ee519a1fSgjelinek 1181*8cd327d5Sgjelinek if (!(flags & ZONE_DRY_RUN)) 1182*8cd327d5Sgjelinek (void) chmod(migpath, 0644); 1183ee519a1fSgjelinek 1184ee519a1fSgjelinek stripcomments(handle); 1185ee519a1fSgjelinek 1186ee519a1fSgjelinek handle->zone_dh_newzone = B_FALSE; 1187ee519a1fSgjelinek 1188ee519a1fSgjelinek return (Z_OK); 1189ee519a1fSgjelinek } 1190ee519a1fSgjelinek 1191ee519a1fSgjelinek boolean_t 1192ee519a1fSgjelinek zonecfg_detached(const char *path) 1193ee519a1fSgjelinek { 1194ee519a1fSgjelinek char migpath[MAXPATHLEN]; 1195ee519a1fSgjelinek struct stat buf; 1196ee519a1fSgjelinek 1197ee519a1fSgjelinek if (snprintf(migpath, sizeof (migpath), "%s/%s", path, DETACHED) >= 1198ee519a1fSgjelinek sizeof (migpath)) 1199ee519a1fSgjelinek return (B_FALSE); 1200ee519a1fSgjelinek 1201ee519a1fSgjelinek if (stat(migpath, &buf) != -1) 1202ee519a1fSgjelinek return (B_TRUE); 1203ee519a1fSgjelinek 1204ee519a1fSgjelinek return (B_FALSE); 1205ee519a1fSgjelinek } 1206ee519a1fSgjelinek 1207ee519a1fSgjelinek void 1208ee519a1fSgjelinek zonecfg_rm_detached(zone_dochandle_t handle, boolean_t forced) 1209ee519a1fSgjelinek { 1210ee519a1fSgjelinek char zname[ZONENAME_MAX]; 1211ee519a1fSgjelinek char path[MAXPATHLEN]; 1212ee519a1fSgjelinek char detached[MAXPATHLEN]; 1213ee519a1fSgjelinek char attached[MAXPATHLEN]; 1214ee519a1fSgjelinek 1215ee519a1fSgjelinek if (zonecfg_check_handle(handle) != Z_OK) 1216ee519a1fSgjelinek return; 1217ee519a1fSgjelinek 1218ee519a1fSgjelinek if (zonecfg_get_name(handle, zname, sizeof (zname)) != Z_OK) 1219ee519a1fSgjelinek return; 1220ee519a1fSgjelinek 1221ee519a1fSgjelinek if (zone_get_zonepath(zname, path, sizeof (path)) != Z_OK) 1222ee519a1fSgjelinek return; 1223ee519a1fSgjelinek 1224ee519a1fSgjelinek (void) snprintf(detached, sizeof (detached), "%s/%s", path, DETACHED); 1225ee519a1fSgjelinek (void) snprintf(attached, sizeof (attached), "%s/%s", path, 1226ee519a1fSgjelinek ATTACH_FORCED); 1227ee519a1fSgjelinek 1228ee519a1fSgjelinek if (forced) { 1229ee519a1fSgjelinek (void) rename(detached, attached); 1230ee519a1fSgjelinek } else { 1231ee519a1fSgjelinek (void) unlink(attached); 1232ee519a1fSgjelinek (void) unlink(detached); 1233ee519a1fSgjelinek } 1234ee519a1fSgjelinek } 1235ee519a1fSgjelinek 12367c478bd9Sstevel@tonic-gate /* 12377c478bd9Sstevel@tonic-gate * Special case: if access(2) fails with ENOENT, then try again using 12387c478bd9Sstevel@tonic-gate * ZONE_CONFIG_ROOT instead of config_file_path(zonename). This is how we 12397c478bd9Sstevel@tonic-gate * work around the case of a config file which has not been created yet: 12407c478bd9Sstevel@tonic-gate * the user will need access to the directory so use that as a heuristic. 12417c478bd9Sstevel@tonic-gate */ 12427c478bd9Sstevel@tonic-gate 12437c478bd9Sstevel@tonic-gate int 12447c478bd9Sstevel@tonic-gate zonecfg_access(const char *zonename, int amode) 12457c478bd9Sstevel@tonic-gate { 12467c478bd9Sstevel@tonic-gate char path[MAXPATHLEN]; 12477c478bd9Sstevel@tonic-gate 1248108322fbScarlsonj if (!config_file_path(zonename, path)) 1249108322fbScarlsonj return (Z_INVAL); 12507c478bd9Sstevel@tonic-gate if (access(path, amode) == 0) 12517c478bd9Sstevel@tonic-gate return (Z_OK); 1252108322fbScarlsonj if (errno == ENOENT) { 1253108322fbScarlsonj if (snprintf(path, sizeof (path), "%s%s", zonecfg_root, 1254108322fbScarlsonj ZONE_CONFIG_ROOT) >= sizeof (path)) 1255108322fbScarlsonj return (Z_INVAL); 1256108322fbScarlsonj if (access(path, amode) == 0) 1257108322fbScarlsonj return (Z_OK); 1258108322fbScarlsonj } 12597c478bd9Sstevel@tonic-gate if (errno == EACCES) 12607c478bd9Sstevel@tonic-gate return (Z_ACCES); 12617c478bd9Sstevel@tonic-gate if (errno == EINVAL) 12627c478bd9Sstevel@tonic-gate return (Z_INVAL); 12637c478bd9Sstevel@tonic-gate return (Z_MISC_FS); 12647c478bd9Sstevel@tonic-gate } 12657c478bd9Sstevel@tonic-gate 12667c478bd9Sstevel@tonic-gate int 1267108322fbScarlsonj zonecfg_create_snapshot(const char *zonename) 12687c478bd9Sstevel@tonic-gate { 12697c478bd9Sstevel@tonic-gate zone_dochandle_t handle; 12707c478bd9Sstevel@tonic-gate char path[MAXPATHLEN], zonepath[MAXPATHLEN], rpath[MAXPATHLEN]; 12717c478bd9Sstevel@tonic-gate int error = Z_OK, res; 12727c478bd9Sstevel@tonic-gate 12737c478bd9Sstevel@tonic-gate if ((handle = zonecfg_init_handle()) == NULL) { 12747c478bd9Sstevel@tonic-gate return (Z_NOMEM); 12757c478bd9Sstevel@tonic-gate } 12767c478bd9Sstevel@tonic-gate 1277087719fdSdp handle->zone_dh_newzone = B_TRUE; 1278087719fdSdp handle->zone_dh_snapshot = B_TRUE; 1279087719fdSdp 12807c478bd9Sstevel@tonic-gate if ((error = zonecfg_get_handle(zonename, handle)) != Z_OK) 12817c478bd9Sstevel@tonic-gate goto out; 12827c478bd9Sstevel@tonic-gate if ((error = operation_prep(handle)) != Z_OK) 12837c478bd9Sstevel@tonic-gate goto out; 12847c478bd9Sstevel@tonic-gate error = zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath)); 12857c478bd9Sstevel@tonic-gate if (error != Z_OK) 12867c478bd9Sstevel@tonic-gate goto out; 12877c478bd9Sstevel@tonic-gate if ((res = resolvepath(zonepath, rpath, sizeof (rpath))) == -1) { 12887c478bd9Sstevel@tonic-gate error = Z_RESOLVED_PATH; 12897c478bd9Sstevel@tonic-gate goto out; 12907c478bd9Sstevel@tonic-gate } 12917c478bd9Sstevel@tonic-gate /* 12927c478bd9Sstevel@tonic-gate * If the resolved path is not the same as the original path, then 12937c478bd9Sstevel@tonic-gate * save the resolved path in the snapshot, thus preventing any 12947c478bd9Sstevel@tonic-gate * potential problems down the line when zoneadmd goes to unmount 12957c478bd9Sstevel@tonic-gate * file systems and depends on initial string matches with resolved 12967c478bd9Sstevel@tonic-gate * paths. 12977c478bd9Sstevel@tonic-gate */ 12987c478bd9Sstevel@tonic-gate rpath[res] = '\0'; 12997c478bd9Sstevel@tonic-gate if (strcmp(zonepath, rpath) != 0) { 13007c478bd9Sstevel@tonic-gate if ((error = zonecfg_set_zonepath(handle, rpath)) != Z_OK) 13017c478bd9Sstevel@tonic-gate goto out; 13027c478bd9Sstevel@tonic-gate } 1303108322fbScarlsonj if (snprintf(path, sizeof (path), "%s%s", zonecfg_root, 1304108322fbScarlsonj ZONE_SNAPSHOT_ROOT) >= sizeof (path)) { 1305108322fbScarlsonj error = Z_MISC_FS; 1306108322fbScarlsonj goto out; 1307108322fbScarlsonj } 1308108322fbScarlsonj if ((mkdir(path, S_IRWXU) == -1) && (errno != EEXIST)) { 13097c478bd9Sstevel@tonic-gate error = Z_MISC_FS; 13107c478bd9Sstevel@tonic-gate goto out; 13117c478bd9Sstevel@tonic-gate } 13127c478bd9Sstevel@tonic-gate 1313108322fbScarlsonj if (!snap_file_path(zonename, path)) { 1314108322fbScarlsonj error = Z_MISC_FS; 1315108322fbScarlsonj goto out; 1316108322fbScarlsonj } 1317087719fdSdp 1318087719fdSdp addcomment(handle, "\n DO NOT EDIT THIS FILE. " 1319087719fdSdp "It is a snapshot of running zone state.\n"); 1320087719fdSdp 13217c478bd9Sstevel@tonic-gate error = zonecfg_save_impl(handle, path); 13227c478bd9Sstevel@tonic-gate 1323087719fdSdp stripcomments(handle); 1324087719fdSdp 13257c478bd9Sstevel@tonic-gate out: 13267c478bd9Sstevel@tonic-gate zonecfg_fini_handle(handle); 13277c478bd9Sstevel@tonic-gate return (error); 13287c478bd9Sstevel@tonic-gate } 13297c478bd9Sstevel@tonic-gate 13307c478bd9Sstevel@tonic-gate static int 1331a1be23daSdp newprop(xmlNodePtr node, const xmlChar *attrname, char *src) 13327c478bd9Sstevel@tonic-gate { 13337c478bd9Sstevel@tonic-gate xmlAttrPtr newattr; 13347c478bd9Sstevel@tonic-gate 13357c478bd9Sstevel@tonic-gate newattr = xmlNewProp(node, attrname, (xmlChar *)src); 13367c478bd9Sstevel@tonic-gate if (newattr == NULL) { 13377c478bd9Sstevel@tonic-gate xmlUnlinkNode(node); 13387c478bd9Sstevel@tonic-gate xmlFreeNode(node); 13397c478bd9Sstevel@tonic-gate return (Z_BAD_PROPERTY); 13407c478bd9Sstevel@tonic-gate } 13417c478bd9Sstevel@tonic-gate return (Z_OK); 13427c478bd9Sstevel@tonic-gate } 13437c478bd9Sstevel@tonic-gate 13447c478bd9Sstevel@tonic-gate static int 13457c478bd9Sstevel@tonic-gate zonecfg_add_filesystem_core(zone_dochandle_t handle, struct zone_fstab *tabptr) 13467c478bd9Sstevel@tonic-gate { 13477c478bd9Sstevel@tonic-gate xmlNodePtr newnode, cur = handle->zone_dh_cur, options_node; 13487c478bd9Sstevel@tonic-gate zone_fsopt_t *ptr; 13497c478bd9Sstevel@tonic-gate int err; 13507c478bd9Sstevel@tonic-gate 13517c478bd9Sstevel@tonic-gate newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_FS, NULL); 1352a1be23daSdp if ((err = newprop(newnode, DTD_ATTR_SPECIAL, 13537c478bd9Sstevel@tonic-gate tabptr->zone_fs_special)) != Z_OK) 13547c478bd9Sstevel@tonic-gate return (err); 13557c478bd9Sstevel@tonic-gate if (tabptr->zone_fs_raw[0] != '\0' && 1356a1be23daSdp (err = newprop(newnode, DTD_ATTR_RAW, tabptr->zone_fs_raw)) != Z_OK) 13577c478bd9Sstevel@tonic-gate return (err); 1358a1be23daSdp if ((err = newprop(newnode, DTD_ATTR_DIR, tabptr->zone_fs_dir)) != Z_OK) 13597c478bd9Sstevel@tonic-gate return (err); 1360a1be23daSdp if ((err = newprop(newnode, DTD_ATTR_TYPE, 13617c478bd9Sstevel@tonic-gate tabptr->zone_fs_type)) != Z_OK) 13627c478bd9Sstevel@tonic-gate return (err); 13637c478bd9Sstevel@tonic-gate if (tabptr->zone_fs_options != NULL) { 13647c478bd9Sstevel@tonic-gate for (ptr = tabptr->zone_fs_options; ptr != NULL; 13657c478bd9Sstevel@tonic-gate ptr = ptr->zone_fsopt_next) { 13667c478bd9Sstevel@tonic-gate options_node = xmlNewTextChild(newnode, NULL, 13677c478bd9Sstevel@tonic-gate DTD_ELEM_FSOPTION, NULL); 1368a1be23daSdp if ((err = newprop(options_node, DTD_ATTR_NAME, 13697c478bd9Sstevel@tonic-gate ptr->zone_fsopt_opt)) != Z_OK) 13707c478bd9Sstevel@tonic-gate return (err); 13717c478bd9Sstevel@tonic-gate } 13727c478bd9Sstevel@tonic-gate } 13737c478bd9Sstevel@tonic-gate return (Z_OK); 13747c478bd9Sstevel@tonic-gate } 13757c478bd9Sstevel@tonic-gate 13767c478bd9Sstevel@tonic-gate int 13777c478bd9Sstevel@tonic-gate zonecfg_add_filesystem(zone_dochandle_t handle, struct zone_fstab *tabptr) 13787c478bd9Sstevel@tonic-gate { 13797c478bd9Sstevel@tonic-gate int err; 13807c478bd9Sstevel@tonic-gate 13817c478bd9Sstevel@tonic-gate if (tabptr == NULL) 13827c478bd9Sstevel@tonic-gate return (Z_INVAL); 13837c478bd9Sstevel@tonic-gate 13847c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 13857c478bd9Sstevel@tonic-gate return (err); 13867c478bd9Sstevel@tonic-gate 13877c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_filesystem_core(handle, tabptr)) != Z_OK) 13887c478bd9Sstevel@tonic-gate return (err); 13897c478bd9Sstevel@tonic-gate 13907c478bd9Sstevel@tonic-gate return (Z_OK); 13917c478bd9Sstevel@tonic-gate } 13927c478bd9Sstevel@tonic-gate 13937c478bd9Sstevel@tonic-gate static int 13947c478bd9Sstevel@tonic-gate zonecfg_add_ipd_core(zone_dochandle_t handle, struct zone_fstab *tabptr) 13957c478bd9Sstevel@tonic-gate { 13967c478bd9Sstevel@tonic-gate xmlNodePtr newnode, cur = handle->zone_dh_cur; 13977c478bd9Sstevel@tonic-gate int err; 13987c478bd9Sstevel@tonic-gate 13997c478bd9Sstevel@tonic-gate newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_IPD, NULL); 1400a1be23daSdp if ((err = newprop(newnode, DTD_ATTR_DIR, tabptr->zone_fs_dir)) != Z_OK) 14017c478bd9Sstevel@tonic-gate return (err); 14027c478bd9Sstevel@tonic-gate return (Z_OK); 14037c478bd9Sstevel@tonic-gate } 14047c478bd9Sstevel@tonic-gate 14057c478bd9Sstevel@tonic-gate int 14067c478bd9Sstevel@tonic-gate zonecfg_add_ipd(zone_dochandle_t handle, struct zone_fstab *tabptr) 14077c478bd9Sstevel@tonic-gate { 14087c478bd9Sstevel@tonic-gate int err; 14097c478bd9Sstevel@tonic-gate 14107c478bd9Sstevel@tonic-gate if (tabptr == NULL) 14117c478bd9Sstevel@tonic-gate return (Z_INVAL); 14127c478bd9Sstevel@tonic-gate 14137c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 14147c478bd9Sstevel@tonic-gate return (err); 14157c478bd9Sstevel@tonic-gate 14167c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_ipd_core(handle, tabptr)) != Z_OK) 14177c478bd9Sstevel@tonic-gate return (err); 14187c478bd9Sstevel@tonic-gate 14197c478bd9Sstevel@tonic-gate return (Z_OK); 14207c478bd9Sstevel@tonic-gate } 14217c478bd9Sstevel@tonic-gate 14227c478bd9Sstevel@tonic-gate int 14237c478bd9Sstevel@tonic-gate zonecfg_add_fs_option(struct zone_fstab *tabptr, char *option) 14247c478bd9Sstevel@tonic-gate { 14257c478bd9Sstevel@tonic-gate zone_fsopt_t *last, *old, *new; 14267c478bd9Sstevel@tonic-gate 14277c478bd9Sstevel@tonic-gate last = tabptr->zone_fs_options; 14287c478bd9Sstevel@tonic-gate for (old = last; old != NULL; old = old->zone_fsopt_next) 14297c478bd9Sstevel@tonic-gate last = old; /* walk to the end of the list */ 14307c478bd9Sstevel@tonic-gate new = (zone_fsopt_t *)malloc(sizeof (zone_fsopt_t)); 14317c478bd9Sstevel@tonic-gate if (new == NULL) 14327c478bd9Sstevel@tonic-gate return (Z_NOMEM); 14337c478bd9Sstevel@tonic-gate (void) strlcpy(new->zone_fsopt_opt, option, 14347c478bd9Sstevel@tonic-gate sizeof (new->zone_fsopt_opt)); 14357c478bd9Sstevel@tonic-gate new->zone_fsopt_next = NULL; 14367c478bd9Sstevel@tonic-gate if (last == NULL) 14377c478bd9Sstevel@tonic-gate tabptr->zone_fs_options = new; 14387c478bd9Sstevel@tonic-gate else 14397c478bd9Sstevel@tonic-gate last->zone_fsopt_next = new; 14407c478bd9Sstevel@tonic-gate return (Z_OK); 14417c478bd9Sstevel@tonic-gate } 14427c478bd9Sstevel@tonic-gate 14437c478bd9Sstevel@tonic-gate int 14447c478bd9Sstevel@tonic-gate zonecfg_remove_fs_option(struct zone_fstab *tabptr, char *option) 14457c478bd9Sstevel@tonic-gate { 14467c478bd9Sstevel@tonic-gate zone_fsopt_t *last, *this, *next; 14477c478bd9Sstevel@tonic-gate 14487c478bd9Sstevel@tonic-gate last = tabptr->zone_fs_options; 14497c478bd9Sstevel@tonic-gate for (this = last; this != NULL; this = this->zone_fsopt_next) { 14507c478bd9Sstevel@tonic-gate if (strcmp(this->zone_fsopt_opt, option) == 0) { 14517c478bd9Sstevel@tonic-gate next = this->zone_fsopt_next; 14527c478bd9Sstevel@tonic-gate if (this == tabptr->zone_fs_options) 14537c478bd9Sstevel@tonic-gate tabptr->zone_fs_options = next; 14547c478bd9Sstevel@tonic-gate else 14557c478bd9Sstevel@tonic-gate last->zone_fsopt_next = next; 14567c478bd9Sstevel@tonic-gate free(this); 14577c478bd9Sstevel@tonic-gate return (Z_OK); 14587c478bd9Sstevel@tonic-gate } else 14597c478bd9Sstevel@tonic-gate last = this; 14607c478bd9Sstevel@tonic-gate } 14617c478bd9Sstevel@tonic-gate return (Z_NO_PROPERTY_ID); 14627c478bd9Sstevel@tonic-gate } 14637c478bd9Sstevel@tonic-gate 14647c478bd9Sstevel@tonic-gate void 14657c478bd9Sstevel@tonic-gate zonecfg_free_fs_option_list(zone_fsopt_t *list) 14667c478bd9Sstevel@tonic-gate { 14677c478bd9Sstevel@tonic-gate zone_fsopt_t *this, *next; 14687c478bd9Sstevel@tonic-gate 14697c478bd9Sstevel@tonic-gate for (this = list; this != NULL; this = next) { 14707c478bd9Sstevel@tonic-gate next = this->zone_fsopt_next; 14717c478bd9Sstevel@tonic-gate free(this); 14727c478bd9Sstevel@tonic-gate } 14737c478bd9Sstevel@tonic-gate } 14747c478bd9Sstevel@tonic-gate 14757c478bd9Sstevel@tonic-gate void 14767c478bd9Sstevel@tonic-gate zonecfg_free_rctl_value_list(struct zone_rctlvaltab *valtab) 14777c478bd9Sstevel@tonic-gate { 14787c478bd9Sstevel@tonic-gate if (valtab == NULL) 14797c478bd9Sstevel@tonic-gate return; 14807c478bd9Sstevel@tonic-gate zonecfg_free_rctl_value_list(valtab->zone_rctlval_next); 14817c478bd9Sstevel@tonic-gate free(valtab); 14827c478bd9Sstevel@tonic-gate } 14837c478bd9Sstevel@tonic-gate 14847c478bd9Sstevel@tonic-gate static boolean_t 14857c478bd9Sstevel@tonic-gate match_prop(xmlNodePtr cur, const xmlChar *attr, char *user_prop) 14867c478bd9Sstevel@tonic-gate { 14877c478bd9Sstevel@tonic-gate xmlChar *gotten_prop; 14887c478bd9Sstevel@tonic-gate int prop_result; 14897c478bd9Sstevel@tonic-gate 14907c478bd9Sstevel@tonic-gate gotten_prop = xmlGetProp(cur, attr); 14917c478bd9Sstevel@tonic-gate if (gotten_prop == NULL) /* shouldn't happen */ 14927c478bd9Sstevel@tonic-gate return (B_FALSE); 14937c478bd9Sstevel@tonic-gate prop_result = xmlStrcmp(gotten_prop, (const xmlChar *) user_prop); 14947c478bd9Sstevel@tonic-gate xmlFree(gotten_prop); 14957c478bd9Sstevel@tonic-gate return ((prop_result == 0)); 14967c478bd9Sstevel@tonic-gate } 14977c478bd9Sstevel@tonic-gate 14987c478bd9Sstevel@tonic-gate static int 14997c478bd9Sstevel@tonic-gate zonecfg_delete_filesystem_core(zone_dochandle_t handle, 15007c478bd9Sstevel@tonic-gate struct zone_fstab *tabptr) 15017c478bd9Sstevel@tonic-gate { 15027c478bd9Sstevel@tonic-gate xmlNodePtr cur = handle->zone_dh_cur; 15037c478bd9Sstevel@tonic-gate boolean_t dir_match, spec_match, raw_match, type_match; 15047c478bd9Sstevel@tonic-gate 15057c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 15067c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_FS)) 15077c478bd9Sstevel@tonic-gate continue; 15087c478bd9Sstevel@tonic-gate dir_match = match_prop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir); 15097c478bd9Sstevel@tonic-gate spec_match = match_prop(cur, DTD_ATTR_SPECIAL, 15107c478bd9Sstevel@tonic-gate tabptr->zone_fs_special); 15117c478bd9Sstevel@tonic-gate raw_match = match_prop(cur, DTD_ATTR_RAW, 15127c478bd9Sstevel@tonic-gate tabptr->zone_fs_raw); 15137c478bd9Sstevel@tonic-gate type_match = match_prop(cur, DTD_ATTR_TYPE, 15147c478bd9Sstevel@tonic-gate tabptr->zone_fs_type); 15157c478bd9Sstevel@tonic-gate if (dir_match && spec_match && raw_match && type_match) { 15167c478bd9Sstevel@tonic-gate xmlUnlinkNode(cur); 15177c478bd9Sstevel@tonic-gate xmlFreeNode(cur); 15187c478bd9Sstevel@tonic-gate return (Z_OK); 15197c478bd9Sstevel@tonic-gate } 15207c478bd9Sstevel@tonic-gate } 15217c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 15227c478bd9Sstevel@tonic-gate } 15237c478bd9Sstevel@tonic-gate 15247c478bd9Sstevel@tonic-gate int 15257c478bd9Sstevel@tonic-gate zonecfg_delete_filesystem(zone_dochandle_t handle, struct zone_fstab *tabptr) 15267c478bd9Sstevel@tonic-gate { 15277c478bd9Sstevel@tonic-gate int err; 15287c478bd9Sstevel@tonic-gate 15297c478bd9Sstevel@tonic-gate if (tabptr == NULL) 15307c478bd9Sstevel@tonic-gate return (Z_INVAL); 15317c478bd9Sstevel@tonic-gate 15327c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 15337c478bd9Sstevel@tonic-gate return (err); 15347c478bd9Sstevel@tonic-gate 15357c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_filesystem_core(handle, tabptr)) != Z_OK) 15367c478bd9Sstevel@tonic-gate return (err); 15377c478bd9Sstevel@tonic-gate 15387c478bd9Sstevel@tonic-gate return (Z_OK); 15397c478bd9Sstevel@tonic-gate } 15407c478bd9Sstevel@tonic-gate 15417c478bd9Sstevel@tonic-gate int 15427c478bd9Sstevel@tonic-gate zonecfg_modify_filesystem( 15437c478bd9Sstevel@tonic-gate zone_dochandle_t handle, 15447c478bd9Sstevel@tonic-gate struct zone_fstab *oldtabptr, 15457c478bd9Sstevel@tonic-gate struct zone_fstab *newtabptr) 15467c478bd9Sstevel@tonic-gate { 15477c478bd9Sstevel@tonic-gate int err; 15487c478bd9Sstevel@tonic-gate 15497c478bd9Sstevel@tonic-gate if (oldtabptr == NULL || newtabptr == NULL) 15507c478bd9Sstevel@tonic-gate return (Z_INVAL); 15517c478bd9Sstevel@tonic-gate 15527c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 15537c478bd9Sstevel@tonic-gate return (err); 15547c478bd9Sstevel@tonic-gate 15557c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_filesystem_core(handle, oldtabptr)) != Z_OK) 15567c478bd9Sstevel@tonic-gate return (err); 15577c478bd9Sstevel@tonic-gate 15587c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_filesystem_core(handle, newtabptr)) != Z_OK) 15597c478bd9Sstevel@tonic-gate return (err); 15607c478bd9Sstevel@tonic-gate 15617c478bd9Sstevel@tonic-gate return (Z_OK); 15627c478bd9Sstevel@tonic-gate } 15637c478bd9Sstevel@tonic-gate 15647c478bd9Sstevel@tonic-gate static int 15657c478bd9Sstevel@tonic-gate zonecfg_delete_ipd_core(zone_dochandle_t handle, struct zone_fstab *tabptr) 15667c478bd9Sstevel@tonic-gate { 15677c478bd9Sstevel@tonic-gate xmlNodePtr cur = handle->zone_dh_cur; 15687c478bd9Sstevel@tonic-gate 15697c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 15707c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_IPD)) 15717c478bd9Sstevel@tonic-gate continue; 15727c478bd9Sstevel@tonic-gate if (match_prop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir)) { 15737c478bd9Sstevel@tonic-gate xmlUnlinkNode(cur); 15747c478bd9Sstevel@tonic-gate xmlFreeNode(cur); 15757c478bd9Sstevel@tonic-gate return (Z_OK); 15767c478bd9Sstevel@tonic-gate } 15777c478bd9Sstevel@tonic-gate } 15787c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 15797c478bd9Sstevel@tonic-gate } 15807c478bd9Sstevel@tonic-gate 15817c478bd9Sstevel@tonic-gate int 15827c478bd9Sstevel@tonic-gate zonecfg_delete_ipd(zone_dochandle_t handle, struct zone_fstab *tabptr) 15837c478bd9Sstevel@tonic-gate { 15847c478bd9Sstevel@tonic-gate int err; 15857c478bd9Sstevel@tonic-gate 15867c478bd9Sstevel@tonic-gate if (tabptr == NULL) 15877c478bd9Sstevel@tonic-gate return (Z_INVAL); 15887c478bd9Sstevel@tonic-gate 15897c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 15907c478bd9Sstevel@tonic-gate return (err); 15917c478bd9Sstevel@tonic-gate 15927c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_ipd_core(handle, tabptr)) != Z_OK) 15937c478bd9Sstevel@tonic-gate return (err); 15947c478bd9Sstevel@tonic-gate 15957c478bd9Sstevel@tonic-gate return (Z_OK); 15967c478bd9Sstevel@tonic-gate } 15977c478bd9Sstevel@tonic-gate 15987c478bd9Sstevel@tonic-gate int 15997c478bd9Sstevel@tonic-gate zonecfg_modify_ipd(zone_dochandle_t handle, struct zone_fstab *oldtabptr, 16007c478bd9Sstevel@tonic-gate struct zone_fstab *newtabptr) 16017c478bd9Sstevel@tonic-gate { 16027c478bd9Sstevel@tonic-gate int err; 16037c478bd9Sstevel@tonic-gate 16047c478bd9Sstevel@tonic-gate if (oldtabptr == NULL || newtabptr == NULL) 16057c478bd9Sstevel@tonic-gate return (Z_INVAL); 16067c478bd9Sstevel@tonic-gate 16077c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 16087c478bd9Sstevel@tonic-gate return (err); 16097c478bd9Sstevel@tonic-gate 16107c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_ipd_core(handle, oldtabptr)) != Z_OK) 16117c478bd9Sstevel@tonic-gate return (err); 16127c478bd9Sstevel@tonic-gate 16137c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_ipd_core(handle, newtabptr)) != Z_OK) 16147c478bd9Sstevel@tonic-gate return (err); 16157c478bd9Sstevel@tonic-gate 16167c478bd9Sstevel@tonic-gate return (Z_OK); 16177c478bd9Sstevel@tonic-gate } 16187c478bd9Sstevel@tonic-gate 16197c478bd9Sstevel@tonic-gate int 16207c478bd9Sstevel@tonic-gate zonecfg_lookup_filesystem( 16217c478bd9Sstevel@tonic-gate zone_dochandle_t handle, 16227c478bd9Sstevel@tonic-gate struct zone_fstab *tabptr) 16237c478bd9Sstevel@tonic-gate { 16247c478bd9Sstevel@tonic-gate xmlNodePtr cur, options, firstmatch; 16257c478bd9Sstevel@tonic-gate int err; 16267c478bd9Sstevel@tonic-gate char dirname[MAXPATHLEN], special[MAXPATHLEN], raw[MAXPATHLEN]; 16277c478bd9Sstevel@tonic-gate char type[FSTYPSZ]; 16287c478bd9Sstevel@tonic-gate char options_str[MAX_MNTOPT_STR]; 16297c478bd9Sstevel@tonic-gate 16307c478bd9Sstevel@tonic-gate if (tabptr == NULL) 16317c478bd9Sstevel@tonic-gate return (Z_INVAL); 16327c478bd9Sstevel@tonic-gate 16337c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 16347c478bd9Sstevel@tonic-gate return (err); 16357c478bd9Sstevel@tonic-gate 16367c478bd9Sstevel@tonic-gate /* 16377c478bd9Sstevel@tonic-gate * Walk the list of children looking for matches on any properties 16387c478bd9Sstevel@tonic-gate * specified in the fstab parameter. If more than one resource 16397c478bd9Sstevel@tonic-gate * matches, we return Z_INSUFFICIENT_SPEC; if none match, we return 16407c478bd9Sstevel@tonic-gate * Z_NO_RESOURCE_ID. 16417c478bd9Sstevel@tonic-gate */ 16427c478bd9Sstevel@tonic-gate cur = handle->zone_dh_cur; 16437c478bd9Sstevel@tonic-gate firstmatch = NULL; 16447c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 16457c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_FS)) 16467c478bd9Sstevel@tonic-gate continue; 16477c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_fs_dir) > 0) { 16487c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_DIR, dirname, 16497c478bd9Sstevel@tonic-gate sizeof (dirname)) == Z_OK) && 16507c478bd9Sstevel@tonic-gate (strcmp(tabptr->zone_fs_dir, dirname) == 0)) { 16517c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 16527c478bd9Sstevel@tonic-gate firstmatch = cur; 16537c478bd9Sstevel@tonic-gate else 16547c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 16557c478bd9Sstevel@tonic-gate } 16567c478bd9Sstevel@tonic-gate } 16577c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_fs_special) > 0) { 16587c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_SPECIAL, special, 16597c478bd9Sstevel@tonic-gate sizeof (special)) == Z_OK)) { 16607c478bd9Sstevel@tonic-gate if (strcmp(tabptr->zone_fs_special, 16617c478bd9Sstevel@tonic-gate special) == 0) { 16627c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 16637c478bd9Sstevel@tonic-gate firstmatch = cur; 16647c478bd9Sstevel@tonic-gate else if (firstmatch != cur) 16657c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 16667c478bd9Sstevel@tonic-gate } else { 16677c478bd9Sstevel@tonic-gate /* 16687c478bd9Sstevel@tonic-gate * If another property matched but this 16697c478bd9Sstevel@tonic-gate * one doesn't then reset firstmatch. 16707c478bd9Sstevel@tonic-gate */ 16717c478bd9Sstevel@tonic-gate if (firstmatch == cur) 16727c478bd9Sstevel@tonic-gate firstmatch = NULL; 16737c478bd9Sstevel@tonic-gate } 16747c478bd9Sstevel@tonic-gate } 16757c478bd9Sstevel@tonic-gate } 16767c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_fs_raw) > 0) { 16777c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_RAW, raw, 16787c478bd9Sstevel@tonic-gate sizeof (raw)) == Z_OK)) { 16797c478bd9Sstevel@tonic-gate if (strcmp(tabptr->zone_fs_raw, raw) == 0) { 16807c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 16817c478bd9Sstevel@tonic-gate firstmatch = cur; 16827c478bd9Sstevel@tonic-gate else if (firstmatch != cur) 16837c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 16847c478bd9Sstevel@tonic-gate } else { 16857c478bd9Sstevel@tonic-gate /* 16867c478bd9Sstevel@tonic-gate * If another property matched but this 16877c478bd9Sstevel@tonic-gate * one doesn't then reset firstmatch. 16887c478bd9Sstevel@tonic-gate */ 16897c478bd9Sstevel@tonic-gate if (firstmatch == cur) 16907c478bd9Sstevel@tonic-gate firstmatch = NULL; 16917c478bd9Sstevel@tonic-gate } 16927c478bd9Sstevel@tonic-gate } 16937c478bd9Sstevel@tonic-gate } 16947c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_fs_type) > 0) { 16957c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_TYPE, type, 16967c478bd9Sstevel@tonic-gate sizeof (type)) == Z_OK)) { 16977c478bd9Sstevel@tonic-gate if (strcmp(tabptr->zone_fs_type, type) == 0) { 16987c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 16997c478bd9Sstevel@tonic-gate firstmatch = cur; 17007c478bd9Sstevel@tonic-gate else if (firstmatch != cur) 17017c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 17027c478bd9Sstevel@tonic-gate } else { 17037c478bd9Sstevel@tonic-gate /* 17047c478bd9Sstevel@tonic-gate * If another property matched but this 17057c478bd9Sstevel@tonic-gate * one doesn't then reset firstmatch. 17067c478bd9Sstevel@tonic-gate */ 17077c478bd9Sstevel@tonic-gate if (firstmatch == cur) 17087c478bd9Sstevel@tonic-gate firstmatch = NULL; 17097c478bd9Sstevel@tonic-gate } 17107c478bd9Sstevel@tonic-gate } 17117c478bd9Sstevel@tonic-gate } 17127c478bd9Sstevel@tonic-gate } 17137c478bd9Sstevel@tonic-gate 17147c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 17157c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 17167c478bd9Sstevel@tonic-gate 17177c478bd9Sstevel@tonic-gate cur = firstmatch; 17187c478bd9Sstevel@tonic-gate 17197c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir, 17207c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_dir))) != Z_OK) 17217c478bd9Sstevel@tonic-gate return (err); 17227c478bd9Sstevel@tonic-gate 17237c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_SPECIAL, tabptr->zone_fs_special, 17247c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_special))) != Z_OK) 17257c478bd9Sstevel@tonic-gate return (err); 17267c478bd9Sstevel@tonic-gate 17277c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_RAW, tabptr->zone_fs_raw, 17287c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_raw))) != Z_OK) 17297c478bd9Sstevel@tonic-gate return (err); 17307c478bd9Sstevel@tonic-gate 17317c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_TYPE, tabptr->zone_fs_type, 17327c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_type))) != Z_OK) 17337c478bd9Sstevel@tonic-gate return (err); 17347c478bd9Sstevel@tonic-gate 17357c478bd9Sstevel@tonic-gate /* options are optional */ 17367c478bd9Sstevel@tonic-gate tabptr->zone_fs_options = NULL; 17377c478bd9Sstevel@tonic-gate for (options = cur->xmlChildrenNode; options != NULL; 17387c478bd9Sstevel@tonic-gate options = options->next) { 17397c478bd9Sstevel@tonic-gate if ((fetchprop(options, DTD_ATTR_NAME, options_str, 17407c478bd9Sstevel@tonic-gate sizeof (options_str)) != Z_OK)) 17417c478bd9Sstevel@tonic-gate break; 17427c478bd9Sstevel@tonic-gate if (zonecfg_add_fs_option(tabptr, options_str) != Z_OK) 17437c478bd9Sstevel@tonic-gate break; 17447c478bd9Sstevel@tonic-gate } 17457c478bd9Sstevel@tonic-gate return (Z_OK); 17467c478bd9Sstevel@tonic-gate } 17477c478bd9Sstevel@tonic-gate 17487c478bd9Sstevel@tonic-gate int 17497c478bd9Sstevel@tonic-gate zonecfg_lookup_ipd(zone_dochandle_t handle, struct zone_fstab *tabptr) 17507c478bd9Sstevel@tonic-gate { 17517c478bd9Sstevel@tonic-gate xmlNodePtr cur, match; 17527c478bd9Sstevel@tonic-gate int err; 17537c478bd9Sstevel@tonic-gate char dirname[MAXPATHLEN]; 17547c478bd9Sstevel@tonic-gate 17557c478bd9Sstevel@tonic-gate if (tabptr == NULL) 17567c478bd9Sstevel@tonic-gate return (Z_INVAL); 17577c478bd9Sstevel@tonic-gate 17587c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 17597c478bd9Sstevel@tonic-gate return (err); 17607c478bd9Sstevel@tonic-gate 17617c478bd9Sstevel@tonic-gate /* 17627c478bd9Sstevel@tonic-gate * General algorithm: 17637c478bd9Sstevel@tonic-gate * Walk the list of children looking for matches on any properties 17647c478bd9Sstevel@tonic-gate * specified in the fstab parameter. If more than one resource 17657c478bd9Sstevel@tonic-gate * matches, we return Z_INSUFFICIENT_SPEC; if none match, we return 17667c478bd9Sstevel@tonic-gate * Z_NO_RESOURCE_ID. 17677c478bd9Sstevel@tonic-gate */ 17687c478bd9Sstevel@tonic-gate cur = handle->zone_dh_cur; 17697c478bd9Sstevel@tonic-gate match = NULL; 17707c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 17717c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_IPD)) 17727c478bd9Sstevel@tonic-gate continue; 17737c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_fs_dir) > 0) { 17747c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_DIR, dirname, 17757c478bd9Sstevel@tonic-gate sizeof (dirname)) == Z_OK) && 17767c478bd9Sstevel@tonic-gate (strcmp(tabptr->zone_fs_dir, dirname) == 0)) { 17777c478bd9Sstevel@tonic-gate if (match == NULL) 17787c478bd9Sstevel@tonic-gate match = cur; 17797c478bd9Sstevel@tonic-gate else 17807c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 17817c478bd9Sstevel@tonic-gate } 17827c478bd9Sstevel@tonic-gate } 17837c478bd9Sstevel@tonic-gate } 17847c478bd9Sstevel@tonic-gate 17857c478bd9Sstevel@tonic-gate if (match == NULL) 17867c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 17877c478bd9Sstevel@tonic-gate 17887c478bd9Sstevel@tonic-gate cur = match; 17897c478bd9Sstevel@tonic-gate 17907c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir, 17917c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_dir))) != Z_OK) 17927c478bd9Sstevel@tonic-gate return (err); 17937c478bd9Sstevel@tonic-gate 17947c478bd9Sstevel@tonic-gate return (Z_OK); 17957c478bd9Sstevel@tonic-gate } 17967c478bd9Sstevel@tonic-gate 17977c478bd9Sstevel@tonic-gate /* 17987c478bd9Sstevel@tonic-gate * Compare two IP addresses in string form. Allow for the possibility that 17997c478bd9Sstevel@tonic-gate * one might have "/<prefix-length>" at the end: allow a match on just the 18007c478bd9Sstevel@tonic-gate * IP address (or host name) part. 18017c478bd9Sstevel@tonic-gate */ 18027c478bd9Sstevel@tonic-gate 18037c478bd9Sstevel@tonic-gate boolean_t 18047c478bd9Sstevel@tonic-gate zonecfg_same_net_address(char *a1, char *a2) 18057c478bd9Sstevel@tonic-gate { 18067c478bd9Sstevel@tonic-gate char *slashp, *slashp1, *slashp2; 18077c478bd9Sstevel@tonic-gate int result; 18087c478bd9Sstevel@tonic-gate 18097c478bd9Sstevel@tonic-gate if (strcmp(a1, a2) == 0) 18107c478bd9Sstevel@tonic-gate return (B_TRUE); 18117c478bd9Sstevel@tonic-gate 18127c478bd9Sstevel@tonic-gate /* 18137c478bd9Sstevel@tonic-gate * If neither has a slash or both do, they need to match to be 18147c478bd9Sstevel@tonic-gate * considered the same, but they did not match above, so fail. 18157c478bd9Sstevel@tonic-gate */ 18167c478bd9Sstevel@tonic-gate slashp1 = strchr(a1, '/'); 18177c478bd9Sstevel@tonic-gate slashp2 = strchr(a2, '/'); 18187c478bd9Sstevel@tonic-gate if ((slashp1 == NULL && slashp2 == NULL) || 18197c478bd9Sstevel@tonic-gate (slashp1 != NULL && slashp2 != NULL)) 18207c478bd9Sstevel@tonic-gate return (B_FALSE); 18217c478bd9Sstevel@tonic-gate 18227c478bd9Sstevel@tonic-gate /* 18237c478bd9Sstevel@tonic-gate * Only one had a slash: pick that one, zero out the slash, compare 18247c478bd9Sstevel@tonic-gate * the "address only" strings, restore the slash, and return the 18257c478bd9Sstevel@tonic-gate * result of the comparison. 18267c478bd9Sstevel@tonic-gate */ 18277c478bd9Sstevel@tonic-gate slashp = (slashp1 == NULL) ? slashp2 : slashp1; 18287c478bd9Sstevel@tonic-gate *slashp = '\0'; 18297c478bd9Sstevel@tonic-gate result = strcmp(a1, a2); 18307c478bd9Sstevel@tonic-gate *slashp = '/'; 18317c478bd9Sstevel@tonic-gate return ((result == 0)); 18327c478bd9Sstevel@tonic-gate } 18337c478bd9Sstevel@tonic-gate 18347c478bd9Sstevel@tonic-gate int 18357c478bd9Sstevel@tonic-gate zonecfg_valid_net_address(char *address, struct lifreq *lifr) 18367c478bd9Sstevel@tonic-gate { 18377c478bd9Sstevel@tonic-gate struct sockaddr_in *sin4; 18387c478bd9Sstevel@tonic-gate struct sockaddr_in6 *sin6; 18397c478bd9Sstevel@tonic-gate struct addrinfo hints, *result; 18407c478bd9Sstevel@tonic-gate char *slashp = strchr(address, '/'); 18417c478bd9Sstevel@tonic-gate 18427c478bd9Sstevel@tonic-gate bzero(lifr, sizeof (struct lifreq)); 18437c478bd9Sstevel@tonic-gate sin4 = (struct sockaddr_in *)&lifr->lifr_addr; 18447c478bd9Sstevel@tonic-gate sin6 = (struct sockaddr_in6 *)&lifr->lifr_addr; 18457c478bd9Sstevel@tonic-gate if (slashp != NULL) 18467c478bd9Sstevel@tonic-gate *slashp = '\0'; 18477c478bd9Sstevel@tonic-gate if (inet_pton(AF_INET, address, &sin4->sin_addr) == 1) { 18487c478bd9Sstevel@tonic-gate sin4->sin_family = AF_INET; 18497c478bd9Sstevel@tonic-gate } else if (inet_pton(AF_INET6, address, &sin6->sin6_addr) == 1) { 18507c478bd9Sstevel@tonic-gate if (slashp == NULL) 18517c478bd9Sstevel@tonic-gate return (Z_IPV6_ADDR_PREFIX_LEN); 18527c478bd9Sstevel@tonic-gate sin6->sin6_family = AF_INET6; 18537c478bd9Sstevel@tonic-gate } else { 18547c478bd9Sstevel@tonic-gate /* "address" may be a host name */ 18557c478bd9Sstevel@tonic-gate (void) memset(&hints, 0, sizeof (hints)); 18567c478bd9Sstevel@tonic-gate hints.ai_family = PF_INET; 18577c478bd9Sstevel@tonic-gate if (getaddrinfo(address, NULL, &hints, &result) != 0) 18587c478bd9Sstevel@tonic-gate return (Z_BOGUS_ADDRESS); 18597c478bd9Sstevel@tonic-gate sin4->sin_family = result->ai_family; 1860a1be23daSdp 18617c478bd9Sstevel@tonic-gate (void) memcpy(&sin4->sin_addr, 18627c478bd9Sstevel@tonic-gate /* LINTED E_BAD_PTR_CAST_ALIGN */ 18637c478bd9Sstevel@tonic-gate &((struct sockaddr_in *)result->ai_addr)->sin_addr, 18647c478bd9Sstevel@tonic-gate sizeof (struct in_addr)); 1865a1be23daSdp 18667c478bd9Sstevel@tonic-gate freeaddrinfo(result); 18677c478bd9Sstevel@tonic-gate } 18687c478bd9Sstevel@tonic-gate return (Z_OK); 18697c478bd9Sstevel@tonic-gate } 18707c478bd9Sstevel@tonic-gate 18717c478bd9Sstevel@tonic-gate int 18727c478bd9Sstevel@tonic-gate zonecfg_lookup_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr) 18737c478bd9Sstevel@tonic-gate { 18747c478bd9Sstevel@tonic-gate xmlNodePtr cur, firstmatch; 18757c478bd9Sstevel@tonic-gate int err; 18767c478bd9Sstevel@tonic-gate char address[INET6_ADDRSTRLEN], physical[LIFNAMSIZ]; 18777c478bd9Sstevel@tonic-gate 18787c478bd9Sstevel@tonic-gate if (tabptr == NULL) 18797c478bd9Sstevel@tonic-gate return (Z_INVAL); 18807c478bd9Sstevel@tonic-gate 18817c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 18827c478bd9Sstevel@tonic-gate return (err); 18837c478bd9Sstevel@tonic-gate 18847c478bd9Sstevel@tonic-gate cur = handle->zone_dh_cur; 18857c478bd9Sstevel@tonic-gate firstmatch = NULL; 18867c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 18877c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_NET)) 18887c478bd9Sstevel@tonic-gate continue; 18897c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_nwif_physical) > 0) { 18907c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_PHYSICAL, physical, 18917c478bd9Sstevel@tonic-gate sizeof (physical)) == Z_OK) && 18927c478bd9Sstevel@tonic-gate (strcmp(tabptr->zone_nwif_physical, 18937c478bd9Sstevel@tonic-gate physical) == 0)) { 18947c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 18957c478bd9Sstevel@tonic-gate firstmatch = cur; 18967c478bd9Sstevel@tonic-gate else 18977c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 18987c478bd9Sstevel@tonic-gate } 18997c478bd9Sstevel@tonic-gate } 19007c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_nwif_address) > 0) { 19017c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_ADDRESS, address, 19027c478bd9Sstevel@tonic-gate sizeof (address)) == Z_OK)) { 19037c478bd9Sstevel@tonic-gate if (zonecfg_same_net_address( 19047c478bd9Sstevel@tonic-gate tabptr->zone_nwif_address, address)) { 19057c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 19067c478bd9Sstevel@tonic-gate firstmatch = cur; 19077c478bd9Sstevel@tonic-gate else if (firstmatch != cur) 19087c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 19097c478bd9Sstevel@tonic-gate } else { 19107c478bd9Sstevel@tonic-gate /* 19117c478bd9Sstevel@tonic-gate * If another property matched but this 19127c478bd9Sstevel@tonic-gate * one doesn't then reset firstmatch. 19137c478bd9Sstevel@tonic-gate */ 19147c478bd9Sstevel@tonic-gate if (firstmatch == cur) 19157c478bd9Sstevel@tonic-gate firstmatch = NULL; 19167c478bd9Sstevel@tonic-gate } 19177c478bd9Sstevel@tonic-gate } 19187c478bd9Sstevel@tonic-gate } 19197c478bd9Sstevel@tonic-gate } 19207c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 19217c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 19227c478bd9Sstevel@tonic-gate 19237c478bd9Sstevel@tonic-gate cur = firstmatch; 19247c478bd9Sstevel@tonic-gate 19257c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_PHYSICAL, tabptr->zone_nwif_physical, 19267c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_nwif_physical))) != Z_OK) 19277c478bd9Sstevel@tonic-gate return (err); 19287c478bd9Sstevel@tonic-gate 19297c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_ADDRESS, tabptr->zone_nwif_address, 19307c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_nwif_address))) != Z_OK) 19317c478bd9Sstevel@tonic-gate return (err); 19327c478bd9Sstevel@tonic-gate 19337c478bd9Sstevel@tonic-gate return (Z_OK); 19347c478bd9Sstevel@tonic-gate } 19357c478bd9Sstevel@tonic-gate 19367c478bd9Sstevel@tonic-gate static int 19377c478bd9Sstevel@tonic-gate zonecfg_add_nwif_core(zone_dochandle_t handle, struct zone_nwiftab *tabptr) 19387c478bd9Sstevel@tonic-gate { 19397c478bd9Sstevel@tonic-gate xmlNodePtr newnode, cur = handle->zone_dh_cur; 19407c478bd9Sstevel@tonic-gate int err; 19417c478bd9Sstevel@tonic-gate 19427c478bd9Sstevel@tonic-gate newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_NET, NULL); 1943a1be23daSdp if ((err = newprop(newnode, DTD_ATTR_ADDRESS, 19447c478bd9Sstevel@tonic-gate tabptr->zone_nwif_address)) != Z_OK) 19457c478bd9Sstevel@tonic-gate return (err); 1946a1be23daSdp if ((err = newprop(newnode, DTD_ATTR_PHYSICAL, 19477c478bd9Sstevel@tonic-gate tabptr->zone_nwif_physical)) != Z_OK) 19487c478bd9Sstevel@tonic-gate return (err); 19497c478bd9Sstevel@tonic-gate return (Z_OK); 19507c478bd9Sstevel@tonic-gate } 19517c478bd9Sstevel@tonic-gate 19527c478bd9Sstevel@tonic-gate int 19537c478bd9Sstevel@tonic-gate zonecfg_add_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr) 19547c478bd9Sstevel@tonic-gate { 19557c478bd9Sstevel@tonic-gate int err; 19567c478bd9Sstevel@tonic-gate 19577c478bd9Sstevel@tonic-gate if (tabptr == NULL) 19587c478bd9Sstevel@tonic-gate return (Z_INVAL); 19597c478bd9Sstevel@tonic-gate 19607c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 19617c478bd9Sstevel@tonic-gate return (err); 19627c478bd9Sstevel@tonic-gate 19637c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_nwif_core(handle, tabptr)) != Z_OK) 19647c478bd9Sstevel@tonic-gate return (err); 19657c478bd9Sstevel@tonic-gate 19667c478bd9Sstevel@tonic-gate return (Z_OK); 19677c478bd9Sstevel@tonic-gate } 19687c478bd9Sstevel@tonic-gate 19697c478bd9Sstevel@tonic-gate static int 19707c478bd9Sstevel@tonic-gate zonecfg_delete_nwif_core(zone_dochandle_t handle, struct zone_nwiftab *tabptr) 19717c478bd9Sstevel@tonic-gate { 19727c478bd9Sstevel@tonic-gate xmlNodePtr cur = handle->zone_dh_cur; 19737c478bd9Sstevel@tonic-gate boolean_t addr_match, phys_match; 19747c478bd9Sstevel@tonic-gate 19757c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 19767c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_NET)) 19777c478bd9Sstevel@tonic-gate continue; 19787c478bd9Sstevel@tonic-gate 19797c478bd9Sstevel@tonic-gate addr_match = match_prop(cur, DTD_ATTR_ADDRESS, 19807c478bd9Sstevel@tonic-gate tabptr->zone_nwif_address); 19817c478bd9Sstevel@tonic-gate phys_match = match_prop(cur, DTD_ATTR_PHYSICAL, 19827c478bd9Sstevel@tonic-gate tabptr->zone_nwif_physical); 19837c478bd9Sstevel@tonic-gate 19847c478bd9Sstevel@tonic-gate if (addr_match && phys_match) { 19857c478bd9Sstevel@tonic-gate xmlUnlinkNode(cur); 19867c478bd9Sstevel@tonic-gate xmlFreeNode(cur); 19877c478bd9Sstevel@tonic-gate return (Z_OK); 19887c478bd9Sstevel@tonic-gate } 19897c478bd9Sstevel@tonic-gate } 19907c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 19917c478bd9Sstevel@tonic-gate } 19927c478bd9Sstevel@tonic-gate 19937c478bd9Sstevel@tonic-gate int 19947c478bd9Sstevel@tonic-gate zonecfg_delete_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr) 19957c478bd9Sstevel@tonic-gate { 19967c478bd9Sstevel@tonic-gate int err; 19977c478bd9Sstevel@tonic-gate 19987c478bd9Sstevel@tonic-gate if (tabptr == NULL) 19997c478bd9Sstevel@tonic-gate return (Z_INVAL); 20007c478bd9Sstevel@tonic-gate 20017c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 20027c478bd9Sstevel@tonic-gate return (err); 20037c478bd9Sstevel@tonic-gate 20047c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_nwif_core(handle, tabptr)) != Z_OK) 20057c478bd9Sstevel@tonic-gate return (err); 20067c478bd9Sstevel@tonic-gate 20077c478bd9Sstevel@tonic-gate return (Z_OK); 20087c478bd9Sstevel@tonic-gate } 20097c478bd9Sstevel@tonic-gate 20107c478bd9Sstevel@tonic-gate int 20117c478bd9Sstevel@tonic-gate zonecfg_modify_nwif( 20127c478bd9Sstevel@tonic-gate zone_dochandle_t handle, 20137c478bd9Sstevel@tonic-gate struct zone_nwiftab *oldtabptr, 20147c478bd9Sstevel@tonic-gate struct zone_nwiftab *newtabptr) 20157c478bd9Sstevel@tonic-gate { 20167c478bd9Sstevel@tonic-gate int err; 20177c478bd9Sstevel@tonic-gate 20187c478bd9Sstevel@tonic-gate if (oldtabptr == NULL || newtabptr == NULL) 20197c478bd9Sstevel@tonic-gate return (Z_INVAL); 20207c478bd9Sstevel@tonic-gate 20217c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 20227c478bd9Sstevel@tonic-gate return (err); 20237c478bd9Sstevel@tonic-gate 20247c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_nwif_core(handle, oldtabptr)) != Z_OK) 20257c478bd9Sstevel@tonic-gate return (err); 20267c478bd9Sstevel@tonic-gate 20277c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_nwif_core(handle, newtabptr)) != Z_OK) 20287c478bd9Sstevel@tonic-gate return (err); 20297c478bd9Sstevel@tonic-gate 20307c478bd9Sstevel@tonic-gate return (Z_OK); 20317c478bd9Sstevel@tonic-gate } 20327c478bd9Sstevel@tonic-gate 20337c478bd9Sstevel@tonic-gate int 20347c478bd9Sstevel@tonic-gate zonecfg_lookup_dev(zone_dochandle_t handle, struct zone_devtab *tabptr) 20357c478bd9Sstevel@tonic-gate { 20367c478bd9Sstevel@tonic-gate xmlNodePtr cur, firstmatch; 20377c478bd9Sstevel@tonic-gate int err; 20387c478bd9Sstevel@tonic-gate char match[MAXPATHLEN]; 20397c478bd9Sstevel@tonic-gate 20407c478bd9Sstevel@tonic-gate if (tabptr == NULL) 20417c478bd9Sstevel@tonic-gate return (Z_INVAL); 20427c478bd9Sstevel@tonic-gate 20437c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 20447c478bd9Sstevel@tonic-gate return (err); 20457c478bd9Sstevel@tonic-gate 20467c478bd9Sstevel@tonic-gate cur = handle->zone_dh_cur; 20477c478bd9Sstevel@tonic-gate firstmatch = NULL; 20487c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 20497c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_DEVICE)) 20507c478bd9Sstevel@tonic-gate continue; 20517c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_dev_match) == 0) 20527c478bd9Sstevel@tonic-gate continue; 20537c478bd9Sstevel@tonic-gate 20547c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_MATCH, match, 20557c478bd9Sstevel@tonic-gate sizeof (match)) == Z_OK)) { 20567c478bd9Sstevel@tonic-gate if (strcmp(tabptr->zone_dev_match, 20577c478bd9Sstevel@tonic-gate match) == 0) { 20587c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 20597c478bd9Sstevel@tonic-gate firstmatch = cur; 20607c478bd9Sstevel@tonic-gate else if (firstmatch != cur) 20617c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 20627c478bd9Sstevel@tonic-gate } else { 20637c478bd9Sstevel@tonic-gate /* 20647c478bd9Sstevel@tonic-gate * If another property matched but this 20657c478bd9Sstevel@tonic-gate * one doesn't then reset firstmatch. 20667c478bd9Sstevel@tonic-gate */ 20677c478bd9Sstevel@tonic-gate if (firstmatch == cur) 20687c478bd9Sstevel@tonic-gate firstmatch = NULL; 20697c478bd9Sstevel@tonic-gate } 20707c478bd9Sstevel@tonic-gate } 20717c478bd9Sstevel@tonic-gate } 20727c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 20737c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 20747c478bd9Sstevel@tonic-gate 20757c478bd9Sstevel@tonic-gate cur = firstmatch; 20767c478bd9Sstevel@tonic-gate 20777c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_MATCH, tabptr->zone_dev_match, 20787c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_dev_match))) != Z_OK) 20797c478bd9Sstevel@tonic-gate return (err); 20807c478bd9Sstevel@tonic-gate 20817c478bd9Sstevel@tonic-gate return (Z_OK); 20827c478bd9Sstevel@tonic-gate } 20837c478bd9Sstevel@tonic-gate 20847c478bd9Sstevel@tonic-gate static int 20857c478bd9Sstevel@tonic-gate zonecfg_add_dev_core(zone_dochandle_t handle, struct zone_devtab *tabptr) 20867c478bd9Sstevel@tonic-gate { 20877c478bd9Sstevel@tonic-gate xmlNodePtr newnode, cur = handle->zone_dh_cur; 20887c478bd9Sstevel@tonic-gate int err; 20897c478bd9Sstevel@tonic-gate 20907c478bd9Sstevel@tonic-gate newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_DEVICE, NULL); 20917c478bd9Sstevel@tonic-gate 2092a1be23daSdp if ((err = newprop(newnode, DTD_ATTR_MATCH, 20937c478bd9Sstevel@tonic-gate tabptr->zone_dev_match)) != Z_OK) 20947c478bd9Sstevel@tonic-gate return (err); 20957c478bd9Sstevel@tonic-gate 20967c478bd9Sstevel@tonic-gate return (Z_OK); 20977c478bd9Sstevel@tonic-gate } 20987c478bd9Sstevel@tonic-gate 20997c478bd9Sstevel@tonic-gate int 21007c478bd9Sstevel@tonic-gate zonecfg_add_dev(zone_dochandle_t handle, struct zone_devtab *tabptr) 21017c478bd9Sstevel@tonic-gate { 21027c478bd9Sstevel@tonic-gate int err; 21037c478bd9Sstevel@tonic-gate 21047c478bd9Sstevel@tonic-gate if (tabptr == NULL) 21057c478bd9Sstevel@tonic-gate return (Z_INVAL); 21067c478bd9Sstevel@tonic-gate 21077c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 21087c478bd9Sstevel@tonic-gate return (err); 21097c478bd9Sstevel@tonic-gate 21107c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_dev_core(handle, tabptr)) != Z_OK) 21117c478bd9Sstevel@tonic-gate return (err); 21127c478bd9Sstevel@tonic-gate 21137c478bd9Sstevel@tonic-gate return (Z_OK); 21147c478bd9Sstevel@tonic-gate } 21157c478bd9Sstevel@tonic-gate 21167c478bd9Sstevel@tonic-gate static int 21177c478bd9Sstevel@tonic-gate zonecfg_delete_dev_core(zone_dochandle_t handle, struct zone_devtab *tabptr) 21187c478bd9Sstevel@tonic-gate { 21197c478bd9Sstevel@tonic-gate xmlNodePtr cur = handle->zone_dh_cur; 21207c478bd9Sstevel@tonic-gate int match_match; 21217c478bd9Sstevel@tonic-gate 21227c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 21237c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_DEVICE)) 21247c478bd9Sstevel@tonic-gate continue; 21257c478bd9Sstevel@tonic-gate 21267c478bd9Sstevel@tonic-gate match_match = match_prop(cur, DTD_ATTR_MATCH, 21277c478bd9Sstevel@tonic-gate tabptr->zone_dev_match); 21287c478bd9Sstevel@tonic-gate 21297c478bd9Sstevel@tonic-gate if (match_match) { 21307c478bd9Sstevel@tonic-gate xmlUnlinkNode(cur); 21317c478bd9Sstevel@tonic-gate xmlFreeNode(cur); 21327c478bd9Sstevel@tonic-gate return (Z_OK); 21337c478bd9Sstevel@tonic-gate } 21347c478bd9Sstevel@tonic-gate } 21357c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 21367c478bd9Sstevel@tonic-gate } 21377c478bd9Sstevel@tonic-gate 21387c478bd9Sstevel@tonic-gate int 21397c478bd9Sstevel@tonic-gate zonecfg_delete_dev(zone_dochandle_t handle, struct zone_devtab *tabptr) 21407c478bd9Sstevel@tonic-gate { 21417c478bd9Sstevel@tonic-gate int err; 21427c478bd9Sstevel@tonic-gate 21437c478bd9Sstevel@tonic-gate if (tabptr == NULL) 21447c478bd9Sstevel@tonic-gate return (Z_INVAL); 21457c478bd9Sstevel@tonic-gate 21467c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 21477c478bd9Sstevel@tonic-gate return (err); 21487c478bd9Sstevel@tonic-gate 21497c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_dev_core(handle, tabptr)) != Z_OK) 21507c478bd9Sstevel@tonic-gate return (err); 21517c478bd9Sstevel@tonic-gate 21527c478bd9Sstevel@tonic-gate return (Z_OK); 21537c478bd9Sstevel@tonic-gate } 21547c478bd9Sstevel@tonic-gate 21557c478bd9Sstevel@tonic-gate int 21567c478bd9Sstevel@tonic-gate zonecfg_modify_dev( 21577c478bd9Sstevel@tonic-gate zone_dochandle_t handle, 21587c478bd9Sstevel@tonic-gate struct zone_devtab *oldtabptr, 21597c478bd9Sstevel@tonic-gate struct zone_devtab *newtabptr) 21607c478bd9Sstevel@tonic-gate { 21617c478bd9Sstevel@tonic-gate int err; 21627c478bd9Sstevel@tonic-gate 21637c478bd9Sstevel@tonic-gate if (oldtabptr == NULL || newtabptr == NULL) 21647c478bd9Sstevel@tonic-gate return (Z_INVAL); 21657c478bd9Sstevel@tonic-gate 21667c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 21677c478bd9Sstevel@tonic-gate return (err); 21687c478bd9Sstevel@tonic-gate 21697c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_dev_core(handle, oldtabptr)) != Z_OK) 21707c478bd9Sstevel@tonic-gate return (err); 21717c478bd9Sstevel@tonic-gate 21727c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_dev_core(handle, newtabptr)) != Z_OK) 21737c478bd9Sstevel@tonic-gate return (err); 21747c478bd9Sstevel@tonic-gate 21757c478bd9Sstevel@tonic-gate return (Z_OK); 21767c478bd9Sstevel@tonic-gate } 21777c478bd9Sstevel@tonic-gate 2178ee519a1fSgjelinek /* Lock to serialize all zonecfg_devwalks */ 2179ee519a1fSgjelinek static pthread_mutex_t zonecfg_devwalk_lock = PTHREAD_MUTEX_INITIALIZER; 2180ee519a1fSgjelinek /* 2181ee519a1fSgjelinek * Global variables used to pass data from zonecfg_devwalk to the nftw 2182ee519a1fSgjelinek * call-back (zonecfg_devwalk_cb). g_devwalk_data is really the void* 2183ee519a1fSgjelinek * parameter and g_devwalk_cb is really the *cb parameter from zonecfg_devwalk. 2184ee519a1fSgjelinek */ 2185ee519a1fSgjelinek static void *g_devwalk_data; 2186ee519a1fSgjelinek static int (*g_devwalk_cb)(const char *, uid_t, gid_t, mode_t, const char *, 2187ee519a1fSgjelinek void *); 2188ee519a1fSgjelinek static size_t g_devwalk_skip_prefix; 2189ee519a1fSgjelinek 2190ee519a1fSgjelinek /* 2191ee519a1fSgjelinek * This is the nftw call-back function used by zonecfg_devwalk. It is 2192ee519a1fSgjelinek * responsible for calling the actual call-back that is passed in to 2193ee519a1fSgjelinek * zonecfg_devwalk as the *cb argument. 2194ee519a1fSgjelinek */ 2195ee519a1fSgjelinek /* ARGSUSED2 */ 2196ee519a1fSgjelinek static int 2197ee519a1fSgjelinek zonecfg_devwalk_cb(const char *path, const struct stat *st, int f, 2198ee519a1fSgjelinek struct FTW *ftw) 2199ee519a1fSgjelinek { 2200ee519a1fSgjelinek acl_t *acl; 2201ee519a1fSgjelinek char *acl_txt = NULL; 2202ee519a1fSgjelinek 2203ee519a1fSgjelinek /* skip all but character and block devices */ 2204ee519a1fSgjelinek if (!S_ISBLK(st->st_mode) && !S_ISCHR(st->st_mode)) 2205ee519a1fSgjelinek return (0); 2206ee519a1fSgjelinek 2207ee519a1fSgjelinek if ((acl_get(path, ACL_NO_TRIVIAL, &acl) == 0) && 2208ee519a1fSgjelinek acl != NULL) { 2209ee519a1fSgjelinek acl_txt = acl_totext(acl, ACL_NORESOLVE); 2210ee519a1fSgjelinek acl_free(acl); 2211ee519a1fSgjelinek } 2212ee519a1fSgjelinek 2213ee519a1fSgjelinek if (strlen(path) <= g_devwalk_skip_prefix) 2214ee519a1fSgjelinek return (0); 2215ee519a1fSgjelinek 2216ee519a1fSgjelinek g_devwalk_cb(path + g_devwalk_skip_prefix, st->st_uid, st->st_gid, 2217ee519a1fSgjelinek st->st_mode & S_IAMB, acl_txt != NULL ? acl_txt : "", 2218ee519a1fSgjelinek g_devwalk_data); 2219ee519a1fSgjelinek free(acl_txt); 2220ee519a1fSgjelinek return (0); 2221ee519a1fSgjelinek } 2222ee519a1fSgjelinek 2223ee519a1fSgjelinek /* 2224ee519a1fSgjelinek * Walk the dev tree for the zone specified by hdl and call the call-back (cb) 2225ee519a1fSgjelinek * function for each entry in the tree. The call-back will be passed the 2226ee519a1fSgjelinek * name, uid, gid, mode, acl string and the void *data input parameter 2227ee519a1fSgjelinek * for each dev entry. 2228ee519a1fSgjelinek * 2229ee519a1fSgjelinek * Data is passed to the zonecfg_devwalk_cb through the global variables 2230ee519a1fSgjelinek * g_devwalk_data, *g_devwalk_cb, and g_devwalk_skip_prefix. The 2231ee519a1fSgjelinek * zonecfg_devwalk_cb function will actually call *cb. 2232ee519a1fSgjelinek */ 2233ee519a1fSgjelinek int 2234ee519a1fSgjelinek zonecfg_devwalk(zone_dochandle_t hdl, 2235ee519a1fSgjelinek int (*cb)(const char *, uid_t, gid_t, mode_t, const char *, void *), 2236ee519a1fSgjelinek void *data) 2237ee519a1fSgjelinek { 2238ee519a1fSgjelinek char path[MAXPATHLEN]; 2239ee519a1fSgjelinek int ret; 2240ee519a1fSgjelinek 2241ee519a1fSgjelinek if ((ret = zonecfg_get_zonepath(hdl, path, sizeof (path))) != Z_OK) 2242ee519a1fSgjelinek return (ret); 2243ee519a1fSgjelinek 2244ee519a1fSgjelinek if (strlcat(path, "/dev", sizeof (path)) >= sizeof (path)) 2245ee519a1fSgjelinek return (Z_TOO_BIG); 2246ee519a1fSgjelinek g_devwalk_skip_prefix = strlen(path) + 1; 2247ee519a1fSgjelinek 2248ee519a1fSgjelinek /* 2249ee519a1fSgjelinek * We have to serialize all zonecfg_devwalks in the same process 2250ee519a1fSgjelinek * (which should be fine), since nftw() is so badly designed. 2251ee519a1fSgjelinek */ 2252ee519a1fSgjelinek (void) pthread_mutex_lock(&zonecfg_devwalk_lock); 2253ee519a1fSgjelinek 2254ee519a1fSgjelinek g_devwalk_data = data; 2255ee519a1fSgjelinek g_devwalk_cb = cb; 2256ee519a1fSgjelinek (void) nftw(path, zonecfg_devwalk_cb, 0, FTW_PHYS); 2257ee519a1fSgjelinek 2258ee519a1fSgjelinek (void) pthread_mutex_unlock(&zonecfg_devwalk_lock); 2259ee519a1fSgjelinek return (Z_OK); 2260ee519a1fSgjelinek } 2261ee519a1fSgjelinek 2262ee519a1fSgjelinek /* 2263ee519a1fSgjelinek * Update the owner, group, mode and acl on the specified dev (inpath) for 2264ee519a1fSgjelinek * the zone (hdl). This function can be used to fix up the dev tree after 2265ee519a1fSgjelinek * attaching a migrated zone. 2266ee519a1fSgjelinek */ 2267ee519a1fSgjelinek int 2268ee519a1fSgjelinek zonecfg_devperms_apply(zone_dochandle_t hdl, const char *inpath, uid_t owner, 2269ee519a1fSgjelinek gid_t group, mode_t mode, const char *acltxt) 2270ee519a1fSgjelinek { 2271ee519a1fSgjelinek int ret; 2272ee519a1fSgjelinek char path[MAXPATHLEN]; 2273ee519a1fSgjelinek struct stat st; 2274ee519a1fSgjelinek acl_t *aclp; 2275ee519a1fSgjelinek 2276ee519a1fSgjelinek if ((ret = zonecfg_get_zonepath(hdl, path, sizeof (path))) != Z_OK) 2277ee519a1fSgjelinek return (ret); 2278ee519a1fSgjelinek 2279ee519a1fSgjelinek if (strlcat(path, "/dev/", sizeof (path)) >= sizeof (path)) 2280ee519a1fSgjelinek return (Z_TOO_BIG); 2281ee519a1fSgjelinek if (strlcat(path, inpath, sizeof (path)) >= sizeof (path)) 2282ee519a1fSgjelinek return (Z_TOO_BIG); 2283ee519a1fSgjelinek 2284ee519a1fSgjelinek if (stat(path, &st) == -1) 2285ee519a1fSgjelinek return (Z_INVAL); 2286ee519a1fSgjelinek 2287ee519a1fSgjelinek /* make sure we're only touching device nodes */ 2288ee519a1fSgjelinek if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) 2289ee519a1fSgjelinek return (Z_INVAL); 2290ee519a1fSgjelinek 2291ee519a1fSgjelinek if (chown(path, owner, group) == -1) 2292ee519a1fSgjelinek return (Z_SYSTEM); 2293ee519a1fSgjelinek 2294ee519a1fSgjelinek if (chmod(path, mode) == -1) 2295ee519a1fSgjelinek return (Z_SYSTEM); 2296ee519a1fSgjelinek 2297ee519a1fSgjelinek if ((acltxt == NULL) || (strcmp(acltxt, "") == 0)) 2298ee519a1fSgjelinek return (Z_OK); 2299ee519a1fSgjelinek 2300ee519a1fSgjelinek if (acl_fromtext(acltxt, &aclp) != 0) 2301ee519a1fSgjelinek return (Z_SYSTEM); 2302ee519a1fSgjelinek 2303ee519a1fSgjelinek errno = 0; 2304ee519a1fSgjelinek if (acl_set(path, aclp) == -1) { 2305ee519a1fSgjelinek free(aclp); 2306ee519a1fSgjelinek return (Z_SYSTEM); 2307ee519a1fSgjelinek } 2308ee519a1fSgjelinek 2309ee519a1fSgjelinek free(aclp); 2310ee519a1fSgjelinek return (Z_OK); 2311ee519a1fSgjelinek } 2312ee519a1fSgjelinek 23137c478bd9Sstevel@tonic-gate /* 23147c478bd9Sstevel@tonic-gate * This is the set of devices which must be present in every zone. Users 23157c478bd9Sstevel@tonic-gate * can augment this list with additional device rules in their zone 23167c478bd9Sstevel@tonic-gate * configuration, but at present cannot remove any of the this set of 23177c478bd9Sstevel@tonic-gate * standard devices. All matching is done by /dev pathname (the "/dev" 23187c478bd9Sstevel@tonic-gate * part is implicit. Try to keep rules which match a large number of 23197c478bd9Sstevel@tonic-gate * devices (like the pts rule) first. 23207c478bd9Sstevel@tonic-gate */ 23217c478bd9Sstevel@tonic-gate static const char *standard_devs[] = { 23227c478bd9Sstevel@tonic-gate "pts/*", 23237c478bd9Sstevel@tonic-gate "ptmx", 23247c478bd9Sstevel@tonic-gate "random", 23257c478bd9Sstevel@tonic-gate "urandom", 23267c478bd9Sstevel@tonic-gate "poll", 23277c478bd9Sstevel@tonic-gate "pool", 23287c478bd9Sstevel@tonic-gate "kstat", 23297c478bd9Sstevel@tonic-gate "zero", 23307c478bd9Sstevel@tonic-gate "null", 23317c478bd9Sstevel@tonic-gate "crypto", 23327c478bd9Sstevel@tonic-gate "cryptoadm", 23337c478bd9Sstevel@tonic-gate "ticots", 23347c478bd9Sstevel@tonic-gate "ticotsord", 23357c478bd9Sstevel@tonic-gate "ticlts", 23367c478bd9Sstevel@tonic-gate "lo0", 23377c478bd9Sstevel@tonic-gate "lo1", 23387c478bd9Sstevel@tonic-gate "lo2", 23397c478bd9Sstevel@tonic-gate "lo3", 23407c478bd9Sstevel@tonic-gate "sad/user", 23417c478bd9Sstevel@tonic-gate "tty", 23427c478bd9Sstevel@tonic-gate "logindmux", 23437c478bd9Sstevel@tonic-gate "log", 23447c478bd9Sstevel@tonic-gate "conslog", 23457c478bd9Sstevel@tonic-gate "arp", 23467c478bd9Sstevel@tonic-gate "tcp", 23477c478bd9Sstevel@tonic-gate "tcp6", 23487c478bd9Sstevel@tonic-gate "udp", 23497c478bd9Sstevel@tonic-gate "udp6", 23507c478bd9Sstevel@tonic-gate "sysevent", 23517c478bd9Sstevel@tonic-gate #ifdef __sparc 23527c478bd9Sstevel@tonic-gate "openprom", 23537c478bd9Sstevel@tonic-gate #endif 23547c478bd9Sstevel@tonic-gate "cpu/self/cpuid", 2355ad4023c4Sdp "dtrace/*", 2356ad4023c4Sdp "dtrace/provider/*", 2357fa9e4066Sahrens "zfs", 23587c478bd9Sstevel@tonic-gate NULL 23597c478bd9Sstevel@tonic-gate }; 23607c478bd9Sstevel@tonic-gate 23617c478bd9Sstevel@tonic-gate /* 23627c478bd9Sstevel@tonic-gate * This function finds everything mounted under a zone's rootpath. 23637c478bd9Sstevel@tonic-gate * This returns the number of mounts under rootpath, or -1 on error. 23647c478bd9Sstevel@tonic-gate * callback is called once per mount found with the first argument 23657c478bd9Sstevel@tonic-gate * pointing to the mount point. 23667c478bd9Sstevel@tonic-gate * 23677c478bd9Sstevel@tonic-gate * If the callback function returns non-zero zonecfg_find_mounts 23687c478bd9Sstevel@tonic-gate * aborts with an error. 23697c478bd9Sstevel@tonic-gate */ 23707c478bd9Sstevel@tonic-gate 23717c478bd9Sstevel@tonic-gate int 23727c478bd9Sstevel@tonic-gate zonecfg_find_mounts(char *rootpath, int (*callback)(const char *, void *), 23737c478bd9Sstevel@tonic-gate void *priv) { 23747c478bd9Sstevel@tonic-gate FILE *mnttab; 23757c478bd9Sstevel@tonic-gate struct mnttab m; 23767c478bd9Sstevel@tonic-gate size_t l; 237707b574eeSgjelinek int zfsl; 23787c478bd9Sstevel@tonic-gate int rv = 0; 237907b574eeSgjelinek char zfs_path[MAXPATHLEN]; 23807c478bd9Sstevel@tonic-gate 23817c478bd9Sstevel@tonic-gate assert(rootpath != NULL); 23827c478bd9Sstevel@tonic-gate 238307b574eeSgjelinek if ((zfsl = snprintf(zfs_path, sizeof (zfs_path), "%s/.zfs/", rootpath)) 238407b574eeSgjelinek >= sizeof (zfs_path)) 238507b574eeSgjelinek return (-1); 238607b574eeSgjelinek 23877c478bd9Sstevel@tonic-gate l = strlen(rootpath); 23887c478bd9Sstevel@tonic-gate 23897c478bd9Sstevel@tonic-gate mnttab = fopen("/etc/mnttab", "r"); 23907c478bd9Sstevel@tonic-gate 23917c478bd9Sstevel@tonic-gate if (mnttab == NULL) 23927c478bd9Sstevel@tonic-gate return (-1); 23937c478bd9Sstevel@tonic-gate 23947c478bd9Sstevel@tonic-gate if (ioctl(fileno(mnttab), MNTIOC_SHOWHIDDEN, NULL) < 0) { 23957c478bd9Sstevel@tonic-gate rv = -1; 23967c478bd9Sstevel@tonic-gate goto out; 23977c478bd9Sstevel@tonic-gate } 23987c478bd9Sstevel@tonic-gate 23997c478bd9Sstevel@tonic-gate while (!getmntent(mnttab, &m)) { 24007c478bd9Sstevel@tonic-gate if ((strncmp(rootpath, m.mnt_mountp, l) == 0) && 240107b574eeSgjelinek (m.mnt_mountp[l] == '/') && 240207b574eeSgjelinek (strncmp(zfs_path, m.mnt_mountp, zfsl) != 0)) { 24037c478bd9Sstevel@tonic-gate rv++; 24047c478bd9Sstevel@tonic-gate if (callback == NULL) 24057c478bd9Sstevel@tonic-gate continue; 24067c478bd9Sstevel@tonic-gate if (callback(m.mnt_mountp, priv)) { 24077c478bd9Sstevel@tonic-gate rv = -1; 24087c478bd9Sstevel@tonic-gate goto out; 24097c478bd9Sstevel@tonic-gate 24107c478bd9Sstevel@tonic-gate } 24117c478bd9Sstevel@tonic-gate } 24127c478bd9Sstevel@tonic-gate } 24137c478bd9Sstevel@tonic-gate 24147c478bd9Sstevel@tonic-gate out: 24157c478bd9Sstevel@tonic-gate (void) fclose(mnttab); 24167c478bd9Sstevel@tonic-gate return (rv); 24177c478bd9Sstevel@tonic-gate } 24187c478bd9Sstevel@tonic-gate 24197c478bd9Sstevel@tonic-gate /* 24207c478bd9Sstevel@tonic-gate * This routine is used to determine if a given device should appear in the 24217c478bd9Sstevel@tonic-gate * zone represented by 'handle'. First it consults the list of "standard" 24227c478bd9Sstevel@tonic-gate * zone devices. Then it scans the user-supplied device entries. 24237c478bd9Sstevel@tonic-gate */ 24247c478bd9Sstevel@tonic-gate int 24257c478bd9Sstevel@tonic-gate zonecfg_match_dev(zone_dochandle_t handle, char *devpath, 24267c478bd9Sstevel@tonic-gate struct zone_devtab *out_match) 24277c478bd9Sstevel@tonic-gate { 24287c478bd9Sstevel@tonic-gate int err; 24297c478bd9Sstevel@tonic-gate boolean_t found = B_FALSE; 24307c478bd9Sstevel@tonic-gate char match[MAXPATHLEN]; 24317c478bd9Sstevel@tonic-gate const char **stdmatch; 24327c478bd9Sstevel@tonic-gate xmlNodePtr cur; 24337c478bd9Sstevel@tonic-gate 24347c478bd9Sstevel@tonic-gate if (handle == NULL || devpath == NULL) 24357c478bd9Sstevel@tonic-gate return (Z_INVAL); 24367c478bd9Sstevel@tonic-gate 24377c478bd9Sstevel@tonic-gate /* 24387c478bd9Sstevel@tonic-gate * Check the "standard" devices which we require to be present. 24397c478bd9Sstevel@tonic-gate */ 24407c478bd9Sstevel@tonic-gate for (stdmatch = &standard_devs[0]; *stdmatch != NULL; stdmatch++) { 24417c478bd9Sstevel@tonic-gate /* 24427c478bd9Sstevel@tonic-gate * fnmatch gives us simple but powerful shell-style matching. 24437c478bd9Sstevel@tonic-gate */ 24447c478bd9Sstevel@tonic-gate if (fnmatch(*stdmatch, devpath, FNM_PATHNAME) == 0) { 24457c478bd9Sstevel@tonic-gate if (!out_match) 24467c478bd9Sstevel@tonic-gate return (Z_OK); 24477c478bd9Sstevel@tonic-gate (void) snprintf(out_match->zone_dev_match, 24487c478bd9Sstevel@tonic-gate sizeof (out_match->zone_dev_match), 24497c478bd9Sstevel@tonic-gate "/dev/%s", *stdmatch); 24507c478bd9Sstevel@tonic-gate return (Z_OK); 24517c478bd9Sstevel@tonic-gate } 24527c478bd9Sstevel@tonic-gate } 24537c478bd9Sstevel@tonic-gate 24547c478bd9Sstevel@tonic-gate /* 24557c478bd9Sstevel@tonic-gate * We got no hits in the set of standard devices. On to the user 24567c478bd9Sstevel@tonic-gate * supplied ones. 24577c478bd9Sstevel@tonic-gate */ 24587c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) { 24597c478bd9Sstevel@tonic-gate handle->zone_dh_cur = NULL; 24607c478bd9Sstevel@tonic-gate return (err); 24617c478bd9Sstevel@tonic-gate } 24627c478bd9Sstevel@tonic-gate 24637c478bd9Sstevel@tonic-gate cur = handle->zone_dh_cur; 24647c478bd9Sstevel@tonic-gate cur = cur->xmlChildrenNode; 24657c478bd9Sstevel@tonic-gate if (cur == NULL) 24667c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 24677c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur; 24687c478bd9Sstevel@tonic-gate 24697c478bd9Sstevel@tonic-gate for (; cur != NULL; cur = cur->next) { 24707c478bd9Sstevel@tonic-gate char *m; 24717c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_DEVICE) != 0) 24727c478bd9Sstevel@tonic-gate continue; 24737c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_MATCH, match, 24747c478bd9Sstevel@tonic-gate sizeof (match))) != Z_OK) { 24757c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 24767c478bd9Sstevel@tonic-gate return (err); 24777c478bd9Sstevel@tonic-gate } 24787c478bd9Sstevel@tonic-gate m = match; 24797c478bd9Sstevel@tonic-gate /* 24807c478bd9Sstevel@tonic-gate * fnmatch gives us simple but powerful shell-style matching; 24817c478bd9Sstevel@tonic-gate * but first, we need to strip out /dev/ from the matching rule. 24827c478bd9Sstevel@tonic-gate */ 24837c478bd9Sstevel@tonic-gate if (strncmp(m, "/dev/", 5) == 0) 24847c478bd9Sstevel@tonic-gate m += 5; 24857c478bd9Sstevel@tonic-gate 24867c478bd9Sstevel@tonic-gate if (fnmatch(m, devpath, FNM_PATHNAME) == 0) { 24877c478bd9Sstevel@tonic-gate found = B_TRUE; 24887c478bd9Sstevel@tonic-gate break; 24897c478bd9Sstevel@tonic-gate } 24907c478bd9Sstevel@tonic-gate } 24917c478bd9Sstevel@tonic-gate 24927c478bd9Sstevel@tonic-gate if (!found) 24937c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 24947c478bd9Sstevel@tonic-gate 24957c478bd9Sstevel@tonic-gate if (!out_match) 24967c478bd9Sstevel@tonic-gate return (Z_OK); 24977c478bd9Sstevel@tonic-gate 24987c478bd9Sstevel@tonic-gate (void) strlcpy(out_match->zone_dev_match, match, 24997c478bd9Sstevel@tonic-gate sizeof (out_match->zone_dev_match)); 25007c478bd9Sstevel@tonic-gate return (Z_OK); 25017c478bd9Sstevel@tonic-gate } 25027c478bd9Sstevel@tonic-gate 25037c478bd9Sstevel@tonic-gate int 25047c478bd9Sstevel@tonic-gate zonecfg_lookup_attr(zone_dochandle_t handle, struct zone_attrtab *tabptr) 25057c478bd9Sstevel@tonic-gate { 25067c478bd9Sstevel@tonic-gate xmlNodePtr cur, firstmatch; 25077c478bd9Sstevel@tonic-gate int err; 25087c478bd9Sstevel@tonic-gate char name[MAXNAMELEN], type[MAXNAMELEN], value[MAXNAMELEN]; 25097c478bd9Sstevel@tonic-gate 25107c478bd9Sstevel@tonic-gate if (tabptr == NULL) 25117c478bd9Sstevel@tonic-gate return (Z_INVAL); 25127c478bd9Sstevel@tonic-gate 25137c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 25147c478bd9Sstevel@tonic-gate return (err); 25157c478bd9Sstevel@tonic-gate 25167c478bd9Sstevel@tonic-gate cur = handle->zone_dh_cur; 25177c478bd9Sstevel@tonic-gate firstmatch = NULL; 25187c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 25197c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_ATTR)) 25207c478bd9Sstevel@tonic-gate continue; 25217c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_attr_name) > 0) { 25227c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_NAME, name, 25237c478bd9Sstevel@tonic-gate sizeof (name)) == Z_OK) && 25247c478bd9Sstevel@tonic-gate (strcmp(tabptr->zone_attr_name, name) == 0)) { 25257c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 25267c478bd9Sstevel@tonic-gate firstmatch = cur; 25277c478bd9Sstevel@tonic-gate else 25287c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 25297c478bd9Sstevel@tonic-gate } 25307c478bd9Sstevel@tonic-gate } 25317c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_attr_type) > 0) { 25327c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_TYPE, type, 25337c478bd9Sstevel@tonic-gate sizeof (type)) == Z_OK)) { 25347c478bd9Sstevel@tonic-gate if (strcmp(tabptr->zone_attr_type, type) == 0) { 25357c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 25367c478bd9Sstevel@tonic-gate firstmatch = cur; 25377c478bd9Sstevel@tonic-gate else if (firstmatch != cur) 25387c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 25397c478bd9Sstevel@tonic-gate } else { 25407c478bd9Sstevel@tonic-gate /* 25417c478bd9Sstevel@tonic-gate * If another property matched but this 25427c478bd9Sstevel@tonic-gate * one doesn't then reset firstmatch. 25437c478bd9Sstevel@tonic-gate */ 25447c478bd9Sstevel@tonic-gate if (firstmatch == cur) 25457c478bd9Sstevel@tonic-gate firstmatch = NULL; 25467c478bd9Sstevel@tonic-gate } 25477c478bd9Sstevel@tonic-gate } 25487c478bd9Sstevel@tonic-gate } 25497c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_attr_value) > 0) { 25507c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_VALUE, value, 25517c478bd9Sstevel@tonic-gate sizeof (value)) == Z_OK)) { 25527c478bd9Sstevel@tonic-gate if (strcmp(tabptr->zone_attr_value, value) == 25537c478bd9Sstevel@tonic-gate 0) { 25547c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 25557c478bd9Sstevel@tonic-gate firstmatch = cur; 25567c478bd9Sstevel@tonic-gate else if (firstmatch != cur) 25577c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 25587c478bd9Sstevel@tonic-gate } else { 25597c478bd9Sstevel@tonic-gate /* 25607c478bd9Sstevel@tonic-gate * If another property matched but this 25617c478bd9Sstevel@tonic-gate * one doesn't then reset firstmatch. 25627c478bd9Sstevel@tonic-gate */ 25637c478bd9Sstevel@tonic-gate if (firstmatch == cur) 25647c478bd9Sstevel@tonic-gate firstmatch = NULL; 25657c478bd9Sstevel@tonic-gate } 25667c478bd9Sstevel@tonic-gate } 25677c478bd9Sstevel@tonic-gate } 25687c478bd9Sstevel@tonic-gate } 25697c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 25707c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 25717c478bd9Sstevel@tonic-gate 25727c478bd9Sstevel@tonic-gate cur = firstmatch; 25737c478bd9Sstevel@tonic-gate 25747c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_NAME, tabptr->zone_attr_name, 25757c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_attr_name))) != Z_OK) 25767c478bd9Sstevel@tonic-gate return (err); 25777c478bd9Sstevel@tonic-gate 25787c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_TYPE, tabptr->zone_attr_type, 25797c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_attr_type))) != Z_OK) 25807c478bd9Sstevel@tonic-gate return (err); 25817c478bd9Sstevel@tonic-gate 25827c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_VALUE, tabptr->zone_attr_value, 25837c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_attr_value))) != Z_OK) 25847c478bd9Sstevel@tonic-gate return (err); 25857c478bd9Sstevel@tonic-gate 25867c478bd9Sstevel@tonic-gate return (Z_OK); 25877c478bd9Sstevel@tonic-gate } 25887c478bd9Sstevel@tonic-gate 25897c478bd9Sstevel@tonic-gate static int 25907c478bd9Sstevel@tonic-gate zonecfg_add_attr_core(zone_dochandle_t handle, struct zone_attrtab *tabptr) 25917c478bd9Sstevel@tonic-gate { 25927c478bd9Sstevel@tonic-gate xmlNodePtr newnode, cur = handle->zone_dh_cur; 25937c478bd9Sstevel@tonic-gate int err; 25947c478bd9Sstevel@tonic-gate 25957c478bd9Sstevel@tonic-gate newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_ATTR, NULL); 2596a1be23daSdp err = newprop(newnode, DTD_ATTR_NAME, tabptr->zone_attr_name); 25977c478bd9Sstevel@tonic-gate if (err != Z_OK) 25987c478bd9Sstevel@tonic-gate return (err); 2599a1be23daSdp err = newprop(newnode, DTD_ATTR_TYPE, tabptr->zone_attr_type); 26007c478bd9Sstevel@tonic-gate if (err != Z_OK) 26017c478bd9Sstevel@tonic-gate return (err); 2602a1be23daSdp err = newprop(newnode, DTD_ATTR_VALUE, tabptr->zone_attr_value); 26037c478bd9Sstevel@tonic-gate if (err != Z_OK) 26047c478bd9Sstevel@tonic-gate return (err); 26057c478bd9Sstevel@tonic-gate return (Z_OK); 26067c478bd9Sstevel@tonic-gate } 26077c478bd9Sstevel@tonic-gate 26087c478bd9Sstevel@tonic-gate int 26097c478bd9Sstevel@tonic-gate zonecfg_add_attr(zone_dochandle_t handle, struct zone_attrtab *tabptr) 26107c478bd9Sstevel@tonic-gate { 26117c478bd9Sstevel@tonic-gate int err; 26127c478bd9Sstevel@tonic-gate 26137c478bd9Sstevel@tonic-gate if (tabptr == NULL) 26147c478bd9Sstevel@tonic-gate return (Z_INVAL); 26157c478bd9Sstevel@tonic-gate 26167c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 26177c478bd9Sstevel@tonic-gate return (err); 26187c478bd9Sstevel@tonic-gate 26197c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_attr_core(handle, tabptr)) != Z_OK) 26207c478bd9Sstevel@tonic-gate return (err); 26217c478bd9Sstevel@tonic-gate 26227c478bd9Sstevel@tonic-gate return (Z_OK); 26237c478bd9Sstevel@tonic-gate } 26247c478bd9Sstevel@tonic-gate 26257c478bd9Sstevel@tonic-gate static int 26267c478bd9Sstevel@tonic-gate zonecfg_delete_attr_core(zone_dochandle_t handle, struct zone_attrtab *tabptr) 26277c478bd9Sstevel@tonic-gate { 26287c478bd9Sstevel@tonic-gate xmlNodePtr cur = handle->zone_dh_cur; 26297c478bd9Sstevel@tonic-gate int name_match, type_match, value_match; 26307c478bd9Sstevel@tonic-gate 26317c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 26327c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_ATTR)) 26337c478bd9Sstevel@tonic-gate continue; 26347c478bd9Sstevel@tonic-gate 26357c478bd9Sstevel@tonic-gate name_match = match_prop(cur, DTD_ATTR_NAME, 26367c478bd9Sstevel@tonic-gate tabptr->zone_attr_name); 26377c478bd9Sstevel@tonic-gate type_match = match_prop(cur, DTD_ATTR_TYPE, 26387c478bd9Sstevel@tonic-gate tabptr->zone_attr_type); 26397c478bd9Sstevel@tonic-gate value_match = match_prop(cur, DTD_ATTR_VALUE, 26407c478bd9Sstevel@tonic-gate tabptr->zone_attr_value); 26417c478bd9Sstevel@tonic-gate 26427c478bd9Sstevel@tonic-gate if (name_match && type_match && value_match) { 26437c478bd9Sstevel@tonic-gate xmlUnlinkNode(cur); 26447c478bd9Sstevel@tonic-gate xmlFreeNode(cur); 26457c478bd9Sstevel@tonic-gate return (Z_OK); 26467c478bd9Sstevel@tonic-gate } 26477c478bd9Sstevel@tonic-gate } 26487c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 26497c478bd9Sstevel@tonic-gate } 26507c478bd9Sstevel@tonic-gate 26517c478bd9Sstevel@tonic-gate int 26527c478bd9Sstevel@tonic-gate zonecfg_delete_attr(zone_dochandle_t handle, struct zone_attrtab *tabptr) 26537c478bd9Sstevel@tonic-gate { 26547c478bd9Sstevel@tonic-gate int err; 26557c478bd9Sstevel@tonic-gate 26567c478bd9Sstevel@tonic-gate if (tabptr == NULL) 26577c478bd9Sstevel@tonic-gate return (Z_INVAL); 26587c478bd9Sstevel@tonic-gate 26597c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 26607c478bd9Sstevel@tonic-gate return (err); 26617c478bd9Sstevel@tonic-gate 26627c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_attr_core(handle, tabptr)) != Z_OK) 26637c478bd9Sstevel@tonic-gate return (err); 26647c478bd9Sstevel@tonic-gate 26657c478bd9Sstevel@tonic-gate return (Z_OK); 26667c478bd9Sstevel@tonic-gate } 26677c478bd9Sstevel@tonic-gate 26687c478bd9Sstevel@tonic-gate int 26697c478bd9Sstevel@tonic-gate zonecfg_modify_attr( 26707c478bd9Sstevel@tonic-gate zone_dochandle_t handle, 26717c478bd9Sstevel@tonic-gate struct zone_attrtab *oldtabptr, 26727c478bd9Sstevel@tonic-gate struct zone_attrtab *newtabptr) 26737c478bd9Sstevel@tonic-gate { 26747c478bd9Sstevel@tonic-gate int err; 26757c478bd9Sstevel@tonic-gate 26767c478bd9Sstevel@tonic-gate if (oldtabptr == NULL || newtabptr == NULL) 26777c478bd9Sstevel@tonic-gate return (Z_INVAL); 26787c478bd9Sstevel@tonic-gate 26797c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 26807c478bd9Sstevel@tonic-gate return (err); 26817c478bd9Sstevel@tonic-gate 26827c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_attr_core(handle, oldtabptr)) != Z_OK) 26837c478bd9Sstevel@tonic-gate return (err); 26847c478bd9Sstevel@tonic-gate 26857c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_attr_core(handle, newtabptr)) != Z_OK) 26867c478bd9Sstevel@tonic-gate return (err); 26877c478bd9Sstevel@tonic-gate 26887c478bd9Sstevel@tonic-gate return (Z_OK); 26897c478bd9Sstevel@tonic-gate } 26907c478bd9Sstevel@tonic-gate 26917c478bd9Sstevel@tonic-gate int 26927c478bd9Sstevel@tonic-gate zonecfg_get_attr_boolean(const struct zone_attrtab *attr, boolean_t *value) 26937c478bd9Sstevel@tonic-gate { 26947c478bd9Sstevel@tonic-gate if (attr == NULL) 26957c478bd9Sstevel@tonic-gate return (Z_INVAL); 26967c478bd9Sstevel@tonic-gate 26977c478bd9Sstevel@tonic-gate if (strcmp(attr->zone_attr_type, DTD_ENTITY_BOOLEAN) != 0) 26987c478bd9Sstevel@tonic-gate return (Z_INVAL); 26997c478bd9Sstevel@tonic-gate 27007c478bd9Sstevel@tonic-gate if (strcmp(attr->zone_attr_value, DTD_ENTITY_TRUE) == 0) { 27017c478bd9Sstevel@tonic-gate *value = B_TRUE; 27027c478bd9Sstevel@tonic-gate return (Z_OK); 27037c478bd9Sstevel@tonic-gate } 27047c478bd9Sstevel@tonic-gate if (strcmp(attr->zone_attr_value, DTD_ENTITY_FALSE) == 0) { 27057c478bd9Sstevel@tonic-gate *value = B_FALSE; 27067c478bd9Sstevel@tonic-gate return (Z_OK); 27077c478bd9Sstevel@tonic-gate } 27087c478bd9Sstevel@tonic-gate return (Z_INVAL); 27097c478bd9Sstevel@tonic-gate } 27107c478bd9Sstevel@tonic-gate 27117c478bd9Sstevel@tonic-gate int 27127c478bd9Sstevel@tonic-gate zonecfg_get_attr_int(const struct zone_attrtab *attr, int64_t *value) 27137c478bd9Sstevel@tonic-gate { 27147c478bd9Sstevel@tonic-gate long long result; 27157c478bd9Sstevel@tonic-gate char *endptr; 27167c478bd9Sstevel@tonic-gate 27177c478bd9Sstevel@tonic-gate if (attr == NULL) 27187c478bd9Sstevel@tonic-gate return (Z_INVAL); 27197c478bd9Sstevel@tonic-gate 27207c478bd9Sstevel@tonic-gate if (strcmp(attr->zone_attr_type, DTD_ENTITY_INT) != 0) 27217c478bd9Sstevel@tonic-gate return (Z_INVAL); 27227c478bd9Sstevel@tonic-gate 27237c478bd9Sstevel@tonic-gate errno = 0; 27247c478bd9Sstevel@tonic-gate result = strtoll(attr->zone_attr_value, &endptr, 10); 27257c478bd9Sstevel@tonic-gate if (errno != 0 || *endptr != '\0') 27267c478bd9Sstevel@tonic-gate return (Z_INVAL); 27277c478bd9Sstevel@tonic-gate *value = result; 27287c478bd9Sstevel@tonic-gate return (Z_OK); 27297c478bd9Sstevel@tonic-gate } 27307c478bd9Sstevel@tonic-gate 27317c478bd9Sstevel@tonic-gate int 27327c478bd9Sstevel@tonic-gate zonecfg_get_attr_string(const struct zone_attrtab *attr, char *value, 27337c478bd9Sstevel@tonic-gate size_t val_sz) 27347c478bd9Sstevel@tonic-gate { 27357c478bd9Sstevel@tonic-gate if (attr == NULL) 27367c478bd9Sstevel@tonic-gate return (Z_INVAL); 27377c478bd9Sstevel@tonic-gate 27387c478bd9Sstevel@tonic-gate if (strcmp(attr->zone_attr_type, DTD_ENTITY_STRING) != 0) 27397c478bd9Sstevel@tonic-gate return (Z_INVAL); 27407c478bd9Sstevel@tonic-gate 27417c478bd9Sstevel@tonic-gate if (strlcpy(value, attr->zone_attr_value, val_sz) >= val_sz) 27427c478bd9Sstevel@tonic-gate return (Z_TOO_BIG); 27437c478bd9Sstevel@tonic-gate return (Z_OK); 27447c478bd9Sstevel@tonic-gate } 27457c478bd9Sstevel@tonic-gate 27467c478bd9Sstevel@tonic-gate int 27477c478bd9Sstevel@tonic-gate zonecfg_get_attr_uint(const struct zone_attrtab *attr, uint64_t *value) 27487c478bd9Sstevel@tonic-gate { 27497c478bd9Sstevel@tonic-gate unsigned long long result; 27507c478bd9Sstevel@tonic-gate long long neg_result; 27517c478bd9Sstevel@tonic-gate char *endptr; 27527c478bd9Sstevel@tonic-gate 27537c478bd9Sstevel@tonic-gate if (attr == NULL) 27547c478bd9Sstevel@tonic-gate return (Z_INVAL); 27557c478bd9Sstevel@tonic-gate 27567c478bd9Sstevel@tonic-gate if (strcmp(attr->zone_attr_type, DTD_ENTITY_UINT) != 0) 27577c478bd9Sstevel@tonic-gate return (Z_INVAL); 27587c478bd9Sstevel@tonic-gate 27597c478bd9Sstevel@tonic-gate errno = 0; 27607c478bd9Sstevel@tonic-gate result = strtoull(attr->zone_attr_value, &endptr, 10); 27617c478bd9Sstevel@tonic-gate if (errno != 0 || *endptr != '\0') 27627c478bd9Sstevel@tonic-gate return (Z_INVAL); 27637c478bd9Sstevel@tonic-gate errno = 0; 27647c478bd9Sstevel@tonic-gate neg_result = strtoll(attr->zone_attr_value, &endptr, 10); 27657c478bd9Sstevel@tonic-gate /* 27667c478bd9Sstevel@tonic-gate * Incredibly, strtoull("<negative number>", ...) will not fail but 27677c478bd9Sstevel@tonic-gate * return whatever (negative) number cast as a u_longlong_t, so we 27687c478bd9Sstevel@tonic-gate * need to look for this here. 27697c478bd9Sstevel@tonic-gate */ 27707c478bd9Sstevel@tonic-gate if (errno == 0 && neg_result < 0) 27717c478bd9Sstevel@tonic-gate return (Z_INVAL); 27727c478bd9Sstevel@tonic-gate *value = result; 27737c478bd9Sstevel@tonic-gate return (Z_OK); 27747c478bd9Sstevel@tonic-gate } 27757c478bd9Sstevel@tonic-gate 27767c478bd9Sstevel@tonic-gate int 27777c478bd9Sstevel@tonic-gate zonecfg_lookup_rctl(zone_dochandle_t handle, struct zone_rctltab *tabptr) 27787c478bd9Sstevel@tonic-gate { 27797c478bd9Sstevel@tonic-gate xmlNodePtr cur, val; 27807c478bd9Sstevel@tonic-gate char savedname[MAXNAMELEN]; 27817c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *valptr; 27827c478bd9Sstevel@tonic-gate int err; 27837c478bd9Sstevel@tonic-gate 27847c478bd9Sstevel@tonic-gate if (tabptr->zone_rctl_name == NULL || 27857c478bd9Sstevel@tonic-gate strlen(tabptr->zone_rctl_name) == 0) 27867c478bd9Sstevel@tonic-gate return (Z_INVAL); 27877c478bd9Sstevel@tonic-gate 27887c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 27897c478bd9Sstevel@tonic-gate return (err); 27907c478bd9Sstevel@tonic-gate 27917c478bd9Sstevel@tonic-gate cur = handle->zone_dh_cur; 27927c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 27937c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_RCTL)) 27947c478bd9Sstevel@tonic-gate continue; 27957c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_NAME, savedname, 27967c478bd9Sstevel@tonic-gate sizeof (savedname)) == Z_OK) && 27977c478bd9Sstevel@tonic-gate (strcmp(savedname, tabptr->zone_rctl_name) == 0)) { 27987c478bd9Sstevel@tonic-gate tabptr->zone_rctl_valptr = NULL; 27997c478bd9Sstevel@tonic-gate for (val = cur->xmlChildrenNode; val != NULL; 28007c478bd9Sstevel@tonic-gate val = val->next) { 28017c478bd9Sstevel@tonic-gate valptr = (struct zone_rctlvaltab *)malloc( 28027c478bd9Sstevel@tonic-gate sizeof (struct zone_rctlvaltab)); 28037c478bd9Sstevel@tonic-gate if (valptr == NULL) 28047c478bd9Sstevel@tonic-gate return (Z_NOMEM); 28057c478bd9Sstevel@tonic-gate if ((fetchprop(val, DTD_ATTR_PRIV, 28067c478bd9Sstevel@tonic-gate valptr->zone_rctlval_priv, 28077c478bd9Sstevel@tonic-gate sizeof (valptr->zone_rctlval_priv)) != 28087c478bd9Sstevel@tonic-gate Z_OK)) 28097c478bd9Sstevel@tonic-gate break; 28107c478bd9Sstevel@tonic-gate if ((fetchprop(val, DTD_ATTR_LIMIT, 28117c478bd9Sstevel@tonic-gate valptr->zone_rctlval_limit, 28127c478bd9Sstevel@tonic-gate sizeof (valptr->zone_rctlval_limit)) != 28137c478bd9Sstevel@tonic-gate Z_OK)) 28147c478bd9Sstevel@tonic-gate break; 28157c478bd9Sstevel@tonic-gate if ((fetchprop(val, DTD_ATTR_ACTION, 28167c478bd9Sstevel@tonic-gate valptr->zone_rctlval_action, 28177c478bd9Sstevel@tonic-gate sizeof (valptr->zone_rctlval_action)) != 28187c478bd9Sstevel@tonic-gate Z_OK)) 28197c478bd9Sstevel@tonic-gate break; 28207c478bd9Sstevel@tonic-gate if (zonecfg_add_rctl_value(tabptr, valptr) != 28217c478bd9Sstevel@tonic-gate Z_OK) 28227c478bd9Sstevel@tonic-gate break; 28237c478bd9Sstevel@tonic-gate } 28247c478bd9Sstevel@tonic-gate return (Z_OK); 28257c478bd9Sstevel@tonic-gate } 28267c478bd9Sstevel@tonic-gate } 28277c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 28287c478bd9Sstevel@tonic-gate } 28297c478bd9Sstevel@tonic-gate 28307c478bd9Sstevel@tonic-gate static int 28317c478bd9Sstevel@tonic-gate zonecfg_add_rctl_core(zone_dochandle_t handle, struct zone_rctltab *tabptr) 28327c478bd9Sstevel@tonic-gate { 28337c478bd9Sstevel@tonic-gate xmlNodePtr newnode, cur = handle->zone_dh_cur, valnode; 28347c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *valptr; 28357c478bd9Sstevel@tonic-gate int err; 28367c478bd9Sstevel@tonic-gate 28377c478bd9Sstevel@tonic-gate newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_RCTL, NULL); 2838a1be23daSdp err = newprop(newnode, DTD_ATTR_NAME, tabptr->zone_rctl_name); 28397c478bd9Sstevel@tonic-gate if (err != Z_OK) 28407c478bd9Sstevel@tonic-gate return (err); 28417c478bd9Sstevel@tonic-gate for (valptr = tabptr->zone_rctl_valptr; valptr != NULL; 28427c478bd9Sstevel@tonic-gate valptr = valptr->zone_rctlval_next) { 28437c478bd9Sstevel@tonic-gate valnode = xmlNewTextChild(newnode, NULL, 28447c478bd9Sstevel@tonic-gate DTD_ELEM_RCTLVALUE, NULL); 2845a1be23daSdp err = newprop(valnode, DTD_ATTR_PRIV, 28467c478bd9Sstevel@tonic-gate valptr->zone_rctlval_priv); 28477c478bd9Sstevel@tonic-gate if (err != Z_OK) 28487c478bd9Sstevel@tonic-gate return (err); 2849a1be23daSdp err = newprop(valnode, DTD_ATTR_LIMIT, 28507c478bd9Sstevel@tonic-gate valptr->zone_rctlval_limit); 28517c478bd9Sstevel@tonic-gate if (err != Z_OK) 28527c478bd9Sstevel@tonic-gate return (err); 2853a1be23daSdp err = newprop(valnode, DTD_ATTR_ACTION, 28547c478bd9Sstevel@tonic-gate valptr->zone_rctlval_action); 28557c478bd9Sstevel@tonic-gate if (err != Z_OK) 28567c478bd9Sstevel@tonic-gate return (err); 28577c478bd9Sstevel@tonic-gate } 28587c478bd9Sstevel@tonic-gate return (Z_OK); 28597c478bd9Sstevel@tonic-gate } 28607c478bd9Sstevel@tonic-gate 28617c478bd9Sstevel@tonic-gate int 28627c478bd9Sstevel@tonic-gate zonecfg_add_rctl(zone_dochandle_t handle, struct zone_rctltab *tabptr) 28637c478bd9Sstevel@tonic-gate { 28647c478bd9Sstevel@tonic-gate int err; 28657c478bd9Sstevel@tonic-gate 28667c478bd9Sstevel@tonic-gate if (tabptr == NULL || tabptr->zone_rctl_name == NULL) 28677c478bd9Sstevel@tonic-gate return (Z_INVAL); 28687c478bd9Sstevel@tonic-gate 28697c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 28707c478bd9Sstevel@tonic-gate return (err); 28717c478bd9Sstevel@tonic-gate 28727c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_rctl_core(handle, tabptr)) != Z_OK) 28737c478bd9Sstevel@tonic-gate return (err); 28747c478bd9Sstevel@tonic-gate 28757c478bd9Sstevel@tonic-gate return (Z_OK); 28767c478bd9Sstevel@tonic-gate } 28777c478bd9Sstevel@tonic-gate 28787c478bd9Sstevel@tonic-gate static int 28797c478bd9Sstevel@tonic-gate zonecfg_delete_rctl_core(zone_dochandle_t handle, struct zone_rctltab *tabptr) 28807c478bd9Sstevel@tonic-gate { 28817c478bd9Sstevel@tonic-gate xmlNodePtr cur = handle->zone_dh_cur; 28827c478bd9Sstevel@tonic-gate xmlChar *savedname; 28837c478bd9Sstevel@tonic-gate int name_result; 28847c478bd9Sstevel@tonic-gate 28857c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 28867c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_RCTL)) 28877c478bd9Sstevel@tonic-gate continue; 28887c478bd9Sstevel@tonic-gate 28897c478bd9Sstevel@tonic-gate savedname = xmlGetProp(cur, DTD_ATTR_NAME); 28907c478bd9Sstevel@tonic-gate if (savedname == NULL) /* shouldn't happen */ 28917c478bd9Sstevel@tonic-gate continue; 28927c478bd9Sstevel@tonic-gate name_result = xmlStrcmp(savedname, 28937c478bd9Sstevel@tonic-gate (const xmlChar *) tabptr->zone_rctl_name); 28947c478bd9Sstevel@tonic-gate xmlFree(savedname); 28957c478bd9Sstevel@tonic-gate 28967c478bd9Sstevel@tonic-gate if (name_result == 0) { 28977c478bd9Sstevel@tonic-gate xmlUnlinkNode(cur); 28987c478bd9Sstevel@tonic-gate xmlFreeNode(cur); 28997c478bd9Sstevel@tonic-gate return (Z_OK); 29007c478bd9Sstevel@tonic-gate } 29017c478bd9Sstevel@tonic-gate } 29027c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 29037c478bd9Sstevel@tonic-gate } 29047c478bd9Sstevel@tonic-gate 29057c478bd9Sstevel@tonic-gate int 29067c478bd9Sstevel@tonic-gate zonecfg_delete_rctl(zone_dochandle_t handle, struct zone_rctltab *tabptr) 29077c478bd9Sstevel@tonic-gate { 29087c478bd9Sstevel@tonic-gate int err; 29097c478bd9Sstevel@tonic-gate 29107c478bd9Sstevel@tonic-gate if (tabptr == NULL || tabptr->zone_rctl_name == NULL) 29117c478bd9Sstevel@tonic-gate return (Z_INVAL); 29127c478bd9Sstevel@tonic-gate 29137c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 29147c478bd9Sstevel@tonic-gate return (err); 29157c478bd9Sstevel@tonic-gate 29167c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_rctl_core(handle, tabptr)) != Z_OK) 29177c478bd9Sstevel@tonic-gate return (err); 29187c478bd9Sstevel@tonic-gate 29197c478bd9Sstevel@tonic-gate return (Z_OK); 29207c478bd9Sstevel@tonic-gate } 29217c478bd9Sstevel@tonic-gate 29227c478bd9Sstevel@tonic-gate int 29237c478bd9Sstevel@tonic-gate zonecfg_modify_rctl( 29247c478bd9Sstevel@tonic-gate zone_dochandle_t handle, 29257c478bd9Sstevel@tonic-gate struct zone_rctltab *oldtabptr, 29267c478bd9Sstevel@tonic-gate struct zone_rctltab *newtabptr) 29277c478bd9Sstevel@tonic-gate { 29287c478bd9Sstevel@tonic-gate int err; 29297c478bd9Sstevel@tonic-gate 29307c478bd9Sstevel@tonic-gate if (oldtabptr == NULL || oldtabptr->zone_rctl_name == NULL || 29317c478bd9Sstevel@tonic-gate newtabptr == NULL || newtabptr->zone_rctl_name == NULL) 29327c478bd9Sstevel@tonic-gate return (Z_INVAL); 29337c478bd9Sstevel@tonic-gate 29347c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 29357c478bd9Sstevel@tonic-gate return (err); 29367c478bd9Sstevel@tonic-gate 29377c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_rctl_core(handle, oldtabptr)) != Z_OK) 29387c478bd9Sstevel@tonic-gate return (err); 29397c478bd9Sstevel@tonic-gate 29407c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_rctl_core(handle, newtabptr)) != Z_OK) 29417c478bd9Sstevel@tonic-gate return (err); 29427c478bd9Sstevel@tonic-gate 29437c478bd9Sstevel@tonic-gate return (Z_OK); 29447c478bd9Sstevel@tonic-gate } 29457c478bd9Sstevel@tonic-gate 29467c478bd9Sstevel@tonic-gate int 29477c478bd9Sstevel@tonic-gate zonecfg_add_rctl_value( 29487c478bd9Sstevel@tonic-gate struct zone_rctltab *tabptr, 29497c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *valtabptr) 29507c478bd9Sstevel@tonic-gate { 29517c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *last, *old, *new; 29527c478bd9Sstevel@tonic-gate rctlblk_t *rctlblk = alloca(rctlblk_size()); 29537c478bd9Sstevel@tonic-gate 29547c478bd9Sstevel@tonic-gate last = tabptr->zone_rctl_valptr; 29557c478bd9Sstevel@tonic-gate for (old = last; old != NULL; old = old->zone_rctlval_next) 29567c478bd9Sstevel@tonic-gate last = old; /* walk to the end of the list */ 29577c478bd9Sstevel@tonic-gate new = valtabptr; /* alloc'd by caller */ 29587c478bd9Sstevel@tonic-gate new->zone_rctlval_next = NULL; 29597c478bd9Sstevel@tonic-gate if (zonecfg_construct_rctlblk(valtabptr, rctlblk) != Z_OK) 29607c478bd9Sstevel@tonic-gate return (Z_INVAL); 29617c478bd9Sstevel@tonic-gate if (!zonecfg_valid_rctlblk(rctlblk)) 29627c478bd9Sstevel@tonic-gate return (Z_INVAL); 29637c478bd9Sstevel@tonic-gate if (last == NULL) 29647c478bd9Sstevel@tonic-gate tabptr->zone_rctl_valptr = new; 29657c478bd9Sstevel@tonic-gate else 29667c478bd9Sstevel@tonic-gate last->zone_rctlval_next = new; 29677c478bd9Sstevel@tonic-gate return (Z_OK); 29687c478bd9Sstevel@tonic-gate } 29697c478bd9Sstevel@tonic-gate 29707c478bd9Sstevel@tonic-gate int 29717c478bd9Sstevel@tonic-gate zonecfg_remove_rctl_value( 29727c478bd9Sstevel@tonic-gate struct zone_rctltab *tabptr, 29737c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *valtabptr) 29747c478bd9Sstevel@tonic-gate { 29757c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *last, *this, *next; 29767c478bd9Sstevel@tonic-gate 29777c478bd9Sstevel@tonic-gate last = tabptr->zone_rctl_valptr; 29787c478bd9Sstevel@tonic-gate for (this = last; this != NULL; this = this->zone_rctlval_next) { 29797c478bd9Sstevel@tonic-gate if (strcmp(this->zone_rctlval_priv, 29807c478bd9Sstevel@tonic-gate valtabptr->zone_rctlval_priv) == 0 && 29817c478bd9Sstevel@tonic-gate strcmp(this->zone_rctlval_limit, 29827c478bd9Sstevel@tonic-gate valtabptr->zone_rctlval_limit) == 0 && 29837c478bd9Sstevel@tonic-gate strcmp(this->zone_rctlval_action, 29847c478bd9Sstevel@tonic-gate valtabptr->zone_rctlval_action) == 0) { 29857c478bd9Sstevel@tonic-gate next = this->zone_rctlval_next; 29867c478bd9Sstevel@tonic-gate if (this == tabptr->zone_rctl_valptr) 29877c478bd9Sstevel@tonic-gate tabptr->zone_rctl_valptr = next; 29887c478bd9Sstevel@tonic-gate else 29897c478bd9Sstevel@tonic-gate last->zone_rctlval_next = next; 29907c478bd9Sstevel@tonic-gate free(this); 29917c478bd9Sstevel@tonic-gate return (Z_OK); 29927c478bd9Sstevel@tonic-gate } else 29937c478bd9Sstevel@tonic-gate last = this; 29947c478bd9Sstevel@tonic-gate } 29957c478bd9Sstevel@tonic-gate return (Z_NO_PROPERTY_ID); 29967c478bd9Sstevel@tonic-gate } 29977c478bd9Sstevel@tonic-gate 29987c478bd9Sstevel@tonic-gate char * 29997c478bd9Sstevel@tonic-gate zonecfg_strerror(int errnum) 30007c478bd9Sstevel@tonic-gate { 30017c478bd9Sstevel@tonic-gate switch (errnum) { 30027c478bd9Sstevel@tonic-gate case Z_OK: 30037c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "OK")); 30047c478bd9Sstevel@tonic-gate case Z_EMPTY_DOCUMENT: 30057c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Empty document")); 30067c478bd9Sstevel@tonic-gate case Z_WRONG_DOC_TYPE: 30077c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Wrong document type")); 30087c478bd9Sstevel@tonic-gate case Z_BAD_PROPERTY: 30097c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Bad document property")); 30107c478bd9Sstevel@tonic-gate case Z_TEMP_FILE: 30117c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, 30127c478bd9Sstevel@tonic-gate "Problem creating temporary file")); 30137c478bd9Sstevel@tonic-gate case Z_SAVING_FILE: 30147c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Problem saving file")); 30157c478bd9Sstevel@tonic-gate case Z_NO_ENTRY: 30167c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "No such entry")); 30177c478bd9Sstevel@tonic-gate case Z_BOGUS_ZONE_NAME: 30187c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Bogus zone name")); 30197c478bd9Sstevel@tonic-gate case Z_REQD_RESOURCE_MISSING: 30207c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Required resource missing")); 30217c478bd9Sstevel@tonic-gate case Z_REQD_PROPERTY_MISSING: 30227c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Required property missing")); 30237c478bd9Sstevel@tonic-gate case Z_BAD_HANDLE: 30247c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Bad handle")); 30257c478bd9Sstevel@tonic-gate case Z_NOMEM: 30267c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Out of memory")); 30277c478bd9Sstevel@tonic-gate case Z_INVAL: 30287c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Invalid argument")); 30297c478bd9Sstevel@tonic-gate case Z_ACCES: 30307c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Permission denied")); 30317c478bd9Sstevel@tonic-gate case Z_TOO_BIG: 30327c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Argument list too long")); 30337c478bd9Sstevel@tonic-gate case Z_MISC_FS: 30347c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, 30357c478bd9Sstevel@tonic-gate "Miscellaneous file system error")); 30367c478bd9Sstevel@tonic-gate case Z_NO_ZONE: 30377c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "No such zone configured")); 30387c478bd9Sstevel@tonic-gate case Z_NO_RESOURCE_TYPE: 30397c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "No such resource type")); 30407c478bd9Sstevel@tonic-gate case Z_NO_RESOURCE_ID: 30417c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "No such resource with that id")); 30427c478bd9Sstevel@tonic-gate case Z_NO_PROPERTY_TYPE: 30437c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "No such property type")); 30447c478bd9Sstevel@tonic-gate case Z_NO_PROPERTY_ID: 30457c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "No such property with that id")); 3046087719fdSdp case Z_BAD_ZONE_STATE: 30477c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, 3048087719fdSdp "Zone state is invalid for the requested operation")); 30497c478bd9Sstevel@tonic-gate case Z_INVALID_DOCUMENT: 30507c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Invalid document")); 3051087719fdSdp case Z_NAME_IN_USE: 3052087719fdSdp return (dgettext(TEXT_DOMAIN, "Zone name already in use")); 30537c478bd9Sstevel@tonic-gate case Z_NO_SUCH_ID: 30547c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "No such zone ID")); 30557c478bd9Sstevel@tonic-gate case Z_UPDATING_INDEX: 30567c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Problem updating index file")); 30577c478bd9Sstevel@tonic-gate case Z_LOCKING_FILE: 30587c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Locking index file")); 30597c478bd9Sstevel@tonic-gate case Z_UNLOCKING_FILE: 30607c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Unlocking index file")); 30617c478bd9Sstevel@tonic-gate case Z_INSUFFICIENT_SPEC: 30627c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Insufficient specification")); 30637c478bd9Sstevel@tonic-gate case Z_RESOLVED_PATH: 30647c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Resolved path mismatch")); 30657c478bd9Sstevel@tonic-gate case Z_IPV6_ADDR_PREFIX_LEN: 30667c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, 30677c478bd9Sstevel@tonic-gate "IPv6 address missing required prefix length")); 30687c478bd9Sstevel@tonic-gate case Z_BOGUS_ADDRESS: 30697c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, 30707c478bd9Sstevel@tonic-gate "Neither an IPv4 nor an IPv6 address nor a host name")); 3071ffbafc53Scomay case Z_PRIV_PROHIBITED: 3072ffbafc53Scomay return (dgettext(TEXT_DOMAIN, 3073ffbafc53Scomay "Specified privilege is prohibited")); 3074ffbafc53Scomay case Z_PRIV_REQUIRED: 3075ffbafc53Scomay return (dgettext(TEXT_DOMAIN, 3076ffbafc53Scomay "Required privilege is missing")); 3077ffbafc53Scomay case Z_PRIV_UNKNOWN: 3078ffbafc53Scomay return (dgettext(TEXT_DOMAIN, 3079ffbafc53Scomay "Specified privilege is unknown")); 30807c478bd9Sstevel@tonic-gate default: 30817c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Unknown error")); 30827c478bd9Sstevel@tonic-gate } 30837c478bd9Sstevel@tonic-gate } 30847c478bd9Sstevel@tonic-gate 30857c478bd9Sstevel@tonic-gate /* 30867c478bd9Sstevel@tonic-gate * Note that the zonecfg_setXent() and zonecfg_endXent() calls are all the 30877c478bd9Sstevel@tonic-gate * same, as they just turn around and call zonecfg_setent() / zonecfg_endent(). 30887c478bd9Sstevel@tonic-gate */ 30897c478bd9Sstevel@tonic-gate 30907c478bd9Sstevel@tonic-gate static int 30917c478bd9Sstevel@tonic-gate zonecfg_setent(zone_dochandle_t handle) 30927c478bd9Sstevel@tonic-gate { 30937c478bd9Sstevel@tonic-gate xmlNodePtr cur; 30947c478bd9Sstevel@tonic-gate int err; 30957c478bd9Sstevel@tonic-gate 30967c478bd9Sstevel@tonic-gate if (handle == NULL) 30977c478bd9Sstevel@tonic-gate return (Z_INVAL); 30987c478bd9Sstevel@tonic-gate 30997c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) { 31007c478bd9Sstevel@tonic-gate handle->zone_dh_cur = NULL; 31017c478bd9Sstevel@tonic-gate return (err); 31027c478bd9Sstevel@tonic-gate } 31037c478bd9Sstevel@tonic-gate cur = handle->zone_dh_cur; 31047c478bd9Sstevel@tonic-gate cur = cur->xmlChildrenNode; 31057c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur; 31067c478bd9Sstevel@tonic-gate return (Z_OK); 31077c478bd9Sstevel@tonic-gate } 31087c478bd9Sstevel@tonic-gate 31097c478bd9Sstevel@tonic-gate static int 31107c478bd9Sstevel@tonic-gate zonecfg_endent(zone_dochandle_t handle) 31117c478bd9Sstevel@tonic-gate { 31127c478bd9Sstevel@tonic-gate if (handle == NULL) 31137c478bd9Sstevel@tonic-gate return (Z_INVAL); 31147c478bd9Sstevel@tonic-gate 31157c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 31167c478bd9Sstevel@tonic-gate return (Z_OK); 31177c478bd9Sstevel@tonic-gate } 31187c478bd9Sstevel@tonic-gate 31197c478bd9Sstevel@tonic-gate int 31207c478bd9Sstevel@tonic-gate zonecfg_setfsent(zone_dochandle_t handle) 31217c478bd9Sstevel@tonic-gate { 31227c478bd9Sstevel@tonic-gate return (zonecfg_setent(handle)); 31237c478bd9Sstevel@tonic-gate } 31247c478bd9Sstevel@tonic-gate 31257c478bd9Sstevel@tonic-gate int 31267c478bd9Sstevel@tonic-gate zonecfg_getfsent(zone_dochandle_t handle, struct zone_fstab *tabptr) 31277c478bd9Sstevel@tonic-gate { 31287c478bd9Sstevel@tonic-gate xmlNodePtr cur, options; 31297c478bd9Sstevel@tonic-gate char options_str[MAX_MNTOPT_STR]; 31307c478bd9Sstevel@tonic-gate int err; 31317c478bd9Sstevel@tonic-gate 31327c478bd9Sstevel@tonic-gate if (handle == NULL) 31337c478bd9Sstevel@tonic-gate return (Z_INVAL); 31347c478bd9Sstevel@tonic-gate 31357c478bd9Sstevel@tonic-gate if ((cur = handle->zone_dh_cur) == NULL) 31367c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 31377c478bd9Sstevel@tonic-gate 31387c478bd9Sstevel@tonic-gate for (; cur != NULL; cur = cur->next) 31397c478bd9Sstevel@tonic-gate if (!xmlStrcmp(cur->name, DTD_ELEM_FS)) 31407c478bd9Sstevel@tonic-gate break; 31417c478bd9Sstevel@tonic-gate if (cur == NULL) { 31427c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 31437c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 31447c478bd9Sstevel@tonic-gate } 31457c478bd9Sstevel@tonic-gate 31467c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_SPECIAL, tabptr->zone_fs_special, 31477c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_special))) != Z_OK) { 31487c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 31497c478bd9Sstevel@tonic-gate return (err); 31507c478bd9Sstevel@tonic-gate } 31517c478bd9Sstevel@tonic-gate 31527c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_RAW, tabptr->zone_fs_raw, 31537c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_raw))) != Z_OK) { 31547c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 31557c478bd9Sstevel@tonic-gate return (err); 31567c478bd9Sstevel@tonic-gate } 31577c478bd9Sstevel@tonic-gate 31587c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir, 31597c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_dir))) != Z_OK) { 31607c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 31617c478bd9Sstevel@tonic-gate return (err); 31627c478bd9Sstevel@tonic-gate } 31637c478bd9Sstevel@tonic-gate 31647c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_TYPE, tabptr->zone_fs_type, 31657c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_type))) != Z_OK) { 31667c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 31677c478bd9Sstevel@tonic-gate return (err); 31687c478bd9Sstevel@tonic-gate } 31697c478bd9Sstevel@tonic-gate 31707c478bd9Sstevel@tonic-gate /* OK for options to be NULL */ 31717c478bd9Sstevel@tonic-gate tabptr->zone_fs_options = NULL; 31727c478bd9Sstevel@tonic-gate for (options = cur->xmlChildrenNode; options != NULL; 31737c478bd9Sstevel@tonic-gate options = options->next) { 31747c478bd9Sstevel@tonic-gate if (fetchprop(options, DTD_ATTR_NAME, options_str, 31757c478bd9Sstevel@tonic-gate sizeof (options_str)) != Z_OK) 31767c478bd9Sstevel@tonic-gate break; 31777c478bd9Sstevel@tonic-gate if (zonecfg_add_fs_option(tabptr, options_str) != Z_OK) 31787c478bd9Sstevel@tonic-gate break; 31797c478bd9Sstevel@tonic-gate } 31807c478bd9Sstevel@tonic-gate 31817c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur->next; 31827c478bd9Sstevel@tonic-gate return (Z_OK); 31837c478bd9Sstevel@tonic-gate } 31847c478bd9Sstevel@tonic-gate 31857c478bd9Sstevel@tonic-gate int 31867c478bd9Sstevel@tonic-gate zonecfg_endfsent(zone_dochandle_t handle) 31877c478bd9Sstevel@tonic-gate { 31887c478bd9Sstevel@tonic-gate return (zonecfg_endent(handle)); 31897c478bd9Sstevel@tonic-gate } 31907c478bd9Sstevel@tonic-gate 31917c478bd9Sstevel@tonic-gate int 31927c478bd9Sstevel@tonic-gate zonecfg_setipdent(zone_dochandle_t handle) 31937c478bd9Sstevel@tonic-gate { 31947c478bd9Sstevel@tonic-gate return (zonecfg_setent(handle)); 31957c478bd9Sstevel@tonic-gate } 31967c478bd9Sstevel@tonic-gate 31977c478bd9Sstevel@tonic-gate int 31987c478bd9Sstevel@tonic-gate zonecfg_getipdent(zone_dochandle_t handle, struct zone_fstab *tabptr) 31997c478bd9Sstevel@tonic-gate { 32007c478bd9Sstevel@tonic-gate xmlNodePtr cur; 32017c478bd9Sstevel@tonic-gate int err; 32027c478bd9Sstevel@tonic-gate 32037c478bd9Sstevel@tonic-gate if (handle == NULL) 32047c478bd9Sstevel@tonic-gate return (Z_INVAL); 32057c478bd9Sstevel@tonic-gate 32067c478bd9Sstevel@tonic-gate if ((cur = handle->zone_dh_cur) == NULL) 32077c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 32087c478bd9Sstevel@tonic-gate 32097c478bd9Sstevel@tonic-gate for (; cur != NULL; cur = cur->next) 32107c478bd9Sstevel@tonic-gate if (!xmlStrcmp(cur->name, DTD_ELEM_IPD)) 32117c478bd9Sstevel@tonic-gate break; 32127c478bd9Sstevel@tonic-gate if (cur == NULL) { 32137c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 32147c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 32157c478bd9Sstevel@tonic-gate } 32167c478bd9Sstevel@tonic-gate 32177c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir, 32187c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_dir))) != Z_OK) { 32197c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 32207c478bd9Sstevel@tonic-gate return (err); 32217c478bd9Sstevel@tonic-gate } 32227c478bd9Sstevel@tonic-gate 32237c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur->next; 32247c478bd9Sstevel@tonic-gate return (Z_OK); 32257c478bd9Sstevel@tonic-gate } 32267c478bd9Sstevel@tonic-gate 32277c478bd9Sstevel@tonic-gate int 32287c478bd9Sstevel@tonic-gate zonecfg_endipdent(zone_dochandle_t handle) 32297c478bd9Sstevel@tonic-gate { 32307c478bd9Sstevel@tonic-gate return (zonecfg_endent(handle)); 32317c478bd9Sstevel@tonic-gate } 32327c478bd9Sstevel@tonic-gate 32337c478bd9Sstevel@tonic-gate int 32347c478bd9Sstevel@tonic-gate zonecfg_setnwifent(zone_dochandle_t handle) 32357c478bd9Sstevel@tonic-gate { 32367c478bd9Sstevel@tonic-gate return (zonecfg_setent(handle)); 32377c478bd9Sstevel@tonic-gate } 32387c478bd9Sstevel@tonic-gate 32397c478bd9Sstevel@tonic-gate int 32407c478bd9Sstevel@tonic-gate zonecfg_getnwifent(zone_dochandle_t handle, struct zone_nwiftab *tabptr) 32417c478bd9Sstevel@tonic-gate { 32427c478bd9Sstevel@tonic-gate xmlNodePtr cur; 32437c478bd9Sstevel@tonic-gate int err; 32447c478bd9Sstevel@tonic-gate 32457c478bd9Sstevel@tonic-gate if (handle == NULL) 32467c478bd9Sstevel@tonic-gate return (Z_INVAL); 32477c478bd9Sstevel@tonic-gate 32487c478bd9Sstevel@tonic-gate if ((cur = handle->zone_dh_cur) == NULL) 32497c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 32507c478bd9Sstevel@tonic-gate 32517c478bd9Sstevel@tonic-gate for (; cur != NULL; cur = cur->next) 32527c478bd9Sstevel@tonic-gate if (!xmlStrcmp(cur->name, DTD_ELEM_NET)) 32537c478bd9Sstevel@tonic-gate break; 32547c478bd9Sstevel@tonic-gate if (cur == NULL) { 32557c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 32567c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 32577c478bd9Sstevel@tonic-gate } 32587c478bd9Sstevel@tonic-gate 32597c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_ADDRESS, tabptr->zone_nwif_address, 32607c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_nwif_address))) != Z_OK) { 32617c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 32627c478bd9Sstevel@tonic-gate return (err); 32637c478bd9Sstevel@tonic-gate } 32647c478bd9Sstevel@tonic-gate 32657c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_PHYSICAL, tabptr->zone_nwif_physical, 32667c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_nwif_physical))) != Z_OK) { 32677c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 32687c478bd9Sstevel@tonic-gate return (err); 32697c478bd9Sstevel@tonic-gate } 32707c478bd9Sstevel@tonic-gate 32717c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur->next; 32727c478bd9Sstevel@tonic-gate return (Z_OK); 32737c478bd9Sstevel@tonic-gate } 32747c478bd9Sstevel@tonic-gate 32757c478bd9Sstevel@tonic-gate int 32767c478bd9Sstevel@tonic-gate zonecfg_endnwifent(zone_dochandle_t handle) 32777c478bd9Sstevel@tonic-gate { 32787c478bd9Sstevel@tonic-gate return (zonecfg_endent(handle)); 32797c478bd9Sstevel@tonic-gate } 32807c478bd9Sstevel@tonic-gate 32817c478bd9Sstevel@tonic-gate int 32827c478bd9Sstevel@tonic-gate zonecfg_setdevent(zone_dochandle_t handle) 32837c478bd9Sstevel@tonic-gate { 32847c478bd9Sstevel@tonic-gate return (zonecfg_setent(handle)); 32857c478bd9Sstevel@tonic-gate } 32867c478bd9Sstevel@tonic-gate 32877c478bd9Sstevel@tonic-gate int 32887c478bd9Sstevel@tonic-gate zonecfg_getdevent(zone_dochandle_t handle, struct zone_devtab *tabptr) 32897c478bd9Sstevel@tonic-gate { 32907c478bd9Sstevel@tonic-gate xmlNodePtr cur; 32917c478bd9Sstevel@tonic-gate int err; 32927c478bd9Sstevel@tonic-gate 32937c478bd9Sstevel@tonic-gate if (handle == NULL) 32947c478bd9Sstevel@tonic-gate return (Z_INVAL); 32957c478bd9Sstevel@tonic-gate 32967c478bd9Sstevel@tonic-gate if ((cur = handle->zone_dh_cur) == NULL) 32977c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 32987c478bd9Sstevel@tonic-gate 32997c478bd9Sstevel@tonic-gate for (; cur != NULL; cur = cur->next) 33007c478bd9Sstevel@tonic-gate if (!xmlStrcmp(cur->name, DTD_ELEM_DEVICE)) 33017c478bd9Sstevel@tonic-gate break; 33027c478bd9Sstevel@tonic-gate if (cur == NULL) { 33037c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 33047c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 33057c478bd9Sstevel@tonic-gate } 33067c478bd9Sstevel@tonic-gate 33077c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_MATCH, tabptr->zone_dev_match, 33087c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_dev_match))) != Z_OK) { 33097c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 33107c478bd9Sstevel@tonic-gate return (err); 33117c478bd9Sstevel@tonic-gate } 33127c478bd9Sstevel@tonic-gate 33137c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur->next; 33147c478bd9Sstevel@tonic-gate return (Z_OK); 33157c478bd9Sstevel@tonic-gate } 33167c478bd9Sstevel@tonic-gate 33177c478bd9Sstevel@tonic-gate int 33187c478bd9Sstevel@tonic-gate zonecfg_enddevent(zone_dochandle_t handle) 33197c478bd9Sstevel@tonic-gate { 33207c478bd9Sstevel@tonic-gate return (zonecfg_endent(handle)); 33217c478bd9Sstevel@tonic-gate } 33227c478bd9Sstevel@tonic-gate 33237c478bd9Sstevel@tonic-gate int 33247c478bd9Sstevel@tonic-gate zonecfg_setrctlent(zone_dochandle_t handle) 33257c478bd9Sstevel@tonic-gate { 33267c478bd9Sstevel@tonic-gate return (zonecfg_setent(handle)); 33277c478bd9Sstevel@tonic-gate } 33287c478bd9Sstevel@tonic-gate 33297c478bd9Sstevel@tonic-gate int 33307c478bd9Sstevel@tonic-gate zonecfg_getrctlent(zone_dochandle_t handle, struct zone_rctltab *tabptr) 33317c478bd9Sstevel@tonic-gate { 33327c478bd9Sstevel@tonic-gate xmlNodePtr cur, val; 33337c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *valptr; 33347c478bd9Sstevel@tonic-gate int err; 33357c478bd9Sstevel@tonic-gate 33367c478bd9Sstevel@tonic-gate if (handle == NULL) 33377c478bd9Sstevel@tonic-gate return (Z_INVAL); 33387c478bd9Sstevel@tonic-gate 33397c478bd9Sstevel@tonic-gate if ((cur = handle->zone_dh_cur) == NULL) 33407c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 33417c478bd9Sstevel@tonic-gate 33427c478bd9Sstevel@tonic-gate for (; cur != NULL; cur = cur->next) 33437c478bd9Sstevel@tonic-gate if (!xmlStrcmp(cur->name, DTD_ELEM_RCTL)) 33447c478bd9Sstevel@tonic-gate break; 33457c478bd9Sstevel@tonic-gate if (cur == NULL) { 33467c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 33477c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 33487c478bd9Sstevel@tonic-gate } 33497c478bd9Sstevel@tonic-gate 33507c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_NAME, tabptr->zone_rctl_name, 33517c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_rctl_name))) != Z_OK) { 33527c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 33537c478bd9Sstevel@tonic-gate return (err); 33547c478bd9Sstevel@tonic-gate } 33557c478bd9Sstevel@tonic-gate 33567c478bd9Sstevel@tonic-gate tabptr->zone_rctl_valptr = NULL; 33577c478bd9Sstevel@tonic-gate for (val = cur->xmlChildrenNode; val != NULL; val = val->next) { 33587c478bd9Sstevel@tonic-gate valptr = (struct zone_rctlvaltab *)malloc( 33597c478bd9Sstevel@tonic-gate sizeof (struct zone_rctlvaltab)); 33607c478bd9Sstevel@tonic-gate if (valptr == NULL) 33617c478bd9Sstevel@tonic-gate return (Z_NOMEM); 33627c478bd9Sstevel@tonic-gate if (fetchprop(val, DTD_ATTR_PRIV, valptr->zone_rctlval_priv, 33637c478bd9Sstevel@tonic-gate sizeof (valptr->zone_rctlval_priv)) != Z_OK) 33647c478bd9Sstevel@tonic-gate break; 33657c478bd9Sstevel@tonic-gate if (fetchprop(val, DTD_ATTR_LIMIT, valptr->zone_rctlval_limit, 33667c478bd9Sstevel@tonic-gate sizeof (valptr->zone_rctlval_limit)) != Z_OK) 33677c478bd9Sstevel@tonic-gate break; 33687c478bd9Sstevel@tonic-gate if (fetchprop(val, DTD_ATTR_ACTION, valptr->zone_rctlval_action, 33697c478bd9Sstevel@tonic-gate sizeof (valptr->zone_rctlval_action)) != Z_OK) 33707c478bd9Sstevel@tonic-gate break; 33717c478bd9Sstevel@tonic-gate if (zonecfg_add_rctl_value(tabptr, valptr) != Z_OK) 33727c478bd9Sstevel@tonic-gate break; 33737c478bd9Sstevel@tonic-gate } 33747c478bd9Sstevel@tonic-gate 33757c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur->next; 33767c478bd9Sstevel@tonic-gate return (Z_OK); 33777c478bd9Sstevel@tonic-gate } 33787c478bd9Sstevel@tonic-gate 33797c478bd9Sstevel@tonic-gate int 33807c478bd9Sstevel@tonic-gate zonecfg_endrctlent(zone_dochandle_t handle) 33817c478bd9Sstevel@tonic-gate { 33827c478bd9Sstevel@tonic-gate return (zonecfg_endent(handle)); 33837c478bd9Sstevel@tonic-gate } 33847c478bd9Sstevel@tonic-gate 33857c478bd9Sstevel@tonic-gate int 33867c478bd9Sstevel@tonic-gate zonecfg_setattrent(zone_dochandle_t handle) 33877c478bd9Sstevel@tonic-gate { 33887c478bd9Sstevel@tonic-gate return (zonecfg_setent(handle)); 33897c478bd9Sstevel@tonic-gate } 33907c478bd9Sstevel@tonic-gate 33917c478bd9Sstevel@tonic-gate int 33927c478bd9Sstevel@tonic-gate zonecfg_getattrent(zone_dochandle_t handle, struct zone_attrtab *tabptr) 33937c478bd9Sstevel@tonic-gate { 33947c478bd9Sstevel@tonic-gate xmlNodePtr cur; 33957c478bd9Sstevel@tonic-gate int err; 33967c478bd9Sstevel@tonic-gate 33977c478bd9Sstevel@tonic-gate if (handle == NULL) 33987c478bd9Sstevel@tonic-gate return (Z_INVAL); 33997c478bd9Sstevel@tonic-gate 34007c478bd9Sstevel@tonic-gate if ((cur = handle->zone_dh_cur) == NULL) 34017c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 34027c478bd9Sstevel@tonic-gate 34037c478bd9Sstevel@tonic-gate for (; cur != NULL; cur = cur->next) 34047c478bd9Sstevel@tonic-gate if (!xmlStrcmp(cur->name, DTD_ELEM_ATTR)) 34057c478bd9Sstevel@tonic-gate break; 34067c478bd9Sstevel@tonic-gate if (cur == NULL) { 34077c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 34087c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 34097c478bd9Sstevel@tonic-gate } 34107c478bd9Sstevel@tonic-gate 34117c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_NAME, tabptr->zone_attr_name, 34127c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_attr_name))) != Z_OK) { 34137c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 34147c478bd9Sstevel@tonic-gate return (err); 34157c478bd9Sstevel@tonic-gate } 34167c478bd9Sstevel@tonic-gate 34177c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_TYPE, tabptr->zone_attr_type, 34187c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_attr_type))) != Z_OK) { 34197c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 34207c478bd9Sstevel@tonic-gate return (err); 34217c478bd9Sstevel@tonic-gate } 34227c478bd9Sstevel@tonic-gate 34237c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_VALUE, tabptr->zone_attr_value, 34247c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_attr_value))) != Z_OK) { 34257c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 34267c478bd9Sstevel@tonic-gate return (err); 34277c478bd9Sstevel@tonic-gate } 34287c478bd9Sstevel@tonic-gate 34297c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur->next; 34307c478bd9Sstevel@tonic-gate return (Z_OK); 34317c478bd9Sstevel@tonic-gate } 34327c478bd9Sstevel@tonic-gate 34337c478bd9Sstevel@tonic-gate int 34347c478bd9Sstevel@tonic-gate zonecfg_endattrent(zone_dochandle_t handle) 34357c478bd9Sstevel@tonic-gate { 34367c478bd9Sstevel@tonic-gate return (zonecfg_endent(handle)); 34377c478bd9Sstevel@tonic-gate } 34387c478bd9Sstevel@tonic-gate 3439ffbafc53Scomay /* 3440ffbafc53Scomay * The privileges available on the system and described in privileges(5) 3441ffbafc53Scomay * fall into four categories with respect to non-global zones; those that 3442ffbafc53Scomay * are required in order for a non-global zone to boot, those which are in 3443ffbafc53Scomay * the default set of privileges available to non-global zones, those 3444ffbafc53Scomay * privileges which should not be allowed to be given to non-global zones 3445ffbafc53Scomay * and all other privileges, which are optional and potentially useful for 3446ffbafc53Scomay * processes executing inside a non-global zone. 3447ffbafc53Scomay * 3448ffbafc53Scomay * When privileges are added to the system, a determination needs to be 3449ffbafc53Scomay * made as to which category the privilege belongs to. Ideally, 3450ffbafc53Scomay * privileges should be fine-grained enough and the mechanisms they cover 3451ffbafc53Scomay * virtualized enough so that they can be made available to non-global 3452ffbafc53Scomay * zones. 3453ffbafc53Scomay */ 3454ffbafc53Scomay 3455ffbafc53Scomay /* 3456ffbafc53Scomay * Set of privileges required in order to get a zone booted and init(1M) 3457ffbafc53Scomay * started. These cannot be removed from the zone's privilege set. 3458ffbafc53Scomay */ 3459ffbafc53Scomay static const char *required_priv_list[] = { 3460ffbafc53Scomay PRIV_PROC_EXEC, 3461ffbafc53Scomay PRIV_PROC_FORK, 3462ffbafc53Scomay PRIV_SYS_MOUNT, 3463ffbafc53Scomay NULL 3464ffbafc53Scomay }; 3465ffbafc53Scomay 3466ffbafc53Scomay /* 3467ffbafc53Scomay * Default set of privileges considered safe for all non-global zones. 3468ffbafc53Scomay * These privileges are "safe" in the sense that a privileged process in 3469ffbafc53Scomay * the zone cannot affect processes in other non-global zones on the 3470ffbafc53Scomay * system or in the global zone. Privileges which are considered by 3471ffbafc53Scomay * default, "unsafe", include ones which affect a global resource, such as 3472ffbafc53Scomay * the system clock or physical memory. 3473ffbafc53Scomay */ 3474ffbafc53Scomay static const char *default_priv_list[] = { 3475ffbafc53Scomay PRIV_CONTRACT_EVENT, 3476ffbafc53Scomay PRIV_CONTRACT_OBSERVER, 34777c478bd9Sstevel@tonic-gate PRIV_FILE_CHOWN, 34787c478bd9Sstevel@tonic-gate PRIV_FILE_CHOWN_SELF, 34797c478bd9Sstevel@tonic-gate PRIV_FILE_DAC_EXECUTE, 34807c478bd9Sstevel@tonic-gate PRIV_FILE_DAC_READ, 34817c478bd9Sstevel@tonic-gate PRIV_FILE_DAC_SEARCH, 34827c478bd9Sstevel@tonic-gate PRIV_FILE_DAC_WRITE, 34837c478bd9Sstevel@tonic-gate PRIV_FILE_OWNER, 34847c478bd9Sstevel@tonic-gate PRIV_FILE_SETID, 34857c478bd9Sstevel@tonic-gate PRIV_IPC_DAC_READ, 34867c478bd9Sstevel@tonic-gate PRIV_IPC_DAC_WRITE, 34877c478bd9Sstevel@tonic-gate PRIV_IPC_OWNER, 348845916cd2Sjpk PRIV_NET_BINDMLP, 34897c478bd9Sstevel@tonic-gate PRIV_NET_ICMPACCESS, 349045916cd2Sjpk PRIV_NET_MAC_AWARE, 34917c478bd9Sstevel@tonic-gate PRIV_NET_PRIVADDR, 34927c478bd9Sstevel@tonic-gate PRIV_PROC_CHROOT, 34937c478bd9Sstevel@tonic-gate PRIV_SYS_AUDIT, 34947c478bd9Sstevel@tonic-gate PRIV_PROC_AUDIT, 34957c478bd9Sstevel@tonic-gate PRIV_PROC_OWNER, 34967c478bd9Sstevel@tonic-gate PRIV_PROC_SETID, 34977c478bd9Sstevel@tonic-gate PRIV_PROC_TASKID, 34987c478bd9Sstevel@tonic-gate PRIV_SYS_ACCT, 34997c478bd9Sstevel@tonic-gate PRIV_SYS_ADMIN, 35007c478bd9Sstevel@tonic-gate PRIV_SYS_MOUNT, 35017c478bd9Sstevel@tonic-gate PRIV_SYS_NFS, 35027c478bd9Sstevel@tonic-gate PRIV_SYS_RESOURCE, 35037c478bd9Sstevel@tonic-gate NULL 35047c478bd9Sstevel@tonic-gate }; 35057c478bd9Sstevel@tonic-gate 3506ffbafc53Scomay /* 3507ffbafc53Scomay * Set of privileges not currently permitted within a non-global zone. 3508ffbafc53Scomay * Some of these privileges are overly broad and cover more than one 3509ffbafc53Scomay * mechanism in the system. In other cases, there has not been sufficient 3510ffbafc53Scomay * virtualization in the parts of the system the privilege covers to allow 3511ffbafc53Scomay * its use within a non-global zone. 3512ffbafc53Scomay */ 3513ffbafc53Scomay static const char *prohibited_priv_list[] = { 3514ffbafc53Scomay PRIV_DTRACE_KERNEL, 3515ffbafc53Scomay PRIV_PROC_ZONE, 3516ffbafc53Scomay PRIV_SYS_CONFIG, 3517ffbafc53Scomay PRIV_SYS_DEVICES, 3518ffbafc53Scomay PRIV_SYS_LINKDIR, 3519ffbafc53Scomay PRIV_SYS_NET_CONFIG, 3520ffbafc53Scomay PRIV_SYS_RES_CONFIG, 3521ffbafc53Scomay PRIV_SYS_SUSER_COMPAT, 3522ffbafc53Scomay NULL 3523ffbafc53Scomay }; 3524ffbafc53Scomay 3525ffbafc53Scomay /* 3526ffbafc53Scomay * Define some of the tokens that priv_str_to_set(3C) recognizes. Since 3527ffbafc53Scomay * the privilege string separator can be any character, although it is 3528ffbafc53Scomay * usually a comma character, define these here as well in the event that 3529ffbafc53Scomay * they change or are augmented in the future. 3530ffbafc53Scomay */ 3531ffbafc53Scomay #define BASIC_TOKEN "basic" 3532ffbafc53Scomay #define DEFAULT_TOKEN "default" 3533ffbafc53Scomay #define ZONE_TOKEN "zone" 3534ffbafc53Scomay #define TOKEN_PRIV_CHAR ',' 3535ffbafc53Scomay #define TOKEN_PRIV_STR "," 3536ffbafc53Scomay 35377c478bd9Sstevel@tonic-gate int 3538ffbafc53Scomay zonecfg_default_privset(priv_set_t *privs) 35397c478bd9Sstevel@tonic-gate { 35407c478bd9Sstevel@tonic-gate const char **strp; 3541ffbafc53Scomay priv_set_t *basic; 35427c478bd9Sstevel@tonic-gate 3543ffbafc53Scomay basic = priv_str_to_set(BASIC_TOKEN, TOKEN_PRIV_STR, NULL); 35447c478bd9Sstevel@tonic-gate if (basic == NULL) 3545ffbafc53Scomay return (errno == ENOMEM ? Z_NOMEM : Z_INVAL); 35467c478bd9Sstevel@tonic-gate 35477c478bd9Sstevel@tonic-gate priv_union(basic, privs); 35487c478bd9Sstevel@tonic-gate priv_freeset(basic); 35497c478bd9Sstevel@tonic-gate 3550ffbafc53Scomay for (strp = default_priv_list; *strp != NULL; strp++) { 35517c478bd9Sstevel@tonic-gate if (priv_addset(privs, *strp) != 0) { 35527c478bd9Sstevel@tonic-gate return (Z_INVAL); 35537c478bd9Sstevel@tonic-gate } 35547c478bd9Sstevel@tonic-gate } 35557c478bd9Sstevel@tonic-gate return (Z_OK); 35567c478bd9Sstevel@tonic-gate } 35577c478bd9Sstevel@tonic-gate 3558ffbafc53Scomay void 3559ffbafc53Scomay append_priv_token(char *priv, char *str, size_t strlen) 3560ffbafc53Scomay { 3561ffbafc53Scomay if (*str != '\0') 3562ffbafc53Scomay (void) strlcat(str, TOKEN_PRIV_STR, strlen); 3563ffbafc53Scomay (void) strlcat(str, priv, strlen); 3564ffbafc53Scomay } 3565ffbafc53Scomay 3566ffbafc53Scomay /* 3567ffbafc53Scomay * Verify that the supplied string is a valid privilege limit set for a 3568ffbafc53Scomay * non-global zone. This string must not only be acceptable to 3569ffbafc53Scomay * priv_str_to_set(3C) which parses it, but it also must resolve to a 3570ffbafc53Scomay * privilege set that includes certain required privileges and lacks 3571ffbafc53Scomay * certain prohibited privileges. 3572ffbafc53Scomay */ 3573ffbafc53Scomay static int 3574ffbafc53Scomay verify_privset(char *privbuf, priv_set_t *privs, char **privname, 3575ffbafc53Scomay boolean_t add_default) 3576ffbafc53Scomay { 3577ffbafc53Scomay char *cp; 3578ffbafc53Scomay char *lasts; 3579ffbafc53Scomay size_t len; 3580ffbafc53Scomay priv_set_t *mergeset; 3581ffbafc53Scomay const char **strp; 3582ffbafc53Scomay char *tmp; 3583ffbafc53Scomay const char *token; 3584ffbafc53Scomay 3585ffbafc53Scomay /* 3586ffbafc53Scomay * The verification of the privilege string occurs in several 3587ffbafc53Scomay * phases. In the first phase, the supplied string is scanned for 3588ffbafc53Scomay * the ZONE_TOKEN token which is not support as part of the 3589ffbafc53Scomay * "limitpriv" property. 3590ffbafc53Scomay * 3591ffbafc53Scomay * Duplicate the supplied privilege string since strtok_r(3C) 3592ffbafc53Scomay * tokenizes its input by null-terminating the tokens. 3593ffbafc53Scomay */ 3594ffbafc53Scomay if ((tmp = strdup(privbuf)) == NULL) 3595ffbafc53Scomay return (Z_NOMEM); 3596ffbafc53Scomay for (cp = strtok_r(tmp, TOKEN_PRIV_STR, &lasts); cp != NULL; 3597ffbafc53Scomay cp = strtok_r(NULL, TOKEN_PRIV_STR, &lasts)) { 3598ffbafc53Scomay if (strcmp(cp, ZONE_TOKEN) == 0) { 3599ffbafc53Scomay free(tmp); 3600ffbafc53Scomay if ((*privname = strdup(ZONE_TOKEN)) == NULL) 3601ffbafc53Scomay return (Z_NOMEM); 3602ffbafc53Scomay else 3603ffbafc53Scomay return (Z_PRIV_UNKNOWN); 3604ffbafc53Scomay } 3605ffbafc53Scomay } 3606ffbafc53Scomay free(tmp); 3607ffbafc53Scomay 3608ffbafc53Scomay if (add_default) { 3609ffbafc53Scomay /* 3610ffbafc53Scomay * If DEFAULT_TOKEN was specified, a string needs to be 3611ffbafc53Scomay * built containing the privileges from the default, safe 3612ffbafc53Scomay * set along with those of the "limitpriv" property. 3613ffbafc53Scomay */ 3614ffbafc53Scomay len = strlen(privbuf) + sizeof (BASIC_TOKEN) + 2; 3615ffbafc53Scomay for (strp = default_priv_list; *strp != NULL; strp++) 3616ffbafc53Scomay len += strlen(*strp) + 1; 3617ffbafc53Scomay tmp = alloca(len); 3618ffbafc53Scomay *tmp = '\0'; 3619ffbafc53Scomay 3620ffbafc53Scomay append_priv_token(BASIC_TOKEN, tmp, len); 3621ffbafc53Scomay for (strp = default_priv_list; *strp != NULL; strp++) 3622ffbafc53Scomay append_priv_token((char *)*strp, tmp, len); 3623ffbafc53Scomay (void) strlcat(tmp, TOKEN_PRIV_STR, len); 3624ffbafc53Scomay (void) strlcat(tmp, privbuf, len); 3625ffbafc53Scomay } else { 3626ffbafc53Scomay tmp = privbuf; 3627ffbafc53Scomay } 3628ffbafc53Scomay 3629ffbafc53Scomay 3630ffbafc53Scomay /* 3631ffbafc53Scomay * In the next phase, attempt to convert the merged privilege 3632ffbafc53Scomay * string into a privilege set. In the case of an error, either 3633ffbafc53Scomay * there was a memory allocation failure or there was an invalid 3634ffbafc53Scomay * privilege token in the string. In either case, return an 3635ffbafc53Scomay * appropriate error code but in the event of an invalid token, 3636ffbafc53Scomay * allocate a string containing its name and return that back to 3637ffbafc53Scomay * the caller. 3638ffbafc53Scomay */ 3639ffbafc53Scomay mergeset = priv_str_to_set(tmp, TOKEN_PRIV_STR, &token); 3640ffbafc53Scomay if (mergeset == NULL) { 3641ffbafc53Scomay if (token == NULL) 3642ffbafc53Scomay return (Z_NOMEM); 3643ffbafc53Scomay if ((cp = strchr(token, TOKEN_PRIV_CHAR)) != NULL) 3644ffbafc53Scomay *cp = '\0'; 3645ffbafc53Scomay if ((*privname = strdup(token)) == NULL) 3646ffbafc53Scomay return (Z_NOMEM); 3647ffbafc53Scomay else 3648ffbafc53Scomay return (Z_PRIV_UNKNOWN); 3649ffbafc53Scomay } 3650ffbafc53Scomay 3651ffbafc53Scomay /* 3652ffbafc53Scomay * Next, verify that none of the prohibited zone privileges are 3653ffbafc53Scomay * present in the merged privilege set. 3654ffbafc53Scomay */ 3655ffbafc53Scomay for (strp = prohibited_priv_list; *strp != NULL; strp++) { 3656ffbafc53Scomay if (priv_ismember(mergeset, *strp)) { 3657ffbafc53Scomay priv_freeset(mergeset); 3658ffbafc53Scomay if ((*privname = strdup(*strp)) == NULL) 3659ffbafc53Scomay return (Z_NOMEM); 3660ffbafc53Scomay else 3661ffbafc53Scomay return (Z_PRIV_PROHIBITED); 3662ffbafc53Scomay } 3663ffbafc53Scomay } 3664ffbafc53Scomay 3665ffbafc53Scomay /* 3666ffbafc53Scomay * Finally, verify that all of the required zone privileges are 3667ffbafc53Scomay * present in the merged privilege set. 3668ffbafc53Scomay */ 3669ffbafc53Scomay for (strp = required_priv_list; *strp != NULL; strp++) { 3670ffbafc53Scomay if (!priv_ismember(mergeset, *strp)) { 3671ffbafc53Scomay priv_freeset(mergeset); 3672ffbafc53Scomay if ((*privname = strdup(*strp)) == NULL) 3673ffbafc53Scomay return (Z_NOMEM); 3674ffbafc53Scomay else 3675ffbafc53Scomay return (Z_PRIV_REQUIRED); 3676ffbafc53Scomay } 3677ffbafc53Scomay } 3678ffbafc53Scomay 3679ffbafc53Scomay priv_copyset(mergeset, privs); 3680ffbafc53Scomay priv_freeset(mergeset); 3681ffbafc53Scomay return (Z_OK); 3682ffbafc53Scomay } 3683ffbafc53Scomay 3684ffbafc53Scomay /* 3685ffbafc53Scomay * Fill in the supplied privilege set with either the default, safe set of 3686ffbafc53Scomay * privileges suitable for a non-global zone, or one based on the 3687ffbafc53Scomay * "limitpriv" property in the zone's configuration. 3688ffbafc53Scomay * 3689ffbafc53Scomay * In the event of an invalid privilege specification in the 3690ffbafc53Scomay * configuration, a string is allocated and returned containing the 3691ffbafc53Scomay * "privilege" causing the issue. It is the caller's responsibility to 3692ffbafc53Scomay * free this memory when it is done with it. 3693ffbafc53Scomay */ 3694ffbafc53Scomay int 3695ffbafc53Scomay zonecfg_get_privset(zone_dochandle_t handle, priv_set_t *privs, 3696ffbafc53Scomay char **privname) 3697ffbafc53Scomay { 3698ffbafc53Scomay char *cp; 3699ffbafc53Scomay int err; 3700ffbafc53Scomay int limitlen; 3701ffbafc53Scomay char *limitpriv = NULL; 3702ffbafc53Scomay 3703ffbafc53Scomay /* 3704ffbafc53Scomay * Attempt to lookup the "limitpriv" property. If it does not 3705ffbafc53Scomay * exist or matches the string DEFAULT_TOKEN exactly, then the 3706ffbafc53Scomay * default, safe privilege set is returned. 3707ffbafc53Scomay */ 3708ffbafc53Scomay err = zonecfg_get_limitpriv(handle, &limitpriv); 3709ffbafc53Scomay if (err != Z_OK) 3710ffbafc53Scomay return (err); 3711ffbafc53Scomay limitlen = strlen(limitpriv); 3712ffbafc53Scomay if (limitlen == 0 || strcmp(limitpriv, DEFAULT_TOKEN) == 0) { 3713ffbafc53Scomay free(limitpriv); 3714ffbafc53Scomay return (zonecfg_default_privset(privs)); 3715ffbafc53Scomay } 3716ffbafc53Scomay 3717ffbafc53Scomay /* 3718ffbafc53Scomay * Check if the string DEFAULT_TOKEN is the first token in a list 3719ffbafc53Scomay * of privileges. 3720ffbafc53Scomay */ 3721ffbafc53Scomay cp = strchr(limitpriv, TOKEN_PRIV_CHAR); 3722ffbafc53Scomay if (cp != NULL && 3723ffbafc53Scomay strncmp(limitpriv, DEFAULT_TOKEN, cp - limitpriv) == 0) 3724ffbafc53Scomay err = verify_privset(cp + 1, privs, privname, B_TRUE); 3725ffbafc53Scomay else 3726ffbafc53Scomay err = verify_privset(limitpriv, privs, privname, B_FALSE); 3727ffbafc53Scomay 3728ffbafc53Scomay free(limitpriv); 3729ffbafc53Scomay return (err); 3730ffbafc53Scomay } 3731ffbafc53Scomay 37327c478bd9Sstevel@tonic-gate int 37337c478bd9Sstevel@tonic-gate zone_get_zonepath(char *zone_name, char *zonepath, size_t rp_sz) 37347c478bd9Sstevel@tonic-gate { 37357c478bd9Sstevel@tonic-gate zone_dochandle_t handle; 37367c478bd9Sstevel@tonic-gate boolean_t found = B_FALSE; 37377c478bd9Sstevel@tonic-gate struct zoneent *ze; 37387c478bd9Sstevel@tonic-gate FILE *cookie; 37397c478bd9Sstevel@tonic-gate int err; 3740108322fbScarlsonj char *cp; 37417c478bd9Sstevel@tonic-gate 37427c478bd9Sstevel@tonic-gate if (zone_name == NULL) 37437c478bd9Sstevel@tonic-gate return (Z_INVAL); 37447c478bd9Sstevel@tonic-gate 3745108322fbScarlsonj (void) strlcpy(zonepath, zonecfg_root, rp_sz); 3746108322fbScarlsonj cp = zonepath + strlen(zonepath); 3747108322fbScarlsonj while (cp > zonepath && cp[-1] == '/') 3748108322fbScarlsonj *--cp = '\0'; 3749108322fbScarlsonj 37507c478bd9Sstevel@tonic-gate if (strcmp(zone_name, GLOBAL_ZONENAME) == 0) { 3751108322fbScarlsonj if (zonepath[0] == '\0') 3752108322fbScarlsonj (void) strlcpy(zonepath, "/", rp_sz); 37537c478bd9Sstevel@tonic-gate return (Z_OK); 37547c478bd9Sstevel@tonic-gate } 37557c478bd9Sstevel@tonic-gate 37567c478bd9Sstevel@tonic-gate /* 37577c478bd9Sstevel@tonic-gate * First check the index file. Because older versions did not have 37587c478bd9Sstevel@tonic-gate * a copy of the zone path, allow for it to be zero length, in which 37597c478bd9Sstevel@tonic-gate * case we ignore this result and fall back to the XML files. 37607c478bd9Sstevel@tonic-gate */ 37617c478bd9Sstevel@tonic-gate cookie = setzoneent(); 37627c478bd9Sstevel@tonic-gate while ((ze = getzoneent_private(cookie)) != NULL) { 37637c478bd9Sstevel@tonic-gate if (strcmp(ze->zone_name, zone_name) == 0) { 37647c478bd9Sstevel@tonic-gate found = B_TRUE; 3765108322fbScarlsonj if (ze->zone_path[0] != '\0') 3766108322fbScarlsonj (void) strlcpy(cp, ze->zone_path, 3767108322fbScarlsonj rp_sz - (cp - zonepath)); 37687c478bd9Sstevel@tonic-gate } 37697c478bd9Sstevel@tonic-gate free(ze); 37707c478bd9Sstevel@tonic-gate if (found) 37717c478bd9Sstevel@tonic-gate break; 37727c478bd9Sstevel@tonic-gate } 37737c478bd9Sstevel@tonic-gate endzoneent(cookie); 3774108322fbScarlsonj if (found && *cp != '\0') 37757c478bd9Sstevel@tonic-gate return (Z_OK); 37767c478bd9Sstevel@tonic-gate 37777c478bd9Sstevel@tonic-gate /* Fall back to the XML files. */ 37787c478bd9Sstevel@tonic-gate if ((handle = zonecfg_init_handle()) == NULL) 37797c478bd9Sstevel@tonic-gate return (Z_NOMEM); 37807c478bd9Sstevel@tonic-gate 37817c478bd9Sstevel@tonic-gate /* 37827c478bd9Sstevel@tonic-gate * Check the snapshot first: if a zone is running, its zonepath 37837c478bd9Sstevel@tonic-gate * may have changed. 37847c478bd9Sstevel@tonic-gate */ 37857c478bd9Sstevel@tonic-gate if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) { 37867c478bd9Sstevel@tonic-gate if ((err = zonecfg_get_handle(zone_name, handle)) != Z_OK) 37877c478bd9Sstevel@tonic-gate return (err); 37887c478bd9Sstevel@tonic-gate } 37897c478bd9Sstevel@tonic-gate err = zonecfg_get_zonepath(handle, zonepath, rp_sz); 37907c478bd9Sstevel@tonic-gate zonecfg_fini_handle(handle); 37917c478bd9Sstevel@tonic-gate return (err); 37927c478bd9Sstevel@tonic-gate } 37937c478bd9Sstevel@tonic-gate 37947c478bd9Sstevel@tonic-gate int 37957c478bd9Sstevel@tonic-gate zone_get_rootpath(char *zone_name, char *rootpath, size_t rp_sz) 37967c478bd9Sstevel@tonic-gate { 37977c478bd9Sstevel@tonic-gate int err; 37987c478bd9Sstevel@tonic-gate 37997c478bd9Sstevel@tonic-gate /* This function makes sense for non-global zones only. */ 38007c478bd9Sstevel@tonic-gate if (strcmp(zone_name, GLOBAL_ZONENAME) == 0) 38017c478bd9Sstevel@tonic-gate return (Z_BOGUS_ZONE_NAME); 38027c478bd9Sstevel@tonic-gate if ((err = zone_get_zonepath(zone_name, rootpath, rp_sz)) != Z_OK) 38037c478bd9Sstevel@tonic-gate return (err); 38047c478bd9Sstevel@tonic-gate if (strlcat(rootpath, "/root", rp_sz) >= rp_sz) 38057c478bd9Sstevel@tonic-gate return (Z_TOO_BIG); 38067c478bd9Sstevel@tonic-gate return (Z_OK); 38077c478bd9Sstevel@tonic-gate } 38087c478bd9Sstevel@tonic-gate 38097c478bd9Sstevel@tonic-gate static zone_state_t 3810108322fbScarlsonj kernel_state_to_user_state(zoneid_t zoneid, zone_status_t kernel_state) 38117c478bd9Sstevel@tonic-gate { 3812108322fbScarlsonj char zoneroot[MAXPATHLEN]; 3813108322fbScarlsonj size_t zlen; 3814108322fbScarlsonj 38157c478bd9Sstevel@tonic-gate assert(kernel_state <= ZONE_MAX_STATE); 38167c478bd9Sstevel@tonic-gate switch (kernel_state) { 38177c478bd9Sstevel@tonic-gate case ZONE_IS_UNINITIALIZED: 3818108322fbScarlsonj return (ZONE_STATE_READY); 38197c478bd9Sstevel@tonic-gate case ZONE_IS_READY: 3820108322fbScarlsonj /* 3821108322fbScarlsonj * If the zone's root is mounted on $ZONEPATH/lu, then 3822108322fbScarlsonj * it's a mounted scratch zone. 3823108322fbScarlsonj */ 3824108322fbScarlsonj if (zone_getattr(zoneid, ZONE_ATTR_ROOT, zoneroot, 3825108322fbScarlsonj sizeof (zoneroot)) >= 0) { 3826108322fbScarlsonj zlen = strlen(zoneroot); 3827108322fbScarlsonj if (zlen > 3 && 3828108322fbScarlsonj strcmp(zoneroot + zlen - 3, "/lu") == 0) 3829108322fbScarlsonj return (ZONE_STATE_MOUNTED); 3830108322fbScarlsonj } 38317c478bd9Sstevel@tonic-gate return (ZONE_STATE_READY); 38327c478bd9Sstevel@tonic-gate case ZONE_IS_BOOTING: 38337c478bd9Sstevel@tonic-gate case ZONE_IS_RUNNING: 38347c478bd9Sstevel@tonic-gate return (ZONE_STATE_RUNNING); 38357c478bd9Sstevel@tonic-gate case ZONE_IS_SHUTTING_DOWN: 38367c478bd9Sstevel@tonic-gate case ZONE_IS_EMPTY: 38377c478bd9Sstevel@tonic-gate return (ZONE_STATE_SHUTTING_DOWN); 38387c478bd9Sstevel@tonic-gate case ZONE_IS_DOWN: 38397c478bd9Sstevel@tonic-gate case ZONE_IS_DYING: 38407c478bd9Sstevel@tonic-gate case ZONE_IS_DEAD: 38417c478bd9Sstevel@tonic-gate default: 38427c478bd9Sstevel@tonic-gate return (ZONE_STATE_DOWN); 38437c478bd9Sstevel@tonic-gate } 38447c478bd9Sstevel@tonic-gate /* NOTREACHED */ 38457c478bd9Sstevel@tonic-gate } 38467c478bd9Sstevel@tonic-gate 38477c478bd9Sstevel@tonic-gate int 38487c478bd9Sstevel@tonic-gate zone_get_state(char *zone_name, zone_state_t *state_num) 38497c478bd9Sstevel@tonic-gate { 38507c478bd9Sstevel@tonic-gate zone_status_t status; 38517c478bd9Sstevel@tonic-gate zoneid_t zone_id; 38527c478bd9Sstevel@tonic-gate struct zoneent *ze; 38537c478bd9Sstevel@tonic-gate boolean_t found = B_FALSE; 38547c478bd9Sstevel@tonic-gate FILE *cookie; 3855108322fbScarlsonj char kernzone[ZONENAME_MAX]; 3856108322fbScarlsonj FILE *fp; 38577c478bd9Sstevel@tonic-gate 38587c478bd9Sstevel@tonic-gate if (zone_name == NULL) 38597c478bd9Sstevel@tonic-gate return (Z_INVAL); 38607c478bd9Sstevel@tonic-gate 3861108322fbScarlsonj /* 3862108322fbScarlsonj * If we're looking at an alternate root, then we need to query the 3863108322fbScarlsonj * kernel using the scratch zone name. 3864108322fbScarlsonj */ 3865108322fbScarlsonj zone_id = -1; 3866108322fbScarlsonj if (*zonecfg_root != '\0' && !zonecfg_is_scratch(zone_name)) { 3867108322fbScarlsonj if ((fp = zonecfg_open_scratch("", B_FALSE)) != NULL) { 3868108322fbScarlsonj if (zonecfg_find_scratch(fp, zone_name, zonecfg_root, 3869108322fbScarlsonj kernzone, sizeof (kernzone)) == 0) 3870108322fbScarlsonj zone_id = getzoneidbyname(kernzone); 3871108322fbScarlsonj zonecfg_close_scratch(fp); 3872108322fbScarlsonj } 3873108322fbScarlsonj } else { 3874108322fbScarlsonj zone_id = getzoneidbyname(zone_name); 3875108322fbScarlsonj } 3876108322fbScarlsonj 38777c478bd9Sstevel@tonic-gate /* check to see if zone is running */ 3878108322fbScarlsonj if (zone_id != -1 && 38797c478bd9Sstevel@tonic-gate zone_getattr(zone_id, ZONE_ATTR_STATUS, &status, 38807c478bd9Sstevel@tonic-gate sizeof (status)) >= 0) { 3881108322fbScarlsonj *state_num = kernel_state_to_user_state(zone_id, status); 38827c478bd9Sstevel@tonic-gate return (Z_OK); 38837c478bd9Sstevel@tonic-gate } 38847c478bd9Sstevel@tonic-gate 38857c478bd9Sstevel@tonic-gate cookie = setzoneent(); 38867c478bd9Sstevel@tonic-gate while ((ze = getzoneent_private(cookie)) != NULL) { 38877c478bd9Sstevel@tonic-gate if (strcmp(ze->zone_name, zone_name) == 0) { 38887c478bd9Sstevel@tonic-gate found = B_TRUE; 38897c478bd9Sstevel@tonic-gate *state_num = ze->zone_state; 38907c478bd9Sstevel@tonic-gate } 38917c478bd9Sstevel@tonic-gate free(ze); 38927c478bd9Sstevel@tonic-gate if (found) 38937c478bd9Sstevel@tonic-gate break; 38947c478bd9Sstevel@tonic-gate } 38957c478bd9Sstevel@tonic-gate endzoneent(cookie); 38967c478bd9Sstevel@tonic-gate return ((found) ? Z_OK : Z_NO_ZONE); 38977c478bd9Sstevel@tonic-gate } 38987c478bd9Sstevel@tonic-gate 38997c478bd9Sstevel@tonic-gate int 39007c478bd9Sstevel@tonic-gate zone_set_state(char *zone, zone_state_t state) 39017c478bd9Sstevel@tonic-gate { 39027c478bd9Sstevel@tonic-gate struct zoneent ze; 39037c478bd9Sstevel@tonic-gate 39047c478bd9Sstevel@tonic-gate if (state != ZONE_STATE_CONFIGURED && state != ZONE_STATE_INSTALLED && 39057c478bd9Sstevel@tonic-gate state != ZONE_STATE_INCOMPLETE) 39067c478bd9Sstevel@tonic-gate return (Z_INVAL); 39077c478bd9Sstevel@tonic-gate 3908087719fdSdp bzero(&ze, sizeof (ze)); 39097c478bd9Sstevel@tonic-gate (void) strlcpy(ze.zone_name, zone, sizeof (ze.zone_name)); 39107c478bd9Sstevel@tonic-gate ze.zone_state = state; 39117c478bd9Sstevel@tonic-gate (void) strlcpy(ze.zone_path, "", sizeof (ze.zone_path)); 39127c478bd9Sstevel@tonic-gate return (putzoneent(&ze, PZE_MODIFY)); 39137c478bd9Sstevel@tonic-gate } 39147c478bd9Sstevel@tonic-gate 39157c478bd9Sstevel@tonic-gate /* 39167c478bd9Sstevel@tonic-gate * Get id (if any) for specified zone. There are four possible outcomes: 39177c478bd9Sstevel@tonic-gate * - If the string corresponds to the numeric id of an active (booted) 39187c478bd9Sstevel@tonic-gate * zone, sets *zip to the zone id and returns 0. 39197c478bd9Sstevel@tonic-gate * - If the string corresponds to the name of an active (booted) zone, 39207c478bd9Sstevel@tonic-gate * sets *zip to the zone id and returns 0. 39217c478bd9Sstevel@tonic-gate * - If the string is a name in the configuration but is not booted, 39227c478bd9Sstevel@tonic-gate * sets *zip to ZONE_ID_UNDEFINED and returns 0. 39237c478bd9Sstevel@tonic-gate * - Otherwise, leaves *zip unchanged and returns -1. 39247c478bd9Sstevel@tonic-gate * 39257c478bd9Sstevel@tonic-gate * This function acts as an auxiliary filter on the function of the same 39267c478bd9Sstevel@tonic-gate * name in libc; the linker binds to this version if libzonecfg exists, 39277c478bd9Sstevel@tonic-gate * and the libc version if it doesn't. Any changes to this version of 39287c478bd9Sstevel@tonic-gate * the function should probably be reflected in the libc version as well. 39297c478bd9Sstevel@tonic-gate */ 39307c478bd9Sstevel@tonic-gate int 39317c478bd9Sstevel@tonic-gate zone_get_id(const char *str, zoneid_t *zip) 39327c478bd9Sstevel@tonic-gate { 39337c478bd9Sstevel@tonic-gate zone_dochandle_t hdl; 39347c478bd9Sstevel@tonic-gate zoneid_t zoneid; 39357c478bd9Sstevel@tonic-gate char *cp; 39367c478bd9Sstevel@tonic-gate int err; 39377c478bd9Sstevel@tonic-gate 39387c478bd9Sstevel@tonic-gate /* first try looking for active zone by id */ 39397c478bd9Sstevel@tonic-gate errno = 0; 39407c478bd9Sstevel@tonic-gate zoneid = (zoneid_t)strtol(str, &cp, 0); 39417c478bd9Sstevel@tonic-gate if (errno == 0 && cp != str && *cp == '\0' && 39427c478bd9Sstevel@tonic-gate getzonenamebyid(zoneid, NULL, 0) != -1) { 39437c478bd9Sstevel@tonic-gate *zip = zoneid; 39447c478bd9Sstevel@tonic-gate return (0); 39457c478bd9Sstevel@tonic-gate } 39467c478bd9Sstevel@tonic-gate 39477c478bd9Sstevel@tonic-gate /* then look for active zone by name */ 39487c478bd9Sstevel@tonic-gate if ((zoneid = getzoneidbyname(str)) != -1) { 39497c478bd9Sstevel@tonic-gate *zip = zoneid; 39507c478bd9Sstevel@tonic-gate return (0); 39517c478bd9Sstevel@tonic-gate } 39527c478bd9Sstevel@tonic-gate 39537c478bd9Sstevel@tonic-gate /* if in global zone, try looking up name in configuration database */ 39547c478bd9Sstevel@tonic-gate if (getzoneid() != GLOBAL_ZONEID || 39557c478bd9Sstevel@tonic-gate (hdl = zonecfg_init_handle()) == NULL) 39567c478bd9Sstevel@tonic-gate return (-1); 39577c478bd9Sstevel@tonic-gate 3958108322fbScarlsonj if (zonecfg_get_handle(str, hdl) == Z_OK) { 39597c478bd9Sstevel@tonic-gate /* zone exists but isn't active */ 39607c478bd9Sstevel@tonic-gate *zip = ZONE_ID_UNDEFINED; 39617c478bd9Sstevel@tonic-gate err = 0; 39627c478bd9Sstevel@tonic-gate } else { 39637c478bd9Sstevel@tonic-gate err = -1; 39647c478bd9Sstevel@tonic-gate } 39657c478bd9Sstevel@tonic-gate 39667c478bd9Sstevel@tonic-gate zonecfg_fini_handle(hdl); 39677c478bd9Sstevel@tonic-gate return (err); 39687c478bd9Sstevel@tonic-gate } 39697c478bd9Sstevel@tonic-gate 39707c478bd9Sstevel@tonic-gate char * 39717c478bd9Sstevel@tonic-gate zone_state_str(zone_state_t state_num) 39727c478bd9Sstevel@tonic-gate { 39737c478bd9Sstevel@tonic-gate switch (state_num) { 39747c478bd9Sstevel@tonic-gate case ZONE_STATE_CONFIGURED: 39757c478bd9Sstevel@tonic-gate return (ZONE_STATE_STR_CONFIGURED); 39767c478bd9Sstevel@tonic-gate case ZONE_STATE_INCOMPLETE: 39777c478bd9Sstevel@tonic-gate return (ZONE_STATE_STR_INCOMPLETE); 39787c478bd9Sstevel@tonic-gate case ZONE_STATE_INSTALLED: 39797c478bd9Sstevel@tonic-gate return (ZONE_STATE_STR_INSTALLED); 39807c478bd9Sstevel@tonic-gate case ZONE_STATE_READY: 39817c478bd9Sstevel@tonic-gate return (ZONE_STATE_STR_READY); 3982108322fbScarlsonj case ZONE_STATE_MOUNTED: 3983108322fbScarlsonj return (ZONE_STATE_STR_MOUNTED); 39847c478bd9Sstevel@tonic-gate case ZONE_STATE_RUNNING: 39857c478bd9Sstevel@tonic-gate return (ZONE_STATE_STR_RUNNING); 39867c478bd9Sstevel@tonic-gate case ZONE_STATE_SHUTTING_DOWN: 39877c478bd9Sstevel@tonic-gate return (ZONE_STATE_STR_SHUTTING_DOWN); 39887c478bd9Sstevel@tonic-gate case ZONE_STATE_DOWN: 39897c478bd9Sstevel@tonic-gate return (ZONE_STATE_STR_DOWN); 39907c478bd9Sstevel@tonic-gate default: 39917c478bd9Sstevel@tonic-gate return ("unknown"); 39927c478bd9Sstevel@tonic-gate } 39937c478bd9Sstevel@tonic-gate } 39947c478bd9Sstevel@tonic-gate 3995108322fbScarlsonj /* 3996108322fbScarlsonj * Given a UUID value, find an associated zone name. This is intended to be 3997108322fbScarlsonj * used by callers who set up some 'default' name (corresponding to the 3998108322fbScarlsonj * expected name for the zone) in the zonename buffer, and thus the function 3999108322fbScarlsonj * doesn't touch this buffer on failure. 4000108322fbScarlsonj */ 4001108322fbScarlsonj int 4002108322fbScarlsonj zonecfg_get_name_by_uuid(const uuid_t uuid, char *zonename, size_t namelen) 4003108322fbScarlsonj { 4004108322fbScarlsonj FILE *fp; 4005108322fbScarlsonj struct zoneent *ze; 4006108322fbScarlsonj 4007108322fbScarlsonj /* 4008108322fbScarlsonj * A small amount of subterfuge via casts is necessary here because 4009108322fbScarlsonj * libuuid doesn't use const correctly, but we don't want to export 4010108322fbScarlsonj * this brokenness to our clients. 4011108322fbScarlsonj */ 4012108322fbScarlsonj if (uuid_is_null(*(uuid_t *)&uuid)) 4013108322fbScarlsonj return (Z_NO_ZONE); 4014108322fbScarlsonj if ((fp = setzoneent()) == NULL) 4015108322fbScarlsonj return (Z_NO_ZONE); 4016108322fbScarlsonj while ((ze = getzoneent_private(fp)) != NULL) { 4017108322fbScarlsonj if (uuid_compare(*(uuid_t *)&uuid, ze->zone_uuid) == 0) 4018108322fbScarlsonj break; 4019108322fbScarlsonj free(ze); 4020108322fbScarlsonj } 4021108322fbScarlsonj endzoneent(fp); 4022108322fbScarlsonj if (ze != NULL) { 4023108322fbScarlsonj (void) strlcpy(zonename, ze->zone_name, namelen); 4024108322fbScarlsonj free(ze); 4025108322fbScarlsonj return (Z_OK); 4026108322fbScarlsonj } else { 4027108322fbScarlsonj return (Z_NO_ZONE); 4028108322fbScarlsonj } 4029108322fbScarlsonj } 4030108322fbScarlsonj 4031108322fbScarlsonj /* 4032108322fbScarlsonj * Given a zone name, get its UUID. Returns a "NULL" UUID value if the zone 4033108322fbScarlsonj * exists but the file doesn't have a value set yet. Returns an error if the 4034108322fbScarlsonj * zone cannot be located. 4035108322fbScarlsonj */ 4036108322fbScarlsonj int 4037108322fbScarlsonj zonecfg_get_uuid(const char *zonename, uuid_t uuid) 4038108322fbScarlsonj { 4039108322fbScarlsonj FILE *fp; 4040108322fbScarlsonj struct zoneent *ze; 4041108322fbScarlsonj 4042108322fbScarlsonj if ((fp = setzoneent()) == NULL) 4043108322fbScarlsonj return (Z_NO_ZONE); 4044108322fbScarlsonj while ((ze = getzoneent_private(fp)) != NULL) { 4045108322fbScarlsonj if (strcmp(ze->zone_name, zonename) == 0) 4046108322fbScarlsonj break; 4047108322fbScarlsonj free(ze); 4048108322fbScarlsonj } 4049108322fbScarlsonj endzoneent(fp); 4050108322fbScarlsonj if (ze != NULL) { 4051108322fbScarlsonj uuid_copy(uuid, ze->zone_uuid); 4052108322fbScarlsonj free(ze); 4053108322fbScarlsonj return (Z_OK); 4054108322fbScarlsonj } else { 4055108322fbScarlsonj return (Z_NO_ZONE); 4056108322fbScarlsonj } 4057108322fbScarlsonj } 4058108322fbScarlsonj 40597c478bd9Sstevel@tonic-gate /* 40607c478bd9Sstevel@tonic-gate * File-system convenience functions. 40617c478bd9Sstevel@tonic-gate */ 40627c478bd9Sstevel@tonic-gate boolean_t 40637c478bd9Sstevel@tonic-gate zonecfg_valid_fs_type(const char *type) 40647c478bd9Sstevel@tonic-gate { 40657c478bd9Sstevel@tonic-gate /* 40667c478bd9Sstevel@tonic-gate * We already know which FS types don't work. 40677c478bd9Sstevel@tonic-gate */ 40687c478bd9Sstevel@tonic-gate if (strcmp(type, "proc") == 0 || 40697c478bd9Sstevel@tonic-gate strcmp(type, "mntfs") == 0 || 40707c478bd9Sstevel@tonic-gate strcmp(type, "autofs") == 0 || 40717c478bd9Sstevel@tonic-gate strncmp(type, "nfs", sizeof ("nfs") - 1) == 0 || 40727c478bd9Sstevel@tonic-gate strcmp(type, "cachefs") == 0) 40737c478bd9Sstevel@tonic-gate return (B_FALSE); 40747c478bd9Sstevel@tonic-gate /* 40757c478bd9Sstevel@tonic-gate * The caller may do more detailed verification to make sure other 40767c478bd9Sstevel@tonic-gate * aspects of this filesystem type make sense. 40777c478bd9Sstevel@tonic-gate */ 40787c478bd9Sstevel@tonic-gate return (B_TRUE); 40797c478bd9Sstevel@tonic-gate } 40807c478bd9Sstevel@tonic-gate 40817c478bd9Sstevel@tonic-gate /* 40827c478bd9Sstevel@tonic-gate * Generally uninteresting rctl convenience functions. 40837c478bd9Sstevel@tonic-gate */ 40847c478bd9Sstevel@tonic-gate 40857c478bd9Sstevel@tonic-gate int 40867c478bd9Sstevel@tonic-gate zonecfg_construct_rctlblk(const struct zone_rctlvaltab *rctlval, 40877c478bd9Sstevel@tonic-gate rctlblk_t *rctlblk) 40887c478bd9Sstevel@tonic-gate { 40897c478bd9Sstevel@tonic-gate unsigned long long ull; 40907c478bd9Sstevel@tonic-gate char *endp; 40917c478bd9Sstevel@tonic-gate rctl_priv_t priv; 40927c478bd9Sstevel@tonic-gate rctl_qty_t limit; 40937c478bd9Sstevel@tonic-gate uint_t action; 40947c478bd9Sstevel@tonic-gate 40957c478bd9Sstevel@tonic-gate /* Get the privilege */ 40967c478bd9Sstevel@tonic-gate if (strcmp(rctlval->zone_rctlval_priv, "basic") == 0) { 40977c478bd9Sstevel@tonic-gate priv = RCPRIV_BASIC; 40987c478bd9Sstevel@tonic-gate } else if (strcmp(rctlval->zone_rctlval_priv, "privileged") == 0) { 40997c478bd9Sstevel@tonic-gate priv = RCPRIV_PRIVILEGED; 41007c478bd9Sstevel@tonic-gate } else { 41017c478bd9Sstevel@tonic-gate /* Invalid privilege */ 41027c478bd9Sstevel@tonic-gate return (Z_INVAL); 41037c478bd9Sstevel@tonic-gate } 41047c478bd9Sstevel@tonic-gate 41057c478bd9Sstevel@tonic-gate /* deal with negative input; strtoull(3c) doesn't do what we want */ 41067c478bd9Sstevel@tonic-gate if (rctlval->zone_rctlval_limit[0] == '-') 41077c478bd9Sstevel@tonic-gate return (Z_INVAL); 41087c478bd9Sstevel@tonic-gate /* Get the limit */ 41097c478bd9Sstevel@tonic-gate errno = 0; 41107c478bd9Sstevel@tonic-gate ull = strtoull(rctlval->zone_rctlval_limit, &endp, 0); 41117c478bd9Sstevel@tonic-gate if (errno != 0 || *endp != '\0') { 41127c478bd9Sstevel@tonic-gate /* parse failed */ 41137c478bd9Sstevel@tonic-gate return (Z_INVAL); 41147c478bd9Sstevel@tonic-gate } 41157c478bd9Sstevel@tonic-gate limit = (rctl_qty_t)ull; 41167c478bd9Sstevel@tonic-gate 41177c478bd9Sstevel@tonic-gate /* Get the action */ 41187c478bd9Sstevel@tonic-gate if (strcmp(rctlval->zone_rctlval_action, "none") == 0) { 41197c478bd9Sstevel@tonic-gate action = RCTL_LOCAL_NOACTION; 41207c478bd9Sstevel@tonic-gate } else if (strcmp(rctlval->zone_rctlval_action, "signal") == 0) { 41217c478bd9Sstevel@tonic-gate action = RCTL_LOCAL_SIGNAL; 41227c478bd9Sstevel@tonic-gate } else if (strcmp(rctlval->zone_rctlval_action, "deny") == 0) { 41237c478bd9Sstevel@tonic-gate action = RCTL_LOCAL_DENY; 41247c478bd9Sstevel@tonic-gate } else { 41257c478bd9Sstevel@tonic-gate /* Invalid Action */ 41267c478bd9Sstevel@tonic-gate return (Z_INVAL); 41277c478bd9Sstevel@tonic-gate } 41287c478bd9Sstevel@tonic-gate rctlblk_set_local_action(rctlblk, action, 0); 41297c478bd9Sstevel@tonic-gate rctlblk_set_privilege(rctlblk, priv); 41307c478bd9Sstevel@tonic-gate rctlblk_set_value(rctlblk, limit); 41317c478bd9Sstevel@tonic-gate return (Z_OK); 41327c478bd9Sstevel@tonic-gate } 41337c478bd9Sstevel@tonic-gate 41347c478bd9Sstevel@tonic-gate static int 41357c478bd9Sstevel@tonic-gate rctl_check(const char *rctlname, void *arg) 41367c478bd9Sstevel@tonic-gate { 41377c478bd9Sstevel@tonic-gate const char *attrname = arg; 41387c478bd9Sstevel@tonic-gate 41397c478bd9Sstevel@tonic-gate /* 41407c478bd9Sstevel@tonic-gate * Returning 1 here is our signal to zonecfg_is_rctl() that it is 41417c478bd9Sstevel@tonic-gate * indeed an rctl name recognized by the system. 41427c478bd9Sstevel@tonic-gate */ 41437c478bd9Sstevel@tonic-gate return (strcmp(rctlname, attrname) == 0 ? 1 : 0); 41447c478bd9Sstevel@tonic-gate } 41457c478bd9Sstevel@tonic-gate 41467c478bd9Sstevel@tonic-gate boolean_t 41477c478bd9Sstevel@tonic-gate zonecfg_is_rctl(const char *name) 41487c478bd9Sstevel@tonic-gate { 41497c478bd9Sstevel@tonic-gate return (rctl_walk(rctl_check, (void *)name) == 1); 41507c478bd9Sstevel@tonic-gate } 41517c478bd9Sstevel@tonic-gate 41527c478bd9Sstevel@tonic-gate boolean_t 41537c478bd9Sstevel@tonic-gate zonecfg_valid_rctlname(const char *name) 41547c478bd9Sstevel@tonic-gate { 41557c478bd9Sstevel@tonic-gate const char *c; 41567c478bd9Sstevel@tonic-gate 41577c478bd9Sstevel@tonic-gate if (strncmp(name, "zone.", sizeof ("zone.") - 1) != 0) 41587c478bd9Sstevel@tonic-gate return (B_FALSE); 41597c478bd9Sstevel@tonic-gate if (strlen(name) == sizeof ("zone.") - 1) 41607c478bd9Sstevel@tonic-gate return (B_FALSE); 41617c478bd9Sstevel@tonic-gate for (c = name + sizeof ("zone.") - 1; *c != '\0'; c++) { 41627c478bd9Sstevel@tonic-gate if (!isalpha(*c) && *c != '-') 41637c478bd9Sstevel@tonic-gate return (B_FALSE); 41647c478bd9Sstevel@tonic-gate } 41657c478bd9Sstevel@tonic-gate return (B_TRUE); 41667c478bd9Sstevel@tonic-gate } 41677c478bd9Sstevel@tonic-gate 41687c478bd9Sstevel@tonic-gate boolean_t 41697c478bd9Sstevel@tonic-gate zonecfg_valid_rctlblk(const rctlblk_t *rctlblk) 41707c478bd9Sstevel@tonic-gate { 41717c478bd9Sstevel@tonic-gate rctl_priv_t priv = rctlblk_get_privilege((rctlblk_t *)rctlblk); 41727c478bd9Sstevel@tonic-gate uint_t action = rctlblk_get_local_action((rctlblk_t *)rctlblk, NULL); 41737c478bd9Sstevel@tonic-gate 41747c478bd9Sstevel@tonic-gate if (priv != RCPRIV_PRIVILEGED) 41757c478bd9Sstevel@tonic-gate return (B_FALSE); 41767c478bd9Sstevel@tonic-gate if (action != RCTL_LOCAL_NOACTION && action != RCTL_LOCAL_DENY) 41777c478bd9Sstevel@tonic-gate return (B_FALSE); 41787c478bd9Sstevel@tonic-gate return (B_TRUE); 41797c478bd9Sstevel@tonic-gate } 41807c478bd9Sstevel@tonic-gate 41817c478bd9Sstevel@tonic-gate boolean_t 41827c478bd9Sstevel@tonic-gate zonecfg_valid_rctl(const char *name, const rctlblk_t *rctlblk) 41837c478bd9Sstevel@tonic-gate { 41847c478bd9Sstevel@tonic-gate rctlblk_t *current, *next; 41857c478bd9Sstevel@tonic-gate rctl_qty_t limit = rctlblk_get_value((rctlblk_t *)rctlblk); 41867c478bd9Sstevel@tonic-gate uint_t action = rctlblk_get_local_action((rctlblk_t *)rctlblk, NULL); 41877c478bd9Sstevel@tonic-gate uint_t global_flags; 41887c478bd9Sstevel@tonic-gate 41897c478bd9Sstevel@tonic-gate if (!zonecfg_valid_rctlblk(rctlblk)) 41907c478bd9Sstevel@tonic-gate return (B_FALSE); 41917c478bd9Sstevel@tonic-gate if (!zonecfg_valid_rctlname(name)) 41927c478bd9Sstevel@tonic-gate return (B_FALSE); 41937c478bd9Sstevel@tonic-gate 41947c478bd9Sstevel@tonic-gate current = alloca(rctlblk_size()); 41957c478bd9Sstevel@tonic-gate if (getrctl(name, NULL, current, RCTL_FIRST) != 0) 41967c478bd9Sstevel@tonic-gate return (B_TRUE); /* not an rctl on this system */ 41977c478bd9Sstevel@tonic-gate /* 41987c478bd9Sstevel@tonic-gate * Make sure the proposed value isn't greater than the current system 41997c478bd9Sstevel@tonic-gate * value. 42007c478bd9Sstevel@tonic-gate */ 42017c478bd9Sstevel@tonic-gate next = alloca(rctlblk_size()); 42027c478bd9Sstevel@tonic-gate while (rctlblk_get_privilege(current) != RCPRIV_SYSTEM) { 42037c478bd9Sstevel@tonic-gate rctlblk_t *tmp; 42047c478bd9Sstevel@tonic-gate 42057c478bd9Sstevel@tonic-gate if (getrctl(name, current, next, RCTL_NEXT) != 0) 42067c478bd9Sstevel@tonic-gate return (B_FALSE); /* shouldn't happen */ 42077c478bd9Sstevel@tonic-gate tmp = current; 42087c478bd9Sstevel@tonic-gate current = next; 42097c478bd9Sstevel@tonic-gate next = tmp; 42107c478bd9Sstevel@tonic-gate } 42117c478bd9Sstevel@tonic-gate if (limit > rctlblk_get_value(current)) 42127c478bd9Sstevel@tonic-gate return (B_FALSE); 42137c478bd9Sstevel@tonic-gate 42147c478bd9Sstevel@tonic-gate /* 42157c478bd9Sstevel@tonic-gate * Make sure the proposed action is allowed. 42167c478bd9Sstevel@tonic-gate */ 42177c478bd9Sstevel@tonic-gate global_flags = rctlblk_get_global_flags(current); 42187c478bd9Sstevel@tonic-gate if ((global_flags & RCTL_GLOBAL_DENY_NEVER) && 42197c478bd9Sstevel@tonic-gate action == RCTL_LOCAL_DENY) 42207c478bd9Sstevel@tonic-gate return (B_FALSE); 42217c478bd9Sstevel@tonic-gate if ((global_flags & RCTL_GLOBAL_DENY_ALWAYS) && 42227c478bd9Sstevel@tonic-gate action == RCTL_LOCAL_NOACTION) 42237c478bd9Sstevel@tonic-gate return (B_FALSE); 42247c478bd9Sstevel@tonic-gate 42257c478bd9Sstevel@tonic-gate return (B_TRUE); 42267c478bd9Sstevel@tonic-gate } 4227fa9e4066Sahrens 4228cf8f45c7Sdstaff /* 4229cf8f45c7Sdstaff * There is always a race condition between reading the initial copy of 4230cf8f45c7Sdstaff * a zones state and its state changing. We address this by providing 4231cf8f45c7Sdstaff * zonecfg_notify_critical_enter and zonecfg_noticy_critical_exit functions. 4232cf8f45c7Sdstaff * When zonecfg_critical_enter is called, sets the state field to LOCKED 4233cf8f45c7Sdstaff * and aquires biglock. Biglock protects against other threads executing 4234cf8f45c7Sdstaff * critical_enter and the state field protects against state changes during 4235cf8f45c7Sdstaff * the critical period. 4236cf8f45c7Sdstaff * 4237cf8f45c7Sdstaff * If any state changes occur, zn_cb will set the failed field of the znotify 4238cf8f45c7Sdstaff * structure. This will cause the critical_exit function to re-lock the 4239cf8f45c7Sdstaff * channel and return an error. Since evsnts may be delayed, the critical_exit 4240cf8f45c7Sdstaff * function "flushes" the queue by putting an event on the queue and waiting for 4241cf8f45c7Sdstaff * zn_cb to notify critical_exit that it received the ping event. 4242cf8f45c7Sdstaff */ 4243cf8f45c7Sdstaff static const char * 4244cf8f45c7Sdstaff string_get_tok(const char *in, char delim, int num) 4245cf8f45c7Sdstaff { 4246cf8f45c7Sdstaff int i = 0; 4247cf8f45c7Sdstaff 4248cf8f45c7Sdstaff for (; i < num; in++) { 4249cf8f45c7Sdstaff if (*in == delim) 4250cf8f45c7Sdstaff i++; 4251cf8f45c7Sdstaff if (*in == 0) 4252cf8f45c7Sdstaff return (NULL); 4253cf8f45c7Sdstaff } 4254cf8f45c7Sdstaff return (in); 4255cf8f45c7Sdstaff } 4256cf8f45c7Sdstaff 4257cf8f45c7Sdstaff static boolean_t 4258cf8f45c7Sdstaff is_ping(sysevent_t *ev) 4259cf8f45c7Sdstaff { 4260cf8f45c7Sdstaff if (strcmp(sysevent_get_subclass_name(ev), 4261ffbafc53Scomay ZONE_EVENT_PING_SUBCLASS) == 0) { 4262cf8f45c7Sdstaff return (B_TRUE); 4263cf8f45c7Sdstaff } else { 4264cf8f45c7Sdstaff return (B_FALSE); 4265cf8f45c7Sdstaff } 4266cf8f45c7Sdstaff } 4267cf8f45c7Sdstaff 4268cf8f45c7Sdstaff static boolean_t 4269cf8f45c7Sdstaff is_my_ping(sysevent_t *ev) 4270cf8f45c7Sdstaff { 4271cf8f45c7Sdstaff const char *sender; 4272cf8f45c7Sdstaff char mypid[sizeof (pid_t) * 3 + 1]; 4273cf8f45c7Sdstaff 4274cf8f45c7Sdstaff (void) snprintf(mypid, sizeof (mypid), "%i", getpid()); 4275cf8f45c7Sdstaff sender = string_get_tok(sysevent_get_pub(ev), ':', 3); 4276cf8f45c7Sdstaff if (sender == NULL) 4277cf8f45c7Sdstaff return (B_FALSE); 4278cf8f45c7Sdstaff if (strcmp(sender, mypid) != 0) 4279cf8f45c7Sdstaff return (B_FALSE); 4280cf8f45c7Sdstaff return (B_TRUE); 4281cf8f45c7Sdstaff } 4282cf8f45c7Sdstaff 4283cf8f45c7Sdstaff static int 4284cf8f45c7Sdstaff do_callback(struct znotify *zevtchan, sysevent_t *ev) 4285cf8f45c7Sdstaff { 4286cf8f45c7Sdstaff nvlist_t *l; 4287cf8f45c7Sdstaff int zid; 4288cf8f45c7Sdstaff char *zonename; 4289cf8f45c7Sdstaff char *newstate; 4290cf8f45c7Sdstaff char *oldstate; 4291cf8f45c7Sdstaff int ret; 4292cf8f45c7Sdstaff hrtime_t when; 4293cf8f45c7Sdstaff 4294cf8f45c7Sdstaff if (strcmp(sysevent_get_subclass_name(ev), 4295cf8f45c7Sdstaff ZONE_EVENT_STATUS_SUBCLASS) == 0) { 4296cf8f45c7Sdstaff 4297cf8f45c7Sdstaff if (sysevent_get_attr_list(ev, &l) != 0) { 4298cf8f45c7Sdstaff if (errno == ENOMEM) { 4299cf8f45c7Sdstaff zevtchan->zn_failure_count++; 4300cf8f45c7Sdstaff return (EAGAIN); 4301cf8f45c7Sdstaff } 4302cf8f45c7Sdstaff return (0); 4303cf8f45c7Sdstaff } 4304cf8f45c7Sdstaff ret = 0; 4305cf8f45c7Sdstaff 4306cf8f45c7Sdstaff if ((nvlist_lookup_string(l, ZONE_CB_NAME, &zonename) == 0) && 4307cf8f45c7Sdstaff (nvlist_lookup_string(l, ZONE_CB_NEWSTATE, &newstate) 4308ffbafc53Scomay == 0) && 4309cf8f45c7Sdstaff (nvlist_lookup_string(l, ZONE_CB_OLDSTATE, &oldstate) 4310ffbafc53Scomay == 0) && 4311cf8f45c7Sdstaff (nvlist_lookup_uint64(l, ZONE_CB_TIMESTAMP, 4312ffbafc53Scomay (uint64_t *)&when) == 0) && 4313cf8f45c7Sdstaff (nvlist_lookup_int32(l, ZONE_CB_ZONEID, &zid) == 0)) { 4314cf8f45c7Sdstaff ret = zevtchan->zn_callback(zonename, zid, newstate, 4315cf8f45c7Sdstaff oldstate, when, zevtchan->zn_private); 4316cf8f45c7Sdstaff } 4317cf8f45c7Sdstaff 4318cf8f45c7Sdstaff zevtchan->zn_failure_count = 0; 4319cf8f45c7Sdstaff nvlist_free(l); 4320cf8f45c7Sdstaff return (ret); 4321cf8f45c7Sdstaff } else { 4322cf8f45c7Sdstaff /* 4323cf8f45c7Sdstaff * We have received an event in an unknown subclass. Ignore. 4324cf8f45c7Sdstaff */ 4325cf8f45c7Sdstaff zevtchan->zn_failure_count = 0; 4326cf8f45c7Sdstaff return (0); 4327cf8f45c7Sdstaff } 4328cf8f45c7Sdstaff } 4329cf8f45c7Sdstaff 4330cf8f45c7Sdstaff static int 4331cf8f45c7Sdstaff zn_cb(sysevent_t *ev, void *p) 4332cf8f45c7Sdstaff { 4333cf8f45c7Sdstaff struct znotify *zevtchan = p; 4334cf8f45c7Sdstaff int error; 4335cf8f45c7Sdstaff 4336cf8f45c7Sdstaff (void) pthread_mutex_lock(&(zevtchan->zn_mutex)); 4337cf8f45c7Sdstaff 4338cf8f45c7Sdstaff if (is_ping(ev) && !is_my_ping(ev)) { 4339cf8f45c7Sdstaff (void) pthread_mutex_unlock((&zevtchan->zn_mutex)); 4340cf8f45c7Sdstaff return (0); 4341cf8f45c7Sdstaff } 4342cf8f45c7Sdstaff 4343cf8f45c7Sdstaff if (zevtchan->zn_state == ZN_LOCKED) { 4344cf8f45c7Sdstaff assert(!is_ping(ev)); 4345cf8f45c7Sdstaff zevtchan->zn_failed = B_TRUE; 4346cf8f45c7Sdstaff (void) pthread_mutex_unlock(&(zevtchan->zn_mutex)); 4347cf8f45c7Sdstaff return (0); 4348cf8f45c7Sdstaff } 4349cf8f45c7Sdstaff 4350cf8f45c7Sdstaff if (zevtchan->zn_state == ZN_PING_INFLIGHT) { 4351cf8f45c7Sdstaff if (is_ping(ev)) { 4352cf8f45c7Sdstaff zevtchan->zn_state = ZN_PING_RECEIVED; 4353cf8f45c7Sdstaff (void) pthread_cond_signal(&(zevtchan->zn_cond)); 4354cf8f45c7Sdstaff (void) pthread_mutex_unlock(&(zevtchan->zn_mutex)); 4355cf8f45c7Sdstaff return (0); 4356cf8f45c7Sdstaff } else { 4357cf8f45c7Sdstaff zevtchan->zn_failed = B_TRUE; 4358cf8f45c7Sdstaff (void) pthread_mutex_unlock(&(zevtchan->zn_mutex)); 4359cf8f45c7Sdstaff return (0); 4360cf8f45c7Sdstaff } 4361cf8f45c7Sdstaff } 4362cf8f45c7Sdstaff 4363cf8f45c7Sdstaff if (zevtchan->zn_state == ZN_UNLOCKED) { 4364cf8f45c7Sdstaff 4365cf8f45c7Sdstaff error = do_callback(zevtchan, ev); 4366cf8f45c7Sdstaff (void) pthread_mutex_unlock(&(zevtchan->zn_mutex)); 4367cf8f45c7Sdstaff /* 4368cf8f45c7Sdstaff * Every ENOMEM failure causes do_callback to increment 4369cf8f45c7Sdstaff * zn_failure_count and every success causes it to 4370cf8f45c7Sdstaff * set zn_failure_count to zero. If we got EAGAIN, 4371cf8f45c7Sdstaff * we will sleep for zn_failure_count seconds and return 4372cf8f45c7Sdstaff * EAGAIN to gpec to try again. 4373cf8f45c7Sdstaff * 4374cf8f45c7Sdstaff * After 55 seconds, or 10 try's we give up and drop the 4375cf8f45c7Sdstaff * event. 4376cf8f45c7Sdstaff */ 4377cf8f45c7Sdstaff if (error == EAGAIN) { 4378cf8f45c7Sdstaff if (zevtchan->zn_failure_count > ZONE_CB_RETRY_COUNT) { 4379cf8f45c7Sdstaff return (0); 4380cf8f45c7Sdstaff } 4381cf8f45c7Sdstaff (void) sleep(zevtchan->zn_failure_count); 4382cf8f45c7Sdstaff } 4383cf8f45c7Sdstaff return (error); 4384cf8f45c7Sdstaff } 4385cf8f45c7Sdstaff 4386cf8f45c7Sdstaff if (zevtchan->zn_state == ZN_PING_RECEIVED) { 4387cf8f45c7Sdstaff (void) pthread_mutex_unlock(&(zevtchan->zn_mutex)); 4388cf8f45c7Sdstaff return (0); 4389cf8f45c7Sdstaff } 4390cf8f45c7Sdstaff 4391cf8f45c7Sdstaff abort(); 4392cf8f45c7Sdstaff return (0); 4393cf8f45c7Sdstaff } 4394cf8f45c7Sdstaff 4395cf8f45c7Sdstaff void 4396cf8f45c7Sdstaff zonecfg_notify_critical_enter(void *h) 4397cf8f45c7Sdstaff { 4398cf8f45c7Sdstaff struct znotify *zevtchan = h; 4399cf8f45c7Sdstaff 4400cf8f45c7Sdstaff (void) pthread_mutex_lock(&(zevtchan->zn_bigmutex)); 4401cf8f45c7Sdstaff zevtchan->zn_state = ZN_LOCKED; 4402cf8f45c7Sdstaff } 4403cf8f45c7Sdstaff 4404cf8f45c7Sdstaff int 4405cf8f45c7Sdstaff zonecfg_notify_critical_exit(void * h) 4406cf8f45c7Sdstaff { 4407cf8f45c7Sdstaff 4408cf8f45c7Sdstaff struct znotify *zevtchan = h; 4409cf8f45c7Sdstaff 4410cf8f45c7Sdstaff if (zevtchan->zn_state == ZN_UNLOCKED) 4411cf8f45c7Sdstaff return (0); 4412cf8f45c7Sdstaff 4413cf8f45c7Sdstaff (void) pthread_mutex_lock(&(zevtchan->zn_mutex)); 4414cf8f45c7Sdstaff zevtchan->zn_state = ZN_PING_INFLIGHT; 4415cf8f45c7Sdstaff 4416ee519a1fSgjelinek (void) sysevent_evc_publish(zevtchan->zn_eventchan, 4417ee519a1fSgjelinek ZONE_EVENT_STATUS_CLASS, 4418cf8f45c7Sdstaff ZONE_EVENT_PING_SUBCLASS, ZONE_EVENT_PING_PUBLISHER, 4419cf8f45c7Sdstaff zevtchan->zn_subscriber_id, NULL, EVCH_SLEEP); 4420cf8f45c7Sdstaff 4421cf8f45c7Sdstaff while (zevtchan->zn_state != ZN_PING_RECEIVED) { 4422cf8f45c7Sdstaff (void) pthread_cond_wait(&(zevtchan->zn_cond), 4423cf8f45c7Sdstaff &(zevtchan->zn_mutex)); 4424cf8f45c7Sdstaff } 4425cf8f45c7Sdstaff 4426cf8f45c7Sdstaff if (zevtchan->zn_failed == B_TRUE) { 4427cf8f45c7Sdstaff zevtchan->zn_state = ZN_LOCKED; 4428cf8f45c7Sdstaff zevtchan->zn_failed = B_FALSE; 4429cf8f45c7Sdstaff (void) pthread_mutex_unlock(&(zevtchan->zn_mutex)); 4430cf8f45c7Sdstaff return (1); 4431cf8f45c7Sdstaff } 4432cf8f45c7Sdstaff 4433cf8f45c7Sdstaff zevtchan->zn_state = ZN_UNLOCKED; 4434cf8f45c7Sdstaff (void) pthread_mutex_unlock(&(zevtchan->zn_mutex)); 4435cf8f45c7Sdstaff (void) pthread_mutex_unlock(&(zevtchan->zn_bigmutex)); 4436cf8f45c7Sdstaff return (0); 4437cf8f45c7Sdstaff } 4438cf8f45c7Sdstaff 4439cf8f45c7Sdstaff void 4440cf8f45c7Sdstaff zonecfg_notify_critical_abort(void *h) 4441cf8f45c7Sdstaff { 4442cf8f45c7Sdstaff struct znotify *zevtchan = h; 4443cf8f45c7Sdstaff 4444cf8f45c7Sdstaff zevtchan->zn_state = ZN_UNLOCKED; 4445cf8f45c7Sdstaff zevtchan->zn_failed = B_FALSE; 4446cf8f45c7Sdstaff /* 4447cf8f45c7Sdstaff * Don't do anything about zn_lock. If it is held, it could only be 4448cf8f45c7Sdstaff * held by zn_cb and it will be unlocked soon. 4449cf8f45c7Sdstaff */ 4450cf8f45c7Sdstaff (void) pthread_mutex_unlock(&(zevtchan->zn_bigmutex)); 4451cf8f45c7Sdstaff } 4452cf8f45c7Sdstaff 4453cf8f45c7Sdstaff void * 4454cf8f45c7Sdstaff zonecfg_notify_bind(int(*func)(const char *zonename, zoneid_t zid, 4455cf8f45c7Sdstaff const char *newstate, const char *oldstate, hrtime_t when, void *p), 4456cf8f45c7Sdstaff void *p) 4457cf8f45c7Sdstaff { 4458cf8f45c7Sdstaff struct znotify *zevtchan; 4459cf8f45c7Sdstaff int i = 1; 4460cf8f45c7Sdstaff int r; 4461cf8f45c7Sdstaff 4462cf8f45c7Sdstaff zevtchan = malloc(sizeof (struct znotify)); 4463cf8f45c7Sdstaff 4464cf8f45c7Sdstaff if (zevtchan == NULL) 4465cf8f45c7Sdstaff return (NULL); 4466cf8f45c7Sdstaff 4467cf8f45c7Sdstaff zevtchan->zn_private = p; 4468cf8f45c7Sdstaff zevtchan->zn_callback = func; 4469cf8f45c7Sdstaff zevtchan->zn_state = ZN_UNLOCKED; 4470cf8f45c7Sdstaff zevtchan->zn_failed = B_FALSE; 4471cf8f45c7Sdstaff 4472cf8f45c7Sdstaff if (pthread_mutex_init(&(zevtchan->zn_mutex), NULL)) 44739d4be64eSdstaff goto out3; 4474cf8f45c7Sdstaff if (pthread_cond_init(&(zevtchan->zn_cond), NULL)) { 4475cf8f45c7Sdstaff (void) pthread_mutex_destroy(&(zevtchan->zn_mutex)); 44769d4be64eSdstaff goto out3; 4477cf8f45c7Sdstaff } 4478cf8f45c7Sdstaff if (pthread_mutex_init(&(zevtchan->zn_bigmutex), NULL)) { 4479cf8f45c7Sdstaff (void) pthread_mutex_destroy(&(zevtchan->zn_mutex)); 4480cf8f45c7Sdstaff (void) pthread_cond_destroy(&(zevtchan->zn_cond)); 44819d4be64eSdstaff goto out3; 4482cf8f45c7Sdstaff } 4483cf8f45c7Sdstaff 4484cf8f45c7Sdstaff if (sysevent_evc_bind(ZONE_EVENT_CHANNEL, &(zevtchan->zn_eventchan), 4485ffbafc53Scomay 0) != 0) 4486cf8f45c7Sdstaff goto out2; 4487cf8f45c7Sdstaff 4488cf8f45c7Sdstaff do { 4489cf8f45c7Sdstaff /* 4490cf8f45c7Sdstaff * At 4 digits the subscriber ID gets too long and we have 4491cf8f45c7Sdstaff * no chance of successfully registering. 4492cf8f45c7Sdstaff */ 4493cf8f45c7Sdstaff if (i > 999) 44949d4be64eSdstaff goto out1; 4495cf8f45c7Sdstaff 4496cf8f45c7Sdstaff (void) sprintf(zevtchan->zn_subscriber_id, "zone_%li_%i", 4497cf8f45c7Sdstaff getpid() % 999999l, i); 4498cf8f45c7Sdstaff 4499cf8f45c7Sdstaff r = sysevent_evc_subscribe(zevtchan->zn_eventchan, 4500cf8f45c7Sdstaff zevtchan->zn_subscriber_id, ZONE_EVENT_STATUS_CLASS, zn_cb, 4501cf8f45c7Sdstaff zevtchan, 0); 4502cf8f45c7Sdstaff 4503cf8f45c7Sdstaff i++; 4504cf8f45c7Sdstaff 4505cf8f45c7Sdstaff } while (r); 4506cf8f45c7Sdstaff 4507cf8f45c7Sdstaff return (zevtchan); 45089d4be64eSdstaff out1: 4509cf8f45c7Sdstaff sysevent_evc_unbind(zevtchan->zn_eventchan); 45109d4be64eSdstaff out2: 4511cf8f45c7Sdstaff (void) pthread_mutex_destroy(&zevtchan->zn_mutex); 4512cf8f45c7Sdstaff (void) pthread_cond_destroy(&zevtchan->zn_cond); 4513cf8f45c7Sdstaff (void) pthread_mutex_destroy(&(zevtchan->zn_bigmutex)); 45149d4be64eSdstaff out3: 4515cf8f45c7Sdstaff free(zevtchan); 4516cf8f45c7Sdstaff 4517cf8f45c7Sdstaff return (NULL); 4518cf8f45c7Sdstaff } 4519cf8f45c7Sdstaff 4520cf8f45c7Sdstaff void 4521cf8f45c7Sdstaff zonecfg_notify_unbind(void *handle) 4522cf8f45c7Sdstaff { 4523cf8f45c7Sdstaff 4524cf8f45c7Sdstaff int ret; 4525cf8f45c7Sdstaff 4526cf8f45c7Sdstaff sysevent_evc_unbind(((struct znotify *)handle)->zn_eventchan); 4527cf8f45c7Sdstaff /* 4528cf8f45c7Sdstaff * Check that all evc threads have gone away. This should be 4529cf8f45c7Sdstaff * enforced by sysevent_evc_unbind. 4530cf8f45c7Sdstaff */ 4531cf8f45c7Sdstaff ret = pthread_mutex_trylock(&((struct znotify *)handle)->zn_mutex); 4532cf8f45c7Sdstaff 4533cf8f45c7Sdstaff if (ret) 4534cf8f45c7Sdstaff abort(); 4535cf8f45c7Sdstaff 4536cf8f45c7Sdstaff (void) pthread_mutex_unlock(&((struct znotify *)handle)->zn_mutex); 4537cf8f45c7Sdstaff (void) pthread_mutex_destroy(&((struct znotify *)handle)->zn_mutex); 4538cf8f45c7Sdstaff (void) pthread_cond_destroy(&((struct znotify *)handle)->zn_cond); 4539cf8f45c7Sdstaff (void) pthread_mutex_destroy(&((struct znotify *)handle)->zn_bigmutex); 4540cf8f45c7Sdstaff 4541cf8f45c7Sdstaff free(handle); 4542cf8f45c7Sdstaff } 4543cf8f45c7Sdstaff 4544fa9e4066Sahrens static int 4545fa9e4066Sahrens zonecfg_add_ds_core(zone_dochandle_t handle, struct zone_dstab *tabptr) 4546fa9e4066Sahrens { 4547fa9e4066Sahrens xmlNodePtr newnode, cur = handle->zone_dh_cur; 4548fa9e4066Sahrens int err; 4549fa9e4066Sahrens 4550fa9e4066Sahrens newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_DATASET, NULL); 4551fa9e4066Sahrens if ((err = newprop(newnode, DTD_ATTR_NAME, 4552fa9e4066Sahrens tabptr->zone_dataset_name)) != Z_OK) 4553fa9e4066Sahrens return (err); 4554fa9e4066Sahrens return (Z_OK); 4555fa9e4066Sahrens } 4556fa9e4066Sahrens 4557fa9e4066Sahrens int 4558fa9e4066Sahrens zonecfg_add_ds(zone_dochandle_t handle, struct zone_dstab *tabptr) 4559fa9e4066Sahrens { 4560fa9e4066Sahrens int err; 4561fa9e4066Sahrens 4562fa9e4066Sahrens if (tabptr == NULL) 4563fa9e4066Sahrens return (Z_INVAL); 4564fa9e4066Sahrens 4565fa9e4066Sahrens if ((err = operation_prep(handle)) != Z_OK) 4566fa9e4066Sahrens return (err); 4567fa9e4066Sahrens 4568fa9e4066Sahrens if ((err = zonecfg_add_ds_core(handle, tabptr)) != Z_OK) 4569fa9e4066Sahrens return (err); 4570fa9e4066Sahrens 4571fa9e4066Sahrens return (Z_OK); 4572fa9e4066Sahrens } 4573fa9e4066Sahrens 4574fa9e4066Sahrens static int 4575fa9e4066Sahrens zonecfg_delete_ds_core(zone_dochandle_t handle, struct zone_dstab *tabptr) 4576fa9e4066Sahrens { 4577fa9e4066Sahrens xmlNodePtr cur = handle->zone_dh_cur; 4578fa9e4066Sahrens 4579fa9e4066Sahrens for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 4580fa9e4066Sahrens if (xmlStrcmp(cur->name, DTD_ELEM_DATASET)) 4581fa9e4066Sahrens continue; 4582fa9e4066Sahrens 4583fa9e4066Sahrens if (match_prop(cur, DTD_ATTR_NAME, 4584fa9e4066Sahrens tabptr->zone_dataset_name)) { 4585fa9e4066Sahrens xmlUnlinkNode(cur); 4586fa9e4066Sahrens xmlFreeNode(cur); 4587fa9e4066Sahrens return (Z_OK); 4588fa9e4066Sahrens } 4589fa9e4066Sahrens } 4590fa9e4066Sahrens return (Z_NO_RESOURCE_ID); 4591fa9e4066Sahrens } 4592fa9e4066Sahrens 4593fa9e4066Sahrens int 4594fa9e4066Sahrens zonecfg_delete_ds(zone_dochandle_t handle, struct zone_dstab *tabptr) 4595fa9e4066Sahrens { 4596fa9e4066Sahrens int err; 4597fa9e4066Sahrens 4598fa9e4066Sahrens if (tabptr == NULL) 4599fa9e4066Sahrens return (Z_INVAL); 4600fa9e4066Sahrens 4601fa9e4066Sahrens if ((err = operation_prep(handle)) != Z_OK) 4602fa9e4066Sahrens return (err); 4603fa9e4066Sahrens 4604fa9e4066Sahrens if ((err = zonecfg_delete_ds_core(handle, tabptr)) != Z_OK) 4605fa9e4066Sahrens return (err); 4606fa9e4066Sahrens 4607fa9e4066Sahrens return (Z_OK); 4608fa9e4066Sahrens } 4609fa9e4066Sahrens 4610fa9e4066Sahrens int 4611fa9e4066Sahrens zonecfg_modify_ds( 4612fa9e4066Sahrens zone_dochandle_t handle, 4613fa9e4066Sahrens struct zone_dstab *oldtabptr, 4614fa9e4066Sahrens struct zone_dstab *newtabptr) 4615fa9e4066Sahrens { 4616fa9e4066Sahrens int err; 4617fa9e4066Sahrens 4618fa9e4066Sahrens if (oldtabptr == NULL || newtabptr == NULL) 4619fa9e4066Sahrens return (Z_INVAL); 4620fa9e4066Sahrens 4621fa9e4066Sahrens if ((err = operation_prep(handle)) != Z_OK) 4622fa9e4066Sahrens return (err); 4623fa9e4066Sahrens 4624fa9e4066Sahrens if ((err = zonecfg_delete_ds_core(handle, oldtabptr)) != Z_OK) 4625fa9e4066Sahrens return (err); 4626fa9e4066Sahrens 4627fa9e4066Sahrens if ((err = zonecfg_add_ds_core(handle, newtabptr)) != Z_OK) 4628fa9e4066Sahrens return (err); 4629fa9e4066Sahrens 4630fa9e4066Sahrens return (Z_OK); 4631fa9e4066Sahrens } 4632fa9e4066Sahrens 4633fa9e4066Sahrens int 4634fa9e4066Sahrens zonecfg_lookup_ds(zone_dochandle_t handle, struct zone_dstab *tabptr) 4635fa9e4066Sahrens { 4636fa9e4066Sahrens xmlNodePtr cur, firstmatch; 4637fa9e4066Sahrens int err; 4638fa9e4066Sahrens char dataset[MAXNAMELEN]; 4639fa9e4066Sahrens 4640fa9e4066Sahrens if (tabptr == NULL) 4641fa9e4066Sahrens return (Z_INVAL); 4642fa9e4066Sahrens 4643fa9e4066Sahrens if ((err = operation_prep(handle)) != Z_OK) 4644fa9e4066Sahrens return (err); 4645fa9e4066Sahrens 4646fa9e4066Sahrens cur = handle->zone_dh_cur; 4647fa9e4066Sahrens firstmatch = NULL; 4648fa9e4066Sahrens for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 4649fa9e4066Sahrens if (xmlStrcmp(cur->name, DTD_ELEM_DATASET)) 4650fa9e4066Sahrens continue; 4651fa9e4066Sahrens if (strlen(tabptr->zone_dataset_name) > 0) { 4652fa9e4066Sahrens if ((fetchprop(cur, DTD_ATTR_NAME, dataset, 4653fa9e4066Sahrens sizeof (dataset)) == Z_OK) && 4654fa9e4066Sahrens (strcmp(tabptr->zone_dataset_name, 4655fa9e4066Sahrens dataset) == 0)) { 4656fa9e4066Sahrens if (firstmatch == NULL) 4657fa9e4066Sahrens firstmatch = cur; 4658fa9e4066Sahrens else 4659fa9e4066Sahrens return (Z_INSUFFICIENT_SPEC); 4660fa9e4066Sahrens } 4661fa9e4066Sahrens } 4662fa9e4066Sahrens } 4663fa9e4066Sahrens if (firstmatch == NULL) 4664fa9e4066Sahrens return (Z_NO_RESOURCE_ID); 4665fa9e4066Sahrens 4666fa9e4066Sahrens cur = firstmatch; 4667fa9e4066Sahrens 4668fa9e4066Sahrens if ((err = fetchprop(cur, DTD_ATTR_NAME, tabptr->zone_dataset_name, 4669fa9e4066Sahrens sizeof (tabptr->zone_dataset_name))) != Z_OK) 4670fa9e4066Sahrens return (err); 4671fa9e4066Sahrens 4672fa9e4066Sahrens return (Z_OK); 4673fa9e4066Sahrens } 4674fa9e4066Sahrens 4675fa9e4066Sahrens int 4676fa9e4066Sahrens zonecfg_setdsent(zone_dochandle_t handle) 4677fa9e4066Sahrens { 4678fa9e4066Sahrens return (zonecfg_setent(handle)); 4679fa9e4066Sahrens } 4680fa9e4066Sahrens 4681fa9e4066Sahrens int 4682fa9e4066Sahrens zonecfg_getdsent(zone_dochandle_t handle, struct zone_dstab *tabptr) 4683fa9e4066Sahrens { 4684fa9e4066Sahrens xmlNodePtr cur; 4685fa9e4066Sahrens int err; 4686fa9e4066Sahrens 4687fa9e4066Sahrens if (handle == NULL) 4688fa9e4066Sahrens return (Z_INVAL); 4689fa9e4066Sahrens 4690fa9e4066Sahrens if ((cur = handle->zone_dh_cur) == NULL) 4691fa9e4066Sahrens return (Z_NO_ENTRY); 4692fa9e4066Sahrens 4693fa9e4066Sahrens for (; cur != NULL; cur = cur->next) 4694fa9e4066Sahrens if (!xmlStrcmp(cur->name, DTD_ELEM_DATASET)) 4695fa9e4066Sahrens break; 4696fa9e4066Sahrens if (cur == NULL) { 4697fa9e4066Sahrens handle->zone_dh_cur = handle->zone_dh_top; 4698fa9e4066Sahrens return (Z_NO_ENTRY); 4699fa9e4066Sahrens } 4700fa9e4066Sahrens 4701fa9e4066Sahrens if ((err = fetchprop(cur, DTD_ATTR_NAME, tabptr->zone_dataset_name, 4702fa9e4066Sahrens sizeof (tabptr->zone_dataset_name))) != Z_OK) { 4703fa9e4066Sahrens handle->zone_dh_cur = handle->zone_dh_top; 4704fa9e4066Sahrens return (err); 4705fa9e4066Sahrens } 4706fa9e4066Sahrens 4707fa9e4066Sahrens handle->zone_dh_cur = cur->next; 4708fa9e4066Sahrens return (Z_OK); 4709fa9e4066Sahrens } 4710fa9e4066Sahrens 4711fa9e4066Sahrens int 4712fa9e4066Sahrens zonecfg_enddsent(zone_dochandle_t handle) 4713fa9e4066Sahrens { 4714fa9e4066Sahrens return (zonecfg_endent(handle)); 4715fa9e4066Sahrens } 4716ee519a1fSgjelinek 4717ee519a1fSgjelinek int 4718ee519a1fSgjelinek zonecfg_setpkgent(zone_dochandle_t handle) 4719ee519a1fSgjelinek { 4720ee519a1fSgjelinek return (zonecfg_setent(handle)); 4721ee519a1fSgjelinek } 4722ee519a1fSgjelinek 4723ee519a1fSgjelinek int 4724ee519a1fSgjelinek zonecfg_getpkgent(zone_dochandle_t handle, struct zone_pkgtab *tabptr) 4725ee519a1fSgjelinek { 4726ee519a1fSgjelinek xmlNodePtr cur; 4727ee519a1fSgjelinek int err; 4728ee519a1fSgjelinek 4729ee519a1fSgjelinek if (handle == NULL) 4730ee519a1fSgjelinek return (Z_INVAL); 4731ee519a1fSgjelinek 4732ee519a1fSgjelinek if ((cur = handle->zone_dh_cur) == NULL) 4733ee519a1fSgjelinek return (Z_NO_ENTRY); 4734ee519a1fSgjelinek 4735ee519a1fSgjelinek for (; cur != NULL; cur = cur->next) 4736ee519a1fSgjelinek if (!xmlStrcmp(cur->name, DTD_ELEM_PACKAGE)) 4737ee519a1fSgjelinek break; 4738ee519a1fSgjelinek if (cur == NULL) { 4739ee519a1fSgjelinek handle->zone_dh_cur = handle->zone_dh_top; 4740ee519a1fSgjelinek return (Z_NO_ENTRY); 4741ee519a1fSgjelinek } 4742ee519a1fSgjelinek 4743ee519a1fSgjelinek if ((err = fetchprop(cur, DTD_ATTR_NAME, tabptr->zone_pkg_name, 4744ee519a1fSgjelinek sizeof (tabptr->zone_pkg_name))) != Z_OK) { 4745ee519a1fSgjelinek handle->zone_dh_cur = handle->zone_dh_top; 4746ee519a1fSgjelinek return (err); 4747ee519a1fSgjelinek } 4748ee519a1fSgjelinek 4749ee519a1fSgjelinek if ((err = fetchprop(cur, DTD_ATTR_VERSION, tabptr->zone_pkg_version, 4750ee519a1fSgjelinek sizeof (tabptr->zone_pkg_version))) != Z_OK) { 4751ee519a1fSgjelinek handle->zone_dh_cur = handle->zone_dh_top; 4752ee519a1fSgjelinek return (err); 4753ee519a1fSgjelinek } 4754ee519a1fSgjelinek 4755ee519a1fSgjelinek handle->zone_dh_cur = cur->next; 4756ee519a1fSgjelinek return (Z_OK); 4757ee519a1fSgjelinek } 4758ee519a1fSgjelinek 4759ee519a1fSgjelinek int 4760ee519a1fSgjelinek zonecfg_endpkgent(zone_dochandle_t handle) 4761ee519a1fSgjelinek { 4762ee519a1fSgjelinek return (zonecfg_endent(handle)); 4763ee519a1fSgjelinek } 4764ee519a1fSgjelinek 4765ee519a1fSgjelinek int 4766ee519a1fSgjelinek zonecfg_setpatchent(zone_dochandle_t handle) 4767ee519a1fSgjelinek { 4768ee519a1fSgjelinek return (zonecfg_setent(handle)); 4769ee519a1fSgjelinek } 4770ee519a1fSgjelinek 4771ee519a1fSgjelinek int 4772ee519a1fSgjelinek zonecfg_getpatchent(zone_dochandle_t handle, struct zone_patchtab *tabptr) 4773ee519a1fSgjelinek { 4774ee519a1fSgjelinek xmlNodePtr cur; 4775ee519a1fSgjelinek int err; 4776ee519a1fSgjelinek 4777ee519a1fSgjelinek if (handle == NULL) 4778ee519a1fSgjelinek return (Z_INVAL); 4779ee519a1fSgjelinek 4780ee519a1fSgjelinek if ((cur = handle->zone_dh_cur) == NULL) 4781ee519a1fSgjelinek return (Z_NO_ENTRY); 4782ee519a1fSgjelinek 4783ee519a1fSgjelinek for (; cur != NULL; cur = cur->next) 4784ee519a1fSgjelinek if (!xmlStrcmp(cur->name, DTD_ELEM_PATCH)) 4785ee519a1fSgjelinek break; 4786ee519a1fSgjelinek if (cur == NULL) { 4787ee519a1fSgjelinek handle->zone_dh_cur = handle->zone_dh_top; 4788ee519a1fSgjelinek return (Z_NO_ENTRY); 4789ee519a1fSgjelinek } 4790ee519a1fSgjelinek 4791ee519a1fSgjelinek if ((err = fetchprop(cur, DTD_ATTR_ID, tabptr->zone_patch_id, 4792ee519a1fSgjelinek sizeof (tabptr->zone_patch_id))) != Z_OK) { 4793ee519a1fSgjelinek handle->zone_dh_cur = handle->zone_dh_top; 4794ee519a1fSgjelinek return (err); 4795ee519a1fSgjelinek } 4796ee519a1fSgjelinek 4797ee519a1fSgjelinek handle->zone_dh_cur = cur->next; 4798ee519a1fSgjelinek return (Z_OK); 4799ee519a1fSgjelinek } 4800ee519a1fSgjelinek 4801ee519a1fSgjelinek int 4802ee519a1fSgjelinek zonecfg_endpatchent(zone_dochandle_t handle) 4803ee519a1fSgjelinek { 4804ee519a1fSgjelinek return (zonecfg_endent(handle)); 4805ee519a1fSgjelinek } 4806ee519a1fSgjelinek 4807ee519a1fSgjelinek int 4808ee519a1fSgjelinek zonecfg_setdevperment(zone_dochandle_t handle) 4809ee519a1fSgjelinek { 4810ee519a1fSgjelinek return (zonecfg_setent(handle)); 4811ee519a1fSgjelinek } 4812ee519a1fSgjelinek 4813ee519a1fSgjelinek int 4814ee519a1fSgjelinek zonecfg_getdevperment(zone_dochandle_t handle, struct zone_devpermtab *tabptr) 4815ee519a1fSgjelinek { 4816ee519a1fSgjelinek xmlNodePtr cur; 4817ee519a1fSgjelinek int err; 4818ee519a1fSgjelinek char buf[128]; 4819ee519a1fSgjelinek 4820ee519a1fSgjelinek tabptr->zone_devperm_acl = NULL; 4821ee519a1fSgjelinek 4822ee519a1fSgjelinek if (handle == NULL) 4823ee519a1fSgjelinek return (Z_INVAL); 4824ee519a1fSgjelinek 4825ee519a1fSgjelinek if ((cur = handle->zone_dh_cur) == NULL) 4826ee519a1fSgjelinek return (Z_NO_ENTRY); 4827ee519a1fSgjelinek 4828ee519a1fSgjelinek for (; cur != NULL; cur = cur->next) 4829ee519a1fSgjelinek if (!xmlStrcmp(cur->name, DTD_ELEM_DEV_PERM)) 4830ee519a1fSgjelinek break; 4831ee519a1fSgjelinek if (cur == NULL) { 4832ee519a1fSgjelinek handle->zone_dh_cur = handle->zone_dh_top; 4833ee519a1fSgjelinek return (Z_NO_ENTRY); 4834ee519a1fSgjelinek } 4835ee519a1fSgjelinek 4836ee519a1fSgjelinek if ((err = fetchprop(cur, DTD_ATTR_NAME, tabptr->zone_devperm_name, 4837ee519a1fSgjelinek sizeof (tabptr->zone_devperm_name))) != Z_OK) { 4838ee519a1fSgjelinek handle->zone_dh_cur = handle->zone_dh_top; 4839ee519a1fSgjelinek return (err); 4840ee519a1fSgjelinek } 4841ee519a1fSgjelinek 4842ee519a1fSgjelinek if ((err = fetchprop(cur, DTD_ATTR_UID, buf, sizeof (buf))) != Z_OK) { 4843ee519a1fSgjelinek handle->zone_dh_cur = handle->zone_dh_top; 4844ee519a1fSgjelinek return (err); 4845ee519a1fSgjelinek } 4846ee519a1fSgjelinek tabptr->zone_devperm_uid = (uid_t)atol(buf); 4847ee519a1fSgjelinek 4848ee519a1fSgjelinek if ((err = fetchprop(cur, DTD_ATTR_GID, buf, sizeof (buf))) != Z_OK) { 4849ee519a1fSgjelinek handle->zone_dh_cur = handle->zone_dh_top; 4850ee519a1fSgjelinek return (err); 4851ee519a1fSgjelinek } 4852ee519a1fSgjelinek tabptr->zone_devperm_gid = (gid_t)atol(buf); 4853ee519a1fSgjelinek 4854ee519a1fSgjelinek if ((err = fetchprop(cur, DTD_ATTR_MODE, buf, sizeof (buf))) != Z_OK) { 4855ee519a1fSgjelinek handle->zone_dh_cur = handle->zone_dh_top; 4856ee519a1fSgjelinek return (err); 4857ee519a1fSgjelinek } 4858ee519a1fSgjelinek tabptr->zone_devperm_mode = (mode_t)strtol(buf, (char **)NULL, 8); 4859ee519a1fSgjelinek 4860ee519a1fSgjelinek if ((err = fetch_alloc_prop(cur, DTD_ATTR_ACL, 4861ee519a1fSgjelinek &(tabptr->zone_devperm_acl))) != Z_OK) { 4862ee519a1fSgjelinek handle->zone_dh_cur = handle->zone_dh_top; 4863ee519a1fSgjelinek return (err); 4864ee519a1fSgjelinek } 4865ee519a1fSgjelinek 4866ee519a1fSgjelinek handle->zone_dh_cur = cur->next; 4867ee519a1fSgjelinek return (Z_OK); 4868ee519a1fSgjelinek } 4869ee519a1fSgjelinek 4870ee519a1fSgjelinek int 4871ee519a1fSgjelinek zonecfg_enddevperment(zone_dochandle_t handle) 4872ee519a1fSgjelinek { 4873ee519a1fSgjelinek return (zonecfg_endent(handle)); 4874ee519a1fSgjelinek } 4875ee519a1fSgjelinek 4876ee519a1fSgjelinek /* 4877ee519a1fSgjelinek * Process a list of pkgs from an entry in the contents file, adding each pkg 4878ee519a1fSgjelinek * name to the list of pkgs. 4879ee519a1fSgjelinek * 4880ee519a1fSgjelinek * It is possible for the pkg name to be preceeded by a special character 4881ee519a1fSgjelinek * which indicates some bookkeeping information for pkging. Check if the 4882ee519a1fSgjelinek * first char is not an Alpha char. If so, skip over it. 4883ee519a1fSgjelinek */ 4884ee519a1fSgjelinek static int 4885ee519a1fSgjelinek add_pkg_list(char *lastp, char ***plist, int *pcnt) 4886ee519a1fSgjelinek { 4887ee519a1fSgjelinek char *p; 4888ee519a1fSgjelinek int pkg_cnt = *pcnt; 4889ee519a1fSgjelinek char **pkgs = *plist; 4890ee519a1fSgjelinek int res = Z_OK; 4891ee519a1fSgjelinek 4892ee519a1fSgjelinek while ((p = strtok_r(NULL, " ", &lastp)) != NULL) { 4893ee519a1fSgjelinek char **tmpp; 4894ee519a1fSgjelinek int i; 4895ee519a1fSgjelinek 4896ee519a1fSgjelinek /* skip over any special pkg bookkeeping char */ 4897ee519a1fSgjelinek if (!isalpha(*p)) 4898ee519a1fSgjelinek p++; 4899ee519a1fSgjelinek 4900ee519a1fSgjelinek /* Check if the pkg is already in the list */ 4901ee519a1fSgjelinek for (i = 0; i < pkg_cnt; i++) { 4902ee519a1fSgjelinek if (strcmp(p, pkgs[i]) == 0) 4903ee519a1fSgjelinek break; 4904ee519a1fSgjelinek } 4905ee519a1fSgjelinek 4906ee519a1fSgjelinek if (i < pkg_cnt) 4907ee519a1fSgjelinek continue; 4908ee519a1fSgjelinek 4909ee519a1fSgjelinek /* The pkg is not in the list; add it. */ 4910ee519a1fSgjelinek if ((tmpp = (char **)realloc(pkgs, 4911ee519a1fSgjelinek sizeof (char *) * (pkg_cnt + 1))) == NULL) { 4912ee519a1fSgjelinek res = Z_NOMEM; 4913ee519a1fSgjelinek break; 4914ee519a1fSgjelinek } 4915ee519a1fSgjelinek pkgs = tmpp; 4916ee519a1fSgjelinek 4917ee519a1fSgjelinek if ((pkgs[pkg_cnt] = strdup(p)) == NULL) { 4918ee519a1fSgjelinek res = Z_NOMEM; 4919ee519a1fSgjelinek break; 4920ee519a1fSgjelinek } 4921ee519a1fSgjelinek pkg_cnt++; 4922ee519a1fSgjelinek } 4923ee519a1fSgjelinek 4924ee519a1fSgjelinek *plist = pkgs; 4925ee519a1fSgjelinek *pcnt = pkg_cnt; 4926ee519a1fSgjelinek 4927ee519a1fSgjelinek return (res); 4928ee519a1fSgjelinek } 4929ee519a1fSgjelinek 4930ee519a1fSgjelinek /* 4931ee519a1fSgjelinek * Process an entry from the contents file (type "directory") and if the 4932ee519a1fSgjelinek * directory path is in the list of paths, add the associated list of pkgs 4933ee519a1fSgjelinek * to the pkg list. The input parameter "entry" will be broken up by 4934ee519a1fSgjelinek * the parser within this function so its value will be modified when this 4935ee519a1fSgjelinek * function exits. 4936ee519a1fSgjelinek * 4937ee519a1fSgjelinek * The entries we are looking for will look something like: 4938ee519a1fSgjelinek * /usr d none 0755 root sys SUNWctpls SUNWidnl SUNWlibCf .... 4939ee519a1fSgjelinek */ 4940ee519a1fSgjelinek static int 4941ee519a1fSgjelinek get_path_pkgs(char *entry, char **paths, int cnt, char ***pkgs, int *pkg_cnt) 4942ee519a1fSgjelinek { 4943ee519a1fSgjelinek char *f1; 4944ee519a1fSgjelinek char *f2; 4945ee519a1fSgjelinek char *lastp; 4946ee519a1fSgjelinek int i; 4947ee519a1fSgjelinek int res = Z_OK; 4948ee519a1fSgjelinek 4949ee519a1fSgjelinek if ((f1 = strtok_r(entry, " ", &lastp)) == NULL || 4950ee519a1fSgjelinek (f2 = strtok_r(NULL, " ", &lastp)) == NULL || strcmp(f2, "d") != 0) 4951ee519a1fSgjelinek return (Z_OK); 4952ee519a1fSgjelinek 4953ee519a1fSgjelinek /* Check if this directory entry is in the list of paths. */ 4954ee519a1fSgjelinek for (i = 0; i < cnt; i++) { 4955ee519a1fSgjelinek if (fnmatch(paths[i], f1, FNM_PATHNAME) == 0) { 4956ee519a1fSgjelinek /* 4957ee519a1fSgjelinek * We do want the pkgs for this path. First, skip 4958ee519a1fSgjelinek * over the next 4 fields in the entry so that we call 4959ee519a1fSgjelinek * add_pkg_list starting with the pkg names. 4960ee519a1fSgjelinek */ 4961ee519a1fSgjelinek int j; 496207b574eeSgjelinek char *nlp; 4963ee519a1fSgjelinek 4964ee519a1fSgjelinek for (j = 0; j < 4 && 4965ffbafc53Scomay strtok_r(NULL, " ", &lastp) != NULL; j++) 4966ffbafc53Scomay ; 4967ee519a1fSgjelinek /* 4968ee519a1fSgjelinek * If there are < 4 fields this entry is corrupt, 4969ee519a1fSgjelinek * just skip it. 4970ee519a1fSgjelinek */ 4971ee519a1fSgjelinek if (j < 4) 4972ee519a1fSgjelinek return (Z_OK); 4973ee519a1fSgjelinek 497407b574eeSgjelinek /* strip newline from the line */ 497507b574eeSgjelinek nlp = (lastp + strlen(lastp) - 1); 497607b574eeSgjelinek if (*nlp == '\n') 497707b574eeSgjelinek *nlp = '\0'; 497807b574eeSgjelinek 4979ee519a1fSgjelinek res = add_pkg_list(lastp, pkgs, pkg_cnt); 4980ee519a1fSgjelinek break; 4981ee519a1fSgjelinek } 4982ee519a1fSgjelinek } 4983ee519a1fSgjelinek 4984ee519a1fSgjelinek return (res); 4985ee519a1fSgjelinek } 4986ee519a1fSgjelinek 4987ee519a1fSgjelinek /* 4988ee519a1fSgjelinek * Read an entry from a pkginfo or contents file. Some of these lines can 4989ee519a1fSgjelinek * either be arbitrarily long or be continued by a backslash at the end of 4990ee519a1fSgjelinek * the line. This function coalesces lines that are longer than the read 4991ee519a1fSgjelinek * buffer, and lines that are continued, into one buffer which is returned. 4992ee519a1fSgjelinek * The caller must free this memory. NULL is returned when we hit EOF or 4993ee519a1fSgjelinek * if we run out of memory (errno is set to ENOMEM). 4994ee519a1fSgjelinek */ 4995ee519a1fSgjelinek static char * 4996ee519a1fSgjelinek read_pkg_data(FILE *fp) 4997ee519a1fSgjelinek { 4998ee519a1fSgjelinek char *start; 4999ee519a1fSgjelinek char *inp; 5000ee519a1fSgjelinek char *p; 5001ee519a1fSgjelinek int char_cnt = 0; 5002ee519a1fSgjelinek 5003ee519a1fSgjelinek errno = 0; 5004ee519a1fSgjelinek if ((start = (char *)malloc(PKGINFO_RD_LEN)) == NULL) { 5005ee519a1fSgjelinek errno = ENOMEM; 5006ee519a1fSgjelinek return (NULL); 5007ee519a1fSgjelinek } 5008ee519a1fSgjelinek 5009ee519a1fSgjelinek inp = start; 5010ee519a1fSgjelinek while ((p = fgets(inp, PKGINFO_RD_LEN, fp)) != NULL) { 5011ee519a1fSgjelinek int len; 5012ee519a1fSgjelinek 5013ee519a1fSgjelinek len = strlen(inp); 5014ee519a1fSgjelinek if (inp[len - 1] == '\n' && 5015ee519a1fSgjelinek (len == 1 || inp[len - 2] != '\\')) { 5016ee519a1fSgjelinek char_cnt = len; 5017ee519a1fSgjelinek break; 5018ee519a1fSgjelinek } 5019ee519a1fSgjelinek 5020ee519a1fSgjelinek if (inp[len - 2] == '\\') 5021ee519a1fSgjelinek char_cnt += len - 2; 5022ee519a1fSgjelinek else 5023ee519a1fSgjelinek char_cnt += PKGINFO_RD_LEN - 1; 5024ee519a1fSgjelinek 5025ee519a1fSgjelinek if ((p = realloc(start, char_cnt + PKGINFO_RD_LEN)) == NULL) { 5026ee519a1fSgjelinek errno = ENOMEM; 5027ee519a1fSgjelinek break; 5028ee519a1fSgjelinek } 5029ee519a1fSgjelinek 5030ee519a1fSgjelinek start = p; 5031ee519a1fSgjelinek inp = start + char_cnt; 5032ee519a1fSgjelinek } 5033ee519a1fSgjelinek 5034ee519a1fSgjelinek if (errno == ENOMEM || (p == NULL && char_cnt == 0)) { 5035ee519a1fSgjelinek free(start); 5036ee519a1fSgjelinek start = NULL; 5037ee519a1fSgjelinek } 5038ee519a1fSgjelinek 5039ee519a1fSgjelinek return (start); 5040ee519a1fSgjelinek } 5041ee519a1fSgjelinek 5042ee519a1fSgjelinek static void 5043ee519a1fSgjelinek free_ipd_pkgs(char **pkgs, int cnt) 5044ee519a1fSgjelinek { 5045ee519a1fSgjelinek int i; 5046ee519a1fSgjelinek 5047ee519a1fSgjelinek for (i = 0; i < cnt; i++) 5048ee519a1fSgjelinek free(pkgs[i]); 5049ee519a1fSgjelinek free(pkgs); 5050ee519a1fSgjelinek } 5051ee519a1fSgjelinek 5052ee519a1fSgjelinek /* 5053ee519a1fSgjelinek * Get the list of inherited-pkg-dirs (ipd) for the zone and then get the 5054ee519a1fSgjelinek * list of pkgs that deliver into those dirs. 5055ee519a1fSgjelinek */ 5056ee519a1fSgjelinek static int 5057ee519a1fSgjelinek get_ipd_pkgs(zone_dochandle_t handle, char ***pkg_list, int *cnt) 5058ee519a1fSgjelinek { 5059ee519a1fSgjelinek int res; 5060ee519a1fSgjelinek struct zone_fstab fstab; 5061ee519a1fSgjelinek int ipd_cnt = 0; 5062ee519a1fSgjelinek char **ipds = NULL; 5063ee519a1fSgjelinek int pkg_cnt = 0; 5064ee519a1fSgjelinek char **pkgs = NULL; 5065ee519a1fSgjelinek int i; 5066ee519a1fSgjelinek 5067ee519a1fSgjelinek if ((res = zonecfg_setipdent(handle)) != Z_OK) 5068ee519a1fSgjelinek return (res); 5069ee519a1fSgjelinek 5070ee519a1fSgjelinek while (zonecfg_getipdent(handle, &fstab) == Z_OK) { 5071ee519a1fSgjelinek char **p; 5072ee519a1fSgjelinek int len; 5073ee519a1fSgjelinek 5074ee519a1fSgjelinek if ((p = (char **)realloc(ipds, 5075ee519a1fSgjelinek sizeof (char *) * (ipd_cnt + 2))) == NULL) { 5076ee519a1fSgjelinek res = Z_NOMEM; 5077ee519a1fSgjelinek break; 5078ee519a1fSgjelinek } 5079ee519a1fSgjelinek ipds = p; 5080ee519a1fSgjelinek 5081ee519a1fSgjelinek if ((ipds[ipd_cnt] = strdup(fstab.zone_fs_dir)) == NULL) { 5082ee519a1fSgjelinek res = Z_NOMEM; 5083ee519a1fSgjelinek break; 5084ee519a1fSgjelinek } 5085ee519a1fSgjelinek ipd_cnt++; 5086ee519a1fSgjelinek 5087ee519a1fSgjelinek len = strlen(fstab.zone_fs_dir) + 3; 5088ee519a1fSgjelinek if ((ipds[ipd_cnt] = malloc(len)) == NULL) { 5089ee519a1fSgjelinek res = Z_NOMEM; 5090ee519a1fSgjelinek break; 5091ee519a1fSgjelinek } 5092ee519a1fSgjelinek 5093ee519a1fSgjelinek (void) snprintf(ipds[ipd_cnt], len, "%s/*", fstab.zone_fs_dir); 5094ee519a1fSgjelinek ipd_cnt++; 5095ee519a1fSgjelinek } 5096ee519a1fSgjelinek 5097ee519a1fSgjelinek (void) zonecfg_endipdent(handle); 5098ee519a1fSgjelinek 5099ee519a1fSgjelinek if (res != Z_OK) { 5100ee519a1fSgjelinek for (i = 0; i < ipd_cnt; i++) 5101ee519a1fSgjelinek free(ipds[i]); 5102ee519a1fSgjelinek free(ipds); 5103ee519a1fSgjelinek return (res); 5104ee519a1fSgjelinek } 5105ee519a1fSgjelinek 5106ee519a1fSgjelinek /* We only have to process the contents file if we have ipds. */ 5107ee519a1fSgjelinek if (ipd_cnt > 0) { 5108ee519a1fSgjelinek FILE *fp; 5109ee519a1fSgjelinek 5110ee519a1fSgjelinek if ((fp = fopen(CONTENTS_FILE, "r")) != NULL) { 5111ee519a1fSgjelinek char *buf; 5112ee519a1fSgjelinek 5113ee519a1fSgjelinek while ((buf = read_pkg_data(fp)) != NULL) { 5114ee519a1fSgjelinek res = get_path_pkgs(buf, ipds, ipd_cnt, &pkgs, 5115ee519a1fSgjelinek &pkg_cnt); 5116ee519a1fSgjelinek free(buf); 5117ee519a1fSgjelinek if (res != Z_OK) 5118ee519a1fSgjelinek break; 5119ee519a1fSgjelinek } 5120ee519a1fSgjelinek 5121ee519a1fSgjelinek (void) fclose(fp); 5122ee519a1fSgjelinek } 5123ee519a1fSgjelinek } 5124ee519a1fSgjelinek 5125ee519a1fSgjelinek for (i = 0; i < ipd_cnt; i++) 5126ee519a1fSgjelinek free(ipds[i]); 5127ee519a1fSgjelinek free(ipds); 5128ee519a1fSgjelinek 5129ee519a1fSgjelinek if (res != Z_OK) { 5130ee519a1fSgjelinek free_ipd_pkgs(pkgs, pkg_cnt); 5131ee519a1fSgjelinek } else { 5132ee519a1fSgjelinek *pkg_list = pkgs; 5133ee519a1fSgjelinek *cnt = pkg_cnt; 5134ee519a1fSgjelinek } 5135ee519a1fSgjelinek 5136ee519a1fSgjelinek return (res); 5137ee519a1fSgjelinek } 5138ee519a1fSgjelinek 5139ee519a1fSgjelinek /* 5140ee519a1fSgjelinek * Return true if pkg_name is in the list of pkgs that deliver into an 5141ee519a1fSgjelinek * inherited pkg directory for the zone. 5142ee519a1fSgjelinek */ 5143ee519a1fSgjelinek static boolean_t 5144ee519a1fSgjelinek dir_pkg(char *pkg_name, char **pkg_list, int cnt) 5145ee519a1fSgjelinek { 5146ee519a1fSgjelinek int i; 5147ee519a1fSgjelinek 5148ee519a1fSgjelinek for (i = 0; i < cnt; i++) { 5149ee519a1fSgjelinek if (strcmp(pkg_name, pkg_list[i]) == 0) 5150ee519a1fSgjelinek return (B_TRUE); 5151ee519a1fSgjelinek } 5152ee519a1fSgjelinek 5153ee519a1fSgjelinek return (B_FALSE); 5154ee519a1fSgjelinek } 5155ee519a1fSgjelinek 5156ee519a1fSgjelinek /* 5157ee519a1fSgjelinek * Start by adding the patch to the sw inventory on the handle. 5158ee519a1fSgjelinek * 5159ee519a1fSgjelinek * The info parameter will be the portion of the PATCH_INFO_ entry following 5160ee519a1fSgjelinek * the '='. For example: 5161ee519a1fSgjelinek * Installed: Wed Dec 7 07:13:51 PST 2005 From: mum Obsoletes: 120777-03 \ 5162ee519a1fSgjelinek * 121087-02 119108-07 Requires: 119575-02 119255-06 Incompatibles: 5163ee519a1fSgjelinek * 516407b574eeSgjelinek * A backed out patch will have an info line of "backed out\n". We should 516507b574eeSgjelinek * skip these patches. 516607b574eeSgjelinek * 5167ee519a1fSgjelinek * We also want to add the Obsolete and Incompatible patches to the 5168ee519a1fSgjelinek * sw inventory description of this patch. 5169ee519a1fSgjelinek */ 5170ee519a1fSgjelinek static int 5171ee519a1fSgjelinek add_patch(zone_dochandle_t handle, char *patch, char *info) 5172ee519a1fSgjelinek { 5173ee519a1fSgjelinek xmlNodePtr node; 5174ee519a1fSgjelinek xmlNodePtr cur; 5175ee519a1fSgjelinek int err; 5176ee519a1fSgjelinek char *p; 5177ee519a1fSgjelinek char *lastp; 5178ee519a1fSgjelinek boolean_t add_info = B_FALSE; 5179ee519a1fSgjelinek boolean_t obsolete; 5180ee519a1fSgjelinek 518107b574eeSgjelinek if (strcmp(info, "backed out\n") == 0) 518207b574eeSgjelinek return (Z_OK); 518307b574eeSgjelinek 5184ee519a1fSgjelinek if ((err = operation_prep(handle)) != Z_OK) 5185ee519a1fSgjelinek return (err); 5186ee519a1fSgjelinek 5187ee519a1fSgjelinek cur = handle->zone_dh_cur; 5188ee519a1fSgjelinek node = xmlNewTextChild(cur, NULL, DTD_ELEM_PATCH, NULL); 5189ee519a1fSgjelinek if ((err = newprop(node, DTD_ATTR_ID, patch)) != Z_OK) 5190ee519a1fSgjelinek return (err); 5191ee519a1fSgjelinek 5192ee519a1fSgjelinek /* 5193ee519a1fSgjelinek * Start with the first token. This will probably be "Installed:". 5194ee519a1fSgjelinek * If we can't tokenize this entry, just return. 5195ee519a1fSgjelinek */ 5196ee519a1fSgjelinek if ((p = strtok_r(info, " ", &lastp)) == NULL) 5197ee519a1fSgjelinek return (Z_OK); 5198ee519a1fSgjelinek 5199ee519a1fSgjelinek do { 5200ee519a1fSgjelinek xmlNodePtr new_node; 5201ee519a1fSgjelinek char *nlp; 5202ee519a1fSgjelinek 5203ee519a1fSgjelinek if (strcmp(p, "Installed:") == 0 || 5204ee519a1fSgjelinek strcmp(p, "Requires:") == 0 || 5205ee519a1fSgjelinek strcmp(p, "From:") == 0) { 5206ee519a1fSgjelinek add_info = B_FALSE; 5207ee519a1fSgjelinek continue; 5208ee519a1fSgjelinek } else if (strcmp(p, "Obsoletes:") == 0) { 5209ee519a1fSgjelinek obsolete = B_TRUE; 5210ee519a1fSgjelinek add_info = B_TRUE; 5211ee519a1fSgjelinek continue; 5212ee519a1fSgjelinek } else if (strcmp(p, "Incompatibles:") == 0) { 5213ee519a1fSgjelinek obsolete = B_FALSE; 5214ee519a1fSgjelinek add_info = B_TRUE; 5215ee519a1fSgjelinek continue; 5216ee519a1fSgjelinek } 5217ee519a1fSgjelinek 5218ee519a1fSgjelinek if (!add_info) 5219ee519a1fSgjelinek continue; 5220ee519a1fSgjelinek 5221ee519a1fSgjelinek /* strip newline from last patch in the line */ 5222ee519a1fSgjelinek nlp = (p + strlen(p) - 1); 5223ee519a1fSgjelinek if (*nlp == '\n') 5224ee519a1fSgjelinek *nlp = '\0'; 5225ee519a1fSgjelinek 5226ee519a1fSgjelinek if (obsolete) 5227ee519a1fSgjelinek new_node = xmlNewTextChild(node, NULL, 5228ee519a1fSgjelinek DTD_ELEM_OBSOLETES, NULL); 5229ee519a1fSgjelinek else 5230ee519a1fSgjelinek new_node = xmlNewTextChild(node, NULL, 5231ee519a1fSgjelinek DTD_ELEM_INCOMPATIBLE, NULL); 5232ee519a1fSgjelinek 5233ee519a1fSgjelinek if ((err = newprop(new_node, DTD_ATTR_ID, p)) != Z_OK) 5234ee519a1fSgjelinek return (err); 5235ee519a1fSgjelinek 5236ee519a1fSgjelinek } while ((p = strtok_r(NULL, " ", &lastp)) != NULL); 5237ee519a1fSgjelinek 5238ee519a1fSgjelinek return (Z_OK); 5239ee519a1fSgjelinek } 5240ee519a1fSgjelinek 5241ee519a1fSgjelinek static boolean_t 5242ee519a1fSgjelinek unique_patch(zone_dochandle_t handle, char *patch) 5243ee519a1fSgjelinek { 5244ee519a1fSgjelinek xmlNodePtr cur; 5245ee519a1fSgjelinek char id[MAXNAMELEN]; 5246ee519a1fSgjelinek 5247ee519a1fSgjelinek cur = xmlDocGetRootElement(handle->zone_dh_doc); 5248ee519a1fSgjelinek for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 5249ee519a1fSgjelinek if (xmlStrcmp(cur->name, DTD_ELEM_PATCH) == 0) { 5250ee519a1fSgjelinek if (fetchprop(cur, DTD_ATTR_ID, id, sizeof (id)) 5251ee519a1fSgjelinek != Z_OK) 5252ee519a1fSgjelinek continue; 5253ee519a1fSgjelinek 5254ee519a1fSgjelinek if (strcmp(patch, id) == 0) 5255ee519a1fSgjelinek return (B_FALSE); 5256ee519a1fSgjelinek } 5257ee519a1fSgjelinek } 5258ee519a1fSgjelinek 5259ee519a1fSgjelinek return (B_TRUE); 5260ee519a1fSgjelinek } 5261ee519a1fSgjelinek 5262ee519a1fSgjelinek /* 5263ee519a1fSgjelinek * Add the unique patches associated with this pkg to the sw inventory on the 5264ee519a1fSgjelinek * handle. 5265ee519a1fSgjelinek * 5266ee519a1fSgjelinek * We are processing entries of the form: 5267ee519a1fSgjelinek * PATCH_INFO_121454-02=Installed: Wed Dec 7 07:13:51 PST 2005 From: mum \ 5268ee519a1fSgjelinek * Obsoletes: 120777-03 121087-02 119108-07 Requires: 119575-02 \ 5269ee519a1fSgjelinek * 119255-06 Incompatibles: 5270ee519a1fSgjelinek * 5271ee519a1fSgjelinek */ 5272ee519a1fSgjelinek static int 5273ee519a1fSgjelinek add_patches(zone_dochandle_t handle, struct zone_pkginfo *infop) 5274ee519a1fSgjelinek { 5275ee519a1fSgjelinek int i; 5276ee519a1fSgjelinek int res = Z_OK; 5277ee519a1fSgjelinek 5278ee519a1fSgjelinek for (i = 0; i < infop->zpi_patch_cnt; i++) { 5279ee519a1fSgjelinek char *p, *ep; 5280ee519a1fSgjelinek 5281ee519a1fSgjelinek if (strlen(infop->zpi_patchinfo[i]) < (sizeof (PATCHINFO) - 1)) 5282ee519a1fSgjelinek continue; 5283ee519a1fSgjelinek 5284ee519a1fSgjelinek /* Skip over "PATCH_INFO_" to get the patch id. */ 5285ee519a1fSgjelinek p = infop->zpi_patchinfo[i] + sizeof (PATCHINFO) - 1; 5286ee519a1fSgjelinek if ((ep = strchr(p, '=')) == NULL) 5287ee519a1fSgjelinek continue; 5288ee519a1fSgjelinek 5289ee519a1fSgjelinek *ep = '\0'; 5290ee519a1fSgjelinek if (unique_patch(handle, p)) 529107b574eeSgjelinek if ((res = add_patch(handle, p, ep + 1)) != Z_OK) 529207b574eeSgjelinek break; 5293ee519a1fSgjelinek } 5294ee519a1fSgjelinek 5295ee519a1fSgjelinek return (res); 5296ee519a1fSgjelinek } 5297ee519a1fSgjelinek 5298ee519a1fSgjelinek /* 5299ee519a1fSgjelinek * Add the pkg to the sw inventory on the handle. 5300ee519a1fSgjelinek */ 5301ee519a1fSgjelinek static int 5302ee519a1fSgjelinek add_pkg(zone_dochandle_t handle, char *name, char *version) 5303ee519a1fSgjelinek { 5304ee519a1fSgjelinek xmlNodePtr newnode; 5305ee519a1fSgjelinek xmlNodePtr cur; 5306ee519a1fSgjelinek int err; 5307ee519a1fSgjelinek 5308ee519a1fSgjelinek if ((err = operation_prep(handle)) != Z_OK) 5309ee519a1fSgjelinek return (err); 5310ee519a1fSgjelinek 5311ee519a1fSgjelinek cur = handle->zone_dh_cur; 5312ee519a1fSgjelinek newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_PACKAGE, NULL); 5313ee519a1fSgjelinek if ((err = newprop(newnode, DTD_ATTR_NAME, name)) != Z_OK) 5314ee519a1fSgjelinek return (err); 5315ee519a1fSgjelinek if ((err = newprop(newnode, DTD_ATTR_VERSION, version)) != Z_OK) 5316ee519a1fSgjelinek return (err); 5317ee519a1fSgjelinek return (Z_OK); 5318ee519a1fSgjelinek } 5319ee519a1fSgjelinek 5320ee519a1fSgjelinek static void 5321ee519a1fSgjelinek free_pkginfo(struct zone_pkginfo *infop) 5322ee519a1fSgjelinek { 5323ee519a1fSgjelinek free(infop->zpi_version); 5324ee519a1fSgjelinek if (infop->zpi_patch_cnt > 0) { 5325ee519a1fSgjelinek int i; 5326ee519a1fSgjelinek 5327ee519a1fSgjelinek for (i = 0; i < infop->zpi_patch_cnt; i++) 5328ee519a1fSgjelinek free(infop->zpi_patchinfo[i]); 5329ee519a1fSgjelinek free(infop->zpi_patchinfo); 5330ee519a1fSgjelinek } 5331ee519a1fSgjelinek } 5332ee519a1fSgjelinek 5333ee519a1fSgjelinek /* 5334ee519a1fSgjelinek * Read the pkginfo file and populate the structure with the data we need 5335ee519a1fSgjelinek * from this pkg for a sw inventory. 5336ee519a1fSgjelinek */ 5337ee519a1fSgjelinek static int 5338ee519a1fSgjelinek get_pkginfo(char *pkginfo, struct zone_pkginfo *infop) 5339ee519a1fSgjelinek { 5340ee519a1fSgjelinek FILE *fp; 5341ee519a1fSgjelinek char *buf; 5342ee519a1fSgjelinek int err = 0; 5343ee519a1fSgjelinek 5344ee519a1fSgjelinek infop->zpi_all_zones = B_FALSE; 5345ee519a1fSgjelinek infop->zpi_this_zone = B_FALSE; 5346ee519a1fSgjelinek infop->zpi_version = NULL; 5347ee519a1fSgjelinek infop->zpi_patch_cnt = 0; 5348ee519a1fSgjelinek infop->zpi_patchinfo = NULL; 5349ee519a1fSgjelinek 5350ee519a1fSgjelinek if ((fp = fopen(pkginfo, "r")) == NULL) 5351ee519a1fSgjelinek return (errno); 5352ee519a1fSgjelinek 5353ee519a1fSgjelinek while ((buf = read_pkg_data(fp)) != NULL) { 5354ee519a1fSgjelinek if (strncmp(buf, VERSION, sizeof (VERSION) - 1) == 0) { 5355ee519a1fSgjelinek int len; 5356ee519a1fSgjelinek 5357ee519a1fSgjelinek if ((infop->zpi_version = 5358ee519a1fSgjelinek strdup(buf + sizeof (VERSION) - 1)) == NULL) { 5359ee519a1fSgjelinek err = ENOMEM; 5360ee519a1fSgjelinek break; 5361ee519a1fSgjelinek } 5362ee519a1fSgjelinek 5363ee519a1fSgjelinek /* remove trailing newline */ 5364ee519a1fSgjelinek len = strlen(infop->zpi_version); 5365ee519a1fSgjelinek *(infop->zpi_version + len - 1) = 0; 5366ee519a1fSgjelinek 536745916cd2Sjpk } else if (strcmp(buf, SUNW_PKG_ALL_ZONES) == 0) { 5368ee519a1fSgjelinek infop->zpi_all_zones = B_TRUE; 5369ee519a1fSgjelinek 537045916cd2Sjpk } else if (strcmp(buf, SUNW_PKG_THIS_ZONE) == 0) { 5371ee519a1fSgjelinek infop->zpi_this_zone = B_TRUE; 5372ee519a1fSgjelinek 5373ee519a1fSgjelinek } else if (strncmp(buf, PATCHINFO, sizeof (PATCHINFO) - 1) 5374ee519a1fSgjelinek == 0) { 5375ee519a1fSgjelinek char **p; 5376ee519a1fSgjelinek 5377ee519a1fSgjelinek if ((p = (char **)realloc(infop->zpi_patchinfo, 5378ee519a1fSgjelinek sizeof (char *) * (infop->zpi_patch_cnt + 1))) 5379ee519a1fSgjelinek == NULL) { 5380ee519a1fSgjelinek err = ENOMEM; 5381ee519a1fSgjelinek break; 5382ee519a1fSgjelinek } 5383ee519a1fSgjelinek infop->zpi_patchinfo = p; 5384ee519a1fSgjelinek 5385ee519a1fSgjelinek if ((infop->zpi_patchinfo[infop->zpi_patch_cnt] = 5386ee519a1fSgjelinek strdup(buf)) == NULL) { 5387ee519a1fSgjelinek err = ENOMEM; 5388ee519a1fSgjelinek break; 5389ee519a1fSgjelinek } 5390ee519a1fSgjelinek infop->zpi_patch_cnt++; 5391ee519a1fSgjelinek } 5392ee519a1fSgjelinek 5393ee519a1fSgjelinek free(buf); 5394ee519a1fSgjelinek } 5395ee519a1fSgjelinek 5396ee519a1fSgjelinek free(buf); 5397ee519a1fSgjelinek 5398ee519a1fSgjelinek if (errno == ENOMEM) { 5399ee519a1fSgjelinek err = ENOMEM; 5400ee519a1fSgjelinek /* Clean up anything we did manage to allocate. */ 5401ee519a1fSgjelinek free_pkginfo(infop); 5402ee519a1fSgjelinek } 5403ee519a1fSgjelinek 5404ee519a1fSgjelinek (void) fclose(fp); 5405ee519a1fSgjelinek 5406ee519a1fSgjelinek return (err); 5407ee519a1fSgjelinek } 5408ee519a1fSgjelinek 5409ee519a1fSgjelinek /* 5410ee519a1fSgjelinek * Take a software inventory of the global zone. We need to get the set of 5411ee519a1fSgjelinek * packages and patches that are on the global zone that the specified 5412ee519a1fSgjelinek * non-global zone depends on. The packages we need in the inventory are: 5413ee519a1fSgjelinek * 5414ee519a1fSgjelinek * - skip the package if SUNW_PKG_THISZONE is 'true' 5415ee519a1fSgjelinek * otherwise, 5416ee519a1fSgjelinek * - add the package if 5417ee519a1fSgjelinek * a) SUNW_PKG_ALLZONES is 'true', 5418ee519a1fSgjelinek * or 5419ee519a1fSgjelinek * b) any file delivered by the package is in a file system that is inherited 5420ee519a1fSgjelinek * from the global zone. 5421ee519a1fSgjelinek * If the zone does not inherit any file systems (whole root) 5422ee519a1fSgjelinek * then (b) will be skipped. 5423ee519a1fSgjelinek * 5424ee519a1fSgjelinek * For each of the packages that is being added to the inventory, we will also 5425ee519a1fSgjelinek * add all of the associated, unique patches to the inventory. 5426ee519a1fSgjelinek */ 5427ee519a1fSgjelinek static int 5428ee519a1fSgjelinek zonecfg_sw_inventory(zone_dochandle_t handle) 5429ee519a1fSgjelinek { 5430ee519a1fSgjelinek char pkginfo[MAXPATHLEN]; 5431ee519a1fSgjelinek int res; 5432ee519a1fSgjelinek struct dirent *dp; 5433ee519a1fSgjelinek DIR *dirp; 5434ee519a1fSgjelinek struct stat buf; 5435ee519a1fSgjelinek struct zone_pkginfo info; 5436ee519a1fSgjelinek int pkg_cnt = 0; 5437ee519a1fSgjelinek char **pkgs = NULL; 5438ee519a1fSgjelinek 5439ee519a1fSgjelinek if ((res = get_ipd_pkgs(handle, &pkgs, &pkg_cnt)) != Z_OK) 5440ee519a1fSgjelinek return (res); 5441ee519a1fSgjelinek 5442ee519a1fSgjelinek if ((dirp = opendir(PKG_PATH)) == NULL) { 5443ee519a1fSgjelinek free_ipd_pkgs(pkgs, pkg_cnt); 5444ee519a1fSgjelinek return (Z_OK); 5445ee519a1fSgjelinek } 5446ee519a1fSgjelinek 5447ee519a1fSgjelinek while ((dp = readdir(dirp)) != (struct dirent *)0) { 5448ee519a1fSgjelinek if (strcmp(dp->d_name, ".") == 0 || 5449ee519a1fSgjelinek strcmp(dp->d_name, "..") == 0) 5450ee519a1fSgjelinek continue; 5451ee519a1fSgjelinek 5452ee519a1fSgjelinek (void) snprintf(pkginfo, sizeof (pkginfo), "%s/%s/pkginfo", 5453ee519a1fSgjelinek PKG_PATH, dp->d_name); 5454ee519a1fSgjelinek 5455ee519a1fSgjelinek if (stat(pkginfo, &buf) == -1 || !S_ISREG(buf.st_mode)) 5456ee519a1fSgjelinek continue; 5457ee519a1fSgjelinek 5458ee519a1fSgjelinek if (get_pkginfo(pkginfo, &info) != 0) { 5459ee519a1fSgjelinek res = Z_NOMEM; 5460ee519a1fSgjelinek break; 5461ee519a1fSgjelinek } 5462ee519a1fSgjelinek 5463ee519a1fSgjelinek if (!info.zpi_this_zone && 5464ee519a1fSgjelinek (info.zpi_all_zones || 5465ee519a1fSgjelinek dir_pkg(dp->d_name, pkgs, pkg_cnt))) { 5466ee519a1fSgjelinek if ((res = add_pkg(handle, dp->d_name, 5467ee519a1fSgjelinek info.zpi_version)) == Z_OK) { 5468ee519a1fSgjelinek if (info.zpi_patch_cnt > 0) 5469ee519a1fSgjelinek res = add_patches(handle, &info); 5470ee519a1fSgjelinek } 5471ee519a1fSgjelinek } 5472ee519a1fSgjelinek 5473ee519a1fSgjelinek free_pkginfo(&info); 5474ee519a1fSgjelinek 5475ee519a1fSgjelinek if (res != Z_OK) 5476ee519a1fSgjelinek break; 5477ee519a1fSgjelinek } 5478ee519a1fSgjelinek 5479ee519a1fSgjelinek (void) closedir(dirp); 5480ee519a1fSgjelinek 5481ee519a1fSgjelinek free_ipd_pkgs(pkgs, pkg_cnt); 5482ee519a1fSgjelinek 5483ee519a1fSgjelinek if (res == Z_OK) 5484ee519a1fSgjelinek handle->zone_dh_sw_inv = B_TRUE; 5485ee519a1fSgjelinek 5486ee519a1fSgjelinek return (res); 5487ee519a1fSgjelinek } 5488ee519a1fSgjelinek 5489ee519a1fSgjelinek /* 5490ee519a1fSgjelinek * zonecfg_devwalk call-back function used during detach to generate the 5491ee519a1fSgjelinek * dev info in the manifest. 5492ee519a1fSgjelinek */ 5493ee519a1fSgjelinek static int 5494ee519a1fSgjelinek get_detach_dev_entry(const char *name, uid_t uid, gid_t gid, mode_t mode, 5495ee519a1fSgjelinek const char *acl, void *hdl) 5496ee519a1fSgjelinek { 5497ee519a1fSgjelinek zone_dochandle_t handle = (zone_dochandle_t)hdl; 5498ee519a1fSgjelinek xmlNodePtr newnode; 5499ee519a1fSgjelinek xmlNodePtr cur; 5500ee519a1fSgjelinek int err; 5501ee519a1fSgjelinek char buf[128]; 5502ee519a1fSgjelinek 5503ee519a1fSgjelinek if ((err = operation_prep(handle)) != Z_OK) 5504ee519a1fSgjelinek return (err); 5505ee519a1fSgjelinek 5506ee519a1fSgjelinek cur = handle->zone_dh_cur; 5507ee519a1fSgjelinek newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_DEV_PERM, NULL); 5508ee519a1fSgjelinek if ((err = newprop(newnode, DTD_ATTR_NAME, (char *)name)) != Z_OK) 5509ee519a1fSgjelinek return (err); 5510ee519a1fSgjelinek (void) snprintf(buf, sizeof (buf), "%lu", uid); 5511ee519a1fSgjelinek if ((err = newprop(newnode, DTD_ATTR_UID, buf)) != Z_OK) 5512ee519a1fSgjelinek return (err); 5513ee519a1fSgjelinek (void) snprintf(buf, sizeof (buf), "%lu", gid); 5514ee519a1fSgjelinek if ((err = newprop(newnode, DTD_ATTR_GID, buf)) != Z_OK) 5515ee519a1fSgjelinek return (err); 5516ee519a1fSgjelinek (void) snprintf(buf, sizeof (buf), "%o", mode); 5517ee519a1fSgjelinek if ((err = newprop(newnode, DTD_ATTR_MODE, buf)) != Z_OK) 5518ee519a1fSgjelinek return (err); 5519ee519a1fSgjelinek if ((err = newprop(newnode, DTD_ATTR_ACL, (char *)acl)) != Z_OK) 5520ee519a1fSgjelinek return (err); 5521ee519a1fSgjelinek return (Z_OK); 5522ee519a1fSgjelinek } 5523ee519a1fSgjelinek 5524ee519a1fSgjelinek /* 5525ee519a1fSgjelinek * Get the information required to support detaching a zone. This is 5526ee519a1fSgjelinek * called on the source system when detaching (the detaching parameter should 5527ee519a1fSgjelinek * be set to true) and on the destination system before attaching (the 5528ee519a1fSgjelinek * detaching parameter should be false). 5529ee519a1fSgjelinek * 5530ee519a1fSgjelinek * For native Solaris zones, the detach/attach process involves validating 5531ee519a1fSgjelinek * that the software on the global zone can support the zone when we attach. 5532ee519a1fSgjelinek * To do this we take a software inventory of the global zone. We also 5533ee519a1fSgjelinek * have to keep track of the device configuration so that we can properly 5534ee519a1fSgjelinek * recreate it on the destination. 5535ee519a1fSgjelinek */ 5536ee519a1fSgjelinek int 5537ee519a1fSgjelinek zonecfg_get_detach_info(zone_dochandle_t handle, boolean_t detaching) 5538ee519a1fSgjelinek { 5539ee519a1fSgjelinek int res; 5540ee519a1fSgjelinek 5541ee519a1fSgjelinek if ((res = zonecfg_sw_inventory(handle)) != Z_OK) 5542ee519a1fSgjelinek return (res); 5543ee519a1fSgjelinek 5544ee519a1fSgjelinek if (detaching) 5545ee519a1fSgjelinek res = zonecfg_devwalk(handle, get_detach_dev_entry, handle); 5546ee519a1fSgjelinek 5547ee519a1fSgjelinek return (res); 5548ee519a1fSgjelinek } 5549