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 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 237c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 29*cf8f45c7Sdstaff #include <libsysevent.h> 30*cf8f45c7Sdstaff #include <pthread.h> 31*cf8f45c7Sdstaff #include <stdlib.h> 327c478bd9Sstevel@tonic-gate #include <errno.h> 337c478bd9Sstevel@tonic-gate #include <fnmatch.h> 347c478bd9Sstevel@tonic-gate #include <strings.h> 357c478bd9Sstevel@tonic-gate #include <unistd.h> 367c478bd9Sstevel@tonic-gate #include <sys/stat.h> 377c478bd9Sstevel@tonic-gate #include <assert.h> 387c478bd9Sstevel@tonic-gate #include <libgen.h> 397c478bd9Sstevel@tonic-gate #include <libintl.h> 407c478bd9Sstevel@tonic-gate #include <alloca.h> 417c478bd9Sstevel@tonic-gate #include <ctype.h> 427c478bd9Sstevel@tonic-gate #include <sys/mntio.h> 437c478bd9Sstevel@tonic-gate #include <sys/mnttab.h> 44087719fdSdp #include <sys/types.h> 45*cf8f45c7Sdstaff #include <sys/nvpair.h> 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 487c478bd9Sstevel@tonic-gate #include <netdb.h> 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate #include <priv.h> 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate #include <libxml/xmlmemory.h> 537c478bd9Sstevel@tonic-gate #include <libxml/parser.h> 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate #include <libdevinfo.h> 56108322fbScarlsonj #include <uuid/uuid.h> 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate #include <libzonecfg.h> 597c478bd9Sstevel@tonic-gate #include "zonecfg_impl.h" 607c478bd9Sstevel@tonic-gate 61*cf8f45c7Sdstaff 627c478bd9Sstevel@tonic-gate #define _PATH_TMPFILE "/zonecfg.XXXXXX" 63*cf8f45c7Sdstaff #define ZONE_CB_RETRY_COUNT 10 64*cf8f45c7Sdstaff #define ZONE_EVENT_PING_SUBCLASS "ping" 65*cf8f45c7Sdstaff #define ZONE_EVENT_PING_PUBLISHER "solaris" 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate /* Hard-code the DTD element/attribute/entity names just once, here. */ 687c478bd9Sstevel@tonic-gate #define DTD_ELEM_ATTR (const xmlChar *) "attr" 697c478bd9Sstevel@tonic-gate #define DTD_ELEM_COMMENT (const xmlChar *) "comment" 707c478bd9Sstevel@tonic-gate #define DTD_ELEM_DEVICE (const xmlChar *) "device" 717c478bd9Sstevel@tonic-gate #define DTD_ELEM_FS (const xmlChar *) "filesystem" 727c478bd9Sstevel@tonic-gate #define DTD_ELEM_FSOPTION (const xmlChar *) "fsoption" 737c478bd9Sstevel@tonic-gate #define DTD_ELEM_IPD (const xmlChar *) "inherited-pkg-dir" 747c478bd9Sstevel@tonic-gate #define DTD_ELEM_NET (const xmlChar *) "network" 757c478bd9Sstevel@tonic-gate #define DTD_ELEM_RCTL (const xmlChar *) "rctl" 767c478bd9Sstevel@tonic-gate #define DTD_ELEM_RCTLVALUE (const xmlChar *) "rctl-value" 777c478bd9Sstevel@tonic-gate #define DTD_ELEM_ZONE (const xmlChar *) "zone" 78fa9e4066Sahrens #define DTD_ELEM_DATASET (const xmlChar *) "dataset" 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate #define DTD_ATTR_ACTION (const xmlChar *) "action" 817c478bd9Sstevel@tonic-gate #define DTD_ATTR_ADDRESS (const xmlChar *) "address" 827c478bd9Sstevel@tonic-gate #define DTD_ATTR_AUTOBOOT (const xmlChar *) "autoboot" 837c478bd9Sstevel@tonic-gate #define DTD_ATTR_DIR (const xmlChar *) "directory" 847c478bd9Sstevel@tonic-gate #define DTD_ATTR_LIMIT (const xmlChar *) "limit" 857c478bd9Sstevel@tonic-gate #define DTD_ATTR_MATCH (const xmlChar *) "match" 867c478bd9Sstevel@tonic-gate #define DTD_ATTR_NAME (const xmlChar *) "name" 877c478bd9Sstevel@tonic-gate #define DTD_ATTR_PHYSICAL (const xmlChar *) "physical" 887c478bd9Sstevel@tonic-gate #define DTD_ATTR_POOL (const xmlChar *) "pool" 897c478bd9Sstevel@tonic-gate #define DTD_ATTR_PRIV (const xmlChar *) "priv" 907c478bd9Sstevel@tonic-gate #define DTD_ATTR_RAW (const xmlChar *) "raw" 917c478bd9Sstevel@tonic-gate #define DTD_ATTR_SPECIAL (const xmlChar *) "special" 927c478bd9Sstevel@tonic-gate #define DTD_ATTR_TYPE (const xmlChar *) "type" 937c478bd9Sstevel@tonic-gate #define DTD_ATTR_VALUE (const xmlChar *) "value" 947c478bd9Sstevel@tonic-gate #define DTD_ATTR_ZONEPATH (const xmlChar *) "zonepath" 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate #define DTD_ENTITY_BOOLEAN "boolean" 977c478bd9Sstevel@tonic-gate #define DTD_ENTITY_DEVPATH "devpath" 987c478bd9Sstevel@tonic-gate #define DTD_ENTITY_DRIVER "driver" 997c478bd9Sstevel@tonic-gate #define DTD_ENTITY_DRVMIN "drv_min" 1007c478bd9Sstevel@tonic-gate #define DTD_ENTITY_FALSE "false" 1017c478bd9Sstevel@tonic-gate #define DTD_ENTITY_INT "int" 1027c478bd9Sstevel@tonic-gate #define DTD_ENTITY_STRING "string" 1037c478bd9Sstevel@tonic-gate #define DTD_ENTITY_TRUE "true" 1047c478bd9Sstevel@tonic-gate #define DTD_ENTITY_UINT "uint" 1057c478bd9Sstevel@tonic-gate 106a1be23daSdp #define DTD_ENTITY_BOOL_LEN 6 /* "false" */ 107a1be23daSdp 1087c478bd9Sstevel@tonic-gate struct zone_dochandle { 1097c478bd9Sstevel@tonic-gate char *zone_dh_rootdir; 1107c478bd9Sstevel@tonic-gate xmlDocPtr zone_dh_doc; 1117c478bd9Sstevel@tonic-gate xmlNodePtr zone_dh_cur; 1127c478bd9Sstevel@tonic-gate xmlNodePtr zone_dh_top; 113087719fdSdp boolean_t zone_dh_newzone; 114087719fdSdp boolean_t zone_dh_snapshot; 115087719fdSdp char zone_dh_delete_name[ZONENAME_MAX]; 1167c478bd9Sstevel@tonic-gate }; 1177c478bd9Sstevel@tonic-gate 118*cf8f45c7Sdstaff struct znotify { 119*cf8f45c7Sdstaff void * zn_private; 120*cf8f45c7Sdstaff evchan_t *zn_eventchan; 121*cf8f45c7Sdstaff int (*zn_callback)(const char *zonename, zoneid_t zid, 122*cf8f45c7Sdstaff const char *newstate, const char *oldstate, hrtime_t when, void *p); 123*cf8f45c7Sdstaff pthread_mutex_t zn_mutex; 124*cf8f45c7Sdstaff pthread_cond_t zn_cond; 125*cf8f45c7Sdstaff pthread_mutex_t zn_bigmutex; 126*cf8f45c7Sdstaff volatile enum {ZN_UNLOCKED, ZN_LOCKED, ZN_PING_INFLIGHT, 127*cf8f45c7Sdstaff ZN_PING_RECEIVED} zn_state; 128*cf8f45c7Sdstaff char zn_subscriber_id[MAX_SUBID_LEN]; 129*cf8f45c7Sdstaff volatile boolean_t zn_failed; 130*cf8f45c7Sdstaff int zn_failure_count; 131*cf8f45c7Sdstaff }; 132*cf8f45c7Sdstaff 133108322fbScarlsonj char *zonecfg_root = ""; 134108322fbScarlsonj 1357c478bd9Sstevel@tonic-gate /* 1367c478bd9Sstevel@tonic-gate * For functions which return int, which is most of the functions herein, 1377c478bd9Sstevel@tonic-gate * the return values should be from the Z_foo set defined in <libzonecfg.h>. 1387c478bd9Sstevel@tonic-gate * In some instances, we take pains mapping some libc errno values to Z_foo 1397c478bd9Sstevel@tonic-gate * values from this set. 1407c478bd9Sstevel@tonic-gate */ 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate /* 143108322fbScarlsonj * Set the root (/) path for all zonecfg configuration files. This is a 144108322fbScarlsonj * private interface used by Live Upgrade extensions to access zone 145108322fbScarlsonj * configuration inside mounted alternate boot environments. 146108322fbScarlsonj */ 147108322fbScarlsonj void 148108322fbScarlsonj zonecfg_set_root(const char *rootpath) 149108322fbScarlsonj { 150108322fbScarlsonj if (*zonecfg_root != '\0') 151108322fbScarlsonj free(zonecfg_root); 152108322fbScarlsonj if (rootpath == NULL || rootpath[0] == '\0' || rootpath[1] == '\0' || 153108322fbScarlsonj (zonecfg_root = strdup(rootpath)) == NULL) 154108322fbScarlsonj zonecfg_root = ""; 155108322fbScarlsonj } 156108322fbScarlsonj 157108322fbScarlsonj const char * 158108322fbScarlsonj zonecfg_get_root(void) 159108322fbScarlsonj { 160108322fbScarlsonj return (zonecfg_root); 161108322fbScarlsonj } 162108322fbScarlsonj 163108322fbScarlsonj boolean_t 164108322fbScarlsonj zonecfg_in_alt_root(void) 165108322fbScarlsonj { 166108322fbScarlsonj return (*zonecfg_root != '\0'); 167108322fbScarlsonj } 168108322fbScarlsonj 169108322fbScarlsonj /* 1707c478bd9Sstevel@tonic-gate * Callers of the _file_path() functions are expected to have the second 1717c478bd9Sstevel@tonic-gate * parameter be a (char foo[MAXPATHLEN]). 1727c478bd9Sstevel@tonic-gate */ 1737c478bd9Sstevel@tonic-gate 174108322fbScarlsonj static boolean_t 1757c478bd9Sstevel@tonic-gate config_file_path(const char *zonename, char *answer) 1767c478bd9Sstevel@tonic-gate { 177108322fbScarlsonj return (snprintf(answer, MAXPATHLEN, "%s%s/%s.xml", zonecfg_root, 178108322fbScarlsonj ZONE_CONFIG_ROOT, zonename) < MAXPATHLEN); 1797c478bd9Sstevel@tonic-gate } 1807c478bd9Sstevel@tonic-gate 181108322fbScarlsonj static boolean_t 182108322fbScarlsonj snap_file_path(const char *zonename, char *answer) 1837c478bd9Sstevel@tonic-gate { 184108322fbScarlsonj return (snprintf(answer, MAXPATHLEN, "%s%s/%s.snapshot.xml", 185108322fbScarlsonj zonecfg_root, ZONE_SNAPSHOT_ROOT, zonename) < MAXPATHLEN); 1867c478bd9Sstevel@tonic-gate } 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1897c478bd9Sstevel@tonic-gate static void 1907c478bd9Sstevel@tonic-gate zonecfg_error_func(void *ctx, const char *msg, ...) 1917c478bd9Sstevel@tonic-gate { 1927c478bd9Sstevel@tonic-gate /* 1937c478bd9Sstevel@tonic-gate * This function does nothing by design. Its purpose is to prevent 1947c478bd9Sstevel@tonic-gate * libxml from dumping unwanted messages to stdout/stderr. 1957c478bd9Sstevel@tonic-gate */ 1967c478bd9Sstevel@tonic-gate } 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate zone_dochandle_t 1997c478bd9Sstevel@tonic-gate zonecfg_init_handle(void) 2007c478bd9Sstevel@tonic-gate { 201087719fdSdp zone_dochandle_t handle = calloc(1, sizeof (struct zone_dochandle)); 2027c478bd9Sstevel@tonic-gate if (handle == NULL) { 2037c478bd9Sstevel@tonic-gate errno = Z_NOMEM; 2047c478bd9Sstevel@tonic-gate return (NULL); 2057c478bd9Sstevel@tonic-gate } 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate /* generic libxml initialization */ 2087c478bd9Sstevel@tonic-gate xmlLineNumbersDefault(1); 2097c478bd9Sstevel@tonic-gate xmlLoadExtDtdDefaultValue |= XML_DETECT_IDS; 2107c478bd9Sstevel@tonic-gate xmlDoValidityCheckingDefaultValue = 1; 2117c478bd9Sstevel@tonic-gate (void) xmlKeepBlanksDefault(0); 2127c478bd9Sstevel@tonic-gate xmlGetWarningsDefaultValue = 0; 2137c478bd9Sstevel@tonic-gate xmlSetGenericErrorFunc(NULL, zonecfg_error_func); 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate return (handle); 2167c478bd9Sstevel@tonic-gate } 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate int 2197c478bd9Sstevel@tonic-gate zonecfg_check_handle(zone_dochandle_t handle) 2207c478bd9Sstevel@tonic-gate { 2217c478bd9Sstevel@tonic-gate if (handle == NULL || handle->zone_dh_doc == NULL) 2227c478bd9Sstevel@tonic-gate return (Z_BAD_HANDLE); 2237c478bd9Sstevel@tonic-gate return (Z_OK); 2247c478bd9Sstevel@tonic-gate } 2257c478bd9Sstevel@tonic-gate 2267c478bd9Sstevel@tonic-gate void 2277c478bd9Sstevel@tonic-gate zonecfg_fini_handle(zone_dochandle_t handle) 2287c478bd9Sstevel@tonic-gate { 2297c478bd9Sstevel@tonic-gate if (zonecfg_check_handle(handle) == Z_OK) 2307c478bd9Sstevel@tonic-gate xmlFreeDoc(handle->zone_dh_doc); 2317c478bd9Sstevel@tonic-gate if (handle != NULL) 2327c478bd9Sstevel@tonic-gate free(handle); 2337c478bd9Sstevel@tonic-gate } 2347c478bd9Sstevel@tonic-gate 2357c478bd9Sstevel@tonic-gate static int 2367c478bd9Sstevel@tonic-gate zonecfg_destroy_impl(char *filename) 2377c478bd9Sstevel@tonic-gate { 2387c478bd9Sstevel@tonic-gate if (unlink(filename) == -1) { 2397c478bd9Sstevel@tonic-gate if (errno == EACCES) 2407c478bd9Sstevel@tonic-gate return (Z_ACCES); 2417c478bd9Sstevel@tonic-gate if (errno == ENOENT) 2427c478bd9Sstevel@tonic-gate return (Z_NO_ZONE); 2437c478bd9Sstevel@tonic-gate return (Z_MISC_FS); 2447c478bd9Sstevel@tonic-gate } 2457c478bd9Sstevel@tonic-gate return (Z_OK); 2467c478bd9Sstevel@tonic-gate } 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate int 249087719fdSdp zonecfg_destroy(const char *zonename, boolean_t force) 2507c478bd9Sstevel@tonic-gate { 2517c478bd9Sstevel@tonic-gate char path[MAXPATHLEN]; 252087719fdSdp struct zoneent ze; 253087719fdSdp int err, state_err; 254087719fdSdp zone_state_t state; 2557c478bd9Sstevel@tonic-gate 256108322fbScarlsonj if (!config_file_path(zonename, path)) 257108322fbScarlsonj return (Z_MISC_FS); 258087719fdSdp 259087719fdSdp state_err = zone_get_state((char *)zonename, &state); 260087719fdSdp err = access(path, W_OK); 261087719fdSdp 262087719fdSdp /* 263087719fdSdp * If there is no file, and no index entry, reliably indicate that no 264087719fdSdp * such zone exists. 265087719fdSdp */ 266087719fdSdp if ((state_err == Z_NO_ZONE) && (err == -1) && (errno == ENOENT)) 267087719fdSdp return (Z_NO_ZONE); 268087719fdSdp 269087719fdSdp /* 270087719fdSdp * Handle any other filesystem related errors (except if the XML 271087719fdSdp * file is missing, which we treat silently), unless we're forcing, 272087719fdSdp * in which case we plow on. 273087719fdSdp */ 274087719fdSdp if (err == -1 && errno != ENOENT) { 275087719fdSdp if (errno == EACCES) 276087719fdSdp return (Z_ACCES); 277087719fdSdp else if (!force) 278087719fdSdp return (Z_MISC_FS); 279087719fdSdp } 280087719fdSdp 281087719fdSdp if (state > ZONE_STATE_INSTALLED) 282087719fdSdp return (Z_BAD_ZONE_STATE); 283087719fdSdp 284087719fdSdp if (!force && state > ZONE_STATE_CONFIGURED) 285087719fdSdp return (Z_BAD_ZONE_STATE); 286087719fdSdp 287087719fdSdp /* 288087719fdSdp * Index deletion succeeds even if the entry doesn't exist. So this 289087719fdSdp * will fail only if we've had some more severe problem. 290087719fdSdp */ 291087719fdSdp bzero(&ze, sizeof (ze)); 292087719fdSdp (void) strlcpy(ze.zone_name, zonename, sizeof (ze.zone_name)); 293087719fdSdp if ((err = putzoneent(&ze, PZE_REMOVE)) != Z_OK) 294087719fdSdp if (!force) 295087719fdSdp return (err); 296087719fdSdp 297087719fdSdp err = zonecfg_destroy_impl(path); 298087719fdSdp 299087719fdSdp /* 300087719fdSdp * Treat failure to find the XML file silently, since, well, it's 301087719fdSdp * gone, and with the index file cleaned up, we're done. 302087719fdSdp */ 303087719fdSdp if (err == Z_OK || err == Z_NO_ZONE) 304087719fdSdp return (Z_OK); 305087719fdSdp return (err); 3067c478bd9Sstevel@tonic-gate } 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate int 309108322fbScarlsonj zonecfg_destroy_snapshot(const char *zonename) 3107c478bd9Sstevel@tonic-gate { 3117c478bd9Sstevel@tonic-gate char path[MAXPATHLEN]; 3127c478bd9Sstevel@tonic-gate 313108322fbScarlsonj if (!snap_file_path(zonename, path)) 314108322fbScarlsonj return (Z_MISC_FS); 3157c478bd9Sstevel@tonic-gate return (zonecfg_destroy_impl(path)); 3167c478bd9Sstevel@tonic-gate } 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate static int 319a1be23daSdp getroot(zone_dochandle_t handle, xmlNodePtr *root) 3207c478bd9Sstevel@tonic-gate { 3217c478bd9Sstevel@tonic-gate if (zonecfg_check_handle(handle) == Z_BAD_HANDLE) 3227c478bd9Sstevel@tonic-gate return (Z_BAD_HANDLE); 3237c478bd9Sstevel@tonic-gate 324a1be23daSdp *root = xmlDocGetRootElement(handle->zone_dh_doc); 325a1be23daSdp 326a1be23daSdp if (*root == NULL) 3277c478bd9Sstevel@tonic-gate return (Z_EMPTY_DOCUMENT); 328a1be23daSdp 329a1be23daSdp if (xmlStrcmp((*root)->name, DTD_ELEM_ZONE)) 330a1be23daSdp return (Z_WRONG_DOC_TYPE); 331a1be23daSdp 332a1be23daSdp return (Z_OK); 3337c478bd9Sstevel@tonic-gate } 3347c478bd9Sstevel@tonic-gate 335a1be23daSdp static int 336a1be23daSdp operation_prep(zone_dochandle_t handle) 337a1be23daSdp { 338a1be23daSdp xmlNodePtr root; 339a1be23daSdp int err; 340a1be23daSdp 341a1be23daSdp if ((err = getroot(handle, &root)) != 0) 342a1be23daSdp return (err); 343a1be23daSdp 344a1be23daSdp handle->zone_dh_cur = root; 345a1be23daSdp handle->zone_dh_top = root; 346a1be23daSdp return (Z_OK); 3477c478bd9Sstevel@tonic-gate } 348a1be23daSdp 349a1be23daSdp static int 350a1be23daSdp getrootattr(zone_dochandle_t handle, const xmlChar *propname, 351a1be23daSdp char *propval, size_t propsize) 352a1be23daSdp { 353a1be23daSdp xmlNodePtr root; 354a1be23daSdp xmlChar *property; 355a1be23daSdp size_t srcsize; 356a1be23daSdp int err; 357a1be23daSdp 358a1be23daSdp if ((err = getroot(handle, &root)) != 0) 359a1be23daSdp return (err); 360a1be23daSdp 361a1be23daSdp if ((property = xmlGetProp(root, propname)) == NULL) 362a1be23daSdp return (Z_BAD_PROPERTY); 363a1be23daSdp srcsize = strlcpy(propval, (char *)property, propsize); 364a1be23daSdp xmlFree(property); 365a1be23daSdp if (srcsize >= propsize) 366a1be23daSdp return (Z_TOO_BIG); 367a1be23daSdp return (Z_OK); 368a1be23daSdp } 369a1be23daSdp 370a1be23daSdp static int 371108322fbScarlsonj setrootattr(zone_dochandle_t handle, const xmlChar *propname, 372108322fbScarlsonj const char *propval) 373a1be23daSdp { 374a1be23daSdp int err; 375a1be23daSdp xmlNodePtr root; 376a1be23daSdp 377a1be23daSdp if (propval == NULL) 378a1be23daSdp return (Z_INVAL); 379a1be23daSdp 380a1be23daSdp if ((err = getroot(handle, &root)) != Z_OK) 381a1be23daSdp return (err); 382a1be23daSdp 383a1be23daSdp if (xmlSetProp(root, propname, (const xmlChar *) propval) == NULL) 384a1be23daSdp return (Z_INVAL); 3857c478bd9Sstevel@tonic-gate return (Z_OK); 3867c478bd9Sstevel@tonic-gate } 3877c478bd9Sstevel@tonic-gate 388087719fdSdp static void 389087719fdSdp addcomment(zone_dochandle_t handle, const char *comment) 390087719fdSdp { 391087719fdSdp xmlNodePtr node; 392087719fdSdp node = xmlNewComment((xmlChar *) comment); 393087719fdSdp 394087719fdSdp if (node != NULL) 395087719fdSdp (void) xmlAddPrevSibling(handle->zone_dh_top, node); 396087719fdSdp } 397087719fdSdp 398087719fdSdp static void 399087719fdSdp stripcomments(zone_dochandle_t handle) 400087719fdSdp { 401087719fdSdp xmlDocPtr top; 402087719fdSdp xmlNodePtr child, next; 403087719fdSdp 404087719fdSdp top = handle->zone_dh_doc; 405087719fdSdp for (child = top->xmlChildrenNode; child != NULL; child = next) { 406087719fdSdp next = child->next; 407087719fdSdp if (child->name == NULL) 408087719fdSdp continue; 409087719fdSdp if (xmlStrcmp(child->name, DTD_ELEM_COMMENT) == 0) { 410087719fdSdp next = child->next; 411087719fdSdp xmlUnlinkNode(child); 412087719fdSdp xmlFreeNode(child); 413087719fdSdp } 414087719fdSdp } 415087719fdSdp } 416087719fdSdp 4177c478bd9Sstevel@tonic-gate static int 418108322fbScarlsonj zonecfg_get_handle_impl(const char *zonename, const char *filename, 419108322fbScarlsonj zone_dochandle_t handle) 4207c478bd9Sstevel@tonic-gate { 4217c478bd9Sstevel@tonic-gate xmlValidCtxtPtr cvp; 4227c478bd9Sstevel@tonic-gate struct stat statbuf; 4237c478bd9Sstevel@tonic-gate int valid; 4247c478bd9Sstevel@tonic-gate 4257c478bd9Sstevel@tonic-gate if (zonename == NULL) 4267c478bd9Sstevel@tonic-gate return (Z_NO_ZONE); 4277c478bd9Sstevel@tonic-gate if ((handle->zone_dh_doc = xmlParseFile(filename)) == NULL) { 4287c478bd9Sstevel@tonic-gate /* distinguish file not found vs. found but not parsed */ 4297c478bd9Sstevel@tonic-gate if (stat(filename, &statbuf) == 0) 4307c478bd9Sstevel@tonic-gate return (Z_INVALID_DOCUMENT); 4317c478bd9Sstevel@tonic-gate return (Z_NO_ZONE); 4327c478bd9Sstevel@tonic-gate } 4337c478bd9Sstevel@tonic-gate if ((cvp = xmlNewValidCtxt()) == NULL) 4347c478bd9Sstevel@tonic-gate return (Z_NOMEM); 4357c478bd9Sstevel@tonic-gate cvp->error = zonecfg_error_func; 4367c478bd9Sstevel@tonic-gate cvp->warning = zonecfg_error_func; 4377c478bd9Sstevel@tonic-gate valid = xmlValidateDocument(cvp, handle->zone_dh_doc); 4387c478bd9Sstevel@tonic-gate xmlFreeValidCtxt(cvp); 4397c478bd9Sstevel@tonic-gate if (valid == 0) 4407c478bd9Sstevel@tonic-gate return (Z_INVALID_DOCUMENT); 441087719fdSdp 4427c478bd9Sstevel@tonic-gate /* delete any comments such as inherited Sun copyright / ident str */ 443087719fdSdp stripcomments(handle); 4447c478bd9Sstevel@tonic-gate return (Z_OK); 4457c478bd9Sstevel@tonic-gate } 4467c478bd9Sstevel@tonic-gate 4477c478bd9Sstevel@tonic-gate int 448108322fbScarlsonj zonecfg_get_handle(const char *zonename, zone_dochandle_t handle) 4497c478bd9Sstevel@tonic-gate { 4507c478bd9Sstevel@tonic-gate char path[MAXPATHLEN]; 4517c478bd9Sstevel@tonic-gate 452108322fbScarlsonj if (!config_file_path(zonename, path)) 453108322fbScarlsonj return (Z_MISC_FS); 454087719fdSdp handle->zone_dh_newzone = B_FALSE; 455087719fdSdp 4567c478bd9Sstevel@tonic-gate return (zonecfg_get_handle_impl(zonename, path, handle)); 4577c478bd9Sstevel@tonic-gate } 4587c478bd9Sstevel@tonic-gate 4597c478bd9Sstevel@tonic-gate int 460108322fbScarlsonj zonecfg_get_snapshot_handle(const char *zonename, zone_dochandle_t handle) 4617c478bd9Sstevel@tonic-gate { 4627c478bd9Sstevel@tonic-gate char path[MAXPATHLEN]; 4637c478bd9Sstevel@tonic-gate 464108322fbScarlsonj if (!snap_file_path(zonename, path)) 465108322fbScarlsonj return (Z_MISC_FS); 466087719fdSdp handle->zone_dh_newzone = B_FALSE; 4677c478bd9Sstevel@tonic-gate return (zonecfg_get_handle_impl(zonename, path, handle)); 4687c478bd9Sstevel@tonic-gate } 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate int 471108322fbScarlsonj zonecfg_get_template_handle(const char *template, const char *zonename, 472087719fdSdp zone_dochandle_t handle) 473087719fdSdp { 474087719fdSdp char path[MAXPATHLEN]; 475087719fdSdp int err; 476087719fdSdp 477108322fbScarlsonj if (!config_file_path(template, path)) 478108322fbScarlsonj return (Z_MISC_FS); 479087719fdSdp 480087719fdSdp if ((err = zonecfg_get_handle_impl(template, path, handle)) != Z_OK) 481087719fdSdp return (err); 482087719fdSdp handle->zone_dh_newzone = B_TRUE; 483087719fdSdp return (setrootattr(handle, DTD_ATTR_NAME, zonename)); 484087719fdSdp } 485087719fdSdp 486087719fdSdp static boolean_t 487087719fdSdp is_renaming(zone_dochandle_t handle) 488087719fdSdp { 489087719fdSdp if (handle->zone_dh_newzone) 490087719fdSdp return (B_FALSE); 491087719fdSdp if (strlen(handle->zone_dh_delete_name) > 0) 492087719fdSdp return (B_TRUE); 493087719fdSdp return (B_FALSE); 494087719fdSdp } 495087719fdSdp 496087719fdSdp static boolean_t 497087719fdSdp is_new(zone_dochandle_t handle) 498087719fdSdp { 499087719fdSdp return (handle->zone_dh_newzone || handle->zone_dh_snapshot); 500087719fdSdp } 501087719fdSdp 502087719fdSdp static boolean_t 503087719fdSdp is_snapshot(zone_dochandle_t handle) 504087719fdSdp { 505087719fdSdp return (handle->zone_dh_snapshot); 506087719fdSdp } 507087719fdSdp 508087719fdSdp /* 509087719fdSdp * It would be great to be able to use libc's ctype(3c) macros, but we 510087719fdSdp * can't, as they are locale sensitive, and it would break our limited thread 511087719fdSdp * safety if this routine had to change the app locale on the fly. 512087719fdSdp */ 513087719fdSdp int 514108322fbScarlsonj zonecfg_validate_zonename(const char *zone) 515087719fdSdp { 516087719fdSdp int i; 517087719fdSdp 518087719fdSdp if (strcmp(zone, GLOBAL_ZONENAME) == 0) 519087719fdSdp return (Z_BOGUS_ZONE_NAME); 520087719fdSdp 521087719fdSdp if (strlen(zone) >= ZONENAME_MAX) 522087719fdSdp return (Z_BOGUS_ZONE_NAME); 523087719fdSdp 524087719fdSdp if (!((zone[0] >= 'a' && zone[0] <= 'z') || 525087719fdSdp (zone[0] >= 'A' && zone[0] <= 'Z') || 526087719fdSdp (zone[0] >= '0' && zone[0] <= '9'))) 527087719fdSdp return (Z_BOGUS_ZONE_NAME); 528087719fdSdp 529087719fdSdp for (i = 1; zone[i] != '\0'; i++) { 530087719fdSdp if (!((zone[i] >= 'a' && zone[i] <= 'z') || 531087719fdSdp (zone[i] >= 'A' && zone[i] <= 'Z') || 532087719fdSdp (zone[i] >= '0' && zone[i] <= '9') || 533087719fdSdp (zone[i] == '-') || (zone[i] == '_') || (zone[i] == '.'))) 534087719fdSdp return (Z_BOGUS_ZONE_NAME); 535087719fdSdp } 536087719fdSdp 537087719fdSdp return (Z_OK); 538087719fdSdp } 539087719fdSdp 540087719fdSdp /* 541087719fdSdp * Changing the zone name requires us to track both the old and new 542087719fdSdp * name of the zone until commit time. 543087719fdSdp */ 544087719fdSdp int 5457c478bd9Sstevel@tonic-gate zonecfg_get_name(zone_dochandle_t handle, char *name, size_t namesize) 5467c478bd9Sstevel@tonic-gate { 547a1be23daSdp return (getrootattr(handle, DTD_ATTR_NAME, name, namesize)); 5487c478bd9Sstevel@tonic-gate } 5497c478bd9Sstevel@tonic-gate 550a1be23daSdp int 551a1be23daSdp zonecfg_set_name(zone_dochandle_t handle, char *name) 552a1be23daSdp { 553087719fdSdp zone_state_t state; 554087719fdSdp char curname[ZONENAME_MAX], old_delname[ZONENAME_MAX]; 555087719fdSdp int err; 556087719fdSdp 557087719fdSdp if ((err = getrootattr(handle, DTD_ATTR_NAME, curname, 558087719fdSdp sizeof (curname))) != Z_OK) 559087719fdSdp return (err); 560087719fdSdp 561087719fdSdp if (strcmp(name, curname) == 0) 562087719fdSdp return (Z_OK); 563087719fdSdp 564087719fdSdp /* 565087719fdSdp * Switching zone names to one beginning with SUNW is not permitted. 566087719fdSdp */ 567087719fdSdp if (strncmp(name, "SUNW", 4) == 0) 568087719fdSdp return (Z_BOGUS_ZONE_NAME); 569087719fdSdp 570087719fdSdp if ((err = zonecfg_validate_zonename(name)) != Z_OK) 571087719fdSdp return (err); 572087719fdSdp 573087719fdSdp /* 574087719fdSdp * Setting the name back to the original name (effectively a revert of 575087719fdSdp * the name) is fine. But if we carry on, we'll falsely identify the 576087719fdSdp * name as "in use," so special case here. 577087719fdSdp */ 578087719fdSdp if (strcmp(name, handle->zone_dh_delete_name) == 0) { 579087719fdSdp err = setrootattr(handle, DTD_ATTR_NAME, name); 580087719fdSdp handle->zone_dh_delete_name[0] = '\0'; 581087719fdSdp return (err); 582087719fdSdp } 583087719fdSdp 584087719fdSdp /* Check to see if new name chosen is already in use */ 585087719fdSdp if (zone_get_state(name, &state) != Z_NO_ZONE) 586087719fdSdp return (Z_NAME_IN_USE); 587087719fdSdp 588087719fdSdp /* 589087719fdSdp * If this isn't already "new" or in a renaming transition, then 590087719fdSdp * we're initiating a rename here; so stash the "delete name" 591087719fdSdp * (i.e. the name of the zone we'll be removing) for the rename. 592087719fdSdp */ 593087719fdSdp (void) strlcpy(old_delname, handle->zone_dh_delete_name, 594087719fdSdp sizeof (old_delname)); 595087719fdSdp if (!is_new(handle) && !is_renaming(handle)) { 596087719fdSdp /* 597087719fdSdp * Name change is allowed only when the zone we're altering 598087719fdSdp * is not ready or running. 599087719fdSdp */ 600087719fdSdp err = zone_get_state(curname, &state); 601087719fdSdp if (err == Z_OK) { 602087719fdSdp if (state > ZONE_STATE_INSTALLED) 603087719fdSdp return (Z_BAD_ZONE_STATE); 604087719fdSdp } else if (err != Z_NO_ZONE) { 605087719fdSdp return (err); 606087719fdSdp } 607087719fdSdp 608087719fdSdp (void) strlcpy(handle->zone_dh_delete_name, curname, 609087719fdSdp sizeof (handle->zone_dh_delete_name)); 610087719fdSdp assert(is_renaming(handle)); 611087719fdSdp } else if (is_renaming(handle)) { 612087719fdSdp err = zone_get_state(handle->zone_dh_delete_name, &state); 613087719fdSdp if (err == Z_OK) { 614087719fdSdp if (state > ZONE_STATE_INSTALLED) 615087719fdSdp return (Z_BAD_ZONE_STATE); 616087719fdSdp } else if (err != Z_NO_ZONE) { 617087719fdSdp return (err); 618087719fdSdp } 619087719fdSdp } 620087719fdSdp 621087719fdSdp if ((err = setrootattr(handle, DTD_ATTR_NAME, name)) != Z_OK) { 622087719fdSdp /* 623087719fdSdp * Restore the deletename to whatever it was at the 624087719fdSdp * top of the routine, since we've had a failure. 625087719fdSdp */ 626087719fdSdp (void) strlcpy(handle->zone_dh_delete_name, old_delname, 627087719fdSdp sizeof (handle->zone_dh_delete_name)); 628087719fdSdp return (err); 629087719fdSdp } 630087719fdSdp 631087719fdSdp return (Z_OK); 6327c478bd9Sstevel@tonic-gate } 633a1be23daSdp 634a1be23daSdp int 635a1be23daSdp zonecfg_get_zonepath(zone_dochandle_t handle, char *path, size_t pathsize) 636a1be23daSdp { 637108322fbScarlsonj size_t len; 638108322fbScarlsonj 639108322fbScarlsonj if ((len = strlcpy(path, zonecfg_root, pathsize)) >= pathsize) 640108322fbScarlsonj return (Z_TOO_BIG); 641108322fbScarlsonj return (getrootattr(handle, DTD_ATTR_ZONEPATH, path + len, 642108322fbScarlsonj pathsize - len)); 643a1be23daSdp } 644a1be23daSdp 645a1be23daSdp int 646a1be23daSdp zonecfg_set_zonepath(zone_dochandle_t handle, char *zonepath) 647a1be23daSdp { 648a1be23daSdp return (setrootattr(handle, DTD_ATTR_ZONEPATH, zonepath)); 649a1be23daSdp } 650a1be23daSdp 651a1be23daSdp int 652a1be23daSdp zonecfg_get_autoboot(zone_dochandle_t handle, boolean_t *autoboot) 653a1be23daSdp { 654a1be23daSdp char autobootstr[DTD_ENTITY_BOOL_LEN]; 655a1be23daSdp int ret; 656a1be23daSdp 657a1be23daSdp if ((ret = getrootattr(handle, DTD_ATTR_AUTOBOOT, autobootstr, 658a1be23daSdp sizeof (autobootstr))) != Z_OK) 659a1be23daSdp return (ret); 660a1be23daSdp 661a1be23daSdp if (strcmp(autobootstr, DTD_ENTITY_TRUE) == 0) 662a1be23daSdp *autoboot = B_TRUE; 663a1be23daSdp else if (strcmp(autobootstr, DTD_ENTITY_FALSE) == 0) 664a1be23daSdp *autoboot = B_FALSE; 665a1be23daSdp else 666a1be23daSdp ret = Z_BAD_PROPERTY; 667a1be23daSdp return (ret); 668a1be23daSdp } 669a1be23daSdp 670a1be23daSdp int 671a1be23daSdp zonecfg_set_autoboot(zone_dochandle_t handle, boolean_t autoboot) 672a1be23daSdp { 673a1be23daSdp return (setrootattr(handle, DTD_ATTR_AUTOBOOT, 674a1be23daSdp autoboot ? DTD_ENTITY_TRUE : DTD_ENTITY_FALSE)); 675a1be23daSdp } 676a1be23daSdp 677a1be23daSdp int 678a1be23daSdp zonecfg_get_pool(zone_dochandle_t handle, char *pool, size_t poolsize) 679a1be23daSdp { 680a1be23daSdp return (getrootattr(handle, DTD_ATTR_POOL, pool, poolsize)); 681a1be23daSdp } 682a1be23daSdp 683a1be23daSdp int 684a1be23daSdp zonecfg_set_pool(zone_dochandle_t handle, char *pool) 685a1be23daSdp { 686a1be23daSdp return (setrootattr(handle, DTD_ATTR_POOL, pool)); 687a1be23daSdp } 688a1be23daSdp 689a1be23daSdp /* 690a1be23daSdp * /etc/zones/index caches a vital piece of information which is also 691a1be23daSdp * in the <zonename>.xml file: the path to the zone. This is for performance, 692a1be23daSdp * since we need to walk all zonepath's in order to be able to detect conflicts 693a1be23daSdp * (see crosscheck_zonepaths() in the zoneadm command). 694087719fdSdp * 695087719fdSdp * An additional complexity is that when doing a rename, we'd like the entire 696087719fdSdp * index update operation (rename, and potential state changes) to be atomic. 697087719fdSdp * In general, the operation of this function should succeed or fail as 698087719fdSdp * a unit. 699a1be23daSdp */ 700a1be23daSdp int 701a1be23daSdp zonecfg_refresh_index_file(zone_dochandle_t handle) 702a1be23daSdp { 703a1be23daSdp char name[ZONENAME_MAX], zonepath[MAXPATHLEN]; 704a1be23daSdp struct zoneent ze; 705a1be23daSdp int err; 706087719fdSdp int opcode; 707087719fdSdp char *zn; 708087719fdSdp 709087719fdSdp bzero(&ze, sizeof (ze)); 710087719fdSdp ze.zone_state = -1; /* Preserve existing state in index */ 711a1be23daSdp 712a1be23daSdp if ((err = zonecfg_get_name(handle, name, sizeof (name))) != Z_OK) 713a1be23daSdp return (err); 714087719fdSdp (void) strlcpy(ze.zone_name, name, sizeof (ze.zone_name)); 715087719fdSdp 716a1be23daSdp if ((err = zonecfg_get_zonepath(handle, zonepath, 717a1be23daSdp sizeof (zonepath))) != Z_OK) 718a1be23daSdp return (err); 719a1be23daSdp (void) strlcpy(ze.zone_path, zonepath, sizeof (ze.zone_path)); 720087719fdSdp 721087719fdSdp if (is_renaming(handle)) { 722087719fdSdp opcode = PZE_MODIFY; 723087719fdSdp (void) strlcpy(ze.zone_name, handle->zone_dh_delete_name, 724087719fdSdp sizeof (ze.zone_name)); 725087719fdSdp (void) strlcpy(ze.zone_newname, name, sizeof (ze.zone_newname)); 726087719fdSdp } else if (is_new(handle)) { 727087719fdSdp FILE *cookie; 728087719fdSdp /* 729087719fdSdp * Be tolerant of the zone already existing in the index file, 730087719fdSdp * since we might be forcibly overwriting an existing 731087719fdSdp * configuration with a new one (for example 'create -F' 732087719fdSdp * in zonecfg). 733087719fdSdp */ 734087719fdSdp opcode = PZE_ADD; 735087719fdSdp cookie = setzoneent(); 736087719fdSdp while ((zn = getzoneent(cookie)) != NULL) { 737087719fdSdp if (strcmp(zn, name) == 0) { 738087719fdSdp opcode = PZE_MODIFY; 739087719fdSdp free(zn); 740087719fdSdp break; 741087719fdSdp } 742087719fdSdp free(zn); 743087719fdSdp } 744087719fdSdp endzoneent(cookie); 745087719fdSdp ze.zone_state = ZONE_STATE_CONFIGURED; 746087719fdSdp } else { 747087719fdSdp opcode = PZE_MODIFY; 7487c478bd9Sstevel@tonic-gate } 7497c478bd9Sstevel@tonic-gate 750087719fdSdp if ((err = putzoneent(&ze, opcode)) != Z_OK) 751087719fdSdp return (err); 752087719fdSdp 753087719fdSdp return (Z_OK); 754087719fdSdp } 755087719fdSdp 756087719fdSdp /* 757087719fdSdp * The goal of this routine is to cause the index file update and the 758087719fdSdp * document save to happen as an atomic operation. We do the document 759087719fdSdp * first, saving a backup copy using a hard link; if that succeeds, we go 760087719fdSdp * on to the index. If that fails, we roll the document back into place. 761087719fdSdp * 762087719fdSdp * Strategy: 763087719fdSdp * 764087719fdSdp * New zone 'foo' configuration: 765087719fdSdp * Create tmpfile (zonecfg.xxxxxx) 766087719fdSdp * Write XML to tmpfile 767087719fdSdp * Rename tmpfile to xmlfile (zonecfg.xxxxxx -> foo.xml) 768087719fdSdp * Add entry to index file 769087719fdSdp * If it fails, delete foo.xml, leaving nothing behind. 770087719fdSdp * 771087719fdSdp * Save existing zone 'foo': 772087719fdSdp * Make backup of foo.xml -> .backup 773087719fdSdp * Create tmpfile (zonecfg.xxxxxx) 774087719fdSdp * Write XML to tmpfile 775087719fdSdp * Rename tmpfile to xmlfile (zonecfg.xxxxxx -> foo.xml) 776087719fdSdp * Modify index file as needed 777087719fdSdp * If it fails, recover from .backup -> foo.xml 778087719fdSdp * 779087719fdSdp * Rename 'foo' to 'bar': 780087719fdSdp * Create tmpfile (zonecfg.xxxxxx) 781087719fdSdp * Write XML to tmpfile 782087719fdSdp * Rename tmpfile to xmlfile (zonecfg.xxxxxx -> bar.xml) 783087719fdSdp * Add entry for 'bar' to index file, Remove entry for 'foo' (refresh) 784087719fdSdp * If it fails, delete bar.xml; foo.xml is left behind. 785087719fdSdp */ 7867c478bd9Sstevel@tonic-gate static int 7877c478bd9Sstevel@tonic-gate zonecfg_save_impl(zone_dochandle_t handle, char *filename) 7887c478bd9Sstevel@tonic-gate { 7897c478bd9Sstevel@tonic-gate char tmpfile[MAXPATHLEN]; 790087719fdSdp char bakdir[MAXPATHLEN], bakbase[MAXPATHLEN], bakfile[MAXPATHLEN]; 791087719fdSdp int tmpfd, err; 7927c478bd9Sstevel@tonic-gate xmlValidCtxt cvp = { NULL }; 793087719fdSdp boolean_t backup; 7947c478bd9Sstevel@tonic-gate 7957c478bd9Sstevel@tonic-gate (void) strlcpy(tmpfile, filename, sizeof (tmpfile)); 7967c478bd9Sstevel@tonic-gate (void) dirname(tmpfile); 7977c478bd9Sstevel@tonic-gate (void) strlcat(tmpfile, _PATH_TMPFILE, sizeof (tmpfile)); 7987c478bd9Sstevel@tonic-gate 7997c478bd9Sstevel@tonic-gate tmpfd = mkstemp(tmpfile); 8007c478bd9Sstevel@tonic-gate if (tmpfd == -1) { 8017c478bd9Sstevel@tonic-gate (void) unlink(tmpfile); 8027c478bd9Sstevel@tonic-gate return (Z_TEMP_FILE); 8037c478bd9Sstevel@tonic-gate } 8047c478bd9Sstevel@tonic-gate (void) close(tmpfd); 8057c478bd9Sstevel@tonic-gate 8067c478bd9Sstevel@tonic-gate cvp.error = zonecfg_error_func; 8077c478bd9Sstevel@tonic-gate cvp.warning = zonecfg_error_func; 8087c478bd9Sstevel@tonic-gate 809087719fdSdp /* 810087719fdSdp * We do a final validation of the document-- but the library has 811087719fdSdp * malfunctioned if it fails to validate, so it's an assert. 812087719fdSdp */ 813087719fdSdp assert(xmlValidateDocument(&cvp, handle->zone_dh_doc) != 0); 8147c478bd9Sstevel@tonic-gate 8157c478bd9Sstevel@tonic-gate if (xmlSaveFormatFile(tmpfile, handle->zone_dh_doc, 1) <= 0) 8167c478bd9Sstevel@tonic-gate goto err; 817087719fdSdp 8187c478bd9Sstevel@tonic-gate (void) chmod(tmpfile, 0644); 8197c478bd9Sstevel@tonic-gate 820087719fdSdp /* 821087719fdSdp * In the event we are doing a standard save, hard link a copy of the 822087719fdSdp * original file in .backup.<pid>.filename so we can restore it if 823087719fdSdp * something goes wrong. 824087719fdSdp */ 825087719fdSdp if (!is_new(handle) && !is_renaming(handle)) { 826087719fdSdp backup = B_TRUE; 827087719fdSdp 828087719fdSdp (void) strlcpy(bakdir, filename, sizeof (bakdir)); 829087719fdSdp (void) strlcpy(bakbase, filename, sizeof (bakbase)); 830087719fdSdp (void) snprintf(bakfile, sizeof (bakfile), "%s/.backup.%d.%s", 831087719fdSdp dirname(bakdir), getpid(), basename(bakbase)); 832087719fdSdp 833087719fdSdp if (link(filename, bakfile) == -1) { 834087719fdSdp err = errno; 8357c478bd9Sstevel@tonic-gate (void) unlink(tmpfile); 8367c478bd9Sstevel@tonic-gate if (errno == EACCES) 8377c478bd9Sstevel@tonic-gate return (Z_ACCES); 8387c478bd9Sstevel@tonic-gate return (Z_MISC_FS); 8397c478bd9Sstevel@tonic-gate } 840087719fdSdp } 841a1be23daSdp 842087719fdSdp /* 843087719fdSdp * Move the new document over top of the old. 844087719fdSdp * i.e.: zonecfg.XXXXXX -> myzone.xml 845087719fdSdp */ 846087719fdSdp if (rename(tmpfile, filename) == -1) { 847087719fdSdp err = errno; 848087719fdSdp (void) unlink(tmpfile); 849087719fdSdp if (backup) 850087719fdSdp (void) unlink(bakfile); 851087719fdSdp if (err == EACCES) 852087719fdSdp return (Z_ACCES); 853087719fdSdp return (Z_MISC_FS); 854087719fdSdp } 855087719fdSdp 856087719fdSdp /* 857087719fdSdp * If this is a snapshot, we're done-- don't add an index entry. 858087719fdSdp */ 859087719fdSdp if (is_snapshot(handle)) 860087719fdSdp return (Z_OK); 861087719fdSdp 862087719fdSdp /* now update the index file to reflect whatever we just did */ 863087719fdSdp if ((err = zonecfg_refresh_index_file(handle)) != Z_OK) { 864087719fdSdp if (backup) { 865087719fdSdp /* 866087719fdSdp * Try to restore from our backup. 867087719fdSdp */ 868087719fdSdp (void) unlink(filename); 869087719fdSdp (void) rename(bakfile, filename); 870087719fdSdp } else { 871087719fdSdp /* 872087719fdSdp * Either the zone is new, in which case we can delete 873087719fdSdp * new.xml, or we're doing a rename, so ditto. 874087719fdSdp */ 875087719fdSdp assert(is_new(handle) || is_renaming(handle)); 876087719fdSdp (void) unlink(filename); 877087719fdSdp } 878087719fdSdp return (Z_UPDATING_INDEX); 879087719fdSdp } 880087719fdSdp 881087719fdSdp if (backup) 882087719fdSdp (void) unlink(bakfile); 883087719fdSdp 884087719fdSdp return (Z_OK); 8857c478bd9Sstevel@tonic-gate 8867c478bd9Sstevel@tonic-gate err: 8877c478bd9Sstevel@tonic-gate (void) unlink(tmpfile); 8887c478bd9Sstevel@tonic-gate return (Z_SAVING_FILE); 8897c478bd9Sstevel@tonic-gate } 8907c478bd9Sstevel@tonic-gate 8917c478bd9Sstevel@tonic-gate int 8927c478bd9Sstevel@tonic-gate zonecfg_save(zone_dochandle_t handle) 8937c478bd9Sstevel@tonic-gate { 894087719fdSdp char zname[ZONENAME_MAX], path[MAXPATHLEN]; 895087719fdSdp char delpath[MAXPATHLEN]; 896087719fdSdp int err = Z_SAVING_FILE; 8977c478bd9Sstevel@tonic-gate 898087719fdSdp if (zonecfg_check_handle(handle) != Z_OK) 899087719fdSdp return (Z_BAD_HANDLE); 900087719fdSdp 901087719fdSdp /* 902087719fdSdp * We don't support saving snapshots at this time. 903087719fdSdp */ 904087719fdSdp if (handle->zone_dh_snapshot) 905087719fdSdp return (Z_INVAL); 906087719fdSdp 907087719fdSdp if ((err = zonecfg_get_name(handle, zname, sizeof (zname))) != Z_OK) 9087c478bd9Sstevel@tonic-gate return (err); 909087719fdSdp 910108322fbScarlsonj if (!config_file_path(zname, path)) 911108322fbScarlsonj return (Z_MISC_FS); 912087719fdSdp 913087719fdSdp addcomment(handle, "\n DO NOT EDIT THIS " 914087719fdSdp "FILE. Use zonecfg(1M) instead.\n"); 915087719fdSdp 916087719fdSdp err = zonecfg_save_impl(handle, path); 917087719fdSdp 918087719fdSdp stripcomments(handle); 919087719fdSdp 920087719fdSdp if (err != Z_OK) 921087719fdSdp return (err); 922087719fdSdp 923087719fdSdp handle->zone_dh_newzone = B_FALSE; 924087719fdSdp 925087719fdSdp if (is_renaming(handle)) { 926108322fbScarlsonj if (config_file_path(handle->zone_dh_delete_name, delpath)) 927087719fdSdp (void) unlink(delpath); 928087719fdSdp handle->zone_dh_delete_name[0] = '\0'; 929087719fdSdp } 930087719fdSdp 931087719fdSdp return (Z_OK); 9327c478bd9Sstevel@tonic-gate } 9337c478bd9Sstevel@tonic-gate 9347c478bd9Sstevel@tonic-gate /* 9357c478bd9Sstevel@tonic-gate * Special case: if access(2) fails with ENOENT, then try again using 9367c478bd9Sstevel@tonic-gate * ZONE_CONFIG_ROOT instead of config_file_path(zonename). This is how we 9377c478bd9Sstevel@tonic-gate * work around the case of a config file which has not been created yet: 9387c478bd9Sstevel@tonic-gate * the user will need access to the directory so use that as a heuristic. 9397c478bd9Sstevel@tonic-gate */ 9407c478bd9Sstevel@tonic-gate 9417c478bd9Sstevel@tonic-gate int 9427c478bd9Sstevel@tonic-gate zonecfg_access(const char *zonename, int amode) 9437c478bd9Sstevel@tonic-gate { 9447c478bd9Sstevel@tonic-gate char path[MAXPATHLEN]; 9457c478bd9Sstevel@tonic-gate 946108322fbScarlsonj if (!config_file_path(zonename, path)) 947108322fbScarlsonj return (Z_INVAL); 9487c478bd9Sstevel@tonic-gate if (access(path, amode) == 0) 9497c478bd9Sstevel@tonic-gate return (Z_OK); 950108322fbScarlsonj if (errno == ENOENT) { 951108322fbScarlsonj if (snprintf(path, sizeof (path), "%s%s", zonecfg_root, 952108322fbScarlsonj ZONE_CONFIG_ROOT) >= sizeof (path)) 953108322fbScarlsonj return (Z_INVAL); 954108322fbScarlsonj if (access(path, amode) == 0) 9557c478bd9Sstevel@tonic-gate return (Z_OK); 956108322fbScarlsonj } 9577c478bd9Sstevel@tonic-gate if (errno == EACCES) 9587c478bd9Sstevel@tonic-gate return (Z_ACCES); 9597c478bd9Sstevel@tonic-gate if (errno == EINVAL) 9607c478bd9Sstevel@tonic-gate return (Z_INVAL); 9617c478bd9Sstevel@tonic-gate return (Z_MISC_FS); 9627c478bd9Sstevel@tonic-gate } 9637c478bd9Sstevel@tonic-gate 9647c478bd9Sstevel@tonic-gate int 965108322fbScarlsonj zonecfg_create_snapshot(const char *zonename) 9667c478bd9Sstevel@tonic-gate { 9677c478bd9Sstevel@tonic-gate zone_dochandle_t handle; 9687c478bd9Sstevel@tonic-gate char path[MAXPATHLEN], zonepath[MAXPATHLEN], rpath[MAXPATHLEN]; 9697c478bd9Sstevel@tonic-gate int error = Z_OK, res; 9707c478bd9Sstevel@tonic-gate 9717c478bd9Sstevel@tonic-gate if ((handle = zonecfg_init_handle()) == NULL) { 9727c478bd9Sstevel@tonic-gate return (Z_NOMEM); 9737c478bd9Sstevel@tonic-gate } 9747c478bd9Sstevel@tonic-gate 975087719fdSdp handle->zone_dh_newzone = B_TRUE; 976087719fdSdp handle->zone_dh_snapshot = B_TRUE; 977087719fdSdp 9787c478bd9Sstevel@tonic-gate if ((error = zonecfg_get_handle(zonename, handle)) != Z_OK) 9797c478bd9Sstevel@tonic-gate goto out; 9807c478bd9Sstevel@tonic-gate if ((error = operation_prep(handle)) != Z_OK) 9817c478bd9Sstevel@tonic-gate goto out; 9827c478bd9Sstevel@tonic-gate error = zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath)); 9837c478bd9Sstevel@tonic-gate if (error != Z_OK) 9847c478bd9Sstevel@tonic-gate goto out; 9857c478bd9Sstevel@tonic-gate if ((res = resolvepath(zonepath, rpath, sizeof (rpath))) == -1) { 9867c478bd9Sstevel@tonic-gate error = Z_RESOLVED_PATH; 9877c478bd9Sstevel@tonic-gate goto out; 9887c478bd9Sstevel@tonic-gate } 9897c478bd9Sstevel@tonic-gate /* 9907c478bd9Sstevel@tonic-gate * If the resolved path is not the same as the original path, then 9917c478bd9Sstevel@tonic-gate * save the resolved path in the snapshot, thus preventing any 9927c478bd9Sstevel@tonic-gate * potential problems down the line when zoneadmd goes to unmount 9937c478bd9Sstevel@tonic-gate * file systems and depends on initial string matches with resolved 9947c478bd9Sstevel@tonic-gate * paths. 9957c478bd9Sstevel@tonic-gate */ 9967c478bd9Sstevel@tonic-gate rpath[res] = '\0'; 9977c478bd9Sstevel@tonic-gate if (strcmp(zonepath, rpath) != 0) { 9987c478bd9Sstevel@tonic-gate if ((error = zonecfg_set_zonepath(handle, rpath)) != Z_OK) 9997c478bd9Sstevel@tonic-gate goto out; 10007c478bd9Sstevel@tonic-gate } 1001108322fbScarlsonj if (snprintf(path, sizeof (path), "%s%s", zonecfg_root, 1002108322fbScarlsonj ZONE_SNAPSHOT_ROOT) >= sizeof (path)) { 1003108322fbScarlsonj error = Z_MISC_FS; 1004108322fbScarlsonj goto out; 1005108322fbScarlsonj } 1006108322fbScarlsonj if ((mkdir(path, S_IRWXU) == -1) && (errno != EEXIST)) { 10077c478bd9Sstevel@tonic-gate error = Z_MISC_FS; 10087c478bd9Sstevel@tonic-gate goto out; 10097c478bd9Sstevel@tonic-gate } 10107c478bd9Sstevel@tonic-gate 1011108322fbScarlsonj if (!snap_file_path(zonename, path)) { 1012108322fbScarlsonj error = Z_MISC_FS; 1013108322fbScarlsonj goto out; 1014108322fbScarlsonj } 1015087719fdSdp 1016087719fdSdp addcomment(handle, "\n DO NOT EDIT THIS FILE. " 1017087719fdSdp "It is a snapshot of running zone state.\n"); 1018087719fdSdp 10197c478bd9Sstevel@tonic-gate error = zonecfg_save_impl(handle, path); 10207c478bd9Sstevel@tonic-gate 1021087719fdSdp stripcomments(handle); 1022087719fdSdp 10237c478bd9Sstevel@tonic-gate out: 10247c478bd9Sstevel@tonic-gate zonecfg_fini_handle(handle); 10257c478bd9Sstevel@tonic-gate return (error); 10267c478bd9Sstevel@tonic-gate } 10277c478bd9Sstevel@tonic-gate 10287c478bd9Sstevel@tonic-gate static int 1029a1be23daSdp newprop(xmlNodePtr node, const xmlChar *attrname, char *src) 10307c478bd9Sstevel@tonic-gate { 10317c478bd9Sstevel@tonic-gate xmlAttrPtr newattr; 10327c478bd9Sstevel@tonic-gate 10337c478bd9Sstevel@tonic-gate newattr = xmlNewProp(node, attrname, (xmlChar *)src); 10347c478bd9Sstevel@tonic-gate if (newattr == NULL) { 10357c478bd9Sstevel@tonic-gate xmlUnlinkNode(node); 10367c478bd9Sstevel@tonic-gate xmlFreeNode(node); 10377c478bd9Sstevel@tonic-gate return (Z_BAD_PROPERTY); 10387c478bd9Sstevel@tonic-gate } 10397c478bd9Sstevel@tonic-gate return (Z_OK); 10407c478bd9Sstevel@tonic-gate } 10417c478bd9Sstevel@tonic-gate 10427c478bd9Sstevel@tonic-gate static int 10437c478bd9Sstevel@tonic-gate zonecfg_add_filesystem_core(zone_dochandle_t handle, struct zone_fstab *tabptr) 10447c478bd9Sstevel@tonic-gate { 10457c478bd9Sstevel@tonic-gate xmlNodePtr newnode, cur = handle->zone_dh_cur, options_node; 10467c478bd9Sstevel@tonic-gate zone_fsopt_t *ptr; 10477c478bd9Sstevel@tonic-gate int err; 10487c478bd9Sstevel@tonic-gate 10497c478bd9Sstevel@tonic-gate newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_FS, NULL); 1050a1be23daSdp if ((err = newprop(newnode, DTD_ATTR_SPECIAL, 10517c478bd9Sstevel@tonic-gate tabptr->zone_fs_special)) != Z_OK) 10527c478bd9Sstevel@tonic-gate return (err); 10537c478bd9Sstevel@tonic-gate if (tabptr->zone_fs_raw[0] != '\0' && 1054a1be23daSdp (err = newprop(newnode, DTD_ATTR_RAW, tabptr->zone_fs_raw)) != Z_OK) 10557c478bd9Sstevel@tonic-gate return (err); 1056a1be23daSdp if ((err = newprop(newnode, DTD_ATTR_DIR, tabptr->zone_fs_dir)) != Z_OK) 10577c478bd9Sstevel@tonic-gate return (err); 1058a1be23daSdp if ((err = newprop(newnode, DTD_ATTR_TYPE, 10597c478bd9Sstevel@tonic-gate tabptr->zone_fs_type)) != Z_OK) 10607c478bd9Sstevel@tonic-gate return (err); 10617c478bd9Sstevel@tonic-gate if (tabptr->zone_fs_options != NULL) { 10627c478bd9Sstevel@tonic-gate for (ptr = tabptr->zone_fs_options; ptr != NULL; 10637c478bd9Sstevel@tonic-gate ptr = ptr->zone_fsopt_next) { 10647c478bd9Sstevel@tonic-gate options_node = xmlNewTextChild(newnode, NULL, 10657c478bd9Sstevel@tonic-gate DTD_ELEM_FSOPTION, NULL); 1066a1be23daSdp if ((err = newprop(options_node, DTD_ATTR_NAME, 10677c478bd9Sstevel@tonic-gate ptr->zone_fsopt_opt)) != Z_OK) 10687c478bd9Sstevel@tonic-gate return (err); 10697c478bd9Sstevel@tonic-gate } 10707c478bd9Sstevel@tonic-gate } 10717c478bd9Sstevel@tonic-gate return (Z_OK); 10727c478bd9Sstevel@tonic-gate } 10737c478bd9Sstevel@tonic-gate 10747c478bd9Sstevel@tonic-gate int 10757c478bd9Sstevel@tonic-gate zonecfg_add_filesystem(zone_dochandle_t handle, struct zone_fstab *tabptr) 10767c478bd9Sstevel@tonic-gate { 10777c478bd9Sstevel@tonic-gate int err; 10787c478bd9Sstevel@tonic-gate 10797c478bd9Sstevel@tonic-gate if (tabptr == NULL) 10807c478bd9Sstevel@tonic-gate return (Z_INVAL); 10817c478bd9Sstevel@tonic-gate 10827c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 10837c478bd9Sstevel@tonic-gate return (err); 10847c478bd9Sstevel@tonic-gate 10857c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_filesystem_core(handle, tabptr)) != Z_OK) 10867c478bd9Sstevel@tonic-gate return (err); 10877c478bd9Sstevel@tonic-gate 10887c478bd9Sstevel@tonic-gate return (Z_OK); 10897c478bd9Sstevel@tonic-gate } 10907c478bd9Sstevel@tonic-gate 10917c478bd9Sstevel@tonic-gate static int 10927c478bd9Sstevel@tonic-gate zonecfg_add_ipd_core(zone_dochandle_t handle, struct zone_fstab *tabptr) 10937c478bd9Sstevel@tonic-gate { 10947c478bd9Sstevel@tonic-gate xmlNodePtr newnode, cur = handle->zone_dh_cur; 10957c478bd9Sstevel@tonic-gate int err; 10967c478bd9Sstevel@tonic-gate 10977c478bd9Sstevel@tonic-gate newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_IPD, NULL); 1098a1be23daSdp if ((err = newprop(newnode, DTD_ATTR_DIR, tabptr->zone_fs_dir)) != Z_OK) 10997c478bd9Sstevel@tonic-gate return (err); 11007c478bd9Sstevel@tonic-gate return (Z_OK); 11017c478bd9Sstevel@tonic-gate } 11027c478bd9Sstevel@tonic-gate 11037c478bd9Sstevel@tonic-gate int 11047c478bd9Sstevel@tonic-gate zonecfg_add_ipd(zone_dochandle_t handle, struct zone_fstab *tabptr) 11057c478bd9Sstevel@tonic-gate { 11067c478bd9Sstevel@tonic-gate int err; 11077c478bd9Sstevel@tonic-gate 11087c478bd9Sstevel@tonic-gate if (tabptr == NULL) 11097c478bd9Sstevel@tonic-gate return (Z_INVAL); 11107c478bd9Sstevel@tonic-gate 11117c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 11127c478bd9Sstevel@tonic-gate return (err); 11137c478bd9Sstevel@tonic-gate 11147c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_ipd_core(handle, tabptr)) != Z_OK) 11157c478bd9Sstevel@tonic-gate return (err); 11167c478bd9Sstevel@tonic-gate 11177c478bd9Sstevel@tonic-gate return (Z_OK); 11187c478bd9Sstevel@tonic-gate } 11197c478bd9Sstevel@tonic-gate 11207c478bd9Sstevel@tonic-gate int 11217c478bd9Sstevel@tonic-gate zonecfg_add_fs_option(struct zone_fstab *tabptr, char *option) 11227c478bd9Sstevel@tonic-gate { 11237c478bd9Sstevel@tonic-gate zone_fsopt_t *last, *old, *new; 11247c478bd9Sstevel@tonic-gate 11257c478bd9Sstevel@tonic-gate last = tabptr->zone_fs_options; 11267c478bd9Sstevel@tonic-gate for (old = last; old != NULL; old = old->zone_fsopt_next) 11277c478bd9Sstevel@tonic-gate last = old; /* walk to the end of the list */ 11287c478bd9Sstevel@tonic-gate new = (zone_fsopt_t *)malloc(sizeof (zone_fsopt_t)); 11297c478bd9Sstevel@tonic-gate if (new == NULL) 11307c478bd9Sstevel@tonic-gate return (Z_NOMEM); 11317c478bd9Sstevel@tonic-gate (void) strlcpy(new->zone_fsopt_opt, option, 11327c478bd9Sstevel@tonic-gate sizeof (new->zone_fsopt_opt)); 11337c478bd9Sstevel@tonic-gate new->zone_fsopt_next = NULL; 11347c478bd9Sstevel@tonic-gate if (last == NULL) 11357c478bd9Sstevel@tonic-gate tabptr->zone_fs_options = new; 11367c478bd9Sstevel@tonic-gate else 11377c478bd9Sstevel@tonic-gate last->zone_fsopt_next = new; 11387c478bd9Sstevel@tonic-gate return (Z_OK); 11397c478bd9Sstevel@tonic-gate } 11407c478bd9Sstevel@tonic-gate 11417c478bd9Sstevel@tonic-gate int 11427c478bd9Sstevel@tonic-gate zonecfg_remove_fs_option(struct zone_fstab *tabptr, char *option) 11437c478bd9Sstevel@tonic-gate { 11447c478bd9Sstevel@tonic-gate zone_fsopt_t *last, *this, *next; 11457c478bd9Sstevel@tonic-gate 11467c478bd9Sstevel@tonic-gate last = tabptr->zone_fs_options; 11477c478bd9Sstevel@tonic-gate for (this = last; this != NULL; this = this->zone_fsopt_next) { 11487c478bd9Sstevel@tonic-gate if (strcmp(this->zone_fsopt_opt, option) == 0) { 11497c478bd9Sstevel@tonic-gate next = this->zone_fsopt_next; 11507c478bd9Sstevel@tonic-gate if (this == tabptr->zone_fs_options) 11517c478bd9Sstevel@tonic-gate tabptr->zone_fs_options = next; 11527c478bd9Sstevel@tonic-gate else 11537c478bd9Sstevel@tonic-gate last->zone_fsopt_next = next; 11547c478bd9Sstevel@tonic-gate free(this); 11557c478bd9Sstevel@tonic-gate return (Z_OK); 11567c478bd9Sstevel@tonic-gate } else 11577c478bd9Sstevel@tonic-gate last = this; 11587c478bd9Sstevel@tonic-gate } 11597c478bd9Sstevel@tonic-gate return (Z_NO_PROPERTY_ID); 11607c478bd9Sstevel@tonic-gate } 11617c478bd9Sstevel@tonic-gate 11627c478bd9Sstevel@tonic-gate void 11637c478bd9Sstevel@tonic-gate zonecfg_free_fs_option_list(zone_fsopt_t *list) 11647c478bd9Sstevel@tonic-gate { 11657c478bd9Sstevel@tonic-gate zone_fsopt_t *this, *next; 11667c478bd9Sstevel@tonic-gate 11677c478bd9Sstevel@tonic-gate for (this = list; this != NULL; this = next) { 11687c478bd9Sstevel@tonic-gate next = this->zone_fsopt_next; 11697c478bd9Sstevel@tonic-gate free(this); 11707c478bd9Sstevel@tonic-gate } 11717c478bd9Sstevel@tonic-gate } 11727c478bd9Sstevel@tonic-gate 11737c478bd9Sstevel@tonic-gate void 11747c478bd9Sstevel@tonic-gate zonecfg_free_rctl_value_list(struct zone_rctlvaltab *valtab) 11757c478bd9Sstevel@tonic-gate { 11767c478bd9Sstevel@tonic-gate if (valtab == NULL) 11777c478bd9Sstevel@tonic-gate return; 11787c478bd9Sstevel@tonic-gate zonecfg_free_rctl_value_list(valtab->zone_rctlval_next); 11797c478bd9Sstevel@tonic-gate free(valtab); 11807c478bd9Sstevel@tonic-gate } 11817c478bd9Sstevel@tonic-gate 11827c478bd9Sstevel@tonic-gate static boolean_t 11837c478bd9Sstevel@tonic-gate match_prop(xmlNodePtr cur, const xmlChar *attr, char *user_prop) 11847c478bd9Sstevel@tonic-gate { 11857c478bd9Sstevel@tonic-gate xmlChar *gotten_prop; 11867c478bd9Sstevel@tonic-gate int prop_result; 11877c478bd9Sstevel@tonic-gate 11887c478bd9Sstevel@tonic-gate gotten_prop = xmlGetProp(cur, attr); 11897c478bd9Sstevel@tonic-gate if (gotten_prop == NULL) /* shouldn't happen */ 11907c478bd9Sstevel@tonic-gate return (B_FALSE); 11917c478bd9Sstevel@tonic-gate prop_result = xmlStrcmp(gotten_prop, (const xmlChar *) user_prop); 11927c478bd9Sstevel@tonic-gate xmlFree(gotten_prop); 11937c478bd9Sstevel@tonic-gate return ((prop_result == 0)); 11947c478bd9Sstevel@tonic-gate } 11957c478bd9Sstevel@tonic-gate 11967c478bd9Sstevel@tonic-gate static int 11977c478bd9Sstevel@tonic-gate zonecfg_delete_filesystem_core(zone_dochandle_t handle, 11987c478bd9Sstevel@tonic-gate struct zone_fstab *tabptr) 11997c478bd9Sstevel@tonic-gate { 12007c478bd9Sstevel@tonic-gate xmlNodePtr cur = handle->zone_dh_cur; 12017c478bd9Sstevel@tonic-gate boolean_t dir_match, spec_match, raw_match, type_match; 12027c478bd9Sstevel@tonic-gate 12037c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 12047c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_FS)) 12057c478bd9Sstevel@tonic-gate continue; 12067c478bd9Sstevel@tonic-gate dir_match = match_prop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir); 12077c478bd9Sstevel@tonic-gate spec_match = match_prop(cur, DTD_ATTR_SPECIAL, 12087c478bd9Sstevel@tonic-gate tabptr->zone_fs_special); 12097c478bd9Sstevel@tonic-gate raw_match = match_prop(cur, DTD_ATTR_RAW, 12107c478bd9Sstevel@tonic-gate tabptr->zone_fs_raw); 12117c478bd9Sstevel@tonic-gate type_match = match_prop(cur, DTD_ATTR_TYPE, 12127c478bd9Sstevel@tonic-gate tabptr->zone_fs_type); 12137c478bd9Sstevel@tonic-gate if (dir_match && spec_match && raw_match && type_match) { 12147c478bd9Sstevel@tonic-gate xmlUnlinkNode(cur); 12157c478bd9Sstevel@tonic-gate xmlFreeNode(cur); 12167c478bd9Sstevel@tonic-gate return (Z_OK); 12177c478bd9Sstevel@tonic-gate } 12187c478bd9Sstevel@tonic-gate } 12197c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 12207c478bd9Sstevel@tonic-gate } 12217c478bd9Sstevel@tonic-gate 12227c478bd9Sstevel@tonic-gate int 12237c478bd9Sstevel@tonic-gate zonecfg_delete_filesystem(zone_dochandle_t handle, struct zone_fstab *tabptr) 12247c478bd9Sstevel@tonic-gate { 12257c478bd9Sstevel@tonic-gate int err; 12267c478bd9Sstevel@tonic-gate 12277c478bd9Sstevel@tonic-gate if (tabptr == NULL) 12287c478bd9Sstevel@tonic-gate return (Z_INVAL); 12297c478bd9Sstevel@tonic-gate 12307c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 12317c478bd9Sstevel@tonic-gate return (err); 12327c478bd9Sstevel@tonic-gate 12337c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_filesystem_core(handle, tabptr)) != Z_OK) 12347c478bd9Sstevel@tonic-gate return (err); 12357c478bd9Sstevel@tonic-gate 12367c478bd9Sstevel@tonic-gate return (Z_OK); 12377c478bd9Sstevel@tonic-gate } 12387c478bd9Sstevel@tonic-gate 12397c478bd9Sstevel@tonic-gate int 12407c478bd9Sstevel@tonic-gate zonecfg_modify_filesystem( 12417c478bd9Sstevel@tonic-gate zone_dochandle_t handle, 12427c478bd9Sstevel@tonic-gate struct zone_fstab *oldtabptr, 12437c478bd9Sstevel@tonic-gate struct zone_fstab *newtabptr) 12447c478bd9Sstevel@tonic-gate { 12457c478bd9Sstevel@tonic-gate int err; 12467c478bd9Sstevel@tonic-gate 12477c478bd9Sstevel@tonic-gate if (oldtabptr == NULL || newtabptr == NULL) 12487c478bd9Sstevel@tonic-gate return (Z_INVAL); 12497c478bd9Sstevel@tonic-gate 12507c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 12517c478bd9Sstevel@tonic-gate return (err); 12527c478bd9Sstevel@tonic-gate 12537c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_filesystem_core(handle, oldtabptr)) != Z_OK) 12547c478bd9Sstevel@tonic-gate return (err); 12557c478bd9Sstevel@tonic-gate 12567c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_filesystem_core(handle, newtabptr)) != Z_OK) 12577c478bd9Sstevel@tonic-gate return (err); 12587c478bd9Sstevel@tonic-gate 12597c478bd9Sstevel@tonic-gate return (Z_OK); 12607c478bd9Sstevel@tonic-gate } 12617c478bd9Sstevel@tonic-gate 12627c478bd9Sstevel@tonic-gate static int 12637c478bd9Sstevel@tonic-gate zonecfg_delete_ipd_core(zone_dochandle_t handle, struct zone_fstab *tabptr) 12647c478bd9Sstevel@tonic-gate { 12657c478bd9Sstevel@tonic-gate xmlNodePtr cur = handle->zone_dh_cur; 12667c478bd9Sstevel@tonic-gate 12677c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 12687c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_IPD)) 12697c478bd9Sstevel@tonic-gate continue; 12707c478bd9Sstevel@tonic-gate if (match_prop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir)) { 12717c478bd9Sstevel@tonic-gate xmlUnlinkNode(cur); 12727c478bd9Sstevel@tonic-gate xmlFreeNode(cur); 12737c478bd9Sstevel@tonic-gate return (Z_OK); 12747c478bd9Sstevel@tonic-gate } 12757c478bd9Sstevel@tonic-gate } 12767c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 12777c478bd9Sstevel@tonic-gate } 12787c478bd9Sstevel@tonic-gate 12797c478bd9Sstevel@tonic-gate int 12807c478bd9Sstevel@tonic-gate zonecfg_delete_ipd(zone_dochandle_t handle, struct zone_fstab *tabptr) 12817c478bd9Sstevel@tonic-gate { 12827c478bd9Sstevel@tonic-gate int err; 12837c478bd9Sstevel@tonic-gate 12847c478bd9Sstevel@tonic-gate if (tabptr == NULL) 12857c478bd9Sstevel@tonic-gate return (Z_INVAL); 12867c478bd9Sstevel@tonic-gate 12877c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 12887c478bd9Sstevel@tonic-gate return (err); 12897c478bd9Sstevel@tonic-gate 12907c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_ipd_core(handle, tabptr)) != Z_OK) 12917c478bd9Sstevel@tonic-gate return (err); 12927c478bd9Sstevel@tonic-gate 12937c478bd9Sstevel@tonic-gate return (Z_OK); 12947c478bd9Sstevel@tonic-gate } 12957c478bd9Sstevel@tonic-gate 12967c478bd9Sstevel@tonic-gate int 12977c478bd9Sstevel@tonic-gate zonecfg_modify_ipd(zone_dochandle_t handle, struct zone_fstab *oldtabptr, 12987c478bd9Sstevel@tonic-gate struct zone_fstab *newtabptr) 12997c478bd9Sstevel@tonic-gate { 13007c478bd9Sstevel@tonic-gate int err; 13017c478bd9Sstevel@tonic-gate 13027c478bd9Sstevel@tonic-gate if (oldtabptr == NULL || newtabptr == NULL) 13037c478bd9Sstevel@tonic-gate return (Z_INVAL); 13047c478bd9Sstevel@tonic-gate 13057c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 13067c478bd9Sstevel@tonic-gate return (err); 13077c478bd9Sstevel@tonic-gate 13087c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_ipd_core(handle, oldtabptr)) != Z_OK) 13097c478bd9Sstevel@tonic-gate return (err); 13107c478bd9Sstevel@tonic-gate 13117c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_ipd_core(handle, newtabptr)) != Z_OK) 13127c478bd9Sstevel@tonic-gate return (err); 13137c478bd9Sstevel@tonic-gate 13147c478bd9Sstevel@tonic-gate return (Z_OK); 13157c478bd9Sstevel@tonic-gate } 13167c478bd9Sstevel@tonic-gate 13177c478bd9Sstevel@tonic-gate static int 13187c478bd9Sstevel@tonic-gate fetchprop(xmlNodePtr cur, const xmlChar *propname, char *dst, size_t dstsize) 13197c478bd9Sstevel@tonic-gate { 13207c478bd9Sstevel@tonic-gate xmlChar *property; 13217c478bd9Sstevel@tonic-gate size_t srcsize; 13227c478bd9Sstevel@tonic-gate 13237c478bd9Sstevel@tonic-gate if ((property = xmlGetProp(cur, propname)) == NULL) 13247c478bd9Sstevel@tonic-gate return (Z_BAD_PROPERTY); 13257c478bd9Sstevel@tonic-gate srcsize = strlcpy(dst, (char *)property, dstsize); 13267c478bd9Sstevel@tonic-gate xmlFree(property); 13277c478bd9Sstevel@tonic-gate if (srcsize >= dstsize) 13287c478bd9Sstevel@tonic-gate return (Z_TOO_BIG); 13297c478bd9Sstevel@tonic-gate return (Z_OK); 13307c478bd9Sstevel@tonic-gate } 13317c478bd9Sstevel@tonic-gate 13327c478bd9Sstevel@tonic-gate int 13337c478bd9Sstevel@tonic-gate zonecfg_lookup_filesystem( 13347c478bd9Sstevel@tonic-gate zone_dochandle_t handle, 13357c478bd9Sstevel@tonic-gate struct zone_fstab *tabptr) 13367c478bd9Sstevel@tonic-gate { 13377c478bd9Sstevel@tonic-gate xmlNodePtr cur, options, firstmatch; 13387c478bd9Sstevel@tonic-gate int err; 13397c478bd9Sstevel@tonic-gate char dirname[MAXPATHLEN], special[MAXPATHLEN], raw[MAXPATHLEN]; 13407c478bd9Sstevel@tonic-gate char type[FSTYPSZ]; 13417c478bd9Sstevel@tonic-gate char options_str[MAX_MNTOPT_STR]; 13427c478bd9Sstevel@tonic-gate 13437c478bd9Sstevel@tonic-gate if (tabptr == NULL) 13447c478bd9Sstevel@tonic-gate return (Z_INVAL); 13457c478bd9Sstevel@tonic-gate 13467c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 13477c478bd9Sstevel@tonic-gate return (err); 13487c478bd9Sstevel@tonic-gate 13497c478bd9Sstevel@tonic-gate /* 13507c478bd9Sstevel@tonic-gate * Walk the list of children looking for matches on any properties 13517c478bd9Sstevel@tonic-gate * specified in the fstab parameter. If more than one resource 13527c478bd9Sstevel@tonic-gate * matches, we return Z_INSUFFICIENT_SPEC; if none match, we return 13537c478bd9Sstevel@tonic-gate * Z_NO_RESOURCE_ID. 13547c478bd9Sstevel@tonic-gate */ 13557c478bd9Sstevel@tonic-gate cur = handle->zone_dh_cur; 13567c478bd9Sstevel@tonic-gate firstmatch = NULL; 13577c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 13587c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_FS)) 13597c478bd9Sstevel@tonic-gate continue; 13607c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_fs_dir) > 0) { 13617c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_DIR, dirname, 13627c478bd9Sstevel@tonic-gate sizeof (dirname)) == Z_OK) && 13637c478bd9Sstevel@tonic-gate (strcmp(tabptr->zone_fs_dir, dirname) == 0)) { 13647c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 13657c478bd9Sstevel@tonic-gate firstmatch = cur; 13667c478bd9Sstevel@tonic-gate else 13677c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 13687c478bd9Sstevel@tonic-gate } 13697c478bd9Sstevel@tonic-gate } 13707c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_fs_special) > 0) { 13717c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_SPECIAL, special, 13727c478bd9Sstevel@tonic-gate sizeof (special)) == Z_OK)) { 13737c478bd9Sstevel@tonic-gate if (strcmp(tabptr->zone_fs_special, 13747c478bd9Sstevel@tonic-gate special) == 0) { 13757c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 13767c478bd9Sstevel@tonic-gate firstmatch = cur; 13777c478bd9Sstevel@tonic-gate else if (firstmatch != cur) 13787c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 13797c478bd9Sstevel@tonic-gate } else { 13807c478bd9Sstevel@tonic-gate /* 13817c478bd9Sstevel@tonic-gate * If another property matched but this 13827c478bd9Sstevel@tonic-gate * one doesn't then reset firstmatch. 13837c478bd9Sstevel@tonic-gate */ 13847c478bd9Sstevel@tonic-gate if (firstmatch == cur) 13857c478bd9Sstevel@tonic-gate firstmatch = NULL; 13867c478bd9Sstevel@tonic-gate } 13877c478bd9Sstevel@tonic-gate } 13887c478bd9Sstevel@tonic-gate } 13897c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_fs_raw) > 0) { 13907c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_RAW, raw, 13917c478bd9Sstevel@tonic-gate sizeof (raw)) == Z_OK)) { 13927c478bd9Sstevel@tonic-gate if (strcmp(tabptr->zone_fs_raw, raw) == 0) { 13937c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 13947c478bd9Sstevel@tonic-gate firstmatch = cur; 13957c478bd9Sstevel@tonic-gate else if (firstmatch != cur) 13967c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 13977c478bd9Sstevel@tonic-gate } else { 13987c478bd9Sstevel@tonic-gate /* 13997c478bd9Sstevel@tonic-gate * If another property matched but this 14007c478bd9Sstevel@tonic-gate * one doesn't then reset firstmatch. 14017c478bd9Sstevel@tonic-gate */ 14027c478bd9Sstevel@tonic-gate if (firstmatch == cur) 14037c478bd9Sstevel@tonic-gate firstmatch = NULL; 14047c478bd9Sstevel@tonic-gate } 14057c478bd9Sstevel@tonic-gate } 14067c478bd9Sstevel@tonic-gate } 14077c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_fs_type) > 0) { 14087c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_TYPE, type, 14097c478bd9Sstevel@tonic-gate sizeof (type)) == Z_OK)) { 14107c478bd9Sstevel@tonic-gate if (strcmp(tabptr->zone_fs_type, type) == 0) { 14117c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 14127c478bd9Sstevel@tonic-gate firstmatch = cur; 14137c478bd9Sstevel@tonic-gate else if (firstmatch != cur) 14147c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 14157c478bd9Sstevel@tonic-gate } else { 14167c478bd9Sstevel@tonic-gate /* 14177c478bd9Sstevel@tonic-gate * If another property matched but this 14187c478bd9Sstevel@tonic-gate * one doesn't then reset firstmatch. 14197c478bd9Sstevel@tonic-gate */ 14207c478bd9Sstevel@tonic-gate if (firstmatch == cur) 14217c478bd9Sstevel@tonic-gate firstmatch = NULL; 14227c478bd9Sstevel@tonic-gate } 14237c478bd9Sstevel@tonic-gate } 14247c478bd9Sstevel@tonic-gate } 14257c478bd9Sstevel@tonic-gate } 14267c478bd9Sstevel@tonic-gate 14277c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 14287c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 14297c478bd9Sstevel@tonic-gate 14307c478bd9Sstevel@tonic-gate cur = firstmatch; 14317c478bd9Sstevel@tonic-gate 14327c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir, 14337c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_dir))) != Z_OK) 14347c478bd9Sstevel@tonic-gate return (err); 14357c478bd9Sstevel@tonic-gate 14367c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_SPECIAL, tabptr->zone_fs_special, 14377c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_special))) != Z_OK) 14387c478bd9Sstevel@tonic-gate return (err); 14397c478bd9Sstevel@tonic-gate 14407c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_RAW, tabptr->zone_fs_raw, 14417c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_raw))) != Z_OK) 14427c478bd9Sstevel@tonic-gate return (err); 14437c478bd9Sstevel@tonic-gate 14447c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_TYPE, tabptr->zone_fs_type, 14457c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_type))) != Z_OK) 14467c478bd9Sstevel@tonic-gate return (err); 14477c478bd9Sstevel@tonic-gate 14487c478bd9Sstevel@tonic-gate /* options are optional */ 14497c478bd9Sstevel@tonic-gate tabptr->zone_fs_options = NULL; 14507c478bd9Sstevel@tonic-gate for (options = cur->xmlChildrenNode; options != NULL; 14517c478bd9Sstevel@tonic-gate options = options->next) { 14527c478bd9Sstevel@tonic-gate if ((fetchprop(options, DTD_ATTR_NAME, options_str, 14537c478bd9Sstevel@tonic-gate sizeof (options_str)) != Z_OK)) 14547c478bd9Sstevel@tonic-gate break; 14557c478bd9Sstevel@tonic-gate if (zonecfg_add_fs_option(tabptr, options_str) != Z_OK) 14567c478bd9Sstevel@tonic-gate break; 14577c478bd9Sstevel@tonic-gate } 14587c478bd9Sstevel@tonic-gate return (Z_OK); 14597c478bd9Sstevel@tonic-gate } 14607c478bd9Sstevel@tonic-gate 14617c478bd9Sstevel@tonic-gate int 14627c478bd9Sstevel@tonic-gate zonecfg_lookup_ipd(zone_dochandle_t handle, struct zone_fstab *tabptr) 14637c478bd9Sstevel@tonic-gate { 14647c478bd9Sstevel@tonic-gate xmlNodePtr cur, match; 14657c478bd9Sstevel@tonic-gate int err; 14667c478bd9Sstevel@tonic-gate char dirname[MAXPATHLEN]; 14677c478bd9Sstevel@tonic-gate 14687c478bd9Sstevel@tonic-gate if (tabptr == NULL) 14697c478bd9Sstevel@tonic-gate return (Z_INVAL); 14707c478bd9Sstevel@tonic-gate 14717c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 14727c478bd9Sstevel@tonic-gate return (err); 14737c478bd9Sstevel@tonic-gate 14747c478bd9Sstevel@tonic-gate /* 14757c478bd9Sstevel@tonic-gate * General algorithm: 14767c478bd9Sstevel@tonic-gate * Walk the list of children looking for matches on any properties 14777c478bd9Sstevel@tonic-gate * specified in the fstab parameter. If more than one resource 14787c478bd9Sstevel@tonic-gate * matches, we return Z_INSUFFICIENT_SPEC; if none match, we return 14797c478bd9Sstevel@tonic-gate * Z_NO_RESOURCE_ID. 14807c478bd9Sstevel@tonic-gate */ 14817c478bd9Sstevel@tonic-gate cur = handle->zone_dh_cur; 14827c478bd9Sstevel@tonic-gate match = NULL; 14837c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 14847c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_IPD)) 14857c478bd9Sstevel@tonic-gate continue; 14867c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_fs_dir) > 0) { 14877c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_DIR, dirname, 14887c478bd9Sstevel@tonic-gate sizeof (dirname)) == Z_OK) && 14897c478bd9Sstevel@tonic-gate (strcmp(tabptr->zone_fs_dir, dirname) == 0)) { 14907c478bd9Sstevel@tonic-gate if (match == NULL) 14917c478bd9Sstevel@tonic-gate match = cur; 14927c478bd9Sstevel@tonic-gate else 14937c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 14947c478bd9Sstevel@tonic-gate } 14957c478bd9Sstevel@tonic-gate } 14967c478bd9Sstevel@tonic-gate } 14977c478bd9Sstevel@tonic-gate 14987c478bd9Sstevel@tonic-gate if (match == NULL) 14997c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 15007c478bd9Sstevel@tonic-gate 15017c478bd9Sstevel@tonic-gate cur = match; 15027c478bd9Sstevel@tonic-gate 15037c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir, 15047c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_dir))) != Z_OK) 15057c478bd9Sstevel@tonic-gate return (err); 15067c478bd9Sstevel@tonic-gate 15077c478bd9Sstevel@tonic-gate return (Z_OK); 15087c478bd9Sstevel@tonic-gate } 15097c478bd9Sstevel@tonic-gate 15107c478bd9Sstevel@tonic-gate /* 15117c478bd9Sstevel@tonic-gate * Compare two IP addresses in string form. Allow for the possibility that 15127c478bd9Sstevel@tonic-gate * one might have "/<prefix-length>" at the end: allow a match on just the 15137c478bd9Sstevel@tonic-gate * IP address (or host name) part. 15147c478bd9Sstevel@tonic-gate */ 15157c478bd9Sstevel@tonic-gate 15167c478bd9Sstevel@tonic-gate boolean_t 15177c478bd9Sstevel@tonic-gate zonecfg_same_net_address(char *a1, char *a2) 15187c478bd9Sstevel@tonic-gate { 15197c478bd9Sstevel@tonic-gate char *slashp, *slashp1, *slashp2; 15207c478bd9Sstevel@tonic-gate int result; 15217c478bd9Sstevel@tonic-gate 15227c478bd9Sstevel@tonic-gate if (strcmp(a1, a2) == 0) 15237c478bd9Sstevel@tonic-gate return (B_TRUE); 15247c478bd9Sstevel@tonic-gate 15257c478bd9Sstevel@tonic-gate /* 15267c478bd9Sstevel@tonic-gate * If neither has a slash or both do, they need to match to be 15277c478bd9Sstevel@tonic-gate * considered the same, but they did not match above, so fail. 15287c478bd9Sstevel@tonic-gate */ 15297c478bd9Sstevel@tonic-gate slashp1 = strchr(a1, '/'); 15307c478bd9Sstevel@tonic-gate slashp2 = strchr(a2, '/'); 15317c478bd9Sstevel@tonic-gate if ((slashp1 == NULL && slashp2 == NULL) || 15327c478bd9Sstevel@tonic-gate (slashp1 != NULL && slashp2 != NULL)) 15337c478bd9Sstevel@tonic-gate return (B_FALSE); 15347c478bd9Sstevel@tonic-gate 15357c478bd9Sstevel@tonic-gate /* 15367c478bd9Sstevel@tonic-gate * Only one had a slash: pick that one, zero out the slash, compare 15377c478bd9Sstevel@tonic-gate * the "address only" strings, restore the slash, and return the 15387c478bd9Sstevel@tonic-gate * result of the comparison. 15397c478bd9Sstevel@tonic-gate */ 15407c478bd9Sstevel@tonic-gate slashp = (slashp1 == NULL) ? slashp2 : slashp1; 15417c478bd9Sstevel@tonic-gate *slashp = '\0'; 15427c478bd9Sstevel@tonic-gate result = strcmp(a1, a2); 15437c478bd9Sstevel@tonic-gate *slashp = '/'; 15447c478bd9Sstevel@tonic-gate return ((result == 0)); 15457c478bd9Sstevel@tonic-gate } 15467c478bd9Sstevel@tonic-gate 15477c478bd9Sstevel@tonic-gate int 15487c478bd9Sstevel@tonic-gate zonecfg_valid_net_address(char *address, struct lifreq *lifr) 15497c478bd9Sstevel@tonic-gate { 15507c478bd9Sstevel@tonic-gate struct sockaddr_in *sin4; 15517c478bd9Sstevel@tonic-gate struct sockaddr_in6 *sin6; 15527c478bd9Sstevel@tonic-gate struct addrinfo hints, *result; 15537c478bd9Sstevel@tonic-gate char *slashp = strchr(address, '/'); 15547c478bd9Sstevel@tonic-gate 15557c478bd9Sstevel@tonic-gate bzero(lifr, sizeof (struct lifreq)); 15567c478bd9Sstevel@tonic-gate sin4 = (struct sockaddr_in *)&lifr->lifr_addr; 15577c478bd9Sstevel@tonic-gate sin6 = (struct sockaddr_in6 *)&lifr->lifr_addr; 15587c478bd9Sstevel@tonic-gate if (slashp != NULL) 15597c478bd9Sstevel@tonic-gate *slashp = '\0'; 15607c478bd9Sstevel@tonic-gate if (inet_pton(AF_INET, address, &sin4->sin_addr) == 1) { 15617c478bd9Sstevel@tonic-gate sin4->sin_family = AF_INET; 15627c478bd9Sstevel@tonic-gate } else if (inet_pton(AF_INET6, address, &sin6->sin6_addr) == 1) { 15637c478bd9Sstevel@tonic-gate if (slashp == NULL) 15647c478bd9Sstevel@tonic-gate return (Z_IPV6_ADDR_PREFIX_LEN); 15657c478bd9Sstevel@tonic-gate sin6->sin6_family = AF_INET6; 15667c478bd9Sstevel@tonic-gate } else { 15677c478bd9Sstevel@tonic-gate /* "address" may be a host name */ 15687c478bd9Sstevel@tonic-gate (void) memset(&hints, 0, sizeof (hints)); 15697c478bd9Sstevel@tonic-gate hints.ai_family = PF_INET; 15707c478bd9Sstevel@tonic-gate if (getaddrinfo(address, NULL, &hints, &result) != 0) 15717c478bd9Sstevel@tonic-gate return (Z_BOGUS_ADDRESS); 15727c478bd9Sstevel@tonic-gate sin4->sin_family = result->ai_family; 1573a1be23daSdp 15747c478bd9Sstevel@tonic-gate (void) memcpy(&sin4->sin_addr, 15757c478bd9Sstevel@tonic-gate /* LINTED E_BAD_PTR_CAST_ALIGN */ 15767c478bd9Sstevel@tonic-gate &((struct sockaddr_in *)result->ai_addr)->sin_addr, 15777c478bd9Sstevel@tonic-gate sizeof (struct in_addr)); 1578a1be23daSdp 15797c478bd9Sstevel@tonic-gate freeaddrinfo(result); 15807c478bd9Sstevel@tonic-gate } 15817c478bd9Sstevel@tonic-gate return (Z_OK); 15827c478bd9Sstevel@tonic-gate } 15837c478bd9Sstevel@tonic-gate 15847c478bd9Sstevel@tonic-gate int 15857c478bd9Sstevel@tonic-gate zonecfg_lookup_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr) 15867c478bd9Sstevel@tonic-gate { 15877c478bd9Sstevel@tonic-gate xmlNodePtr cur, firstmatch; 15887c478bd9Sstevel@tonic-gate int err; 15897c478bd9Sstevel@tonic-gate char address[INET6_ADDRSTRLEN], physical[LIFNAMSIZ]; 15907c478bd9Sstevel@tonic-gate 15917c478bd9Sstevel@tonic-gate if (tabptr == NULL) 15927c478bd9Sstevel@tonic-gate return (Z_INVAL); 15937c478bd9Sstevel@tonic-gate 15947c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 15957c478bd9Sstevel@tonic-gate return (err); 15967c478bd9Sstevel@tonic-gate 15977c478bd9Sstevel@tonic-gate cur = handle->zone_dh_cur; 15987c478bd9Sstevel@tonic-gate firstmatch = NULL; 15997c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 16007c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_NET)) 16017c478bd9Sstevel@tonic-gate continue; 16027c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_nwif_physical) > 0) { 16037c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_PHYSICAL, physical, 16047c478bd9Sstevel@tonic-gate sizeof (physical)) == Z_OK) && 16057c478bd9Sstevel@tonic-gate (strcmp(tabptr->zone_nwif_physical, 16067c478bd9Sstevel@tonic-gate physical) == 0)) { 16077c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 16087c478bd9Sstevel@tonic-gate firstmatch = cur; 16097c478bd9Sstevel@tonic-gate else 16107c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 16117c478bd9Sstevel@tonic-gate } 16127c478bd9Sstevel@tonic-gate } 16137c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_nwif_address) > 0) { 16147c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_ADDRESS, address, 16157c478bd9Sstevel@tonic-gate sizeof (address)) == Z_OK)) { 16167c478bd9Sstevel@tonic-gate if (zonecfg_same_net_address( 16177c478bd9Sstevel@tonic-gate tabptr->zone_nwif_address, address)) { 16187c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 16197c478bd9Sstevel@tonic-gate firstmatch = cur; 16207c478bd9Sstevel@tonic-gate else if (firstmatch != cur) 16217c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 16227c478bd9Sstevel@tonic-gate } else { 16237c478bd9Sstevel@tonic-gate /* 16247c478bd9Sstevel@tonic-gate * If another property matched but this 16257c478bd9Sstevel@tonic-gate * one doesn't then reset firstmatch. 16267c478bd9Sstevel@tonic-gate */ 16277c478bd9Sstevel@tonic-gate if (firstmatch == cur) 16287c478bd9Sstevel@tonic-gate firstmatch = NULL; 16297c478bd9Sstevel@tonic-gate } 16307c478bd9Sstevel@tonic-gate } 16317c478bd9Sstevel@tonic-gate } 16327c478bd9Sstevel@tonic-gate } 16337c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 16347c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 16357c478bd9Sstevel@tonic-gate 16367c478bd9Sstevel@tonic-gate cur = firstmatch; 16377c478bd9Sstevel@tonic-gate 16387c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_PHYSICAL, tabptr->zone_nwif_physical, 16397c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_nwif_physical))) != Z_OK) 16407c478bd9Sstevel@tonic-gate return (err); 16417c478bd9Sstevel@tonic-gate 16427c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_ADDRESS, tabptr->zone_nwif_address, 16437c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_nwif_address))) != Z_OK) 16447c478bd9Sstevel@tonic-gate return (err); 16457c478bd9Sstevel@tonic-gate 16467c478bd9Sstevel@tonic-gate return (Z_OK); 16477c478bd9Sstevel@tonic-gate } 16487c478bd9Sstevel@tonic-gate 16497c478bd9Sstevel@tonic-gate static int 16507c478bd9Sstevel@tonic-gate zonecfg_add_nwif_core(zone_dochandle_t handle, struct zone_nwiftab *tabptr) 16517c478bd9Sstevel@tonic-gate { 16527c478bd9Sstevel@tonic-gate xmlNodePtr newnode, cur = handle->zone_dh_cur; 16537c478bd9Sstevel@tonic-gate int err; 16547c478bd9Sstevel@tonic-gate 16557c478bd9Sstevel@tonic-gate newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_NET, NULL); 1656a1be23daSdp if ((err = newprop(newnode, DTD_ATTR_ADDRESS, 16577c478bd9Sstevel@tonic-gate tabptr->zone_nwif_address)) != Z_OK) 16587c478bd9Sstevel@tonic-gate return (err); 1659a1be23daSdp if ((err = newprop(newnode, DTD_ATTR_PHYSICAL, 16607c478bd9Sstevel@tonic-gate tabptr->zone_nwif_physical)) != Z_OK) 16617c478bd9Sstevel@tonic-gate return (err); 16627c478bd9Sstevel@tonic-gate return (Z_OK); 16637c478bd9Sstevel@tonic-gate } 16647c478bd9Sstevel@tonic-gate 16657c478bd9Sstevel@tonic-gate int 16667c478bd9Sstevel@tonic-gate zonecfg_add_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr) 16677c478bd9Sstevel@tonic-gate { 16687c478bd9Sstevel@tonic-gate int err; 16697c478bd9Sstevel@tonic-gate 16707c478bd9Sstevel@tonic-gate if (tabptr == NULL) 16717c478bd9Sstevel@tonic-gate return (Z_INVAL); 16727c478bd9Sstevel@tonic-gate 16737c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 16747c478bd9Sstevel@tonic-gate return (err); 16757c478bd9Sstevel@tonic-gate 16767c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_nwif_core(handle, tabptr)) != Z_OK) 16777c478bd9Sstevel@tonic-gate return (err); 16787c478bd9Sstevel@tonic-gate 16797c478bd9Sstevel@tonic-gate return (Z_OK); 16807c478bd9Sstevel@tonic-gate } 16817c478bd9Sstevel@tonic-gate 16827c478bd9Sstevel@tonic-gate static int 16837c478bd9Sstevel@tonic-gate zonecfg_delete_nwif_core(zone_dochandle_t handle, struct zone_nwiftab *tabptr) 16847c478bd9Sstevel@tonic-gate { 16857c478bd9Sstevel@tonic-gate xmlNodePtr cur = handle->zone_dh_cur; 16867c478bd9Sstevel@tonic-gate boolean_t addr_match, phys_match; 16877c478bd9Sstevel@tonic-gate 16887c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 16897c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_NET)) 16907c478bd9Sstevel@tonic-gate continue; 16917c478bd9Sstevel@tonic-gate 16927c478bd9Sstevel@tonic-gate addr_match = match_prop(cur, DTD_ATTR_ADDRESS, 16937c478bd9Sstevel@tonic-gate tabptr->zone_nwif_address); 16947c478bd9Sstevel@tonic-gate phys_match = match_prop(cur, DTD_ATTR_PHYSICAL, 16957c478bd9Sstevel@tonic-gate tabptr->zone_nwif_physical); 16967c478bd9Sstevel@tonic-gate 16977c478bd9Sstevel@tonic-gate if (addr_match && phys_match) { 16987c478bd9Sstevel@tonic-gate xmlUnlinkNode(cur); 16997c478bd9Sstevel@tonic-gate xmlFreeNode(cur); 17007c478bd9Sstevel@tonic-gate return (Z_OK); 17017c478bd9Sstevel@tonic-gate } 17027c478bd9Sstevel@tonic-gate } 17037c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 17047c478bd9Sstevel@tonic-gate } 17057c478bd9Sstevel@tonic-gate 17067c478bd9Sstevel@tonic-gate int 17077c478bd9Sstevel@tonic-gate zonecfg_delete_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr) 17087c478bd9Sstevel@tonic-gate { 17097c478bd9Sstevel@tonic-gate int err; 17107c478bd9Sstevel@tonic-gate 17117c478bd9Sstevel@tonic-gate if (tabptr == NULL) 17127c478bd9Sstevel@tonic-gate return (Z_INVAL); 17137c478bd9Sstevel@tonic-gate 17147c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 17157c478bd9Sstevel@tonic-gate return (err); 17167c478bd9Sstevel@tonic-gate 17177c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_nwif_core(handle, tabptr)) != Z_OK) 17187c478bd9Sstevel@tonic-gate return (err); 17197c478bd9Sstevel@tonic-gate 17207c478bd9Sstevel@tonic-gate return (Z_OK); 17217c478bd9Sstevel@tonic-gate } 17227c478bd9Sstevel@tonic-gate 17237c478bd9Sstevel@tonic-gate int 17247c478bd9Sstevel@tonic-gate zonecfg_modify_nwif( 17257c478bd9Sstevel@tonic-gate zone_dochandle_t handle, 17267c478bd9Sstevel@tonic-gate struct zone_nwiftab *oldtabptr, 17277c478bd9Sstevel@tonic-gate struct zone_nwiftab *newtabptr) 17287c478bd9Sstevel@tonic-gate { 17297c478bd9Sstevel@tonic-gate int err; 17307c478bd9Sstevel@tonic-gate 17317c478bd9Sstevel@tonic-gate if (oldtabptr == NULL || newtabptr == NULL) 17327c478bd9Sstevel@tonic-gate return (Z_INVAL); 17337c478bd9Sstevel@tonic-gate 17347c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 17357c478bd9Sstevel@tonic-gate return (err); 17367c478bd9Sstevel@tonic-gate 17377c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_nwif_core(handle, oldtabptr)) != Z_OK) 17387c478bd9Sstevel@tonic-gate return (err); 17397c478bd9Sstevel@tonic-gate 17407c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_nwif_core(handle, newtabptr)) != Z_OK) 17417c478bd9Sstevel@tonic-gate return (err); 17427c478bd9Sstevel@tonic-gate 17437c478bd9Sstevel@tonic-gate return (Z_OK); 17447c478bd9Sstevel@tonic-gate } 17457c478bd9Sstevel@tonic-gate 17467c478bd9Sstevel@tonic-gate int 17477c478bd9Sstevel@tonic-gate zonecfg_lookup_dev(zone_dochandle_t handle, struct zone_devtab *tabptr) 17487c478bd9Sstevel@tonic-gate { 17497c478bd9Sstevel@tonic-gate xmlNodePtr cur, firstmatch; 17507c478bd9Sstevel@tonic-gate int err; 17517c478bd9Sstevel@tonic-gate char match[MAXPATHLEN]; 17527c478bd9Sstevel@tonic-gate 17537c478bd9Sstevel@tonic-gate if (tabptr == NULL) 17547c478bd9Sstevel@tonic-gate return (Z_INVAL); 17557c478bd9Sstevel@tonic-gate 17567c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 17577c478bd9Sstevel@tonic-gate return (err); 17587c478bd9Sstevel@tonic-gate 17597c478bd9Sstevel@tonic-gate cur = handle->zone_dh_cur; 17607c478bd9Sstevel@tonic-gate firstmatch = NULL; 17617c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 17627c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_DEVICE)) 17637c478bd9Sstevel@tonic-gate continue; 17647c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_dev_match) == 0) 17657c478bd9Sstevel@tonic-gate continue; 17667c478bd9Sstevel@tonic-gate 17677c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_MATCH, match, 17687c478bd9Sstevel@tonic-gate sizeof (match)) == Z_OK)) { 17697c478bd9Sstevel@tonic-gate if (strcmp(tabptr->zone_dev_match, 17707c478bd9Sstevel@tonic-gate match) == 0) { 17717c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 17727c478bd9Sstevel@tonic-gate firstmatch = cur; 17737c478bd9Sstevel@tonic-gate else if (firstmatch != cur) 17747c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 17757c478bd9Sstevel@tonic-gate } else { 17767c478bd9Sstevel@tonic-gate /* 17777c478bd9Sstevel@tonic-gate * If another property matched but this 17787c478bd9Sstevel@tonic-gate * one doesn't then reset firstmatch. 17797c478bd9Sstevel@tonic-gate */ 17807c478bd9Sstevel@tonic-gate if (firstmatch == cur) 17817c478bd9Sstevel@tonic-gate firstmatch = NULL; 17827c478bd9Sstevel@tonic-gate } 17837c478bd9Sstevel@tonic-gate } 17847c478bd9Sstevel@tonic-gate } 17857c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 17867c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 17877c478bd9Sstevel@tonic-gate 17887c478bd9Sstevel@tonic-gate cur = firstmatch; 17897c478bd9Sstevel@tonic-gate 17907c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_MATCH, tabptr->zone_dev_match, 17917c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_dev_match))) != Z_OK) 17927c478bd9Sstevel@tonic-gate return (err); 17937c478bd9Sstevel@tonic-gate 17947c478bd9Sstevel@tonic-gate return (Z_OK); 17957c478bd9Sstevel@tonic-gate } 17967c478bd9Sstevel@tonic-gate 17977c478bd9Sstevel@tonic-gate static int 17987c478bd9Sstevel@tonic-gate zonecfg_add_dev_core(zone_dochandle_t handle, struct zone_devtab *tabptr) 17997c478bd9Sstevel@tonic-gate { 18007c478bd9Sstevel@tonic-gate xmlNodePtr newnode, cur = handle->zone_dh_cur; 18017c478bd9Sstevel@tonic-gate int err; 18027c478bd9Sstevel@tonic-gate 18037c478bd9Sstevel@tonic-gate newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_DEVICE, NULL); 18047c478bd9Sstevel@tonic-gate 1805a1be23daSdp if ((err = newprop(newnode, DTD_ATTR_MATCH, 18067c478bd9Sstevel@tonic-gate tabptr->zone_dev_match)) != Z_OK) 18077c478bd9Sstevel@tonic-gate return (err); 18087c478bd9Sstevel@tonic-gate 18097c478bd9Sstevel@tonic-gate return (Z_OK); 18107c478bd9Sstevel@tonic-gate } 18117c478bd9Sstevel@tonic-gate 18127c478bd9Sstevel@tonic-gate int 18137c478bd9Sstevel@tonic-gate zonecfg_add_dev(zone_dochandle_t handle, struct zone_devtab *tabptr) 18147c478bd9Sstevel@tonic-gate { 18157c478bd9Sstevel@tonic-gate int err; 18167c478bd9Sstevel@tonic-gate 18177c478bd9Sstevel@tonic-gate if (tabptr == NULL) 18187c478bd9Sstevel@tonic-gate return (Z_INVAL); 18197c478bd9Sstevel@tonic-gate 18207c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 18217c478bd9Sstevel@tonic-gate return (err); 18227c478bd9Sstevel@tonic-gate 18237c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_dev_core(handle, tabptr)) != Z_OK) 18247c478bd9Sstevel@tonic-gate return (err); 18257c478bd9Sstevel@tonic-gate 18267c478bd9Sstevel@tonic-gate return (Z_OK); 18277c478bd9Sstevel@tonic-gate } 18287c478bd9Sstevel@tonic-gate 18297c478bd9Sstevel@tonic-gate static int 18307c478bd9Sstevel@tonic-gate zonecfg_delete_dev_core(zone_dochandle_t handle, struct zone_devtab *tabptr) 18317c478bd9Sstevel@tonic-gate { 18327c478bd9Sstevel@tonic-gate xmlNodePtr cur = handle->zone_dh_cur; 18337c478bd9Sstevel@tonic-gate int match_match; 18347c478bd9Sstevel@tonic-gate 18357c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 18367c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_DEVICE)) 18377c478bd9Sstevel@tonic-gate continue; 18387c478bd9Sstevel@tonic-gate 18397c478bd9Sstevel@tonic-gate match_match = match_prop(cur, DTD_ATTR_MATCH, 18407c478bd9Sstevel@tonic-gate tabptr->zone_dev_match); 18417c478bd9Sstevel@tonic-gate 18427c478bd9Sstevel@tonic-gate if (match_match) { 18437c478bd9Sstevel@tonic-gate xmlUnlinkNode(cur); 18447c478bd9Sstevel@tonic-gate xmlFreeNode(cur); 18457c478bd9Sstevel@tonic-gate return (Z_OK); 18467c478bd9Sstevel@tonic-gate } 18477c478bd9Sstevel@tonic-gate } 18487c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 18497c478bd9Sstevel@tonic-gate } 18507c478bd9Sstevel@tonic-gate 18517c478bd9Sstevel@tonic-gate int 18527c478bd9Sstevel@tonic-gate zonecfg_delete_dev(zone_dochandle_t handle, struct zone_devtab *tabptr) 18537c478bd9Sstevel@tonic-gate { 18547c478bd9Sstevel@tonic-gate int err; 18557c478bd9Sstevel@tonic-gate 18567c478bd9Sstevel@tonic-gate if (tabptr == NULL) 18577c478bd9Sstevel@tonic-gate return (Z_INVAL); 18587c478bd9Sstevel@tonic-gate 18597c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 18607c478bd9Sstevel@tonic-gate return (err); 18617c478bd9Sstevel@tonic-gate 18627c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_dev_core(handle, tabptr)) != Z_OK) 18637c478bd9Sstevel@tonic-gate return (err); 18647c478bd9Sstevel@tonic-gate 18657c478bd9Sstevel@tonic-gate return (Z_OK); 18667c478bd9Sstevel@tonic-gate } 18677c478bd9Sstevel@tonic-gate 18687c478bd9Sstevel@tonic-gate int 18697c478bd9Sstevel@tonic-gate zonecfg_modify_dev( 18707c478bd9Sstevel@tonic-gate zone_dochandle_t handle, 18717c478bd9Sstevel@tonic-gate struct zone_devtab *oldtabptr, 18727c478bd9Sstevel@tonic-gate struct zone_devtab *newtabptr) 18737c478bd9Sstevel@tonic-gate { 18747c478bd9Sstevel@tonic-gate int err; 18757c478bd9Sstevel@tonic-gate 18767c478bd9Sstevel@tonic-gate if (oldtabptr == NULL || newtabptr == NULL) 18777c478bd9Sstevel@tonic-gate return (Z_INVAL); 18787c478bd9Sstevel@tonic-gate 18797c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 18807c478bd9Sstevel@tonic-gate return (err); 18817c478bd9Sstevel@tonic-gate 18827c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_dev_core(handle, oldtabptr)) != Z_OK) 18837c478bd9Sstevel@tonic-gate return (err); 18847c478bd9Sstevel@tonic-gate 18857c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_dev_core(handle, newtabptr)) != Z_OK) 18867c478bd9Sstevel@tonic-gate return (err); 18877c478bd9Sstevel@tonic-gate 18887c478bd9Sstevel@tonic-gate return (Z_OK); 18897c478bd9Sstevel@tonic-gate } 18907c478bd9Sstevel@tonic-gate 18917c478bd9Sstevel@tonic-gate /* 18927c478bd9Sstevel@tonic-gate * This is the set of devices which must be present in every zone. Users 18937c478bd9Sstevel@tonic-gate * can augment this list with additional device rules in their zone 18947c478bd9Sstevel@tonic-gate * configuration, but at present cannot remove any of the this set of 18957c478bd9Sstevel@tonic-gate * standard devices. All matching is done by /dev pathname (the "/dev" 18967c478bd9Sstevel@tonic-gate * part is implicit. Try to keep rules which match a large number of 18977c478bd9Sstevel@tonic-gate * devices (like the pts rule) first. 18987c478bd9Sstevel@tonic-gate */ 18997c478bd9Sstevel@tonic-gate static const char *standard_devs[] = { 19007c478bd9Sstevel@tonic-gate "pts/*", 19017c478bd9Sstevel@tonic-gate "ptmx", 19027c478bd9Sstevel@tonic-gate "random", 19037c478bd9Sstevel@tonic-gate "urandom", 19047c478bd9Sstevel@tonic-gate "poll", 19057c478bd9Sstevel@tonic-gate "pool", 19067c478bd9Sstevel@tonic-gate "kstat", 19077c478bd9Sstevel@tonic-gate "zero", 19087c478bd9Sstevel@tonic-gate "null", 19097c478bd9Sstevel@tonic-gate "crypto", 19107c478bd9Sstevel@tonic-gate "cryptoadm", 19117c478bd9Sstevel@tonic-gate "ticots", 19127c478bd9Sstevel@tonic-gate "ticotsord", 19137c478bd9Sstevel@tonic-gate "ticlts", 19147c478bd9Sstevel@tonic-gate "lo0", 19157c478bd9Sstevel@tonic-gate "lo1", 19167c478bd9Sstevel@tonic-gate "lo2", 19177c478bd9Sstevel@tonic-gate "lo3", 19187c478bd9Sstevel@tonic-gate "sad/user", 19197c478bd9Sstevel@tonic-gate "tty", 19207c478bd9Sstevel@tonic-gate "logindmux", 19217c478bd9Sstevel@tonic-gate "log", 19227c478bd9Sstevel@tonic-gate "conslog", 19237c478bd9Sstevel@tonic-gate "arp", 19247c478bd9Sstevel@tonic-gate "tcp", 19257c478bd9Sstevel@tonic-gate "tcp6", 19267c478bd9Sstevel@tonic-gate "udp", 19277c478bd9Sstevel@tonic-gate "udp6", 19287c478bd9Sstevel@tonic-gate "sysevent", 19297c478bd9Sstevel@tonic-gate #ifdef __sparc 19307c478bd9Sstevel@tonic-gate "openprom", 19317c478bd9Sstevel@tonic-gate #endif 19327c478bd9Sstevel@tonic-gate "cpu/self/cpuid", 19337c478bd9Sstevel@tonic-gate "dtrace/helper", 1934fa9e4066Sahrens "zfs", 19357c478bd9Sstevel@tonic-gate NULL 19367c478bd9Sstevel@tonic-gate }; 19377c478bd9Sstevel@tonic-gate 19387c478bd9Sstevel@tonic-gate /* 19397c478bd9Sstevel@tonic-gate * This function finds everything mounted under a zone's rootpath. 19407c478bd9Sstevel@tonic-gate * This returns the number of mounts under rootpath, or -1 on error. 19417c478bd9Sstevel@tonic-gate * callback is called once per mount found with the first argument 19427c478bd9Sstevel@tonic-gate * pointing to the mount point. 19437c478bd9Sstevel@tonic-gate * 19447c478bd9Sstevel@tonic-gate * If the callback function returns non-zero zonecfg_find_mounts 19457c478bd9Sstevel@tonic-gate * aborts with an error. 19467c478bd9Sstevel@tonic-gate */ 19477c478bd9Sstevel@tonic-gate 19487c478bd9Sstevel@tonic-gate int 19497c478bd9Sstevel@tonic-gate zonecfg_find_mounts(char *rootpath, int (*callback)(const char *, void *), 19507c478bd9Sstevel@tonic-gate void *priv) { 19517c478bd9Sstevel@tonic-gate FILE *mnttab; 19527c478bd9Sstevel@tonic-gate struct mnttab m; 19537c478bd9Sstevel@tonic-gate size_t l; 19547c478bd9Sstevel@tonic-gate int rv = 0; 19557c478bd9Sstevel@tonic-gate 19567c478bd9Sstevel@tonic-gate assert(rootpath != NULL); 19577c478bd9Sstevel@tonic-gate 19587c478bd9Sstevel@tonic-gate l = strlen(rootpath); 19597c478bd9Sstevel@tonic-gate 19607c478bd9Sstevel@tonic-gate mnttab = fopen("/etc/mnttab", "r"); 19617c478bd9Sstevel@tonic-gate 19627c478bd9Sstevel@tonic-gate if (mnttab == NULL) 19637c478bd9Sstevel@tonic-gate return (-1); 19647c478bd9Sstevel@tonic-gate 19657c478bd9Sstevel@tonic-gate if (ioctl(fileno(mnttab), MNTIOC_SHOWHIDDEN, NULL) < 0) { 19667c478bd9Sstevel@tonic-gate rv = -1; 19677c478bd9Sstevel@tonic-gate goto out; 19687c478bd9Sstevel@tonic-gate } 19697c478bd9Sstevel@tonic-gate 19707c478bd9Sstevel@tonic-gate while (!getmntent(mnttab, &m)) { 19717c478bd9Sstevel@tonic-gate if ((strncmp(rootpath, m.mnt_mountp, l) == 0) && 19727c478bd9Sstevel@tonic-gate (m.mnt_mountp[l] == '/')) { 19737c478bd9Sstevel@tonic-gate rv++; 19747c478bd9Sstevel@tonic-gate if (callback == NULL) 19757c478bd9Sstevel@tonic-gate continue; 19767c478bd9Sstevel@tonic-gate if (callback(m.mnt_mountp, priv)) { 19777c478bd9Sstevel@tonic-gate rv = -1; 19787c478bd9Sstevel@tonic-gate goto out; 19797c478bd9Sstevel@tonic-gate 19807c478bd9Sstevel@tonic-gate } 19817c478bd9Sstevel@tonic-gate } 19827c478bd9Sstevel@tonic-gate } 19837c478bd9Sstevel@tonic-gate 19847c478bd9Sstevel@tonic-gate out: 19857c478bd9Sstevel@tonic-gate (void) fclose(mnttab); 19867c478bd9Sstevel@tonic-gate return (rv); 19877c478bd9Sstevel@tonic-gate } 19887c478bd9Sstevel@tonic-gate 19897c478bd9Sstevel@tonic-gate /* 19907c478bd9Sstevel@tonic-gate * This routine is used to determine if a given device should appear in the 19917c478bd9Sstevel@tonic-gate * zone represented by 'handle'. First it consults the list of "standard" 19927c478bd9Sstevel@tonic-gate * zone devices. Then it scans the user-supplied device entries. 19937c478bd9Sstevel@tonic-gate */ 19947c478bd9Sstevel@tonic-gate int 19957c478bd9Sstevel@tonic-gate zonecfg_match_dev(zone_dochandle_t handle, char *devpath, 19967c478bd9Sstevel@tonic-gate struct zone_devtab *out_match) 19977c478bd9Sstevel@tonic-gate { 19987c478bd9Sstevel@tonic-gate int err; 19997c478bd9Sstevel@tonic-gate boolean_t found = B_FALSE; 20007c478bd9Sstevel@tonic-gate char match[MAXPATHLEN]; 20017c478bd9Sstevel@tonic-gate const char **stdmatch; 20027c478bd9Sstevel@tonic-gate xmlNodePtr cur; 20037c478bd9Sstevel@tonic-gate 20047c478bd9Sstevel@tonic-gate if (handle == NULL || devpath == NULL) 20057c478bd9Sstevel@tonic-gate return (Z_INVAL); 20067c478bd9Sstevel@tonic-gate 20077c478bd9Sstevel@tonic-gate /* 20087c478bd9Sstevel@tonic-gate * Check the "standard" devices which we require to be present. 20097c478bd9Sstevel@tonic-gate */ 20107c478bd9Sstevel@tonic-gate for (stdmatch = &standard_devs[0]; *stdmatch != NULL; stdmatch++) { 20117c478bd9Sstevel@tonic-gate /* 20127c478bd9Sstevel@tonic-gate * fnmatch gives us simple but powerful shell-style matching. 20137c478bd9Sstevel@tonic-gate */ 20147c478bd9Sstevel@tonic-gate if (fnmatch(*stdmatch, devpath, FNM_PATHNAME) == 0) { 20157c478bd9Sstevel@tonic-gate if (!out_match) 20167c478bd9Sstevel@tonic-gate return (Z_OK); 20177c478bd9Sstevel@tonic-gate (void) snprintf(out_match->zone_dev_match, 20187c478bd9Sstevel@tonic-gate sizeof (out_match->zone_dev_match), 20197c478bd9Sstevel@tonic-gate "/dev/%s", *stdmatch); 20207c478bd9Sstevel@tonic-gate return (Z_OK); 20217c478bd9Sstevel@tonic-gate } 20227c478bd9Sstevel@tonic-gate } 20237c478bd9Sstevel@tonic-gate 20247c478bd9Sstevel@tonic-gate /* 20257c478bd9Sstevel@tonic-gate * We got no hits in the set of standard devices. On to the user 20267c478bd9Sstevel@tonic-gate * supplied ones. 20277c478bd9Sstevel@tonic-gate */ 20287c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) { 20297c478bd9Sstevel@tonic-gate handle->zone_dh_cur = NULL; 20307c478bd9Sstevel@tonic-gate return (err); 20317c478bd9Sstevel@tonic-gate } 20327c478bd9Sstevel@tonic-gate 20337c478bd9Sstevel@tonic-gate cur = handle->zone_dh_cur; 20347c478bd9Sstevel@tonic-gate cur = cur->xmlChildrenNode; 20357c478bd9Sstevel@tonic-gate if (cur == NULL) 20367c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 20377c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur; 20387c478bd9Sstevel@tonic-gate 20397c478bd9Sstevel@tonic-gate for (; cur != NULL; cur = cur->next) { 20407c478bd9Sstevel@tonic-gate char *m; 20417c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_DEVICE) != 0) 20427c478bd9Sstevel@tonic-gate continue; 20437c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_MATCH, match, 20447c478bd9Sstevel@tonic-gate sizeof (match))) != Z_OK) { 20457c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 20467c478bd9Sstevel@tonic-gate return (err); 20477c478bd9Sstevel@tonic-gate } 20487c478bd9Sstevel@tonic-gate m = match; 20497c478bd9Sstevel@tonic-gate /* 20507c478bd9Sstevel@tonic-gate * fnmatch gives us simple but powerful shell-style matching; 20517c478bd9Sstevel@tonic-gate * but first, we need to strip out /dev/ from the matching rule. 20527c478bd9Sstevel@tonic-gate */ 20537c478bd9Sstevel@tonic-gate if (strncmp(m, "/dev/", 5) == 0) 20547c478bd9Sstevel@tonic-gate m += 5; 20557c478bd9Sstevel@tonic-gate 20567c478bd9Sstevel@tonic-gate if (fnmatch(m, devpath, FNM_PATHNAME) == 0) { 20577c478bd9Sstevel@tonic-gate found = B_TRUE; 20587c478bd9Sstevel@tonic-gate break; 20597c478bd9Sstevel@tonic-gate } 20607c478bd9Sstevel@tonic-gate } 20617c478bd9Sstevel@tonic-gate 20627c478bd9Sstevel@tonic-gate if (!found) 20637c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 20647c478bd9Sstevel@tonic-gate 20657c478bd9Sstevel@tonic-gate if (!out_match) 20667c478bd9Sstevel@tonic-gate return (Z_OK); 20677c478bd9Sstevel@tonic-gate 20687c478bd9Sstevel@tonic-gate (void) strlcpy(out_match->zone_dev_match, match, 20697c478bd9Sstevel@tonic-gate sizeof (out_match->zone_dev_match)); 20707c478bd9Sstevel@tonic-gate return (Z_OK); 20717c478bd9Sstevel@tonic-gate } 20727c478bd9Sstevel@tonic-gate 20737c478bd9Sstevel@tonic-gate int 20747c478bd9Sstevel@tonic-gate zonecfg_lookup_attr(zone_dochandle_t handle, struct zone_attrtab *tabptr) 20757c478bd9Sstevel@tonic-gate { 20767c478bd9Sstevel@tonic-gate xmlNodePtr cur, firstmatch; 20777c478bd9Sstevel@tonic-gate int err; 20787c478bd9Sstevel@tonic-gate char name[MAXNAMELEN], type[MAXNAMELEN], value[MAXNAMELEN]; 20797c478bd9Sstevel@tonic-gate 20807c478bd9Sstevel@tonic-gate if (tabptr == NULL) 20817c478bd9Sstevel@tonic-gate return (Z_INVAL); 20827c478bd9Sstevel@tonic-gate 20837c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 20847c478bd9Sstevel@tonic-gate return (err); 20857c478bd9Sstevel@tonic-gate 20867c478bd9Sstevel@tonic-gate cur = handle->zone_dh_cur; 20877c478bd9Sstevel@tonic-gate firstmatch = NULL; 20887c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 20897c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_ATTR)) 20907c478bd9Sstevel@tonic-gate continue; 20917c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_attr_name) > 0) { 20927c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_NAME, name, 20937c478bd9Sstevel@tonic-gate sizeof (name)) == Z_OK) && 20947c478bd9Sstevel@tonic-gate (strcmp(tabptr->zone_attr_name, name) == 0)) { 20957c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 20967c478bd9Sstevel@tonic-gate firstmatch = cur; 20977c478bd9Sstevel@tonic-gate else 20987c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 20997c478bd9Sstevel@tonic-gate } 21007c478bd9Sstevel@tonic-gate } 21017c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_attr_type) > 0) { 21027c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_TYPE, type, 21037c478bd9Sstevel@tonic-gate sizeof (type)) == Z_OK)) { 21047c478bd9Sstevel@tonic-gate if (strcmp(tabptr->zone_attr_type, type) == 0) { 21057c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 21067c478bd9Sstevel@tonic-gate firstmatch = cur; 21077c478bd9Sstevel@tonic-gate else if (firstmatch != cur) 21087c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 21097c478bd9Sstevel@tonic-gate } else { 21107c478bd9Sstevel@tonic-gate /* 21117c478bd9Sstevel@tonic-gate * If another property matched but this 21127c478bd9Sstevel@tonic-gate * one doesn't then reset firstmatch. 21137c478bd9Sstevel@tonic-gate */ 21147c478bd9Sstevel@tonic-gate if (firstmatch == cur) 21157c478bd9Sstevel@tonic-gate firstmatch = NULL; 21167c478bd9Sstevel@tonic-gate } 21177c478bd9Sstevel@tonic-gate } 21187c478bd9Sstevel@tonic-gate } 21197c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_attr_value) > 0) { 21207c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_VALUE, value, 21217c478bd9Sstevel@tonic-gate sizeof (value)) == Z_OK)) { 21227c478bd9Sstevel@tonic-gate if (strcmp(tabptr->zone_attr_value, value) == 21237c478bd9Sstevel@tonic-gate 0) { 21247c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 21257c478bd9Sstevel@tonic-gate firstmatch = cur; 21267c478bd9Sstevel@tonic-gate else if (firstmatch != cur) 21277c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 21287c478bd9Sstevel@tonic-gate } else { 21297c478bd9Sstevel@tonic-gate /* 21307c478bd9Sstevel@tonic-gate * If another property matched but this 21317c478bd9Sstevel@tonic-gate * one doesn't then reset firstmatch. 21327c478bd9Sstevel@tonic-gate */ 21337c478bd9Sstevel@tonic-gate if (firstmatch == cur) 21347c478bd9Sstevel@tonic-gate firstmatch = NULL; 21357c478bd9Sstevel@tonic-gate } 21367c478bd9Sstevel@tonic-gate } 21377c478bd9Sstevel@tonic-gate } 21387c478bd9Sstevel@tonic-gate } 21397c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 21407c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 21417c478bd9Sstevel@tonic-gate 21427c478bd9Sstevel@tonic-gate cur = firstmatch; 21437c478bd9Sstevel@tonic-gate 21447c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_NAME, tabptr->zone_attr_name, 21457c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_attr_name))) != Z_OK) 21467c478bd9Sstevel@tonic-gate return (err); 21477c478bd9Sstevel@tonic-gate 21487c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_TYPE, tabptr->zone_attr_type, 21497c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_attr_type))) != Z_OK) 21507c478bd9Sstevel@tonic-gate return (err); 21517c478bd9Sstevel@tonic-gate 21527c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_VALUE, tabptr->zone_attr_value, 21537c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_attr_value))) != Z_OK) 21547c478bd9Sstevel@tonic-gate return (err); 21557c478bd9Sstevel@tonic-gate 21567c478bd9Sstevel@tonic-gate return (Z_OK); 21577c478bd9Sstevel@tonic-gate } 21587c478bd9Sstevel@tonic-gate 21597c478bd9Sstevel@tonic-gate static int 21607c478bd9Sstevel@tonic-gate zonecfg_add_attr_core(zone_dochandle_t handle, struct zone_attrtab *tabptr) 21617c478bd9Sstevel@tonic-gate { 21627c478bd9Sstevel@tonic-gate xmlNodePtr newnode, cur = handle->zone_dh_cur; 21637c478bd9Sstevel@tonic-gate int err; 21647c478bd9Sstevel@tonic-gate 21657c478bd9Sstevel@tonic-gate newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_ATTR, NULL); 2166a1be23daSdp err = newprop(newnode, DTD_ATTR_NAME, tabptr->zone_attr_name); 21677c478bd9Sstevel@tonic-gate if (err != Z_OK) 21687c478bd9Sstevel@tonic-gate return (err); 2169a1be23daSdp err = newprop(newnode, DTD_ATTR_TYPE, tabptr->zone_attr_type); 21707c478bd9Sstevel@tonic-gate if (err != Z_OK) 21717c478bd9Sstevel@tonic-gate return (err); 2172a1be23daSdp err = newprop(newnode, DTD_ATTR_VALUE, tabptr->zone_attr_value); 21737c478bd9Sstevel@tonic-gate if (err != Z_OK) 21747c478bd9Sstevel@tonic-gate return (err); 21757c478bd9Sstevel@tonic-gate return (Z_OK); 21767c478bd9Sstevel@tonic-gate } 21777c478bd9Sstevel@tonic-gate 21787c478bd9Sstevel@tonic-gate int 21797c478bd9Sstevel@tonic-gate zonecfg_add_attr(zone_dochandle_t handle, struct zone_attrtab *tabptr) 21807c478bd9Sstevel@tonic-gate { 21817c478bd9Sstevel@tonic-gate int err; 21827c478bd9Sstevel@tonic-gate 21837c478bd9Sstevel@tonic-gate if (tabptr == NULL) 21847c478bd9Sstevel@tonic-gate return (Z_INVAL); 21857c478bd9Sstevel@tonic-gate 21867c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 21877c478bd9Sstevel@tonic-gate return (err); 21887c478bd9Sstevel@tonic-gate 21897c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_attr_core(handle, tabptr)) != Z_OK) 21907c478bd9Sstevel@tonic-gate return (err); 21917c478bd9Sstevel@tonic-gate 21927c478bd9Sstevel@tonic-gate return (Z_OK); 21937c478bd9Sstevel@tonic-gate } 21947c478bd9Sstevel@tonic-gate 21957c478bd9Sstevel@tonic-gate static int 21967c478bd9Sstevel@tonic-gate zonecfg_delete_attr_core(zone_dochandle_t handle, struct zone_attrtab *tabptr) 21977c478bd9Sstevel@tonic-gate { 21987c478bd9Sstevel@tonic-gate xmlNodePtr cur = handle->zone_dh_cur; 21997c478bd9Sstevel@tonic-gate int name_match, type_match, value_match; 22007c478bd9Sstevel@tonic-gate 22017c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 22027c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_ATTR)) 22037c478bd9Sstevel@tonic-gate continue; 22047c478bd9Sstevel@tonic-gate 22057c478bd9Sstevel@tonic-gate name_match = match_prop(cur, DTD_ATTR_NAME, 22067c478bd9Sstevel@tonic-gate tabptr->zone_attr_name); 22077c478bd9Sstevel@tonic-gate type_match = match_prop(cur, DTD_ATTR_TYPE, 22087c478bd9Sstevel@tonic-gate tabptr->zone_attr_type); 22097c478bd9Sstevel@tonic-gate value_match = match_prop(cur, DTD_ATTR_VALUE, 22107c478bd9Sstevel@tonic-gate tabptr->zone_attr_value); 22117c478bd9Sstevel@tonic-gate 22127c478bd9Sstevel@tonic-gate if (name_match && type_match && value_match) { 22137c478bd9Sstevel@tonic-gate xmlUnlinkNode(cur); 22147c478bd9Sstevel@tonic-gate xmlFreeNode(cur); 22157c478bd9Sstevel@tonic-gate return (Z_OK); 22167c478bd9Sstevel@tonic-gate } 22177c478bd9Sstevel@tonic-gate } 22187c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 22197c478bd9Sstevel@tonic-gate } 22207c478bd9Sstevel@tonic-gate 22217c478bd9Sstevel@tonic-gate int 22227c478bd9Sstevel@tonic-gate zonecfg_delete_attr(zone_dochandle_t handle, struct zone_attrtab *tabptr) 22237c478bd9Sstevel@tonic-gate { 22247c478bd9Sstevel@tonic-gate int err; 22257c478bd9Sstevel@tonic-gate 22267c478bd9Sstevel@tonic-gate if (tabptr == NULL) 22277c478bd9Sstevel@tonic-gate return (Z_INVAL); 22287c478bd9Sstevel@tonic-gate 22297c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 22307c478bd9Sstevel@tonic-gate return (err); 22317c478bd9Sstevel@tonic-gate 22327c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_attr_core(handle, tabptr)) != Z_OK) 22337c478bd9Sstevel@tonic-gate return (err); 22347c478bd9Sstevel@tonic-gate 22357c478bd9Sstevel@tonic-gate return (Z_OK); 22367c478bd9Sstevel@tonic-gate } 22377c478bd9Sstevel@tonic-gate 22387c478bd9Sstevel@tonic-gate int 22397c478bd9Sstevel@tonic-gate zonecfg_modify_attr( 22407c478bd9Sstevel@tonic-gate zone_dochandle_t handle, 22417c478bd9Sstevel@tonic-gate struct zone_attrtab *oldtabptr, 22427c478bd9Sstevel@tonic-gate struct zone_attrtab *newtabptr) 22437c478bd9Sstevel@tonic-gate { 22447c478bd9Sstevel@tonic-gate int err; 22457c478bd9Sstevel@tonic-gate 22467c478bd9Sstevel@tonic-gate if (oldtabptr == NULL || newtabptr == NULL) 22477c478bd9Sstevel@tonic-gate return (Z_INVAL); 22487c478bd9Sstevel@tonic-gate 22497c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 22507c478bd9Sstevel@tonic-gate return (err); 22517c478bd9Sstevel@tonic-gate 22527c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_attr_core(handle, oldtabptr)) != Z_OK) 22537c478bd9Sstevel@tonic-gate return (err); 22547c478bd9Sstevel@tonic-gate 22557c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_attr_core(handle, newtabptr)) != Z_OK) 22567c478bd9Sstevel@tonic-gate return (err); 22577c478bd9Sstevel@tonic-gate 22587c478bd9Sstevel@tonic-gate return (Z_OK); 22597c478bd9Sstevel@tonic-gate } 22607c478bd9Sstevel@tonic-gate 22617c478bd9Sstevel@tonic-gate int 22627c478bd9Sstevel@tonic-gate zonecfg_get_attr_boolean(const struct zone_attrtab *attr, boolean_t *value) 22637c478bd9Sstevel@tonic-gate { 22647c478bd9Sstevel@tonic-gate if (attr == NULL) 22657c478bd9Sstevel@tonic-gate return (Z_INVAL); 22667c478bd9Sstevel@tonic-gate 22677c478bd9Sstevel@tonic-gate if (strcmp(attr->zone_attr_type, DTD_ENTITY_BOOLEAN) != 0) 22687c478bd9Sstevel@tonic-gate return (Z_INVAL); 22697c478bd9Sstevel@tonic-gate 22707c478bd9Sstevel@tonic-gate if (strcmp(attr->zone_attr_value, DTD_ENTITY_TRUE) == 0) { 22717c478bd9Sstevel@tonic-gate *value = B_TRUE; 22727c478bd9Sstevel@tonic-gate return (Z_OK); 22737c478bd9Sstevel@tonic-gate } 22747c478bd9Sstevel@tonic-gate if (strcmp(attr->zone_attr_value, DTD_ENTITY_FALSE) == 0) { 22757c478bd9Sstevel@tonic-gate *value = B_FALSE; 22767c478bd9Sstevel@tonic-gate return (Z_OK); 22777c478bd9Sstevel@tonic-gate } 22787c478bd9Sstevel@tonic-gate return (Z_INVAL); 22797c478bd9Sstevel@tonic-gate } 22807c478bd9Sstevel@tonic-gate 22817c478bd9Sstevel@tonic-gate int 22827c478bd9Sstevel@tonic-gate zonecfg_get_attr_int(const struct zone_attrtab *attr, int64_t *value) 22837c478bd9Sstevel@tonic-gate { 22847c478bd9Sstevel@tonic-gate long long result; 22857c478bd9Sstevel@tonic-gate char *endptr; 22867c478bd9Sstevel@tonic-gate 22877c478bd9Sstevel@tonic-gate if (attr == NULL) 22887c478bd9Sstevel@tonic-gate return (Z_INVAL); 22897c478bd9Sstevel@tonic-gate 22907c478bd9Sstevel@tonic-gate if (strcmp(attr->zone_attr_type, DTD_ENTITY_INT) != 0) 22917c478bd9Sstevel@tonic-gate return (Z_INVAL); 22927c478bd9Sstevel@tonic-gate 22937c478bd9Sstevel@tonic-gate errno = 0; 22947c478bd9Sstevel@tonic-gate result = strtoll(attr->zone_attr_value, &endptr, 10); 22957c478bd9Sstevel@tonic-gate if (errno != 0 || *endptr != '\0') 22967c478bd9Sstevel@tonic-gate return (Z_INVAL); 22977c478bd9Sstevel@tonic-gate *value = result; 22987c478bd9Sstevel@tonic-gate return (Z_OK); 22997c478bd9Sstevel@tonic-gate } 23007c478bd9Sstevel@tonic-gate 23017c478bd9Sstevel@tonic-gate int 23027c478bd9Sstevel@tonic-gate zonecfg_get_attr_string(const struct zone_attrtab *attr, char *value, 23037c478bd9Sstevel@tonic-gate size_t val_sz) 23047c478bd9Sstevel@tonic-gate { 23057c478bd9Sstevel@tonic-gate if (attr == NULL) 23067c478bd9Sstevel@tonic-gate return (Z_INVAL); 23077c478bd9Sstevel@tonic-gate 23087c478bd9Sstevel@tonic-gate if (strcmp(attr->zone_attr_type, DTD_ENTITY_STRING) != 0) 23097c478bd9Sstevel@tonic-gate return (Z_INVAL); 23107c478bd9Sstevel@tonic-gate 23117c478bd9Sstevel@tonic-gate if (strlcpy(value, attr->zone_attr_value, val_sz) >= val_sz) 23127c478bd9Sstevel@tonic-gate return (Z_TOO_BIG); 23137c478bd9Sstevel@tonic-gate return (Z_OK); 23147c478bd9Sstevel@tonic-gate } 23157c478bd9Sstevel@tonic-gate 23167c478bd9Sstevel@tonic-gate int 23177c478bd9Sstevel@tonic-gate zonecfg_get_attr_uint(const struct zone_attrtab *attr, uint64_t *value) 23187c478bd9Sstevel@tonic-gate { 23197c478bd9Sstevel@tonic-gate unsigned long long result; 23207c478bd9Sstevel@tonic-gate long long neg_result; 23217c478bd9Sstevel@tonic-gate char *endptr; 23227c478bd9Sstevel@tonic-gate 23237c478bd9Sstevel@tonic-gate if (attr == NULL) 23247c478bd9Sstevel@tonic-gate return (Z_INVAL); 23257c478bd9Sstevel@tonic-gate 23267c478bd9Sstevel@tonic-gate if (strcmp(attr->zone_attr_type, DTD_ENTITY_UINT) != 0) 23277c478bd9Sstevel@tonic-gate return (Z_INVAL); 23287c478bd9Sstevel@tonic-gate 23297c478bd9Sstevel@tonic-gate errno = 0; 23307c478bd9Sstevel@tonic-gate result = strtoull(attr->zone_attr_value, &endptr, 10); 23317c478bd9Sstevel@tonic-gate if (errno != 0 || *endptr != '\0') 23327c478bd9Sstevel@tonic-gate return (Z_INVAL); 23337c478bd9Sstevel@tonic-gate errno = 0; 23347c478bd9Sstevel@tonic-gate neg_result = strtoll(attr->zone_attr_value, &endptr, 10); 23357c478bd9Sstevel@tonic-gate /* 23367c478bd9Sstevel@tonic-gate * Incredibly, strtoull("<negative number>", ...) will not fail but 23377c478bd9Sstevel@tonic-gate * return whatever (negative) number cast as a u_longlong_t, so we 23387c478bd9Sstevel@tonic-gate * need to look for this here. 23397c478bd9Sstevel@tonic-gate */ 23407c478bd9Sstevel@tonic-gate if (errno == 0 && neg_result < 0) 23417c478bd9Sstevel@tonic-gate return (Z_INVAL); 23427c478bd9Sstevel@tonic-gate *value = result; 23437c478bd9Sstevel@tonic-gate return (Z_OK); 23447c478bd9Sstevel@tonic-gate } 23457c478bd9Sstevel@tonic-gate 23467c478bd9Sstevel@tonic-gate int 23477c478bd9Sstevel@tonic-gate zonecfg_lookup_rctl(zone_dochandle_t handle, struct zone_rctltab *tabptr) 23487c478bd9Sstevel@tonic-gate { 23497c478bd9Sstevel@tonic-gate xmlNodePtr cur, val; 23507c478bd9Sstevel@tonic-gate char savedname[MAXNAMELEN]; 23517c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *valptr; 23527c478bd9Sstevel@tonic-gate int err; 23537c478bd9Sstevel@tonic-gate 23547c478bd9Sstevel@tonic-gate if (tabptr->zone_rctl_name == NULL || 23557c478bd9Sstevel@tonic-gate strlen(tabptr->zone_rctl_name) == 0) 23567c478bd9Sstevel@tonic-gate return (Z_INVAL); 23577c478bd9Sstevel@tonic-gate 23587c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 23597c478bd9Sstevel@tonic-gate return (err); 23607c478bd9Sstevel@tonic-gate 23617c478bd9Sstevel@tonic-gate cur = handle->zone_dh_cur; 23627c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 23637c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_RCTL)) 23647c478bd9Sstevel@tonic-gate continue; 23657c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_NAME, savedname, 23667c478bd9Sstevel@tonic-gate sizeof (savedname)) == Z_OK) && 23677c478bd9Sstevel@tonic-gate (strcmp(savedname, tabptr->zone_rctl_name) == 0)) { 23687c478bd9Sstevel@tonic-gate tabptr->zone_rctl_valptr = NULL; 23697c478bd9Sstevel@tonic-gate for (val = cur->xmlChildrenNode; val != NULL; 23707c478bd9Sstevel@tonic-gate val = val->next) { 23717c478bd9Sstevel@tonic-gate valptr = (struct zone_rctlvaltab *)malloc( 23727c478bd9Sstevel@tonic-gate sizeof (struct zone_rctlvaltab)); 23737c478bd9Sstevel@tonic-gate if (valptr == NULL) 23747c478bd9Sstevel@tonic-gate return (Z_NOMEM); 23757c478bd9Sstevel@tonic-gate if ((fetchprop(val, DTD_ATTR_PRIV, 23767c478bd9Sstevel@tonic-gate valptr->zone_rctlval_priv, 23777c478bd9Sstevel@tonic-gate sizeof (valptr->zone_rctlval_priv)) != 23787c478bd9Sstevel@tonic-gate Z_OK)) 23797c478bd9Sstevel@tonic-gate break; 23807c478bd9Sstevel@tonic-gate if ((fetchprop(val, DTD_ATTR_LIMIT, 23817c478bd9Sstevel@tonic-gate valptr->zone_rctlval_limit, 23827c478bd9Sstevel@tonic-gate sizeof (valptr->zone_rctlval_limit)) != 23837c478bd9Sstevel@tonic-gate Z_OK)) 23847c478bd9Sstevel@tonic-gate break; 23857c478bd9Sstevel@tonic-gate if ((fetchprop(val, DTD_ATTR_ACTION, 23867c478bd9Sstevel@tonic-gate valptr->zone_rctlval_action, 23877c478bd9Sstevel@tonic-gate sizeof (valptr->zone_rctlval_action)) != 23887c478bd9Sstevel@tonic-gate Z_OK)) 23897c478bd9Sstevel@tonic-gate break; 23907c478bd9Sstevel@tonic-gate if (zonecfg_add_rctl_value(tabptr, valptr) != 23917c478bd9Sstevel@tonic-gate Z_OK) 23927c478bd9Sstevel@tonic-gate break; 23937c478bd9Sstevel@tonic-gate } 23947c478bd9Sstevel@tonic-gate return (Z_OK); 23957c478bd9Sstevel@tonic-gate } 23967c478bd9Sstevel@tonic-gate } 23977c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 23987c478bd9Sstevel@tonic-gate } 23997c478bd9Sstevel@tonic-gate 24007c478bd9Sstevel@tonic-gate static int 24017c478bd9Sstevel@tonic-gate zonecfg_add_rctl_core(zone_dochandle_t handle, struct zone_rctltab *tabptr) 24027c478bd9Sstevel@tonic-gate { 24037c478bd9Sstevel@tonic-gate xmlNodePtr newnode, cur = handle->zone_dh_cur, valnode; 24047c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *valptr; 24057c478bd9Sstevel@tonic-gate int err; 24067c478bd9Sstevel@tonic-gate 24077c478bd9Sstevel@tonic-gate newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_RCTL, NULL); 2408a1be23daSdp err = newprop(newnode, DTD_ATTR_NAME, tabptr->zone_rctl_name); 24097c478bd9Sstevel@tonic-gate if (err != Z_OK) 24107c478bd9Sstevel@tonic-gate return (err); 24117c478bd9Sstevel@tonic-gate for (valptr = tabptr->zone_rctl_valptr; valptr != NULL; 24127c478bd9Sstevel@tonic-gate valptr = valptr->zone_rctlval_next) { 24137c478bd9Sstevel@tonic-gate valnode = xmlNewTextChild(newnode, NULL, 24147c478bd9Sstevel@tonic-gate DTD_ELEM_RCTLVALUE, NULL); 2415a1be23daSdp err = newprop(valnode, DTD_ATTR_PRIV, 24167c478bd9Sstevel@tonic-gate valptr->zone_rctlval_priv); 24177c478bd9Sstevel@tonic-gate if (err != Z_OK) 24187c478bd9Sstevel@tonic-gate return (err); 2419a1be23daSdp err = newprop(valnode, DTD_ATTR_LIMIT, 24207c478bd9Sstevel@tonic-gate valptr->zone_rctlval_limit); 24217c478bd9Sstevel@tonic-gate if (err != Z_OK) 24227c478bd9Sstevel@tonic-gate return (err); 2423a1be23daSdp err = newprop(valnode, DTD_ATTR_ACTION, 24247c478bd9Sstevel@tonic-gate valptr->zone_rctlval_action); 24257c478bd9Sstevel@tonic-gate if (err != Z_OK) 24267c478bd9Sstevel@tonic-gate return (err); 24277c478bd9Sstevel@tonic-gate } 24287c478bd9Sstevel@tonic-gate return (Z_OK); 24297c478bd9Sstevel@tonic-gate } 24307c478bd9Sstevel@tonic-gate 24317c478bd9Sstevel@tonic-gate int 24327c478bd9Sstevel@tonic-gate zonecfg_add_rctl(zone_dochandle_t handle, struct zone_rctltab *tabptr) 24337c478bd9Sstevel@tonic-gate { 24347c478bd9Sstevel@tonic-gate int err; 24357c478bd9Sstevel@tonic-gate 24367c478bd9Sstevel@tonic-gate if (tabptr == NULL || tabptr->zone_rctl_name == NULL) 24377c478bd9Sstevel@tonic-gate return (Z_INVAL); 24387c478bd9Sstevel@tonic-gate 24397c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 24407c478bd9Sstevel@tonic-gate return (err); 24417c478bd9Sstevel@tonic-gate 24427c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_rctl_core(handle, tabptr)) != Z_OK) 24437c478bd9Sstevel@tonic-gate return (err); 24447c478bd9Sstevel@tonic-gate 24457c478bd9Sstevel@tonic-gate return (Z_OK); 24467c478bd9Sstevel@tonic-gate } 24477c478bd9Sstevel@tonic-gate 24487c478bd9Sstevel@tonic-gate static int 24497c478bd9Sstevel@tonic-gate zonecfg_delete_rctl_core(zone_dochandle_t handle, struct zone_rctltab *tabptr) 24507c478bd9Sstevel@tonic-gate { 24517c478bd9Sstevel@tonic-gate xmlNodePtr cur = handle->zone_dh_cur; 24527c478bd9Sstevel@tonic-gate xmlChar *savedname; 24537c478bd9Sstevel@tonic-gate int name_result; 24547c478bd9Sstevel@tonic-gate 24557c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 24567c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_RCTL)) 24577c478bd9Sstevel@tonic-gate continue; 24587c478bd9Sstevel@tonic-gate 24597c478bd9Sstevel@tonic-gate savedname = xmlGetProp(cur, DTD_ATTR_NAME); 24607c478bd9Sstevel@tonic-gate if (savedname == NULL) /* shouldn't happen */ 24617c478bd9Sstevel@tonic-gate continue; 24627c478bd9Sstevel@tonic-gate name_result = xmlStrcmp(savedname, 24637c478bd9Sstevel@tonic-gate (const xmlChar *) tabptr->zone_rctl_name); 24647c478bd9Sstevel@tonic-gate xmlFree(savedname); 24657c478bd9Sstevel@tonic-gate 24667c478bd9Sstevel@tonic-gate if (name_result == 0) { 24677c478bd9Sstevel@tonic-gate xmlUnlinkNode(cur); 24687c478bd9Sstevel@tonic-gate xmlFreeNode(cur); 24697c478bd9Sstevel@tonic-gate return (Z_OK); 24707c478bd9Sstevel@tonic-gate } 24717c478bd9Sstevel@tonic-gate } 24727c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 24737c478bd9Sstevel@tonic-gate } 24747c478bd9Sstevel@tonic-gate 24757c478bd9Sstevel@tonic-gate int 24767c478bd9Sstevel@tonic-gate zonecfg_delete_rctl(zone_dochandle_t handle, struct zone_rctltab *tabptr) 24777c478bd9Sstevel@tonic-gate { 24787c478bd9Sstevel@tonic-gate int err; 24797c478bd9Sstevel@tonic-gate 24807c478bd9Sstevel@tonic-gate if (tabptr == NULL || tabptr->zone_rctl_name == NULL) 24817c478bd9Sstevel@tonic-gate return (Z_INVAL); 24827c478bd9Sstevel@tonic-gate 24837c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 24847c478bd9Sstevel@tonic-gate return (err); 24857c478bd9Sstevel@tonic-gate 24867c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_rctl_core(handle, tabptr)) != Z_OK) 24877c478bd9Sstevel@tonic-gate return (err); 24887c478bd9Sstevel@tonic-gate 24897c478bd9Sstevel@tonic-gate return (Z_OK); 24907c478bd9Sstevel@tonic-gate } 24917c478bd9Sstevel@tonic-gate 24927c478bd9Sstevel@tonic-gate int 24937c478bd9Sstevel@tonic-gate zonecfg_modify_rctl( 24947c478bd9Sstevel@tonic-gate zone_dochandle_t handle, 24957c478bd9Sstevel@tonic-gate struct zone_rctltab *oldtabptr, 24967c478bd9Sstevel@tonic-gate struct zone_rctltab *newtabptr) 24977c478bd9Sstevel@tonic-gate { 24987c478bd9Sstevel@tonic-gate int err; 24997c478bd9Sstevel@tonic-gate 25007c478bd9Sstevel@tonic-gate if (oldtabptr == NULL || oldtabptr->zone_rctl_name == NULL || 25017c478bd9Sstevel@tonic-gate newtabptr == NULL || newtabptr->zone_rctl_name == NULL) 25027c478bd9Sstevel@tonic-gate return (Z_INVAL); 25037c478bd9Sstevel@tonic-gate 25047c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 25057c478bd9Sstevel@tonic-gate return (err); 25067c478bd9Sstevel@tonic-gate 25077c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_rctl_core(handle, oldtabptr)) != Z_OK) 25087c478bd9Sstevel@tonic-gate return (err); 25097c478bd9Sstevel@tonic-gate 25107c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_rctl_core(handle, newtabptr)) != Z_OK) 25117c478bd9Sstevel@tonic-gate return (err); 25127c478bd9Sstevel@tonic-gate 25137c478bd9Sstevel@tonic-gate return (Z_OK); 25147c478bd9Sstevel@tonic-gate } 25157c478bd9Sstevel@tonic-gate 25167c478bd9Sstevel@tonic-gate int 25177c478bd9Sstevel@tonic-gate zonecfg_add_rctl_value( 25187c478bd9Sstevel@tonic-gate struct zone_rctltab *tabptr, 25197c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *valtabptr) 25207c478bd9Sstevel@tonic-gate { 25217c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *last, *old, *new; 25227c478bd9Sstevel@tonic-gate rctlblk_t *rctlblk = alloca(rctlblk_size()); 25237c478bd9Sstevel@tonic-gate 25247c478bd9Sstevel@tonic-gate last = tabptr->zone_rctl_valptr; 25257c478bd9Sstevel@tonic-gate for (old = last; old != NULL; old = old->zone_rctlval_next) 25267c478bd9Sstevel@tonic-gate last = old; /* walk to the end of the list */ 25277c478bd9Sstevel@tonic-gate new = valtabptr; /* alloc'd by caller */ 25287c478bd9Sstevel@tonic-gate new->zone_rctlval_next = NULL; 25297c478bd9Sstevel@tonic-gate if (zonecfg_construct_rctlblk(valtabptr, rctlblk) != Z_OK) 25307c478bd9Sstevel@tonic-gate return (Z_INVAL); 25317c478bd9Sstevel@tonic-gate if (!zonecfg_valid_rctlblk(rctlblk)) 25327c478bd9Sstevel@tonic-gate return (Z_INVAL); 25337c478bd9Sstevel@tonic-gate if (last == NULL) 25347c478bd9Sstevel@tonic-gate tabptr->zone_rctl_valptr = new; 25357c478bd9Sstevel@tonic-gate else 25367c478bd9Sstevel@tonic-gate last->zone_rctlval_next = new; 25377c478bd9Sstevel@tonic-gate return (Z_OK); 25387c478bd9Sstevel@tonic-gate } 25397c478bd9Sstevel@tonic-gate 25407c478bd9Sstevel@tonic-gate int 25417c478bd9Sstevel@tonic-gate zonecfg_remove_rctl_value( 25427c478bd9Sstevel@tonic-gate struct zone_rctltab *tabptr, 25437c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *valtabptr) 25447c478bd9Sstevel@tonic-gate { 25457c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *last, *this, *next; 25467c478bd9Sstevel@tonic-gate 25477c478bd9Sstevel@tonic-gate last = tabptr->zone_rctl_valptr; 25487c478bd9Sstevel@tonic-gate for (this = last; this != NULL; this = this->zone_rctlval_next) { 25497c478bd9Sstevel@tonic-gate if (strcmp(this->zone_rctlval_priv, 25507c478bd9Sstevel@tonic-gate valtabptr->zone_rctlval_priv) == 0 && 25517c478bd9Sstevel@tonic-gate strcmp(this->zone_rctlval_limit, 25527c478bd9Sstevel@tonic-gate valtabptr->zone_rctlval_limit) == 0 && 25537c478bd9Sstevel@tonic-gate strcmp(this->zone_rctlval_action, 25547c478bd9Sstevel@tonic-gate valtabptr->zone_rctlval_action) == 0) { 25557c478bd9Sstevel@tonic-gate next = this->zone_rctlval_next; 25567c478bd9Sstevel@tonic-gate if (this == tabptr->zone_rctl_valptr) 25577c478bd9Sstevel@tonic-gate tabptr->zone_rctl_valptr = next; 25587c478bd9Sstevel@tonic-gate else 25597c478bd9Sstevel@tonic-gate last->zone_rctlval_next = next; 25607c478bd9Sstevel@tonic-gate free(this); 25617c478bd9Sstevel@tonic-gate return (Z_OK); 25627c478bd9Sstevel@tonic-gate } else 25637c478bd9Sstevel@tonic-gate last = this; 25647c478bd9Sstevel@tonic-gate } 25657c478bd9Sstevel@tonic-gate return (Z_NO_PROPERTY_ID); 25667c478bd9Sstevel@tonic-gate } 25677c478bd9Sstevel@tonic-gate 25687c478bd9Sstevel@tonic-gate char * 25697c478bd9Sstevel@tonic-gate zonecfg_strerror(int errnum) 25707c478bd9Sstevel@tonic-gate { 25717c478bd9Sstevel@tonic-gate switch (errnum) { 25727c478bd9Sstevel@tonic-gate case Z_OK: 25737c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "OK")); 25747c478bd9Sstevel@tonic-gate case Z_EMPTY_DOCUMENT: 25757c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Empty document")); 25767c478bd9Sstevel@tonic-gate case Z_WRONG_DOC_TYPE: 25777c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Wrong document type")); 25787c478bd9Sstevel@tonic-gate case Z_BAD_PROPERTY: 25797c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Bad document property")); 25807c478bd9Sstevel@tonic-gate case Z_TEMP_FILE: 25817c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, 25827c478bd9Sstevel@tonic-gate "Problem creating temporary file")); 25837c478bd9Sstevel@tonic-gate case Z_SAVING_FILE: 25847c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Problem saving file")); 25857c478bd9Sstevel@tonic-gate case Z_NO_ENTRY: 25867c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "No such entry")); 25877c478bd9Sstevel@tonic-gate case Z_BOGUS_ZONE_NAME: 25887c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Bogus zone name")); 25897c478bd9Sstevel@tonic-gate case Z_REQD_RESOURCE_MISSING: 25907c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Required resource missing")); 25917c478bd9Sstevel@tonic-gate case Z_REQD_PROPERTY_MISSING: 25927c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Required property missing")); 25937c478bd9Sstevel@tonic-gate case Z_BAD_HANDLE: 25947c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Bad handle")); 25957c478bd9Sstevel@tonic-gate case Z_NOMEM: 25967c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Out of memory")); 25977c478bd9Sstevel@tonic-gate case Z_INVAL: 25987c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Invalid argument")); 25997c478bd9Sstevel@tonic-gate case Z_ACCES: 26007c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Permission denied")); 26017c478bd9Sstevel@tonic-gate case Z_TOO_BIG: 26027c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Argument list too long")); 26037c478bd9Sstevel@tonic-gate case Z_MISC_FS: 26047c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, 26057c478bd9Sstevel@tonic-gate "Miscellaneous file system error")); 26067c478bd9Sstevel@tonic-gate case Z_NO_ZONE: 26077c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "No such zone configured")); 26087c478bd9Sstevel@tonic-gate case Z_NO_RESOURCE_TYPE: 26097c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "No such resource type")); 26107c478bd9Sstevel@tonic-gate case Z_NO_RESOURCE_ID: 26117c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "No such resource with that id")); 26127c478bd9Sstevel@tonic-gate case Z_NO_PROPERTY_TYPE: 26137c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "No such property type")); 26147c478bd9Sstevel@tonic-gate case Z_NO_PROPERTY_ID: 26157c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "No such property with that id")); 2616087719fdSdp case Z_BAD_ZONE_STATE: 26177c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, 2618087719fdSdp "Zone state is invalid for the requested operation")); 26197c478bd9Sstevel@tonic-gate case Z_INVALID_DOCUMENT: 26207c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Invalid document")); 2621087719fdSdp case Z_NAME_IN_USE: 2622087719fdSdp return (dgettext(TEXT_DOMAIN, "Zone name already in use")); 26237c478bd9Sstevel@tonic-gate case Z_NO_SUCH_ID: 26247c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "No such zone ID")); 26257c478bd9Sstevel@tonic-gate case Z_UPDATING_INDEX: 26267c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Problem updating index file")); 26277c478bd9Sstevel@tonic-gate case Z_LOCKING_FILE: 26287c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Locking index file")); 26297c478bd9Sstevel@tonic-gate case Z_UNLOCKING_FILE: 26307c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Unlocking index file")); 26317c478bd9Sstevel@tonic-gate case Z_INSUFFICIENT_SPEC: 26327c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Insufficient specification")); 26337c478bd9Sstevel@tonic-gate case Z_RESOLVED_PATH: 26347c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Resolved path mismatch")); 26357c478bd9Sstevel@tonic-gate case Z_IPV6_ADDR_PREFIX_LEN: 26367c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, 26377c478bd9Sstevel@tonic-gate "IPv6 address missing required prefix length")); 26387c478bd9Sstevel@tonic-gate case Z_BOGUS_ADDRESS: 26397c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, 26407c478bd9Sstevel@tonic-gate "Neither an IPv4 nor an IPv6 address nor a host name")); 26417c478bd9Sstevel@tonic-gate default: 26427c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Unknown error")); 26437c478bd9Sstevel@tonic-gate } 26447c478bd9Sstevel@tonic-gate } 26457c478bd9Sstevel@tonic-gate 26467c478bd9Sstevel@tonic-gate /* 26477c478bd9Sstevel@tonic-gate * Note that the zonecfg_setXent() and zonecfg_endXent() calls are all the 26487c478bd9Sstevel@tonic-gate * same, as they just turn around and call zonecfg_setent() / zonecfg_endent(). 26497c478bd9Sstevel@tonic-gate */ 26507c478bd9Sstevel@tonic-gate 26517c478bd9Sstevel@tonic-gate static int 26527c478bd9Sstevel@tonic-gate zonecfg_setent(zone_dochandle_t handle) 26537c478bd9Sstevel@tonic-gate { 26547c478bd9Sstevel@tonic-gate xmlNodePtr cur; 26557c478bd9Sstevel@tonic-gate int err; 26567c478bd9Sstevel@tonic-gate 26577c478bd9Sstevel@tonic-gate if (handle == NULL) 26587c478bd9Sstevel@tonic-gate return (Z_INVAL); 26597c478bd9Sstevel@tonic-gate 26607c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) { 26617c478bd9Sstevel@tonic-gate handle->zone_dh_cur = NULL; 26627c478bd9Sstevel@tonic-gate return (err); 26637c478bd9Sstevel@tonic-gate } 26647c478bd9Sstevel@tonic-gate cur = handle->zone_dh_cur; 26657c478bd9Sstevel@tonic-gate cur = cur->xmlChildrenNode; 26667c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur; 26677c478bd9Sstevel@tonic-gate return (Z_OK); 26687c478bd9Sstevel@tonic-gate } 26697c478bd9Sstevel@tonic-gate 26707c478bd9Sstevel@tonic-gate static int 26717c478bd9Sstevel@tonic-gate zonecfg_endent(zone_dochandle_t handle) 26727c478bd9Sstevel@tonic-gate { 26737c478bd9Sstevel@tonic-gate if (handle == NULL) 26747c478bd9Sstevel@tonic-gate return (Z_INVAL); 26757c478bd9Sstevel@tonic-gate 26767c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 26777c478bd9Sstevel@tonic-gate return (Z_OK); 26787c478bd9Sstevel@tonic-gate } 26797c478bd9Sstevel@tonic-gate 26807c478bd9Sstevel@tonic-gate int 26817c478bd9Sstevel@tonic-gate zonecfg_setfsent(zone_dochandle_t handle) 26827c478bd9Sstevel@tonic-gate { 26837c478bd9Sstevel@tonic-gate return (zonecfg_setent(handle)); 26847c478bd9Sstevel@tonic-gate } 26857c478bd9Sstevel@tonic-gate 26867c478bd9Sstevel@tonic-gate int 26877c478bd9Sstevel@tonic-gate zonecfg_getfsent(zone_dochandle_t handle, struct zone_fstab *tabptr) 26887c478bd9Sstevel@tonic-gate { 26897c478bd9Sstevel@tonic-gate xmlNodePtr cur, options; 26907c478bd9Sstevel@tonic-gate char options_str[MAX_MNTOPT_STR]; 26917c478bd9Sstevel@tonic-gate int err; 26927c478bd9Sstevel@tonic-gate 26937c478bd9Sstevel@tonic-gate if (handle == NULL) 26947c478bd9Sstevel@tonic-gate return (Z_INVAL); 26957c478bd9Sstevel@tonic-gate 26967c478bd9Sstevel@tonic-gate if ((cur = handle->zone_dh_cur) == NULL) 26977c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 26987c478bd9Sstevel@tonic-gate 26997c478bd9Sstevel@tonic-gate for (; cur != NULL; cur = cur->next) 27007c478bd9Sstevel@tonic-gate if (!xmlStrcmp(cur->name, DTD_ELEM_FS)) 27017c478bd9Sstevel@tonic-gate break; 27027c478bd9Sstevel@tonic-gate if (cur == NULL) { 27037c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 27047c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 27057c478bd9Sstevel@tonic-gate } 27067c478bd9Sstevel@tonic-gate 27077c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_SPECIAL, tabptr->zone_fs_special, 27087c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_special))) != Z_OK) { 27097c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 27107c478bd9Sstevel@tonic-gate return (err); 27117c478bd9Sstevel@tonic-gate } 27127c478bd9Sstevel@tonic-gate 27137c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_RAW, tabptr->zone_fs_raw, 27147c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_raw))) != Z_OK) { 27157c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 27167c478bd9Sstevel@tonic-gate return (err); 27177c478bd9Sstevel@tonic-gate } 27187c478bd9Sstevel@tonic-gate 27197c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir, 27207c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_dir))) != Z_OK) { 27217c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 27227c478bd9Sstevel@tonic-gate return (err); 27237c478bd9Sstevel@tonic-gate } 27247c478bd9Sstevel@tonic-gate 27257c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_TYPE, tabptr->zone_fs_type, 27267c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_type))) != Z_OK) { 27277c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 27287c478bd9Sstevel@tonic-gate return (err); 27297c478bd9Sstevel@tonic-gate } 27307c478bd9Sstevel@tonic-gate 27317c478bd9Sstevel@tonic-gate /* OK for options to be NULL */ 27327c478bd9Sstevel@tonic-gate tabptr->zone_fs_options = NULL; 27337c478bd9Sstevel@tonic-gate for (options = cur->xmlChildrenNode; options != NULL; 27347c478bd9Sstevel@tonic-gate options = options->next) { 27357c478bd9Sstevel@tonic-gate if (fetchprop(options, DTD_ATTR_NAME, options_str, 27367c478bd9Sstevel@tonic-gate sizeof (options_str)) != Z_OK) 27377c478bd9Sstevel@tonic-gate break; 27387c478bd9Sstevel@tonic-gate if (zonecfg_add_fs_option(tabptr, options_str) != Z_OK) 27397c478bd9Sstevel@tonic-gate break; 27407c478bd9Sstevel@tonic-gate } 27417c478bd9Sstevel@tonic-gate 27427c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur->next; 27437c478bd9Sstevel@tonic-gate return (Z_OK); 27447c478bd9Sstevel@tonic-gate } 27457c478bd9Sstevel@tonic-gate 27467c478bd9Sstevel@tonic-gate int 27477c478bd9Sstevel@tonic-gate zonecfg_endfsent(zone_dochandle_t handle) 27487c478bd9Sstevel@tonic-gate { 27497c478bd9Sstevel@tonic-gate return (zonecfg_endent(handle)); 27507c478bd9Sstevel@tonic-gate } 27517c478bd9Sstevel@tonic-gate 27527c478bd9Sstevel@tonic-gate int 27537c478bd9Sstevel@tonic-gate zonecfg_setipdent(zone_dochandle_t handle) 27547c478bd9Sstevel@tonic-gate { 27557c478bd9Sstevel@tonic-gate return (zonecfg_setent(handle)); 27567c478bd9Sstevel@tonic-gate } 27577c478bd9Sstevel@tonic-gate 27587c478bd9Sstevel@tonic-gate int 27597c478bd9Sstevel@tonic-gate zonecfg_getipdent(zone_dochandle_t handle, struct zone_fstab *tabptr) 27607c478bd9Sstevel@tonic-gate { 27617c478bd9Sstevel@tonic-gate xmlNodePtr cur; 27627c478bd9Sstevel@tonic-gate int err; 27637c478bd9Sstevel@tonic-gate 27647c478bd9Sstevel@tonic-gate if (handle == NULL) 27657c478bd9Sstevel@tonic-gate return (Z_INVAL); 27667c478bd9Sstevel@tonic-gate 27677c478bd9Sstevel@tonic-gate if ((cur = handle->zone_dh_cur) == NULL) 27687c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 27697c478bd9Sstevel@tonic-gate 27707c478bd9Sstevel@tonic-gate for (; cur != NULL; cur = cur->next) 27717c478bd9Sstevel@tonic-gate if (!xmlStrcmp(cur->name, DTD_ELEM_IPD)) 27727c478bd9Sstevel@tonic-gate break; 27737c478bd9Sstevel@tonic-gate if (cur == NULL) { 27747c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 27757c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 27767c478bd9Sstevel@tonic-gate } 27777c478bd9Sstevel@tonic-gate 27787c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir, 27797c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_dir))) != Z_OK) { 27807c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 27817c478bd9Sstevel@tonic-gate return (err); 27827c478bd9Sstevel@tonic-gate } 27837c478bd9Sstevel@tonic-gate 27847c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur->next; 27857c478bd9Sstevel@tonic-gate return (Z_OK); 27867c478bd9Sstevel@tonic-gate } 27877c478bd9Sstevel@tonic-gate 27887c478bd9Sstevel@tonic-gate int 27897c478bd9Sstevel@tonic-gate zonecfg_endipdent(zone_dochandle_t handle) 27907c478bd9Sstevel@tonic-gate { 27917c478bd9Sstevel@tonic-gate return (zonecfg_endent(handle)); 27927c478bd9Sstevel@tonic-gate } 27937c478bd9Sstevel@tonic-gate 27947c478bd9Sstevel@tonic-gate int 27957c478bd9Sstevel@tonic-gate zonecfg_setnwifent(zone_dochandle_t handle) 27967c478bd9Sstevel@tonic-gate { 27977c478bd9Sstevel@tonic-gate return (zonecfg_setent(handle)); 27987c478bd9Sstevel@tonic-gate } 27997c478bd9Sstevel@tonic-gate 28007c478bd9Sstevel@tonic-gate int 28017c478bd9Sstevel@tonic-gate zonecfg_getnwifent(zone_dochandle_t handle, struct zone_nwiftab *tabptr) 28027c478bd9Sstevel@tonic-gate { 28037c478bd9Sstevel@tonic-gate xmlNodePtr cur; 28047c478bd9Sstevel@tonic-gate int err; 28057c478bd9Sstevel@tonic-gate 28067c478bd9Sstevel@tonic-gate if (handle == NULL) 28077c478bd9Sstevel@tonic-gate return (Z_INVAL); 28087c478bd9Sstevel@tonic-gate 28097c478bd9Sstevel@tonic-gate if ((cur = handle->zone_dh_cur) == NULL) 28107c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 28117c478bd9Sstevel@tonic-gate 28127c478bd9Sstevel@tonic-gate for (; cur != NULL; cur = cur->next) 28137c478bd9Sstevel@tonic-gate if (!xmlStrcmp(cur->name, DTD_ELEM_NET)) 28147c478bd9Sstevel@tonic-gate break; 28157c478bd9Sstevel@tonic-gate if (cur == NULL) { 28167c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 28177c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 28187c478bd9Sstevel@tonic-gate } 28197c478bd9Sstevel@tonic-gate 28207c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_ADDRESS, tabptr->zone_nwif_address, 28217c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_nwif_address))) != Z_OK) { 28227c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 28237c478bd9Sstevel@tonic-gate return (err); 28247c478bd9Sstevel@tonic-gate } 28257c478bd9Sstevel@tonic-gate 28267c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_PHYSICAL, tabptr->zone_nwif_physical, 28277c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_nwif_physical))) != Z_OK) { 28287c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 28297c478bd9Sstevel@tonic-gate return (err); 28307c478bd9Sstevel@tonic-gate } 28317c478bd9Sstevel@tonic-gate 28327c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur->next; 28337c478bd9Sstevel@tonic-gate return (Z_OK); 28347c478bd9Sstevel@tonic-gate } 28357c478bd9Sstevel@tonic-gate 28367c478bd9Sstevel@tonic-gate int 28377c478bd9Sstevel@tonic-gate zonecfg_endnwifent(zone_dochandle_t handle) 28387c478bd9Sstevel@tonic-gate { 28397c478bd9Sstevel@tonic-gate return (zonecfg_endent(handle)); 28407c478bd9Sstevel@tonic-gate } 28417c478bd9Sstevel@tonic-gate 28427c478bd9Sstevel@tonic-gate int 28437c478bd9Sstevel@tonic-gate zonecfg_setdevent(zone_dochandle_t handle) 28447c478bd9Sstevel@tonic-gate { 28457c478bd9Sstevel@tonic-gate return (zonecfg_setent(handle)); 28467c478bd9Sstevel@tonic-gate } 28477c478bd9Sstevel@tonic-gate 28487c478bd9Sstevel@tonic-gate int 28497c478bd9Sstevel@tonic-gate zonecfg_getdevent(zone_dochandle_t handle, struct zone_devtab *tabptr) 28507c478bd9Sstevel@tonic-gate { 28517c478bd9Sstevel@tonic-gate xmlNodePtr cur; 28527c478bd9Sstevel@tonic-gate int err; 28537c478bd9Sstevel@tonic-gate 28547c478bd9Sstevel@tonic-gate if (handle == NULL) 28557c478bd9Sstevel@tonic-gate return (Z_INVAL); 28567c478bd9Sstevel@tonic-gate 28577c478bd9Sstevel@tonic-gate if ((cur = handle->zone_dh_cur) == NULL) 28587c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 28597c478bd9Sstevel@tonic-gate 28607c478bd9Sstevel@tonic-gate for (; cur != NULL; cur = cur->next) 28617c478bd9Sstevel@tonic-gate if (!xmlStrcmp(cur->name, DTD_ELEM_DEVICE)) 28627c478bd9Sstevel@tonic-gate break; 28637c478bd9Sstevel@tonic-gate if (cur == NULL) { 28647c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 28657c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 28667c478bd9Sstevel@tonic-gate } 28677c478bd9Sstevel@tonic-gate 28687c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_MATCH, tabptr->zone_dev_match, 28697c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_dev_match))) != Z_OK) { 28707c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 28717c478bd9Sstevel@tonic-gate return (err); 28727c478bd9Sstevel@tonic-gate } 28737c478bd9Sstevel@tonic-gate 28747c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur->next; 28757c478bd9Sstevel@tonic-gate return (Z_OK); 28767c478bd9Sstevel@tonic-gate } 28777c478bd9Sstevel@tonic-gate 28787c478bd9Sstevel@tonic-gate int 28797c478bd9Sstevel@tonic-gate zonecfg_enddevent(zone_dochandle_t handle) 28807c478bd9Sstevel@tonic-gate { 28817c478bd9Sstevel@tonic-gate return (zonecfg_endent(handle)); 28827c478bd9Sstevel@tonic-gate } 28837c478bd9Sstevel@tonic-gate 28847c478bd9Sstevel@tonic-gate int 28857c478bd9Sstevel@tonic-gate zonecfg_setrctlent(zone_dochandle_t handle) 28867c478bd9Sstevel@tonic-gate { 28877c478bd9Sstevel@tonic-gate return (zonecfg_setent(handle)); 28887c478bd9Sstevel@tonic-gate } 28897c478bd9Sstevel@tonic-gate 28907c478bd9Sstevel@tonic-gate int 28917c478bd9Sstevel@tonic-gate zonecfg_getrctlent(zone_dochandle_t handle, struct zone_rctltab *tabptr) 28927c478bd9Sstevel@tonic-gate { 28937c478bd9Sstevel@tonic-gate xmlNodePtr cur, val; 28947c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *valptr; 28957c478bd9Sstevel@tonic-gate int err; 28967c478bd9Sstevel@tonic-gate 28977c478bd9Sstevel@tonic-gate if (handle == NULL) 28987c478bd9Sstevel@tonic-gate return (Z_INVAL); 28997c478bd9Sstevel@tonic-gate 29007c478bd9Sstevel@tonic-gate if ((cur = handle->zone_dh_cur) == NULL) 29017c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 29027c478bd9Sstevel@tonic-gate 29037c478bd9Sstevel@tonic-gate for (; cur != NULL; cur = cur->next) 29047c478bd9Sstevel@tonic-gate if (!xmlStrcmp(cur->name, DTD_ELEM_RCTL)) 29057c478bd9Sstevel@tonic-gate break; 29067c478bd9Sstevel@tonic-gate if (cur == NULL) { 29077c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 29087c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 29097c478bd9Sstevel@tonic-gate } 29107c478bd9Sstevel@tonic-gate 29117c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_NAME, tabptr->zone_rctl_name, 29127c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_rctl_name))) != Z_OK) { 29137c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 29147c478bd9Sstevel@tonic-gate return (err); 29157c478bd9Sstevel@tonic-gate } 29167c478bd9Sstevel@tonic-gate 29177c478bd9Sstevel@tonic-gate tabptr->zone_rctl_valptr = NULL; 29187c478bd9Sstevel@tonic-gate for (val = cur->xmlChildrenNode; val != NULL; val = val->next) { 29197c478bd9Sstevel@tonic-gate valptr = (struct zone_rctlvaltab *)malloc( 29207c478bd9Sstevel@tonic-gate sizeof (struct zone_rctlvaltab)); 29217c478bd9Sstevel@tonic-gate if (valptr == NULL) 29227c478bd9Sstevel@tonic-gate return (Z_NOMEM); 29237c478bd9Sstevel@tonic-gate if (fetchprop(val, DTD_ATTR_PRIV, valptr->zone_rctlval_priv, 29247c478bd9Sstevel@tonic-gate sizeof (valptr->zone_rctlval_priv)) != Z_OK) 29257c478bd9Sstevel@tonic-gate break; 29267c478bd9Sstevel@tonic-gate if (fetchprop(val, DTD_ATTR_LIMIT, valptr->zone_rctlval_limit, 29277c478bd9Sstevel@tonic-gate sizeof (valptr->zone_rctlval_limit)) != Z_OK) 29287c478bd9Sstevel@tonic-gate break; 29297c478bd9Sstevel@tonic-gate if (fetchprop(val, DTD_ATTR_ACTION, valptr->zone_rctlval_action, 29307c478bd9Sstevel@tonic-gate sizeof (valptr->zone_rctlval_action)) != Z_OK) 29317c478bd9Sstevel@tonic-gate break; 29327c478bd9Sstevel@tonic-gate if (zonecfg_add_rctl_value(tabptr, valptr) != Z_OK) 29337c478bd9Sstevel@tonic-gate break; 29347c478bd9Sstevel@tonic-gate } 29357c478bd9Sstevel@tonic-gate 29367c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur->next; 29377c478bd9Sstevel@tonic-gate return (Z_OK); 29387c478bd9Sstevel@tonic-gate } 29397c478bd9Sstevel@tonic-gate 29407c478bd9Sstevel@tonic-gate int 29417c478bd9Sstevel@tonic-gate zonecfg_endrctlent(zone_dochandle_t handle) 29427c478bd9Sstevel@tonic-gate { 29437c478bd9Sstevel@tonic-gate return (zonecfg_endent(handle)); 29447c478bd9Sstevel@tonic-gate } 29457c478bd9Sstevel@tonic-gate 29467c478bd9Sstevel@tonic-gate int 29477c478bd9Sstevel@tonic-gate zonecfg_setattrent(zone_dochandle_t handle) 29487c478bd9Sstevel@tonic-gate { 29497c478bd9Sstevel@tonic-gate return (zonecfg_setent(handle)); 29507c478bd9Sstevel@tonic-gate } 29517c478bd9Sstevel@tonic-gate 29527c478bd9Sstevel@tonic-gate int 29537c478bd9Sstevel@tonic-gate zonecfg_getattrent(zone_dochandle_t handle, struct zone_attrtab *tabptr) 29547c478bd9Sstevel@tonic-gate { 29557c478bd9Sstevel@tonic-gate xmlNodePtr cur; 29567c478bd9Sstevel@tonic-gate int err; 29577c478bd9Sstevel@tonic-gate 29587c478bd9Sstevel@tonic-gate if (handle == NULL) 29597c478bd9Sstevel@tonic-gate return (Z_INVAL); 29607c478bd9Sstevel@tonic-gate 29617c478bd9Sstevel@tonic-gate if ((cur = handle->zone_dh_cur) == NULL) 29627c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 29637c478bd9Sstevel@tonic-gate 29647c478bd9Sstevel@tonic-gate for (; cur != NULL; cur = cur->next) 29657c478bd9Sstevel@tonic-gate if (!xmlStrcmp(cur->name, DTD_ELEM_ATTR)) 29667c478bd9Sstevel@tonic-gate break; 29677c478bd9Sstevel@tonic-gate if (cur == NULL) { 29687c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 29697c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 29707c478bd9Sstevel@tonic-gate } 29717c478bd9Sstevel@tonic-gate 29727c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_NAME, tabptr->zone_attr_name, 29737c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_attr_name))) != Z_OK) { 29747c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 29757c478bd9Sstevel@tonic-gate return (err); 29767c478bd9Sstevel@tonic-gate } 29777c478bd9Sstevel@tonic-gate 29787c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_TYPE, tabptr->zone_attr_type, 29797c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_attr_type))) != Z_OK) { 29807c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 29817c478bd9Sstevel@tonic-gate return (err); 29827c478bd9Sstevel@tonic-gate } 29837c478bd9Sstevel@tonic-gate 29847c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_VALUE, tabptr->zone_attr_value, 29857c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_attr_value))) != Z_OK) { 29867c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 29877c478bd9Sstevel@tonic-gate return (err); 29887c478bd9Sstevel@tonic-gate } 29897c478bd9Sstevel@tonic-gate 29907c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur->next; 29917c478bd9Sstevel@tonic-gate return (Z_OK); 29927c478bd9Sstevel@tonic-gate } 29937c478bd9Sstevel@tonic-gate 29947c478bd9Sstevel@tonic-gate int 29957c478bd9Sstevel@tonic-gate zonecfg_endattrent(zone_dochandle_t handle) 29967c478bd9Sstevel@tonic-gate { 29977c478bd9Sstevel@tonic-gate return (zonecfg_endent(handle)); 29987c478bd9Sstevel@tonic-gate } 29997c478bd9Sstevel@tonic-gate 30007c478bd9Sstevel@tonic-gate /* This will ultimately be configurable. */ 30017c478bd9Sstevel@tonic-gate static const char *priv_list[] = { 30027c478bd9Sstevel@tonic-gate PRIV_FILE_CHOWN, 30037c478bd9Sstevel@tonic-gate PRIV_FILE_CHOWN_SELF, 30047c478bd9Sstevel@tonic-gate PRIV_FILE_DAC_EXECUTE, 30057c478bd9Sstevel@tonic-gate PRIV_FILE_DAC_READ, 30067c478bd9Sstevel@tonic-gate PRIV_FILE_DAC_SEARCH, 30077c478bd9Sstevel@tonic-gate PRIV_FILE_DAC_WRITE, 30087c478bd9Sstevel@tonic-gate PRIV_FILE_OWNER, 30097c478bd9Sstevel@tonic-gate PRIV_FILE_SETID, 30107c478bd9Sstevel@tonic-gate PRIV_IPC_DAC_READ, 30117c478bd9Sstevel@tonic-gate PRIV_IPC_DAC_WRITE, 30127c478bd9Sstevel@tonic-gate PRIV_IPC_OWNER, 30137c478bd9Sstevel@tonic-gate PRIV_NET_ICMPACCESS, 30147c478bd9Sstevel@tonic-gate PRIV_NET_PRIVADDR, 30157c478bd9Sstevel@tonic-gate PRIV_PROC_CHROOT, 30167c478bd9Sstevel@tonic-gate PRIV_SYS_AUDIT, 30177c478bd9Sstevel@tonic-gate PRIV_PROC_AUDIT, 30187c478bd9Sstevel@tonic-gate PRIV_PROC_OWNER, 30197c478bd9Sstevel@tonic-gate PRIV_PROC_SETID, 30207c478bd9Sstevel@tonic-gate PRIV_PROC_TASKID, 30217c478bd9Sstevel@tonic-gate PRIV_SYS_ACCT, 30227c478bd9Sstevel@tonic-gate PRIV_SYS_ADMIN, 30237c478bd9Sstevel@tonic-gate PRIV_SYS_MOUNT, 30247c478bd9Sstevel@tonic-gate PRIV_SYS_NFS, 30257c478bd9Sstevel@tonic-gate PRIV_SYS_RESOURCE, 30267c478bd9Sstevel@tonic-gate PRIV_CONTRACT_EVENT, 30277c478bd9Sstevel@tonic-gate PRIV_CONTRACT_OBSERVER, 30287c478bd9Sstevel@tonic-gate NULL 30297c478bd9Sstevel@tonic-gate }; 30307c478bd9Sstevel@tonic-gate 30317c478bd9Sstevel@tonic-gate int 30327c478bd9Sstevel@tonic-gate zonecfg_get_privset(priv_set_t *privs) 30337c478bd9Sstevel@tonic-gate { 30347c478bd9Sstevel@tonic-gate const char **strp; 30357c478bd9Sstevel@tonic-gate priv_set_t *basic = priv_str_to_set("basic", ",", NULL); 30367c478bd9Sstevel@tonic-gate 30377c478bd9Sstevel@tonic-gate if (basic == NULL) 30387c478bd9Sstevel@tonic-gate return (Z_INVAL); 30397c478bd9Sstevel@tonic-gate 30407c478bd9Sstevel@tonic-gate priv_union(basic, privs); 30417c478bd9Sstevel@tonic-gate priv_freeset(basic); 30427c478bd9Sstevel@tonic-gate 30437c478bd9Sstevel@tonic-gate for (strp = priv_list; *strp != NULL; strp++) { 30447c478bd9Sstevel@tonic-gate if (priv_addset(privs, *strp) != 0) { 30457c478bd9Sstevel@tonic-gate return (Z_INVAL); 30467c478bd9Sstevel@tonic-gate } 30477c478bd9Sstevel@tonic-gate } 30487c478bd9Sstevel@tonic-gate return (Z_OK); 30497c478bd9Sstevel@tonic-gate } 30507c478bd9Sstevel@tonic-gate 30517c478bd9Sstevel@tonic-gate int 30527c478bd9Sstevel@tonic-gate zone_get_zonepath(char *zone_name, char *zonepath, size_t rp_sz) 30537c478bd9Sstevel@tonic-gate { 30547c478bd9Sstevel@tonic-gate zone_dochandle_t handle; 30557c478bd9Sstevel@tonic-gate boolean_t found = B_FALSE; 30567c478bd9Sstevel@tonic-gate struct zoneent *ze; 30577c478bd9Sstevel@tonic-gate FILE *cookie; 30587c478bd9Sstevel@tonic-gate int err; 3059108322fbScarlsonj char *cp; 30607c478bd9Sstevel@tonic-gate 30617c478bd9Sstevel@tonic-gate if (zone_name == NULL) 30627c478bd9Sstevel@tonic-gate return (Z_INVAL); 30637c478bd9Sstevel@tonic-gate 3064108322fbScarlsonj (void) strlcpy(zonepath, zonecfg_root, rp_sz); 3065108322fbScarlsonj cp = zonepath + strlen(zonepath); 3066108322fbScarlsonj while (cp > zonepath && cp[-1] == '/') 3067108322fbScarlsonj *--cp = '\0'; 3068108322fbScarlsonj 30697c478bd9Sstevel@tonic-gate if (strcmp(zone_name, GLOBAL_ZONENAME) == 0) { 3070108322fbScarlsonj if (zonepath[0] == '\0') 30717c478bd9Sstevel@tonic-gate (void) strlcpy(zonepath, "/", rp_sz); 30727c478bd9Sstevel@tonic-gate return (Z_OK); 30737c478bd9Sstevel@tonic-gate } 30747c478bd9Sstevel@tonic-gate 30757c478bd9Sstevel@tonic-gate /* 30767c478bd9Sstevel@tonic-gate * First check the index file. Because older versions did not have 30777c478bd9Sstevel@tonic-gate * a copy of the zone path, allow for it to be zero length, in which 30787c478bd9Sstevel@tonic-gate * case we ignore this result and fall back to the XML files. 30797c478bd9Sstevel@tonic-gate */ 30807c478bd9Sstevel@tonic-gate cookie = setzoneent(); 30817c478bd9Sstevel@tonic-gate while ((ze = getzoneent_private(cookie)) != NULL) { 30827c478bd9Sstevel@tonic-gate if (strcmp(ze->zone_name, zone_name) == 0) { 30837c478bd9Sstevel@tonic-gate found = B_TRUE; 3084108322fbScarlsonj if (ze->zone_path[0] != '\0') 3085108322fbScarlsonj (void) strlcpy(cp, ze->zone_path, 3086108322fbScarlsonj rp_sz - (cp - zonepath)); 30877c478bd9Sstevel@tonic-gate } 30887c478bd9Sstevel@tonic-gate free(ze); 30897c478bd9Sstevel@tonic-gate if (found) 30907c478bd9Sstevel@tonic-gate break; 30917c478bd9Sstevel@tonic-gate } 30927c478bd9Sstevel@tonic-gate endzoneent(cookie); 3093108322fbScarlsonj if (found && *cp != '\0') 30947c478bd9Sstevel@tonic-gate return (Z_OK); 30957c478bd9Sstevel@tonic-gate 30967c478bd9Sstevel@tonic-gate /* Fall back to the XML files. */ 30977c478bd9Sstevel@tonic-gate if ((handle = zonecfg_init_handle()) == NULL) 30987c478bd9Sstevel@tonic-gate return (Z_NOMEM); 30997c478bd9Sstevel@tonic-gate 31007c478bd9Sstevel@tonic-gate /* 31017c478bd9Sstevel@tonic-gate * Check the snapshot first: if a zone is running, its zonepath 31027c478bd9Sstevel@tonic-gate * may have changed. 31037c478bd9Sstevel@tonic-gate */ 31047c478bd9Sstevel@tonic-gate if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) { 31057c478bd9Sstevel@tonic-gate if ((err = zonecfg_get_handle(zone_name, handle)) != Z_OK) 31067c478bd9Sstevel@tonic-gate return (err); 31077c478bd9Sstevel@tonic-gate } 31087c478bd9Sstevel@tonic-gate err = zonecfg_get_zonepath(handle, zonepath, rp_sz); 31097c478bd9Sstevel@tonic-gate zonecfg_fini_handle(handle); 31107c478bd9Sstevel@tonic-gate return (err); 31117c478bd9Sstevel@tonic-gate } 31127c478bd9Sstevel@tonic-gate 31137c478bd9Sstevel@tonic-gate int 31147c478bd9Sstevel@tonic-gate zone_get_rootpath(char *zone_name, char *rootpath, size_t rp_sz) 31157c478bd9Sstevel@tonic-gate { 31167c478bd9Sstevel@tonic-gate int err; 31177c478bd9Sstevel@tonic-gate 31187c478bd9Sstevel@tonic-gate /* This function makes sense for non-global zones only. */ 31197c478bd9Sstevel@tonic-gate if (strcmp(zone_name, GLOBAL_ZONENAME) == 0) 31207c478bd9Sstevel@tonic-gate return (Z_BOGUS_ZONE_NAME); 31217c478bd9Sstevel@tonic-gate if ((err = zone_get_zonepath(zone_name, rootpath, rp_sz)) != Z_OK) 31227c478bd9Sstevel@tonic-gate return (err); 31237c478bd9Sstevel@tonic-gate if (strlcat(rootpath, "/root", rp_sz) >= rp_sz) 31247c478bd9Sstevel@tonic-gate return (Z_TOO_BIG); 31257c478bd9Sstevel@tonic-gate return (Z_OK); 31267c478bd9Sstevel@tonic-gate } 31277c478bd9Sstevel@tonic-gate 31287c478bd9Sstevel@tonic-gate static zone_state_t 3129108322fbScarlsonj kernel_state_to_user_state(zoneid_t zoneid, zone_status_t kernel_state) 31307c478bd9Sstevel@tonic-gate { 3131108322fbScarlsonj char zoneroot[MAXPATHLEN]; 3132108322fbScarlsonj size_t zlen; 3133108322fbScarlsonj 31347c478bd9Sstevel@tonic-gate assert(kernel_state <= ZONE_MAX_STATE); 31357c478bd9Sstevel@tonic-gate switch (kernel_state) { 31367c478bd9Sstevel@tonic-gate case ZONE_IS_UNINITIALIZED: 3137108322fbScarlsonj return (ZONE_STATE_READY); 31387c478bd9Sstevel@tonic-gate case ZONE_IS_READY: 3139108322fbScarlsonj /* 3140108322fbScarlsonj * If the zone's root is mounted on $ZONEPATH/lu, then 3141108322fbScarlsonj * it's a mounted scratch zone. 3142108322fbScarlsonj */ 3143108322fbScarlsonj if (zone_getattr(zoneid, ZONE_ATTR_ROOT, zoneroot, 3144108322fbScarlsonj sizeof (zoneroot)) >= 0) { 3145108322fbScarlsonj zlen = strlen(zoneroot); 3146108322fbScarlsonj if (zlen > 3 && 3147108322fbScarlsonj strcmp(zoneroot + zlen - 3, "/lu") == 0) 3148108322fbScarlsonj return (ZONE_STATE_MOUNTED); 3149108322fbScarlsonj } 31507c478bd9Sstevel@tonic-gate return (ZONE_STATE_READY); 31517c478bd9Sstevel@tonic-gate case ZONE_IS_BOOTING: 31527c478bd9Sstevel@tonic-gate case ZONE_IS_RUNNING: 31537c478bd9Sstevel@tonic-gate return (ZONE_STATE_RUNNING); 31547c478bd9Sstevel@tonic-gate case ZONE_IS_SHUTTING_DOWN: 31557c478bd9Sstevel@tonic-gate case ZONE_IS_EMPTY: 31567c478bd9Sstevel@tonic-gate return (ZONE_STATE_SHUTTING_DOWN); 31577c478bd9Sstevel@tonic-gate case ZONE_IS_DOWN: 31587c478bd9Sstevel@tonic-gate case ZONE_IS_DYING: 31597c478bd9Sstevel@tonic-gate case ZONE_IS_DEAD: 31607c478bd9Sstevel@tonic-gate default: 31617c478bd9Sstevel@tonic-gate return (ZONE_STATE_DOWN); 31627c478bd9Sstevel@tonic-gate } 31637c478bd9Sstevel@tonic-gate /* NOTREACHED */ 31647c478bd9Sstevel@tonic-gate } 31657c478bd9Sstevel@tonic-gate 31667c478bd9Sstevel@tonic-gate int 31677c478bd9Sstevel@tonic-gate zone_get_state(char *zone_name, zone_state_t *state_num) 31687c478bd9Sstevel@tonic-gate { 31697c478bd9Sstevel@tonic-gate zone_status_t status; 31707c478bd9Sstevel@tonic-gate zoneid_t zone_id; 31717c478bd9Sstevel@tonic-gate struct zoneent *ze; 31727c478bd9Sstevel@tonic-gate boolean_t found = B_FALSE; 31737c478bd9Sstevel@tonic-gate FILE *cookie; 3174108322fbScarlsonj char kernzone[ZONENAME_MAX]; 3175108322fbScarlsonj FILE *fp; 31767c478bd9Sstevel@tonic-gate 31777c478bd9Sstevel@tonic-gate if (zone_name == NULL) 31787c478bd9Sstevel@tonic-gate return (Z_INVAL); 31797c478bd9Sstevel@tonic-gate 3180108322fbScarlsonj /* 3181108322fbScarlsonj * If we're looking at an alternate root, then we need to query the 3182108322fbScarlsonj * kernel using the scratch zone name. 3183108322fbScarlsonj */ 3184108322fbScarlsonj zone_id = -1; 3185108322fbScarlsonj if (*zonecfg_root != '\0' && !zonecfg_is_scratch(zone_name)) { 3186108322fbScarlsonj if ((fp = zonecfg_open_scratch("", B_FALSE)) != NULL) { 3187108322fbScarlsonj if (zonecfg_find_scratch(fp, zone_name, zonecfg_root, 3188108322fbScarlsonj kernzone, sizeof (kernzone)) == 0) 3189108322fbScarlsonj zone_id = getzoneidbyname(kernzone); 3190108322fbScarlsonj zonecfg_close_scratch(fp); 3191108322fbScarlsonj } 3192108322fbScarlsonj } else { 3193108322fbScarlsonj zone_id = getzoneidbyname(zone_name); 3194108322fbScarlsonj } 3195108322fbScarlsonj 31967c478bd9Sstevel@tonic-gate /* check to see if zone is running */ 3197108322fbScarlsonj if (zone_id != -1 && 31987c478bd9Sstevel@tonic-gate zone_getattr(zone_id, ZONE_ATTR_STATUS, &status, 31997c478bd9Sstevel@tonic-gate sizeof (status)) >= 0) { 3200108322fbScarlsonj *state_num = kernel_state_to_user_state(zone_id, status); 32017c478bd9Sstevel@tonic-gate return (Z_OK); 32027c478bd9Sstevel@tonic-gate } 32037c478bd9Sstevel@tonic-gate 32047c478bd9Sstevel@tonic-gate cookie = setzoneent(); 32057c478bd9Sstevel@tonic-gate while ((ze = getzoneent_private(cookie)) != NULL) { 32067c478bd9Sstevel@tonic-gate if (strcmp(ze->zone_name, zone_name) == 0) { 32077c478bd9Sstevel@tonic-gate found = B_TRUE; 32087c478bd9Sstevel@tonic-gate *state_num = ze->zone_state; 32097c478bd9Sstevel@tonic-gate } 32107c478bd9Sstevel@tonic-gate free(ze); 32117c478bd9Sstevel@tonic-gate if (found) 32127c478bd9Sstevel@tonic-gate break; 32137c478bd9Sstevel@tonic-gate } 32147c478bd9Sstevel@tonic-gate endzoneent(cookie); 32157c478bd9Sstevel@tonic-gate return ((found) ? Z_OK : Z_NO_ZONE); 32167c478bd9Sstevel@tonic-gate } 32177c478bd9Sstevel@tonic-gate 32187c478bd9Sstevel@tonic-gate int 32197c478bd9Sstevel@tonic-gate zone_set_state(char *zone, zone_state_t state) 32207c478bd9Sstevel@tonic-gate { 32217c478bd9Sstevel@tonic-gate struct zoneent ze; 32227c478bd9Sstevel@tonic-gate 32237c478bd9Sstevel@tonic-gate if (state != ZONE_STATE_CONFIGURED && state != ZONE_STATE_INSTALLED && 32247c478bd9Sstevel@tonic-gate state != ZONE_STATE_INCOMPLETE) 32257c478bd9Sstevel@tonic-gate return (Z_INVAL); 32267c478bd9Sstevel@tonic-gate 3227087719fdSdp bzero(&ze, sizeof (ze)); 32287c478bd9Sstevel@tonic-gate (void) strlcpy(ze.zone_name, zone, sizeof (ze.zone_name)); 32297c478bd9Sstevel@tonic-gate ze.zone_state = state; 32307c478bd9Sstevel@tonic-gate (void) strlcpy(ze.zone_path, "", sizeof (ze.zone_path)); 32317c478bd9Sstevel@tonic-gate return (putzoneent(&ze, PZE_MODIFY)); 32327c478bd9Sstevel@tonic-gate } 32337c478bd9Sstevel@tonic-gate 32347c478bd9Sstevel@tonic-gate /* 32357c478bd9Sstevel@tonic-gate * Get id (if any) for specified zone. There are four possible outcomes: 32367c478bd9Sstevel@tonic-gate * - If the string corresponds to the numeric id of an active (booted) 32377c478bd9Sstevel@tonic-gate * zone, sets *zip to the zone id and returns 0. 32387c478bd9Sstevel@tonic-gate * - If the string corresponds to the name of an active (booted) zone, 32397c478bd9Sstevel@tonic-gate * sets *zip to the zone id and returns 0. 32407c478bd9Sstevel@tonic-gate * - If the string is a name in the configuration but is not booted, 32417c478bd9Sstevel@tonic-gate * sets *zip to ZONE_ID_UNDEFINED and returns 0. 32427c478bd9Sstevel@tonic-gate * - Otherwise, leaves *zip unchanged and returns -1. 32437c478bd9Sstevel@tonic-gate * 32447c478bd9Sstevel@tonic-gate * This function acts as an auxiliary filter on the function of the same 32457c478bd9Sstevel@tonic-gate * name in libc; the linker binds to this version if libzonecfg exists, 32467c478bd9Sstevel@tonic-gate * and the libc version if it doesn't. Any changes to this version of 32477c478bd9Sstevel@tonic-gate * the function should probably be reflected in the libc version as well. 32487c478bd9Sstevel@tonic-gate */ 32497c478bd9Sstevel@tonic-gate int 32507c478bd9Sstevel@tonic-gate zone_get_id(const char *str, zoneid_t *zip) 32517c478bd9Sstevel@tonic-gate { 32527c478bd9Sstevel@tonic-gate zone_dochandle_t hdl; 32537c478bd9Sstevel@tonic-gate zoneid_t zoneid; 32547c478bd9Sstevel@tonic-gate char *cp; 32557c478bd9Sstevel@tonic-gate int err; 32567c478bd9Sstevel@tonic-gate 32577c478bd9Sstevel@tonic-gate /* first try looking for active zone by id */ 32587c478bd9Sstevel@tonic-gate errno = 0; 32597c478bd9Sstevel@tonic-gate zoneid = (zoneid_t)strtol(str, &cp, 0); 32607c478bd9Sstevel@tonic-gate if (errno == 0 && cp != str && *cp == '\0' && 32617c478bd9Sstevel@tonic-gate getzonenamebyid(zoneid, NULL, 0) != -1) { 32627c478bd9Sstevel@tonic-gate *zip = zoneid; 32637c478bd9Sstevel@tonic-gate return (0); 32647c478bd9Sstevel@tonic-gate } 32657c478bd9Sstevel@tonic-gate 32667c478bd9Sstevel@tonic-gate /* then look for active zone by name */ 32677c478bd9Sstevel@tonic-gate if ((zoneid = getzoneidbyname(str)) != -1) { 32687c478bd9Sstevel@tonic-gate *zip = zoneid; 32697c478bd9Sstevel@tonic-gate return (0); 32707c478bd9Sstevel@tonic-gate } 32717c478bd9Sstevel@tonic-gate 32727c478bd9Sstevel@tonic-gate /* if in global zone, try looking up name in configuration database */ 32737c478bd9Sstevel@tonic-gate if (getzoneid() != GLOBAL_ZONEID || 32747c478bd9Sstevel@tonic-gate (hdl = zonecfg_init_handle()) == NULL) 32757c478bd9Sstevel@tonic-gate return (-1); 32767c478bd9Sstevel@tonic-gate 3277108322fbScarlsonj if (zonecfg_get_handle(str, hdl) == Z_OK) { 32787c478bd9Sstevel@tonic-gate /* zone exists but isn't active */ 32797c478bd9Sstevel@tonic-gate *zip = ZONE_ID_UNDEFINED; 32807c478bd9Sstevel@tonic-gate err = 0; 32817c478bd9Sstevel@tonic-gate } else { 32827c478bd9Sstevel@tonic-gate err = -1; 32837c478bd9Sstevel@tonic-gate } 32847c478bd9Sstevel@tonic-gate 32857c478bd9Sstevel@tonic-gate zonecfg_fini_handle(hdl); 32867c478bd9Sstevel@tonic-gate return (err); 32877c478bd9Sstevel@tonic-gate } 32887c478bd9Sstevel@tonic-gate 32897c478bd9Sstevel@tonic-gate char * 32907c478bd9Sstevel@tonic-gate zone_state_str(zone_state_t state_num) 32917c478bd9Sstevel@tonic-gate { 32927c478bd9Sstevel@tonic-gate switch (state_num) { 32937c478bd9Sstevel@tonic-gate case ZONE_STATE_CONFIGURED: 32947c478bd9Sstevel@tonic-gate return (ZONE_STATE_STR_CONFIGURED); 32957c478bd9Sstevel@tonic-gate case ZONE_STATE_INCOMPLETE: 32967c478bd9Sstevel@tonic-gate return (ZONE_STATE_STR_INCOMPLETE); 32977c478bd9Sstevel@tonic-gate case ZONE_STATE_INSTALLED: 32987c478bd9Sstevel@tonic-gate return (ZONE_STATE_STR_INSTALLED); 32997c478bd9Sstevel@tonic-gate case ZONE_STATE_READY: 33007c478bd9Sstevel@tonic-gate return (ZONE_STATE_STR_READY); 3301108322fbScarlsonj case ZONE_STATE_MOUNTED: 3302108322fbScarlsonj return (ZONE_STATE_STR_MOUNTED); 33037c478bd9Sstevel@tonic-gate case ZONE_STATE_RUNNING: 33047c478bd9Sstevel@tonic-gate return (ZONE_STATE_STR_RUNNING); 33057c478bd9Sstevel@tonic-gate case ZONE_STATE_SHUTTING_DOWN: 33067c478bd9Sstevel@tonic-gate return (ZONE_STATE_STR_SHUTTING_DOWN); 33077c478bd9Sstevel@tonic-gate case ZONE_STATE_DOWN: 33087c478bd9Sstevel@tonic-gate return (ZONE_STATE_STR_DOWN); 33097c478bd9Sstevel@tonic-gate default: 33107c478bd9Sstevel@tonic-gate return ("unknown"); 33117c478bd9Sstevel@tonic-gate } 33127c478bd9Sstevel@tonic-gate } 33137c478bd9Sstevel@tonic-gate 33147c478bd9Sstevel@tonic-gate /* 3315108322fbScarlsonj * Given a UUID value, find an associated zone name. This is intended to be 3316108322fbScarlsonj * used by callers who set up some 'default' name (corresponding to the 3317108322fbScarlsonj * expected name for the zone) in the zonename buffer, and thus the function 3318108322fbScarlsonj * doesn't touch this buffer on failure. 3319108322fbScarlsonj */ 3320108322fbScarlsonj int 3321108322fbScarlsonj zonecfg_get_name_by_uuid(const uuid_t uuid, char *zonename, size_t namelen) 3322108322fbScarlsonj { 3323108322fbScarlsonj FILE *fp; 3324108322fbScarlsonj struct zoneent *ze; 3325108322fbScarlsonj 3326108322fbScarlsonj /* 3327108322fbScarlsonj * A small amount of subterfuge via casts is necessary here because 3328108322fbScarlsonj * libuuid doesn't use const correctly, but we don't want to export 3329108322fbScarlsonj * this brokenness to our clients. 3330108322fbScarlsonj */ 3331108322fbScarlsonj if (uuid_is_null(*(uuid_t *)&uuid)) 3332108322fbScarlsonj return (Z_NO_ZONE); 3333108322fbScarlsonj if ((fp = setzoneent()) == NULL) 3334108322fbScarlsonj return (Z_NO_ZONE); 3335108322fbScarlsonj while ((ze = getzoneent_private(fp)) != NULL) { 3336108322fbScarlsonj if (uuid_compare(*(uuid_t *)&uuid, ze->zone_uuid) == 0) 3337108322fbScarlsonj break; 3338108322fbScarlsonj free(ze); 3339108322fbScarlsonj } 3340108322fbScarlsonj endzoneent(fp); 3341108322fbScarlsonj if (ze != NULL) { 3342108322fbScarlsonj (void) strlcpy(zonename, ze->zone_name, namelen); 3343108322fbScarlsonj free(ze); 3344108322fbScarlsonj return (Z_OK); 3345108322fbScarlsonj } else { 3346108322fbScarlsonj return (Z_NO_ZONE); 3347108322fbScarlsonj } 3348108322fbScarlsonj } 3349108322fbScarlsonj 3350108322fbScarlsonj /* 3351108322fbScarlsonj * Given a zone name, get its UUID. Returns a "NULL" UUID value if the zone 3352108322fbScarlsonj * exists but the file doesn't have a value set yet. Returns an error if the 3353108322fbScarlsonj * zone cannot be located. 3354108322fbScarlsonj */ 3355108322fbScarlsonj int 3356108322fbScarlsonj zonecfg_get_uuid(const char *zonename, uuid_t uuid) 3357108322fbScarlsonj { 3358108322fbScarlsonj FILE *fp; 3359108322fbScarlsonj struct zoneent *ze; 3360108322fbScarlsonj 3361108322fbScarlsonj if ((fp = setzoneent()) == NULL) 3362108322fbScarlsonj return (Z_NO_ZONE); 3363108322fbScarlsonj while ((ze = getzoneent_private(fp)) != NULL) { 3364108322fbScarlsonj if (strcmp(ze->zone_name, zonename) == 0) 3365108322fbScarlsonj break; 3366108322fbScarlsonj free(ze); 3367108322fbScarlsonj } 3368108322fbScarlsonj endzoneent(fp); 3369108322fbScarlsonj if (ze != NULL) { 3370108322fbScarlsonj uuid_copy(uuid, ze->zone_uuid); 3371108322fbScarlsonj free(ze); 3372108322fbScarlsonj return (Z_OK); 3373108322fbScarlsonj } else { 3374108322fbScarlsonj return (Z_NO_ZONE); 3375108322fbScarlsonj } 3376108322fbScarlsonj } 3377108322fbScarlsonj 3378108322fbScarlsonj /* 33797c478bd9Sstevel@tonic-gate * File-system convenience functions. 33807c478bd9Sstevel@tonic-gate */ 33817c478bd9Sstevel@tonic-gate boolean_t 33827c478bd9Sstevel@tonic-gate zonecfg_valid_fs_type(const char *type) 33837c478bd9Sstevel@tonic-gate { 33847c478bd9Sstevel@tonic-gate /* 33857c478bd9Sstevel@tonic-gate * We already know which FS types don't work. 33867c478bd9Sstevel@tonic-gate */ 33877c478bd9Sstevel@tonic-gate if (strcmp(type, "proc") == 0 || 33887c478bd9Sstevel@tonic-gate strcmp(type, "mntfs") == 0 || 33897c478bd9Sstevel@tonic-gate strcmp(type, "autofs") == 0 || 33907c478bd9Sstevel@tonic-gate strncmp(type, "nfs", sizeof ("nfs") - 1) == 0 || 33917c478bd9Sstevel@tonic-gate strcmp(type, "cachefs") == 0) 33927c478bd9Sstevel@tonic-gate return (B_FALSE); 33937c478bd9Sstevel@tonic-gate /* 33947c478bd9Sstevel@tonic-gate * The caller may do more detailed verification to make sure other 33957c478bd9Sstevel@tonic-gate * aspects of this filesystem type make sense. 33967c478bd9Sstevel@tonic-gate */ 33977c478bd9Sstevel@tonic-gate return (B_TRUE); 33987c478bd9Sstevel@tonic-gate } 33997c478bd9Sstevel@tonic-gate 34007c478bd9Sstevel@tonic-gate /* 34017c478bd9Sstevel@tonic-gate * Generally uninteresting rctl convenience functions. 34027c478bd9Sstevel@tonic-gate */ 34037c478bd9Sstevel@tonic-gate 34047c478bd9Sstevel@tonic-gate int 34057c478bd9Sstevel@tonic-gate zonecfg_construct_rctlblk(const struct zone_rctlvaltab *rctlval, 34067c478bd9Sstevel@tonic-gate rctlblk_t *rctlblk) 34077c478bd9Sstevel@tonic-gate { 34087c478bd9Sstevel@tonic-gate unsigned long long ull; 34097c478bd9Sstevel@tonic-gate char *endp; 34107c478bd9Sstevel@tonic-gate rctl_priv_t priv; 34117c478bd9Sstevel@tonic-gate rctl_qty_t limit; 34127c478bd9Sstevel@tonic-gate uint_t action; 34137c478bd9Sstevel@tonic-gate 34147c478bd9Sstevel@tonic-gate /* Get the privilege */ 34157c478bd9Sstevel@tonic-gate if (strcmp(rctlval->zone_rctlval_priv, "basic") == 0) { 34167c478bd9Sstevel@tonic-gate priv = RCPRIV_BASIC; 34177c478bd9Sstevel@tonic-gate } else if (strcmp(rctlval->zone_rctlval_priv, "privileged") == 0) { 34187c478bd9Sstevel@tonic-gate priv = RCPRIV_PRIVILEGED; 34197c478bd9Sstevel@tonic-gate } else { 34207c478bd9Sstevel@tonic-gate /* Invalid privilege */ 34217c478bd9Sstevel@tonic-gate return (Z_INVAL); 34227c478bd9Sstevel@tonic-gate } 34237c478bd9Sstevel@tonic-gate 34247c478bd9Sstevel@tonic-gate /* deal with negative input; strtoull(3c) doesn't do what we want */ 34257c478bd9Sstevel@tonic-gate if (rctlval->zone_rctlval_limit[0] == '-') 34267c478bd9Sstevel@tonic-gate return (Z_INVAL); 34277c478bd9Sstevel@tonic-gate /* Get the limit */ 34287c478bd9Sstevel@tonic-gate errno = 0; 34297c478bd9Sstevel@tonic-gate ull = strtoull(rctlval->zone_rctlval_limit, &endp, 0); 34307c478bd9Sstevel@tonic-gate if (errno != 0 || *endp != '\0') { 34317c478bd9Sstevel@tonic-gate /* parse failed */ 34327c478bd9Sstevel@tonic-gate return (Z_INVAL); 34337c478bd9Sstevel@tonic-gate } 34347c478bd9Sstevel@tonic-gate limit = (rctl_qty_t)ull; 34357c478bd9Sstevel@tonic-gate 34367c478bd9Sstevel@tonic-gate /* Get the action */ 34377c478bd9Sstevel@tonic-gate if (strcmp(rctlval->zone_rctlval_action, "none") == 0) { 34387c478bd9Sstevel@tonic-gate action = RCTL_LOCAL_NOACTION; 34397c478bd9Sstevel@tonic-gate } else if (strcmp(rctlval->zone_rctlval_action, "signal") == 0) { 34407c478bd9Sstevel@tonic-gate action = RCTL_LOCAL_SIGNAL; 34417c478bd9Sstevel@tonic-gate } else if (strcmp(rctlval->zone_rctlval_action, "deny") == 0) { 34427c478bd9Sstevel@tonic-gate action = RCTL_LOCAL_DENY; 34437c478bd9Sstevel@tonic-gate } else { 34447c478bd9Sstevel@tonic-gate /* Invalid Action */ 34457c478bd9Sstevel@tonic-gate return (Z_INVAL); 34467c478bd9Sstevel@tonic-gate } 34477c478bd9Sstevel@tonic-gate rctlblk_set_local_action(rctlblk, action, 0); 34487c478bd9Sstevel@tonic-gate rctlblk_set_privilege(rctlblk, priv); 34497c478bd9Sstevel@tonic-gate rctlblk_set_value(rctlblk, limit); 34507c478bd9Sstevel@tonic-gate return (Z_OK); 34517c478bd9Sstevel@tonic-gate } 34527c478bd9Sstevel@tonic-gate 34537c478bd9Sstevel@tonic-gate static int 34547c478bd9Sstevel@tonic-gate rctl_check(const char *rctlname, void *arg) 34557c478bd9Sstevel@tonic-gate { 34567c478bd9Sstevel@tonic-gate const char *attrname = arg; 34577c478bd9Sstevel@tonic-gate 34587c478bd9Sstevel@tonic-gate /* 34597c478bd9Sstevel@tonic-gate * Returning 1 here is our signal to zonecfg_is_rctl() that it is 34607c478bd9Sstevel@tonic-gate * indeed an rctl name recognized by the system. 34617c478bd9Sstevel@tonic-gate */ 34627c478bd9Sstevel@tonic-gate return (strcmp(rctlname, attrname) == 0 ? 1 : 0); 34637c478bd9Sstevel@tonic-gate } 34647c478bd9Sstevel@tonic-gate 34657c478bd9Sstevel@tonic-gate boolean_t 34667c478bd9Sstevel@tonic-gate zonecfg_is_rctl(const char *name) 34677c478bd9Sstevel@tonic-gate { 34687c478bd9Sstevel@tonic-gate return (rctl_walk(rctl_check, (void *)name) == 1); 34697c478bd9Sstevel@tonic-gate } 34707c478bd9Sstevel@tonic-gate 34717c478bd9Sstevel@tonic-gate boolean_t 34727c478bd9Sstevel@tonic-gate zonecfg_valid_rctlname(const char *name) 34737c478bd9Sstevel@tonic-gate { 34747c478bd9Sstevel@tonic-gate const char *c; 34757c478bd9Sstevel@tonic-gate 34767c478bd9Sstevel@tonic-gate if (strncmp(name, "zone.", sizeof ("zone.") - 1) != 0) 34777c478bd9Sstevel@tonic-gate return (B_FALSE); 34787c478bd9Sstevel@tonic-gate if (strlen(name) == sizeof ("zone.") - 1) 34797c478bd9Sstevel@tonic-gate return (B_FALSE); 34807c478bd9Sstevel@tonic-gate for (c = name + sizeof ("zone.") - 1; *c != '\0'; c++) { 34817c478bd9Sstevel@tonic-gate if (!isalpha(*c) && *c != '-') 34827c478bd9Sstevel@tonic-gate return (B_FALSE); 34837c478bd9Sstevel@tonic-gate } 34847c478bd9Sstevel@tonic-gate return (B_TRUE); 34857c478bd9Sstevel@tonic-gate } 34867c478bd9Sstevel@tonic-gate 34877c478bd9Sstevel@tonic-gate boolean_t 34887c478bd9Sstevel@tonic-gate zonecfg_valid_rctlblk(const rctlblk_t *rctlblk) 34897c478bd9Sstevel@tonic-gate { 34907c478bd9Sstevel@tonic-gate rctl_priv_t priv = rctlblk_get_privilege((rctlblk_t *)rctlblk); 34917c478bd9Sstevel@tonic-gate uint_t action = rctlblk_get_local_action((rctlblk_t *)rctlblk, NULL); 34927c478bd9Sstevel@tonic-gate 34937c478bd9Sstevel@tonic-gate if (priv != RCPRIV_PRIVILEGED) 34947c478bd9Sstevel@tonic-gate return (B_FALSE); 34957c478bd9Sstevel@tonic-gate if (action != RCTL_LOCAL_NOACTION && action != RCTL_LOCAL_DENY) 34967c478bd9Sstevel@tonic-gate return (B_FALSE); 34977c478bd9Sstevel@tonic-gate return (B_TRUE); 34987c478bd9Sstevel@tonic-gate } 34997c478bd9Sstevel@tonic-gate 35007c478bd9Sstevel@tonic-gate boolean_t 35017c478bd9Sstevel@tonic-gate zonecfg_valid_rctl(const char *name, const rctlblk_t *rctlblk) 35027c478bd9Sstevel@tonic-gate { 35037c478bd9Sstevel@tonic-gate rctlblk_t *current, *next; 35047c478bd9Sstevel@tonic-gate rctl_qty_t limit = rctlblk_get_value((rctlblk_t *)rctlblk); 35057c478bd9Sstevel@tonic-gate uint_t action = rctlblk_get_local_action((rctlblk_t *)rctlblk, NULL); 35067c478bd9Sstevel@tonic-gate uint_t global_flags; 35077c478bd9Sstevel@tonic-gate 35087c478bd9Sstevel@tonic-gate if (!zonecfg_valid_rctlblk(rctlblk)) 35097c478bd9Sstevel@tonic-gate return (B_FALSE); 35107c478bd9Sstevel@tonic-gate if (!zonecfg_valid_rctlname(name)) 35117c478bd9Sstevel@tonic-gate return (B_FALSE); 35127c478bd9Sstevel@tonic-gate 35137c478bd9Sstevel@tonic-gate current = alloca(rctlblk_size()); 35147c478bd9Sstevel@tonic-gate if (getrctl(name, NULL, current, RCTL_FIRST) != 0) 35157c478bd9Sstevel@tonic-gate return (B_TRUE); /* not an rctl on this system */ 35167c478bd9Sstevel@tonic-gate /* 35177c478bd9Sstevel@tonic-gate * Make sure the proposed value isn't greater than the current system 35187c478bd9Sstevel@tonic-gate * value. 35197c478bd9Sstevel@tonic-gate */ 35207c478bd9Sstevel@tonic-gate next = alloca(rctlblk_size()); 35217c478bd9Sstevel@tonic-gate while (rctlblk_get_privilege(current) != RCPRIV_SYSTEM) { 35227c478bd9Sstevel@tonic-gate rctlblk_t *tmp; 35237c478bd9Sstevel@tonic-gate 35247c478bd9Sstevel@tonic-gate if (getrctl(name, current, next, RCTL_NEXT) != 0) 35257c478bd9Sstevel@tonic-gate return (B_FALSE); /* shouldn't happen */ 35267c478bd9Sstevel@tonic-gate tmp = current; 35277c478bd9Sstevel@tonic-gate current = next; 35287c478bd9Sstevel@tonic-gate next = tmp; 35297c478bd9Sstevel@tonic-gate } 35307c478bd9Sstevel@tonic-gate if (limit > rctlblk_get_value(current)) 35317c478bd9Sstevel@tonic-gate return (B_FALSE); 35327c478bd9Sstevel@tonic-gate 35337c478bd9Sstevel@tonic-gate /* 35347c478bd9Sstevel@tonic-gate * Make sure the proposed action is allowed. 35357c478bd9Sstevel@tonic-gate */ 35367c478bd9Sstevel@tonic-gate global_flags = rctlblk_get_global_flags(current); 35377c478bd9Sstevel@tonic-gate if ((global_flags & RCTL_GLOBAL_DENY_NEVER) && 35387c478bd9Sstevel@tonic-gate action == RCTL_LOCAL_DENY) 35397c478bd9Sstevel@tonic-gate return (B_FALSE); 35407c478bd9Sstevel@tonic-gate if ((global_flags & RCTL_GLOBAL_DENY_ALWAYS) && 35417c478bd9Sstevel@tonic-gate action == RCTL_LOCAL_NOACTION) 35427c478bd9Sstevel@tonic-gate return (B_FALSE); 35437c478bd9Sstevel@tonic-gate 35447c478bd9Sstevel@tonic-gate return (B_TRUE); 35457c478bd9Sstevel@tonic-gate } 3546fa9e4066Sahrens 3547*cf8f45c7Sdstaff /* 3548*cf8f45c7Sdstaff * There is always a race condition between reading the initial copy of 3549*cf8f45c7Sdstaff * a zones state and its state changing. We address this by providing 3550*cf8f45c7Sdstaff * zonecfg_notify_critical_enter and zonecfg_noticy_critical_exit functions. 3551*cf8f45c7Sdstaff * When zonecfg_critical_enter is called, sets the state field to LOCKED 3552*cf8f45c7Sdstaff * and aquires biglock. Biglock protects against other threads executing 3553*cf8f45c7Sdstaff * critical_enter and the state field protects against state changes during 3554*cf8f45c7Sdstaff * the critical period. 3555*cf8f45c7Sdstaff * 3556*cf8f45c7Sdstaff * If any state changes occur, zn_cb will set the failed field of the znotify 3557*cf8f45c7Sdstaff * structure. This will cause the critical_exit function to re-lock the 3558*cf8f45c7Sdstaff * channel and return an error. Since evsnts may be delayed, the critical_exit 3559*cf8f45c7Sdstaff * function "flushes" the queue by putting an event on the queue and waiting for 3560*cf8f45c7Sdstaff * zn_cb to notify critical_exit that it received the ping event. 3561*cf8f45c7Sdstaff */ 3562*cf8f45c7Sdstaff static const char * 3563*cf8f45c7Sdstaff string_get_tok(const char *in, char delim, int num) 3564*cf8f45c7Sdstaff { 3565*cf8f45c7Sdstaff int i = 0; 3566*cf8f45c7Sdstaff 3567*cf8f45c7Sdstaff for (; i < num; in++) { 3568*cf8f45c7Sdstaff if (*in == delim) 3569*cf8f45c7Sdstaff i++; 3570*cf8f45c7Sdstaff if (*in == 0) 3571*cf8f45c7Sdstaff return (NULL); 3572*cf8f45c7Sdstaff } 3573*cf8f45c7Sdstaff return (in); 3574*cf8f45c7Sdstaff } 3575*cf8f45c7Sdstaff 3576*cf8f45c7Sdstaff static boolean_t 3577*cf8f45c7Sdstaff is_ping(sysevent_t *ev) 3578*cf8f45c7Sdstaff { 3579*cf8f45c7Sdstaff if (strcmp(sysevent_get_subclass_name(ev), 3580*cf8f45c7Sdstaff ZONE_EVENT_PING_SUBCLASS) == 0) { 3581*cf8f45c7Sdstaff return (B_TRUE); 3582*cf8f45c7Sdstaff } else { 3583*cf8f45c7Sdstaff return (B_FALSE); 3584*cf8f45c7Sdstaff } 3585*cf8f45c7Sdstaff } 3586*cf8f45c7Sdstaff 3587*cf8f45c7Sdstaff static boolean_t 3588*cf8f45c7Sdstaff is_my_ping(sysevent_t *ev) 3589*cf8f45c7Sdstaff { 3590*cf8f45c7Sdstaff const char *sender; 3591*cf8f45c7Sdstaff char mypid[sizeof (pid_t) * 3 + 1]; 3592*cf8f45c7Sdstaff 3593*cf8f45c7Sdstaff (void) snprintf(mypid, sizeof (mypid), "%i", getpid()); 3594*cf8f45c7Sdstaff sender = string_get_tok(sysevent_get_pub(ev), ':', 3); 3595*cf8f45c7Sdstaff if (sender == NULL) 3596*cf8f45c7Sdstaff return (B_FALSE); 3597*cf8f45c7Sdstaff if (strcmp(sender, mypid) != 0) 3598*cf8f45c7Sdstaff return (B_FALSE); 3599*cf8f45c7Sdstaff return (B_TRUE); 3600*cf8f45c7Sdstaff } 3601*cf8f45c7Sdstaff 3602*cf8f45c7Sdstaff static int 3603*cf8f45c7Sdstaff do_callback(struct znotify *zevtchan, sysevent_t *ev) 3604*cf8f45c7Sdstaff { 3605*cf8f45c7Sdstaff nvlist_t *l; 3606*cf8f45c7Sdstaff int zid; 3607*cf8f45c7Sdstaff char *zonename; 3608*cf8f45c7Sdstaff char *newstate; 3609*cf8f45c7Sdstaff char *oldstate; 3610*cf8f45c7Sdstaff int ret; 3611*cf8f45c7Sdstaff hrtime_t when; 3612*cf8f45c7Sdstaff 3613*cf8f45c7Sdstaff if (strcmp(sysevent_get_subclass_name(ev), 3614*cf8f45c7Sdstaff ZONE_EVENT_STATUS_SUBCLASS) == 0) { 3615*cf8f45c7Sdstaff 3616*cf8f45c7Sdstaff if (sysevent_get_attr_list(ev, &l) != 0) { 3617*cf8f45c7Sdstaff if (errno == ENOMEM) { 3618*cf8f45c7Sdstaff zevtchan->zn_failure_count++; 3619*cf8f45c7Sdstaff return (EAGAIN); 3620*cf8f45c7Sdstaff } 3621*cf8f45c7Sdstaff return (0); 3622*cf8f45c7Sdstaff } 3623*cf8f45c7Sdstaff ret = 0; 3624*cf8f45c7Sdstaff 3625*cf8f45c7Sdstaff if ((nvlist_lookup_string(l, ZONE_CB_NAME, &zonename) == 0) && 3626*cf8f45c7Sdstaff (nvlist_lookup_string(l, ZONE_CB_NEWSTATE, &newstate) 3627*cf8f45c7Sdstaff == 0) && 3628*cf8f45c7Sdstaff (nvlist_lookup_string(l, ZONE_CB_OLDSTATE, &oldstate) 3629*cf8f45c7Sdstaff == 0) && 3630*cf8f45c7Sdstaff (nvlist_lookup_uint64(l, ZONE_CB_TIMESTAMP, 3631*cf8f45c7Sdstaff (uint64_t *)&when) == 0) && 3632*cf8f45c7Sdstaff (nvlist_lookup_int32(l, ZONE_CB_ZONEID, &zid) == 0)) { 3633*cf8f45c7Sdstaff ret = zevtchan->zn_callback(zonename, zid, newstate, 3634*cf8f45c7Sdstaff oldstate, when, zevtchan->zn_private); 3635*cf8f45c7Sdstaff } 3636*cf8f45c7Sdstaff 3637*cf8f45c7Sdstaff zevtchan->zn_failure_count = 0; 3638*cf8f45c7Sdstaff nvlist_free(l); 3639*cf8f45c7Sdstaff return (ret); 3640*cf8f45c7Sdstaff } else { 3641*cf8f45c7Sdstaff /* 3642*cf8f45c7Sdstaff * We have received an event in an unknown subclass. Ignore. 3643*cf8f45c7Sdstaff */ 3644*cf8f45c7Sdstaff zevtchan->zn_failure_count = 0; 3645*cf8f45c7Sdstaff return (0); 3646*cf8f45c7Sdstaff } 3647*cf8f45c7Sdstaff } 3648*cf8f45c7Sdstaff 3649*cf8f45c7Sdstaff static int 3650*cf8f45c7Sdstaff zn_cb(sysevent_t *ev, void *p) 3651*cf8f45c7Sdstaff { 3652*cf8f45c7Sdstaff struct znotify *zevtchan = p; 3653*cf8f45c7Sdstaff int error; 3654*cf8f45c7Sdstaff 3655*cf8f45c7Sdstaff (void) pthread_mutex_lock(&(zevtchan->zn_mutex)); 3656*cf8f45c7Sdstaff 3657*cf8f45c7Sdstaff if (is_ping(ev) && !is_my_ping(ev)) { 3658*cf8f45c7Sdstaff (void) pthread_mutex_unlock((&zevtchan->zn_mutex)); 3659*cf8f45c7Sdstaff return (0); 3660*cf8f45c7Sdstaff } 3661*cf8f45c7Sdstaff 3662*cf8f45c7Sdstaff if (zevtchan->zn_state == ZN_LOCKED) { 3663*cf8f45c7Sdstaff assert(!is_ping(ev)); 3664*cf8f45c7Sdstaff zevtchan->zn_failed = B_TRUE; 3665*cf8f45c7Sdstaff (void) pthread_mutex_unlock(&(zevtchan->zn_mutex)); 3666*cf8f45c7Sdstaff return (0); 3667*cf8f45c7Sdstaff } 3668*cf8f45c7Sdstaff 3669*cf8f45c7Sdstaff if (zevtchan->zn_state == ZN_PING_INFLIGHT) { 3670*cf8f45c7Sdstaff if (is_ping(ev)) { 3671*cf8f45c7Sdstaff zevtchan->zn_state = ZN_PING_RECEIVED; 3672*cf8f45c7Sdstaff (void) pthread_cond_signal(&(zevtchan->zn_cond)); 3673*cf8f45c7Sdstaff (void) pthread_mutex_unlock(&(zevtchan->zn_mutex)); 3674*cf8f45c7Sdstaff return (0); 3675*cf8f45c7Sdstaff } else { 3676*cf8f45c7Sdstaff zevtchan->zn_failed = B_TRUE; 3677*cf8f45c7Sdstaff (void) pthread_mutex_unlock(&(zevtchan->zn_mutex)); 3678*cf8f45c7Sdstaff return (0); 3679*cf8f45c7Sdstaff } 3680*cf8f45c7Sdstaff } 3681*cf8f45c7Sdstaff 3682*cf8f45c7Sdstaff if (zevtchan->zn_state == ZN_UNLOCKED) { 3683*cf8f45c7Sdstaff 3684*cf8f45c7Sdstaff error = do_callback(zevtchan, ev); 3685*cf8f45c7Sdstaff (void) pthread_mutex_unlock(&(zevtchan->zn_mutex)); 3686*cf8f45c7Sdstaff /* 3687*cf8f45c7Sdstaff * Every ENOMEM failure causes do_callback to increment 3688*cf8f45c7Sdstaff * zn_failure_count and every success causes it to 3689*cf8f45c7Sdstaff * set zn_failure_count to zero. If we got EAGAIN, 3690*cf8f45c7Sdstaff * we will sleep for zn_failure_count seconds and return 3691*cf8f45c7Sdstaff * EAGAIN to gpec to try again. 3692*cf8f45c7Sdstaff * 3693*cf8f45c7Sdstaff * After 55 seconds, or 10 try's we give up and drop the 3694*cf8f45c7Sdstaff * event. 3695*cf8f45c7Sdstaff */ 3696*cf8f45c7Sdstaff if (error == EAGAIN) { 3697*cf8f45c7Sdstaff if (zevtchan->zn_failure_count > ZONE_CB_RETRY_COUNT) { 3698*cf8f45c7Sdstaff return (0); 3699*cf8f45c7Sdstaff } 3700*cf8f45c7Sdstaff (void) sleep(zevtchan->zn_failure_count); 3701*cf8f45c7Sdstaff } 3702*cf8f45c7Sdstaff return (error); 3703*cf8f45c7Sdstaff } 3704*cf8f45c7Sdstaff 3705*cf8f45c7Sdstaff if (zevtchan->zn_state == ZN_PING_RECEIVED) { 3706*cf8f45c7Sdstaff (void) pthread_mutex_unlock(&(zevtchan->zn_mutex)); 3707*cf8f45c7Sdstaff return (0); 3708*cf8f45c7Sdstaff } 3709*cf8f45c7Sdstaff 3710*cf8f45c7Sdstaff abort(); 3711*cf8f45c7Sdstaff return (0); 3712*cf8f45c7Sdstaff } 3713*cf8f45c7Sdstaff 3714*cf8f45c7Sdstaff void 3715*cf8f45c7Sdstaff zonecfg_notify_critical_enter(void *h) 3716*cf8f45c7Sdstaff { 3717*cf8f45c7Sdstaff struct znotify *zevtchan = h; 3718*cf8f45c7Sdstaff 3719*cf8f45c7Sdstaff (void) pthread_mutex_lock(&(zevtchan->zn_bigmutex)); 3720*cf8f45c7Sdstaff zevtchan->zn_state = ZN_LOCKED; 3721*cf8f45c7Sdstaff } 3722*cf8f45c7Sdstaff 3723*cf8f45c7Sdstaff int 3724*cf8f45c7Sdstaff zonecfg_notify_critical_exit(void * h) 3725*cf8f45c7Sdstaff { 3726*cf8f45c7Sdstaff 3727*cf8f45c7Sdstaff struct znotify *zevtchan = h; 3728*cf8f45c7Sdstaff 3729*cf8f45c7Sdstaff if (zevtchan->zn_state == ZN_UNLOCKED) 3730*cf8f45c7Sdstaff return (0); 3731*cf8f45c7Sdstaff 3732*cf8f45c7Sdstaff (void) pthread_mutex_lock(&(zevtchan->zn_mutex)); 3733*cf8f45c7Sdstaff zevtchan->zn_state = ZN_PING_INFLIGHT; 3734*cf8f45c7Sdstaff 3735*cf8f45c7Sdstaff sysevent_evc_publish(zevtchan->zn_eventchan, ZONE_EVENT_STATUS_CLASS, 3736*cf8f45c7Sdstaff ZONE_EVENT_PING_SUBCLASS, ZONE_EVENT_PING_PUBLISHER, 3737*cf8f45c7Sdstaff zevtchan->zn_subscriber_id, NULL, EVCH_SLEEP); 3738*cf8f45c7Sdstaff 3739*cf8f45c7Sdstaff while (zevtchan->zn_state != ZN_PING_RECEIVED) { 3740*cf8f45c7Sdstaff (void) pthread_cond_wait(&(zevtchan->zn_cond), 3741*cf8f45c7Sdstaff &(zevtchan->zn_mutex)); 3742*cf8f45c7Sdstaff } 3743*cf8f45c7Sdstaff 3744*cf8f45c7Sdstaff if (zevtchan->zn_failed == B_TRUE) { 3745*cf8f45c7Sdstaff zevtchan->zn_state = ZN_LOCKED; 3746*cf8f45c7Sdstaff zevtchan->zn_failed = B_FALSE; 3747*cf8f45c7Sdstaff (void) pthread_mutex_unlock(&(zevtchan->zn_mutex)); 3748*cf8f45c7Sdstaff return (1); 3749*cf8f45c7Sdstaff } 3750*cf8f45c7Sdstaff 3751*cf8f45c7Sdstaff zevtchan->zn_state = ZN_UNLOCKED; 3752*cf8f45c7Sdstaff (void) pthread_mutex_unlock(&(zevtchan->zn_mutex)); 3753*cf8f45c7Sdstaff (void) pthread_mutex_unlock(&(zevtchan->zn_bigmutex)); 3754*cf8f45c7Sdstaff return (0); 3755*cf8f45c7Sdstaff } 3756*cf8f45c7Sdstaff 3757*cf8f45c7Sdstaff void 3758*cf8f45c7Sdstaff zonecfg_notify_critical_abort(void *h) 3759*cf8f45c7Sdstaff { 3760*cf8f45c7Sdstaff struct znotify *zevtchan = h; 3761*cf8f45c7Sdstaff 3762*cf8f45c7Sdstaff zevtchan->zn_state = ZN_UNLOCKED; 3763*cf8f45c7Sdstaff zevtchan->zn_failed = B_FALSE; 3764*cf8f45c7Sdstaff /* 3765*cf8f45c7Sdstaff * Don't do anything about zn_lock. If it is held, it could only be 3766*cf8f45c7Sdstaff * held by zn_cb and it will be unlocked soon. 3767*cf8f45c7Sdstaff */ 3768*cf8f45c7Sdstaff (void) pthread_mutex_unlock(&(zevtchan->zn_bigmutex)); 3769*cf8f45c7Sdstaff } 3770*cf8f45c7Sdstaff 3771*cf8f45c7Sdstaff void * 3772*cf8f45c7Sdstaff zonecfg_notify_bind(int(*func)(const char *zonename, zoneid_t zid, 3773*cf8f45c7Sdstaff const char *newstate, const char *oldstate, hrtime_t when, void *p), 3774*cf8f45c7Sdstaff void *p) 3775*cf8f45c7Sdstaff { 3776*cf8f45c7Sdstaff struct znotify *zevtchan; 3777*cf8f45c7Sdstaff int i = 1; 3778*cf8f45c7Sdstaff int r; 3779*cf8f45c7Sdstaff 3780*cf8f45c7Sdstaff zevtchan = malloc(sizeof (struct znotify)); 3781*cf8f45c7Sdstaff 3782*cf8f45c7Sdstaff if (zevtchan == NULL) 3783*cf8f45c7Sdstaff return (NULL); 3784*cf8f45c7Sdstaff 3785*cf8f45c7Sdstaff zevtchan->zn_private = p; 3786*cf8f45c7Sdstaff zevtchan->zn_callback = func; 3787*cf8f45c7Sdstaff zevtchan->zn_state = ZN_UNLOCKED; 3788*cf8f45c7Sdstaff zevtchan->zn_failed = B_FALSE; 3789*cf8f45c7Sdstaff 3790*cf8f45c7Sdstaff if (pthread_mutex_init(&(zevtchan->zn_mutex), NULL)) 3791*cf8f45c7Sdstaff goto out2; 3792*cf8f45c7Sdstaff if (pthread_cond_init(&(zevtchan->zn_cond), NULL)) { 3793*cf8f45c7Sdstaff (void) pthread_mutex_destroy(&(zevtchan->zn_mutex)); 3794*cf8f45c7Sdstaff goto out2; 3795*cf8f45c7Sdstaff } 3796*cf8f45c7Sdstaff if (pthread_mutex_init(&(zevtchan->zn_bigmutex), NULL)) { 3797*cf8f45c7Sdstaff (void) pthread_mutex_destroy(&(zevtchan->zn_mutex)); 3798*cf8f45c7Sdstaff (void) pthread_cond_destroy(&(zevtchan->zn_cond)); 3799*cf8f45c7Sdstaff goto out2; 3800*cf8f45c7Sdstaff } 3801*cf8f45c7Sdstaff 3802*cf8f45c7Sdstaff if (sysevent_evc_bind(ZONE_EVENT_CHANNEL, &(zevtchan->zn_eventchan), 3803*cf8f45c7Sdstaff 0) != 0) 3804*cf8f45c7Sdstaff goto out2; 3805*cf8f45c7Sdstaff 3806*cf8f45c7Sdstaff do { 3807*cf8f45c7Sdstaff /* 3808*cf8f45c7Sdstaff * At 4 digits the subscriber ID gets too long and we have 3809*cf8f45c7Sdstaff * no chance of successfully registering. 3810*cf8f45c7Sdstaff */ 3811*cf8f45c7Sdstaff if (i > 999) 3812*cf8f45c7Sdstaff goto out; 3813*cf8f45c7Sdstaff 3814*cf8f45c7Sdstaff (void) sprintf(zevtchan->zn_subscriber_id, "zone_%li_%i", 3815*cf8f45c7Sdstaff getpid() % 999999l, i); 3816*cf8f45c7Sdstaff 3817*cf8f45c7Sdstaff r = sysevent_evc_subscribe(zevtchan->zn_eventchan, 3818*cf8f45c7Sdstaff zevtchan->zn_subscriber_id, ZONE_EVENT_STATUS_CLASS, zn_cb, 3819*cf8f45c7Sdstaff zevtchan, 0); 3820*cf8f45c7Sdstaff 3821*cf8f45c7Sdstaff i++; 3822*cf8f45c7Sdstaff 3823*cf8f45c7Sdstaff } while (r); 3824*cf8f45c7Sdstaff 3825*cf8f45c7Sdstaff return (zevtchan); 3826*cf8f45c7Sdstaff out: 3827*cf8f45c7Sdstaff sysevent_evc_unbind(zevtchan->zn_eventchan); 3828*cf8f45c7Sdstaff (void) pthread_mutex_destroy(&zevtchan->zn_mutex); 3829*cf8f45c7Sdstaff (void) pthread_cond_destroy(&zevtchan->zn_cond); 3830*cf8f45c7Sdstaff (void) pthread_mutex_destroy(&(zevtchan->zn_bigmutex)); 3831*cf8f45c7Sdstaff out2: 3832*cf8f45c7Sdstaff free(zevtchan); 3833*cf8f45c7Sdstaff 3834*cf8f45c7Sdstaff return (NULL); 3835*cf8f45c7Sdstaff } 3836*cf8f45c7Sdstaff 3837*cf8f45c7Sdstaff void 3838*cf8f45c7Sdstaff zonecfg_notify_unbind(void *handle) 3839*cf8f45c7Sdstaff { 3840*cf8f45c7Sdstaff 3841*cf8f45c7Sdstaff int ret; 3842*cf8f45c7Sdstaff 3843*cf8f45c7Sdstaff sysevent_evc_unbind(((struct znotify *)handle)->zn_eventchan); 3844*cf8f45c7Sdstaff /* 3845*cf8f45c7Sdstaff * Check that all evc threads have gone away. This should be 3846*cf8f45c7Sdstaff * enforced by sysevent_evc_unbind. 3847*cf8f45c7Sdstaff */ 3848*cf8f45c7Sdstaff ret = pthread_mutex_trylock(&((struct znotify *)handle)->zn_mutex); 3849*cf8f45c7Sdstaff 3850*cf8f45c7Sdstaff if (ret) 3851*cf8f45c7Sdstaff abort(); 3852*cf8f45c7Sdstaff 3853*cf8f45c7Sdstaff (void) pthread_mutex_unlock(&((struct znotify *)handle)->zn_mutex); 3854*cf8f45c7Sdstaff (void) pthread_mutex_destroy(&((struct znotify *)handle)->zn_mutex); 3855*cf8f45c7Sdstaff (void) pthread_cond_destroy(&((struct znotify *)handle)->zn_cond); 3856*cf8f45c7Sdstaff (void) pthread_mutex_destroy(&((struct znotify *)handle)->zn_bigmutex); 3857*cf8f45c7Sdstaff 3858*cf8f45c7Sdstaff free(handle); 3859*cf8f45c7Sdstaff } 3860*cf8f45c7Sdstaff 3861fa9e4066Sahrens static int 3862fa9e4066Sahrens zonecfg_add_ds_core(zone_dochandle_t handle, struct zone_dstab *tabptr) 3863fa9e4066Sahrens { 3864fa9e4066Sahrens xmlNodePtr newnode, cur = handle->zone_dh_cur; 3865fa9e4066Sahrens int err; 3866fa9e4066Sahrens 3867fa9e4066Sahrens newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_DATASET, NULL); 3868fa9e4066Sahrens if ((err = newprop(newnode, DTD_ATTR_NAME, 3869fa9e4066Sahrens tabptr->zone_dataset_name)) != Z_OK) 3870fa9e4066Sahrens return (err); 3871fa9e4066Sahrens return (Z_OK); 3872fa9e4066Sahrens } 3873fa9e4066Sahrens 3874fa9e4066Sahrens int 3875fa9e4066Sahrens zonecfg_add_ds(zone_dochandle_t handle, struct zone_dstab *tabptr) 3876fa9e4066Sahrens { 3877fa9e4066Sahrens int err; 3878fa9e4066Sahrens 3879fa9e4066Sahrens if (tabptr == NULL) 3880fa9e4066Sahrens return (Z_INVAL); 3881fa9e4066Sahrens 3882fa9e4066Sahrens if ((err = operation_prep(handle)) != Z_OK) 3883fa9e4066Sahrens return (err); 3884fa9e4066Sahrens 3885fa9e4066Sahrens if ((err = zonecfg_add_ds_core(handle, tabptr)) != Z_OK) 3886fa9e4066Sahrens return (err); 3887fa9e4066Sahrens 3888fa9e4066Sahrens return (Z_OK); 3889fa9e4066Sahrens } 3890fa9e4066Sahrens 3891fa9e4066Sahrens static int 3892fa9e4066Sahrens zonecfg_delete_ds_core(zone_dochandle_t handle, struct zone_dstab *tabptr) 3893fa9e4066Sahrens { 3894fa9e4066Sahrens xmlNodePtr cur = handle->zone_dh_cur; 3895fa9e4066Sahrens 3896fa9e4066Sahrens for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 3897fa9e4066Sahrens if (xmlStrcmp(cur->name, DTD_ELEM_DATASET)) 3898fa9e4066Sahrens continue; 3899fa9e4066Sahrens 3900fa9e4066Sahrens if (match_prop(cur, DTD_ATTR_NAME, 3901fa9e4066Sahrens tabptr->zone_dataset_name)) { 3902fa9e4066Sahrens xmlUnlinkNode(cur); 3903fa9e4066Sahrens xmlFreeNode(cur); 3904fa9e4066Sahrens return (Z_OK); 3905fa9e4066Sahrens } 3906fa9e4066Sahrens } 3907fa9e4066Sahrens return (Z_NO_RESOURCE_ID); 3908fa9e4066Sahrens } 3909fa9e4066Sahrens 3910fa9e4066Sahrens int 3911fa9e4066Sahrens zonecfg_delete_ds(zone_dochandle_t handle, struct zone_dstab *tabptr) 3912fa9e4066Sahrens { 3913fa9e4066Sahrens int err; 3914fa9e4066Sahrens 3915fa9e4066Sahrens if (tabptr == NULL) 3916fa9e4066Sahrens return (Z_INVAL); 3917fa9e4066Sahrens 3918fa9e4066Sahrens if ((err = operation_prep(handle)) != Z_OK) 3919fa9e4066Sahrens return (err); 3920fa9e4066Sahrens 3921fa9e4066Sahrens if ((err = zonecfg_delete_ds_core(handle, tabptr)) != Z_OK) 3922fa9e4066Sahrens return (err); 3923fa9e4066Sahrens 3924fa9e4066Sahrens return (Z_OK); 3925fa9e4066Sahrens } 3926fa9e4066Sahrens 3927fa9e4066Sahrens int 3928fa9e4066Sahrens zonecfg_modify_ds( 3929fa9e4066Sahrens zone_dochandle_t handle, 3930fa9e4066Sahrens struct zone_dstab *oldtabptr, 3931fa9e4066Sahrens struct zone_dstab *newtabptr) 3932fa9e4066Sahrens { 3933fa9e4066Sahrens int err; 3934fa9e4066Sahrens 3935fa9e4066Sahrens if (oldtabptr == NULL || newtabptr == NULL) 3936fa9e4066Sahrens return (Z_INVAL); 3937fa9e4066Sahrens 3938fa9e4066Sahrens if ((err = operation_prep(handle)) != Z_OK) 3939fa9e4066Sahrens return (err); 3940fa9e4066Sahrens 3941fa9e4066Sahrens if ((err = zonecfg_delete_ds_core(handle, oldtabptr)) != Z_OK) 3942fa9e4066Sahrens return (err); 3943fa9e4066Sahrens 3944fa9e4066Sahrens if ((err = zonecfg_add_ds_core(handle, newtabptr)) != Z_OK) 3945fa9e4066Sahrens return (err); 3946fa9e4066Sahrens 3947fa9e4066Sahrens return (Z_OK); 3948fa9e4066Sahrens } 3949fa9e4066Sahrens 3950fa9e4066Sahrens int 3951fa9e4066Sahrens zonecfg_lookup_ds(zone_dochandle_t handle, struct zone_dstab *tabptr) 3952fa9e4066Sahrens { 3953fa9e4066Sahrens xmlNodePtr cur, firstmatch; 3954fa9e4066Sahrens int err; 3955fa9e4066Sahrens char dataset[MAXNAMELEN]; 3956fa9e4066Sahrens 3957fa9e4066Sahrens if (tabptr == NULL) 3958fa9e4066Sahrens return (Z_INVAL); 3959fa9e4066Sahrens 3960fa9e4066Sahrens if ((err = operation_prep(handle)) != Z_OK) 3961fa9e4066Sahrens return (err); 3962fa9e4066Sahrens 3963fa9e4066Sahrens cur = handle->zone_dh_cur; 3964fa9e4066Sahrens firstmatch = NULL; 3965fa9e4066Sahrens for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 3966fa9e4066Sahrens if (xmlStrcmp(cur->name, DTD_ELEM_DATASET)) 3967fa9e4066Sahrens continue; 3968fa9e4066Sahrens if (strlen(tabptr->zone_dataset_name) > 0) { 3969fa9e4066Sahrens if ((fetchprop(cur, DTD_ATTR_NAME, dataset, 3970fa9e4066Sahrens sizeof (dataset)) == Z_OK) && 3971fa9e4066Sahrens (strcmp(tabptr->zone_dataset_name, 3972fa9e4066Sahrens dataset) == 0)) { 3973fa9e4066Sahrens if (firstmatch == NULL) 3974fa9e4066Sahrens firstmatch = cur; 3975fa9e4066Sahrens else 3976fa9e4066Sahrens return (Z_INSUFFICIENT_SPEC); 3977fa9e4066Sahrens } 3978fa9e4066Sahrens } 3979fa9e4066Sahrens } 3980fa9e4066Sahrens if (firstmatch == NULL) 3981fa9e4066Sahrens return (Z_NO_RESOURCE_ID); 3982fa9e4066Sahrens 3983fa9e4066Sahrens cur = firstmatch; 3984fa9e4066Sahrens 3985fa9e4066Sahrens if ((err = fetchprop(cur, DTD_ATTR_NAME, tabptr->zone_dataset_name, 3986fa9e4066Sahrens sizeof (tabptr->zone_dataset_name))) != Z_OK) 3987fa9e4066Sahrens return (err); 3988fa9e4066Sahrens 3989fa9e4066Sahrens return (Z_OK); 3990fa9e4066Sahrens } 3991fa9e4066Sahrens 3992fa9e4066Sahrens int 3993fa9e4066Sahrens zonecfg_setdsent(zone_dochandle_t handle) 3994fa9e4066Sahrens { 3995fa9e4066Sahrens return (zonecfg_setent(handle)); 3996fa9e4066Sahrens } 3997fa9e4066Sahrens 3998fa9e4066Sahrens int 3999fa9e4066Sahrens zonecfg_getdsent(zone_dochandle_t handle, struct zone_dstab *tabptr) 4000fa9e4066Sahrens { 4001fa9e4066Sahrens xmlNodePtr cur; 4002fa9e4066Sahrens int err; 4003fa9e4066Sahrens 4004fa9e4066Sahrens if (handle == NULL) 4005fa9e4066Sahrens return (Z_INVAL); 4006fa9e4066Sahrens 4007fa9e4066Sahrens if ((cur = handle->zone_dh_cur) == NULL) 4008fa9e4066Sahrens return (Z_NO_ENTRY); 4009fa9e4066Sahrens 4010fa9e4066Sahrens for (; cur != NULL; cur = cur->next) 4011fa9e4066Sahrens if (!xmlStrcmp(cur->name, DTD_ELEM_DATASET)) 4012fa9e4066Sahrens break; 4013fa9e4066Sahrens if (cur == NULL) { 4014fa9e4066Sahrens handle->zone_dh_cur = handle->zone_dh_top; 4015fa9e4066Sahrens return (Z_NO_ENTRY); 4016fa9e4066Sahrens } 4017fa9e4066Sahrens 4018fa9e4066Sahrens if ((err = fetchprop(cur, DTD_ATTR_NAME, tabptr->zone_dataset_name, 4019fa9e4066Sahrens sizeof (tabptr->zone_dataset_name))) != Z_OK) { 4020fa9e4066Sahrens handle->zone_dh_cur = handle->zone_dh_top; 4021fa9e4066Sahrens return (err); 4022fa9e4066Sahrens } 4023fa9e4066Sahrens 4024fa9e4066Sahrens handle->zone_dh_cur = cur->next; 4025fa9e4066Sahrens return (Z_OK); 4026fa9e4066Sahrens } 4027fa9e4066Sahrens 4028fa9e4066Sahrens int 4029fa9e4066Sahrens zonecfg_enddsent(zone_dochandle_t handle) 4030fa9e4066Sahrens { 4031fa9e4066Sahrens return (zonecfg_endent(handle)); 4032fa9e4066Sahrens } 4033