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 5*ee519a1fSgjelinek * Common Development and Distribution License (the "License"). 6*ee519a1fSgjelinek * 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 */ 217c478bd9Sstevel@tonic-gate /* 229d4be64eSdstaff * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 28cf8f45c7Sdstaff #include <libsysevent.h> 29cf8f45c7Sdstaff #include <pthread.h> 30cf8f45c7Sdstaff #include <stdlib.h> 317c478bd9Sstevel@tonic-gate #include <errno.h> 327c478bd9Sstevel@tonic-gate #include <fnmatch.h> 337c478bd9Sstevel@tonic-gate #include <strings.h> 347c478bd9Sstevel@tonic-gate #include <unistd.h> 357c478bd9Sstevel@tonic-gate #include <sys/stat.h> 367c478bd9Sstevel@tonic-gate #include <assert.h> 377c478bd9Sstevel@tonic-gate #include <libgen.h> 387c478bd9Sstevel@tonic-gate #include <libintl.h> 397c478bd9Sstevel@tonic-gate #include <alloca.h> 407c478bd9Sstevel@tonic-gate #include <ctype.h> 417c478bd9Sstevel@tonic-gate #include <sys/mntio.h> 427c478bd9Sstevel@tonic-gate #include <sys/mnttab.h> 43087719fdSdp #include <sys/types.h> 44cf8f45c7Sdstaff #include <sys/nvpair.h> 45*ee519a1fSgjelinek #include <sys/acl.h> 46*ee519a1fSgjelinek #include <ftw.h> 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 497c478bd9Sstevel@tonic-gate #include <netdb.h> 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate #include <priv.h> 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate #include <libxml/xmlmemory.h> 547c478bd9Sstevel@tonic-gate #include <libxml/parser.h> 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate #include <libdevinfo.h> 57108322fbScarlsonj #include <uuid/uuid.h> 587c478bd9Sstevel@tonic-gate 59*ee519a1fSgjelinek #include <dirent.h> 60*ee519a1fSgjelinek 617c478bd9Sstevel@tonic-gate #include <libzonecfg.h> 627c478bd9Sstevel@tonic-gate #include "zonecfg_impl.h" 637c478bd9Sstevel@tonic-gate 64cf8f45c7Sdstaff 657c478bd9Sstevel@tonic-gate #define _PATH_TMPFILE "/zonecfg.XXXXXX" 66cf8f45c7Sdstaff #define ZONE_CB_RETRY_COUNT 10 67cf8f45c7Sdstaff #define ZONE_EVENT_PING_SUBCLASS "ping" 68cf8f45c7Sdstaff #define ZONE_EVENT_PING_PUBLISHER "solaris" 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate /* Hard-code the DTD element/attribute/entity names just once, here. */ 717c478bd9Sstevel@tonic-gate #define DTD_ELEM_ATTR (const xmlChar *) "attr" 727c478bd9Sstevel@tonic-gate #define DTD_ELEM_COMMENT (const xmlChar *) "comment" 737c478bd9Sstevel@tonic-gate #define DTD_ELEM_DEVICE (const xmlChar *) "device" 747c478bd9Sstevel@tonic-gate #define DTD_ELEM_FS (const xmlChar *) "filesystem" 757c478bd9Sstevel@tonic-gate #define DTD_ELEM_FSOPTION (const xmlChar *) "fsoption" 767c478bd9Sstevel@tonic-gate #define DTD_ELEM_IPD (const xmlChar *) "inherited-pkg-dir" 777c478bd9Sstevel@tonic-gate #define DTD_ELEM_NET (const xmlChar *) "network" 787c478bd9Sstevel@tonic-gate #define DTD_ELEM_RCTL (const xmlChar *) "rctl" 797c478bd9Sstevel@tonic-gate #define DTD_ELEM_RCTLVALUE (const xmlChar *) "rctl-value" 807c478bd9Sstevel@tonic-gate #define DTD_ELEM_ZONE (const xmlChar *) "zone" 81fa9e4066Sahrens #define DTD_ELEM_DATASET (const xmlChar *) "dataset" 82*ee519a1fSgjelinek #define DTD_ELEM_PACKAGE (const xmlChar *) "package" 83*ee519a1fSgjelinek #define DTD_ELEM_PATCH (const xmlChar *) "patch" 84*ee519a1fSgjelinek #define DTD_ELEM_OBSOLETES (const xmlChar *) "obsoletes" 85*ee519a1fSgjelinek #define DTD_ELEM_INCOMPATIBLE (const xmlChar *) "incompatible" 86*ee519a1fSgjelinek #define DTD_ELEM_DEV_PERM (const xmlChar *) "dev-perm" 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate #define DTD_ATTR_ACTION (const xmlChar *) "action" 897c478bd9Sstevel@tonic-gate #define DTD_ATTR_ADDRESS (const xmlChar *) "address" 907c478bd9Sstevel@tonic-gate #define DTD_ATTR_AUTOBOOT (const xmlChar *) "autoboot" 917c478bd9Sstevel@tonic-gate #define DTD_ATTR_DIR (const xmlChar *) "directory" 927c478bd9Sstevel@tonic-gate #define DTD_ATTR_LIMIT (const xmlChar *) "limit" 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" 103*ee519a1fSgjelinek #define DTD_ATTR_VERSION (const xmlChar *) "version" 104*ee519a1fSgjelinek #define DTD_ATTR_ID (const xmlChar *) "id" 105*ee519a1fSgjelinek #define DTD_ATTR_UID (const xmlChar *) "uid" 106*ee519a1fSgjelinek #define DTD_ATTR_GID (const xmlChar *) "gid" 107*ee519a1fSgjelinek #define DTD_ATTR_MODE (const xmlChar *) "mode" 108*ee519a1fSgjelinek #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 122*ee519a1fSgjelinek #define DETACHED "SUNWdetached.xml" 123*ee519a1fSgjelinek #define ATTACH_FORCED "SUNWattached.xml" 124*ee519a1fSgjelinek #define PKG_PATH "/var/sadm/pkg" 125*ee519a1fSgjelinek #define CONTENTS_FILE "/var/sadm/install/contents" 126*ee519a1fSgjelinek #define ALL_ZONES "SUNW_PKG_ALLZONES=true\n" 127*ee519a1fSgjelinek #define THIS_ZONE "SUNW_PKG_THISZONE=true\n" 128*ee519a1fSgjelinek #define VERSION "VERSION=" 129*ee519a1fSgjelinek #define PATCHLIST "PATCHLIST=" 130*ee519a1fSgjelinek #define PATCHINFO "PATCH_INFO_" 131*ee519a1fSgjelinek #define PKGINFO_RD_LEN 128 132*ee519a1fSgjelinek 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; 140*ee519a1fSgjelinek 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 159*ee519a1fSgjelinek struct zone_pkginfo { 160*ee519a1fSgjelinek boolean_t zpi_all_zones; 161*ee519a1fSgjelinek boolean_t zpi_this_zone; 162*ee519a1fSgjelinek int zpi_patch_cnt; 163*ee519a1fSgjelinek char *zpi_version; 164*ee519a1fSgjelinek char **zpi_patchinfo; 165*ee519a1fSgjelinek }; 166*ee519a1fSgjelinek 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 383a1be23daSdp static int 384a1be23daSdp getrootattr(zone_dochandle_t handle, const xmlChar *propname, 385a1be23daSdp char *propval, size_t propsize) 386a1be23daSdp { 387a1be23daSdp xmlNodePtr root; 388a1be23daSdp xmlChar *property; 389a1be23daSdp size_t srcsize; 390a1be23daSdp int err; 391a1be23daSdp 392a1be23daSdp if ((err = getroot(handle, &root)) != 0) 393a1be23daSdp return (err); 394a1be23daSdp 395a1be23daSdp if ((property = xmlGetProp(root, propname)) == NULL) 396a1be23daSdp return (Z_BAD_PROPERTY); 397a1be23daSdp srcsize = strlcpy(propval, (char *)property, propsize); 398a1be23daSdp xmlFree(property); 399a1be23daSdp if (srcsize >= propsize) 400a1be23daSdp return (Z_TOO_BIG); 401a1be23daSdp return (Z_OK); 402a1be23daSdp } 403a1be23daSdp 404a1be23daSdp static int 405108322fbScarlsonj setrootattr(zone_dochandle_t handle, const xmlChar *propname, 406108322fbScarlsonj const char *propval) 407a1be23daSdp { 408a1be23daSdp int err; 409a1be23daSdp xmlNodePtr root; 410a1be23daSdp 411a1be23daSdp if (propval == NULL) 412a1be23daSdp return (Z_INVAL); 413a1be23daSdp 414a1be23daSdp if ((err = getroot(handle, &root)) != Z_OK) 415a1be23daSdp return (err); 416a1be23daSdp 417a1be23daSdp if (xmlSetProp(root, propname, (const xmlChar *) propval) == NULL) 418a1be23daSdp return (Z_INVAL); 4197c478bd9Sstevel@tonic-gate return (Z_OK); 4207c478bd9Sstevel@tonic-gate } 4217c478bd9Sstevel@tonic-gate 422087719fdSdp static void 423087719fdSdp addcomment(zone_dochandle_t handle, const char *comment) 424087719fdSdp { 425087719fdSdp xmlNodePtr node; 426087719fdSdp node = xmlNewComment((xmlChar *) comment); 427087719fdSdp 428087719fdSdp if (node != NULL) 429087719fdSdp (void) xmlAddPrevSibling(handle->zone_dh_top, node); 430087719fdSdp } 431087719fdSdp 432087719fdSdp static void 433087719fdSdp stripcomments(zone_dochandle_t handle) 434087719fdSdp { 435087719fdSdp xmlDocPtr top; 436087719fdSdp xmlNodePtr child, next; 437087719fdSdp 438087719fdSdp top = handle->zone_dh_doc; 439087719fdSdp for (child = top->xmlChildrenNode; child != NULL; child = next) { 440087719fdSdp next = child->next; 441087719fdSdp if (child->name == NULL) 442087719fdSdp continue; 443087719fdSdp if (xmlStrcmp(child->name, DTD_ELEM_COMMENT) == 0) { 444087719fdSdp next = child->next; 445087719fdSdp xmlUnlinkNode(child); 446087719fdSdp xmlFreeNode(child); 447087719fdSdp } 448087719fdSdp } 449087719fdSdp } 450087719fdSdp 451*ee519a1fSgjelinek static void 452*ee519a1fSgjelinek strip_sw_inv(zone_dochandle_t handle) 453*ee519a1fSgjelinek { 454*ee519a1fSgjelinek xmlNodePtr root, child, next; 455*ee519a1fSgjelinek 456*ee519a1fSgjelinek root = xmlDocGetRootElement(handle->zone_dh_doc); 457*ee519a1fSgjelinek for (child = root->xmlChildrenNode; child != NULL; child = next) { 458*ee519a1fSgjelinek next = child->next; 459*ee519a1fSgjelinek if (child->name == NULL) 460*ee519a1fSgjelinek continue; 461*ee519a1fSgjelinek if (xmlStrcmp(child->name, DTD_ELEM_PACKAGE) == 0 || 462*ee519a1fSgjelinek xmlStrcmp(child->name, DTD_ELEM_PATCH) == 0) { 463*ee519a1fSgjelinek next = child->next; 464*ee519a1fSgjelinek xmlUnlinkNode(child); 465*ee519a1fSgjelinek xmlFreeNode(child); 466*ee519a1fSgjelinek } 467*ee519a1fSgjelinek } 468*ee519a1fSgjelinek } 469*ee519a1fSgjelinek 4707c478bd9Sstevel@tonic-gate static int 471108322fbScarlsonj zonecfg_get_handle_impl(const char *zonename, const char *filename, 472108322fbScarlsonj zone_dochandle_t handle) 4737c478bd9Sstevel@tonic-gate { 4747c478bd9Sstevel@tonic-gate xmlValidCtxtPtr cvp; 4757c478bd9Sstevel@tonic-gate struct stat statbuf; 4767c478bd9Sstevel@tonic-gate int valid; 4777c478bd9Sstevel@tonic-gate 4787c478bd9Sstevel@tonic-gate if (zonename == NULL) 4797c478bd9Sstevel@tonic-gate return (Z_NO_ZONE); 4807c478bd9Sstevel@tonic-gate if ((handle->zone_dh_doc = xmlParseFile(filename)) == NULL) { 4817c478bd9Sstevel@tonic-gate /* distinguish file not found vs. found but not parsed */ 4827c478bd9Sstevel@tonic-gate if (stat(filename, &statbuf) == 0) 4837c478bd9Sstevel@tonic-gate return (Z_INVALID_DOCUMENT); 4847c478bd9Sstevel@tonic-gate return (Z_NO_ZONE); 4857c478bd9Sstevel@tonic-gate } 4867c478bd9Sstevel@tonic-gate if ((cvp = xmlNewValidCtxt()) == NULL) 4877c478bd9Sstevel@tonic-gate return (Z_NOMEM); 4887c478bd9Sstevel@tonic-gate cvp->error = zonecfg_error_func; 4897c478bd9Sstevel@tonic-gate cvp->warning = zonecfg_error_func; 4907c478bd9Sstevel@tonic-gate valid = xmlValidateDocument(cvp, handle->zone_dh_doc); 4917c478bd9Sstevel@tonic-gate xmlFreeValidCtxt(cvp); 4927c478bd9Sstevel@tonic-gate if (valid == 0) 4937c478bd9Sstevel@tonic-gate return (Z_INVALID_DOCUMENT); 494087719fdSdp 4957c478bd9Sstevel@tonic-gate /* delete any comments such as inherited Sun copyright / ident str */ 496087719fdSdp stripcomments(handle); 4977c478bd9Sstevel@tonic-gate return (Z_OK); 4987c478bd9Sstevel@tonic-gate } 4997c478bd9Sstevel@tonic-gate 5007c478bd9Sstevel@tonic-gate int 501108322fbScarlsonj zonecfg_get_handle(const char *zonename, zone_dochandle_t handle) 5027c478bd9Sstevel@tonic-gate { 5037c478bd9Sstevel@tonic-gate char path[MAXPATHLEN]; 5047c478bd9Sstevel@tonic-gate 505108322fbScarlsonj if (!config_file_path(zonename, path)) 506108322fbScarlsonj return (Z_MISC_FS); 507087719fdSdp handle->zone_dh_newzone = B_FALSE; 508087719fdSdp 5097c478bd9Sstevel@tonic-gate return (zonecfg_get_handle_impl(zonename, path, handle)); 5107c478bd9Sstevel@tonic-gate } 5117c478bd9Sstevel@tonic-gate 512*ee519a1fSgjelinek int 513*ee519a1fSgjelinek zonecfg_get_attach_handle(const char *path, const char *zonename, 514*ee519a1fSgjelinek boolean_t preserve_sw, zone_dochandle_t handle) 515*ee519a1fSgjelinek { 516*ee519a1fSgjelinek char migpath[MAXPATHLEN]; 517*ee519a1fSgjelinek int err; 518*ee519a1fSgjelinek struct stat buf; 519*ee519a1fSgjelinek 520*ee519a1fSgjelinek if (snprintf(migpath, sizeof (migpath), "%s/root", path) >= 521*ee519a1fSgjelinek sizeof (migpath)) 522*ee519a1fSgjelinek return (Z_NOMEM); 523*ee519a1fSgjelinek 524*ee519a1fSgjelinek if (stat(migpath, &buf) == -1 || !S_ISDIR(buf.st_mode)) 525*ee519a1fSgjelinek return (Z_NO_ZONE); 526*ee519a1fSgjelinek 527*ee519a1fSgjelinek if (snprintf(migpath, sizeof (migpath), "%s/%s", path, DETACHED) >= 528*ee519a1fSgjelinek sizeof (migpath)) 529*ee519a1fSgjelinek return (Z_NOMEM); 530*ee519a1fSgjelinek 531*ee519a1fSgjelinek if ((err = zonecfg_get_handle_impl(zonename, migpath, handle)) != Z_OK) 532*ee519a1fSgjelinek return (err); 533*ee519a1fSgjelinek 534*ee519a1fSgjelinek if (!preserve_sw) 535*ee519a1fSgjelinek strip_sw_inv(handle); 536*ee519a1fSgjelinek 537*ee519a1fSgjelinek handle->zone_dh_newzone = B_TRUE; 538*ee519a1fSgjelinek if ((err = setrootattr(handle, DTD_ATTR_ZONEPATH, path)) != Z_OK) 539*ee519a1fSgjelinek return (err); 540*ee519a1fSgjelinek 541*ee519a1fSgjelinek return (setrootattr(handle, DTD_ATTR_NAME, zonename)); 542*ee519a1fSgjelinek } 543*ee519a1fSgjelinek 5447c478bd9Sstevel@tonic-gate int 545108322fbScarlsonj zonecfg_get_snapshot_handle(const char *zonename, zone_dochandle_t handle) 5467c478bd9Sstevel@tonic-gate { 5477c478bd9Sstevel@tonic-gate char path[MAXPATHLEN]; 5487c478bd9Sstevel@tonic-gate 549108322fbScarlsonj if (!snap_file_path(zonename, path)) 550108322fbScarlsonj return (Z_MISC_FS); 551087719fdSdp handle->zone_dh_newzone = B_FALSE; 5527c478bd9Sstevel@tonic-gate return (zonecfg_get_handle_impl(zonename, path, handle)); 5537c478bd9Sstevel@tonic-gate } 5547c478bd9Sstevel@tonic-gate 555087719fdSdp int 556108322fbScarlsonj zonecfg_get_template_handle(const char *template, const char *zonename, 557087719fdSdp zone_dochandle_t handle) 558087719fdSdp { 559087719fdSdp char path[MAXPATHLEN]; 560087719fdSdp int err; 561087719fdSdp 562108322fbScarlsonj if (!config_file_path(template, path)) 563108322fbScarlsonj return (Z_MISC_FS); 564087719fdSdp 565087719fdSdp if ((err = zonecfg_get_handle_impl(template, path, handle)) != Z_OK) 566087719fdSdp return (err); 567087719fdSdp handle->zone_dh_newzone = B_TRUE; 568087719fdSdp return (setrootattr(handle, DTD_ATTR_NAME, zonename)); 569087719fdSdp } 570087719fdSdp 571087719fdSdp static boolean_t 572087719fdSdp is_renaming(zone_dochandle_t handle) 573087719fdSdp { 574087719fdSdp if (handle->zone_dh_newzone) 575087719fdSdp return (B_FALSE); 576087719fdSdp if (strlen(handle->zone_dh_delete_name) > 0) 577087719fdSdp return (B_TRUE); 578087719fdSdp return (B_FALSE); 579087719fdSdp } 580087719fdSdp 581087719fdSdp static boolean_t 582087719fdSdp is_new(zone_dochandle_t handle) 583087719fdSdp { 584087719fdSdp return (handle->zone_dh_newzone || handle->zone_dh_snapshot); 585087719fdSdp } 586087719fdSdp 587087719fdSdp static boolean_t 588087719fdSdp is_snapshot(zone_dochandle_t handle) 589087719fdSdp { 590087719fdSdp return (handle->zone_dh_snapshot); 591087719fdSdp } 592087719fdSdp 593087719fdSdp /* 594087719fdSdp * It would be great to be able to use libc's ctype(3c) macros, but we 595087719fdSdp * can't, as they are locale sensitive, and it would break our limited thread 596087719fdSdp * safety if this routine had to change the app locale on the fly. 597087719fdSdp */ 598087719fdSdp int 599108322fbScarlsonj zonecfg_validate_zonename(const char *zone) 600087719fdSdp { 601087719fdSdp int i; 602087719fdSdp 603087719fdSdp if (strcmp(zone, GLOBAL_ZONENAME) == 0) 604087719fdSdp return (Z_BOGUS_ZONE_NAME); 605087719fdSdp 606087719fdSdp if (strlen(zone) >= ZONENAME_MAX) 607087719fdSdp return (Z_BOGUS_ZONE_NAME); 608087719fdSdp 609087719fdSdp if (!((zone[0] >= 'a' && zone[0] <= 'z') || 610087719fdSdp (zone[0] >= 'A' && zone[0] <= 'Z') || 611087719fdSdp (zone[0] >= '0' && zone[0] <= '9'))) 612087719fdSdp return (Z_BOGUS_ZONE_NAME); 613087719fdSdp 614087719fdSdp for (i = 1; zone[i] != '\0'; i++) { 615087719fdSdp if (!((zone[i] >= 'a' && zone[i] <= 'z') || 616087719fdSdp (zone[i] >= 'A' && zone[i] <= 'Z') || 617087719fdSdp (zone[i] >= '0' && zone[i] <= '9') || 618087719fdSdp (zone[i] == '-') || (zone[i] == '_') || (zone[i] == '.'))) 619087719fdSdp return (Z_BOGUS_ZONE_NAME); 620087719fdSdp } 621087719fdSdp 622087719fdSdp return (Z_OK); 623087719fdSdp } 624087719fdSdp 625087719fdSdp /* 626087719fdSdp * Changing the zone name requires us to track both the old and new 627087719fdSdp * name of the zone until commit time. 628087719fdSdp */ 6297c478bd9Sstevel@tonic-gate int 6307c478bd9Sstevel@tonic-gate zonecfg_get_name(zone_dochandle_t handle, char *name, size_t namesize) 6317c478bd9Sstevel@tonic-gate { 632a1be23daSdp return (getrootattr(handle, DTD_ATTR_NAME, name, namesize)); 633a1be23daSdp } 6347c478bd9Sstevel@tonic-gate 635a1be23daSdp int 636a1be23daSdp zonecfg_set_name(zone_dochandle_t handle, char *name) 637a1be23daSdp { 638087719fdSdp zone_state_t state; 639087719fdSdp char curname[ZONENAME_MAX], old_delname[ZONENAME_MAX]; 640087719fdSdp int err; 641087719fdSdp 642087719fdSdp if ((err = getrootattr(handle, DTD_ATTR_NAME, curname, 643087719fdSdp sizeof (curname))) != Z_OK) 644087719fdSdp return (err); 645087719fdSdp 646087719fdSdp if (strcmp(name, curname) == 0) 647087719fdSdp return (Z_OK); 648087719fdSdp 649087719fdSdp /* 650087719fdSdp * Switching zone names to one beginning with SUNW is not permitted. 651087719fdSdp */ 652087719fdSdp if (strncmp(name, "SUNW", 4) == 0) 653087719fdSdp return (Z_BOGUS_ZONE_NAME); 654087719fdSdp 655087719fdSdp if ((err = zonecfg_validate_zonename(name)) != Z_OK) 656087719fdSdp return (err); 657087719fdSdp 658087719fdSdp /* 659087719fdSdp * Setting the name back to the original name (effectively a revert of 660087719fdSdp * the name) is fine. But if we carry on, we'll falsely identify the 661087719fdSdp * name as "in use," so special case here. 662087719fdSdp */ 663087719fdSdp if (strcmp(name, handle->zone_dh_delete_name) == 0) { 664087719fdSdp err = setrootattr(handle, DTD_ATTR_NAME, name); 665087719fdSdp handle->zone_dh_delete_name[0] = '\0'; 666087719fdSdp return (err); 667087719fdSdp } 668087719fdSdp 669087719fdSdp /* Check to see if new name chosen is already in use */ 670087719fdSdp if (zone_get_state(name, &state) != Z_NO_ZONE) 671087719fdSdp return (Z_NAME_IN_USE); 672087719fdSdp 673087719fdSdp /* 674087719fdSdp * If this isn't already "new" or in a renaming transition, then 675087719fdSdp * we're initiating a rename here; so stash the "delete name" 676087719fdSdp * (i.e. the name of the zone we'll be removing) for the rename. 677087719fdSdp */ 678087719fdSdp (void) strlcpy(old_delname, handle->zone_dh_delete_name, 679087719fdSdp sizeof (old_delname)); 680087719fdSdp if (!is_new(handle) && !is_renaming(handle)) { 681087719fdSdp /* 682087719fdSdp * Name change is allowed only when the zone we're altering 683087719fdSdp * is not ready or running. 684087719fdSdp */ 685087719fdSdp err = zone_get_state(curname, &state); 686087719fdSdp if (err == Z_OK) { 687087719fdSdp if (state > ZONE_STATE_INSTALLED) 688087719fdSdp return (Z_BAD_ZONE_STATE); 689087719fdSdp } else if (err != Z_NO_ZONE) { 690087719fdSdp return (err); 691087719fdSdp } 692087719fdSdp 693087719fdSdp (void) strlcpy(handle->zone_dh_delete_name, curname, 694087719fdSdp sizeof (handle->zone_dh_delete_name)); 695087719fdSdp assert(is_renaming(handle)); 696087719fdSdp } else if (is_renaming(handle)) { 697087719fdSdp err = zone_get_state(handle->zone_dh_delete_name, &state); 698087719fdSdp if (err == Z_OK) { 699087719fdSdp if (state > ZONE_STATE_INSTALLED) 700087719fdSdp return (Z_BAD_ZONE_STATE); 701087719fdSdp } else if (err != Z_NO_ZONE) { 702087719fdSdp return (err); 703087719fdSdp } 704087719fdSdp } 705087719fdSdp 706087719fdSdp if ((err = setrootattr(handle, DTD_ATTR_NAME, name)) != Z_OK) { 707087719fdSdp /* 708087719fdSdp * Restore the deletename to whatever it was at the 709087719fdSdp * top of the routine, since we've had a failure. 710087719fdSdp */ 711087719fdSdp (void) strlcpy(handle->zone_dh_delete_name, old_delname, 712087719fdSdp sizeof (handle->zone_dh_delete_name)); 713087719fdSdp return (err); 714087719fdSdp } 715087719fdSdp 716087719fdSdp return (Z_OK); 717a1be23daSdp } 7187c478bd9Sstevel@tonic-gate 719a1be23daSdp int 720a1be23daSdp zonecfg_get_zonepath(zone_dochandle_t handle, char *path, size_t pathsize) 721a1be23daSdp { 722108322fbScarlsonj size_t len; 723108322fbScarlsonj 724108322fbScarlsonj if ((len = strlcpy(path, zonecfg_root, pathsize)) >= pathsize) 725108322fbScarlsonj return (Z_TOO_BIG); 726108322fbScarlsonj return (getrootattr(handle, DTD_ATTR_ZONEPATH, path + len, 727108322fbScarlsonj pathsize - len)); 728a1be23daSdp } 7297c478bd9Sstevel@tonic-gate 730a1be23daSdp int 731a1be23daSdp zonecfg_set_zonepath(zone_dochandle_t handle, char *zonepath) 732a1be23daSdp { 733a1be23daSdp return (setrootattr(handle, DTD_ATTR_ZONEPATH, zonepath)); 734a1be23daSdp } 735a1be23daSdp 736a1be23daSdp int 737a1be23daSdp zonecfg_get_autoboot(zone_dochandle_t handle, boolean_t *autoboot) 738a1be23daSdp { 739a1be23daSdp char autobootstr[DTD_ENTITY_BOOL_LEN]; 740a1be23daSdp int ret; 741a1be23daSdp 742a1be23daSdp if ((ret = getrootattr(handle, DTD_ATTR_AUTOBOOT, autobootstr, 743a1be23daSdp sizeof (autobootstr))) != Z_OK) 744a1be23daSdp return (ret); 745a1be23daSdp 746a1be23daSdp if (strcmp(autobootstr, DTD_ENTITY_TRUE) == 0) 747a1be23daSdp *autoboot = B_TRUE; 748a1be23daSdp else if (strcmp(autobootstr, DTD_ENTITY_FALSE) == 0) 749a1be23daSdp *autoboot = B_FALSE; 750a1be23daSdp else 751a1be23daSdp ret = Z_BAD_PROPERTY; 752a1be23daSdp return (ret); 753a1be23daSdp } 754a1be23daSdp 755a1be23daSdp int 756a1be23daSdp zonecfg_set_autoboot(zone_dochandle_t handle, boolean_t autoboot) 757a1be23daSdp { 758a1be23daSdp return (setrootattr(handle, DTD_ATTR_AUTOBOOT, 759a1be23daSdp autoboot ? DTD_ENTITY_TRUE : DTD_ENTITY_FALSE)); 760a1be23daSdp } 761a1be23daSdp 762a1be23daSdp int 763a1be23daSdp zonecfg_get_pool(zone_dochandle_t handle, char *pool, size_t poolsize) 764a1be23daSdp { 765a1be23daSdp return (getrootattr(handle, DTD_ATTR_POOL, pool, poolsize)); 766a1be23daSdp } 767a1be23daSdp 768a1be23daSdp int 769a1be23daSdp zonecfg_set_pool(zone_dochandle_t handle, char *pool) 770a1be23daSdp { 771a1be23daSdp return (setrootattr(handle, DTD_ATTR_POOL, pool)); 772a1be23daSdp } 773a1be23daSdp 774a1be23daSdp /* 775a1be23daSdp * /etc/zones/index caches a vital piece of information which is also 776a1be23daSdp * in the <zonename>.xml file: the path to the zone. This is for performance, 777a1be23daSdp * since we need to walk all zonepath's in order to be able to detect conflicts 778a1be23daSdp * (see crosscheck_zonepaths() in the zoneadm command). 779087719fdSdp * 780087719fdSdp * An additional complexity is that when doing a rename, we'd like the entire 781087719fdSdp * index update operation (rename, and potential state changes) to be atomic. 782087719fdSdp * In general, the operation of this function should succeed or fail as 783087719fdSdp * a unit. 784a1be23daSdp */ 785a1be23daSdp int 786a1be23daSdp zonecfg_refresh_index_file(zone_dochandle_t handle) 787a1be23daSdp { 788a1be23daSdp char name[ZONENAME_MAX], zonepath[MAXPATHLEN]; 789a1be23daSdp struct zoneent ze; 790a1be23daSdp int err; 791087719fdSdp int opcode; 792087719fdSdp char *zn; 793087719fdSdp 794087719fdSdp bzero(&ze, sizeof (ze)); 795087719fdSdp ze.zone_state = -1; /* Preserve existing state in index */ 796a1be23daSdp 797a1be23daSdp if ((err = zonecfg_get_name(handle, name, sizeof (name))) != Z_OK) 798a1be23daSdp return (err); 799087719fdSdp (void) strlcpy(ze.zone_name, name, sizeof (ze.zone_name)); 800087719fdSdp 801a1be23daSdp if ((err = zonecfg_get_zonepath(handle, zonepath, 802a1be23daSdp sizeof (zonepath))) != Z_OK) 803a1be23daSdp return (err); 804a1be23daSdp (void) strlcpy(ze.zone_path, zonepath, sizeof (ze.zone_path)); 805087719fdSdp 806087719fdSdp if (is_renaming(handle)) { 807087719fdSdp opcode = PZE_MODIFY; 808087719fdSdp (void) strlcpy(ze.zone_name, handle->zone_dh_delete_name, 809087719fdSdp sizeof (ze.zone_name)); 810087719fdSdp (void) strlcpy(ze.zone_newname, name, sizeof (ze.zone_newname)); 811087719fdSdp } else if (is_new(handle)) { 812087719fdSdp FILE *cookie; 813087719fdSdp /* 814087719fdSdp * Be tolerant of the zone already existing in the index file, 815087719fdSdp * since we might be forcibly overwriting an existing 816087719fdSdp * configuration with a new one (for example 'create -F' 817087719fdSdp * in zonecfg). 818087719fdSdp */ 819087719fdSdp opcode = PZE_ADD; 820087719fdSdp cookie = setzoneent(); 821087719fdSdp while ((zn = getzoneent(cookie)) != NULL) { 822087719fdSdp if (strcmp(zn, name) == 0) { 823087719fdSdp opcode = PZE_MODIFY; 824087719fdSdp free(zn); 825087719fdSdp break; 826087719fdSdp } 827087719fdSdp free(zn); 828087719fdSdp } 829087719fdSdp endzoneent(cookie); 830087719fdSdp ze.zone_state = ZONE_STATE_CONFIGURED; 831087719fdSdp } else { 832087719fdSdp opcode = PZE_MODIFY; 833087719fdSdp } 834087719fdSdp 835087719fdSdp if ((err = putzoneent(&ze, opcode)) != Z_OK) 836087719fdSdp return (err); 837087719fdSdp 838087719fdSdp return (Z_OK); 8397c478bd9Sstevel@tonic-gate } 8407c478bd9Sstevel@tonic-gate 841087719fdSdp /* 842087719fdSdp * The goal of this routine is to cause the index file update and the 843087719fdSdp * document save to happen as an atomic operation. We do the document 844087719fdSdp * first, saving a backup copy using a hard link; if that succeeds, we go 845087719fdSdp * on to the index. If that fails, we roll the document back into place. 846087719fdSdp * 847087719fdSdp * Strategy: 848087719fdSdp * 849087719fdSdp * New zone 'foo' configuration: 850087719fdSdp * Create tmpfile (zonecfg.xxxxxx) 851087719fdSdp * Write XML to tmpfile 852087719fdSdp * Rename tmpfile to xmlfile (zonecfg.xxxxxx -> foo.xml) 853087719fdSdp * Add entry to index file 854087719fdSdp * If it fails, delete foo.xml, leaving nothing behind. 855087719fdSdp * 856087719fdSdp * Save existing zone 'foo': 857087719fdSdp * Make backup of foo.xml -> .backup 858087719fdSdp * Create tmpfile (zonecfg.xxxxxx) 859087719fdSdp * Write XML to tmpfile 860087719fdSdp * Rename tmpfile to xmlfile (zonecfg.xxxxxx -> foo.xml) 861087719fdSdp * Modify index file as needed 862087719fdSdp * If it fails, recover from .backup -> foo.xml 863087719fdSdp * 864087719fdSdp * Rename 'foo' to 'bar': 865087719fdSdp * Create tmpfile (zonecfg.xxxxxx) 866087719fdSdp * Write XML to tmpfile 867087719fdSdp * Rename tmpfile to xmlfile (zonecfg.xxxxxx -> bar.xml) 868087719fdSdp * Add entry for 'bar' to index file, Remove entry for 'foo' (refresh) 869087719fdSdp * If it fails, delete bar.xml; foo.xml is left behind. 870087719fdSdp */ 8717c478bd9Sstevel@tonic-gate static int 8727c478bd9Sstevel@tonic-gate zonecfg_save_impl(zone_dochandle_t handle, char *filename) 8737c478bd9Sstevel@tonic-gate { 8747c478bd9Sstevel@tonic-gate char tmpfile[MAXPATHLEN]; 875087719fdSdp char bakdir[MAXPATHLEN], bakbase[MAXPATHLEN], bakfile[MAXPATHLEN]; 876087719fdSdp int tmpfd, err; 8777c478bd9Sstevel@tonic-gate xmlValidCtxt cvp = { NULL }; 878087719fdSdp boolean_t backup; 8797c478bd9Sstevel@tonic-gate 8807c478bd9Sstevel@tonic-gate (void) strlcpy(tmpfile, filename, sizeof (tmpfile)); 8817c478bd9Sstevel@tonic-gate (void) dirname(tmpfile); 8827c478bd9Sstevel@tonic-gate (void) strlcat(tmpfile, _PATH_TMPFILE, sizeof (tmpfile)); 8837c478bd9Sstevel@tonic-gate 8847c478bd9Sstevel@tonic-gate tmpfd = mkstemp(tmpfile); 8857c478bd9Sstevel@tonic-gate if (tmpfd == -1) { 8867c478bd9Sstevel@tonic-gate (void) unlink(tmpfile); 8877c478bd9Sstevel@tonic-gate return (Z_TEMP_FILE); 8887c478bd9Sstevel@tonic-gate } 8897c478bd9Sstevel@tonic-gate (void) close(tmpfd); 8907c478bd9Sstevel@tonic-gate 8917c478bd9Sstevel@tonic-gate cvp.error = zonecfg_error_func; 8927c478bd9Sstevel@tonic-gate cvp.warning = zonecfg_error_func; 8937c478bd9Sstevel@tonic-gate 894087719fdSdp /* 895087719fdSdp * We do a final validation of the document-- but the library has 896087719fdSdp * malfunctioned if it fails to validate, so it's an assert. 897087719fdSdp */ 898087719fdSdp assert(xmlValidateDocument(&cvp, handle->zone_dh_doc) != 0); 8997c478bd9Sstevel@tonic-gate 9007c478bd9Sstevel@tonic-gate if (xmlSaveFormatFile(tmpfile, handle->zone_dh_doc, 1) <= 0) 9017c478bd9Sstevel@tonic-gate goto err; 902087719fdSdp 9037c478bd9Sstevel@tonic-gate (void) chmod(tmpfile, 0644); 9047c478bd9Sstevel@tonic-gate 905087719fdSdp /* 906087719fdSdp * In the event we are doing a standard save, hard link a copy of the 907087719fdSdp * original file in .backup.<pid>.filename so we can restore it if 908087719fdSdp * something goes wrong. 909087719fdSdp */ 910087719fdSdp if (!is_new(handle) && !is_renaming(handle)) { 911087719fdSdp backup = B_TRUE; 912087719fdSdp 913087719fdSdp (void) strlcpy(bakdir, filename, sizeof (bakdir)); 914087719fdSdp (void) strlcpy(bakbase, filename, sizeof (bakbase)); 915087719fdSdp (void) snprintf(bakfile, sizeof (bakfile), "%s/.backup.%d.%s", 916087719fdSdp dirname(bakdir), getpid(), basename(bakbase)); 917087719fdSdp 918087719fdSdp if (link(filename, bakfile) == -1) { 919087719fdSdp err = errno; 920087719fdSdp (void) unlink(tmpfile); 921087719fdSdp if (errno == EACCES) 922087719fdSdp return (Z_ACCES); 923087719fdSdp return (Z_MISC_FS); 924087719fdSdp } 925087719fdSdp } 926087719fdSdp 927087719fdSdp /* 928087719fdSdp * Move the new document over top of the old. 929087719fdSdp * i.e.: zonecfg.XXXXXX -> myzone.xml 930087719fdSdp */ 9317c478bd9Sstevel@tonic-gate if (rename(tmpfile, filename) == -1) { 932087719fdSdp err = errno; 9337c478bd9Sstevel@tonic-gate (void) unlink(tmpfile); 934087719fdSdp if (backup) 935087719fdSdp (void) unlink(bakfile); 936087719fdSdp if (err == EACCES) 9377c478bd9Sstevel@tonic-gate return (Z_ACCES); 9387c478bd9Sstevel@tonic-gate return (Z_MISC_FS); 9397c478bd9Sstevel@tonic-gate } 940a1be23daSdp 941087719fdSdp /* 942087719fdSdp * If this is a snapshot, we're done-- don't add an index entry. 943087719fdSdp */ 944087719fdSdp if (is_snapshot(handle)) 945087719fdSdp return (Z_OK); 946087719fdSdp 947087719fdSdp /* now update the index file to reflect whatever we just did */ 948087719fdSdp if ((err = zonecfg_refresh_index_file(handle)) != Z_OK) { 949087719fdSdp if (backup) { 950087719fdSdp /* 951087719fdSdp * Try to restore from our backup. 952087719fdSdp */ 953087719fdSdp (void) unlink(filename); 954087719fdSdp (void) rename(bakfile, filename); 955087719fdSdp } else { 956087719fdSdp /* 957087719fdSdp * Either the zone is new, in which case we can delete 958087719fdSdp * new.xml, or we're doing a rename, so ditto. 959087719fdSdp */ 960087719fdSdp assert(is_new(handle) || is_renaming(handle)); 961087719fdSdp (void) unlink(filename); 962087719fdSdp } 963087719fdSdp return (Z_UPDATING_INDEX); 964087719fdSdp } 965087719fdSdp 966087719fdSdp if (backup) 967087719fdSdp (void) unlink(bakfile); 968087719fdSdp 969087719fdSdp return (Z_OK); 9707c478bd9Sstevel@tonic-gate 9717c478bd9Sstevel@tonic-gate err: 9727c478bd9Sstevel@tonic-gate (void) unlink(tmpfile); 9737c478bd9Sstevel@tonic-gate return (Z_SAVING_FILE); 9747c478bd9Sstevel@tonic-gate } 9757c478bd9Sstevel@tonic-gate 9767c478bd9Sstevel@tonic-gate int 9777c478bd9Sstevel@tonic-gate zonecfg_save(zone_dochandle_t handle) 9787c478bd9Sstevel@tonic-gate { 979087719fdSdp char zname[ZONENAME_MAX], path[MAXPATHLEN]; 980087719fdSdp char delpath[MAXPATHLEN]; 981087719fdSdp int err = Z_SAVING_FILE; 982087719fdSdp 983087719fdSdp if (zonecfg_check_handle(handle) != Z_OK) 984087719fdSdp return (Z_BAD_HANDLE); 9857c478bd9Sstevel@tonic-gate 986087719fdSdp /* 987*ee519a1fSgjelinek * We don't support saving snapshots or a tree containing a sw 988*ee519a1fSgjelinek * inventory at this time. 989087719fdSdp */ 990*ee519a1fSgjelinek if (handle->zone_dh_snapshot || handle->zone_dh_sw_inv) 991087719fdSdp return (Z_INVAL); 992087719fdSdp 993087719fdSdp if ((err = zonecfg_get_name(handle, zname, sizeof (zname))) != Z_OK) 9947c478bd9Sstevel@tonic-gate return (err); 995087719fdSdp 996108322fbScarlsonj if (!config_file_path(zname, path)) 997108322fbScarlsonj return (Z_MISC_FS); 998087719fdSdp 999087719fdSdp addcomment(handle, "\n DO NOT EDIT THIS " 1000087719fdSdp "FILE. Use zonecfg(1M) instead.\n"); 1001087719fdSdp 1002087719fdSdp err = zonecfg_save_impl(handle, path); 1003087719fdSdp 1004087719fdSdp stripcomments(handle); 1005087719fdSdp 1006087719fdSdp if (err != Z_OK) 1007087719fdSdp return (err); 1008087719fdSdp 1009087719fdSdp handle->zone_dh_newzone = B_FALSE; 1010087719fdSdp 1011087719fdSdp if (is_renaming(handle)) { 1012108322fbScarlsonj if (config_file_path(handle->zone_dh_delete_name, delpath)) 1013108322fbScarlsonj (void) unlink(delpath); 1014087719fdSdp handle->zone_dh_delete_name[0] = '\0'; 1015087719fdSdp } 1016087719fdSdp 1017087719fdSdp return (Z_OK); 10187c478bd9Sstevel@tonic-gate } 10197c478bd9Sstevel@tonic-gate 1020*ee519a1fSgjelinek int 1021*ee519a1fSgjelinek zonecfg_detach_save(zone_dochandle_t handle) 1022*ee519a1fSgjelinek { 1023*ee519a1fSgjelinek char zname[ZONENAME_MAX]; 1024*ee519a1fSgjelinek char path[MAXPATHLEN]; 1025*ee519a1fSgjelinek char migpath[MAXPATHLEN]; 1026*ee519a1fSgjelinek xmlValidCtxt cvp = { NULL }; 1027*ee519a1fSgjelinek int err = Z_SAVING_FILE; 1028*ee519a1fSgjelinek 1029*ee519a1fSgjelinek if (zonecfg_check_handle(handle) != Z_OK) 1030*ee519a1fSgjelinek return (Z_BAD_HANDLE); 1031*ee519a1fSgjelinek 1032*ee519a1fSgjelinek /* 1033*ee519a1fSgjelinek * We can only detach if we have taken a sw inventory. 1034*ee519a1fSgjelinek */ 1035*ee519a1fSgjelinek if (!handle->zone_dh_sw_inv) 1036*ee519a1fSgjelinek return (Z_INVAL); 1037*ee519a1fSgjelinek 1038*ee519a1fSgjelinek if ((err = zonecfg_get_name(handle, zname, sizeof (zname))) != Z_OK) 1039*ee519a1fSgjelinek return (err); 1040*ee519a1fSgjelinek 1041*ee519a1fSgjelinek if ((err = zone_get_zonepath(zname, path, sizeof (path))) != Z_OK) 1042*ee519a1fSgjelinek return (err); 1043*ee519a1fSgjelinek 1044*ee519a1fSgjelinek if (snprintf(migpath, sizeof (migpath), "%s/%s", path, DETACHED) >= 1045*ee519a1fSgjelinek sizeof (migpath)) 1046*ee519a1fSgjelinek return (Z_NOMEM); 1047*ee519a1fSgjelinek 1048*ee519a1fSgjelinek if ((err = operation_prep(handle)) != Z_OK) 1049*ee519a1fSgjelinek return (err); 1050*ee519a1fSgjelinek 1051*ee519a1fSgjelinek addcomment(handle, "\n DO NOT EDIT THIS FILE. " 1052*ee519a1fSgjelinek "Use zonecfg(1M) and zoneadm(1M) attach.\n"); 1053*ee519a1fSgjelinek 1054*ee519a1fSgjelinek cvp.error = zonecfg_error_func; 1055*ee519a1fSgjelinek cvp.warning = zonecfg_error_func; 1056*ee519a1fSgjelinek 1057*ee519a1fSgjelinek /* 1058*ee519a1fSgjelinek * We do a final validation of the document-- but the library has 1059*ee519a1fSgjelinek * malfunctioned if it fails to validate, so it's an assert. 1060*ee519a1fSgjelinek */ 1061*ee519a1fSgjelinek assert(xmlValidateDocument(&cvp, handle->zone_dh_doc) != 0); 1062*ee519a1fSgjelinek 1063*ee519a1fSgjelinek if (xmlSaveFormatFile(migpath, handle->zone_dh_doc, 1) <= 0) 1064*ee519a1fSgjelinek return (Z_SAVING_FILE); 1065*ee519a1fSgjelinek 1066*ee519a1fSgjelinek (void) chmod(migpath, 0644); 1067*ee519a1fSgjelinek 1068*ee519a1fSgjelinek stripcomments(handle); 1069*ee519a1fSgjelinek 1070*ee519a1fSgjelinek handle->zone_dh_newzone = B_FALSE; 1071*ee519a1fSgjelinek 1072*ee519a1fSgjelinek return (Z_OK); 1073*ee519a1fSgjelinek } 1074*ee519a1fSgjelinek 1075*ee519a1fSgjelinek boolean_t 1076*ee519a1fSgjelinek zonecfg_detached(const char *path) 1077*ee519a1fSgjelinek { 1078*ee519a1fSgjelinek char migpath[MAXPATHLEN]; 1079*ee519a1fSgjelinek struct stat buf; 1080*ee519a1fSgjelinek 1081*ee519a1fSgjelinek if (snprintf(migpath, sizeof (migpath), "%s/%s", path, DETACHED) >= 1082*ee519a1fSgjelinek sizeof (migpath)) 1083*ee519a1fSgjelinek return (B_FALSE); 1084*ee519a1fSgjelinek 1085*ee519a1fSgjelinek if (stat(migpath, &buf) != -1) 1086*ee519a1fSgjelinek return (B_TRUE); 1087*ee519a1fSgjelinek 1088*ee519a1fSgjelinek return (B_FALSE); 1089*ee519a1fSgjelinek } 1090*ee519a1fSgjelinek 1091*ee519a1fSgjelinek void 1092*ee519a1fSgjelinek zonecfg_rm_detached(zone_dochandle_t handle, boolean_t forced) 1093*ee519a1fSgjelinek { 1094*ee519a1fSgjelinek char zname[ZONENAME_MAX]; 1095*ee519a1fSgjelinek char path[MAXPATHLEN]; 1096*ee519a1fSgjelinek char detached[MAXPATHLEN]; 1097*ee519a1fSgjelinek char attached[MAXPATHLEN]; 1098*ee519a1fSgjelinek 1099*ee519a1fSgjelinek if (zonecfg_check_handle(handle) != Z_OK) 1100*ee519a1fSgjelinek return; 1101*ee519a1fSgjelinek 1102*ee519a1fSgjelinek if (zonecfg_get_name(handle, zname, sizeof (zname)) != Z_OK) 1103*ee519a1fSgjelinek return; 1104*ee519a1fSgjelinek 1105*ee519a1fSgjelinek if (zone_get_zonepath(zname, path, sizeof (path)) != Z_OK) 1106*ee519a1fSgjelinek return; 1107*ee519a1fSgjelinek 1108*ee519a1fSgjelinek (void) snprintf(detached, sizeof (detached), "%s/%s", path, DETACHED); 1109*ee519a1fSgjelinek (void) snprintf(attached, sizeof (attached), "%s/%s", path, 1110*ee519a1fSgjelinek ATTACH_FORCED); 1111*ee519a1fSgjelinek 1112*ee519a1fSgjelinek if (forced) { 1113*ee519a1fSgjelinek (void) rename(detached, attached); 1114*ee519a1fSgjelinek } else { 1115*ee519a1fSgjelinek (void) unlink(attached); 1116*ee519a1fSgjelinek (void) unlink(detached); 1117*ee519a1fSgjelinek } 1118*ee519a1fSgjelinek } 1119*ee519a1fSgjelinek 11207c478bd9Sstevel@tonic-gate /* 11217c478bd9Sstevel@tonic-gate * Special case: if access(2) fails with ENOENT, then try again using 11227c478bd9Sstevel@tonic-gate * ZONE_CONFIG_ROOT instead of config_file_path(zonename). This is how we 11237c478bd9Sstevel@tonic-gate * work around the case of a config file which has not been created yet: 11247c478bd9Sstevel@tonic-gate * the user will need access to the directory so use that as a heuristic. 11257c478bd9Sstevel@tonic-gate */ 11267c478bd9Sstevel@tonic-gate 11277c478bd9Sstevel@tonic-gate int 11287c478bd9Sstevel@tonic-gate zonecfg_access(const char *zonename, int amode) 11297c478bd9Sstevel@tonic-gate { 11307c478bd9Sstevel@tonic-gate char path[MAXPATHLEN]; 11317c478bd9Sstevel@tonic-gate 1132108322fbScarlsonj if (!config_file_path(zonename, path)) 1133108322fbScarlsonj return (Z_INVAL); 11347c478bd9Sstevel@tonic-gate if (access(path, amode) == 0) 11357c478bd9Sstevel@tonic-gate return (Z_OK); 1136108322fbScarlsonj if (errno == ENOENT) { 1137108322fbScarlsonj if (snprintf(path, sizeof (path), "%s%s", zonecfg_root, 1138108322fbScarlsonj ZONE_CONFIG_ROOT) >= sizeof (path)) 1139108322fbScarlsonj return (Z_INVAL); 1140108322fbScarlsonj if (access(path, amode) == 0) 1141108322fbScarlsonj return (Z_OK); 1142108322fbScarlsonj } 11437c478bd9Sstevel@tonic-gate if (errno == EACCES) 11447c478bd9Sstevel@tonic-gate return (Z_ACCES); 11457c478bd9Sstevel@tonic-gate if (errno == EINVAL) 11467c478bd9Sstevel@tonic-gate return (Z_INVAL); 11477c478bd9Sstevel@tonic-gate return (Z_MISC_FS); 11487c478bd9Sstevel@tonic-gate } 11497c478bd9Sstevel@tonic-gate 11507c478bd9Sstevel@tonic-gate int 1151108322fbScarlsonj zonecfg_create_snapshot(const char *zonename) 11527c478bd9Sstevel@tonic-gate { 11537c478bd9Sstevel@tonic-gate zone_dochandle_t handle; 11547c478bd9Sstevel@tonic-gate char path[MAXPATHLEN], zonepath[MAXPATHLEN], rpath[MAXPATHLEN]; 11557c478bd9Sstevel@tonic-gate int error = Z_OK, res; 11567c478bd9Sstevel@tonic-gate 11577c478bd9Sstevel@tonic-gate if ((handle = zonecfg_init_handle()) == NULL) { 11587c478bd9Sstevel@tonic-gate return (Z_NOMEM); 11597c478bd9Sstevel@tonic-gate } 11607c478bd9Sstevel@tonic-gate 1161087719fdSdp handle->zone_dh_newzone = B_TRUE; 1162087719fdSdp handle->zone_dh_snapshot = B_TRUE; 1163087719fdSdp 11647c478bd9Sstevel@tonic-gate if ((error = zonecfg_get_handle(zonename, handle)) != Z_OK) 11657c478bd9Sstevel@tonic-gate goto out; 11667c478bd9Sstevel@tonic-gate if ((error = operation_prep(handle)) != Z_OK) 11677c478bd9Sstevel@tonic-gate goto out; 11687c478bd9Sstevel@tonic-gate error = zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath)); 11697c478bd9Sstevel@tonic-gate if (error != Z_OK) 11707c478bd9Sstevel@tonic-gate goto out; 11717c478bd9Sstevel@tonic-gate if ((res = resolvepath(zonepath, rpath, sizeof (rpath))) == -1) { 11727c478bd9Sstevel@tonic-gate error = Z_RESOLVED_PATH; 11737c478bd9Sstevel@tonic-gate goto out; 11747c478bd9Sstevel@tonic-gate } 11757c478bd9Sstevel@tonic-gate /* 11767c478bd9Sstevel@tonic-gate * If the resolved path is not the same as the original path, then 11777c478bd9Sstevel@tonic-gate * save the resolved path in the snapshot, thus preventing any 11787c478bd9Sstevel@tonic-gate * potential problems down the line when zoneadmd goes to unmount 11797c478bd9Sstevel@tonic-gate * file systems and depends on initial string matches with resolved 11807c478bd9Sstevel@tonic-gate * paths. 11817c478bd9Sstevel@tonic-gate */ 11827c478bd9Sstevel@tonic-gate rpath[res] = '\0'; 11837c478bd9Sstevel@tonic-gate if (strcmp(zonepath, rpath) != 0) { 11847c478bd9Sstevel@tonic-gate if ((error = zonecfg_set_zonepath(handle, rpath)) != Z_OK) 11857c478bd9Sstevel@tonic-gate goto out; 11867c478bd9Sstevel@tonic-gate } 1187108322fbScarlsonj if (snprintf(path, sizeof (path), "%s%s", zonecfg_root, 1188108322fbScarlsonj ZONE_SNAPSHOT_ROOT) >= sizeof (path)) { 1189108322fbScarlsonj error = Z_MISC_FS; 1190108322fbScarlsonj goto out; 1191108322fbScarlsonj } 1192108322fbScarlsonj if ((mkdir(path, S_IRWXU) == -1) && (errno != EEXIST)) { 11937c478bd9Sstevel@tonic-gate error = Z_MISC_FS; 11947c478bd9Sstevel@tonic-gate goto out; 11957c478bd9Sstevel@tonic-gate } 11967c478bd9Sstevel@tonic-gate 1197108322fbScarlsonj if (!snap_file_path(zonename, path)) { 1198108322fbScarlsonj error = Z_MISC_FS; 1199108322fbScarlsonj goto out; 1200108322fbScarlsonj } 1201087719fdSdp 1202087719fdSdp addcomment(handle, "\n DO NOT EDIT THIS FILE. " 1203087719fdSdp "It is a snapshot of running zone state.\n"); 1204087719fdSdp 12057c478bd9Sstevel@tonic-gate error = zonecfg_save_impl(handle, path); 12067c478bd9Sstevel@tonic-gate 1207087719fdSdp stripcomments(handle); 1208087719fdSdp 12097c478bd9Sstevel@tonic-gate out: 12107c478bd9Sstevel@tonic-gate zonecfg_fini_handle(handle); 12117c478bd9Sstevel@tonic-gate return (error); 12127c478bd9Sstevel@tonic-gate } 12137c478bd9Sstevel@tonic-gate 12147c478bd9Sstevel@tonic-gate static int 1215a1be23daSdp newprop(xmlNodePtr node, const xmlChar *attrname, char *src) 12167c478bd9Sstevel@tonic-gate { 12177c478bd9Sstevel@tonic-gate xmlAttrPtr newattr; 12187c478bd9Sstevel@tonic-gate 12197c478bd9Sstevel@tonic-gate newattr = xmlNewProp(node, attrname, (xmlChar *)src); 12207c478bd9Sstevel@tonic-gate if (newattr == NULL) { 12217c478bd9Sstevel@tonic-gate xmlUnlinkNode(node); 12227c478bd9Sstevel@tonic-gate xmlFreeNode(node); 12237c478bd9Sstevel@tonic-gate return (Z_BAD_PROPERTY); 12247c478bd9Sstevel@tonic-gate } 12257c478bd9Sstevel@tonic-gate return (Z_OK); 12267c478bd9Sstevel@tonic-gate } 12277c478bd9Sstevel@tonic-gate 12287c478bd9Sstevel@tonic-gate static int 12297c478bd9Sstevel@tonic-gate zonecfg_add_filesystem_core(zone_dochandle_t handle, struct zone_fstab *tabptr) 12307c478bd9Sstevel@tonic-gate { 12317c478bd9Sstevel@tonic-gate xmlNodePtr newnode, cur = handle->zone_dh_cur, options_node; 12327c478bd9Sstevel@tonic-gate zone_fsopt_t *ptr; 12337c478bd9Sstevel@tonic-gate int err; 12347c478bd9Sstevel@tonic-gate 12357c478bd9Sstevel@tonic-gate newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_FS, NULL); 1236a1be23daSdp if ((err = newprop(newnode, DTD_ATTR_SPECIAL, 12377c478bd9Sstevel@tonic-gate tabptr->zone_fs_special)) != Z_OK) 12387c478bd9Sstevel@tonic-gate return (err); 12397c478bd9Sstevel@tonic-gate if (tabptr->zone_fs_raw[0] != '\0' && 1240a1be23daSdp (err = newprop(newnode, DTD_ATTR_RAW, tabptr->zone_fs_raw)) != Z_OK) 12417c478bd9Sstevel@tonic-gate return (err); 1242a1be23daSdp if ((err = newprop(newnode, DTD_ATTR_DIR, tabptr->zone_fs_dir)) != Z_OK) 12437c478bd9Sstevel@tonic-gate return (err); 1244a1be23daSdp if ((err = newprop(newnode, DTD_ATTR_TYPE, 12457c478bd9Sstevel@tonic-gate tabptr->zone_fs_type)) != Z_OK) 12467c478bd9Sstevel@tonic-gate return (err); 12477c478bd9Sstevel@tonic-gate if (tabptr->zone_fs_options != NULL) { 12487c478bd9Sstevel@tonic-gate for (ptr = tabptr->zone_fs_options; ptr != NULL; 12497c478bd9Sstevel@tonic-gate ptr = ptr->zone_fsopt_next) { 12507c478bd9Sstevel@tonic-gate options_node = xmlNewTextChild(newnode, NULL, 12517c478bd9Sstevel@tonic-gate DTD_ELEM_FSOPTION, NULL); 1252a1be23daSdp if ((err = newprop(options_node, DTD_ATTR_NAME, 12537c478bd9Sstevel@tonic-gate ptr->zone_fsopt_opt)) != Z_OK) 12547c478bd9Sstevel@tonic-gate return (err); 12557c478bd9Sstevel@tonic-gate } 12567c478bd9Sstevel@tonic-gate } 12577c478bd9Sstevel@tonic-gate return (Z_OK); 12587c478bd9Sstevel@tonic-gate } 12597c478bd9Sstevel@tonic-gate 12607c478bd9Sstevel@tonic-gate int 12617c478bd9Sstevel@tonic-gate zonecfg_add_filesystem(zone_dochandle_t handle, struct zone_fstab *tabptr) 12627c478bd9Sstevel@tonic-gate { 12637c478bd9Sstevel@tonic-gate int err; 12647c478bd9Sstevel@tonic-gate 12657c478bd9Sstevel@tonic-gate if (tabptr == NULL) 12667c478bd9Sstevel@tonic-gate return (Z_INVAL); 12677c478bd9Sstevel@tonic-gate 12687c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 12697c478bd9Sstevel@tonic-gate return (err); 12707c478bd9Sstevel@tonic-gate 12717c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_filesystem_core(handle, tabptr)) != Z_OK) 12727c478bd9Sstevel@tonic-gate return (err); 12737c478bd9Sstevel@tonic-gate 12747c478bd9Sstevel@tonic-gate return (Z_OK); 12757c478bd9Sstevel@tonic-gate } 12767c478bd9Sstevel@tonic-gate 12777c478bd9Sstevel@tonic-gate static int 12787c478bd9Sstevel@tonic-gate zonecfg_add_ipd_core(zone_dochandle_t handle, struct zone_fstab *tabptr) 12797c478bd9Sstevel@tonic-gate { 12807c478bd9Sstevel@tonic-gate xmlNodePtr newnode, cur = handle->zone_dh_cur; 12817c478bd9Sstevel@tonic-gate int err; 12827c478bd9Sstevel@tonic-gate 12837c478bd9Sstevel@tonic-gate newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_IPD, NULL); 1284a1be23daSdp if ((err = newprop(newnode, DTD_ATTR_DIR, tabptr->zone_fs_dir)) != Z_OK) 12857c478bd9Sstevel@tonic-gate return (err); 12867c478bd9Sstevel@tonic-gate return (Z_OK); 12877c478bd9Sstevel@tonic-gate } 12887c478bd9Sstevel@tonic-gate 12897c478bd9Sstevel@tonic-gate int 12907c478bd9Sstevel@tonic-gate zonecfg_add_ipd(zone_dochandle_t handle, struct zone_fstab *tabptr) 12917c478bd9Sstevel@tonic-gate { 12927c478bd9Sstevel@tonic-gate int err; 12937c478bd9Sstevel@tonic-gate 12947c478bd9Sstevel@tonic-gate if (tabptr == NULL) 12957c478bd9Sstevel@tonic-gate return (Z_INVAL); 12967c478bd9Sstevel@tonic-gate 12977c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 12987c478bd9Sstevel@tonic-gate return (err); 12997c478bd9Sstevel@tonic-gate 13007c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_ipd_core(handle, tabptr)) != Z_OK) 13017c478bd9Sstevel@tonic-gate return (err); 13027c478bd9Sstevel@tonic-gate 13037c478bd9Sstevel@tonic-gate return (Z_OK); 13047c478bd9Sstevel@tonic-gate } 13057c478bd9Sstevel@tonic-gate 13067c478bd9Sstevel@tonic-gate int 13077c478bd9Sstevel@tonic-gate zonecfg_add_fs_option(struct zone_fstab *tabptr, char *option) 13087c478bd9Sstevel@tonic-gate { 13097c478bd9Sstevel@tonic-gate zone_fsopt_t *last, *old, *new; 13107c478bd9Sstevel@tonic-gate 13117c478bd9Sstevel@tonic-gate last = tabptr->zone_fs_options; 13127c478bd9Sstevel@tonic-gate for (old = last; old != NULL; old = old->zone_fsopt_next) 13137c478bd9Sstevel@tonic-gate last = old; /* walk to the end of the list */ 13147c478bd9Sstevel@tonic-gate new = (zone_fsopt_t *)malloc(sizeof (zone_fsopt_t)); 13157c478bd9Sstevel@tonic-gate if (new == NULL) 13167c478bd9Sstevel@tonic-gate return (Z_NOMEM); 13177c478bd9Sstevel@tonic-gate (void) strlcpy(new->zone_fsopt_opt, option, 13187c478bd9Sstevel@tonic-gate sizeof (new->zone_fsopt_opt)); 13197c478bd9Sstevel@tonic-gate new->zone_fsopt_next = NULL; 13207c478bd9Sstevel@tonic-gate if (last == NULL) 13217c478bd9Sstevel@tonic-gate tabptr->zone_fs_options = new; 13227c478bd9Sstevel@tonic-gate else 13237c478bd9Sstevel@tonic-gate last->zone_fsopt_next = new; 13247c478bd9Sstevel@tonic-gate return (Z_OK); 13257c478bd9Sstevel@tonic-gate } 13267c478bd9Sstevel@tonic-gate 13277c478bd9Sstevel@tonic-gate int 13287c478bd9Sstevel@tonic-gate zonecfg_remove_fs_option(struct zone_fstab *tabptr, char *option) 13297c478bd9Sstevel@tonic-gate { 13307c478bd9Sstevel@tonic-gate zone_fsopt_t *last, *this, *next; 13317c478bd9Sstevel@tonic-gate 13327c478bd9Sstevel@tonic-gate last = tabptr->zone_fs_options; 13337c478bd9Sstevel@tonic-gate for (this = last; this != NULL; this = this->zone_fsopt_next) { 13347c478bd9Sstevel@tonic-gate if (strcmp(this->zone_fsopt_opt, option) == 0) { 13357c478bd9Sstevel@tonic-gate next = this->zone_fsopt_next; 13367c478bd9Sstevel@tonic-gate if (this == tabptr->zone_fs_options) 13377c478bd9Sstevel@tonic-gate tabptr->zone_fs_options = next; 13387c478bd9Sstevel@tonic-gate else 13397c478bd9Sstevel@tonic-gate last->zone_fsopt_next = next; 13407c478bd9Sstevel@tonic-gate free(this); 13417c478bd9Sstevel@tonic-gate return (Z_OK); 13427c478bd9Sstevel@tonic-gate } else 13437c478bd9Sstevel@tonic-gate last = this; 13447c478bd9Sstevel@tonic-gate } 13457c478bd9Sstevel@tonic-gate return (Z_NO_PROPERTY_ID); 13467c478bd9Sstevel@tonic-gate } 13477c478bd9Sstevel@tonic-gate 13487c478bd9Sstevel@tonic-gate void 13497c478bd9Sstevel@tonic-gate zonecfg_free_fs_option_list(zone_fsopt_t *list) 13507c478bd9Sstevel@tonic-gate { 13517c478bd9Sstevel@tonic-gate zone_fsopt_t *this, *next; 13527c478bd9Sstevel@tonic-gate 13537c478bd9Sstevel@tonic-gate for (this = list; this != NULL; this = next) { 13547c478bd9Sstevel@tonic-gate next = this->zone_fsopt_next; 13557c478bd9Sstevel@tonic-gate free(this); 13567c478bd9Sstevel@tonic-gate } 13577c478bd9Sstevel@tonic-gate } 13587c478bd9Sstevel@tonic-gate 13597c478bd9Sstevel@tonic-gate void 13607c478bd9Sstevel@tonic-gate zonecfg_free_rctl_value_list(struct zone_rctlvaltab *valtab) 13617c478bd9Sstevel@tonic-gate { 13627c478bd9Sstevel@tonic-gate if (valtab == NULL) 13637c478bd9Sstevel@tonic-gate return; 13647c478bd9Sstevel@tonic-gate zonecfg_free_rctl_value_list(valtab->zone_rctlval_next); 13657c478bd9Sstevel@tonic-gate free(valtab); 13667c478bd9Sstevel@tonic-gate } 13677c478bd9Sstevel@tonic-gate 13687c478bd9Sstevel@tonic-gate static boolean_t 13697c478bd9Sstevel@tonic-gate match_prop(xmlNodePtr cur, const xmlChar *attr, char *user_prop) 13707c478bd9Sstevel@tonic-gate { 13717c478bd9Sstevel@tonic-gate xmlChar *gotten_prop; 13727c478bd9Sstevel@tonic-gate int prop_result; 13737c478bd9Sstevel@tonic-gate 13747c478bd9Sstevel@tonic-gate gotten_prop = xmlGetProp(cur, attr); 13757c478bd9Sstevel@tonic-gate if (gotten_prop == NULL) /* shouldn't happen */ 13767c478bd9Sstevel@tonic-gate return (B_FALSE); 13777c478bd9Sstevel@tonic-gate prop_result = xmlStrcmp(gotten_prop, (const xmlChar *) user_prop); 13787c478bd9Sstevel@tonic-gate xmlFree(gotten_prop); 13797c478bd9Sstevel@tonic-gate return ((prop_result == 0)); 13807c478bd9Sstevel@tonic-gate } 13817c478bd9Sstevel@tonic-gate 13827c478bd9Sstevel@tonic-gate static int 13837c478bd9Sstevel@tonic-gate zonecfg_delete_filesystem_core(zone_dochandle_t handle, 13847c478bd9Sstevel@tonic-gate struct zone_fstab *tabptr) 13857c478bd9Sstevel@tonic-gate { 13867c478bd9Sstevel@tonic-gate xmlNodePtr cur = handle->zone_dh_cur; 13877c478bd9Sstevel@tonic-gate boolean_t dir_match, spec_match, raw_match, type_match; 13887c478bd9Sstevel@tonic-gate 13897c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 13907c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_FS)) 13917c478bd9Sstevel@tonic-gate continue; 13927c478bd9Sstevel@tonic-gate dir_match = match_prop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir); 13937c478bd9Sstevel@tonic-gate spec_match = match_prop(cur, DTD_ATTR_SPECIAL, 13947c478bd9Sstevel@tonic-gate tabptr->zone_fs_special); 13957c478bd9Sstevel@tonic-gate raw_match = match_prop(cur, DTD_ATTR_RAW, 13967c478bd9Sstevel@tonic-gate tabptr->zone_fs_raw); 13977c478bd9Sstevel@tonic-gate type_match = match_prop(cur, DTD_ATTR_TYPE, 13987c478bd9Sstevel@tonic-gate tabptr->zone_fs_type); 13997c478bd9Sstevel@tonic-gate if (dir_match && spec_match && raw_match && type_match) { 14007c478bd9Sstevel@tonic-gate xmlUnlinkNode(cur); 14017c478bd9Sstevel@tonic-gate xmlFreeNode(cur); 14027c478bd9Sstevel@tonic-gate return (Z_OK); 14037c478bd9Sstevel@tonic-gate } 14047c478bd9Sstevel@tonic-gate } 14057c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 14067c478bd9Sstevel@tonic-gate } 14077c478bd9Sstevel@tonic-gate 14087c478bd9Sstevel@tonic-gate int 14097c478bd9Sstevel@tonic-gate zonecfg_delete_filesystem(zone_dochandle_t handle, struct zone_fstab *tabptr) 14107c478bd9Sstevel@tonic-gate { 14117c478bd9Sstevel@tonic-gate int err; 14127c478bd9Sstevel@tonic-gate 14137c478bd9Sstevel@tonic-gate if (tabptr == NULL) 14147c478bd9Sstevel@tonic-gate return (Z_INVAL); 14157c478bd9Sstevel@tonic-gate 14167c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 14177c478bd9Sstevel@tonic-gate return (err); 14187c478bd9Sstevel@tonic-gate 14197c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_filesystem_core(handle, tabptr)) != Z_OK) 14207c478bd9Sstevel@tonic-gate return (err); 14217c478bd9Sstevel@tonic-gate 14227c478bd9Sstevel@tonic-gate return (Z_OK); 14237c478bd9Sstevel@tonic-gate } 14247c478bd9Sstevel@tonic-gate 14257c478bd9Sstevel@tonic-gate int 14267c478bd9Sstevel@tonic-gate zonecfg_modify_filesystem( 14277c478bd9Sstevel@tonic-gate zone_dochandle_t handle, 14287c478bd9Sstevel@tonic-gate struct zone_fstab *oldtabptr, 14297c478bd9Sstevel@tonic-gate struct zone_fstab *newtabptr) 14307c478bd9Sstevel@tonic-gate { 14317c478bd9Sstevel@tonic-gate int err; 14327c478bd9Sstevel@tonic-gate 14337c478bd9Sstevel@tonic-gate if (oldtabptr == NULL || newtabptr == NULL) 14347c478bd9Sstevel@tonic-gate return (Z_INVAL); 14357c478bd9Sstevel@tonic-gate 14367c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 14377c478bd9Sstevel@tonic-gate return (err); 14387c478bd9Sstevel@tonic-gate 14397c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_filesystem_core(handle, oldtabptr)) != Z_OK) 14407c478bd9Sstevel@tonic-gate return (err); 14417c478bd9Sstevel@tonic-gate 14427c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_filesystem_core(handle, newtabptr)) != Z_OK) 14437c478bd9Sstevel@tonic-gate return (err); 14447c478bd9Sstevel@tonic-gate 14457c478bd9Sstevel@tonic-gate return (Z_OK); 14467c478bd9Sstevel@tonic-gate } 14477c478bd9Sstevel@tonic-gate 14487c478bd9Sstevel@tonic-gate static int 14497c478bd9Sstevel@tonic-gate zonecfg_delete_ipd_core(zone_dochandle_t handle, struct zone_fstab *tabptr) 14507c478bd9Sstevel@tonic-gate { 14517c478bd9Sstevel@tonic-gate xmlNodePtr cur = handle->zone_dh_cur; 14527c478bd9Sstevel@tonic-gate 14537c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 14547c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_IPD)) 14557c478bd9Sstevel@tonic-gate continue; 14567c478bd9Sstevel@tonic-gate if (match_prop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir)) { 14577c478bd9Sstevel@tonic-gate xmlUnlinkNode(cur); 14587c478bd9Sstevel@tonic-gate xmlFreeNode(cur); 14597c478bd9Sstevel@tonic-gate return (Z_OK); 14607c478bd9Sstevel@tonic-gate } 14617c478bd9Sstevel@tonic-gate } 14627c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 14637c478bd9Sstevel@tonic-gate } 14647c478bd9Sstevel@tonic-gate 14657c478bd9Sstevel@tonic-gate int 14667c478bd9Sstevel@tonic-gate zonecfg_delete_ipd(zone_dochandle_t handle, struct zone_fstab *tabptr) 14677c478bd9Sstevel@tonic-gate { 14687c478bd9Sstevel@tonic-gate int err; 14697c478bd9Sstevel@tonic-gate 14707c478bd9Sstevel@tonic-gate if (tabptr == NULL) 14717c478bd9Sstevel@tonic-gate return (Z_INVAL); 14727c478bd9Sstevel@tonic-gate 14737c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 14747c478bd9Sstevel@tonic-gate return (err); 14757c478bd9Sstevel@tonic-gate 14767c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_ipd_core(handle, tabptr)) != Z_OK) 14777c478bd9Sstevel@tonic-gate return (err); 14787c478bd9Sstevel@tonic-gate 14797c478bd9Sstevel@tonic-gate return (Z_OK); 14807c478bd9Sstevel@tonic-gate } 14817c478bd9Sstevel@tonic-gate 14827c478bd9Sstevel@tonic-gate int 14837c478bd9Sstevel@tonic-gate zonecfg_modify_ipd(zone_dochandle_t handle, struct zone_fstab *oldtabptr, 14847c478bd9Sstevel@tonic-gate struct zone_fstab *newtabptr) 14857c478bd9Sstevel@tonic-gate { 14867c478bd9Sstevel@tonic-gate int err; 14877c478bd9Sstevel@tonic-gate 14887c478bd9Sstevel@tonic-gate if (oldtabptr == NULL || newtabptr == NULL) 14897c478bd9Sstevel@tonic-gate return (Z_INVAL); 14907c478bd9Sstevel@tonic-gate 14917c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 14927c478bd9Sstevel@tonic-gate return (err); 14937c478bd9Sstevel@tonic-gate 14947c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_ipd_core(handle, oldtabptr)) != Z_OK) 14957c478bd9Sstevel@tonic-gate return (err); 14967c478bd9Sstevel@tonic-gate 14977c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_ipd_core(handle, newtabptr)) != Z_OK) 14987c478bd9Sstevel@tonic-gate return (err); 14997c478bd9Sstevel@tonic-gate 15007c478bd9Sstevel@tonic-gate return (Z_OK); 15017c478bd9Sstevel@tonic-gate } 15027c478bd9Sstevel@tonic-gate 15037c478bd9Sstevel@tonic-gate static int 15047c478bd9Sstevel@tonic-gate fetchprop(xmlNodePtr cur, const xmlChar *propname, char *dst, size_t dstsize) 15057c478bd9Sstevel@tonic-gate { 15067c478bd9Sstevel@tonic-gate xmlChar *property; 15077c478bd9Sstevel@tonic-gate size_t srcsize; 15087c478bd9Sstevel@tonic-gate 15097c478bd9Sstevel@tonic-gate if ((property = xmlGetProp(cur, propname)) == NULL) 15107c478bd9Sstevel@tonic-gate return (Z_BAD_PROPERTY); 15117c478bd9Sstevel@tonic-gate srcsize = strlcpy(dst, (char *)property, dstsize); 15127c478bd9Sstevel@tonic-gate xmlFree(property); 15137c478bd9Sstevel@tonic-gate if (srcsize >= dstsize) 15147c478bd9Sstevel@tonic-gate return (Z_TOO_BIG); 15157c478bd9Sstevel@tonic-gate return (Z_OK); 15167c478bd9Sstevel@tonic-gate } 15177c478bd9Sstevel@tonic-gate 1518*ee519a1fSgjelinek static int 1519*ee519a1fSgjelinek fetch_alloc_prop(xmlNodePtr cur, const xmlChar *propname, char **dst) 1520*ee519a1fSgjelinek { 1521*ee519a1fSgjelinek xmlChar *property; 1522*ee519a1fSgjelinek 1523*ee519a1fSgjelinek if ((property = xmlGetProp(cur, propname)) == NULL) 1524*ee519a1fSgjelinek return (Z_BAD_PROPERTY); 1525*ee519a1fSgjelinek if ((*dst = strdup((char *)property)) == NULL) { 1526*ee519a1fSgjelinek xmlFree(property); 1527*ee519a1fSgjelinek return (Z_NOMEM); 1528*ee519a1fSgjelinek } 1529*ee519a1fSgjelinek xmlFree(property); 1530*ee519a1fSgjelinek return (Z_OK); 1531*ee519a1fSgjelinek } 1532*ee519a1fSgjelinek 15337c478bd9Sstevel@tonic-gate int 15347c478bd9Sstevel@tonic-gate zonecfg_lookup_filesystem( 15357c478bd9Sstevel@tonic-gate zone_dochandle_t handle, 15367c478bd9Sstevel@tonic-gate struct zone_fstab *tabptr) 15377c478bd9Sstevel@tonic-gate { 15387c478bd9Sstevel@tonic-gate xmlNodePtr cur, options, firstmatch; 15397c478bd9Sstevel@tonic-gate int err; 15407c478bd9Sstevel@tonic-gate char dirname[MAXPATHLEN], special[MAXPATHLEN], raw[MAXPATHLEN]; 15417c478bd9Sstevel@tonic-gate char type[FSTYPSZ]; 15427c478bd9Sstevel@tonic-gate char options_str[MAX_MNTOPT_STR]; 15437c478bd9Sstevel@tonic-gate 15447c478bd9Sstevel@tonic-gate if (tabptr == NULL) 15457c478bd9Sstevel@tonic-gate return (Z_INVAL); 15467c478bd9Sstevel@tonic-gate 15477c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 15487c478bd9Sstevel@tonic-gate return (err); 15497c478bd9Sstevel@tonic-gate 15507c478bd9Sstevel@tonic-gate /* 15517c478bd9Sstevel@tonic-gate * Walk the list of children looking for matches on any properties 15527c478bd9Sstevel@tonic-gate * specified in the fstab parameter. If more than one resource 15537c478bd9Sstevel@tonic-gate * matches, we return Z_INSUFFICIENT_SPEC; if none match, we return 15547c478bd9Sstevel@tonic-gate * Z_NO_RESOURCE_ID. 15557c478bd9Sstevel@tonic-gate */ 15567c478bd9Sstevel@tonic-gate cur = handle->zone_dh_cur; 15577c478bd9Sstevel@tonic-gate firstmatch = NULL; 15587c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 15597c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_FS)) 15607c478bd9Sstevel@tonic-gate continue; 15617c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_fs_dir) > 0) { 15627c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_DIR, dirname, 15637c478bd9Sstevel@tonic-gate sizeof (dirname)) == Z_OK) && 15647c478bd9Sstevel@tonic-gate (strcmp(tabptr->zone_fs_dir, dirname) == 0)) { 15657c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 15667c478bd9Sstevel@tonic-gate firstmatch = cur; 15677c478bd9Sstevel@tonic-gate else 15687c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 15697c478bd9Sstevel@tonic-gate } 15707c478bd9Sstevel@tonic-gate } 15717c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_fs_special) > 0) { 15727c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_SPECIAL, special, 15737c478bd9Sstevel@tonic-gate sizeof (special)) == Z_OK)) { 15747c478bd9Sstevel@tonic-gate if (strcmp(tabptr->zone_fs_special, 15757c478bd9Sstevel@tonic-gate special) == 0) { 15767c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 15777c478bd9Sstevel@tonic-gate firstmatch = cur; 15787c478bd9Sstevel@tonic-gate else if (firstmatch != cur) 15797c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 15807c478bd9Sstevel@tonic-gate } else { 15817c478bd9Sstevel@tonic-gate /* 15827c478bd9Sstevel@tonic-gate * If another property matched but this 15837c478bd9Sstevel@tonic-gate * one doesn't then reset firstmatch. 15847c478bd9Sstevel@tonic-gate */ 15857c478bd9Sstevel@tonic-gate if (firstmatch == cur) 15867c478bd9Sstevel@tonic-gate firstmatch = NULL; 15877c478bd9Sstevel@tonic-gate } 15887c478bd9Sstevel@tonic-gate } 15897c478bd9Sstevel@tonic-gate } 15907c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_fs_raw) > 0) { 15917c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_RAW, raw, 15927c478bd9Sstevel@tonic-gate sizeof (raw)) == Z_OK)) { 15937c478bd9Sstevel@tonic-gate if (strcmp(tabptr->zone_fs_raw, raw) == 0) { 15947c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 15957c478bd9Sstevel@tonic-gate firstmatch = cur; 15967c478bd9Sstevel@tonic-gate else if (firstmatch != cur) 15977c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 15987c478bd9Sstevel@tonic-gate } else { 15997c478bd9Sstevel@tonic-gate /* 16007c478bd9Sstevel@tonic-gate * If another property matched but this 16017c478bd9Sstevel@tonic-gate * one doesn't then reset firstmatch. 16027c478bd9Sstevel@tonic-gate */ 16037c478bd9Sstevel@tonic-gate if (firstmatch == cur) 16047c478bd9Sstevel@tonic-gate firstmatch = NULL; 16057c478bd9Sstevel@tonic-gate } 16067c478bd9Sstevel@tonic-gate } 16077c478bd9Sstevel@tonic-gate } 16087c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_fs_type) > 0) { 16097c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_TYPE, type, 16107c478bd9Sstevel@tonic-gate sizeof (type)) == Z_OK)) { 16117c478bd9Sstevel@tonic-gate if (strcmp(tabptr->zone_fs_type, type) == 0) { 16127c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 16137c478bd9Sstevel@tonic-gate firstmatch = cur; 16147c478bd9Sstevel@tonic-gate else if (firstmatch != cur) 16157c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 16167c478bd9Sstevel@tonic-gate } else { 16177c478bd9Sstevel@tonic-gate /* 16187c478bd9Sstevel@tonic-gate * If another property matched but this 16197c478bd9Sstevel@tonic-gate * one doesn't then reset firstmatch. 16207c478bd9Sstevel@tonic-gate */ 16217c478bd9Sstevel@tonic-gate if (firstmatch == cur) 16227c478bd9Sstevel@tonic-gate firstmatch = NULL; 16237c478bd9Sstevel@tonic-gate } 16247c478bd9Sstevel@tonic-gate } 16257c478bd9Sstevel@tonic-gate } 16267c478bd9Sstevel@tonic-gate } 16277c478bd9Sstevel@tonic-gate 16287c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 16297c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 16307c478bd9Sstevel@tonic-gate 16317c478bd9Sstevel@tonic-gate cur = firstmatch; 16327c478bd9Sstevel@tonic-gate 16337c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir, 16347c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_dir))) != Z_OK) 16357c478bd9Sstevel@tonic-gate return (err); 16367c478bd9Sstevel@tonic-gate 16377c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_SPECIAL, tabptr->zone_fs_special, 16387c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_special))) != Z_OK) 16397c478bd9Sstevel@tonic-gate return (err); 16407c478bd9Sstevel@tonic-gate 16417c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_RAW, tabptr->zone_fs_raw, 16427c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_raw))) != Z_OK) 16437c478bd9Sstevel@tonic-gate return (err); 16447c478bd9Sstevel@tonic-gate 16457c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_TYPE, tabptr->zone_fs_type, 16467c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_type))) != Z_OK) 16477c478bd9Sstevel@tonic-gate return (err); 16487c478bd9Sstevel@tonic-gate 16497c478bd9Sstevel@tonic-gate /* options are optional */ 16507c478bd9Sstevel@tonic-gate tabptr->zone_fs_options = NULL; 16517c478bd9Sstevel@tonic-gate for (options = cur->xmlChildrenNode; options != NULL; 16527c478bd9Sstevel@tonic-gate options = options->next) { 16537c478bd9Sstevel@tonic-gate if ((fetchprop(options, DTD_ATTR_NAME, options_str, 16547c478bd9Sstevel@tonic-gate sizeof (options_str)) != Z_OK)) 16557c478bd9Sstevel@tonic-gate break; 16567c478bd9Sstevel@tonic-gate if (zonecfg_add_fs_option(tabptr, options_str) != Z_OK) 16577c478bd9Sstevel@tonic-gate break; 16587c478bd9Sstevel@tonic-gate } 16597c478bd9Sstevel@tonic-gate return (Z_OK); 16607c478bd9Sstevel@tonic-gate } 16617c478bd9Sstevel@tonic-gate 16627c478bd9Sstevel@tonic-gate int 16637c478bd9Sstevel@tonic-gate zonecfg_lookup_ipd(zone_dochandle_t handle, struct zone_fstab *tabptr) 16647c478bd9Sstevel@tonic-gate { 16657c478bd9Sstevel@tonic-gate xmlNodePtr cur, match; 16667c478bd9Sstevel@tonic-gate int err; 16677c478bd9Sstevel@tonic-gate char dirname[MAXPATHLEN]; 16687c478bd9Sstevel@tonic-gate 16697c478bd9Sstevel@tonic-gate if (tabptr == NULL) 16707c478bd9Sstevel@tonic-gate return (Z_INVAL); 16717c478bd9Sstevel@tonic-gate 16727c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 16737c478bd9Sstevel@tonic-gate return (err); 16747c478bd9Sstevel@tonic-gate 16757c478bd9Sstevel@tonic-gate /* 16767c478bd9Sstevel@tonic-gate * General algorithm: 16777c478bd9Sstevel@tonic-gate * Walk the list of children looking for matches on any properties 16787c478bd9Sstevel@tonic-gate * specified in the fstab parameter. If more than one resource 16797c478bd9Sstevel@tonic-gate * matches, we return Z_INSUFFICIENT_SPEC; if none match, we return 16807c478bd9Sstevel@tonic-gate * Z_NO_RESOURCE_ID. 16817c478bd9Sstevel@tonic-gate */ 16827c478bd9Sstevel@tonic-gate cur = handle->zone_dh_cur; 16837c478bd9Sstevel@tonic-gate match = NULL; 16847c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 16857c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_IPD)) 16867c478bd9Sstevel@tonic-gate continue; 16877c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_fs_dir) > 0) { 16887c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_DIR, dirname, 16897c478bd9Sstevel@tonic-gate sizeof (dirname)) == Z_OK) && 16907c478bd9Sstevel@tonic-gate (strcmp(tabptr->zone_fs_dir, dirname) == 0)) { 16917c478bd9Sstevel@tonic-gate if (match == NULL) 16927c478bd9Sstevel@tonic-gate match = cur; 16937c478bd9Sstevel@tonic-gate else 16947c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 16957c478bd9Sstevel@tonic-gate } 16967c478bd9Sstevel@tonic-gate } 16977c478bd9Sstevel@tonic-gate } 16987c478bd9Sstevel@tonic-gate 16997c478bd9Sstevel@tonic-gate if (match == NULL) 17007c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 17017c478bd9Sstevel@tonic-gate 17027c478bd9Sstevel@tonic-gate cur = match; 17037c478bd9Sstevel@tonic-gate 17047c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir, 17057c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_dir))) != Z_OK) 17067c478bd9Sstevel@tonic-gate return (err); 17077c478bd9Sstevel@tonic-gate 17087c478bd9Sstevel@tonic-gate return (Z_OK); 17097c478bd9Sstevel@tonic-gate } 17107c478bd9Sstevel@tonic-gate 17117c478bd9Sstevel@tonic-gate /* 17127c478bd9Sstevel@tonic-gate * Compare two IP addresses in string form. Allow for the possibility that 17137c478bd9Sstevel@tonic-gate * one might have "/<prefix-length>" at the end: allow a match on just the 17147c478bd9Sstevel@tonic-gate * IP address (or host name) part. 17157c478bd9Sstevel@tonic-gate */ 17167c478bd9Sstevel@tonic-gate 17177c478bd9Sstevel@tonic-gate boolean_t 17187c478bd9Sstevel@tonic-gate zonecfg_same_net_address(char *a1, char *a2) 17197c478bd9Sstevel@tonic-gate { 17207c478bd9Sstevel@tonic-gate char *slashp, *slashp1, *slashp2; 17217c478bd9Sstevel@tonic-gate int result; 17227c478bd9Sstevel@tonic-gate 17237c478bd9Sstevel@tonic-gate if (strcmp(a1, a2) == 0) 17247c478bd9Sstevel@tonic-gate return (B_TRUE); 17257c478bd9Sstevel@tonic-gate 17267c478bd9Sstevel@tonic-gate /* 17277c478bd9Sstevel@tonic-gate * If neither has a slash or both do, they need to match to be 17287c478bd9Sstevel@tonic-gate * considered the same, but they did not match above, so fail. 17297c478bd9Sstevel@tonic-gate */ 17307c478bd9Sstevel@tonic-gate slashp1 = strchr(a1, '/'); 17317c478bd9Sstevel@tonic-gate slashp2 = strchr(a2, '/'); 17327c478bd9Sstevel@tonic-gate if ((slashp1 == NULL && slashp2 == NULL) || 17337c478bd9Sstevel@tonic-gate (slashp1 != NULL && slashp2 != NULL)) 17347c478bd9Sstevel@tonic-gate return (B_FALSE); 17357c478bd9Sstevel@tonic-gate 17367c478bd9Sstevel@tonic-gate /* 17377c478bd9Sstevel@tonic-gate * Only one had a slash: pick that one, zero out the slash, compare 17387c478bd9Sstevel@tonic-gate * the "address only" strings, restore the slash, and return the 17397c478bd9Sstevel@tonic-gate * result of the comparison. 17407c478bd9Sstevel@tonic-gate */ 17417c478bd9Sstevel@tonic-gate slashp = (slashp1 == NULL) ? slashp2 : slashp1; 17427c478bd9Sstevel@tonic-gate *slashp = '\0'; 17437c478bd9Sstevel@tonic-gate result = strcmp(a1, a2); 17447c478bd9Sstevel@tonic-gate *slashp = '/'; 17457c478bd9Sstevel@tonic-gate return ((result == 0)); 17467c478bd9Sstevel@tonic-gate } 17477c478bd9Sstevel@tonic-gate 17487c478bd9Sstevel@tonic-gate int 17497c478bd9Sstevel@tonic-gate zonecfg_valid_net_address(char *address, struct lifreq *lifr) 17507c478bd9Sstevel@tonic-gate { 17517c478bd9Sstevel@tonic-gate struct sockaddr_in *sin4; 17527c478bd9Sstevel@tonic-gate struct sockaddr_in6 *sin6; 17537c478bd9Sstevel@tonic-gate struct addrinfo hints, *result; 17547c478bd9Sstevel@tonic-gate char *slashp = strchr(address, '/'); 17557c478bd9Sstevel@tonic-gate 17567c478bd9Sstevel@tonic-gate bzero(lifr, sizeof (struct lifreq)); 17577c478bd9Sstevel@tonic-gate sin4 = (struct sockaddr_in *)&lifr->lifr_addr; 17587c478bd9Sstevel@tonic-gate sin6 = (struct sockaddr_in6 *)&lifr->lifr_addr; 17597c478bd9Sstevel@tonic-gate if (slashp != NULL) 17607c478bd9Sstevel@tonic-gate *slashp = '\0'; 17617c478bd9Sstevel@tonic-gate if (inet_pton(AF_INET, address, &sin4->sin_addr) == 1) { 17627c478bd9Sstevel@tonic-gate sin4->sin_family = AF_INET; 17637c478bd9Sstevel@tonic-gate } else if (inet_pton(AF_INET6, address, &sin6->sin6_addr) == 1) { 17647c478bd9Sstevel@tonic-gate if (slashp == NULL) 17657c478bd9Sstevel@tonic-gate return (Z_IPV6_ADDR_PREFIX_LEN); 17667c478bd9Sstevel@tonic-gate sin6->sin6_family = AF_INET6; 17677c478bd9Sstevel@tonic-gate } else { 17687c478bd9Sstevel@tonic-gate /* "address" may be a host name */ 17697c478bd9Sstevel@tonic-gate (void) memset(&hints, 0, sizeof (hints)); 17707c478bd9Sstevel@tonic-gate hints.ai_family = PF_INET; 17717c478bd9Sstevel@tonic-gate if (getaddrinfo(address, NULL, &hints, &result) != 0) 17727c478bd9Sstevel@tonic-gate return (Z_BOGUS_ADDRESS); 17737c478bd9Sstevel@tonic-gate sin4->sin_family = result->ai_family; 1774a1be23daSdp 17757c478bd9Sstevel@tonic-gate (void) memcpy(&sin4->sin_addr, 17767c478bd9Sstevel@tonic-gate /* LINTED E_BAD_PTR_CAST_ALIGN */ 17777c478bd9Sstevel@tonic-gate &((struct sockaddr_in *)result->ai_addr)->sin_addr, 17787c478bd9Sstevel@tonic-gate sizeof (struct in_addr)); 1779a1be23daSdp 17807c478bd9Sstevel@tonic-gate freeaddrinfo(result); 17817c478bd9Sstevel@tonic-gate } 17827c478bd9Sstevel@tonic-gate return (Z_OK); 17837c478bd9Sstevel@tonic-gate } 17847c478bd9Sstevel@tonic-gate 17857c478bd9Sstevel@tonic-gate int 17867c478bd9Sstevel@tonic-gate zonecfg_lookup_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr) 17877c478bd9Sstevel@tonic-gate { 17887c478bd9Sstevel@tonic-gate xmlNodePtr cur, firstmatch; 17897c478bd9Sstevel@tonic-gate int err; 17907c478bd9Sstevel@tonic-gate char address[INET6_ADDRSTRLEN], physical[LIFNAMSIZ]; 17917c478bd9Sstevel@tonic-gate 17927c478bd9Sstevel@tonic-gate if (tabptr == NULL) 17937c478bd9Sstevel@tonic-gate return (Z_INVAL); 17947c478bd9Sstevel@tonic-gate 17957c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 17967c478bd9Sstevel@tonic-gate return (err); 17977c478bd9Sstevel@tonic-gate 17987c478bd9Sstevel@tonic-gate cur = handle->zone_dh_cur; 17997c478bd9Sstevel@tonic-gate firstmatch = NULL; 18007c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 18017c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_NET)) 18027c478bd9Sstevel@tonic-gate continue; 18037c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_nwif_physical) > 0) { 18047c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_PHYSICAL, physical, 18057c478bd9Sstevel@tonic-gate sizeof (physical)) == Z_OK) && 18067c478bd9Sstevel@tonic-gate (strcmp(tabptr->zone_nwif_physical, 18077c478bd9Sstevel@tonic-gate physical) == 0)) { 18087c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 18097c478bd9Sstevel@tonic-gate firstmatch = cur; 18107c478bd9Sstevel@tonic-gate else 18117c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 18127c478bd9Sstevel@tonic-gate } 18137c478bd9Sstevel@tonic-gate } 18147c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_nwif_address) > 0) { 18157c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_ADDRESS, address, 18167c478bd9Sstevel@tonic-gate sizeof (address)) == Z_OK)) { 18177c478bd9Sstevel@tonic-gate if (zonecfg_same_net_address( 18187c478bd9Sstevel@tonic-gate tabptr->zone_nwif_address, address)) { 18197c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 18207c478bd9Sstevel@tonic-gate firstmatch = cur; 18217c478bd9Sstevel@tonic-gate else if (firstmatch != cur) 18227c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 18237c478bd9Sstevel@tonic-gate } else { 18247c478bd9Sstevel@tonic-gate /* 18257c478bd9Sstevel@tonic-gate * If another property matched but this 18267c478bd9Sstevel@tonic-gate * one doesn't then reset firstmatch. 18277c478bd9Sstevel@tonic-gate */ 18287c478bd9Sstevel@tonic-gate if (firstmatch == cur) 18297c478bd9Sstevel@tonic-gate firstmatch = NULL; 18307c478bd9Sstevel@tonic-gate } 18317c478bd9Sstevel@tonic-gate } 18327c478bd9Sstevel@tonic-gate } 18337c478bd9Sstevel@tonic-gate } 18347c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 18357c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 18367c478bd9Sstevel@tonic-gate 18377c478bd9Sstevel@tonic-gate cur = firstmatch; 18387c478bd9Sstevel@tonic-gate 18397c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_PHYSICAL, tabptr->zone_nwif_physical, 18407c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_nwif_physical))) != Z_OK) 18417c478bd9Sstevel@tonic-gate return (err); 18427c478bd9Sstevel@tonic-gate 18437c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_ADDRESS, tabptr->zone_nwif_address, 18447c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_nwif_address))) != Z_OK) 18457c478bd9Sstevel@tonic-gate return (err); 18467c478bd9Sstevel@tonic-gate 18477c478bd9Sstevel@tonic-gate return (Z_OK); 18487c478bd9Sstevel@tonic-gate } 18497c478bd9Sstevel@tonic-gate 18507c478bd9Sstevel@tonic-gate static int 18517c478bd9Sstevel@tonic-gate zonecfg_add_nwif_core(zone_dochandle_t handle, struct zone_nwiftab *tabptr) 18527c478bd9Sstevel@tonic-gate { 18537c478bd9Sstevel@tonic-gate xmlNodePtr newnode, cur = handle->zone_dh_cur; 18547c478bd9Sstevel@tonic-gate int err; 18557c478bd9Sstevel@tonic-gate 18567c478bd9Sstevel@tonic-gate newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_NET, NULL); 1857a1be23daSdp if ((err = newprop(newnode, DTD_ATTR_ADDRESS, 18587c478bd9Sstevel@tonic-gate tabptr->zone_nwif_address)) != Z_OK) 18597c478bd9Sstevel@tonic-gate return (err); 1860a1be23daSdp if ((err = newprop(newnode, DTD_ATTR_PHYSICAL, 18617c478bd9Sstevel@tonic-gate tabptr->zone_nwif_physical)) != Z_OK) 18627c478bd9Sstevel@tonic-gate return (err); 18637c478bd9Sstevel@tonic-gate return (Z_OK); 18647c478bd9Sstevel@tonic-gate } 18657c478bd9Sstevel@tonic-gate 18667c478bd9Sstevel@tonic-gate int 18677c478bd9Sstevel@tonic-gate zonecfg_add_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr) 18687c478bd9Sstevel@tonic-gate { 18697c478bd9Sstevel@tonic-gate int err; 18707c478bd9Sstevel@tonic-gate 18717c478bd9Sstevel@tonic-gate if (tabptr == NULL) 18727c478bd9Sstevel@tonic-gate return (Z_INVAL); 18737c478bd9Sstevel@tonic-gate 18747c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 18757c478bd9Sstevel@tonic-gate return (err); 18767c478bd9Sstevel@tonic-gate 18777c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_nwif_core(handle, tabptr)) != Z_OK) 18787c478bd9Sstevel@tonic-gate return (err); 18797c478bd9Sstevel@tonic-gate 18807c478bd9Sstevel@tonic-gate return (Z_OK); 18817c478bd9Sstevel@tonic-gate } 18827c478bd9Sstevel@tonic-gate 18837c478bd9Sstevel@tonic-gate static int 18847c478bd9Sstevel@tonic-gate zonecfg_delete_nwif_core(zone_dochandle_t handle, struct zone_nwiftab *tabptr) 18857c478bd9Sstevel@tonic-gate { 18867c478bd9Sstevel@tonic-gate xmlNodePtr cur = handle->zone_dh_cur; 18877c478bd9Sstevel@tonic-gate boolean_t addr_match, phys_match; 18887c478bd9Sstevel@tonic-gate 18897c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 18907c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_NET)) 18917c478bd9Sstevel@tonic-gate continue; 18927c478bd9Sstevel@tonic-gate 18937c478bd9Sstevel@tonic-gate addr_match = match_prop(cur, DTD_ATTR_ADDRESS, 18947c478bd9Sstevel@tonic-gate tabptr->zone_nwif_address); 18957c478bd9Sstevel@tonic-gate phys_match = match_prop(cur, DTD_ATTR_PHYSICAL, 18967c478bd9Sstevel@tonic-gate tabptr->zone_nwif_physical); 18977c478bd9Sstevel@tonic-gate 18987c478bd9Sstevel@tonic-gate if (addr_match && phys_match) { 18997c478bd9Sstevel@tonic-gate xmlUnlinkNode(cur); 19007c478bd9Sstevel@tonic-gate xmlFreeNode(cur); 19017c478bd9Sstevel@tonic-gate return (Z_OK); 19027c478bd9Sstevel@tonic-gate } 19037c478bd9Sstevel@tonic-gate } 19047c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 19057c478bd9Sstevel@tonic-gate } 19067c478bd9Sstevel@tonic-gate 19077c478bd9Sstevel@tonic-gate int 19087c478bd9Sstevel@tonic-gate zonecfg_delete_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr) 19097c478bd9Sstevel@tonic-gate { 19107c478bd9Sstevel@tonic-gate int err; 19117c478bd9Sstevel@tonic-gate 19127c478bd9Sstevel@tonic-gate if (tabptr == NULL) 19137c478bd9Sstevel@tonic-gate return (Z_INVAL); 19147c478bd9Sstevel@tonic-gate 19157c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 19167c478bd9Sstevel@tonic-gate return (err); 19177c478bd9Sstevel@tonic-gate 19187c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_nwif_core(handle, tabptr)) != Z_OK) 19197c478bd9Sstevel@tonic-gate return (err); 19207c478bd9Sstevel@tonic-gate 19217c478bd9Sstevel@tonic-gate return (Z_OK); 19227c478bd9Sstevel@tonic-gate } 19237c478bd9Sstevel@tonic-gate 19247c478bd9Sstevel@tonic-gate int 19257c478bd9Sstevel@tonic-gate zonecfg_modify_nwif( 19267c478bd9Sstevel@tonic-gate zone_dochandle_t handle, 19277c478bd9Sstevel@tonic-gate struct zone_nwiftab *oldtabptr, 19287c478bd9Sstevel@tonic-gate struct zone_nwiftab *newtabptr) 19297c478bd9Sstevel@tonic-gate { 19307c478bd9Sstevel@tonic-gate int err; 19317c478bd9Sstevel@tonic-gate 19327c478bd9Sstevel@tonic-gate if (oldtabptr == NULL || newtabptr == NULL) 19337c478bd9Sstevel@tonic-gate return (Z_INVAL); 19347c478bd9Sstevel@tonic-gate 19357c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 19367c478bd9Sstevel@tonic-gate return (err); 19377c478bd9Sstevel@tonic-gate 19387c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_nwif_core(handle, oldtabptr)) != Z_OK) 19397c478bd9Sstevel@tonic-gate return (err); 19407c478bd9Sstevel@tonic-gate 19417c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_nwif_core(handle, newtabptr)) != Z_OK) 19427c478bd9Sstevel@tonic-gate return (err); 19437c478bd9Sstevel@tonic-gate 19447c478bd9Sstevel@tonic-gate return (Z_OK); 19457c478bd9Sstevel@tonic-gate } 19467c478bd9Sstevel@tonic-gate 19477c478bd9Sstevel@tonic-gate int 19487c478bd9Sstevel@tonic-gate zonecfg_lookup_dev(zone_dochandle_t handle, struct zone_devtab *tabptr) 19497c478bd9Sstevel@tonic-gate { 19507c478bd9Sstevel@tonic-gate xmlNodePtr cur, firstmatch; 19517c478bd9Sstevel@tonic-gate int err; 19527c478bd9Sstevel@tonic-gate char match[MAXPATHLEN]; 19537c478bd9Sstevel@tonic-gate 19547c478bd9Sstevel@tonic-gate if (tabptr == NULL) 19557c478bd9Sstevel@tonic-gate return (Z_INVAL); 19567c478bd9Sstevel@tonic-gate 19577c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 19587c478bd9Sstevel@tonic-gate return (err); 19597c478bd9Sstevel@tonic-gate 19607c478bd9Sstevel@tonic-gate cur = handle->zone_dh_cur; 19617c478bd9Sstevel@tonic-gate firstmatch = NULL; 19627c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 19637c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_DEVICE)) 19647c478bd9Sstevel@tonic-gate continue; 19657c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_dev_match) == 0) 19667c478bd9Sstevel@tonic-gate continue; 19677c478bd9Sstevel@tonic-gate 19687c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_MATCH, match, 19697c478bd9Sstevel@tonic-gate sizeof (match)) == Z_OK)) { 19707c478bd9Sstevel@tonic-gate if (strcmp(tabptr->zone_dev_match, 19717c478bd9Sstevel@tonic-gate match) == 0) { 19727c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 19737c478bd9Sstevel@tonic-gate firstmatch = cur; 19747c478bd9Sstevel@tonic-gate else if (firstmatch != cur) 19757c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 19767c478bd9Sstevel@tonic-gate } else { 19777c478bd9Sstevel@tonic-gate /* 19787c478bd9Sstevel@tonic-gate * If another property matched but this 19797c478bd9Sstevel@tonic-gate * one doesn't then reset firstmatch. 19807c478bd9Sstevel@tonic-gate */ 19817c478bd9Sstevel@tonic-gate if (firstmatch == cur) 19827c478bd9Sstevel@tonic-gate firstmatch = NULL; 19837c478bd9Sstevel@tonic-gate } 19847c478bd9Sstevel@tonic-gate } 19857c478bd9Sstevel@tonic-gate } 19867c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 19877c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 19887c478bd9Sstevel@tonic-gate 19897c478bd9Sstevel@tonic-gate cur = firstmatch; 19907c478bd9Sstevel@tonic-gate 19917c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_MATCH, tabptr->zone_dev_match, 19927c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_dev_match))) != Z_OK) 19937c478bd9Sstevel@tonic-gate return (err); 19947c478bd9Sstevel@tonic-gate 19957c478bd9Sstevel@tonic-gate return (Z_OK); 19967c478bd9Sstevel@tonic-gate } 19977c478bd9Sstevel@tonic-gate 19987c478bd9Sstevel@tonic-gate static int 19997c478bd9Sstevel@tonic-gate zonecfg_add_dev_core(zone_dochandle_t handle, struct zone_devtab *tabptr) 20007c478bd9Sstevel@tonic-gate { 20017c478bd9Sstevel@tonic-gate xmlNodePtr newnode, cur = handle->zone_dh_cur; 20027c478bd9Sstevel@tonic-gate int err; 20037c478bd9Sstevel@tonic-gate 20047c478bd9Sstevel@tonic-gate newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_DEVICE, NULL); 20057c478bd9Sstevel@tonic-gate 2006a1be23daSdp if ((err = newprop(newnode, DTD_ATTR_MATCH, 20077c478bd9Sstevel@tonic-gate tabptr->zone_dev_match)) != Z_OK) 20087c478bd9Sstevel@tonic-gate return (err); 20097c478bd9Sstevel@tonic-gate 20107c478bd9Sstevel@tonic-gate return (Z_OK); 20117c478bd9Sstevel@tonic-gate } 20127c478bd9Sstevel@tonic-gate 20137c478bd9Sstevel@tonic-gate int 20147c478bd9Sstevel@tonic-gate zonecfg_add_dev(zone_dochandle_t handle, struct zone_devtab *tabptr) 20157c478bd9Sstevel@tonic-gate { 20167c478bd9Sstevel@tonic-gate int err; 20177c478bd9Sstevel@tonic-gate 20187c478bd9Sstevel@tonic-gate if (tabptr == 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_add_dev_core(handle, tabptr)) != Z_OK) 20257c478bd9Sstevel@tonic-gate return (err); 20267c478bd9Sstevel@tonic-gate 20277c478bd9Sstevel@tonic-gate return (Z_OK); 20287c478bd9Sstevel@tonic-gate } 20297c478bd9Sstevel@tonic-gate 20307c478bd9Sstevel@tonic-gate static int 20317c478bd9Sstevel@tonic-gate zonecfg_delete_dev_core(zone_dochandle_t handle, struct zone_devtab *tabptr) 20327c478bd9Sstevel@tonic-gate { 20337c478bd9Sstevel@tonic-gate xmlNodePtr cur = handle->zone_dh_cur; 20347c478bd9Sstevel@tonic-gate int match_match; 20357c478bd9Sstevel@tonic-gate 20367c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 20377c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_DEVICE)) 20387c478bd9Sstevel@tonic-gate continue; 20397c478bd9Sstevel@tonic-gate 20407c478bd9Sstevel@tonic-gate match_match = match_prop(cur, DTD_ATTR_MATCH, 20417c478bd9Sstevel@tonic-gate tabptr->zone_dev_match); 20427c478bd9Sstevel@tonic-gate 20437c478bd9Sstevel@tonic-gate if (match_match) { 20447c478bd9Sstevel@tonic-gate xmlUnlinkNode(cur); 20457c478bd9Sstevel@tonic-gate xmlFreeNode(cur); 20467c478bd9Sstevel@tonic-gate return (Z_OK); 20477c478bd9Sstevel@tonic-gate } 20487c478bd9Sstevel@tonic-gate } 20497c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 20507c478bd9Sstevel@tonic-gate } 20517c478bd9Sstevel@tonic-gate 20527c478bd9Sstevel@tonic-gate int 20537c478bd9Sstevel@tonic-gate zonecfg_delete_dev(zone_dochandle_t handle, struct zone_devtab *tabptr) 20547c478bd9Sstevel@tonic-gate { 20557c478bd9Sstevel@tonic-gate int err; 20567c478bd9Sstevel@tonic-gate 20577c478bd9Sstevel@tonic-gate if (tabptr == NULL) 20587c478bd9Sstevel@tonic-gate return (Z_INVAL); 20597c478bd9Sstevel@tonic-gate 20607c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 20617c478bd9Sstevel@tonic-gate return (err); 20627c478bd9Sstevel@tonic-gate 20637c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_dev_core(handle, tabptr)) != Z_OK) 20647c478bd9Sstevel@tonic-gate return (err); 20657c478bd9Sstevel@tonic-gate 20667c478bd9Sstevel@tonic-gate return (Z_OK); 20677c478bd9Sstevel@tonic-gate } 20687c478bd9Sstevel@tonic-gate 20697c478bd9Sstevel@tonic-gate int 20707c478bd9Sstevel@tonic-gate zonecfg_modify_dev( 20717c478bd9Sstevel@tonic-gate zone_dochandle_t handle, 20727c478bd9Sstevel@tonic-gate struct zone_devtab *oldtabptr, 20737c478bd9Sstevel@tonic-gate struct zone_devtab *newtabptr) 20747c478bd9Sstevel@tonic-gate { 20757c478bd9Sstevel@tonic-gate int err; 20767c478bd9Sstevel@tonic-gate 20777c478bd9Sstevel@tonic-gate if (oldtabptr == NULL || newtabptr == NULL) 20787c478bd9Sstevel@tonic-gate return (Z_INVAL); 20797c478bd9Sstevel@tonic-gate 20807c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 20817c478bd9Sstevel@tonic-gate return (err); 20827c478bd9Sstevel@tonic-gate 20837c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_dev_core(handle, oldtabptr)) != Z_OK) 20847c478bd9Sstevel@tonic-gate return (err); 20857c478bd9Sstevel@tonic-gate 20867c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_dev_core(handle, newtabptr)) != Z_OK) 20877c478bd9Sstevel@tonic-gate return (err); 20887c478bd9Sstevel@tonic-gate 20897c478bd9Sstevel@tonic-gate return (Z_OK); 20907c478bd9Sstevel@tonic-gate } 20917c478bd9Sstevel@tonic-gate 2092*ee519a1fSgjelinek /* Lock to serialize all zonecfg_devwalks */ 2093*ee519a1fSgjelinek static pthread_mutex_t zonecfg_devwalk_lock = PTHREAD_MUTEX_INITIALIZER; 2094*ee519a1fSgjelinek /* 2095*ee519a1fSgjelinek * Global variables used to pass data from zonecfg_devwalk to the nftw 2096*ee519a1fSgjelinek * call-back (zonecfg_devwalk_cb). g_devwalk_data is really the void* 2097*ee519a1fSgjelinek * parameter and g_devwalk_cb is really the *cb parameter from zonecfg_devwalk. 2098*ee519a1fSgjelinek */ 2099*ee519a1fSgjelinek static void *g_devwalk_data; 2100*ee519a1fSgjelinek static int (*g_devwalk_cb)(const char *, uid_t, gid_t, mode_t, const char *, 2101*ee519a1fSgjelinek void *); 2102*ee519a1fSgjelinek static size_t g_devwalk_skip_prefix; 2103*ee519a1fSgjelinek 2104*ee519a1fSgjelinek /* 2105*ee519a1fSgjelinek * This is the nftw call-back function used by zonecfg_devwalk. It is 2106*ee519a1fSgjelinek * responsible for calling the actual call-back that is passed in to 2107*ee519a1fSgjelinek * zonecfg_devwalk as the *cb argument. 2108*ee519a1fSgjelinek */ 2109*ee519a1fSgjelinek /* ARGSUSED2 */ 2110*ee519a1fSgjelinek static int 2111*ee519a1fSgjelinek zonecfg_devwalk_cb(const char *path, const struct stat *st, int f, 2112*ee519a1fSgjelinek struct FTW *ftw) 2113*ee519a1fSgjelinek { 2114*ee519a1fSgjelinek acl_t *acl; 2115*ee519a1fSgjelinek char *acl_txt = NULL; 2116*ee519a1fSgjelinek 2117*ee519a1fSgjelinek /* skip all but character and block devices */ 2118*ee519a1fSgjelinek if (!S_ISBLK(st->st_mode) && !S_ISCHR(st->st_mode)) 2119*ee519a1fSgjelinek return (0); 2120*ee519a1fSgjelinek 2121*ee519a1fSgjelinek if ((acl_get(path, ACL_NO_TRIVIAL, &acl) == 0) && 2122*ee519a1fSgjelinek acl != NULL) { 2123*ee519a1fSgjelinek acl_txt = acl_totext(acl, ACL_NORESOLVE); 2124*ee519a1fSgjelinek acl_free(acl); 2125*ee519a1fSgjelinek } 2126*ee519a1fSgjelinek 2127*ee519a1fSgjelinek if (strlen(path) <= g_devwalk_skip_prefix) 2128*ee519a1fSgjelinek return (0); 2129*ee519a1fSgjelinek 2130*ee519a1fSgjelinek g_devwalk_cb(path + g_devwalk_skip_prefix, st->st_uid, st->st_gid, 2131*ee519a1fSgjelinek st->st_mode & S_IAMB, acl_txt != NULL ? acl_txt : "", 2132*ee519a1fSgjelinek g_devwalk_data); 2133*ee519a1fSgjelinek free(acl_txt); 2134*ee519a1fSgjelinek return (0); 2135*ee519a1fSgjelinek } 2136*ee519a1fSgjelinek 2137*ee519a1fSgjelinek /* 2138*ee519a1fSgjelinek * Walk the dev tree for the zone specified by hdl and call the call-back (cb) 2139*ee519a1fSgjelinek * function for each entry in the tree. The call-back will be passed the 2140*ee519a1fSgjelinek * name, uid, gid, mode, acl string and the void *data input parameter 2141*ee519a1fSgjelinek * for each dev entry. 2142*ee519a1fSgjelinek * 2143*ee519a1fSgjelinek * Data is passed to the zonecfg_devwalk_cb through the global variables 2144*ee519a1fSgjelinek * g_devwalk_data, *g_devwalk_cb, and g_devwalk_skip_prefix. The 2145*ee519a1fSgjelinek * zonecfg_devwalk_cb function will actually call *cb. 2146*ee519a1fSgjelinek */ 2147*ee519a1fSgjelinek int 2148*ee519a1fSgjelinek zonecfg_devwalk(zone_dochandle_t hdl, 2149*ee519a1fSgjelinek int (*cb)(const char *, uid_t, gid_t, mode_t, const char *, void *), 2150*ee519a1fSgjelinek void *data) 2151*ee519a1fSgjelinek { 2152*ee519a1fSgjelinek char path[MAXPATHLEN]; 2153*ee519a1fSgjelinek int ret; 2154*ee519a1fSgjelinek 2155*ee519a1fSgjelinek if ((ret = zonecfg_get_zonepath(hdl, path, sizeof (path))) != Z_OK) 2156*ee519a1fSgjelinek return (ret); 2157*ee519a1fSgjelinek 2158*ee519a1fSgjelinek if (strlcat(path, "/dev", sizeof (path)) >= sizeof (path)) 2159*ee519a1fSgjelinek return (Z_TOO_BIG); 2160*ee519a1fSgjelinek g_devwalk_skip_prefix = strlen(path) + 1; 2161*ee519a1fSgjelinek 2162*ee519a1fSgjelinek /* 2163*ee519a1fSgjelinek * We have to serialize all zonecfg_devwalks in the same process 2164*ee519a1fSgjelinek * (which should be fine), since nftw() is so badly designed. 2165*ee519a1fSgjelinek */ 2166*ee519a1fSgjelinek (void) pthread_mutex_lock(&zonecfg_devwalk_lock); 2167*ee519a1fSgjelinek 2168*ee519a1fSgjelinek g_devwalk_data = data; 2169*ee519a1fSgjelinek g_devwalk_cb = cb; 2170*ee519a1fSgjelinek (void) nftw(path, zonecfg_devwalk_cb, 0, FTW_PHYS); 2171*ee519a1fSgjelinek 2172*ee519a1fSgjelinek (void) pthread_mutex_unlock(&zonecfg_devwalk_lock); 2173*ee519a1fSgjelinek return (Z_OK); 2174*ee519a1fSgjelinek } 2175*ee519a1fSgjelinek 2176*ee519a1fSgjelinek /* 2177*ee519a1fSgjelinek * Update the owner, group, mode and acl on the specified dev (inpath) for 2178*ee519a1fSgjelinek * the zone (hdl). This function can be used to fix up the dev tree after 2179*ee519a1fSgjelinek * attaching a migrated zone. 2180*ee519a1fSgjelinek */ 2181*ee519a1fSgjelinek int 2182*ee519a1fSgjelinek zonecfg_devperms_apply(zone_dochandle_t hdl, const char *inpath, uid_t owner, 2183*ee519a1fSgjelinek gid_t group, mode_t mode, const char *acltxt) 2184*ee519a1fSgjelinek { 2185*ee519a1fSgjelinek int ret; 2186*ee519a1fSgjelinek char path[MAXPATHLEN]; 2187*ee519a1fSgjelinek struct stat st; 2188*ee519a1fSgjelinek acl_t *aclp; 2189*ee519a1fSgjelinek 2190*ee519a1fSgjelinek if ((ret = zonecfg_get_zonepath(hdl, path, sizeof (path))) != Z_OK) 2191*ee519a1fSgjelinek return (ret); 2192*ee519a1fSgjelinek 2193*ee519a1fSgjelinek if (strlcat(path, "/dev/", sizeof (path)) >= sizeof (path)) 2194*ee519a1fSgjelinek return (Z_TOO_BIG); 2195*ee519a1fSgjelinek if (strlcat(path, inpath, sizeof (path)) >= sizeof (path)) 2196*ee519a1fSgjelinek return (Z_TOO_BIG); 2197*ee519a1fSgjelinek 2198*ee519a1fSgjelinek if (stat(path, &st) == -1) 2199*ee519a1fSgjelinek return (Z_INVAL); 2200*ee519a1fSgjelinek 2201*ee519a1fSgjelinek /* make sure we're only touching device nodes */ 2202*ee519a1fSgjelinek if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) 2203*ee519a1fSgjelinek return (Z_INVAL); 2204*ee519a1fSgjelinek 2205*ee519a1fSgjelinek if (chown(path, owner, group) == -1) 2206*ee519a1fSgjelinek return (Z_SYSTEM); 2207*ee519a1fSgjelinek 2208*ee519a1fSgjelinek if (chmod(path, mode) == -1) 2209*ee519a1fSgjelinek return (Z_SYSTEM); 2210*ee519a1fSgjelinek 2211*ee519a1fSgjelinek if ((acltxt == NULL) || (strcmp(acltxt, "") == 0)) 2212*ee519a1fSgjelinek return (Z_OK); 2213*ee519a1fSgjelinek 2214*ee519a1fSgjelinek if (acl_fromtext(acltxt, &aclp) != 0) 2215*ee519a1fSgjelinek return (Z_SYSTEM); 2216*ee519a1fSgjelinek 2217*ee519a1fSgjelinek errno = 0; 2218*ee519a1fSgjelinek if (acl_set(path, aclp) == -1) { 2219*ee519a1fSgjelinek free(aclp); 2220*ee519a1fSgjelinek return (Z_SYSTEM); 2221*ee519a1fSgjelinek } 2222*ee519a1fSgjelinek 2223*ee519a1fSgjelinek free(aclp); 2224*ee519a1fSgjelinek return (Z_OK); 2225*ee519a1fSgjelinek } 2226*ee519a1fSgjelinek 22277c478bd9Sstevel@tonic-gate /* 22287c478bd9Sstevel@tonic-gate * This is the set of devices which must be present in every zone. Users 22297c478bd9Sstevel@tonic-gate * can augment this list with additional device rules in their zone 22307c478bd9Sstevel@tonic-gate * configuration, but at present cannot remove any of the this set of 22317c478bd9Sstevel@tonic-gate * standard devices. All matching is done by /dev pathname (the "/dev" 22327c478bd9Sstevel@tonic-gate * part is implicit. Try to keep rules which match a large number of 22337c478bd9Sstevel@tonic-gate * devices (like the pts rule) first. 22347c478bd9Sstevel@tonic-gate */ 22357c478bd9Sstevel@tonic-gate static const char *standard_devs[] = { 22367c478bd9Sstevel@tonic-gate "pts/*", 22377c478bd9Sstevel@tonic-gate "ptmx", 22387c478bd9Sstevel@tonic-gate "random", 22397c478bd9Sstevel@tonic-gate "urandom", 22407c478bd9Sstevel@tonic-gate "poll", 22417c478bd9Sstevel@tonic-gate "pool", 22427c478bd9Sstevel@tonic-gate "kstat", 22437c478bd9Sstevel@tonic-gate "zero", 22447c478bd9Sstevel@tonic-gate "null", 22457c478bd9Sstevel@tonic-gate "crypto", 22467c478bd9Sstevel@tonic-gate "cryptoadm", 22477c478bd9Sstevel@tonic-gate "ticots", 22487c478bd9Sstevel@tonic-gate "ticotsord", 22497c478bd9Sstevel@tonic-gate "ticlts", 22507c478bd9Sstevel@tonic-gate "lo0", 22517c478bd9Sstevel@tonic-gate "lo1", 22527c478bd9Sstevel@tonic-gate "lo2", 22537c478bd9Sstevel@tonic-gate "lo3", 22547c478bd9Sstevel@tonic-gate "sad/user", 22557c478bd9Sstevel@tonic-gate "tty", 22567c478bd9Sstevel@tonic-gate "logindmux", 22577c478bd9Sstevel@tonic-gate "log", 22587c478bd9Sstevel@tonic-gate "conslog", 22597c478bd9Sstevel@tonic-gate "arp", 22607c478bd9Sstevel@tonic-gate "tcp", 22617c478bd9Sstevel@tonic-gate "tcp6", 22627c478bd9Sstevel@tonic-gate "udp", 22637c478bd9Sstevel@tonic-gate "udp6", 22647c478bd9Sstevel@tonic-gate "sysevent", 22657c478bd9Sstevel@tonic-gate #ifdef __sparc 22667c478bd9Sstevel@tonic-gate "openprom", 22677c478bd9Sstevel@tonic-gate #endif 22687c478bd9Sstevel@tonic-gate "cpu/self/cpuid", 22697c478bd9Sstevel@tonic-gate "dtrace/helper", 2270fa9e4066Sahrens "zfs", 22717c478bd9Sstevel@tonic-gate NULL 22727c478bd9Sstevel@tonic-gate }; 22737c478bd9Sstevel@tonic-gate 22747c478bd9Sstevel@tonic-gate /* 22757c478bd9Sstevel@tonic-gate * This function finds everything mounted under a zone's rootpath. 22767c478bd9Sstevel@tonic-gate * This returns the number of mounts under rootpath, or -1 on error. 22777c478bd9Sstevel@tonic-gate * callback is called once per mount found with the first argument 22787c478bd9Sstevel@tonic-gate * pointing to the mount point. 22797c478bd9Sstevel@tonic-gate * 22807c478bd9Sstevel@tonic-gate * If the callback function returns non-zero zonecfg_find_mounts 22817c478bd9Sstevel@tonic-gate * aborts with an error. 22827c478bd9Sstevel@tonic-gate */ 22837c478bd9Sstevel@tonic-gate 22847c478bd9Sstevel@tonic-gate int 22857c478bd9Sstevel@tonic-gate zonecfg_find_mounts(char *rootpath, int (*callback)(const char *, void *), 22867c478bd9Sstevel@tonic-gate void *priv) { 22877c478bd9Sstevel@tonic-gate FILE *mnttab; 22887c478bd9Sstevel@tonic-gate struct mnttab m; 22897c478bd9Sstevel@tonic-gate size_t l; 22907c478bd9Sstevel@tonic-gate int rv = 0; 22917c478bd9Sstevel@tonic-gate 22927c478bd9Sstevel@tonic-gate assert(rootpath != NULL); 22937c478bd9Sstevel@tonic-gate 22947c478bd9Sstevel@tonic-gate l = strlen(rootpath); 22957c478bd9Sstevel@tonic-gate 22967c478bd9Sstevel@tonic-gate mnttab = fopen("/etc/mnttab", "r"); 22977c478bd9Sstevel@tonic-gate 22987c478bd9Sstevel@tonic-gate if (mnttab == NULL) 22997c478bd9Sstevel@tonic-gate return (-1); 23007c478bd9Sstevel@tonic-gate 23017c478bd9Sstevel@tonic-gate if (ioctl(fileno(mnttab), MNTIOC_SHOWHIDDEN, NULL) < 0) { 23027c478bd9Sstevel@tonic-gate rv = -1; 23037c478bd9Sstevel@tonic-gate goto out; 23047c478bd9Sstevel@tonic-gate } 23057c478bd9Sstevel@tonic-gate 23067c478bd9Sstevel@tonic-gate while (!getmntent(mnttab, &m)) { 23077c478bd9Sstevel@tonic-gate if ((strncmp(rootpath, m.mnt_mountp, l) == 0) && 23087c478bd9Sstevel@tonic-gate (m.mnt_mountp[l] == '/')) { 23097c478bd9Sstevel@tonic-gate rv++; 23107c478bd9Sstevel@tonic-gate if (callback == NULL) 23117c478bd9Sstevel@tonic-gate continue; 23127c478bd9Sstevel@tonic-gate if (callback(m.mnt_mountp, priv)) { 23137c478bd9Sstevel@tonic-gate rv = -1; 23147c478bd9Sstevel@tonic-gate goto out; 23157c478bd9Sstevel@tonic-gate 23167c478bd9Sstevel@tonic-gate } 23177c478bd9Sstevel@tonic-gate } 23187c478bd9Sstevel@tonic-gate } 23197c478bd9Sstevel@tonic-gate 23207c478bd9Sstevel@tonic-gate out: 23217c478bd9Sstevel@tonic-gate (void) fclose(mnttab); 23227c478bd9Sstevel@tonic-gate return (rv); 23237c478bd9Sstevel@tonic-gate } 23247c478bd9Sstevel@tonic-gate 23257c478bd9Sstevel@tonic-gate /* 23267c478bd9Sstevel@tonic-gate * This routine is used to determine if a given device should appear in the 23277c478bd9Sstevel@tonic-gate * zone represented by 'handle'. First it consults the list of "standard" 23287c478bd9Sstevel@tonic-gate * zone devices. Then it scans the user-supplied device entries. 23297c478bd9Sstevel@tonic-gate */ 23307c478bd9Sstevel@tonic-gate int 23317c478bd9Sstevel@tonic-gate zonecfg_match_dev(zone_dochandle_t handle, char *devpath, 23327c478bd9Sstevel@tonic-gate struct zone_devtab *out_match) 23337c478bd9Sstevel@tonic-gate { 23347c478bd9Sstevel@tonic-gate int err; 23357c478bd9Sstevel@tonic-gate boolean_t found = B_FALSE; 23367c478bd9Sstevel@tonic-gate char match[MAXPATHLEN]; 23377c478bd9Sstevel@tonic-gate const char **stdmatch; 23387c478bd9Sstevel@tonic-gate xmlNodePtr cur; 23397c478bd9Sstevel@tonic-gate 23407c478bd9Sstevel@tonic-gate if (handle == NULL || devpath == NULL) 23417c478bd9Sstevel@tonic-gate return (Z_INVAL); 23427c478bd9Sstevel@tonic-gate 23437c478bd9Sstevel@tonic-gate /* 23447c478bd9Sstevel@tonic-gate * Check the "standard" devices which we require to be present. 23457c478bd9Sstevel@tonic-gate */ 23467c478bd9Sstevel@tonic-gate for (stdmatch = &standard_devs[0]; *stdmatch != NULL; stdmatch++) { 23477c478bd9Sstevel@tonic-gate /* 23487c478bd9Sstevel@tonic-gate * fnmatch gives us simple but powerful shell-style matching. 23497c478bd9Sstevel@tonic-gate */ 23507c478bd9Sstevel@tonic-gate if (fnmatch(*stdmatch, devpath, FNM_PATHNAME) == 0) { 23517c478bd9Sstevel@tonic-gate if (!out_match) 23527c478bd9Sstevel@tonic-gate return (Z_OK); 23537c478bd9Sstevel@tonic-gate (void) snprintf(out_match->zone_dev_match, 23547c478bd9Sstevel@tonic-gate sizeof (out_match->zone_dev_match), 23557c478bd9Sstevel@tonic-gate "/dev/%s", *stdmatch); 23567c478bd9Sstevel@tonic-gate return (Z_OK); 23577c478bd9Sstevel@tonic-gate } 23587c478bd9Sstevel@tonic-gate } 23597c478bd9Sstevel@tonic-gate 23607c478bd9Sstevel@tonic-gate /* 23617c478bd9Sstevel@tonic-gate * We got no hits in the set of standard devices. On to the user 23627c478bd9Sstevel@tonic-gate * supplied ones. 23637c478bd9Sstevel@tonic-gate */ 23647c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) { 23657c478bd9Sstevel@tonic-gate handle->zone_dh_cur = NULL; 23667c478bd9Sstevel@tonic-gate return (err); 23677c478bd9Sstevel@tonic-gate } 23687c478bd9Sstevel@tonic-gate 23697c478bd9Sstevel@tonic-gate cur = handle->zone_dh_cur; 23707c478bd9Sstevel@tonic-gate cur = cur->xmlChildrenNode; 23717c478bd9Sstevel@tonic-gate if (cur == NULL) 23727c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 23737c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur; 23747c478bd9Sstevel@tonic-gate 23757c478bd9Sstevel@tonic-gate for (; cur != NULL; cur = cur->next) { 23767c478bd9Sstevel@tonic-gate char *m; 23777c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_DEVICE) != 0) 23787c478bd9Sstevel@tonic-gate continue; 23797c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_MATCH, match, 23807c478bd9Sstevel@tonic-gate sizeof (match))) != Z_OK) { 23817c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 23827c478bd9Sstevel@tonic-gate return (err); 23837c478bd9Sstevel@tonic-gate } 23847c478bd9Sstevel@tonic-gate m = match; 23857c478bd9Sstevel@tonic-gate /* 23867c478bd9Sstevel@tonic-gate * fnmatch gives us simple but powerful shell-style matching; 23877c478bd9Sstevel@tonic-gate * but first, we need to strip out /dev/ from the matching rule. 23887c478bd9Sstevel@tonic-gate */ 23897c478bd9Sstevel@tonic-gate if (strncmp(m, "/dev/", 5) == 0) 23907c478bd9Sstevel@tonic-gate m += 5; 23917c478bd9Sstevel@tonic-gate 23927c478bd9Sstevel@tonic-gate if (fnmatch(m, devpath, FNM_PATHNAME) == 0) { 23937c478bd9Sstevel@tonic-gate found = B_TRUE; 23947c478bd9Sstevel@tonic-gate break; 23957c478bd9Sstevel@tonic-gate } 23967c478bd9Sstevel@tonic-gate } 23977c478bd9Sstevel@tonic-gate 23987c478bd9Sstevel@tonic-gate if (!found) 23997c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 24007c478bd9Sstevel@tonic-gate 24017c478bd9Sstevel@tonic-gate if (!out_match) 24027c478bd9Sstevel@tonic-gate return (Z_OK); 24037c478bd9Sstevel@tonic-gate 24047c478bd9Sstevel@tonic-gate (void) strlcpy(out_match->zone_dev_match, match, 24057c478bd9Sstevel@tonic-gate sizeof (out_match->zone_dev_match)); 24067c478bd9Sstevel@tonic-gate return (Z_OK); 24077c478bd9Sstevel@tonic-gate } 24087c478bd9Sstevel@tonic-gate 24097c478bd9Sstevel@tonic-gate int 24107c478bd9Sstevel@tonic-gate zonecfg_lookup_attr(zone_dochandle_t handle, struct zone_attrtab *tabptr) 24117c478bd9Sstevel@tonic-gate { 24127c478bd9Sstevel@tonic-gate xmlNodePtr cur, firstmatch; 24137c478bd9Sstevel@tonic-gate int err; 24147c478bd9Sstevel@tonic-gate char name[MAXNAMELEN], type[MAXNAMELEN], value[MAXNAMELEN]; 24157c478bd9Sstevel@tonic-gate 24167c478bd9Sstevel@tonic-gate if (tabptr == NULL) 24177c478bd9Sstevel@tonic-gate return (Z_INVAL); 24187c478bd9Sstevel@tonic-gate 24197c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 24207c478bd9Sstevel@tonic-gate return (err); 24217c478bd9Sstevel@tonic-gate 24227c478bd9Sstevel@tonic-gate cur = handle->zone_dh_cur; 24237c478bd9Sstevel@tonic-gate firstmatch = NULL; 24247c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 24257c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_ATTR)) 24267c478bd9Sstevel@tonic-gate continue; 24277c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_attr_name) > 0) { 24287c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_NAME, name, 24297c478bd9Sstevel@tonic-gate sizeof (name)) == Z_OK) && 24307c478bd9Sstevel@tonic-gate (strcmp(tabptr->zone_attr_name, name) == 0)) { 24317c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 24327c478bd9Sstevel@tonic-gate firstmatch = cur; 24337c478bd9Sstevel@tonic-gate else 24347c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 24357c478bd9Sstevel@tonic-gate } 24367c478bd9Sstevel@tonic-gate } 24377c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_attr_type) > 0) { 24387c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_TYPE, type, 24397c478bd9Sstevel@tonic-gate sizeof (type)) == Z_OK)) { 24407c478bd9Sstevel@tonic-gate if (strcmp(tabptr->zone_attr_type, type) == 0) { 24417c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 24427c478bd9Sstevel@tonic-gate firstmatch = cur; 24437c478bd9Sstevel@tonic-gate else if (firstmatch != cur) 24447c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 24457c478bd9Sstevel@tonic-gate } else { 24467c478bd9Sstevel@tonic-gate /* 24477c478bd9Sstevel@tonic-gate * If another property matched but this 24487c478bd9Sstevel@tonic-gate * one doesn't then reset firstmatch. 24497c478bd9Sstevel@tonic-gate */ 24507c478bd9Sstevel@tonic-gate if (firstmatch == cur) 24517c478bd9Sstevel@tonic-gate firstmatch = NULL; 24527c478bd9Sstevel@tonic-gate } 24537c478bd9Sstevel@tonic-gate } 24547c478bd9Sstevel@tonic-gate } 24557c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_attr_value) > 0) { 24567c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_VALUE, value, 24577c478bd9Sstevel@tonic-gate sizeof (value)) == Z_OK)) { 24587c478bd9Sstevel@tonic-gate if (strcmp(tabptr->zone_attr_value, value) == 24597c478bd9Sstevel@tonic-gate 0) { 24607c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 24617c478bd9Sstevel@tonic-gate firstmatch = cur; 24627c478bd9Sstevel@tonic-gate else if (firstmatch != cur) 24637c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 24647c478bd9Sstevel@tonic-gate } else { 24657c478bd9Sstevel@tonic-gate /* 24667c478bd9Sstevel@tonic-gate * If another property matched but this 24677c478bd9Sstevel@tonic-gate * one doesn't then reset firstmatch. 24687c478bd9Sstevel@tonic-gate */ 24697c478bd9Sstevel@tonic-gate if (firstmatch == cur) 24707c478bd9Sstevel@tonic-gate firstmatch = NULL; 24717c478bd9Sstevel@tonic-gate } 24727c478bd9Sstevel@tonic-gate } 24737c478bd9Sstevel@tonic-gate } 24747c478bd9Sstevel@tonic-gate } 24757c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 24767c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 24777c478bd9Sstevel@tonic-gate 24787c478bd9Sstevel@tonic-gate cur = firstmatch; 24797c478bd9Sstevel@tonic-gate 24807c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_NAME, tabptr->zone_attr_name, 24817c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_attr_name))) != Z_OK) 24827c478bd9Sstevel@tonic-gate return (err); 24837c478bd9Sstevel@tonic-gate 24847c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_TYPE, tabptr->zone_attr_type, 24857c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_attr_type))) != Z_OK) 24867c478bd9Sstevel@tonic-gate return (err); 24877c478bd9Sstevel@tonic-gate 24887c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_VALUE, tabptr->zone_attr_value, 24897c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_attr_value))) != Z_OK) 24907c478bd9Sstevel@tonic-gate return (err); 24917c478bd9Sstevel@tonic-gate 24927c478bd9Sstevel@tonic-gate return (Z_OK); 24937c478bd9Sstevel@tonic-gate } 24947c478bd9Sstevel@tonic-gate 24957c478bd9Sstevel@tonic-gate static int 24967c478bd9Sstevel@tonic-gate zonecfg_add_attr_core(zone_dochandle_t handle, struct zone_attrtab *tabptr) 24977c478bd9Sstevel@tonic-gate { 24987c478bd9Sstevel@tonic-gate xmlNodePtr newnode, cur = handle->zone_dh_cur; 24997c478bd9Sstevel@tonic-gate int err; 25007c478bd9Sstevel@tonic-gate 25017c478bd9Sstevel@tonic-gate newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_ATTR, NULL); 2502a1be23daSdp err = newprop(newnode, DTD_ATTR_NAME, tabptr->zone_attr_name); 25037c478bd9Sstevel@tonic-gate if (err != Z_OK) 25047c478bd9Sstevel@tonic-gate return (err); 2505a1be23daSdp err = newprop(newnode, DTD_ATTR_TYPE, tabptr->zone_attr_type); 25067c478bd9Sstevel@tonic-gate if (err != Z_OK) 25077c478bd9Sstevel@tonic-gate return (err); 2508a1be23daSdp err = newprop(newnode, DTD_ATTR_VALUE, tabptr->zone_attr_value); 25097c478bd9Sstevel@tonic-gate if (err != Z_OK) 25107c478bd9Sstevel@tonic-gate return (err); 25117c478bd9Sstevel@tonic-gate return (Z_OK); 25127c478bd9Sstevel@tonic-gate } 25137c478bd9Sstevel@tonic-gate 25147c478bd9Sstevel@tonic-gate int 25157c478bd9Sstevel@tonic-gate zonecfg_add_attr(zone_dochandle_t handle, struct zone_attrtab *tabptr) 25167c478bd9Sstevel@tonic-gate { 25177c478bd9Sstevel@tonic-gate int err; 25187c478bd9Sstevel@tonic-gate 25197c478bd9Sstevel@tonic-gate if (tabptr == NULL) 25207c478bd9Sstevel@tonic-gate return (Z_INVAL); 25217c478bd9Sstevel@tonic-gate 25227c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 25237c478bd9Sstevel@tonic-gate return (err); 25247c478bd9Sstevel@tonic-gate 25257c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_attr_core(handle, tabptr)) != Z_OK) 25267c478bd9Sstevel@tonic-gate return (err); 25277c478bd9Sstevel@tonic-gate 25287c478bd9Sstevel@tonic-gate return (Z_OK); 25297c478bd9Sstevel@tonic-gate } 25307c478bd9Sstevel@tonic-gate 25317c478bd9Sstevel@tonic-gate static int 25327c478bd9Sstevel@tonic-gate zonecfg_delete_attr_core(zone_dochandle_t handle, struct zone_attrtab *tabptr) 25337c478bd9Sstevel@tonic-gate { 25347c478bd9Sstevel@tonic-gate xmlNodePtr cur = handle->zone_dh_cur; 25357c478bd9Sstevel@tonic-gate int name_match, type_match, value_match; 25367c478bd9Sstevel@tonic-gate 25377c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 25387c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_ATTR)) 25397c478bd9Sstevel@tonic-gate continue; 25407c478bd9Sstevel@tonic-gate 25417c478bd9Sstevel@tonic-gate name_match = match_prop(cur, DTD_ATTR_NAME, 25427c478bd9Sstevel@tonic-gate tabptr->zone_attr_name); 25437c478bd9Sstevel@tonic-gate type_match = match_prop(cur, DTD_ATTR_TYPE, 25447c478bd9Sstevel@tonic-gate tabptr->zone_attr_type); 25457c478bd9Sstevel@tonic-gate value_match = match_prop(cur, DTD_ATTR_VALUE, 25467c478bd9Sstevel@tonic-gate tabptr->zone_attr_value); 25477c478bd9Sstevel@tonic-gate 25487c478bd9Sstevel@tonic-gate if (name_match && type_match && value_match) { 25497c478bd9Sstevel@tonic-gate xmlUnlinkNode(cur); 25507c478bd9Sstevel@tonic-gate xmlFreeNode(cur); 25517c478bd9Sstevel@tonic-gate return (Z_OK); 25527c478bd9Sstevel@tonic-gate } 25537c478bd9Sstevel@tonic-gate } 25547c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 25557c478bd9Sstevel@tonic-gate } 25567c478bd9Sstevel@tonic-gate 25577c478bd9Sstevel@tonic-gate int 25587c478bd9Sstevel@tonic-gate zonecfg_delete_attr(zone_dochandle_t handle, struct zone_attrtab *tabptr) 25597c478bd9Sstevel@tonic-gate { 25607c478bd9Sstevel@tonic-gate int err; 25617c478bd9Sstevel@tonic-gate 25627c478bd9Sstevel@tonic-gate if (tabptr == NULL) 25637c478bd9Sstevel@tonic-gate return (Z_INVAL); 25647c478bd9Sstevel@tonic-gate 25657c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 25667c478bd9Sstevel@tonic-gate return (err); 25677c478bd9Sstevel@tonic-gate 25687c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_attr_core(handle, tabptr)) != Z_OK) 25697c478bd9Sstevel@tonic-gate return (err); 25707c478bd9Sstevel@tonic-gate 25717c478bd9Sstevel@tonic-gate return (Z_OK); 25727c478bd9Sstevel@tonic-gate } 25737c478bd9Sstevel@tonic-gate 25747c478bd9Sstevel@tonic-gate int 25757c478bd9Sstevel@tonic-gate zonecfg_modify_attr( 25767c478bd9Sstevel@tonic-gate zone_dochandle_t handle, 25777c478bd9Sstevel@tonic-gate struct zone_attrtab *oldtabptr, 25787c478bd9Sstevel@tonic-gate struct zone_attrtab *newtabptr) 25797c478bd9Sstevel@tonic-gate { 25807c478bd9Sstevel@tonic-gate int err; 25817c478bd9Sstevel@tonic-gate 25827c478bd9Sstevel@tonic-gate if (oldtabptr == NULL || newtabptr == NULL) 25837c478bd9Sstevel@tonic-gate return (Z_INVAL); 25847c478bd9Sstevel@tonic-gate 25857c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 25867c478bd9Sstevel@tonic-gate return (err); 25877c478bd9Sstevel@tonic-gate 25887c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_attr_core(handle, oldtabptr)) != Z_OK) 25897c478bd9Sstevel@tonic-gate return (err); 25907c478bd9Sstevel@tonic-gate 25917c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_attr_core(handle, newtabptr)) != Z_OK) 25927c478bd9Sstevel@tonic-gate return (err); 25937c478bd9Sstevel@tonic-gate 25947c478bd9Sstevel@tonic-gate return (Z_OK); 25957c478bd9Sstevel@tonic-gate } 25967c478bd9Sstevel@tonic-gate 25977c478bd9Sstevel@tonic-gate int 25987c478bd9Sstevel@tonic-gate zonecfg_get_attr_boolean(const struct zone_attrtab *attr, boolean_t *value) 25997c478bd9Sstevel@tonic-gate { 26007c478bd9Sstevel@tonic-gate if (attr == NULL) 26017c478bd9Sstevel@tonic-gate return (Z_INVAL); 26027c478bd9Sstevel@tonic-gate 26037c478bd9Sstevel@tonic-gate if (strcmp(attr->zone_attr_type, DTD_ENTITY_BOOLEAN) != 0) 26047c478bd9Sstevel@tonic-gate return (Z_INVAL); 26057c478bd9Sstevel@tonic-gate 26067c478bd9Sstevel@tonic-gate if (strcmp(attr->zone_attr_value, DTD_ENTITY_TRUE) == 0) { 26077c478bd9Sstevel@tonic-gate *value = B_TRUE; 26087c478bd9Sstevel@tonic-gate return (Z_OK); 26097c478bd9Sstevel@tonic-gate } 26107c478bd9Sstevel@tonic-gate if (strcmp(attr->zone_attr_value, DTD_ENTITY_FALSE) == 0) { 26117c478bd9Sstevel@tonic-gate *value = B_FALSE; 26127c478bd9Sstevel@tonic-gate return (Z_OK); 26137c478bd9Sstevel@tonic-gate } 26147c478bd9Sstevel@tonic-gate return (Z_INVAL); 26157c478bd9Sstevel@tonic-gate } 26167c478bd9Sstevel@tonic-gate 26177c478bd9Sstevel@tonic-gate int 26187c478bd9Sstevel@tonic-gate zonecfg_get_attr_int(const struct zone_attrtab *attr, int64_t *value) 26197c478bd9Sstevel@tonic-gate { 26207c478bd9Sstevel@tonic-gate long long result; 26217c478bd9Sstevel@tonic-gate char *endptr; 26227c478bd9Sstevel@tonic-gate 26237c478bd9Sstevel@tonic-gate if (attr == NULL) 26247c478bd9Sstevel@tonic-gate return (Z_INVAL); 26257c478bd9Sstevel@tonic-gate 26267c478bd9Sstevel@tonic-gate if (strcmp(attr->zone_attr_type, DTD_ENTITY_INT) != 0) 26277c478bd9Sstevel@tonic-gate return (Z_INVAL); 26287c478bd9Sstevel@tonic-gate 26297c478bd9Sstevel@tonic-gate errno = 0; 26307c478bd9Sstevel@tonic-gate result = strtoll(attr->zone_attr_value, &endptr, 10); 26317c478bd9Sstevel@tonic-gate if (errno != 0 || *endptr != '\0') 26327c478bd9Sstevel@tonic-gate return (Z_INVAL); 26337c478bd9Sstevel@tonic-gate *value = result; 26347c478bd9Sstevel@tonic-gate return (Z_OK); 26357c478bd9Sstevel@tonic-gate } 26367c478bd9Sstevel@tonic-gate 26377c478bd9Sstevel@tonic-gate int 26387c478bd9Sstevel@tonic-gate zonecfg_get_attr_string(const struct zone_attrtab *attr, char *value, 26397c478bd9Sstevel@tonic-gate size_t val_sz) 26407c478bd9Sstevel@tonic-gate { 26417c478bd9Sstevel@tonic-gate if (attr == NULL) 26427c478bd9Sstevel@tonic-gate return (Z_INVAL); 26437c478bd9Sstevel@tonic-gate 26447c478bd9Sstevel@tonic-gate if (strcmp(attr->zone_attr_type, DTD_ENTITY_STRING) != 0) 26457c478bd9Sstevel@tonic-gate return (Z_INVAL); 26467c478bd9Sstevel@tonic-gate 26477c478bd9Sstevel@tonic-gate if (strlcpy(value, attr->zone_attr_value, val_sz) >= val_sz) 26487c478bd9Sstevel@tonic-gate return (Z_TOO_BIG); 26497c478bd9Sstevel@tonic-gate return (Z_OK); 26507c478bd9Sstevel@tonic-gate } 26517c478bd9Sstevel@tonic-gate 26527c478bd9Sstevel@tonic-gate int 26537c478bd9Sstevel@tonic-gate zonecfg_get_attr_uint(const struct zone_attrtab *attr, uint64_t *value) 26547c478bd9Sstevel@tonic-gate { 26557c478bd9Sstevel@tonic-gate unsigned long long result; 26567c478bd9Sstevel@tonic-gate long long neg_result; 26577c478bd9Sstevel@tonic-gate char *endptr; 26587c478bd9Sstevel@tonic-gate 26597c478bd9Sstevel@tonic-gate if (attr == NULL) 26607c478bd9Sstevel@tonic-gate return (Z_INVAL); 26617c478bd9Sstevel@tonic-gate 26627c478bd9Sstevel@tonic-gate if (strcmp(attr->zone_attr_type, DTD_ENTITY_UINT) != 0) 26637c478bd9Sstevel@tonic-gate return (Z_INVAL); 26647c478bd9Sstevel@tonic-gate 26657c478bd9Sstevel@tonic-gate errno = 0; 26667c478bd9Sstevel@tonic-gate result = strtoull(attr->zone_attr_value, &endptr, 10); 26677c478bd9Sstevel@tonic-gate if (errno != 0 || *endptr != '\0') 26687c478bd9Sstevel@tonic-gate return (Z_INVAL); 26697c478bd9Sstevel@tonic-gate errno = 0; 26707c478bd9Sstevel@tonic-gate neg_result = strtoll(attr->zone_attr_value, &endptr, 10); 26717c478bd9Sstevel@tonic-gate /* 26727c478bd9Sstevel@tonic-gate * Incredibly, strtoull("<negative number>", ...) will not fail but 26737c478bd9Sstevel@tonic-gate * return whatever (negative) number cast as a u_longlong_t, so we 26747c478bd9Sstevel@tonic-gate * need to look for this here. 26757c478bd9Sstevel@tonic-gate */ 26767c478bd9Sstevel@tonic-gate if (errno == 0 && neg_result < 0) 26777c478bd9Sstevel@tonic-gate return (Z_INVAL); 26787c478bd9Sstevel@tonic-gate *value = result; 26797c478bd9Sstevel@tonic-gate return (Z_OK); 26807c478bd9Sstevel@tonic-gate } 26817c478bd9Sstevel@tonic-gate 26827c478bd9Sstevel@tonic-gate int 26837c478bd9Sstevel@tonic-gate zonecfg_lookup_rctl(zone_dochandle_t handle, struct zone_rctltab *tabptr) 26847c478bd9Sstevel@tonic-gate { 26857c478bd9Sstevel@tonic-gate xmlNodePtr cur, val; 26867c478bd9Sstevel@tonic-gate char savedname[MAXNAMELEN]; 26877c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *valptr; 26887c478bd9Sstevel@tonic-gate int err; 26897c478bd9Sstevel@tonic-gate 26907c478bd9Sstevel@tonic-gate if (tabptr->zone_rctl_name == NULL || 26917c478bd9Sstevel@tonic-gate strlen(tabptr->zone_rctl_name) == 0) 26927c478bd9Sstevel@tonic-gate return (Z_INVAL); 26937c478bd9Sstevel@tonic-gate 26947c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 26957c478bd9Sstevel@tonic-gate return (err); 26967c478bd9Sstevel@tonic-gate 26977c478bd9Sstevel@tonic-gate cur = handle->zone_dh_cur; 26987c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 26997c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_RCTL)) 27007c478bd9Sstevel@tonic-gate continue; 27017c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_NAME, savedname, 27027c478bd9Sstevel@tonic-gate sizeof (savedname)) == Z_OK) && 27037c478bd9Sstevel@tonic-gate (strcmp(savedname, tabptr->zone_rctl_name) == 0)) { 27047c478bd9Sstevel@tonic-gate tabptr->zone_rctl_valptr = NULL; 27057c478bd9Sstevel@tonic-gate for (val = cur->xmlChildrenNode; val != NULL; 27067c478bd9Sstevel@tonic-gate val = val->next) { 27077c478bd9Sstevel@tonic-gate valptr = (struct zone_rctlvaltab *)malloc( 27087c478bd9Sstevel@tonic-gate sizeof (struct zone_rctlvaltab)); 27097c478bd9Sstevel@tonic-gate if (valptr == NULL) 27107c478bd9Sstevel@tonic-gate return (Z_NOMEM); 27117c478bd9Sstevel@tonic-gate if ((fetchprop(val, DTD_ATTR_PRIV, 27127c478bd9Sstevel@tonic-gate valptr->zone_rctlval_priv, 27137c478bd9Sstevel@tonic-gate sizeof (valptr->zone_rctlval_priv)) != 27147c478bd9Sstevel@tonic-gate Z_OK)) 27157c478bd9Sstevel@tonic-gate break; 27167c478bd9Sstevel@tonic-gate if ((fetchprop(val, DTD_ATTR_LIMIT, 27177c478bd9Sstevel@tonic-gate valptr->zone_rctlval_limit, 27187c478bd9Sstevel@tonic-gate sizeof (valptr->zone_rctlval_limit)) != 27197c478bd9Sstevel@tonic-gate Z_OK)) 27207c478bd9Sstevel@tonic-gate break; 27217c478bd9Sstevel@tonic-gate if ((fetchprop(val, DTD_ATTR_ACTION, 27227c478bd9Sstevel@tonic-gate valptr->zone_rctlval_action, 27237c478bd9Sstevel@tonic-gate sizeof (valptr->zone_rctlval_action)) != 27247c478bd9Sstevel@tonic-gate Z_OK)) 27257c478bd9Sstevel@tonic-gate break; 27267c478bd9Sstevel@tonic-gate if (zonecfg_add_rctl_value(tabptr, valptr) != 27277c478bd9Sstevel@tonic-gate Z_OK) 27287c478bd9Sstevel@tonic-gate break; 27297c478bd9Sstevel@tonic-gate } 27307c478bd9Sstevel@tonic-gate return (Z_OK); 27317c478bd9Sstevel@tonic-gate } 27327c478bd9Sstevel@tonic-gate } 27337c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 27347c478bd9Sstevel@tonic-gate } 27357c478bd9Sstevel@tonic-gate 27367c478bd9Sstevel@tonic-gate static int 27377c478bd9Sstevel@tonic-gate zonecfg_add_rctl_core(zone_dochandle_t handle, struct zone_rctltab *tabptr) 27387c478bd9Sstevel@tonic-gate { 27397c478bd9Sstevel@tonic-gate xmlNodePtr newnode, cur = handle->zone_dh_cur, valnode; 27407c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *valptr; 27417c478bd9Sstevel@tonic-gate int err; 27427c478bd9Sstevel@tonic-gate 27437c478bd9Sstevel@tonic-gate newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_RCTL, NULL); 2744a1be23daSdp err = newprop(newnode, DTD_ATTR_NAME, tabptr->zone_rctl_name); 27457c478bd9Sstevel@tonic-gate if (err != Z_OK) 27467c478bd9Sstevel@tonic-gate return (err); 27477c478bd9Sstevel@tonic-gate for (valptr = tabptr->zone_rctl_valptr; valptr != NULL; 27487c478bd9Sstevel@tonic-gate valptr = valptr->zone_rctlval_next) { 27497c478bd9Sstevel@tonic-gate valnode = xmlNewTextChild(newnode, NULL, 27507c478bd9Sstevel@tonic-gate DTD_ELEM_RCTLVALUE, NULL); 2751a1be23daSdp err = newprop(valnode, DTD_ATTR_PRIV, 27527c478bd9Sstevel@tonic-gate valptr->zone_rctlval_priv); 27537c478bd9Sstevel@tonic-gate if (err != Z_OK) 27547c478bd9Sstevel@tonic-gate return (err); 2755a1be23daSdp err = newprop(valnode, DTD_ATTR_LIMIT, 27567c478bd9Sstevel@tonic-gate valptr->zone_rctlval_limit); 27577c478bd9Sstevel@tonic-gate if (err != Z_OK) 27587c478bd9Sstevel@tonic-gate return (err); 2759a1be23daSdp err = newprop(valnode, DTD_ATTR_ACTION, 27607c478bd9Sstevel@tonic-gate valptr->zone_rctlval_action); 27617c478bd9Sstevel@tonic-gate if (err != Z_OK) 27627c478bd9Sstevel@tonic-gate return (err); 27637c478bd9Sstevel@tonic-gate } 27647c478bd9Sstevel@tonic-gate return (Z_OK); 27657c478bd9Sstevel@tonic-gate } 27667c478bd9Sstevel@tonic-gate 27677c478bd9Sstevel@tonic-gate int 27687c478bd9Sstevel@tonic-gate zonecfg_add_rctl(zone_dochandle_t handle, struct zone_rctltab *tabptr) 27697c478bd9Sstevel@tonic-gate { 27707c478bd9Sstevel@tonic-gate int err; 27717c478bd9Sstevel@tonic-gate 27727c478bd9Sstevel@tonic-gate if (tabptr == NULL || tabptr->zone_rctl_name == NULL) 27737c478bd9Sstevel@tonic-gate return (Z_INVAL); 27747c478bd9Sstevel@tonic-gate 27757c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 27767c478bd9Sstevel@tonic-gate return (err); 27777c478bd9Sstevel@tonic-gate 27787c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_rctl_core(handle, tabptr)) != Z_OK) 27797c478bd9Sstevel@tonic-gate return (err); 27807c478bd9Sstevel@tonic-gate 27817c478bd9Sstevel@tonic-gate return (Z_OK); 27827c478bd9Sstevel@tonic-gate } 27837c478bd9Sstevel@tonic-gate 27847c478bd9Sstevel@tonic-gate static int 27857c478bd9Sstevel@tonic-gate zonecfg_delete_rctl_core(zone_dochandle_t handle, struct zone_rctltab *tabptr) 27867c478bd9Sstevel@tonic-gate { 27877c478bd9Sstevel@tonic-gate xmlNodePtr cur = handle->zone_dh_cur; 27887c478bd9Sstevel@tonic-gate xmlChar *savedname; 27897c478bd9Sstevel@tonic-gate int name_result; 27907c478bd9Sstevel@tonic-gate 27917c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 27927c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_RCTL)) 27937c478bd9Sstevel@tonic-gate continue; 27947c478bd9Sstevel@tonic-gate 27957c478bd9Sstevel@tonic-gate savedname = xmlGetProp(cur, DTD_ATTR_NAME); 27967c478bd9Sstevel@tonic-gate if (savedname == NULL) /* shouldn't happen */ 27977c478bd9Sstevel@tonic-gate continue; 27987c478bd9Sstevel@tonic-gate name_result = xmlStrcmp(savedname, 27997c478bd9Sstevel@tonic-gate (const xmlChar *) tabptr->zone_rctl_name); 28007c478bd9Sstevel@tonic-gate xmlFree(savedname); 28017c478bd9Sstevel@tonic-gate 28027c478bd9Sstevel@tonic-gate if (name_result == 0) { 28037c478bd9Sstevel@tonic-gate xmlUnlinkNode(cur); 28047c478bd9Sstevel@tonic-gate xmlFreeNode(cur); 28057c478bd9Sstevel@tonic-gate return (Z_OK); 28067c478bd9Sstevel@tonic-gate } 28077c478bd9Sstevel@tonic-gate } 28087c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 28097c478bd9Sstevel@tonic-gate } 28107c478bd9Sstevel@tonic-gate 28117c478bd9Sstevel@tonic-gate int 28127c478bd9Sstevel@tonic-gate zonecfg_delete_rctl(zone_dochandle_t handle, struct zone_rctltab *tabptr) 28137c478bd9Sstevel@tonic-gate { 28147c478bd9Sstevel@tonic-gate int err; 28157c478bd9Sstevel@tonic-gate 28167c478bd9Sstevel@tonic-gate if (tabptr == NULL || tabptr->zone_rctl_name == NULL) 28177c478bd9Sstevel@tonic-gate return (Z_INVAL); 28187c478bd9Sstevel@tonic-gate 28197c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 28207c478bd9Sstevel@tonic-gate return (err); 28217c478bd9Sstevel@tonic-gate 28227c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_rctl_core(handle, tabptr)) != Z_OK) 28237c478bd9Sstevel@tonic-gate return (err); 28247c478bd9Sstevel@tonic-gate 28257c478bd9Sstevel@tonic-gate return (Z_OK); 28267c478bd9Sstevel@tonic-gate } 28277c478bd9Sstevel@tonic-gate 28287c478bd9Sstevel@tonic-gate int 28297c478bd9Sstevel@tonic-gate zonecfg_modify_rctl( 28307c478bd9Sstevel@tonic-gate zone_dochandle_t handle, 28317c478bd9Sstevel@tonic-gate struct zone_rctltab *oldtabptr, 28327c478bd9Sstevel@tonic-gate struct zone_rctltab *newtabptr) 28337c478bd9Sstevel@tonic-gate { 28347c478bd9Sstevel@tonic-gate int err; 28357c478bd9Sstevel@tonic-gate 28367c478bd9Sstevel@tonic-gate if (oldtabptr == NULL || oldtabptr->zone_rctl_name == NULL || 28377c478bd9Sstevel@tonic-gate newtabptr == NULL || newtabptr->zone_rctl_name == NULL) 28387c478bd9Sstevel@tonic-gate return (Z_INVAL); 28397c478bd9Sstevel@tonic-gate 28407c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 28417c478bd9Sstevel@tonic-gate return (err); 28427c478bd9Sstevel@tonic-gate 28437c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_rctl_core(handle, oldtabptr)) != Z_OK) 28447c478bd9Sstevel@tonic-gate return (err); 28457c478bd9Sstevel@tonic-gate 28467c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_rctl_core(handle, newtabptr)) != Z_OK) 28477c478bd9Sstevel@tonic-gate return (err); 28487c478bd9Sstevel@tonic-gate 28497c478bd9Sstevel@tonic-gate return (Z_OK); 28507c478bd9Sstevel@tonic-gate } 28517c478bd9Sstevel@tonic-gate 28527c478bd9Sstevel@tonic-gate int 28537c478bd9Sstevel@tonic-gate zonecfg_add_rctl_value( 28547c478bd9Sstevel@tonic-gate struct zone_rctltab *tabptr, 28557c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *valtabptr) 28567c478bd9Sstevel@tonic-gate { 28577c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *last, *old, *new; 28587c478bd9Sstevel@tonic-gate rctlblk_t *rctlblk = alloca(rctlblk_size()); 28597c478bd9Sstevel@tonic-gate 28607c478bd9Sstevel@tonic-gate last = tabptr->zone_rctl_valptr; 28617c478bd9Sstevel@tonic-gate for (old = last; old != NULL; old = old->zone_rctlval_next) 28627c478bd9Sstevel@tonic-gate last = old; /* walk to the end of the list */ 28637c478bd9Sstevel@tonic-gate new = valtabptr; /* alloc'd by caller */ 28647c478bd9Sstevel@tonic-gate new->zone_rctlval_next = NULL; 28657c478bd9Sstevel@tonic-gate if (zonecfg_construct_rctlblk(valtabptr, rctlblk) != Z_OK) 28667c478bd9Sstevel@tonic-gate return (Z_INVAL); 28677c478bd9Sstevel@tonic-gate if (!zonecfg_valid_rctlblk(rctlblk)) 28687c478bd9Sstevel@tonic-gate return (Z_INVAL); 28697c478bd9Sstevel@tonic-gate if (last == NULL) 28707c478bd9Sstevel@tonic-gate tabptr->zone_rctl_valptr = new; 28717c478bd9Sstevel@tonic-gate else 28727c478bd9Sstevel@tonic-gate last->zone_rctlval_next = new; 28737c478bd9Sstevel@tonic-gate return (Z_OK); 28747c478bd9Sstevel@tonic-gate } 28757c478bd9Sstevel@tonic-gate 28767c478bd9Sstevel@tonic-gate int 28777c478bd9Sstevel@tonic-gate zonecfg_remove_rctl_value( 28787c478bd9Sstevel@tonic-gate struct zone_rctltab *tabptr, 28797c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *valtabptr) 28807c478bd9Sstevel@tonic-gate { 28817c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *last, *this, *next; 28827c478bd9Sstevel@tonic-gate 28837c478bd9Sstevel@tonic-gate last = tabptr->zone_rctl_valptr; 28847c478bd9Sstevel@tonic-gate for (this = last; this != NULL; this = this->zone_rctlval_next) { 28857c478bd9Sstevel@tonic-gate if (strcmp(this->zone_rctlval_priv, 28867c478bd9Sstevel@tonic-gate valtabptr->zone_rctlval_priv) == 0 && 28877c478bd9Sstevel@tonic-gate strcmp(this->zone_rctlval_limit, 28887c478bd9Sstevel@tonic-gate valtabptr->zone_rctlval_limit) == 0 && 28897c478bd9Sstevel@tonic-gate strcmp(this->zone_rctlval_action, 28907c478bd9Sstevel@tonic-gate valtabptr->zone_rctlval_action) == 0) { 28917c478bd9Sstevel@tonic-gate next = this->zone_rctlval_next; 28927c478bd9Sstevel@tonic-gate if (this == tabptr->zone_rctl_valptr) 28937c478bd9Sstevel@tonic-gate tabptr->zone_rctl_valptr = next; 28947c478bd9Sstevel@tonic-gate else 28957c478bd9Sstevel@tonic-gate last->zone_rctlval_next = next; 28967c478bd9Sstevel@tonic-gate free(this); 28977c478bd9Sstevel@tonic-gate return (Z_OK); 28987c478bd9Sstevel@tonic-gate } else 28997c478bd9Sstevel@tonic-gate last = this; 29007c478bd9Sstevel@tonic-gate } 29017c478bd9Sstevel@tonic-gate return (Z_NO_PROPERTY_ID); 29027c478bd9Sstevel@tonic-gate } 29037c478bd9Sstevel@tonic-gate 29047c478bd9Sstevel@tonic-gate char * 29057c478bd9Sstevel@tonic-gate zonecfg_strerror(int errnum) 29067c478bd9Sstevel@tonic-gate { 29077c478bd9Sstevel@tonic-gate switch (errnum) { 29087c478bd9Sstevel@tonic-gate case Z_OK: 29097c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "OK")); 29107c478bd9Sstevel@tonic-gate case Z_EMPTY_DOCUMENT: 29117c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Empty document")); 29127c478bd9Sstevel@tonic-gate case Z_WRONG_DOC_TYPE: 29137c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Wrong document type")); 29147c478bd9Sstevel@tonic-gate case Z_BAD_PROPERTY: 29157c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Bad document property")); 29167c478bd9Sstevel@tonic-gate case Z_TEMP_FILE: 29177c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, 29187c478bd9Sstevel@tonic-gate "Problem creating temporary file")); 29197c478bd9Sstevel@tonic-gate case Z_SAVING_FILE: 29207c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Problem saving file")); 29217c478bd9Sstevel@tonic-gate case Z_NO_ENTRY: 29227c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "No such entry")); 29237c478bd9Sstevel@tonic-gate case Z_BOGUS_ZONE_NAME: 29247c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Bogus zone name")); 29257c478bd9Sstevel@tonic-gate case Z_REQD_RESOURCE_MISSING: 29267c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Required resource missing")); 29277c478bd9Sstevel@tonic-gate case Z_REQD_PROPERTY_MISSING: 29287c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Required property missing")); 29297c478bd9Sstevel@tonic-gate case Z_BAD_HANDLE: 29307c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Bad handle")); 29317c478bd9Sstevel@tonic-gate case Z_NOMEM: 29327c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Out of memory")); 29337c478bd9Sstevel@tonic-gate case Z_INVAL: 29347c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Invalid argument")); 29357c478bd9Sstevel@tonic-gate case Z_ACCES: 29367c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Permission denied")); 29377c478bd9Sstevel@tonic-gate case Z_TOO_BIG: 29387c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Argument list too long")); 29397c478bd9Sstevel@tonic-gate case Z_MISC_FS: 29407c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, 29417c478bd9Sstevel@tonic-gate "Miscellaneous file system error")); 29427c478bd9Sstevel@tonic-gate case Z_NO_ZONE: 29437c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "No such zone configured")); 29447c478bd9Sstevel@tonic-gate case Z_NO_RESOURCE_TYPE: 29457c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "No such resource type")); 29467c478bd9Sstevel@tonic-gate case Z_NO_RESOURCE_ID: 29477c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "No such resource with that id")); 29487c478bd9Sstevel@tonic-gate case Z_NO_PROPERTY_TYPE: 29497c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "No such property type")); 29507c478bd9Sstevel@tonic-gate case Z_NO_PROPERTY_ID: 29517c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "No such property with that id")); 2952087719fdSdp case Z_BAD_ZONE_STATE: 29537c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, 2954087719fdSdp "Zone state is invalid for the requested operation")); 29557c478bd9Sstevel@tonic-gate case Z_INVALID_DOCUMENT: 29567c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Invalid document")); 2957087719fdSdp case Z_NAME_IN_USE: 2958087719fdSdp return (dgettext(TEXT_DOMAIN, "Zone name already in use")); 29597c478bd9Sstevel@tonic-gate case Z_NO_SUCH_ID: 29607c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "No such zone ID")); 29617c478bd9Sstevel@tonic-gate case Z_UPDATING_INDEX: 29627c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Problem updating index file")); 29637c478bd9Sstevel@tonic-gate case Z_LOCKING_FILE: 29647c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Locking index file")); 29657c478bd9Sstevel@tonic-gate case Z_UNLOCKING_FILE: 29667c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Unlocking index file")); 29677c478bd9Sstevel@tonic-gate case Z_INSUFFICIENT_SPEC: 29687c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Insufficient specification")); 29697c478bd9Sstevel@tonic-gate case Z_RESOLVED_PATH: 29707c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Resolved path mismatch")); 29717c478bd9Sstevel@tonic-gate case Z_IPV6_ADDR_PREFIX_LEN: 29727c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, 29737c478bd9Sstevel@tonic-gate "IPv6 address missing required prefix length")); 29747c478bd9Sstevel@tonic-gate case Z_BOGUS_ADDRESS: 29757c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, 29767c478bd9Sstevel@tonic-gate "Neither an IPv4 nor an IPv6 address nor a host name")); 29777c478bd9Sstevel@tonic-gate default: 29787c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Unknown error")); 29797c478bd9Sstevel@tonic-gate } 29807c478bd9Sstevel@tonic-gate } 29817c478bd9Sstevel@tonic-gate 29827c478bd9Sstevel@tonic-gate /* 29837c478bd9Sstevel@tonic-gate * Note that the zonecfg_setXent() and zonecfg_endXent() calls are all the 29847c478bd9Sstevel@tonic-gate * same, as they just turn around and call zonecfg_setent() / zonecfg_endent(). 29857c478bd9Sstevel@tonic-gate */ 29867c478bd9Sstevel@tonic-gate 29877c478bd9Sstevel@tonic-gate static int 29887c478bd9Sstevel@tonic-gate zonecfg_setent(zone_dochandle_t handle) 29897c478bd9Sstevel@tonic-gate { 29907c478bd9Sstevel@tonic-gate xmlNodePtr cur; 29917c478bd9Sstevel@tonic-gate int err; 29927c478bd9Sstevel@tonic-gate 29937c478bd9Sstevel@tonic-gate if (handle == NULL) 29947c478bd9Sstevel@tonic-gate return (Z_INVAL); 29957c478bd9Sstevel@tonic-gate 29967c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) { 29977c478bd9Sstevel@tonic-gate handle->zone_dh_cur = NULL; 29987c478bd9Sstevel@tonic-gate return (err); 29997c478bd9Sstevel@tonic-gate } 30007c478bd9Sstevel@tonic-gate cur = handle->zone_dh_cur; 30017c478bd9Sstevel@tonic-gate cur = cur->xmlChildrenNode; 30027c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur; 30037c478bd9Sstevel@tonic-gate return (Z_OK); 30047c478bd9Sstevel@tonic-gate } 30057c478bd9Sstevel@tonic-gate 30067c478bd9Sstevel@tonic-gate static int 30077c478bd9Sstevel@tonic-gate zonecfg_endent(zone_dochandle_t handle) 30087c478bd9Sstevel@tonic-gate { 30097c478bd9Sstevel@tonic-gate if (handle == NULL) 30107c478bd9Sstevel@tonic-gate return (Z_INVAL); 30117c478bd9Sstevel@tonic-gate 30127c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 30137c478bd9Sstevel@tonic-gate return (Z_OK); 30147c478bd9Sstevel@tonic-gate } 30157c478bd9Sstevel@tonic-gate 30167c478bd9Sstevel@tonic-gate int 30177c478bd9Sstevel@tonic-gate zonecfg_setfsent(zone_dochandle_t handle) 30187c478bd9Sstevel@tonic-gate { 30197c478bd9Sstevel@tonic-gate return (zonecfg_setent(handle)); 30207c478bd9Sstevel@tonic-gate } 30217c478bd9Sstevel@tonic-gate 30227c478bd9Sstevel@tonic-gate int 30237c478bd9Sstevel@tonic-gate zonecfg_getfsent(zone_dochandle_t handle, struct zone_fstab *tabptr) 30247c478bd9Sstevel@tonic-gate { 30257c478bd9Sstevel@tonic-gate xmlNodePtr cur, options; 30267c478bd9Sstevel@tonic-gate char options_str[MAX_MNTOPT_STR]; 30277c478bd9Sstevel@tonic-gate int err; 30287c478bd9Sstevel@tonic-gate 30297c478bd9Sstevel@tonic-gate if (handle == NULL) 30307c478bd9Sstevel@tonic-gate return (Z_INVAL); 30317c478bd9Sstevel@tonic-gate 30327c478bd9Sstevel@tonic-gate if ((cur = handle->zone_dh_cur) == NULL) 30337c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 30347c478bd9Sstevel@tonic-gate 30357c478bd9Sstevel@tonic-gate for (; cur != NULL; cur = cur->next) 30367c478bd9Sstevel@tonic-gate if (!xmlStrcmp(cur->name, DTD_ELEM_FS)) 30377c478bd9Sstevel@tonic-gate break; 30387c478bd9Sstevel@tonic-gate if (cur == NULL) { 30397c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 30407c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 30417c478bd9Sstevel@tonic-gate } 30427c478bd9Sstevel@tonic-gate 30437c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_SPECIAL, tabptr->zone_fs_special, 30447c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_special))) != Z_OK) { 30457c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 30467c478bd9Sstevel@tonic-gate return (err); 30477c478bd9Sstevel@tonic-gate } 30487c478bd9Sstevel@tonic-gate 30497c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_RAW, tabptr->zone_fs_raw, 30507c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_raw))) != Z_OK) { 30517c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 30527c478bd9Sstevel@tonic-gate return (err); 30537c478bd9Sstevel@tonic-gate } 30547c478bd9Sstevel@tonic-gate 30557c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir, 30567c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_dir))) != Z_OK) { 30577c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 30587c478bd9Sstevel@tonic-gate return (err); 30597c478bd9Sstevel@tonic-gate } 30607c478bd9Sstevel@tonic-gate 30617c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_TYPE, tabptr->zone_fs_type, 30627c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_type))) != Z_OK) { 30637c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 30647c478bd9Sstevel@tonic-gate return (err); 30657c478bd9Sstevel@tonic-gate } 30667c478bd9Sstevel@tonic-gate 30677c478bd9Sstevel@tonic-gate /* OK for options to be NULL */ 30687c478bd9Sstevel@tonic-gate tabptr->zone_fs_options = NULL; 30697c478bd9Sstevel@tonic-gate for (options = cur->xmlChildrenNode; options != NULL; 30707c478bd9Sstevel@tonic-gate options = options->next) { 30717c478bd9Sstevel@tonic-gate if (fetchprop(options, DTD_ATTR_NAME, options_str, 30727c478bd9Sstevel@tonic-gate sizeof (options_str)) != Z_OK) 30737c478bd9Sstevel@tonic-gate break; 30747c478bd9Sstevel@tonic-gate if (zonecfg_add_fs_option(tabptr, options_str) != Z_OK) 30757c478bd9Sstevel@tonic-gate break; 30767c478bd9Sstevel@tonic-gate } 30777c478bd9Sstevel@tonic-gate 30787c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur->next; 30797c478bd9Sstevel@tonic-gate return (Z_OK); 30807c478bd9Sstevel@tonic-gate } 30817c478bd9Sstevel@tonic-gate 30827c478bd9Sstevel@tonic-gate int 30837c478bd9Sstevel@tonic-gate zonecfg_endfsent(zone_dochandle_t handle) 30847c478bd9Sstevel@tonic-gate { 30857c478bd9Sstevel@tonic-gate return (zonecfg_endent(handle)); 30867c478bd9Sstevel@tonic-gate } 30877c478bd9Sstevel@tonic-gate 30887c478bd9Sstevel@tonic-gate int 30897c478bd9Sstevel@tonic-gate zonecfg_setipdent(zone_dochandle_t handle) 30907c478bd9Sstevel@tonic-gate { 30917c478bd9Sstevel@tonic-gate return (zonecfg_setent(handle)); 30927c478bd9Sstevel@tonic-gate } 30937c478bd9Sstevel@tonic-gate 30947c478bd9Sstevel@tonic-gate int 30957c478bd9Sstevel@tonic-gate zonecfg_getipdent(zone_dochandle_t handle, struct zone_fstab *tabptr) 30967c478bd9Sstevel@tonic-gate { 30977c478bd9Sstevel@tonic-gate xmlNodePtr cur; 30987c478bd9Sstevel@tonic-gate int err; 30997c478bd9Sstevel@tonic-gate 31007c478bd9Sstevel@tonic-gate if (handle == NULL) 31017c478bd9Sstevel@tonic-gate return (Z_INVAL); 31027c478bd9Sstevel@tonic-gate 31037c478bd9Sstevel@tonic-gate if ((cur = handle->zone_dh_cur) == NULL) 31047c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 31057c478bd9Sstevel@tonic-gate 31067c478bd9Sstevel@tonic-gate for (; cur != NULL; cur = cur->next) 31077c478bd9Sstevel@tonic-gate if (!xmlStrcmp(cur->name, DTD_ELEM_IPD)) 31087c478bd9Sstevel@tonic-gate break; 31097c478bd9Sstevel@tonic-gate if (cur == NULL) { 31107c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 31117c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 31127c478bd9Sstevel@tonic-gate } 31137c478bd9Sstevel@tonic-gate 31147c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir, 31157c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_dir))) != Z_OK) { 31167c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 31177c478bd9Sstevel@tonic-gate return (err); 31187c478bd9Sstevel@tonic-gate } 31197c478bd9Sstevel@tonic-gate 31207c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur->next; 31217c478bd9Sstevel@tonic-gate return (Z_OK); 31227c478bd9Sstevel@tonic-gate } 31237c478bd9Sstevel@tonic-gate 31247c478bd9Sstevel@tonic-gate int 31257c478bd9Sstevel@tonic-gate zonecfg_endipdent(zone_dochandle_t handle) 31267c478bd9Sstevel@tonic-gate { 31277c478bd9Sstevel@tonic-gate return (zonecfg_endent(handle)); 31287c478bd9Sstevel@tonic-gate } 31297c478bd9Sstevel@tonic-gate 31307c478bd9Sstevel@tonic-gate int 31317c478bd9Sstevel@tonic-gate zonecfg_setnwifent(zone_dochandle_t handle) 31327c478bd9Sstevel@tonic-gate { 31337c478bd9Sstevel@tonic-gate return (zonecfg_setent(handle)); 31347c478bd9Sstevel@tonic-gate } 31357c478bd9Sstevel@tonic-gate 31367c478bd9Sstevel@tonic-gate int 31377c478bd9Sstevel@tonic-gate zonecfg_getnwifent(zone_dochandle_t handle, struct zone_nwiftab *tabptr) 31387c478bd9Sstevel@tonic-gate { 31397c478bd9Sstevel@tonic-gate xmlNodePtr cur; 31407c478bd9Sstevel@tonic-gate int err; 31417c478bd9Sstevel@tonic-gate 31427c478bd9Sstevel@tonic-gate if (handle == NULL) 31437c478bd9Sstevel@tonic-gate return (Z_INVAL); 31447c478bd9Sstevel@tonic-gate 31457c478bd9Sstevel@tonic-gate if ((cur = handle->zone_dh_cur) == NULL) 31467c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 31477c478bd9Sstevel@tonic-gate 31487c478bd9Sstevel@tonic-gate for (; cur != NULL; cur = cur->next) 31497c478bd9Sstevel@tonic-gate if (!xmlStrcmp(cur->name, DTD_ELEM_NET)) 31507c478bd9Sstevel@tonic-gate break; 31517c478bd9Sstevel@tonic-gate if (cur == NULL) { 31527c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 31537c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 31547c478bd9Sstevel@tonic-gate } 31557c478bd9Sstevel@tonic-gate 31567c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_ADDRESS, tabptr->zone_nwif_address, 31577c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_nwif_address))) != Z_OK) { 31587c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 31597c478bd9Sstevel@tonic-gate return (err); 31607c478bd9Sstevel@tonic-gate } 31617c478bd9Sstevel@tonic-gate 31627c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_PHYSICAL, tabptr->zone_nwif_physical, 31637c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_nwif_physical))) != Z_OK) { 31647c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 31657c478bd9Sstevel@tonic-gate return (err); 31667c478bd9Sstevel@tonic-gate } 31677c478bd9Sstevel@tonic-gate 31687c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur->next; 31697c478bd9Sstevel@tonic-gate return (Z_OK); 31707c478bd9Sstevel@tonic-gate } 31717c478bd9Sstevel@tonic-gate 31727c478bd9Sstevel@tonic-gate int 31737c478bd9Sstevel@tonic-gate zonecfg_endnwifent(zone_dochandle_t handle) 31747c478bd9Sstevel@tonic-gate { 31757c478bd9Sstevel@tonic-gate return (zonecfg_endent(handle)); 31767c478bd9Sstevel@tonic-gate } 31777c478bd9Sstevel@tonic-gate 31787c478bd9Sstevel@tonic-gate int 31797c478bd9Sstevel@tonic-gate zonecfg_setdevent(zone_dochandle_t handle) 31807c478bd9Sstevel@tonic-gate { 31817c478bd9Sstevel@tonic-gate return (zonecfg_setent(handle)); 31827c478bd9Sstevel@tonic-gate } 31837c478bd9Sstevel@tonic-gate 31847c478bd9Sstevel@tonic-gate int 31857c478bd9Sstevel@tonic-gate zonecfg_getdevent(zone_dochandle_t handle, struct zone_devtab *tabptr) 31867c478bd9Sstevel@tonic-gate { 31877c478bd9Sstevel@tonic-gate xmlNodePtr cur; 31887c478bd9Sstevel@tonic-gate int err; 31897c478bd9Sstevel@tonic-gate 31907c478bd9Sstevel@tonic-gate if (handle == NULL) 31917c478bd9Sstevel@tonic-gate return (Z_INVAL); 31927c478bd9Sstevel@tonic-gate 31937c478bd9Sstevel@tonic-gate if ((cur = handle->zone_dh_cur) == NULL) 31947c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 31957c478bd9Sstevel@tonic-gate 31967c478bd9Sstevel@tonic-gate for (; cur != NULL; cur = cur->next) 31977c478bd9Sstevel@tonic-gate if (!xmlStrcmp(cur->name, DTD_ELEM_DEVICE)) 31987c478bd9Sstevel@tonic-gate break; 31997c478bd9Sstevel@tonic-gate if (cur == NULL) { 32007c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 32017c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 32027c478bd9Sstevel@tonic-gate } 32037c478bd9Sstevel@tonic-gate 32047c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_MATCH, tabptr->zone_dev_match, 32057c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_dev_match))) != Z_OK) { 32067c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 32077c478bd9Sstevel@tonic-gate return (err); 32087c478bd9Sstevel@tonic-gate } 32097c478bd9Sstevel@tonic-gate 32107c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur->next; 32117c478bd9Sstevel@tonic-gate return (Z_OK); 32127c478bd9Sstevel@tonic-gate } 32137c478bd9Sstevel@tonic-gate 32147c478bd9Sstevel@tonic-gate int 32157c478bd9Sstevel@tonic-gate zonecfg_enddevent(zone_dochandle_t handle) 32167c478bd9Sstevel@tonic-gate { 32177c478bd9Sstevel@tonic-gate return (zonecfg_endent(handle)); 32187c478bd9Sstevel@tonic-gate } 32197c478bd9Sstevel@tonic-gate 32207c478bd9Sstevel@tonic-gate int 32217c478bd9Sstevel@tonic-gate zonecfg_setrctlent(zone_dochandle_t handle) 32227c478bd9Sstevel@tonic-gate { 32237c478bd9Sstevel@tonic-gate return (zonecfg_setent(handle)); 32247c478bd9Sstevel@tonic-gate } 32257c478bd9Sstevel@tonic-gate 32267c478bd9Sstevel@tonic-gate int 32277c478bd9Sstevel@tonic-gate zonecfg_getrctlent(zone_dochandle_t handle, struct zone_rctltab *tabptr) 32287c478bd9Sstevel@tonic-gate { 32297c478bd9Sstevel@tonic-gate xmlNodePtr cur, val; 32307c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *valptr; 32317c478bd9Sstevel@tonic-gate int err; 32327c478bd9Sstevel@tonic-gate 32337c478bd9Sstevel@tonic-gate if (handle == NULL) 32347c478bd9Sstevel@tonic-gate return (Z_INVAL); 32357c478bd9Sstevel@tonic-gate 32367c478bd9Sstevel@tonic-gate if ((cur = handle->zone_dh_cur) == NULL) 32377c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 32387c478bd9Sstevel@tonic-gate 32397c478bd9Sstevel@tonic-gate for (; cur != NULL; cur = cur->next) 32407c478bd9Sstevel@tonic-gate if (!xmlStrcmp(cur->name, DTD_ELEM_RCTL)) 32417c478bd9Sstevel@tonic-gate break; 32427c478bd9Sstevel@tonic-gate if (cur == NULL) { 32437c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 32447c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 32457c478bd9Sstevel@tonic-gate } 32467c478bd9Sstevel@tonic-gate 32477c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_NAME, tabptr->zone_rctl_name, 32487c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_rctl_name))) != Z_OK) { 32497c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 32507c478bd9Sstevel@tonic-gate return (err); 32517c478bd9Sstevel@tonic-gate } 32527c478bd9Sstevel@tonic-gate 32537c478bd9Sstevel@tonic-gate tabptr->zone_rctl_valptr = NULL; 32547c478bd9Sstevel@tonic-gate for (val = cur->xmlChildrenNode; val != NULL; val = val->next) { 32557c478bd9Sstevel@tonic-gate valptr = (struct zone_rctlvaltab *)malloc( 32567c478bd9Sstevel@tonic-gate sizeof (struct zone_rctlvaltab)); 32577c478bd9Sstevel@tonic-gate if (valptr == NULL) 32587c478bd9Sstevel@tonic-gate return (Z_NOMEM); 32597c478bd9Sstevel@tonic-gate if (fetchprop(val, DTD_ATTR_PRIV, valptr->zone_rctlval_priv, 32607c478bd9Sstevel@tonic-gate sizeof (valptr->zone_rctlval_priv)) != Z_OK) 32617c478bd9Sstevel@tonic-gate break; 32627c478bd9Sstevel@tonic-gate if (fetchprop(val, DTD_ATTR_LIMIT, valptr->zone_rctlval_limit, 32637c478bd9Sstevel@tonic-gate sizeof (valptr->zone_rctlval_limit)) != Z_OK) 32647c478bd9Sstevel@tonic-gate break; 32657c478bd9Sstevel@tonic-gate if (fetchprop(val, DTD_ATTR_ACTION, valptr->zone_rctlval_action, 32667c478bd9Sstevel@tonic-gate sizeof (valptr->zone_rctlval_action)) != Z_OK) 32677c478bd9Sstevel@tonic-gate break; 32687c478bd9Sstevel@tonic-gate if (zonecfg_add_rctl_value(tabptr, valptr) != Z_OK) 32697c478bd9Sstevel@tonic-gate break; 32707c478bd9Sstevel@tonic-gate } 32717c478bd9Sstevel@tonic-gate 32727c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur->next; 32737c478bd9Sstevel@tonic-gate return (Z_OK); 32747c478bd9Sstevel@tonic-gate } 32757c478bd9Sstevel@tonic-gate 32767c478bd9Sstevel@tonic-gate int 32777c478bd9Sstevel@tonic-gate zonecfg_endrctlent(zone_dochandle_t handle) 32787c478bd9Sstevel@tonic-gate { 32797c478bd9Sstevel@tonic-gate return (zonecfg_endent(handle)); 32807c478bd9Sstevel@tonic-gate } 32817c478bd9Sstevel@tonic-gate 32827c478bd9Sstevel@tonic-gate int 32837c478bd9Sstevel@tonic-gate zonecfg_setattrent(zone_dochandle_t handle) 32847c478bd9Sstevel@tonic-gate { 32857c478bd9Sstevel@tonic-gate return (zonecfg_setent(handle)); 32867c478bd9Sstevel@tonic-gate } 32877c478bd9Sstevel@tonic-gate 32887c478bd9Sstevel@tonic-gate int 32897c478bd9Sstevel@tonic-gate zonecfg_getattrent(zone_dochandle_t handle, struct zone_attrtab *tabptr) 32907c478bd9Sstevel@tonic-gate { 32917c478bd9Sstevel@tonic-gate xmlNodePtr cur; 32927c478bd9Sstevel@tonic-gate int err; 32937c478bd9Sstevel@tonic-gate 32947c478bd9Sstevel@tonic-gate if (handle == NULL) 32957c478bd9Sstevel@tonic-gate return (Z_INVAL); 32967c478bd9Sstevel@tonic-gate 32977c478bd9Sstevel@tonic-gate if ((cur = handle->zone_dh_cur) == NULL) 32987c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 32997c478bd9Sstevel@tonic-gate 33007c478bd9Sstevel@tonic-gate for (; cur != NULL; cur = cur->next) 33017c478bd9Sstevel@tonic-gate if (!xmlStrcmp(cur->name, DTD_ELEM_ATTR)) 33027c478bd9Sstevel@tonic-gate break; 33037c478bd9Sstevel@tonic-gate if (cur == NULL) { 33047c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 33057c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 33067c478bd9Sstevel@tonic-gate } 33077c478bd9Sstevel@tonic-gate 33087c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_NAME, tabptr->zone_attr_name, 33097c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_attr_name))) != Z_OK) { 33107c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 33117c478bd9Sstevel@tonic-gate return (err); 33127c478bd9Sstevel@tonic-gate } 33137c478bd9Sstevel@tonic-gate 33147c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_TYPE, tabptr->zone_attr_type, 33157c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_attr_type))) != Z_OK) { 33167c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 33177c478bd9Sstevel@tonic-gate return (err); 33187c478bd9Sstevel@tonic-gate } 33197c478bd9Sstevel@tonic-gate 33207c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_VALUE, tabptr->zone_attr_value, 33217c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_attr_value))) != Z_OK) { 33227c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 33237c478bd9Sstevel@tonic-gate return (err); 33247c478bd9Sstevel@tonic-gate } 33257c478bd9Sstevel@tonic-gate 33267c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur->next; 33277c478bd9Sstevel@tonic-gate return (Z_OK); 33287c478bd9Sstevel@tonic-gate } 33297c478bd9Sstevel@tonic-gate 33307c478bd9Sstevel@tonic-gate int 33317c478bd9Sstevel@tonic-gate zonecfg_endattrent(zone_dochandle_t handle) 33327c478bd9Sstevel@tonic-gate { 33337c478bd9Sstevel@tonic-gate return (zonecfg_endent(handle)); 33347c478bd9Sstevel@tonic-gate } 33357c478bd9Sstevel@tonic-gate 33367c478bd9Sstevel@tonic-gate /* This will ultimately be configurable. */ 33377c478bd9Sstevel@tonic-gate static const char *priv_list[] = { 33387c478bd9Sstevel@tonic-gate PRIV_FILE_CHOWN, 33397c478bd9Sstevel@tonic-gate PRIV_FILE_CHOWN_SELF, 33407c478bd9Sstevel@tonic-gate PRIV_FILE_DAC_EXECUTE, 33417c478bd9Sstevel@tonic-gate PRIV_FILE_DAC_READ, 33427c478bd9Sstevel@tonic-gate PRIV_FILE_DAC_SEARCH, 33437c478bd9Sstevel@tonic-gate PRIV_FILE_DAC_WRITE, 33447c478bd9Sstevel@tonic-gate PRIV_FILE_OWNER, 33457c478bd9Sstevel@tonic-gate PRIV_FILE_SETID, 33467c478bd9Sstevel@tonic-gate PRIV_IPC_DAC_READ, 33477c478bd9Sstevel@tonic-gate PRIV_IPC_DAC_WRITE, 33487c478bd9Sstevel@tonic-gate PRIV_IPC_OWNER, 33497c478bd9Sstevel@tonic-gate PRIV_NET_ICMPACCESS, 33507c478bd9Sstevel@tonic-gate PRIV_NET_PRIVADDR, 33517c478bd9Sstevel@tonic-gate PRIV_PROC_CHROOT, 33527c478bd9Sstevel@tonic-gate PRIV_SYS_AUDIT, 33537c478bd9Sstevel@tonic-gate PRIV_PROC_AUDIT, 33547c478bd9Sstevel@tonic-gate PRIV_PROC_OWNER, 33557c478bd9Sstevel@tonic-gate PRIV_PROC_SETID, 33567c478bd9Sstevel@tonic-gate PRIV_PROC_TASKID, 33577c478bd9Sstevel@tonic-gate PRIV_SYS_ACCT, 33587c478bd9Sstevel@tonic-gate PRIV_SYS_ADMIN, 33597c478bd9Sstevel@tonic-gate PRIV_SYS_MOUNT, 33607c478bd9Sstevel@tonic-gate PRIV_SYS_NFS, 33617c478bd9Sstevel@tonic-gate PRIV_SYS_RESOURCE, 33627c478bd9Sstevel@tonic-gate PRIV_CONTRACT_EVENT, 33637c478bd9Sstevel@tonic-gate PRIV_CONTRACT_OBSERVER, 33647c478bd9Sstevel@tonic-gate NULL 33657c478bd9Sstevel@tonic-gate }; 33667c478bd9Sstevel@tonic-gate 33677c478bd9Sstevel@tonic-gate int 33687c478bd9Sstevel@tonic-gate zonecfg_get_privset(priv_set_t *privs) 33697c478bd9Sstevel@tonic-gate { 33707c478bd9Sstevel@tonic-gate const char **strp; 33717c478bd9Sstevel@tonic-gate priv_set_t *basic = priv_str_to_set("basic", ",", NULL); 33727c478bd9Sstevel@tonic-gate 33737c478bd9Sstevel@tonic-gate if (basic == NULL) 33747c478bd9Sstevel@tonic-gate return (Z_INVAL); 33757c478bd9Sstevel@tonic-gate 33767c478bd9Sstevel@tonic-gate priv_union(basic, privs); 33777c478bd9Sstevel@tonic-gate priv_freeset(basic); 33787c478bd9Sstevel@tonic-gate 33797c478bd9Sstevel@tonic-gate for (strp = priv_list; *strp != NULL; strp++) { 33807c478bd9Sstevel@tonic-gate if (priv_addset(privs, *strp) != 0) { 33817c478bd9Sstevel@tonic-gate return (Z_INVAL); 33827c478bd9Sstevel@tonic-gate } 33837c478bd9Sstevel@tonic-gate } 33847c478bd9Sstevel@tonic-gate return (Z_OK); 33857c478bd9Sstevel@tonic-gate } 33867c478bd9Sstevel@tonic-gate 33877c478bd9Sstevel@tonic-gate int 33887c478bd9Sstevel@tonic-gate zone_get_zonepath(char *zone_name, char *zonepath, size_t rp_sz) 33897c478bd9Sstevel@tonic-gate { 33907c478bd9Sstevel@tonic-gate zone_dochandle_t handle; 33917c478bd9Sstevel@tonic-gate boolean_t found = B_FALSE; 33927c478bd9Sstevel@tonic-gate struct zoneent *ze; 33937c478bd9Sstevel@tonic-gate FILE *cookie; 33947c478bd9Sstevel@tonic-gate int err; 3395108322fbScarlsonj char *cp; 33967c478bd9Sstevel@tonic-gate 33977c478bd9Sstevel@tonic-gate if (zone_name == NULL) 33987c478bd9Sstevel@tonic-gate return (Z_INVAL); 33997c478bd9Sstevel@tonic-gate 3400108322fbScarlsonj (void) strlcpy(zonepath, zonecfg_root, rp_sz); 3401108322fbScarlsonj cp = zonepath + strlen(zonepath); 3402108322fbScarlsonj while (cp > zonepath && cp[-1] == '/') 3403108322fbScarlsonj *--cp = '\0'; 3404108322fbScarlsonj 34057c478bd9Sstevel@tonic-gate if (strcmp(zone_name, GLOBAL_ZONENAME) == 0) { 3406108322fbScarlsonj if (zonepath[0] == '\0') 3407108322fbScarlsonj (void) strlcpy(zonepath, "/", rp_sz); 34087c478bd9Sstevel@tonic-gate return (Z_OK); 34097c478bd9Sstevel@tonic-gate } 34107c478bd9Sstevel@tonic-gate 34117c478bd9Sstevel@tonic-gate /* 34127c478bd9Sstevel@tonic-gate * First check the index file. Because older versions did not have 34137c478bd9Sstevel@tonic-gate * a copy of the zone path, allow for it to be zero length, in which 34147c478bd9Sstevel@tonic-gate * case we ignore this result and fall back to the XML files. 34157c478bd9Sstevel@tonic-gate */ 34167c478bd9Sstevel@tonic-gate cookie = setzoneent(); 34177c478bd9Sstevel@tonic-gate while ((ze = getzoneent_private(cookie)) != NULL) { 34187c478bd9Sstevel@tonic-gate if (strcmp(ze->zone_name, zone_name) == 0) { 34197c478bd9Sstevel@tonic-gate found = B_TRUE; 3420108322fbScarlsonj if (ze->zone_path[0] != '\0') 3421108322fbScarlsonj (void) strlcpy(cp, ze->zone_path, 3422108322fbScarlsonj rp_sz - (cp - zonepath)); 34237c478bd9Sstevel@tonic-gate } 34247c478bd9Sstevel@tonic-gate free(ze); 34257c478bd9Sstevel@tonic-gate if (found) 34267c478bd9Sstevel@tonic-gate break; 34277c478bd9Sstevel@tonic-gate } 34287c478bd9Sstevel@tonic-gate endzoneent(cookie); 3429108322fbScarlsonj if (found && *cp != '\0') 34307c478bd9Sstevel@tonic-gate return (Z_OK); 34317c478bd9Sstevel@tonic-gate 34327c478bd9Sstevel@tonic-gate /* Fall back to the XML files. */ 34337c478bd9Sstevel@tonic-gate if ((handle = zonecfg_init_handle()) == NULL) 34347c478bd9Sstevel@tonic-gate return (Z_NOMEM); 34357c478bd9Sstevel@tonic-gate 34367c478bd9Sstevel@tonic-gate /* 34377c478bd9Sstevel@tonic-gate * Check the snapshot first: if a zone is running, its zonepath 34387c478bd9Sstevel@tonic-gate * may have changed. 34397c478bd9Sstevel@tonic-gate */ 34407c478bd9Sstevel@tonic-gate if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) { 34417c478bd9Sstevel@tonic-gate if ((err = zonecfg_get_handle(zone_name, handle)) != Z_OK) 34427c478bd9Sstevel@tonic-gate return (err); 34437c478bd9Sstevel@tonic-gate } 34447c478bd9Sstevel@tonic-gate err = zonecfg_get_zonepath(handle, zonepath, rp_sz); 34457c478bd9Sstevel@tonic-gate zonecfg_fini_handle(handle); 34467c478bd9Sstevel@tonic-gate return (err); 34477c478bd9Sstevel@tonic-gate } 34487c478bd9Sstevel@tonic-gate 34497c478bd9Sstevel@tonic-gate int 34507c478bd9Sstevel@tonic-gate zone_get_rootpath(char *zone_name, char *rootpath, size_t rp_sz) 34517c478bd9Sstevel@tonic-gate { 34527c478bd9Sstevel@tonic-gate int err; 34537c478bd9Sstevel@tonic-gate 34547c478bd9Sstevel@tonic-gate /* This function makes sense for non-global zones only. */ 34557c478bd9Sstevel@tonic-gate if (strcmp(zone_name, GLOBAL_ZONENAME) == 0) 34567c478bd9Sstevel@tonic-gate return (Z_BOGUS_ZONE_NAME); 34577c478bd9Sstevel@tonic-gate if ((err = zone_get_zonepath(zone_name, rootpath, rp_sz)) != Z_OK) 34587c478bd9Sstevel@tonic-gate return (err); 34597c478bd9Sstevel@tonic-gate if (strlcat(rootpath, "/root", rp_sz) >= rp_sz) 34607c478bd9Sstevel@tonic-gate return (Z_TOO_BIG); 34617c478bd9Sstevel@tonic-gate return (Z_OK); 34627c478bd9Sstevel@tonic-gate } 34637c478bd9Sstevel@tonic-gate 34647c478bd9Sstevel@tonic-gate static zone_state_t 3465108322fbScarlsonj kernel_state_to_user_state(zoneid_t zoneid, zone_status_t kernel_state) 34667c478bd9Sstevel@tonic-gate { 3467108322fbScarlsonj char zoneroot[MAXPATHLEN]; 3468108322fbScarlsonj size_t zlen; 3469108322fbScarlsonj 34707c478bd9Sstevel@tonic-gate assert(kernel_state <= ZONE_MAX_STATE); 34717c478bd9Sstevel@tonic-gate switch (kernel_state) { 34727c478bd9Sstevel@tonic-gate case ZONE_IS_UNINITIALIZED: 3473108322fbScarlsonj return (ZONE_STATE_READY); 34747c478bd9Sstevel@tonic-gate case ZONE_IS_READY: 3475108322fbScarlsonj /* 3476108322fbScarlsonj * If the zone's root is mounted on $ZONEPATH/lu, then 3477108322fbScarlsonj * it's a mounted scratch zone. 3478108322fbScarlsonj */ 3479108322fbScarlsonj if (zone_getattr(zoneid, ZONE_ATTR_ROOT, zoneroot, 3480108322fbScarlsonj sizeof (zoneroot)) >= 0) { 3481108322fbScarlsonj zlen = strlen(zoneroot); 3482108322fbScarlsonj if (zlen > 3 && 3483108322fbScarlsonj strcmp(zoneroot + zlen - 3, "/lu") == 0) 3484108322fbScarlsonj return (ZONE_STATE_MOUNTED); 3485108322fbScarlsonj } 34867c478bd9Sstevel@tonic-gate return (ZONE_STATE_READY); 34877c478bd9Sstevel@tonic-gate case ZONE_IS_BOOTING: 34887c478bd9Sstevel@tonic-gate case ZONE_IS_RUNNING: 34897c478bd9Sstevel@tonic-gate return (ZONE_STATE_RUNNING); 34907c478bd9Sstevel@tonic-gate case ZONE_IS_SHUTTING_DOWN: 34917c478bd9Sstevel@tonic-gate case ZONE_IS_EMPTY: 34927c478bd9Sstevel@tonic-gate return (ZONE_STATE_SHUTTING_DOWN); 34937c478bd9Sstevel@tonic-gate case ZONE_IS_DOWN: 34947c478bd9Sstevel@tonic-gate case ZONE_IS_DYING: 34957c478bd9Sstevel@tonic-gate case ZONE_IS_DEAD: 34967c478bd9Sstevel@tonic-gate default: 34977c478bd9Sstevel@tonic-gate return (ZONE_STATE_DOWN); 34987c478bd9Sstevel@tonic-gate } 34997c478bd9Sstevel@tonic-gate /* NOTREACHED */ 35007c478bd9Sstevel@tonic-gate } 35017c478bd9Sstevel@tonic-gate 35027c478bd9Sstevel@tonic-gate int 35037c478bd9Sstevel@tonic-gate zone_get_state(char *zone_name, zone_state_t *state_num) 35047c478bd9Sstevel@tonic-gate { 35057c478bd9Sstevel@tonic-gate zone_status_t status; 35067c478bd9Sstevel@tonic-gate zoneid_t zone_id; 35077c478bd9Sstevel@tonic-gate struct zoneent *ze; 35087c478bd9Sstevel@tonic-gate boolean_t found = B_FALSE; 35097c478bd9Sstevel@tonic-gate FILE *cookie; 3510108322fbScarlsonj char kernzone[ZONENAME_MAX]; 3511108322fbScarlsonj FILE *fp; 35127c478bd9Sstevel@tonic-gate 35137c478bd9Sstevel@tonic-gate if (zone_name == NULL) 35147c478bd9Sstevel@tonic-gate return (Z_INVAL); 35157c478bd9Sstevel@tonic-gate 3516108322fbScarlsonj /* 3517108322fbScarlsonj * If we're looking at an alternate root, then we need to query the 3518108322fbScarlsonj * kernel using the scratch zone name. 3519108322fbScarlsonj */ 3520108322fbScarlsonj zone_id = -1; 3521108322fbScarlsonj if (*zonecfg_root != '\0' && !zonecfg_is_scratch(zone_name)) { 3522108322fbScarlsonj if ((fp = zonecfg_open_scratch("", B_FALSE)) != NULL) { 3523108322fbScarlsonj if (zonecfg_find_scratch(fp, zone_name, zonecfg_root, 3524108322fbScarlsonj kernzone, sizeof (kernzone)) == 0) 3525108322fbScarlsonj zone_id = getzoneidbyname(kernzone); 3526108322fbScarlsonj zonecfg_close_scratch(fp); 3527108322fbScarlsonj } 3528108322fbScarlsonj } else { 3529108322fbScarlsonj zone_id = getzoneidbyname(zone_name); 3530108322fbScarlsonj } 3531108322fbScarlsonj 35327c478bd9Sstevel@tonic-gate /* check to see if zone is running */ 3533108322fbScarlsonj if (zone_id != -1 && 35347c478bd9Sstevel@tonic-gate zone_getattr(zone_id, ZONE_ATTR_STATUS, &status, 35357c478bd9Sstevel@tonic-gate sizeof (status)) >= 0) { 3536108322fbScarlsonj *state_num = kernel_state_to_user_state(zone_id, status); 35377c478bd9Sstevel@tonic-gate return (Z_OK); 35387c478bd9Sstevel@tonic-gate } 35397c478bd9Sstevel@tonic-gate 35407c478bd9Sstevel@tonic-gate cookie = setzoneent(); 35417c478bd9Sstevel@tonic-gate while ((ze = getzoneent_private(cookie)) != NULL) { 35427c478bd9Sstevel@tonic-gate if (strcmp(ze->zone_name, zone_name) == 0) { 35437c478bd9Sstevel@tonic-gate found = B_TRUE; 35447c478bd9Sstevel@tonic-gate *state_num = ze->zone_state; 35457c478bd9Sstevel@tonic-gate } 35467c478bd9Sstevel@tonic-gate free(ze); 35477c478bd9Sstevel@tonic-gate if (found) 35487c478bd9Sstevel@tonic-gate break; 35497c478bd9Sstevel@tonic-gate } 35507c478bd9Sstevel@tonic-gate endzoneent(cookie); 35517c478bd9Sstevel@tonic-gate return ((found) ? Z_OK : Z_NO_ZONE); 35527c478bd9Sstevel@tonic-gate } 35537c478bd9Sstevel@tonic-gate 35547c478bd9Sstevel@tonic-gate int 35557c478bd9Sstevel@tonic-gate zone_set_state(char *zone, zone_state_t state) 35567c478bd9Sstevel@tonic-gate { 35577c478bd9Sstevel@tonic-gate struct zoneent ze; 35587c478bd9Sstevel@tonic-gate 35597c478bd9Sstevel@tonic-gate if (state != ZONE_STATE_CONFIGURED && state != ZONE_STATE_INSTALLED && 35607c478bd9Sstevel@tonic-gate state != ZONE_STATE_INCOMPLETE) 35617c478bd9Sstevel@tonic-gate return (Z_INVAL); 35627c478bd9Sstevel@tonic-gate 3563087719fdSdp bzero(&ze, sizeof (ze)); 35647c478bd9Sstevel@tonic-gate (void) strlcpy(ze.zone_name, zone, sizeof (ze.zone_name)); 35657c478bd9Sstevel@tonic-gate ze.zone_state = state; 35667c478bd9Sstevel@tonic-gate (void) strlcpy(ze.zone_path, "", sizeof (ze.zone_path)); 35677c478bd9Sstevel@tonic-gate return (putzoneent(&ze, PZE_MODIFY)); 35687c478bd9Sstevel@tonic-gate } 35697c478bd9Sstevel@tonic-gate 35707c478bd9Sstevel@tonic-gate /* 35717c478bd9Sstevel@tonic-gate * Get id (if any) for specified zone. There are four possible outcomes: 35727c478bd9Sstevel@tonic-gate * - If the string corresponds to the numeric id of an active (booted) 35737c478bd9Sstevel@tonic-gate * zone, sets *zip to the zone id and returns 0. 35747c478bd9Sstevel@tonic-gate * - If the string corresponds to the name of an active (booted) zone, 35757c478bd9Sstevel@tonic-gate * sets *zip to the zone id and returns 0. 35767c478bd9Sstevel@tonic-gate * - If the string is a name in the configuration but is not booted, 35777c478bd9Sstevel@tonic-gate * sets *zip to ZONE_ID_UNDEFINED and returns 0. 35787c478bd9Sstevel@tonic-gate * - Otherwise, leaves *zip unchanged and returns -1. 35797c478bd9Sstevel@tonic-gate * 35807c478bd9Sstevel@tonic-gate * This function acts as an auxiliary filter on the function of the same 35817c478bd9Sstevel@tonic-gate * name in libc; the linker binds to this version if libzonecfg exists, 35827c478bd9Sstevel@tonic-gate * and the libc version if it doesn't. Any changes to this version of 35837c478bd9Sstevel@tonic-gate * the function should probably be reflected in the libc version as well. 35847c478bd9Sstevel@tonic-gate */ 35857c478bd9Sstevel@tonic-gate int 35867c478bd9Sstevel@tonic-gate zone_get_id(const char *str, zoneid_t *zip) 35877c478bd9Sstevel@tonic-gate { 35887c478bd9Sstevel@tonic-gate zone_dochandle_t hdl; 35897c478bd9Sstevel@tonic-gate zoneid_t zoneid; 35907c478bd9Sstevel@tonic-gate char *cp; 35917c478bd9Sstevel@tonic-gate int err; 35927c478bd9Sstevel@tonic-gate 35937c478bd9Sstevel@tonic-gate /* first try looking for active zone by id */ 35947c478bd9Sstevel@tonic-gate errno = 0; 35957c478bd9Sstevel@tonic-gate zoneid = (zoneid_t)strtol(str, &cp, 0); 35967c478bd9Sstevel@tonic-gate if (errno == 0 && cp != str && *cp == '\0' && 35977c478bd9Sstevel@tonic-gate getzonenamebyid(zoneid, NULL, 0) != -1) { 35987c478bd9Sstevel@tonic-gate *zip = zoneid; 35997c478bd9Sstevel@tonic-gate return (0); 36007c478bd9Sstevel@tonic-gate } 36017c478bd9Sstevel@tonic-gate 36027c478bd9Sstevel@tonic-gate /* then look for active zone by name */ 36037c478bd9Sstevel@tonic-gate if ((zoneid = getzoneidbyname(str)) != -1) { 36047c478bd9Sstevel@tonic-gate *zip = zoneid; 36057c478bd9Sstevel@tonic-gate return (0); 36067c478bd9Sstevel@tonic-gate } 36077c478bd9Sstevel@tonic-gate 36087c478bd9Sstevel@tonic-gate /* if in global zone, try looking up name in configuration database */ 36097c478bd9Sstevel@tonic-gate if (getzoneid() != GLOBAL_ZONEID || 36107c478bd9Sstevel@tonic-gate (hdl = zonecfg_init_handle()) == NULL) 36117c478bd9Sstevel@tonic-gate return (-1); 36127c478bd9Sstevel@tonic-gate 3613108322fbScarlsonj if (zonecfg_get_handle(str, hdl) == Z_OK) { 36147c478bd9Sstevel@tonic-gate /* zone exists but isn't active */ 36157c478bd9Sstevel@tonic-gate *zip = ZONE_ID_UNDEFINED; 36167c478bd9Sstevel@tonic-gate err = 0; 36177c478bd9Sstevel@tonic-gate } else { 36187c478bd9Sstevel@tonic-gate err = -1; 36197c478bd9Sstevel@tonic-gate } 36207c478bd9Sstevel@tonic-gate 36217c478bd9Sstevel@tonic-gate zonecfg_fini_handle(hdl); 36227c478bd9Sstevel@tonic-gate return (err); 36237c478bd9Sstevel@tonic-gate } 36247c478bd9Sstevel@tonic-gate 36257c478bd9Sstevel@tonic-gate char * 36267c478bd9Sstevel@tonic-gate zone_state_str(zone_state_t state_num) 36277c478bd9Sstevel@tonic-gate { 36287c478bd9Sstevel@tonic-gate switch (state_num) { 36297c478bd9Sstevel@tonic-gate case ZONE_STATE_CONFIGURED: 36307c478bd9Sstevel@tonic-gate return (ZONE_STATE_STR_CONFIGURED); 36317c478bd9Sstevel@tonic-gate case ZONE_STATE_INCOMPLETE: 36327c478bd9Sstevel@tonic-gate return (ZONE_STATE_STR_INCOMPLETE); 36337c478bd9Sstevel@tonic-gate case ZONE_STATE_INSTALLED: 36347c478bd9Sstevel@tonic-gate return (ZONE_STATE_STR_INSTALLED); 36357c478bd9Sstevel@tonic-gate case ZONE_STATE_READY: 36367c478bd9Sstevel@tonic-gate return (ZONE_STATE_STR_READY); 3637108322fbScarlsonj case ZONE_STATE_MOUNTED: 3638108322fbScarlsonj return (ZONE_STATE_STR_MOUNTED); 36397c478bd9Sstevel@tonic-gate case ZONE_STATE_RUNNING: 36407c478bd9Sstevel@tonic-gate return (ZONE_STATE_STR_RUNNING); 36417c478bd9Sstevel@tonic-gate case ZONE_STATE_SHUTTING_DOWN: 36427c478bd9Sstevel@tonic-gate return (ZONE_STATE_STR_SHUTTING_DOWN); 36437c478bd9Sstevel@tonic-gate case ZONE_STATE_DOWN: 36447c478bd9Sstevel@tonic-gate return (ZONE_STATE_STR_DOWN); 36457c478bd9Sstevel@tonic-gate default: 36467c478bd9Sstevel@tonic-gate return ("unknown"); 36477c478bd9Sstevel@tonic-gate } 36487c478bd9Sstevel@tonic-gate } 36497c478bd9Sstevel@tonic-gate 3650108322fbScarlsonj /* 3651108322fbScarlsonj * Given a UUID value, find an associated zone name. This is intended to be 3652108322fbScarlsonj * used by callers who set up some 'default' name (corresponding to the 3653108322fbScarlsonj * expected name for the zone) in the zonename buffer, and thus the function 3654108322fbScarlsonj * doesn't touch this buffer on failure. 3655108322fbScarlsonj */ 3656108322fbScarlsonj int 3657108322fbScarlsonj zonecfg_get_name_by_uuid(const uuid_t uuid, char *zonename, size_t namelen) 3658108322fbScarlsonj { 3659108322fbScarlsonj FILE *fp; 3660108322fbScarlsonj struct zoneent *ze; 3661108322fbScarlsonj 3662108322fbScarlsonj /* 3663108322fbScarlsonj * A small amount of subterfuge via casts is necessary here because 3664108322fbScarlsonj * libuuid doesn't use const correctly, but we don't want to export 3665108322fbScarlsonj * this brokenness to our clients. 3666108322fbScarlsonj */ 3667108322fbScarlsonj if (uuid_is_null(*(uuid_t *)&uuid)) 3668108322fbScarlsonj return (Z_NO_ZONE); 3669108322fbScarlsonj if ((fp = setzoneent()) == NULL) 3670108322fbScarlsonj return (Z_NO_ZONE); 3671108322fbScarlsonj while ((ze = getzoneent_private(fp)) != NULL) { 3672108322fbScarlsonj if (uuid_compare(*(uuid_t *)&uuid, ze->zone_uuid) == 0) 3673108322fbScarlsonj break; 3674108322fbScarlsonj free(ze); 3675108322fbScarlsonj } 3676108322fbScarlsonj endzoneent(fp); 3677108322fbScarlsonj if (ze != NULL) { 3678108322fbScarlsonj (void) strlcpy(zonename, ze->zone_name, namelen); 3679108322fbScarlsonj free(ze); 3680108322fbScarlsonj return (Z_OK); 3681108322fbScarlsonj } else { 3682108322fbScarlsonj return (Z_NO_ZONE); 3683108322fbScarlsonj } 3684108322fbScarlsonj } 3685108322fbScarlsonj 3686108322fbScarlsonj /* 3687108322fbScarlsonj * Given a zone name, get its UUID. Returns a "NULL" UUID value if the zone 3688108322fbScarlsonj * exists but the file doesn't have a value set yet. Returns an error if the 3689108322fbScarlsonj * zone cannot be located. 3690108322fbScarlsonj */ 3691108322fbScarlsonj int 3692108322fbScarlsonj zonecfg_get_uuid(const char *zonename, uuid_t uuid) 3693108322fbScarlsonj { 3694108322fbScarlsonj FILE *fp; 3695108322fbScarlsonj struct zoneent *ze; 3696108322fbScarlsonj 3697108322fbScarlsonj if ((fp = setzoneent()) == NULL) 3698108322fbScarlsonj return (Z_NO_ZONE); 3699108322fbScarlsonj while ((ze = getzoneent_private(fp)) != NULL) { 3700108322fbScarlsonj if (strcmp(ze->zone_name, zonename) == 0) 3701108322fbScarlsonj break; 3702108322fbScarlsonj free(ze); 3703108322fbScarlsonj } 3704108322fbScarlsonj endzoneent(fp); 3705108322fbScarlsonj if (ze != NULL) { 3706108322fbScarlsonj uuid_copy(uuid, ze->zone_uuid); 3707108322fbScarlsonj free(ze); 3708108322fbScarlsonj return (Z_OK); 3709108322fbScarlsonj } else { 3710108322fbScarlsonj return (Z_NO_ZONE); 3711108322fbScarlsonj } 3712108322fbScarlsonj } 3713108322fbScarlsonj 37147c478bd9Sstevel@tonic-gate /* 37157c478bd9Sstevel@tonic-gate * File-system convenience functions. 37167c478bd9Sstevel@tonic-gate */ 37177c478bd9Sstevel@tonic-gate boolean_t 37187c478bd9Sstevel@tonic-gate zonecfg_valid_fs_type(const char *type) 37197c478bd9Sstevel@tonic-gate { 37207c478bd9Sstevel@tonic-gate /* 37217c478bd9Sstevel@tonic-gate * We already know which FS types don't work. 37227c478bd9Sstevel@tonic-gate */ 37237c478bd9Sstevel@tonic-gate if (strcmp(type, "proc") == 0 || 37247c478bd9Sstevel@tonic-gate strcmp(type, "mntfs") == 0 || 37257c478bd9Sstevel@tonic-gate strcmp(type, "autofs") == 0 || 37267c478bd9Sstevel@tonic-gate strncmp(type, "nfs", sizeof ("nfs") - 1) == 0 || 37277c478bd9Sstevel@tonic-gate strcmp(type, "cachefs") == 0) 37287c478bd9Sstevel@tonic-gate return (B_FALSE); 37297c478bd9Sstevel@tonic-gate /* 37307c478bd9Sstevel@tonic-gate * The caller may do more detailed verification to make sure other 37317c478bd9Sstevel@tonic-gate * aspects of this filesystem type make sense. 37327c478bd9Sstevel@tonic-gate */ 37337c478bd9Sstevel@tonic-gate return (B_TRUE); 37347c478bd9Sstevel@tonic-gate } 37357c478bd9Sstevel@tonic-gate 37367c478bd9Sstevel@tonic-gate /* 37377c478bd9Sstevel@tonic-gate * Generally uninteresting rctl convenience functions. 37387c478bd9Sstevel@tonic-gate */ 37397c478bd9Sstevel@tonic-gate 37407c478bd9Sstevel@tonic-gate int 37417c478bd9Sstevel@tonic-gate zonecfg_construct_rctlblk(const struct zone_rctlvaltab *rctlval, 37427c478bd9Sstevel@tonic-gate rctlblk_t *rctlblk) 37437c478bd9Sstevel@tonic-gate { 37447c478bd9Sstevel@tonic-gate unsigned long long ull; 37457c478bd9Sstevel@tonic-gate char *endp; 37467c478bd9Sstevel@tonic-gate rctl_priv_t priv; 37477c478bd9Sstevel@tonic-gate rctl_qty_t limit; 37487c478bd9Sstevel@tonic-gate uint_t action; 37497c478bd9Sstevel@tonic-gate 37507c478bd9Sstevel@tonic-gate /* Get the privilege */ 37517c478bd9Sstevel@tonic-gate if (strcmp(rctlval->zone_rctlval_priv, "basic") == 0) { 37527c478bd9Sstevel@tonic-gate priv = RCPRIV_BASIC; 37537c478bd9Sstevel@tonic-gate } else if (strcmp(rctlval->zone_rctlval_priv, "privileged") == 0) { 37547c478bd9Sstevel@tonic-gate priv = RCPRIV_PRIVILEGED; 37557c478bd9Sstevel@tonic-gate } else { 37567c478bd9Sstevel@tonic-gate /* Invalid privilege */ 37577c478bd9Sstevel@tonic-gate return (Z_INVAL); 37587c478bd9Sstevel@tonic-gate } 37597c478bd9Sstevel@tonic-gate 37607c478bd9Sstevel@tonic-gate /* deal with negative input; strtoull(3c) doesn't do what we want */ 37617c478bd9Sstevel@tonic-gate if (rctlval->zone_rctlval_limit[0] == '-') 37627c478bd9Sstevel@tonic-gate return (Z_INVAL); 37637c478bd9Sstevel@tonic-gate /* Get the limit */ 37647c478bd9Sstevel@tonic-gate errno = 0; 37657c478bd9Sstevel@tonic-gate ull = strtoull(rctlval->zone_rctlval_limit, &endp, 0); 37667c478bd9Sstevel@tonic-gate if (errno != 0 || *endp != '\0') { 37677c478bd9Sstevel@tonic-gate /* parse failed */ 37687c478bd9Sstevel@tonic-gate return (Z_INVAL); 37697c478bd9Sstevel@tonic-gate } 37707c478bd9Sstevel@tonic-gate limit = (rctl_qty_t)ull; 37717c478bd9Sstevel@tonic-gate 37727c478bd9Sstevel@tonic-gate /* Get the action */ 37737c478bd9Sstevel@tonic-gate if (strcmp(rctlval->zone_rctlval_action, "none") == 0) { 37747c478bd9Sstevel@tonic-gate action = RCTL_LOCAL_NOACTION; 37757c478bd9Sstevel@tonic-gate } else if (strcmp(rctlval->zone_rctlval_action, "signal") == 0) { 37767c478bd9Sstevel@tonic-gate action = RCTL_LOCAL_SIGNAL; 37777c478bd9Sstevel@tonic-gate } else if (strcmp(rctlval->zone_rctlval_action, "deny") == 0) { 37787c478bd9Sstevel@tonic-gate action = RCTL_LOCAL_DENY; 37797c478bd9Sstevel@tonic-gate } else { 37807c478bd9Sstevel@tonic-gate /* Invalid Action */ 37817c478bd9Sstevel@tonic-gate return (Z_INVAL); 37827c478bd9Sstevel@tonic-gate } 37837c478bd9Sstevel@tonic-gate rctlblk_set_local_action(rctlblk, action, 0); 37847c478bd9Sstevel@tonic-gate rctlblk_set_privilege(rctlblk, priv); 37857c478bd9Sstevel@tonic-gate rctlblk_set_value(rctlblk, limit); 37867c478bd9Sstevel@tonic-gate return (Z_OK); 37877c478bd9Sstevel@tonic-gate } 37887c478bd9Sstevel@tonic-gate 37897c478bd9Sstevel@tonic-gate static int 37907c478bd9Sstevel@tonic-gate rctl_check(const char *rctlname, void *arg) 37917c478bd9Sstevel@tonic-gate { 37927c478bd9Sstevel@tonic-gate const char *attrname = arg; 37937c478bd9Sstevel@tonic-gate 37947c478bd9Sstevel@tonic-gate /* 37957c478bd9Sstevel@tonic-gate * Returning 1 here is our signal to zonecfg_is_rctl() that it is 37967c478bd9Sstevel@tonic-gate * indeed an rctl name recognized by the system. 37977c478bd9Sstevel@tonic-gate */ 37987c478bd9Sstevel@tonic-gate return (strcmp(rctlname, attrname) == 0 ? 1 : 0); 37997c478bd9Sstevel@tonic-gate } 38007c478bd9Sstevel@tonic-gate 38017c478bd9Sstevel@tonic-gate boolean_t 38027c478bd9Sstevel@tonic-gate zonecfg_is_rctl(const char *name) 38037c478bd9Sstevel@tonic-gate { 38047c478bd9Sstevel@tonic-gate return (rctl_walk(rctl_check, (void *)name) == 1); 38057c478bd9Sstevel@tonic-gate } 38067c478bd9Sstevel@tonic-gate 38077c478bd9Sstevel@tonic-gate boolean_t 38087c478bd9Sstevel@tonic-gate zonecfg_valid_rctlname(const char *name) 38097c478bd9Sstevel@tonic-gate { 38107c478bd9Sstevel@tonic-gate const char *c; 38117c478bd9Sstevel@tonic-gate 38127c478bd9Sstevel@tonic-gate if (strncmp(name, "zone.", sizeof ("zone.") - 1) != 0) 38137c478bd9Sstevel@tonic-gate return (B_FALSE); 38147c478bd9Sstevel@tonic-gate if (strlen(name) == sizeof ("zone.") - 1) 38157c478bd9Sstevel@tonic-gate return (B_FALSE); 38167c478bd9Sstevel@tonic-gate for (c = name + sizeof ("zone.") - 1; *c != '\0'; c++) { 38177c478bd9Sstevel@tonic-gate if (!isalpha(*c) && *c != '-') 38187c478bd9Sstevel@tonic-gate return (B_FALSE); 38197c478bd9Sstevel@tonic-gate } 38207c478bd9Sstevel@tonic-gate return (B_TRUE); 38217c478bd9Sstevel@tonic-gate } 38227c478bd9Sstevel@tonic-gate 38237c478bd9Sstevel@tonic-gate boolean_t 38247c478bd9Sstevel@tonic-gate zonecfg_valid_rctlblk(const rctlblk_t *rctlblk) 38257c478bd9Sstevel@tonic-gate { 38267c478bd9Sstevel@tonic-gate rctl_priv_t priv = rctlblk_get_privilege((rctlblk_t *)rctlblk); 38277c478bd9Sstevel@tonic-gate uint_t action = rctlblk_get_local_action((rctlblk_t *)rctlblk, NULL); 38287c478bd9Sstevel@tonic-gate 38297c478bd9Sstevel@tonic-gate if (priv != RCPRIV_PRIVILEGED) 38307c478bd9Sstevel@tonic-gate return (B_FALSE); 38317c478bd9Sstevel@tonic-gate if (action != RCTL_LOCAL_NOACTION && action != RCTL_LOCAL_DENY) 38327c478bd9Sstevel@tonic-gate return (B_FALSE); 38337c478bd9Sstevel@tonic-gate return (B_TRUE); 38347c478bd9Sstevel@tonic-gate } 38357c478bd9Sstevel@tonic-gate 38367c478bd9Sstevel@tonic-gate boolean_t 38377c478bd9Sstevel@tonic-gate zonecfg_valid_rctl(const char *name, const rctlblk_t *rctlblk) 38387c478bd9Sstevel@tonic-gate { 38397c478bd9Sstevel@tonic-gate rctlblk_t *current, *next; 38407c478bd9Sstevel@tonic-gate rctl_qty_t limit = rctlblk_get_value((rctlblk_t *)rctlblk); 38417c478bd9Sstevel@tonic-gate uint_t action = rctlblk_get_local_action((rctlblk_t *)rctlblk, NULL); 38427c478bd9Sstevel@tonic-gate uint_t global_flags; 38437c478bd9Sstevel@tonic-gate 38447c478bd9Sstevel@tonic-gate if (!zonecfg_valid_rctlblk(rctlblk)) 38457c478bd9Sstevel@tonic-gate return (B_FALSE); 38467c478bd9Sstevel@tonic-gate if (!zonecfg_valid_rctlname(name)) 38477c478bd9Sstevel@tonic-gate return (B_FALSE); 38487c478bd9Sstevel@tonic-gate 38497c478bd9Sstevel@tonic-gate current = alloca(rctlblk_size()); 38507c478bd9Sstevel@tonic-gate if (getrctl(name, NULL, current, RCTL_FIRST) != 0) 38517c478bd9Sstevel@tonic-gate return (B_TRUE); /* not an rctl on this system */ 38527c478bd9Sstevel@tonic-gate /* 38537c478bd9Sstevel@tonic-gate * Make sure the proposed value isn't greater than the current system 38547c478bd9Sstevel@tonic-gate * value. 38557c478bd9Sstevel@tonic-gate */ 38567c478bd9Sstevel@tonic-gate next = alloca(rctlblk_size()); 38577c478bd9Sstevel@tonic-gate while (rctlblk_get_privilege(current) != RCPRIV_SYSTEM) { 38587c478bd9Sstevel@tonic-gate rctlblk_t *tmp; 38597c478bd9Sstevel@tonic-gate 38607c478bd9Sstevel@tonic-gate if (getrctl(name, current, next, RCTL_NEXT) != 0) 38617c478bd9Sstevel@tonic-gate return (B_FALSE); /* shouldn't happen */ 38627c478bd9Sstevel@tonic-gate tmp = current; 38637c478bd9Sstevel@tonic-gate current = next; 38647c478bd9Sstevel@tonic-gate next = tmp; 38657c478bd9Sstevel@tonic-gate } 38667c478bd9Sstevel@tonic-gate if (limit > rctlblk_get_value(current)) 38677c478bd9Sstevel@tonic-gate return (B_FALSE); 38687c478bd9Sstevel@tonic-gate 38697c478bd9Sstevel@tonic-gate /* 38707c478bd9Sstevel@tonic-gate * Make sure the proposed action is allowed. 38717c478bd9Sstevel@tonic-gate */ 38727c478bd9Sstevel@tonic-gate global_flags = rctlblk_get_global_flags(current); 38737c478bd9Sstevel@tonic-gate if ((global_flags & RCTL_GLOBAL_DENY_NEVER) && 38747c478bd9Sstevel@tonic-gate action == RCTL_LOCAL_DENY) 38757c478bd9Sstevel@tonic-gate return (B_FALSE); 38767c478bd9Sstevel@tonic-gate if ((global_flags & RCTL_GLOBAL_DENY_ALWAYS) && 38777c478bd9Sstevel@tonic-gate action == RCTL_LOCAL_NOACTION) 38787c478bd9Sstevel@tonic-gate return (B_FALSE); 38797c478bd9Sstevel@tonic-gate 38807c478bd9Sstevel@tonic-gate return (B_TRUE); 38817c478bd9Sstevel@tonic-gate } 3882fa9e4066Sahrens 3883cf8f45c7Sdstaff /* 3884cf8f45c7Sdstaff * There is always a race condition between reading the initial copy of 3885cf8f45c7Sdstaff * a zones state and its state changing. We address this by providing 3886cf8f45c7Sdstaff * zonecfg_notify_critical_enter and zonecfg_noticy_critical_exit functions. 3887cf8f45c7Sdstaff * When zonecfg_critical_enter is called, sets the state field to LOCKED 3888cf8f45c7Sdstaff * and aquires biglock. Biglock protects against other threads executing 3889cf8f45c7Sdstaff * critical_enter and the state field protects against state changes during 3890cf8f45c7Sdstaff * the critical period. 3891cf8f45c7Sdstaff * 3892cf8f45c7Sdstaff * If any state changes occur, zn_cb will set the failed field of the znotify 3893cf8f45c7Sdstaff * structure. This will cause the critical_exit function to re-lock the 3894cf8f45c7Sdstaff * channel and return an error. Since evsnts may be delayed, the critical_exit 3895cf8f45c7Sdstaff * function "flushes" the queue by putting an event on the queue and waiting for 3896cf8f45c7Sdstaff * zn_cb to notify critical_exit that it received the ping event. 3897cf8f45c7Sdstaff */ 3898cf8f45c7Sdstaff static const char * 3899cf8f45c7Sdstaff string_get_tok(const char *in, char delim, int num) 3900cf8f45c7Sdstaff { 3901cf8f45c7Sdstaff int i = 0; 3902cf8f45c7Sdstaff 3903cf8f45c7Sdstaff for (; i < num; in++) { 3904cf8f45c7Sdstaff if (*in == delim) 3905cf8f45c7Sdstaff i++; 3906cf8f45c7Sdstaff if (*in == 0) 3907cf8f45c7Sdstaff return (NULL); 3908cf8f45c7Sdstaff } 3909cf8f45c7Sdstaff return (in); 3910cf8f45c7Sdstaff } 3911cf8f45c7Sdstaff 3912cf8f45c7Sdstaff static boolean_t 3913cf8f45c7Sdstaff is_ping(sysevent_t *ev) 3914cf8f45c7Sdstaff { 3915cf8f45c7Sdstaff if (strcmp(sysevent_get_subclass_name(ev), 3916cf8f45c7Sdstaff ZONE_EVENT_PING_SUBCLASS) == 0) { 3917cf8f45c7Sdstaff return (B_TRUE); 3918cf8f45c7Sdstaff } else { 3919cf8f45c7Sdstaff return (B_FALSE); 3920cf8f45c7Sdstaff } 3921cf8f45c7Sdstaff } 3922cf8f45c7Sdstaff 3923cf8f45c7Sdstaff static boolean_t 3924cf8f45c7Sdstaff is_my_ping(sysevent_t *ev) 3925cf8f45c7Sdstaff { 3926cf8f45c7Sdstaff const char *sender; 3927cf8f45c7Sdstaff char mypid[sizeof (pid_t) * 3 + 1]; 3928cf8f45c7Sdstaff 3929cf8f45c7Sdstaff (void) snprintf(mypid, sizeof (mypid), "%i", getpid()); 3930cf8f45c7Sdstaff sender = string_get_tok(sysevent_get_pub(ev), ':', 3); 3931cf8f45c7Sdstaff if (sender == NULL) 3932cf8f45c7Sdstaff return (B_FALSE); 3933cf8f45c7Sdstaff if (strcmp(sender, mypid) != 0) 3934cf8f45c7Sdstaff return (B_FALSE); 3935cf8f45c7Sdstaff return (B_TRUE); 3936cf8f45c7Sdstaff } 3937cf8f45c7Sdstaff 3938cf8f45c7Sdstaff static int 3939cf8f45c7Sdstaff do_callback(struct znotify *zevtchan, sysevent_t *ev) 3940cf8f45c7Sdstaff { 3941cf8f45c7Sdstaff nvlist_t *l; 3942cf8f45c7Sdstaff int zid; 3943cf8f45c7Sdstaff char *zonename; 3944cf8f45c7Sdstaff char *newstate; 3945cf8f45c7Sdstaff char *oldstate; 3946cf8f45c7Sdstaff int ret; 3947cf8f45c7Sdstaff hrtime_t when; 3948cf8f45c7Sdstaff 3949cf8f45c7Sdstaff if (strcmp(sysevent_get_subclass_name(ev), 3950cf8f45c7Sdstaff ZONE_EVENT_STATUS_SUBCLASS) == 0) { 3951cf8f45c7Sdstaff 3952cf8f45c7Sdstaff if (sysevent_get_attr_list(ev, &l) != 0) { 3953cf8f45c7Sdstaff if (errno == ENOMEM) { 3954cf8f45c7Sdstaff zevtchan->zn_failure_count++; 3955cf8f45c7Sdstaff return (EAGAIN); 3956cf8f45c7Sdstaff } 3957cf8f45c7Sdstaff return (0); 3958cf8f45c7Sdstaff } 3959cf8f45c7Sdstaff ret = 0; 3960cf8f45c7Sdstaff 3961cf8f45c7Sdstaff if ((nvlist_lookup_string(l, ZONE_CB_NAME, &zonename) == 0) && 3962cf8f45c7Sdstaff (nvlist_lookup_string(l, ZONE_CB_NEWSTATE, &newstate) 3963cf8f45c7Sdstaff == 0) && 3964cf8f45c7Sdstaff (nvlist_lookup_string(l, ZONE_CB_OLDSTATE, &oldstate) 3965cf8f45c7Sdstaff == 0) && 3966cf8f45c7Sdstaff (nvlist_lookup_uint64(l, ZONE_CB_TIMESTAMP, 3967cf8f45c7Sdstaff (uint64_t *)&when) == 0) && 3968cf8f45c7Sdstaff (nvlist_lookup_int32(l, ZONE_CB_ZONEID, &zid) == 0)) { 3969cf8f45c7Sdstaff ret = zevtchan->zn_callback(zonename, zid, newstate, 3970cf8f45c7Sdstaff oldstate, when, zevtchan->zn_private); 3971cf8f45c7Sdstaff } 3972cf8f45c7Sdstaff 3973cf8f45c7Sdstaff zevtchan->zn_failure_count = 0; 3974cf8f45c7Sdstaff nvlist_free(l); 3975cf8f45c7Sdstaff return (ret); 3976cf8f45c7Sdstaff } else { 3977cf8f45c7Sdstaff /* 3978cf8f45c7Sdstaff * We have received an event in an unknown subclass. Ignore. 3979cf8f45c7Sdstaff */ 3980cf8f45c7Sdstaff zevtchan->zn_failure_count = 0; 3981cf8f45c7Sdstaff return (0); 3982cf8f45c7Sdstaff } 3983cf8f45c7Sdstaff } 3984cf8f45c7Sdstaff 3985cf8f45c7Sdstaff static int 3986cf8f45c7Sdstaff zn_cb(sysevent_t *ev, void *p) 3987cf8f45c7Sdstaff { 3988cf8f45c7Sdstaff struct znotify *zevtchan = p; 3989cf8f45c7Sdstaff int error; 3990cf8f45c7Sdstaff 3991cf8f45c7Sdstaff (void) pthread_mutex_lock(&(zevtchan->zn_mutex)); 3992cf8f45c7Sdstaff 3993cf8f45c7Sdstaff if (is_ping(ev) && !is_my_ping(ev)) { 3994cf8f45c7Sdstaff (void) pthread_mutex_unlock((&zevtchan->zn_mutex)); 3995cf8f45c7Sdstaff return (0); 3996cf8f45c7Sdstaff } 3997cf8f45c7Sdstaff 3998cf8f45c7Sdstaff if (zevtchan->zn_state == ZN_LOCKED) { 3999cf8f45c7Sdstaff assert(!is_ping(ev)); 4000cf8f45c7Sdstaff zevtchan->zn_failed = B_TRUE; 4001cf8f45c7Sdstaff (void) pthread_mutex_unlock(&(zevtchan->zn_mutex)); 4002cf8f45c7Sdstaff return (0); 4003cf8f45c7Sdstaff } 4004cf8f45c7Sdstaff 4005cf8f45c7Sdstaff if (zevtchan->zn_state == ZN_PING_INFLIGHT) { 4006cf8f45c7Sdstaff if (is_ping(ev)) { 4007cf8f45c7Sdstaff zevtchan->zn_state = ZN_PING_RECEIVED; 4008cf8f45c7Sdstaff (void) pthread_cond_signal(&(zevtchan->zn_cond)); 4009cf8f45c7Sdstaff (void) pthread_mutex_unlock(&(zevtchan->zn_mutex)); 4010cf8f45c7Sdstaff return (0); 4011cf8f45c7Sdstaff } else { 4012cf8f45c7Sdstaff zevtchan->zn_failed = B_TRUE; 4013cf8f45c7Sdstaff (void) pthread_mutex_unlock(&(zevtchan->zn_mutex)); 4014cf8f45c7Sdstaff return (0); 4015cf8f45c7Sdstaff } 4016cf8f45c7Sdstaff } 4017cf8f45c7Sdstaff 4018cf8f45c7Sdstaff if (zevtchan->zn_state == ZN_UNLOCKED) { 4019cf8f45c7Sdstaff 4020cf8f45c7Sdstaff error = do_callback(zevtchan, ev); 4021cf8f45c7Sdstaff (void) pthread_mutex_unlock(&(zevtchan->zn_mutex)); 4022cf8f45c7Sdstaff /* 4023cf8f45c7Sdstaff * Every ENOMEM failure causes do_callback to increment 4024cf8f45c7Sdstaff * zn_failure_count and every success causes it to 4025cf8f45c7Sdstaff * set zn_failure_count to zero. If we got EAGAIN, 4026cf8f45c7Sdstaff * we will sleep for zn_failure_count seconds and return 4027cf8f45c7Sdstaff * EAGAIN to gpec to try again. 4028cf8f45c7Sdstaff * 4029cf8f45c7Sdstaff * After 55 seconds, or 10 try's we give up and drop the 4030cf8f45c7Sdstaff * event. 4031cf8f45c7Sdstaff */ 4032cf8f45c7Sdstaff if (error == EAGAIN) { 4033cf8f45c7Sdstaff if (zevtchan->zn_failure_count > ZONE_CB_RETRY_COUNT) { 4034cf8f45c7Sdstaff return (0); 4035cf8f45c7Sdstaff } 4036cf8f45c7Sdstaff (void) sleep(zevtchan->zn_failure_count); 4037cf8f45c7Sdstaff } 4038cf8f45c7Sdstaff return (error); 4039cf8f45c7Sdstaff } 4040cf8f45c7Sdstaff 4041cf8f45c7Sdstaff if (zevtchan->zn_state == ZN_PING_RECEIVED) { 4042cf8f45c7Sdstaff (void) pthread_mutex_unlock(&(zevtchan->zn_mutex)); 4043cf8f45c7Sdstaff return (0); 4044cf8f45c7Sdstaff } 4045cf8f45c7Sdstaff 4046cf8f45c7Sdstaff abort(); 4047cf8f45c7Sdstaff return (0); 4048cf8f45c7Sdstaff } 4049cf8f45c7Sdstaff 4050cf8f45c7Sdstaff void 4051cf8f45c7Sdstaff zonecfg_notify_critical_enter(void *h) 4052cf8f45c7Sdstaff { 4053cf8f45c7Sdstaff struct znotify *zevtchan = h; 4054cf8f45c7Sdstaff 4055cf8f45c7Sdstaff (void) pthread_mutex_lock(&(zevtchan->zn_bigmutex)); 4056cf8f45c7Sdstaff zevtchan->zn_state = ZN_LOCKED; 4057cf8f45c7Sdstaff } 4058cf8f45c7Sdstaff 4059cf8f45c7Sdstaff int 4060cf8f45c7Sdstaff zonecfg_notify_critical_exit(void * h) 4061cf8f45c7Sdstaff { 4062cf8f45c7Sdstaff 4063cf8f45c7Sdstaff struct znotify *zevtchan = h; 4064cf8f45c7Sdstaff 4065cf8f45c7Sdstaff if (zevtchan->zn_state == ZN_UNLOCKED) 4066cf8f45c7Sdstaff return (0); 4067cf8f45c7Sdstaff 4068cf8f45c7Sdstaff (void) pthread_mutex_lock(&(zevtchan->zn_mutex)); 4069cf8f45c7Sdstaff zevtchan->zn_state = ZN_PING_INFLIGHT; 4070cf8f45c7Sdstaff 4071*ee519a1fSgjelinek (void) sysevent_evc_publish(zevtchan->zn_eventchan, 4072*ee519a1fSgjelinek ZONE_EVENT_STATUS_CLASS, 4073cf8f45c7Sdstaff ZONE_EVENT_PING_SUBCLASS, ZONE_EVENT_PING_PUBLISHER, 4074cf8f45c7Sdstaff zevtchan->zn_subscriber_id, NULL, EVCH_SLEEP); 4075cf8f45c7Sdstaff 4076cf8f45c7Sdstaff while (zevtchan->zn_state != ZN_PING_RECEIVED) { 4077cf8f45c7Sdstaff (void) pthread_cond_wait(&(zevtchan->zn_cond), 4078cf8f45c7Sdstaff &(zevtchan->zn_mutex)); 4079cf8f45c7Sdstaff } 4080cf8f45c7Sdstaff 4081cf8f45c7Sdstaff if (zevtchan->zn_failed == B_TRUE) { 4082cf8f45c7Sdstaff zevtchan->zn_state = ZN_LOCKED; 4083cf8f45c7Sdstaff zevtchan->zn_failed = B_FALSE; 4084cf8f45c7Sdstaff (void) pthread_mutex_unlock(&(zevtchan->zn_mutex)); 4085cf8f45c7Sdstaff return (1); 4086cf8f45c7Sdstaff } 4087cf8f45c7Sdstaff 4088cf8f45c7Sdstaff zevtchan->zn_state = ZN_UNLOCKED; 4089cf8f45c7Sdstaff (void) pthread_mutex_unlock(&(zevtchan->zn_mutex)); 4090cf8f45c7Sdstaff (void) pthread_mutex_unlock(&(zevtchan->zn_bigmutex)); 4091cf8f45c7Sdstaff return (0); 4092cf8f45c7Sdstaff } 4093cf8f45c7Sdstaff 4094cf8f45c7Sdstaff void 4095cf8f45c7Sdstaff zonecfg_notify_critical_abort(void *h) 4096cf8f45c7Sdstaff { 4097cf8f45c7Sdstaff struct znotify *zevtchan = h; 4098cf8f45c7Sdstaff 4099cf8f45c7Sdstaff zevtchan->zn_state = ZN_UNLOCKED; 4100cf8f45c7Sdstaff zevtchan->zn_failed = B_FALSE; 4101cf8f45c7Sdstaff /* 4102cf8f45c7Sdstaff * Don't do anything about zn_lock. If it is held, it could only be 4103cf8f45c7Sdstaff * held by zn_cb and it will be unlocked soon. 4104cf8f45c7Sdstaff */ 4105cf8f45c7Sdstaff (void) pthread_mutex_unlock(&(zevtchan->zn_bigmutex)); 4106cf8f45c7Sdstaff } 4107cf8f45c7Sdstaff 4108cf8f45c7Sdstaff void * 4109cf8f45c7Sdstaff zonecfg_notify_bind(int(*func)(const char *zonename, zoneid_t zid, 4110cf8f45c7Sdstaff const char *newstate, const char *oldstate, hrtime_t when, void *p), 4111cf8f45c7Sdstaff void *p) 4112cf8f45c7Sdstaff { 4113cf8f45c7Sdstaff struct znotify *zevtchan; 4114cf8f45c7Sdstaff int i = 1; 4115cf8f45c7Sdstaff int r; 4116cf8f45c7Sdstaff 4117cf8f45c7Sdstaff zevtchan = malloc(sizeof (struct znotify)); 4118cf8f45c7Sdstaff 4119cf8f45c7Sdstaff if (zevtchan == NULL) 4120cf8f45c7Sdstaff return (NULL); 4121cf8f45c7Sdstaff 4122cf8f45c7Sdstaff zevtchan->zn_private = p; 4123cf8f45c7Sdstaff zevtchan->zn_callback = func; 4124cf8f45c7Sdstaff zevtchan->zn_state = ZN_UNLOCKED; 4125cf8f45c7Sdstaff zevtchan->zn_failed = B_FALSE; 4126cf8f45c7Sdstaff 4127cf8f45c7Sdstaff if (pthread_mutex_init(&(zevtchan->zn_mutex), NULL)) 41289d4be64eSdstaff goto out3; 4129cf8f45c7Sdstaff if (pthread_cond_init(&(zevtchan->zn_cond), NULL)) { 4130cf8f45c7Sdstaff (void) pthread_mutex_destroy(&(zevtchan->zn_mutex)); 41319d4be64eSdstaff goto out3; 4132cf8f45c7Sdstaff } 4133cf8f45c7Sdstaff if (pthread_mutex_init(&(zevtchan->zn_bigmutex), NULL)) { 4134cf8f45c7Sdstaff (void) pthread_mutex_destroy(&(zevtchan->zn_mutex)); 4135cf8f45c7Sdstaff (void) pthread_cond_destroy(&(zevtchan->zn_cond)); 41369d4be64eSdstaff goto out3; 4137cf8f45c7Sdstaff } 4138cf8f45c7Sdstaff 4139cf8f45c7Sdstaff if (sysevent_evc_bind(ZONE_EVENT_CHANNEL, &(zevtchan->zn_eventchan), 4140cf8f45c7Sdstaff 0) != 0) 4141cf8f45c7Sdstaff goto out2; 4142cf8f45c7Sdstaff 4143cf8f45c7Sdstaff do { 4144cf8f45c7Sdstaff /* 4145cf8f45c7Sdstaff * At 4 digits the subscriber ID gets too long and we have 4146cf8f45c7Sdstaff * no chance of successfully registering. 4147cf8f45c7Sdstaff */ 4148cf8f45c7Sdstaff if (i > 999) 41499d4be64eSdstaff goto out1; 4150cf8f45c7Sdstaff 4151cf8f45c7Sdstaff (void) sprintf(zevtchan->zn_subscriber_id, "zone_%li_%i", 4152cf8f45c7Sdstaff getpid() % 999999l, i); 4153cf8f45c7Sdstaff 4154cf8f45c7Sdstaff r = sysevent_evc_subscribe(zevtchan->zn_eventchan, 4155cf8f45c7Sdstaff zevtchan->zn_subscriber_id, ZONE_EVENT_STATUS_CLASS, zn_cb, 4156cf8f45c7Sdstaff zevtchan, 0); 4157cf8f45c7Sdstaff 4158cf8f45c7Sdstaff i++; 4159cf8f45c7Sdstaff 4160cf8f45c7Sdstaff } while (r); 4161cf8f45c7Sdstaff 4162cf8f45c7Sdstaff return (zevtchan); 41639d4be64eSdstaff out1: 4164cf8f45c7Sdstaff sysevent_evc_unbind(zevtchan->zn_eventchan); 41659d4be64eSdstaff out2: 4166cf8f45c7Sdstaff (void) pthread_mutex_destroy(&zevtchan->zn_mutex); 4167cf8f45c7Sdstaff (void) pthread_cond_destroy(&zevtchan->zn_cond); 4168cf8f45c7Sdstaff (void) pthread_mutex_destroy(&(zevtchan->zn_bigmutex)); 41699d4be64eSdstaff out3: 4170cf8f45c7Sdstaff free(zevtchan); 4171cf8f45c7Sdstaff 4172cf8f45c7Sdstaff return (NULL); 4173cf8f45c7Sdstaff } 4174cf8f45c7Sdstaff 4175cf8f45c7Sdstaff void 4176cf8f45c7Sdstaff zonecfg_notify_unbind(void *handle) 4177cf8f45c7Sdstaff { 4178cf8f45c7Sdstaff 4179cf8f45c7Sdstaff int ret; 4180cf8f45c7Sdstaff 4181cf8f45c7Sdstaff sysevent_evc_unbind(((struct znotify *)handle)->zn_eventchan); 4182cf8f45c7Sdstaff /* 4183cf8f45c7Sdstaff * Check that all evc threads have gone away. This should be 4184cf8f45c7Sdstaff * enforced by sysevent_evc_unbind. 4185cf8f45c7Sdstaff */ 4186cf8f45c7Sdstaff ret = pthread_mutex_trylock(&((struct znotify *)handle)->zn_mutex); 4187cf8f45c7Sdstaff 4188cf8f45c7Sdstaff if (ret) 4189cf8f45c7Sdstaff abort(); 4190cf8f45c7Sdstaff 4191cf8f45c7Sdstaff (void) pthread_mutex_unlock(&((struct znotify *)handle)->zn_mutex); 4192cf8f45c7Sdstaff (void) pthread_mutex_destroy(&((struct znotify *)handle)->zn_mutex); 4193cf8f45c7Sdstaff (void) pthread_cond_destroy(&((struct znotify *)handle)->zn_cond); 4194cf8f45c7Sdstaff (void) pthread_mutex_destroy(&((struct znotify *)handle)->zn_bigmutex); 4195cf8f45c7Sdstaff 4196cf8f45c7Sdstaff free(handle); 4197cf8f45c7Sdstaff } 4198cf8f45c7Sdstaff 4199fa9e4066Sahrens static int 4200fa9e4066Sahrens zonecfg_add_ds_core(zone_dochandle_t handle, struct zone_dstab *tabptr) 4201fa9e4066Sahrens { 4202fa9e4066Sahrens xmlNodePtr newnode, cur = handle->zone_dh_cur; 4203fa9e4066Sahrens int err; 4204fa9e4066Sahrens 4205fa9e4066Sahrens newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_DATASET, NULL); 4206fa9e4066Sahrens if ((err = newprop(newnode, DTD_ATTR_NAME, 4207fa9e4066Sahrens tabptr->zone_dataset_name)) != Z_OK) 4208fa9e4066Sahrens return (err); 4209fa9e4066Sahrens return (Z_OK); 4210fa9e4066Sahrens } 4211fa9e4066Sahrens 4212fa9e4066Sahrens int 4213fa9e4066Sahrens zonecfg_add_ds(zone_dochandle_t handle, struct zone_dstab *tabptr) 4214fa9e4066Sahrens { 4215fa9e4066Sahrens int err; 4216fa9e4066Sahrens 4217fa9e4066Sahrens if (tabptr == NULL) 4218fa9e4066Sahrens return (Z_INVAL); 4219fa9e4066Sahrens 4220fa9e4066Sahrens if ((err = operation_prep(handle)) != Z_OK) 4221fa9e4066Sahrens return (err); 4222fa9e4066Sahrens 4223fa9e4066Sahrens if ((err = zonecfg_add_ds_core(handle, tabptr)) != Z_OK) 4224fa9e4066Sahrens return (err); 4225fa9e4066Sahrens 4226fa9e4066Sahrens return (Z_OK); 4227fa9e4066Sahrens } 4228fa9e4066Sahrens 4229fa9e4066Sahrens static int 4230fa9e4066Sahrens zonecfg_delete_ds_core(zone_dochandle_t handle, struct zone_dstab *tabptr) 4231fa9e4066Sahrens { 4232fa9e4066Sahrens xmlNodePtr cur = handle->zone_dh_cur; 4233fa9e4066Sahrens 4234fa9e4066Sahrens for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 4235fa9e4066Sahrens if (xmlStrcmp(cur->name, DTD_ELEM_DATASET)) 4236fa9e4066Sahrens continue; 4237fa9e4066Sahrens 4238fa9e4066Sahrens if (match_prop(cur, DTD_ATTR_NAME, 4239fa9e4066Sahrens tabptr->zone_dataset_name)) { 4240fa9e4066Sahrens xmlUnlinkNode(cur); 4241fa9e4066Sahrens xmlFreeNode(cur); 4242fa9e4066Sahrens return (Z_OK); 4243fa9e4066Sahrens } 4244fa9e4066Sahrens } 4245fa9e4066Sahrens return (Z_NO_RESOURCE_ID); 4246fa9e4066Sahrens } 4247fa9e4066Sahrens 4248fa9e4066Sahrens int 4249fa9e4066Sahrens zonecfg_delete_ds(zone_dochandle_t handle, struct zone_dstab *tabptr) 4250fa9e4066Sahrens { 4251fa9e4066Sahrens int err; 4252fa9e4066Sahrens 4253fa9e4066Sahrens if (tabptr == NULL) 4254fa9e4066Sahrens return (Z_INVAL); 4255fa9e4066Sahrens 4256fa9e4066Sahrens if ((err = operation_prep(handle)) != Z_OK) 4257fa9e4066Sahrens return (err); 4258fa9e4066Sahrens 4259fa9e4066Sahrens if ((err = zonecfg_delete_ds_core(handle, tabptr)) != Z_OK) 4260fa9e4066Sahrens return (err); 4261fa9e4066Sahrens 4262fa9e4066Sahrens return (Z_OK); 4263fa9e4066Sahrens } 4264fa9e4066Sahrens 4265fa9e4066Sahrens int 4266fa9e4066Sahrens zonecfg_modify_ds( 4267fa9e4066Sahrens zone_dochandle_t handle, 4268fa9e4066Sahrens struct zone_dstab *oldtabptr, 4269fa9e4066Sahrens struct zone_dstab *newtabptr) 4270fa9e4066Sahrens { 4271fa9e4066Sahrens int err; 4272fa9e4066Sahrens 4273fa9e4066Sahrens if (oldtabptr == NULL || newtabptr == NULL) 4274fa9e4066Sahrens return (Z_INVAL); 4275fa9e4066Sahrens 4276fa9e4066Sahrens if ((err = operation_prep(handle)) != Z_OK) 4277fa9e4066Sahrens return (err); 4278fa9e4066Sahrens 4279fa9e4066Sahrens if ((err = zonecfg_delete_ds_core(handle, oldtabptr)) != Z_OK) 4280fa9e4066Sahrens return (err); 4281fa9e4066Sahrens 4282fa9e4066Sahrens if ((err = zonecfg_add_ds_core(handle, newtabptr)) != Z_OK) 4283fa9e4066Sahrens return (err); 4284fa9e4066Sahrens 4285fa9e4066Sahrens return (Z_OK); 4286fa9e4066Sahrens } 4287fa9e4066Sahrens 4288fa9e4066Sahrens int 4289fa9e4066Sahrens zonecfg_lookup_ds(zone_dochandle_t handle, struct zone_dstab *tabptr) 4290fa9e4066Sahrens { 4291fa9e4066Sahrens xmlNodePtr cur, firstmatch; 4292fa9e4066Sahrens int err; 4293fa9e4066Sahrens char dataset[MAXNAMELEN]; 4294fa9e4066Sahrens 4295fa9e4066Sahrens if (tabptr == NULL) 4296fa9e4066Sahrens return (Z_INVAL); 4297fa9e4066Sahrens 4298fa9e4066Sahrens if ((err = operation_prep(handle)) != Z_OK) 4299fa9e4066Sahrens return (err); 4300fa9e4066Sahrens 4301fa9e4066Sahrens cur = handle->zone_dh_cur; 4302fa9e4066Sahrens firstmatch = NULL; 4303fa9e4066Sahrens for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 4304fa9e4066Sahrens if (xmlStrcmp(cur->name, DTD_ELEM_DATASET)) 4305fa9e4066Sahrens continue; 4306fa9e4066Sahrens if (strlen(tabptr->zone_dataset_name) > 0) { 4307fa9e4066Sahrens if ((fetchprop(cur, DTD_ATTR_NAME, dataset, 4308fa9e4066Sahrens sizeof (dataset)) == Z_OK) && 4309fa9e4066Sahrens (strcmp(tabptr->zone_dataset_name, 4310fa9e4066Sahrens dataset) == 0)) { 4311fa9e4066Sahrens if (firstmatch == NULL) 4312fa9e4066Sahrens firstmatch = cur; 4313fa9e4066Sahrens else 4314fa9e4066Sahrens return (Z_INSUFFICIENT_SPEC); 4315fa9e4066Sahrens } 4316fa9e4066Sahrens } 4317fa9e4066Sahrens } 4318fa9e4066Sahrens if (firstmatch == NULL) 4319fa9e4066Sahrens return (Z_NO_RESOURCE_ID); 4320fa9e4066Sahrens 4321fa9e4066Sahrens cur = firstmatch; 4322fa9e4066Sahrens 4323fa9e4066Sahrens if ((err = fetchprop(cur, DTD_ATTR_NAME, tabptr->zone_dataset_name, 4324fa9e4066Sahrens sizeof (tabptr->zone_dataset_name))) != Z_OK) 4325fa9e4066Sahrens return (err); 4326fa9e4066Sahrens 4327fa9e4066Sahrens return (Z_OK); 4328fa9e4066Sahrens } 4329fa9e4066Sahrens 4330fa9e4066Sahrens int 4331fa9e4066Sahrens zonecfg_setdsent(zone_dochandle_t handle) 4332fa9e4066Sahrens { 4333fa9e4066Sahrens return (zonecfg_setent(handle)); 4334fa9e4066Sahrens } 4335fa9e4066Sahrens 4336fa9e4066Sahrens int 4337fa9e4066Sahrens zonecfg_getdsent(zone_dochandle_t handle, struct zone_dstab *tabptr) 4338fa9e4066Sahrens { 4339fa9e4066Sahrens xmlNodePtr cur; 4340fa9e4066Sahrens int err; 4341fa9e4066Sahrens 4342fa9e4066Sahrens if (handle == NULL) 4343fa9e4066Sahrens return (Z_INVAL); 4344fa9e4066Sahrens 4345fa9e4066Sahrens if ((cur = handle->zone_dh_cur) == NULL) 4346fa9e4066Sahrens return (Z_NO_ENTRY); 4347fa9e4066Sahrens 4348fa9e4066Sahrens for (; cur != NULL; cur = cur->next) 4349fa9e4066Sahrens if (!xmlStrcmp(cur->name, DTD_ELEM_DATASET)) 4350fa9e4066Sahrens break; 4351fa9e4066Sahrens if (cur == NULL) { 4352fa9e4066Sahrens handle->zone_dh_cur = handle->zone_dh_top; 4353fa9e4066Sahrens return (Z_NO_ENTRY); 4354fa9e4066Sahrens } 4355fa9e4066Sahrens 4356fa9e4066Sahrens if ((err = fetchprop(cur, DTD_ATTR_NAME, tabptr->zone_dataset_name, 4357fa9e4066Sahrens sizeof (tabptr->zone_dataset_name))) != Z_OK) { 4358fa9e4066Sahrens handle->zone_dh_cur = handle->zone_dh_top; 4359fa9e4066Sahrens return (err); 4360fa9e4066Sahrens } 4361fa9e4066Sahrens 4362fa9e4066Sahrens handle->zone_dh_cur = cur->next; 4363fa9e4066Sahrens return (Z_OK); 4364fa9e4066Sahrens } 4365fa9e4066Sahrens 4366fa9e4066Sahrens int 4367fa9e4066Sahrens zonecfg_enddsent(zone_dochandle_t handle) 4368fa9e4066Sahrens { 4369fa9e4066Sahrens return (zonecfg_endent(handle)); 4370fa9e4066Sahrens } 4371*ee519a1fSgjelinek 4372*ee519a1fSgjelinek int 4373*ee519a1fSgjelinek zonecfg_setpkgent(zone_dochandle_t handle) 4374*ee519a1fSgjelinek { 4375*ee519a1fSgjelinek return (zonecfg_setent(handle)); 4376*ee519a1fSgjelinek } 4377*ee519a1fSgjelinek 4378*ee519a1fSgjelinek int 4379*ee519a1fSgjelinek zonecfg_getpkgent(zone_dochandle_t handle, struct zone_pkgtab *tabptr) 4380*ee519a1fSgjelinek { 4381*ee519a1fSgjelinek xmlNodePtr cur; 4382*ee519a1fSgjelinek int err; 4383*ee519a1fSgjelinek 4384*ee519a1fSgjelinek if (handle == NULL) 4385*ee519a1fSgjelinek return (Z_INVAL); 4386*ee519a1fSgjelinek 4387*ee519a1fSgjelinek if ((cur = handle->zone_dh_cur) == NULL) 4388*ee519a1fSgjelinek return (Z_NO_ENTRY); 4389*ee519a1fSgjelinek 4390*ee519a1fSgjelinek for (; cur != NULL; cur = cur->next) 4391*ee519a1fSgjelinek if (!xmlStrcmp(cur->name, DTD_ELEM_PACKAGE)) 4392*ee519a1fSgjelinek break; 4393*ee519a1fSgjelinek if (cur == NULL) { 4394*ee519a1fSgjelinek handle->zone_dh_cur = handle->zone_dh_top; 4395*ee519a1fSgjelinek return (Z_NO_ENTRY); 4396*ee519a1fSgjelinek } 4397*ee519a1fSgjelinek 4398*ee519a1fSgjelinek if ((err = fetchprop(cur, DTD_ATTR_NAME, tabptr->zone_pkg_name, 4399*ee519a1fSgjelinek sizeof (tabptr->zone_pkg_name))) != Z_OK) { 4400*ee519a1fSgjelinek handle->zone_dh_cur = handle->zone_dh_top; 4401*ee519a1fSgjelinek return (err); 4402*ee519a1fSgjelinek } 4403*ee519a1fSgjelinek 4404*ee519a1fSgjelinek if ((err = fetchprop(cur, DTD_ATTR_VERSION, tabptr->zone_pkg_version, 4405*ee519a1fSgjelinek sizeof (tabptr->zone_pkg_version))) != Z_OK) { 4406*ee519a1fSgjelinek handle->zone_dh_cur = handle->zone_dh_top; 4407*ee519a1fSgjelinek return (err); 4408*ee519a1fSgjelinek } 4409*ee519a1fSgjelinek 4410*ee519a1fSgjelinek handle->zone_dh_cur = cur->next; 4411*ee519a1fSgjelinek return (Z_OK); 4412*ee519a1fSgjelinek } 4413*ee519a1fSgjelinek 4414*ee519a1fSgjelinek int 4415*ee519a1fSgjelinek zonecfg_endpkgent(zone_dochandle_t handle) 4416*ee519a1fSgjelinek { 4417*ee519a1fSgjelinek return (zonecfg_endent(handle)); 4418*ee519a1fSgjelinek } 4419*ee519a1fSgjelinek 4420*ee519a1fSgjelinek int 4421*ee519a1fSgjelinek zonecfg_setpatchent(zone_dochandle_t handle) 4422*ee519a1fSgjelinek { 4423*ee519a1fSgjelinek return (zonecfg_setent(handle)); 4424*ee519a1fSgjelinek } 4425*ee519a1fSgjelinek 4426*ee519a1fSgjelinek int 4427*ee519a1fSgjelinek zonecfg_getpatchent(zone_dochandle_t handle, struct zone_patchtab *tabptr) 4428*ee519a1fSgjelinek { 4429*ee519a1fSgjelinek xmlNodePtr cur; 4430*ee519a1fSgjelinek int err; 4431*ee519a1fSgjelinek 4432*ee519a1fSgjelinek if (handle == NULL) 4433*ee519a1fSgjelinek return (Z_INVAL); 4434*ee519a1fSgjelinek 4435*ee519a1fSgjelinek if ((cur = handle->zone_dh_cur) == NULL) 4436*ee519a1fSgjelinek return (Z_NO_ENTRY); 4437*ee519a1fSgjelinek 4438*ee519a1fSgjelinek for (; cur != NULL; cur = cur->next) 4439*ee519a1fSgjelinek if (!xmlStrcmp(cur->name, DTD_ELEM_PATCH)) 4440*ee519a1fSgjelinek break; 4441*ee519a1fSgjelinek if (cur == NULL) { 4442*ee519a1fSgjelinek handle->zone_dh_cur = handle->zone_dh_top; 4443*ee519a1fSgjelinek return (Z_NO_ENTRY); 4444*ee519a1fSgjelinek } 4445*ee519a1fSgjelinek 4446*ee519a1fSgjelinek if ((err = fetchprop(cur, DTD_ATTR_ID, tabptr->zone_patch_id, 4447*ee519a1fSgjelinek sizeof (tabptr->zone_patch_id))) != Z_OK) { 4448*ee519a1fSgjelinek handle->zone_dh_cur = handle->zone_dh_top; 4449*ee519a1fSgjelinek return (err); 4450*ee519a1fSgjelinek } 4451*ee519a1fSgjelinek 4452*ee519a1fSgjelinek handle->zone_dh_cur = cur->next; 4453*ee519a1fSgjelinek return (Z_OK); 4454*ee519a1fSgjelinek } 4455*ee519a1fSgjelinek 4456*ee519a1fSgjelinek int 4457*ee519a1fSgjelinek zonecfg_endpatchent(zone_dochandle_t handle) 4458*ee519a1fSgjelinek { 4459*ee519a1fSgjelinek return (zonecfg_endent(handle)); 4460*ee519a1fSgjelinek } 4461*ee519a1fSgjelinek 4462*ee519a1fSgjelinek int 4463*ee519a1fSgjelinek zonecfg_setdevperment(zone_dochandle_t handle) 4464*ee519a1fSgjelinek { 4465*ee519a1fSgjelinek return (zonecfg_setent(handle)); 4466*ee519a1fSgjelinek } 4467*ee519a1fSgjelinek 4468*ee519a1fSgjelinek int 4469*ee519a1fSgjelinek zonecfg_getdevperment(zone_dochandle_t handle, struct zone_devpermtab *tabptr) 4470*ee519a1fSgjelinek { 4471*ee519a1fSgjelinek xmlNodePtr cur; 4472*ee519a1fSgjelinek int err; 4473*ee519a1fSgjelinek char buf[128]; 4474*ee519a1fSgjelinek 4475*ee519a1fSgjelinek tabptr->zone_devperm_acl = NULL; 4476*ee519a1fSgjelinek 4477*ee519a1fSgjelinek if (handle == NULL) 4478*ee519a1fSgjelinek return (Z_INVAL); 4479*ee519a1fSgjelinek 4480*ee519a1fSgjelinek if ((cur = handle->zone_dh_cur) == NULL) 4481*ee519a1fSgjelinek return (Z_NO_ENTRY); 4482*ee519a1fSgjelinek 4483*ee519a1fSgjelinek for (; cur != NULL; cur = cur->next) 4484*ee519a1fSgjelinek if (!xmlStrcmp(cur->name, DTD_ELEM_DEV_PERM)) 4485*ee519a1fSgjelinek break; 4486*ee519a1fSgjelinek if (cur == NULL) { 4487*ee519a1fSgjelinek handle->zone_dh_cur = handle->zone_dh_top; 4488*ee519a1fSgjelinek return (Z_NO_ENTRY); 4489*ee519a1fSgjelinek } 4490*ee519a1fSgjelinek 4491*ee519a1fSgjelinek if ((err = fetchprop(cur, DTD_ATTR_NAME, tabptr->zone_devperm_name, 4492*ee519a1fSgjelinek sizeof (tabptr->zone_devperm_name))) != Z_OK) { 4493*ee519a1fSgjelinek handle->zone_dh_cur = handle->zone_dh_top; 4494*ee519a1fSgjelinek return (err); 4495*ee519a1fSgjelinek } 4496*ee519a1fSgjelinek 4497*ee519a1fSgjelinek if ((err = fetchprop(cur, DTD_ATTR_UID, buf, sizeof (buf))) != Z_OK) { 4498*ee519a1fSgjelinek handle->zone_dh_cur = handle->zone_dh_top; 4499*ee519a1fSgjelinek return (err); 4500*ee519a1fSgjelinek } 4501*ee519a1fSgjelinek tabptr->zone_devperm_uid = (uid_t)atol(buf); 4502*ee519a1fSgjelinek 4503*ee519a1fSgjelinek if ((err = fetchprop(cur, DTD_ATTR_GID, buf, sizeof (buf))) != Z_OK) { 4504*ee519a1fSgjelinek handle->zone_dh_cur = handle->zone_dh_top; 4505*ee519a1fSgjelinek return (err); 4506*ee519a1fSgjelinek } 4507*ee519a1fSgjelinek tabptr->zone_devperm_gid = (gid_t)atol(buf); 4508*ee519a1fSgjelinek 4509*ee519a1fSgjelinek if ((err = fetchprop(cur, DTD_ATTR_MODE, buf, sizeof (buf))) != Z_OK) { 4510*ee519a1fSgjelinek handle->zone_dh_cur = handle->zone_dh_top; 4511*ee519a1fSgjelinek return (err); 4512*ee519a1fSgjelinek } 4513*ee519a1fSgjelinek tabptr->zone_devperm_mode = (mode_t)strtol(buf, (char **)NULL, 8); 4514*ee519a1fSgjelinek 4515*ee519a1fSgjelinek if ((err = fetch_alloc_prop(cur, DTD_ATTR_ACL, 4516*ee519a1fSgjelinek &(tabptr->zone_devperm_acl))) != Z_OK) { 4517*ee519a1fSgjelinek handle->zone_dh_cur = handle->zone_dh_top; 4518*ee519a1fSgjelinek return (err); 4519*ee519a1fSgjelinek } 4520*ee519a1fSgjelinek 4521*ee519a1fSgjelinek handle->zone_dh_cur = cur->next; 4522*ee519a1fSgjelinek return (Z_OK); 4523*ee519a1fSgjelinek } 4524*ee519a1fSgjelinek 4525*ee519a1fSgjelinek int 4526*ee519a1fSgjelinek zonecfg_enddevperment(zone_dochandle_t handle) 4527*ee519a1fSgjelinek { 4528*ee519a1fSgjelinek return (zonecfg_endent(handle)); 4529*ee519a1fSgjelinek } 4530*ee519a1fSgjelinek 4531*ee519a1fSgjelinek /* 4532*ee519a1fSgjelinek * Process a list of pkgs from an entry in the contents file, adding each pkg 4533*ee519a1fSgjelinek * name to the list of pkgs. 4534*ee519a1fSgjelinek * 4535*ee519a1fSgjelinek * It is possible for the pkg name to be preceeded by a special character 4536*ee519a1fSgjelinek * which indicates some bookkeeping information for pkging. Check if the 4537*ee519a1fSgjelinek * first char is not an Alpha char. If so, skip over it. 4538*ee519a1fSgjelinek */ 4539*ee519a1fSgjelinek static int 4540*ee519a1fSgjelinek add_pkg_list(char *lastp, char ***plist, int *pcnt) 4541*ee519a1fSgjelinek { 4542*ee519a1fSgjelinek char *p; 4543*ee519a1fSgjelinek int pkg_cnt = *pcnt; 4544*ee519a1fSgjelinek char **pkgs = *plist; 4545*ee519a1fSgjelinek int res = Z_OK; 4546*ee519a1fSgjelinek 4547*ee519a1fSgjelinek while ((p = strtok_r(NULL, " ", &lastp)) != NULL) { 4548*ee519a1fSgjelinek char **tmpp; 4549*ee519a1fSgjelinek int i; 4550*ee519a1fSgjelinek 4551*ee519a1fSgjelinek /* skip over any special pkg bookkeeping char */ 4552*ee519a1fSgjelinek if (!isalpha(*p)) 4553*ee519a1fSgjelinek p++; 4554*ee519a1fSgjelinek 4555*ee519a1fSgjelinek /* Check if the pkg is already in the list */ 4556*ee519a1fSgjelinek for (i = 0; i < pkg_cnt; i++) { 4557*ee519a1fSgjelinek if (strcmp(p, pkgs[i]) == 0) 4558*ee519a1fSgjelinek break; 4559*ee519a1fSgjelinek } 4560*ee519a1fSgjelinek 4561*ee519a1fSgjelinek if (i < pkg_cnt) 4562*ee519a1fSgjelinek continue; 4563*ee519a1fSgjelinek 4564*ee519a1fSgjelinek /* The pkg is not in the list; add it. */ 4565*ee519a1fSgjelinek if ((tmpp = (char **)realloc(pkgs, 4566*ee519a1fSgjelinek sizeof (char *) * (pkg_cnt + 1))) == NULL) { 4567*ee519a1fSgjelinek res = Z_NOMEM; 4568*ee519a1fSgjelinek break; 4569*ee519a1fSgjelinek } 4570*ee519a1fSgjelinek pkgs = tmpp; 4571*ee519a1fSgjelinek 4572*ee519a1fSgjelinek if ((pkgs[pkg_cnt] = strdup(p)) == NULL) { 4573*ee519a1fSgjelinek res = Z_NOMEM; 4574*ee519a1fSgjelinek break; 4575*ee519a1fSgjelinek } 4576*ee519a1fSgjelinek pkg_cnt++; 4577*ee519a1fSgjelinek } 4578*ee519a1fSgjelinek 4579*ee519a1fSgjelinek *plist = pkgs; 4580*ee519a1fSgjelinek *pcnt = pkg_cnt; 4581*ee519a1fSgjelinek 4582*ee519a1fSgjelinek return (res); 4583*ee519a1fSgjelinek } 4584*ee519a1fSgjelinek 4585*ee519a1fSgjelinek /* 4586*ee519a1fSgjelinek * Process an entry from the contents file (type "directory") and if the 4587*ee519a1fSgjelinek * directory path is in the list of paths, add the associated list of pkgs 4588*ee519a1fSgjelinek * to the pkg list. The input parameter "entry" will be broken up by 4589*ee519a1fSgjelinek * the parser within this function so its value will be modified when this 4590*ee519a1fSgjelinek * function exits. 4591*ee519a1fSgjelinek * 4592*ee519a1fSgjelinek * The entries we are looking for will look something like: 4593*ee519a1fSgjelinek * /usr d none 0755 root sys SUNWctpls SUNWidnl SUNWlibCf .... 4594*ee519a1fSgjelinek */ 4595*ee519a1fSgjelinek static int 4596*ee519a1fSgjelinek get_path_pkgs(char *entry, char **paths, int cnt, char ***pkgs, int *pkg_cnt) 4597*ee519a1fSgjelinek { 4598*ee519a1fSgjelinek char *f1; 4599*ee519a1fSgjelinek char *f2; 4600*ee519a1fSgjelinek char *lastp; 4601*ee519a1fSgjelinek int i; 4602*ee519a1fSgjelinek int res = Z_OK; 4603*ee519a1fSgjelinek 4604*ee519a1fSgjelinek if ((f1 = strtok_r(entry, " ", &lastp)) == NULL || 4605*ee519a1fSgjelinek (f2 = strtok_r(NULL, " ", &lastp)) == NULL || strcmp(f2, "d") != 0) 4606*ee519a1fSgjelinek return (Z_OK); 4607*ee519a1fSgjelinek 4608*ee519a1fSgjelinek /* Check if this directory entry is in the list of paths. */ 4609*ee519a1fSgjelinek for (i = 0; i < cnt; i++) { 4610*ee519a1fSgjelinek if (fnmatch(paths[i], f1, FNM_PATHNAME) == 0) { 4611*ee519a1fSgjelinek /* 4612*ee519a1fSgjelinek * We do want the pkgs for this path. First, skip 4613*ee519a1fSgjelinek * over the next 4 fields in the entry so that we call 4614*ee519a1fSgjelinek * add_pkg_list starting with the pkg names. 4615*ee519a1fSgjelinek */ 4616*ee519a1fSgjelinek int j; 4617*ee519a1fSgjelinek 4618*ee519a1fSgjelinek for (j = 0; j < 4 && 4619*ee519a1fSgjelinek strtok_r(NULL, " ", &lastp) != NULL; j++); 4620*ee519a1fSgjelinek /* 4621*ee519a1fSgjelinek * If there are < 4 fields this entry is corrupt, 4622*ee519a1fSgjelinek * just skip it. 4623*ee519a1fSgjelinek */ 4624*ee519a1fSgjelinek if (j < 4) 4625*ee519a1fSgjelinek return (Z_OK); 4626*ee519a1fSgjelinek 4627*ee519a1fSgjelinek res = add_pkg_list(lastp, pkgs, pkg_cnt); 4628*ee519a1fSgjelinek break; 4629*ee519a1fSgjelinek } 4630*ee519a1fSgjelinek } 4631*ee519a1fSgjelinek 4632*ee519a1fSgjelinek return (res); 4633*ee519a1fSgjelinek } 4634*ee519a1fSgjelinek 4635*ee519a1fSgjelinek /* 4636*ee519a1fSgjelinek * Read an entry from a pkginfo or contents file. Some of these lines can 4637*ee519a1fSgjelinek * either be arbitrarily long or be continued by a backslash at the end of 4638*ee519a1fSgjelinek * the line. This function coalesces lines that are longer than the read 4639*ee519a1fSgjelinek * buffer, and lines that are continued, into one buffer which is returned. 4640*ee519a1fSgjelinek * The caller must free this memory. NULL is returned when we hit EOF or 4641*ee519a1fSgjelinek * if we run out of memory (errno is set to ENOMEM). 4642*ee519a1fSgjelinek */ 4643*ee519a1fSgjelinek static char * 4644*ee519a1fSgjelinek read_pkg_data(FILE *fp) 4645*ee519a1fSgjelinek { 4646*ee519a1fSgjelinek char *start; 4647*ee519a1fSgjelinek char *inp; 4648*ee519a1fSgjelinek char *p; 4649*ee519a1fSgjelinek int char_cnt = 0; 4650*ee519a1fSgjelinek 4651*ee519a1fSgjelinek errno = 0; 4652*ee519a1fSgjelinek if ((start = (char *)malloc(PKGINFO_RD_LEN)) == NULL) { 4653*ee519a1fSgjelinek errno = ENOMEM; 4654*ee519a1fSgjelinek return (NULL); 4655*ee519a1fSgjelinek } 4656*ee519a1fSgjelinek 4657*ee519a1fSgjelinek inp = start; 4658*ee519a1fSgjelinek while ((p = fgets(inp, PKGINFO_RD_LEN, fp)) != NULL) { 4659*ee519a1fSgjelinek int len; 4660*ee519a1fSgjelinek 4661*ee519a1fSgjelinek len = strlen(inp); 4662*ee519a1fSgjelinek if (inp[len - 1] == '\n' && 4663*ee519a1fSgjelinek (len == 1 || inp[len - 2] != '\\')) { 4664*ee519a1fSgjelinek char_cnt = len; 4665*ee519a1fSgjelinek break; 4666*ee519a1fSgjelinek } 4667*ee519a1fSgjelinek 4668*ee519a1fSgjelinek if (inp[len - 2] == '\\') 4669*ee519a1fSgjelinek char_cnt += len - 2; 4670*ee519a1fSgjelinek else 4671*ee519a1fSgjelinek char_cnt += PKGINFO_RD_LEN - 1; 4672*ee519a1fSgjelinek 4673*ee519a1fSgjelinek if ((p = realloc(start, char_cnt + PKGINFO_RD_LEN)) == NULL) { 4674*ee519a1fSgjelinek errno = ENOMEM; 4675*ee519a1fSgjelinek break; 4676*ee519a1fSgjelinek } 4677*ee519a1fSgjelinek 4678*ee519a1fSgjelinek start = p; 4679*ee519a1fSgjelinek inp = start + char_cnt; 4680*ee519a1fSgjelinek } 4681*ee519a1fSgjelinek 4682*ee519a1fSgjelinek if (errno == ENOMEM || (p == NULL && char_cnt == 0)) { 4683*ee519a1fSgjelinek free(start); 4684*ee519a1fSgjelinek start = NULL; 4685*ee519a1fSgjelinek } 4686*ee519a1fSgjelinek 4687*ee519a1fSgjelinek return (start); 4688*ee519a1fSgjelinek } 4689*ee519a1fSgjelinek 4690*ee519a1fSgjelinek static void 4691*ee519a1fSgjelinek free_ipd_pkgs(char **pkgs, int cnt) 4692*ee519a1fSgjelinek { 4693*ee519a1fSgjelinek int i; 4694*ee519a1fSgjelinek 4695*ee519a1fSgjelinek for (i = 0; i < cnt; i++) 4696*ee519a1fSgjelinek free(pkgs[i]); 4697*ee519a1fSgjelinek free(pkgs); 4698*ee519a1fSgjelinek } 4699*ee519a1fSgjelinek 4700*ee519a1fSgjelinek /* 4701*ee519a1fSgjelinek * Get the list of inherited-pkg-dirs (ipd) for the zone and then get the 4702*ee519a1fSgjelinek * list of pkgs that deliver into those dirs. 4703*ee519a1fSgjelinek */ 4704*ee519a1fSgjelinek static int 4705*ee519a1fSgjelinek get_ipd_pkgs(zone_dochandle_t handle, char ***pkg_list, int *cnt) 4706*ee519a1fSgjelinek { 4707*ee519a1fSgjelinek int res; 4708*ee519a1fSgjelinek struct zone_fstab fstab; 4709*ee519a1fSgjelinek int ipd_cnt = 0; 4710*ee519a1fSgjelinek char **ipds = NULL; 4711*ee519a1fSgjelinek int pkg_cnt = 0; 4712*ee519a1fSgjelinek char **pkgs = NULL; 4713*ee519a1fSgjelinek int i; 4714*ee519a1fSgjelinek 4715*ee519a1fSgjelinek if ((res = zonecfg_setipdent(handle)) != Z_OK) 4716*ee519a1fSgjelinek return (res); 4717*ee519a1fSgjelinek 4718*ee519a1fSgjelinek while (zonecfg_getipdent(handle, &fstab) == Z_OK) { 4719*ee519a1fSgjelinek char **p; 4720*ee519a1fSgjelinek int len; 4721*ee519a1fSgjelinek 4722*ee519a1fSgjelinek if ((p = (char **)realloc(ipds, 4723*ee519a1fSgjelinek sizeof (char *) * (ipd_cnt + 2))) == NULL) { 4724*ee519a1fSgjelinek res = Z_NOMEM; 4725*ee519a1fSgjelinek break; 4726*ee519a1fSgjelinek } 4727*ee519a1fSgjelinek ipds = p; 4728*ee519a1fSgjelinek 4729*ee519a1fSgjelinek if ((ipds[ipd_cnt] = strdup(fstab.zone_fs_dir)) == NULL) { 4730*ee519a1fSgjelinek res = Z_NOMEM; 4731*ee519a1fSgjelinek break; 4732*ee519a1fSgjelinek } 4733*ee519a1fSgjelinek ipd_cnt++; 4734*ee519a1fSgjelinek 4735*ee519a1fSgjelinek len = strlen(fstab.zone_fs_dir) + 3; 4736*ee519a1fSgjelinek if ((ipds[ipd_cnt] = malloc(len)) == NULL) { 4737*ee519a1fSgjelinek res = Z_NOMEM; 4738*ee519a1fSgjelinek break; 4739*ee519a1fSgjelinek } 4740*ee519a1fSgjelinek 4741*ee519a1fSgjelinek (void) snprintf(ipds[ipd_cnt], len, "%s/*", fstab.zone_fs_dir); 4742*ee519a1fSgjelinek ipd_cnt++; 4743*ee519a1fSgjelinek } 4744*ee519a1fSgjelinek 4745*ee519a1fSgjelinek (void) zonecfg_endipdent(handle); 4746*ee519a1fSgjelinek 4747*ee519a1fSgjelinek if (res != Z_OK) { 4748*ee519a1fSgjelinek for (i = 0; i < ipd_cnt; i++) 4749*ee519a1fSgjelinek free(ipds[i]); 4750*ee519a1fSgjelinek free(ipds); 4751*ee519a1fSgjelinek return (res); 4752*ee519a1fSgjelinek } 4753*ee519a1fSgjelinek 4754*ee519a1fSgjelinek /* We only have to process the contents file if we have ipds. */ 4755*ee519a1fSgjelinek if (ipd_cnt > 0) { 4756*ee519a1fSgjelinek FILE *fp; 4757*ee519a1fSgjelinek 4758*ee519a1fSgjelinek if ((fp = fopen(CONTENTS_FILE, "r")) != NULL) { 4759*ee519a1fSgjelinek char *buf; 4760*ee519a1fSgjelinek 4761*ee519a1fSgjelinek while ((buf = read_pkg_data(fp)) != NULL) { 4762*ee519a1fSgjelinek res = get_path_pkgs(buf, ipds, ipd_cnt, &pkgs, 4763*ee519a1fSgjelinek &pkg_cnt); 4764*ee519a1fSgjelinek free(buf); 4765*ee519a1fSgjelinek if (res != Z_OK) 4766*ee519a1fSgjelinek break; 4767*ee519a1fSgjelinek } 4768*ee519a1fSgjelinek 4769*ee519a1fSgjelinek (void) fclose(fp); 4770*ee519a1fSgjelinek } 4771*ee519a1fSgjelinek } 4772*ee519a1fSgjelinek 4773*ee519a1fSgjelinek for (i = 0; i < ipd_cnt; i++) 4774*ee519a1fSgjelinek free(ipds[i]); 4775*ee519a1fSgjelinek free(ipds); 4776*ee519a1fSgjelinek 4777*ee519a1fSgjelinek if (res != Z_OK) { 4778*ee519a1fSgjelinek free_ipd_pkgs(pkgs, pkg_cnt); 4779*ee519a1fSgjelinek } else { 4780*ee519a1fSgjelinek *pkg_list = pkgs; 4781*ee519a1fSgjelinek *cnt = pkg_cnt; 4782*ee519a1fSgjelinek } 4783*ee519a1fSgjelinek 4784*ee519a1fSgjelinek return (res); 4785*ee519a1fSgjelinek } 4786*ee519a1fSgjelinek 4787*ee519a1fSgjelinek /* 4788*ee519a1fSgjelinek * Return true if pkg_name is in the list of pkgs that deliver into an 4789*ee519a1fSgjelinek * inherited pkg directory for the zone. 4790*ee519a1fSgjelinek */ 4791*ee519a1fSgjelinek static boolean_t 4792*ee519a1fSgjelinek dir_pkg(char *pkg_name, char **pkg_list, int cnt) 4793*ee519a1fSgjelinek { 4794*ee519a1fSgjelinek int i; 4795*ee519a1fSgjelinek 4796*ee519a1fSgjelinek for (i = 0; i < cnt; i++) { 4797*ee519a1fSgjelinek if (strcmp(pkg_name, pkg_list[i]) == 0) 4798*ee519a1fSgjelinek return (B_TRUE); 4799*ee519a1fSgjelinek } 4800*ee519a1fSgjelinek 4801*ee519a1fSgjelinek return (B_FALSE); 4802*ee519a1fSgjelinek } 4803*ee519a1fSgjelinek 4804*ee519a1fSgjelinek /* 4805*ee519a1fSgjelinek * Start by adding the patch to the sw inventory on the handle. 4806*ee519a1fSgjelinek * 4807*ee519a1fSgjelinek * The info parameter will be the portion of the PATCH_INFO_ entry following 4808*ee519a1fSgjelinek * the '='. For example: 4809*ee519a1fSgjelinek * Installed: Wed Dec 7 07:13:51 PST 2005 From: mum Obsoletes: 120777-03 \ 4810*ee519a1fSgjelinek * 121087-02 119108-07 Requires: 119575-02 119255-06 Incompatibles: 4811*ee519a1fSgjelinek * 4812*ee519a1fSgjelinek * We also want to add the Obsolete and Incompatible patches to the 4813*ee519a1fSgjelinek * sw inventory description of this patch. 4814*ee519a1fSgjelinek */ 4815*ee519a1fSgjelinek static int 4816*ee519a1fSgjelinek add_patch(zone_dochandle_t handle, char *patch, char *info) 4817*ee519a1fSgjelinek { 4818*ee519a1fSgjelinek xmlNodePtr node; 4819*ee519a1fSgjelinek xmlNodePtr cur; 4820*ee519a1fSgjelinek int err; 4821*ee519a1fSgjelinek char *p; 4822*ee519a1fSgjelinek char *lastp; 4823*ee519a1fSgjelinek boolean_t add_info = B_FALSE; 4824*ee519a1fSgjelinek boolean_t obsolete; 4825*ee519a1fSgjelinek 4826*ee519a1fSgjelinek if ((err = operation_prep(handle)) != Z_OK) 4827*ee519a1fSgjelinek return (err); 4828*ee519a1fSgjelinek 4829*ee519a1fSgjelinek cur = handle->zone_dh_cur; 4830*ee519a1fSgjelinek node = xmlNewTextChild(cur, NULL, DTD_ELEM_PATCH, NULL); 4831*ee519a1fSgjelinek if ((err = newprop(node, DTD_ATTR_ID, patch)) != Z_OK) 4832*ee519a1fSgjelinek return (err); 4833*ee519a1fSgjelinek 4834*ee519a1fSgjelinek /* 4835*ee519a1fSgjelinek * Start with the first token. This will probably be "Installed:". 4836*ee519a1fSgjelinek * If we can't tokenize this entry, just return. 4837*ee519a1fSgjelinek */ 4838*ee519a1fSgjelinek if ((p = strtok_r(info, " ", &lastp)) == NULL) 4839*ee519a1fSgjelinek return (Z_OK); 4840*ee519a1fSgjelinek 4841*ee519a1fSgjelinek do { 4842*ee519a1fSgjelinek xmlNodePtr new_node; 4843*ee519a1fSgjelinek char *nlp; 4844*ee519a1fSgjelinek 4845*ee519a1fSgjelinek if (strcmp(p, "Installed:") == 0 || 4846*ee519a1fSgjelinek strcmp(p, "Requires:") == 0 || 4847*ee519a1fSgjelinek strcmp(p, "From:") == 0) { 4848*ee519a1fSgjelinek add_info = B_FALSE; 4849*ee519a1fSgjelinek continue; 4850*ee519a1fSgjelinek } else if (strcmp(p, "Obsoletes:") == 0) { 4851*ee519a1fSgjelinek obsolete = B_TRUE; 4852*ee519a1fSgjelinek add_info = B_TRUE; 4853*ee519a1fSgjelinek continue; 4854*ee519a1fSgjelinek } else if (strcmp(p, "Incompatibles:") == 0) { 4855*ee519a1fSgjelinek obsolete = B_FALSE; 4856*ee519a1fSgjelinek add_info = B_TRUE; 4857*ee519a1fSgjelinek continue; 4858*ee519a1fSgjelinek } 4859*ee519a1fSgjelinek 4860*ee519a1fSgjelinek if (!add_info) 4861*ee519a1fSgjelinek continue; 4862*ee519a1fSgjelinek 4863*ee519a1fSgjelinek /* strip newline from last patch in the line */ 4864*ee519a1fSgjelinek nlp = (p + strlen(p) - 1); 4865*ee519a1fSgjelinek if (*nlp == '\n') 4866*ee519a1fSgjelinek *nlp = '\0'; 4867*ee519a1fSgjelinek 4868*ee519a1fSgjelinek if (obsolete) 4869*ee519a1fSgjelinek new_node = xmlNewTextChild(node, NULL, 4870*ee519a1fSgjelinek DTD_ELEM_OBSOLETES, NULL); 4871*ee519a1fSgjelinek else 4872*ee519a1fSgjelinek new_node = xmlNewTextChild(node, NULL, 4873*ee519a1fSgjelinek DTD_ELEM_INCOMPATIBLE, NULL); 4874*ee519a1fSgjelinek 4875*ee519a1fSgjelinek if ((err = newprop(new_node, DTD_ATTR_ID, p)) != Z_OK) 4876*ee519a1fSgjelinek return (err); 4877*ee519a1fSgjelinek 4878*ee519a1fSgjelinek } while ((p = strtok_r(NULL, " ", &lastp)) != NULL); 4879*ee519a1fSgjelinek 4880*ee519a1fSgjelinek return (Z_OK); 4881*ee519a1fSgjelinek } 4882*ee519a1fSgjelinek 4883*ee519a1fSgjelinek static boolean_t 4884*ee519a1fSgjelinek unique_patch(zone_dochandle_t handle, char *patch) 4885*ee519a1fSgjelinek { 4886*ee519a1fSgjelinek xmlNodePtr cur; 4887*ee519a1fSgjelinek char id[MAXNAMELEN]; 4888*ee519a1fSgjelinek 4889*ee519a1fSgjelinek cur = xmlDocGetRootElement(handle->zone_dh_doc); 4890*ee519a1fSgjelinek for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 4891*ee519a1fSgjelinek if (xmlStrcmp(cur->name, DTD_ELEM_PATCH) == 0) { 4892*ee519a1fSgjelinek if (fetchprop(cur, DTD_ATTR_ID, id, sizeof (id)) 4893*ee519a1fSgjelinek != Z_OK) 4894*ee519a1fSgjelinek continue; 4895*ee519a1fSgjelinek 4896*ee519a1fSgjelinek if (strcmp(patch, id) == 0) 4897*ee519a1fSgjelinek return (B_FALSE); 4898*ee519a1fSgjelinek } 4899*ee519a1fSgjelinek } 4900*ee519a1fSgjelinek 4901*ee519a1fSgjelinek return (B_TRUE); 4902*ee519a1fSgjelinek } 4903*ee519a1fSgjelinek 4904*ee519a1fSgjelinek /* 4905*ee519a1fSgjelinek * Add the unique patches associated with this pkg to the sw inventory on the 4906*ee519a1fSgjelinek * handle. 4907*ee519a1fSgjelinek * 4908*ee519a1fSgjelinek * We are processing entries of the form: 4909*ee519a1fSgjelinek * PATCH_INFO_121454-02=Installed: Wed Dec 7 07:13:51 PST 2005 From: mum \ 4910*ee519a1fSgjelinek * Obsoletes: 120777-03 121087-02 119108-07 Requires: 119575-02 \ 4911*ee519a1fSgjelinek * 119255-06 Incompatibles: 4912*ee519a1fSgjelinek * 4913*ee519a1fSgjelinek */ 4914*ee519a1fSgjelinek static int 4915*ee519a1fSgjelinek add_patches(zone_dochandle_t handle, struct zone_pkginfo *infop) 4916*ee519a1fSgjelinek { 4917*ee519a1fSgjelinek int i; 4918*ee519a1fSgjelinek int res = Z_OK; 4919*ee519a1fSgjelinek 4920*ee519a1fSgjelinek for (i = 0; i < infop->zpi_patch_cnt; i++) { 4921*ee519a1fSgjelinek char *p, *ep; 4922*ee519a1fSgjelinek 4923*ee519a1fSgjelinek if (strlen(infop->zpi_patchinfo[i]) < (sizeof (PATCHINFO) - 1)) 4924*ee519a1fSgjelinek continue; 4925*ee519a1fSgjelinek 4926*ee519a1fSgjelinek /* Skip over "PATCH_INFO_" to get the patch id. */ 4927*ee519a1fSgjelinek p = infop->zpi_patchinfo[i] + sizeof (PATCHINFO) - 1; 4928*ee519a1fSgjelinek if ((ep = strchr(p, '=')) == NULL) 4929*ee519a1fSgjelinek continue; 4930*ee519a1fSgjelinek 4931*ee519a1fSgjelinek *ep = '\0'; 4932*ee519a1fSgjelinek if (unique_patch(handle, p)) 4933*ee519a1fSgjelinek res = add_patch(handle, p, ep + 1); 4934*ee519a1fSgjelinek } 4935*ee519a1fSgjelinek 4936*ee519a1fSgjelinek return (res); 4937*ee519a1fSgjelinek } 4938*ee519a1fSgjelinek 4939*ee519a1fSgjelinek /* 4940*ee519a1fSgjelinek * Add the pkg to the sw inventory on the handle. 4941*ee519a1fSgjelinek */ 4942*ee519a1fSgjelinek static int 4943*ee519a1fSgjelinek add_pkg(zone_dochandle_t handle, char *name, char *version) 4944*ee519a1fSgjelinek { 4945*ee519a1fSgjelinek xmlNodePtr newnode; 4946*ee519a1fSgjelinek xmlNodePtr cur; 4947*ee519a1fSgjelinek int err; 4948*ee519a1fSgjelinek 4949*ee519a1fSgjelinek if ((err = operation_prep(handle)) != Z_OK) 4950*ee519a1fSgjelinek return (err); 4951*ee519a1fSgjelinek 4952*ee519a1fSgjelinek cur = handle->zone_dh_cur; 4953*ee519a1fSgjelinek newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_PACKAGE, NULL); 4954*ee519a1fSgjelinek if ((err = newprop(newnode, DTD_ATTR_NAME, name)) != Z_OK) 4955*ee519a1fSgjelinek return (err); 4956*ee519a1fSgjelinek if ((err = newprop(newnode, DTD_ATTR_VERSION, version)) != Z_OK) 4957*ee519a1fSgjelinek return (err); 4958*ee519a1fSgjelinek return (Z_OK); 4959*ee519a1fSgjelinek } 4960*ee519a1fSgjelinek 4961*ee519a1fSgjelinek static void 4962*ee519a1fSgjelinek free_pkginfo(struct zone_pkginfo *infop) 4963*ee519a1fSgjelinek { 4964*ee519a1fSgjelinek free(infop->zpi_version); 4965*ee519a1fSgjelinek if (infop->zpi_patch_cnt > 0) { 4966*ee519a1fSgjelinek int i; 4967*ee519a1fSgjelinek 4968*ee519a1fSgjelinek for (i = 0; i < infop->zpi_patch_cnt; i++) 4969*ee519a1fSgjelinek free(infop->zpi_patchinfo[i]); 4970*ee519a1fSgjelinek free(infop->zpi_patchinfo); 4971*ee519a1fSgjelinek } 4972*ee519a1fSgjelinek } 4973*ee519a1fSgjelinek 4974*ee519a1fSgjelinek /* 4975*ee519a1fSgjelinek * Read the pkginfo file and populate the structure with the data we need 4976*ee519a1fSgjelinek * from this pkg for a sw inventory. 4977*ee519a1fSgjelinek */ 4978*ee519a1fSgjelinek static int 4979*ee519a1fSgjelinek get_pkginfo(char *pkginfo, struct zone_pkginfo *infop) 4980*ee519a1fSgjelinek { 4981*ee519a1fSgjelinek FILE *fp; 4982*ee519a1fSgjelinek char *buf; 4983*ee519a1fSgjelinek int err = 0; 4984*ee519a1fSgjelinek 4985*ee519a1fSgjelinek infop->zpi_all_zones = B_FALSE; 4986*ee519a1fSgjelinek infop->zpi_this_zone = B_FALSE; 4987*ee519a1fSgjelinek infop->zpi_version = NULL; 4988*ee519a1fSgjelinek infop->zpi_patch_cnt = 0; 4989*ee519a1fSgjelinek infop->zpi_patchinfo = NULL; 4990*ee519a1fSgjelinek 4991*ee519a1fSgjelinek if ((fp = fopen(pkginfo, "r")) == NULL) 4992*ee519a1fSgjelinek return (errno); 4993*ee519a1fSgjelinek 4994*ee519a1fSgjelinek while ((buf = read_pkg_data(fp)) != NULL) { 4995*ee519a1fSgjelinek if (strncmp(buf, VERSION, sizeof (VERSION) - 1) == 0) { 4996*ee519a1fSgjelinek int len; 4997*ee519a1fSgjelinek 4998*ee519a1fSgjelinek if ((infop->zpi_version = 4999*ee519a1fSgjelinek strdup(buf + sizeof (VERSION) - 1)) == NULL) { 5000*ee519a1fSgjelinek err = ENOMEM; 5001*ee519a1fSgjelinek break; 5002*ee519a1fSgjelinek } 5003*ee519a1fSgjelinek 5004*ee519a1fSgjelinek /* remove trailing newline */ 5005*ee519a1fSgjelinek len = strlen(infop->zpi_version); 5006*ee519a1fSgjelinek *(infop->zpi_version + len - 1) = 0; 5007*ee519a1fSgjelinek 5008*ee519a1fSgjelinek } else if (strcmp(buf, ALL_ZONES) == 0) { 5009*ee519a1fSgjelinek infop->zpi_all_zones = B_TRUE; 5010*ee519a1fSgjelinek 5011*ee519a1fSgjelinek } else if (strcmp(buf, THIS_ZONE) == 0) { 5012*ee519a1fSgjelinek infop->zpi_this_zone = B_TRUE; 5013*ee519a1fSgjelinek 5014*ee519a1fSgjelinek } else if (strncmp(buf, PATCHINFO, sizeof (PATCHINFO) - 1) 5015*ee519a1fSgjelinek == 0) { 5016*ee519a1fSgjelinek char **p; 5017*ee519a1fSgjelinek 5018*ee519a1fSgjelinek if ((p = (char **)realloc(infop->zpi_patchinfo, 5019*ee519a1fSgjelinek sizeof (char *) * (infop->zpi_patch_cnt + 1))) 5020*ee519a1fSgjelinek == NULL) { 5021*ee519a1fSgjelinek err = ENOMEM; 5022*ee519a1fSgjelinek break; 5023*ee519a1fSgjelinek } 5024*ee519a1fSgjelinek infop->zpi_patchinfo = p; 5025*ee519a1fSgjelinek 5026*ee519a1fSgjelinek if ((infop->zpi_patchinfo[infop->zpi_patch_cnt] = 5027*ee519a1fSgjelinek strdup(buf)) == NULL) { 5028*ee519a1fSgjelinek err = ENOMEM; 5029*ee519a1fSgjelinek break; 5030*ee519a1fSgjelinek } 5031*ee519a1fSgjelinek infop->zpi_patch_cnt++; 5032*ee519a1fSgjelinek } 5033*ee519a1fSgjelinek 5034*ee519a1fSgjelinek free(buf); 5035*ee519a1fSgjelinek } 5036*ee519a1fSgjelinek 5037*ee519a1fSgjelinek free(buf); 5038*ee519a1fSgjelinek 5039*ee519a1fSgjelinek if (errno == ENOMEM) { 5040*ee519a1fSgjelinek err = ENOMEM; 5041*ee519a1fSgjelinek /* Clean up anything we did manage to allocate. */ 5042*ee519a1fSgjelinek free_pkginfo(infop); 5043*ee519a1fSgjelinek } 5044*ee519a1fSgjelinek 5045*ee519a1fSgjelinek (void) fclose(fp); 5046*ee519a1fSgjelinek 5047*ee519a1fSgjelinek return (err); 5048*ee519a1fSgjelinek } 5049*ee519a1fSgjelinek 5050*ee519a1fSgjelinek /* 5051*ee519a1fSgjelinek * Take a software inventory of the global zone. We need to get the set of 5052*ee519a1fSgjelinek * packages and patches that are on the global zone that the specified 5053*ee519a1fSgjelinek * non-global zone depends on. The packages we need in the inventory are: 5054*ee519a1fSgjelinek * 5055*ee519a1fSgjelinek * - skip the package if SUNW_PKG_THISZONE is 'true' 5056*ee519a1fSgjelinek * otherwise, 5057*ee519a1fSgjelinek * - add the package if 5058*ee519a1fSgjelinek * a) SUNW_PKG_ALLZONES is 'true', 5059*ee519a1fSgjelinek * or 5060*ee519a1fSgjelinek * b) any file delivered by the package is in a file system that is inherited 5061*ee519a1fSgjelinek * from the global zone. 5062*ee519a1fSgjelinek * If the zone does not inherit any file systems (whole root) 5063*ee519a1fSgjelinek * then (b) will be skipped. 5064*ee519a1fSgjelinek * 5065*ee519a1fSgjelinek * For each of the packages that is being added to the inventory, we will also 5066*ee519a1fSgjelinek * add all of the associated, unique patches to the inventory. 5067*ee519a1fSgjelinek */ 5068*ee519a1fSgjelinek static int 5069*ee519a1fSgjelinek zonecfg_sw_inventory(zone_dochandle_t handle) 5070*ee519a1fSgjelinek { 5071*ee519a1fSgjelinek char pkginfo[MAXPATHLEN]; 5072*ee519a1fSgjelinek int res; 5073*ee519a1fSgjelinek struct dirent *dp; 5074*ee519a1fSgjelinek DIR *dirp; 5075*ee519a1fSgjelinek struct stat buf; 5076*ee519a1fSgjelinek struct zone_pkginfo info; 5077*ee519a1fSgjelinek int pkg_cnt = 0; 5078*ee519a1fSgjelinek char **pkgs = NULL; 5079*ee519a1fSgjelinek 5080*ee519a1fSgjelinek if ((res = get_ipd_pkgs(handle, &pkgs, &pkg_cnt)) != Z_OK) 5081*ee519a1fSgjelinek return (res); 5082*ee519a1fSgjelinek 5083*ee519a1fSgjelinek if ((dirp = opendir(PKG_PATH)) == NULL) { 5084*ee519a1fSgjelinek free_ipd_pkgs(pkgs, pkg_cnt); 5085*ee519a1fSgjelinek return (Z_OK); 5086*ee519a1fSgjelinek } 5087*ee519a1fSgjelinek 5088*ee519a1fSgjelinek while ((dp = readdir(dirp)) != (struct dirent *)0) { 5089*ee519a1fSgjelinek if (strcmp(dp->d_name, ".") == 0 || 5090*ee519a1fSgjelinek strcmp(dp->d_name, "..") == 0) 5091*ee519a1fSgjelinek continue; 5092*ee519a1fSgjelinek 5093*ee519a1fSgjelinek (void) snprintf(pkginfo, sizeof (pkginfo), "%s/%s/pkginfo", 5094*ee519a1fSgjelinek PKG_PATH, dp->d_name); 5095*ee519a1fSgjelinek 5096*ee519a1fSgjelinek if (stat(pkginfo, &buf) == -1 || !S_ISREG(buf.st_mode)) 5097*ee519a1fSgjelinek continue; 5098*ee519a1fSgjelinek 5099*ee519a1fSgjelinek if (get_pkginfo(pkginfo, &info) != 0) { 5100*ee519a1fSgjelinek res = Z_NOMEM; 5101*ee519a1fSgjelinek break; 5102*ee519a1fSgjelinek } 5103*ee519a1fSgjelinek 5104*ee519a1fSgjelinek if (!info.zpi_this_zone && 5105*ee519a1fSgjelinek (info.zpi_all_zones || 5106*ee519a1fSgjelinek dir_pkg(dp->d_name, pkgs, pkg_cnt))) { 5107*ee519a1fSgjelinek if ((res = add_pkg(handle, dp->d_name, 5108*ee519a1fSgjelinek info.zpi_version)) == Z_OK) { 5109*ee519a1fSgjelinek if (info.zpi_patch_cnt > 0) 5110*ee519a1fSgjelinek res = add_patches(handle, &info); 5111*ee519a1fSgjelinek } 5112*ee519a1fSgjelinek } 5113*ee519a1fSgjelinek 5114*ee519a1fSgjelinek free_pkginfo(&info); 5115*ee519a1fSgjelinek 5116*ee519a1fSgjelinek if (res != Z_OK) 5117*ee519a1fSgjelinek break; 5118*ee519a1fSgjelinek } 5119*ee519a1fSgjelinek 5120*ee519a1fSgjelinek (void) closedir(dirp); 5121*ee519a1fSgjelinek 5122*ee519a1fSgjelinek free_ipd_pkgs(pkgs, pkg_cnt); 5123*ee519a1fSgjelinek 5124*ee519a1fSgjelinek if (res == Z_OK) 5125*ee519a1fSgjelinek handle->zone_dh_sw_inv = B_TRUE; 5126*ee519a1fSgjelinek 5127*ee519a1fSgjelinek return (res); 5128*ee519a1fSgjelinek } 5129*ee519a1fSgjelinek 5130*ee519a1fSgjelinek /* 5131*ee519a1fSgjelinek * zonecfg_devwalk call-back function used during detach to generate the 5132*ee519a1fSgjelinek * dev info in the manifest. 5133*ee519a1fSgjelinek */ 5134*ee519a1fSgjelinek static int 5135*ee519a1fSgjelinek get_detach_dev_entry(const char *name, uid_t uid, gid_t gid, mode_t mode, 5136*ee519a1fSgjelinek const char *acl, void *hdl) 5137*ee519a1fSgjelinek { 5138*ee519a1fSgjelinek zone_dochandle_t handle = (zone_dochandle_t)hdl; 5139*ee519a1fSgjelinek xmlNodePtr newnode; 5140*ee519a1fSgjelinek xmlNodePtr cur; 5141*ee519a1fSgjelinek int err; 5142*ee519a1fSgjelinek char buf[128]; 5143*ee519a1fSgjelinek 5144*ee519a1fSgjelinek if ((err = operation_prep(handle)) != Z_OK) 5145*ee519a1fSgjelinek return (err); 5146*ee519a1fSgjelinek 5147*ee519a1fSgjelinek cur = handle->zone_dh_cur; 5148*ee519a1fSgjelinek newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_DEV_PERM, NULL); 5149*ee519a1fSgjelinek if ((err = newprop(newnode, DTD_ATTR_NAME, (char *)name)) != Z_OK) 5150*ee519a1fSgjelinek return (err); 5151*ee519a1fSgjelinek (void) snprintf(buf, sizeof (buf), "%lu", uid); 5152*ee519a1fSgjelinek if ((err = newprop(newnode, DTD_ATTR_UID, buf)) != Z_OK) 5153*ee519a1fSgjelinek return (err); 5154*ee519a1fSgjelinek (void) snprintf(buf, sizeof (buf), "%lu", gid); 5155*ee519a1fSgjelinek if ((err = newprop(newnode, DTD_ATTR_GID, buf)) != Z_OK) 5156*ee519a1fSgjelinek return (err); 5157*ee519a1fSgjelinek (void) snprintf(buf, sizeof (buf), "%o", mode); 5158*ee519a1fSgjelinek if ((err = newprop(newnode, DTD_ATTR_MODE, buf)) != Z_OK) 5159*ee519a1fSgjelinek return (err); 5160*ee519a1fSgjelinek if ((err = newprop(newnode, DTD_ATTR_ACL, (char *)acl)) != Z_OK) 5161*ee519a1fSgjelinek return (err); 5162*ee519a1fSgjelinek return (Z_OK); 5163*ee519a1fSgjelinek } 5164*ee519a1fSgjelinek 5165*ee519a1fSgjelinek /* 5166*ee519a1fSgjelinek * Get the information required to support detaching a zone. This is 5167*ee519a1fSgjelinek * called on the source system when detaching (the detaching parameter should 5168*ee519a1fSgjelinek * be set to true) and on the destination system before attaching (the 5169*ee519a1fSgjelinek * detaching parameter should be false). 5170*ee519a1fSgjelinek * 5171*ee519a1fSgjelinek * For native Solaris zones, the detach/attach process involves validating 5172*ee519a1fSgjelinek * that the software on the global zone can support the zone when we attach. 5173*ee519a1fSgjelinek * To do this we take a software inventory of the global zone. We also 5174*ee519a1fSgjelinek * have to keep track of the device configuration so that we can properly 5175*ee519a1fSgjelinek * recreate it on the destination. 5176*ee519a1fSgjelinek */ 5177*ee519a1fSgjelinek int 5178*ee519a1fSgjelinek zonecfg_get_detach_info(zone_dochandle_t handle, boolean_t detaching) 5179*ee519a1fSgjelinek { 5180*ee519a1fSgjelinek int res; 5181*ee519a1fSgjelinek 5182*ee519a1fSgjelinek if ((res = zonecfg_sw_inventory(handle)) != Z_OK) 5183*ee519a1fSgjelinek return (res); 5184*ee519a1fSgjelinek 5185*ee519a1fSgjelinek if (detaching) 5186*ee519a1fSgjelinek res = zonecfg_devwalk(handle, get_detach_dev_entry, handle); 5187*ee519a1fSgjelinek 5188*ee519a1fSgjelinek return (res); 5189*ee519a1fSgjelinek } 5190