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 297c478bd9Sstevel@tonic-gate #include <errno.h> 307c478bd9Sstevel@tonic-gate #include <fnmatch.h> 317c478bd9Sstevel@tonic-gate #include <strings.h> 327c478bd9Sstevel@tonic-gate #include <unistd.h> 337c478bd9Sstevel@tonic-gate #include <sys/stat.h> 347c478bd9Sstevel@tonic-gate #include <assert.h> 357c478bd9Sstevel@tonic-gate #include <libgen.h> 367c478bd9Sstevel@tonic-gate #include <libintl.h> 377c478bd9Sstevel@tonic-gate #include <alloca.h> 387c478bd9Sstevel@tonic-gate #include <ctype.h> 397c478bd9Sstevel@tonic-gate #include <sys/mntio.h> 407c478bd9Sstevel@tonic-gate #include <sys/mnttab.h> 41*087719fdSdp #include <sys/types.h> 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 447c478bd9Sstevel@tonic-gate #include <netdb.h> 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate #include <priv.h> 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate #include <libxml/xmlmemory.h> 497c478bd9Sstevel@tonic-gate #include <libxml/parser.h> 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate #include <libdevinfo.h> 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate #include <libzonecfg.h> 547c478bd9Sstevel@tonic-gate #include "zonecfg_impl.h" 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate #define _PATH_TMPFILE "/zonecfg.XXXXXX" 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate /* Hard-code the DTD element/attribute/entity names just once, here. */ 597c478bd9Sstevel@tonic-gate #define DTD_ELEM_ATTR (const xmlChar *) "attr" 607c478bd9Sstevel@tonic-gate #define DTD_ELEM_COMMENT (const xmlChar *) "comment" 617c478bd9Sstevel@tonic-gate #define DTD_ELEM_DEVICE (const xmlChar *) "device" 627c478bd9Sstevel@tonic-gate #define DTD_ELEM_FS (const xmlChar *) "filesystem" 637c478bd9Sstevel@tonic-gate #define DTD_ELEM_FSOPTION (const xmlChar *) "fsoption" 647c478bd9Sstevel@tonic-gate #define DTD_ELEM_IPD (const xmlChar *) "inherited-pkg-dir" 657c478bd9Sstevel@tonic-gate #define DTD_ELEM_NET (const xmlChar *) "network" 667c478bd9Sstevel@tonic-gate #define DTD_ELEM_RCTL (const xmlChar *) "rctl" 677c478bd9Sstevel@tonic-gate #define DTD_ELEM_RCTLVALUE (const xmlChar *) "rctl-value" 687c478bd9Sstevel@tonic-gate #define DTD_ELEM_ZONE (const xmlChar *) "zone" 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate #define DTD_ATTR_ACTION (const xmlChar *) "action" 717c478bd9Sstevel@tonic-gate #define DTD_ATTR_ADDRESS (const xmlChar *) "address" 727c478bd9Sstevel@tonic-gate #define DTD_ATTR_AUTOBOOT (const xmlChar *) "autoboot" 737c478bd9Sstevel@tonic-gate #define DTD_ATTR_DIR (const xmlChar *) "directory" 747c478bd9Sstevel@tonic-gate #define DTD_ATTR_LIMIT (const xmlChar *) "limit" 757c478bd9Sstevel@tonic-gate #define DTD_ATTR_MATCH (const xmlChar *) "match" 767c478bd9Sstevel@tonic-gate #define DTD_ATTR_NAME (const xmlChar *) "name" 777c478bd9Sstevel@tonic-gate #define DTD_ATTR_PHYSICAL (const xmlChar *) "physical" 787c478bd9Sstevel@tonic-gate #define DTD_ATTR_POOL (const xmlChar *) "pool" 797c478bd9Sstevel@tonic-gate #define DTD_ATTR_PRIV (const xmlChar *) "priv" 807c478bd9Sstevel@tonic-gate #define DTD_ATTR_RAW (const xmlChar *) "raw" 817c478bd9Sstevel@tonic-gate #define DTD_ATTR_SPECIAL (const xmlChar *) "special" 827c478bd9Sstevel@tonic-gate #define DTD_ATTR_TYPE (const xmlChar *) "type" 837c478bd9Sstevel@tonic-gate #define DTD_ATTR_VALUE (const xmlChar *) "value" 847c478bd9Sstevel@tonic-gate #define DTD_ATTR_ZONEPATH (const xmlChar *) "zonepath" 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate #define DTD_ENTITY_BOOLEAN "boolean" 877c478bd9Sstevel@tonic-gate #define DTD_ENTITY_DEVPATH "devpath" 887c478bd9Sstevel@tonic-gate #define DTD_ENTITY_DRIVER "driver" 897c478bd9Sstevel@tonic-gate #define DTD_ENTITY_DRVMIN "drv_min" 907c478bd9Sstevel@tonic-gate #define DTD_ENTITY_FALSE "false" 917c478bd9Sstevel@tonic-gate #define DTD_ENTITY_INT "int" 927c478bd9Sstevel@tonic-gate #define DTD_ENTITY_STRING "string" 937c478bd9Sstevel@tonic-gate #define DTD_ENTITY_TRUE "true" 947c478bd9Sstevel@tonic-gate #define DTD_ENTITY_UINT "uint" 957c478bd9Sstevel@tonic-gate 96a1be23daSdp #define DTD_ENTITY_BOOL_LEN 6 /* "false" */ 97a1be23daSdp 987c478bd9Sstevel@tonic-gate struct zone_dochandle { 997c478bd9Sstevel@tonic-gate char *zone_dh_rootdir; 1007c478bd9Sstevel@tonic-gate xmlDocPtr zone_dh_doc; 1017c478bd9Sstevel@tonic-gate xmlNodePtr zone_dh_cur; 1027c478bd9Sstevel@tonic-gate xmlNodePtr zone_dh_top; 103*087719fdSdp boolean_t zone_dh_newzone; 104*087719fdSdp boolean_t zone_dh_snapshot; 105*087719fdSdp char zone_dh_delete_name[ZONENAME_MAX]; 1067c478bd9Sstevel@tonic-gate }; 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate /* 1097c478bd9Sstevel@tonic-gate * For functions which return int, which is most of the functions herein, 1107c478bd9Sstevel@tonic-gate * the return values should be from the Z_foo set defined in <libzonecfg.h>. 1117c478bd9Sstevel@tonic-gate * In some instances, we take pains mapping some libc errno values to Z_foo 1127c478bd9Sstevel@tonic-gate * values from this set. 1137c478bd9Sstevel@tonic-gate */ 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate /* 1167c478bd9Sstevel@tonic-gate * Callers of the _file_path() functions are expected to have the second 1177c478bd9Sstevel@tonic-gate * parameter be a (char foo[MAXPATHLEN]). 1187c478bd9Sstevel@tonic-gate */ 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate static void 1217c478bd9Sstevel@tonic-gate config_file_path(const char *zonename, char *answer) 1227c478bd9Sstevel@tonic-gate { 1237c478bd9Sstevel@tonic-gate (void) snprintf(answer, MAXPATHLEN, 1247c478bd9Sstevel@tonic-gate "%s/%s.xml", ZONE_CONFIG_ROOT, zonename); 1257c478bd9Sstevel@tonic-gate } 1267c478bd9Sstevel@tonic-gate 1277c478bd9Sstevel@tonic-gate static void 1287c478bd9Sstevel@tonic-gate snap_file_path(char *zonename, char *answer) 1297c478bd9Sstevel@tonic-gate { 1307c478bd9Sstevel@tonic-gate (void) snprintf(answer, MAXPATHLEN, 1317c478bd9Sstevel@tonic-gate "%s/%s.snapshot.xml", ZONE_SNAPSHOT_ROOT, zonename); 1327c478bd9Sstevel@tonic-gate } 1337c478bd9Sstevel@tonic-gate 1347c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1357c478bd9Sstevel@tonic-gate static void 1367c478bd9Sstevel@tonic-gate zonecfg_error_func(void *ctx, const char *msg, ...) 1377c478bd9Sstevel@tonic-gate { 1387c478bd9Sstevel@tonic-gate /* 1397c478bd9Sstevel@tonic-gate * This function does nothing by design. Its purpose is to prevent 1407c478bd9Sstevel@tonic-gate * libxml from dumping unwanted messages to stdout/stderr. 1417c478bd9Sstevel@tonic-gate */ 1427c478bd9Sstevel@tonic-gate } 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate zone_dochandle_t 1457c478bd9Sstevel@tonic-gate zonecfg_init_handle(void) 1467c478bd9Sstevel@tonic-gate { 147*087719fdSdp zone_dochandle_t handle = calloc(1, sizeof (struct zone_dochandle)); 1487c478bd9Sstevel@tonic-gate if (handle == NULL) { 1497c478bd9Sstevel@tonic-gate errno = Z_NOMEM; 1507c478bd9Sstevel@tonic-gate return (NULL); 1517c478bd9Sstevel@tonic-gate } 1527c478bd9Sstevel@tonic-gate 1537c478bd9Sstevel@tonic-gate /* generic libxml initialization */ 1547c478bd9Sstevel@tonic-gate xmlLineNumbersDefault(1); 1557c478bd9Sstevel@tonic-gate xmlLoadExtDtdDefaultValue |= XML_DETECT_IDS; 1567c478bd9Sstevel@tonic-gate xmlDoValidityCheckingDefaultValue = 1; 1577c478bd9Sstevel@tonic-gate (void) xmlKeepBlanksDefault(0); 1587c478bd9Sstevel@tonic-gate xmlGetWarningsDefaultValue = 0; 1597c478bd9Sstevel@tonic-gate xmlSetGenericErrorFunc(NULL, zonecfg_error_func); 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate return (handle); 1627c478bd9Sstevel@tonic-gate } 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate int 1657c478bd9Sstevel@tonic-gate zonecfg_check_handle(zone_dochandle_t handle) 1667c478bd9Sstevel@tonic-gate { 1677c478bd9Sstevel@tonic-gate if (handle == NULL || handle->zone_dh_doc == NULL) 1687c478bd9Sstevel@tonic-gate return (Z_BAD_HANDLE); 1697c478bd9Sstevel@tonic-gate return (Z_OK); 1707c478bd9Sstevel@tonic-gate } 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate void 1737c478bd9Sstevel@tonic-gate zonecfg_fini_handle(zone_dochandle_t handle) 1747c478bd9Sstevel@tonic-gate { 1757c478bd9Sstevel@tonic-gate if (zonecfg_check_handle(handle) == Z_OK) 1767c478bd9Sstevel@tonic-gate xmlFreeDoc(handle->zone_dh_doc); 1777c478bd9Sstevel@tonic-gate if (handle != NULL) 1787c478bd9Sstevel@tonic-gate free(handle); 1797c478bd9Sstevel@tonic-gate } 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate static int 1827c478bd9Sstevel@tonic-gate zonecfg_destroy_impl(char *filename) 1837c478bd9Sstevel@tonic-gate { 1847c478bd9Sstevel@tonic-gate if (unlink(filename) == -1) { 1857c478bd9Sstevel@tonic-gate if (errno == EACCES) 1867c478bd9Sstevel@tonic-gate return (Z_ACCES); 1877c478bd9Sstevel@tonic-gate if (errno == ENOENT) 1887c478bd9Sstevel@tonic-gate return (Z_NO_ZONE); 1897c478bd9Sstevel@tonic-gate return (Z_MISC_FS); 1907c478bd9Sstevel@tonic-gate } 1917c478bd9Sstevel@tonic-gate return (Z_OK); 1927c478bd9Sstevel@tonic-gate } 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate int 195*087719fdSdp zonecfg_destroy(const char *zonename, boolean_t force) 1967c478bd9Sstevel@tonic-gate { 1977c478bd9Sstevel@tonic-gate char path[MAXPATHLEN]; 198*087719fdSdp struct zoneent ze; 199*087719fdSdp int err, state_err; 200*087719fdSdp zone_state_t state; 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate config_file_path(zonename, path); 203*087719fdSdp 204*087719fdSdp state_err = zone_get_state((char *)zonename, &state); 205*087719fdSdp err = access(path, W_OK); 206*087719fdSdp 207*087719fdSdp /* 208*087719fdSdp * If there is no file, and no index entry, reliably indicate that no 209*087719fdSdp * such zone exists. 210*087719fdSdp */ 211*087719fdSdp if ((state_err == Z_NO_ZONE) && (err == -1) && (errno == ENOENT)) 212*087719fdSdp return (Z_NO_ZONE); 213*087719fdSdp 214*087719fdSdp /* 215*087719fdSdp * Handle any other filesystem related errors (except if the XML 216*087719fdSdp * file is missing, which we treat silently), unless we're forcing, 217*087719fdSdp * in which case we plow on. 218*087719fdSdp */ 219*087719fdSdp if (err == -1 && errno != ENOENT) { 220*087719fdSdp if (errno == EACCES) 221*087719fdSdp return (Z_ACCES); 222*087719fdSdp else if (!force) 223*087719fdSdp return (Z_MISC_FS); 224*087719fdSdp } 225*087719fdSdp 226*087719fdSdp if (state > ZONE_STATE_INSTALLED) 227*087719fdSdp return (Z_BAD_ZONE_STATE); 228*087719fdSdp 229*087719fdSdp if (!force && state > ZONE_STATE_CONFIGURED) 230*087719fdSdp return (Z_BAD_ZONE_STATE); 231*087719fdSdp 232*087719fdSdp /* 233*087719fdSdp * Index deletion succeeds even if the entry doesn't exist. So this 234*087719fdSdp * will fail only if we've had some more severe problem. 235*087719fdSdp */ 236*087719fdSdp bzero(&ze, sizeof (ze)); 237*087719fdSdp (void) strlcpy(ze.zone_name, zonename, sizeof (ze.zone_name)); 238*087719fdSdp if ((err = putzoneent(&ze, PZE_REMOVE)) != Z_OK) 239*087719fdSdp if (!force) 240*087719fdSdp return (err); 241*087719fdSdp 242*087719fdSdp err = zonecfg_destroy_impl(path); 243*087719fdSdp 244*087719fdSdp /* 245*087719fdSdp * Treat failure to find the XML file silently, since, well, it's 246*087719fdSdp * gone, and with the index file cleaned up, we're done. 247*087719fdSdp */ 248*087719fdSdp if (err == Z_OK || err == Z_NO_ZONE) 249*087719fdSdp return (Z_OK); 250*087719fdSdp return (err); 2517c478bd9Sstevel@tonic-gate } 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate int 2547c478bd9Sstevel@tonic-gate zonecfg_destroy_snapshot(char *zonename) 2557c478bd9Sstevel@tonic-gate { 2567c478bd9Sstevel@tonic-gate char path[MAXPATHLEN]; 2577c478bd9Sstevel@tonic-gate 2587c478bd9Sstevel@tonic-gate snap_file_path(zonename, path); 2597c478bd9Sstevel@tonic-gate return (zonecfg_destroy_impl(path)); 2607c478bd9Sstevel@tonic-gate } 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate static int 263a1be23daSdp getroot(zone_dochandle_t handle, xmlNodePtr *root) 2647c478bd9Sstevel@tonic-gate { 2657c478bd9Sstevel@tonic-gate if (zonecfg_check_handle(handle) == Z_BAD_HANDLE) 2667c478bd9Sstevel@tonic-gate return (Z_BAD_HANDLE); 2677c478bd9Sstevel@tonic-gate 268a1be23daSdp *root = xmlDocGetRootElement(handle->zone_dh_doc); 269a1be23daSdp 270a1be23daSdp if (*root == NULL) 2717c478bd9Sstevel@tonic-gate return (Z_EMPTY_DOCUMENT); 272a1be23daSdp 273a1be23daSdp if (xmlStrcmp((*root)->name, DTD_ELEM_ZONE)) 274a1be23daSdp return (Z_WRONG_DOC_TYPE); 275a1be23daSdp 276a1be23daSdp return (Z_OK); 2777c478bd9Sstevel@tonic-gate } 2787c478bd9Sstevel@tonic-gate 279a1be23daSdp static int 280a1be23daSdp operation_prep(zone_dochandle_t handle) 281a1be23daSdp { 282a1be23daSdp xmlNodePtr root; 283a1be23daSdp int err; 284a1be23daSdp 285a1be23daSdp if ((err = getroot(handle, &root)) != 0) 286a1be23daSdp return (err); 287a1be23daSdp 288a1be23daSdp handle->zone_dh_cur = root; 289a1be23daSdp handle->zone_dh_top = root; 290a1be23daSdp return (Z_OK); 2917c478bd9Sstevel@tonic-gate } 292a1be23daSdp 293a1be23daSdp static int 294a1be23daSdp getrootattr(zone_dochandle_t handle, const xmlChar *propname, 295a1be23daSdp char *propval, size_t propsize) 296a1be23daSdp { 297a1be23daSdp xmlNodePtr root; 298a1be23daSdp xmlChar *property; 299a1be23daSdp size_t srcsize; 300a1be23daSdp int err; 301a1be23daSdp 302a1be23daSdp if ((err = getroot(handle, &root)) != 0) 303a1be23daSdp return (err); 304a1be23daSdp 305a1be23daSdp if ((property = xmlGetProp(root, propname)) == NULL) 306a1be23daSdp return (Z_BAD_PROPERTY); 307a1be23daSdp srcsize = strlcpy(propval, (char *)property, propsize); 308a1be23daSdp xmlFree(property); 309a1be23daSdp if (srcsize >= propsize) 310a1be23daSdp return (Z_TOO_BIG); 311a1be23daSdp return (Z_OK); 312a1be23daSdp } 313a1be23daSdp 314a1be23daSdp static int 315a1be23daSdp setrootattr(zone_dochandle_t handle, const xmlChar *propname, char *propval) 316a1be23daSdp { 317a1be23daSdp int err; 318a1be23daSdp xmlNodePtr root; 319a1be23daSdp 320a1be23daSdp if (propval == NULL) 321a1be23daSdp return (Z_INVAL); 322a1be23daSdp 323a1be23daSdp if ((err = getroot(handle, &root)) != Z_OK) 324a1be23daSdp return (err); 325a1be23daSdp 326a1be23daSdp if (xmlSetProp(root, propname, (const xmlChar *) propval) == NULL) 327a1be23daSdp return (Z_INVAL); 3287c478bd9Sstevel@tonic-gate return (Z_OK); 3297c478bd9Sstevel@tonic-gate } 3307c478bd9Sstevel@tonic-gate 331*087719fdSdp static void 332*087719fdSdp addcomment(zone_dochandle_t handle, const char *comment) 333*087719fdSdp { 334*087719fdSdp xmlNodePtr node; 335*087719fdSdp node = xmlNewComment((xmlChar *) comment); 336*087719fdSdp 337*087719fdSdp if (node != NULL) 338*087719fdSdp (void) xmlAddPrevSibling(handle->zone_dh_top, node); 339*087719fdSdp } 340*087719fdSdp 341*087719fdSdp static void 342*087719fdSdp stripcomments(zone_dochandle_t handle) 343*087719fdSdp { 344*087719fdSdp xmlDocPtr top; 345*087719fdSdp xmlNodePtr child, next; 346*087719fdSdp 347*087719fdSdp top = handle->zone_dh_doc; 348*087719fdSdp for (child = top->xmlChildrenNode; child != NULL; child = next) { 349*087719fdSdp next = child->next; 350*087719fdSdp if (child->name == NULL) 351*087719fdSdp continue; 352*087719fdSdp if (xmlStrcmp(child->name, DTD_ELEM_COMMENT) == 0) { 353*087719fdSdp next = child->next; 354*087719fdSdp xmlUnlinkNode(child); 355*087719fdSdp xmlFreeNode(child); 356*087719fdSdp } 357*087719fdSdp } 358*087719fdSdp } 359*087719fdSdp 3607c478bd9Sstevel@tonic-gate static int 3617c478bd9Sstevel@tonic-gate zonecfg_get_handle_impl(char *zonename, char *filename, zone_dochandle_t handle) 3627c478bd9Sstevel@tonic-gate { 3637c478bd9Sstevel@tonic-gate xmlValidCtxtPtr cvp; 3647c478bd9Sstevel@tonic-gate struct stat statbuf; 3657c478bd9Sstevel@tonic-gate int valid; 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate if (zonename == NULL) 3687c478bd9Sstevel@tonic-gate return (Z_NO_ZONE); 3697c478bd9Sstevel@tonic-gate if ((handle->zone_dh_doc = xmlParseFile(filename)) == NULL) { 3707c478bd9Sstevel@tonic-gate /* distinguish file not found vs. found but not parsed */ 3717c478bd9Sstevel@tonic-gate if (stat(filename, &statbuf) == 0) 3727c478bd9Sstevel@tonic-gate return (Z_INVALID_DOCUMENT); 3737c478bd9Sstevel@tonic-gate return (Z_NO_ZONE); 3747c478bd9Sstevel@tonic-gate } 3757c478bd9Sstevel@tonic-gate if ((cvp = xmlNewValidCtxt()) == NULL) 3767c478bd9Sstevel@tonic-gate return (Z_NOMEM); 3777c478bd9Sstevel@tonic-gate cvp->error = zonecfg_error_func; 3787c478bd9Sstevel@tonic-gate cvp->warning = zonecfg_error_func; 3797c478bd9Sstevel@tonic-gate valid = xmlValidateDocument(cvp, handle->zone_dh_doc); 3807c478bd9Sstevel@tonic-gate xmlFreeValidCtxt(cvp); 3817c478bd9Sstevel@tonic-gate if (valid == 0) 3827c478bd9Sstevel@tonic-gate return (Z_INVALID_DOCUMENT); 383*087719fdSdp 3847c478bd9Sstevel@tonic-gate /* delete any comments such as inherited Sun copyright / ident str */ 385*087719fdSdp stripcomments(handle); 3867c478bd9Sstevel@tonic-gate return (Z_OK); 3877c478bd9Sstevel@tonic-gate } 3887c478bd9Sstevel@tonic-gate 3897c478bd9Sstevel@tonic-gate int 3907c478bd9Sstevel@tonic-gate zonecfg_get_handle(char *zonename, zone_dochandle_t handle) 3917c478bd9Sstevel@tonic-gate { 3927c478bd9Sstevel@tonic-gate char path[MAXPATHLEN]; 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate config_file_path(zonename, path); 395*087719fdSdp handle->zone_dh_newzone = B_FALSE; 396*087719fdSdp 3977c478bd9Sstevel@tonic-gate return (zonecfg_get_handle_impl(zonename, path, handle)); 3987c478bd9Sstevel@tonic-gate } 3997c478bd9Sstevel@tonic-gate 4007c478bd9Sstevel@tonic-gate int 4017c478bd9Sstevel@tonic-gate zonecfg_get_snapshot_handle(char *zonename, zone_dochandle_t handle) 4027c478bd9Sstevel@tonic-gate { 4037c478bd9Sstevel@tonic-gate char path[MAXPATHLEN]; 4047c478bd9Sstevel@tonic-gate 4057c478bd9Sstevel@tonic-gate snap_file_path(zonename, path); 406*087719fdSdp handle->zone_dh_newzone = B_FALSE; 4077c478bd9Sstevel@tonic-gate return (zonecfg_get_handle_impl(zonename, path, handle)); 4087c478bd9Sstevel@tonic-gate } 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate int 411*087719fdSdp zonecfg_get_template_handle(char *template, char *zonename, 412*087719fdSdp zone_dochandle_t handle) 413*087719fdSdp { 414*087719fdSdp char path[MAXPATHLEN]; 415*087719fdSdp int err; 416*087719fdSdp 417*087719fdSdp config_file_path(template, path); 418*087719fdSdp 419*087719fdSdp if ((err = zonecfg_get_handle_impl(template, path, handle)) != Z_OK) 420*087719fdSdp return (err); 421*087719fdSdp handle->zone_dh_newzone = B_TRUE; 422*087719fdSdp return (setrootattr(handle, DTD_ATTR_NAME, zonename)); 423*087719fdSdp } 424*087719fdSdp 425*087719fdSdp static boolean_t 426*087719fdSdp is_renaming(zone_dochandle_t handle) 427*087719fdSdp { 428*087719fdSdp if (handle->zone_dh_newzone) 429*087719fdSdp return (B_FALSE); 430*087719fdSdp if (strlen(handle->zone_dh_delete_name) > 0) 431*087719fdSdp return (B_TRUE); 432*087719fdSdp return (B_FALSE); 433*087719fdSdp } 434*087719fdSdp 435*087719fdSdp static boolean_t 436*087719fdSdp is_new(zone_dochandle_t handle) 437*087719fdSdp { 438*087719fdSdp return (handle->zone_dh_newzone || handle->zone_dh_snapshot); 439*087719fdSdp } 440*087719fdSdp 441*087719fdSdp static boolean_t 442*087719fdSdp is_snapshot(zone_dochandle_t handle) 443*087719fdSdp { 444*087719fdSdp return (handle->zone_dh_snapshot); 445*087719fdSdp } 446*087719fdSdp 447*087719fdSdp /* 448*087719fdSdp * It would be great to be able to use libc's ctype(3c) macros, but we 449*087719fdSdp * can't, as they are locale sensitive, and it would break our limited thread 450*087719fdSdp * safety if this routine had to change the app locale on the fly. 451*087719fdSdp */ 452*087719fdSdp int 453*087719fdSdp zonecfg_validate_zonename(char *zone) 454*087719fdSdp { 455*087719fdSdp int i; 456*087719fdSdp 457*087719fdSdp if (strcmp(zone, GLOBAL_ZONENAME) == 0) 458*087719fdSdp return (Z_BOGUS_ZONE_NAME); 459*087719fdSdp 460*087719fdSdp if (strlen(zone) >= ZONENAME_MAX) 461*087719fdSdp return (Z_BOGUS_ZONE_NAME); 462*087719fdSdp 463*087719fdSdp if (!((zone[0] >= 'a' && zone[0] <= 'z') || 464*087719fdSdp (zone[0] >= 'A' && zone[0] <= 'Z') || 465*087719fdSdp (zone[0] >= '0' && zone[0] <= '9'))) 466*087719fdSdp return (Z_BOGUS_ZONE_NAME); 467*087719fdSdp 468*087719fdSdp for (i = 1; zone[i] != '\0'; i++) { 469*087719fdSdp if (!((zone[i] >= 'a' && zone[i] <= 'z') || 470*087719fdSdp (zone[i] >= 'A' && zone[i] <= 'Z') || 471*087719fdSdp (zone[i] >= '0' && zone[i] <= '9') || 472*087719fdSdp (zone[i] == '-') || (zone[i] == '_') || (zone[i] == '.'))) 473*087719fdSdp return (Z_BOGUS_ZONE_NAME); 474*087719fdSdp } 475*087719fdSdp 476*087719fdSdp return (Z_OK); 477*087719fdSdp } 478*087719fdSdp 479*087719fdSdp /* 480*087719fdSdp * Changing the zone name requires us to track both the old and new 481*087719fdSdp * name of the zone until commit time. 482*087719fdSdp */ 483*087719fdSdp int 4847c478bd9Sstevel@tonic-gate zonecfg_get_name(zone_dochandle_t handle, char *name, size_t namesize) 4857c478bd9Sstevel@tonic-gate { 486a1be23daSdp return (getrootattr(handle, DTD_ATTR_NAME, name, namesize)); 4877c478bd9Sstevel@tonic-gate } 4887c478bd9Sstevel@tonic-gate 489a1be23daSdp int 490a1be23daSdp zonecfg_set_name(zone_dochandle_t handle, char *name) 491a1be23daSdp { 492*087719fdSdp zone_state_t state; 493*087719fdSdp char curname[ZONENAME_MAX], old_delname[ZONENAME_MAX]; 494*087719fdSdp int err; 495*087719fdSdp 496*087719fdSdp if ((err = getrootattr(handle, DTD_ATTR_NAME, curname, 497*087719fdSdp sizeof (curname))) != Z_OK) 498*087719fdSdp return (err); 499*087719fdSdp 500*087719fdSdp if (strcmp(name, curname) == 0) 501*087719fdSdp return (Z_OK); 502*087719fdSdp 503*087719fdSdp /* 504*087719fdSdp * Switching zone names to one beginning with SUNW is not permitted. 505*087719fdSdp */ 506*087719fdSdp if (strncmp(name, "SUNW", 4) == 0) 507*087719fdSdp return (Z_BOGUS_ZONE_NAME); 508*087719fdSdp 509*087719fdSdp if ((err = zonecfg_validate_zonename(name)) != Z_OK) 510*087719fdSdp return (err); 511*087719fdSdp 512*087719fdSdp /* 513*087719fdSdp * Setting the name back to the original name (effectively a revert of 514*087719fdSdp * the name) is fine. But if we carry on, we'll falsely identify the 515*087719fdSdp * name as "in use," so special case here. 516*087719fdSdp */ 517*087719fdSdp if (strcmp(name, handle->zone_dh_delete_name) == 0) { 518*087719fdSdp err = setrootattr(handle, DTD_ATTR_NAME, name); 519*087719fdSdp handle->zone_dh_delete_name[0] = '\0'; 520*087719fdSdp return (err); 521*087719fdSdp } 522*087719fdSdp 523*087719fdSdp /* Check to see if new name chosen is already in use */ 524*087719fdSdp if (zone_get_state(name, &state) != Z_NO_ZONE) 525*087719fdSdp return (Z_NAME_IN_USE); 526*087719fdSdp 527*087719fdSdp /* 528*087719fdSdp * If this isn't already "new" or in a renaming transition, then 529*087719fdSdp * we're initiating a rename here; so stash the "delete name" 530*087719fdSdp * (i.e. the name of the zone we'll be removing) for the rename. 531*087719fdSdp */ 532*087719fdSdp (void) strlcpy(old_delname, handle->zone_dh_delete_name, 533*087719fdSdp sizeof (old_delname)); 534*087719fdSdp if (!is_new(handle) && !is_renaming(handle)) { 535*087719fdSdp /* 536*087719fdSdp * Name change is allowed only when the zone we're altering 537*087719fdSdp * is not ready or running. 538*087719fdSdp */ 539*087719fdSdp err = zone_get_state(curname, &state); 540*087719fdSdp if (err == Z_OK) { 541*087719fdSdp if (state > ZONE_STATE_INSTALLED) 542*087719fdSdp return (Z_BAD_ZONE_STATE); 543*087719fdSdp } else if (err != Z_NO_ZONE) { 544*087719fdSdp return (err); 545*087719fdSdp } 546*087719fdSdp 547*087719fdSdp (void) strlcpy(handle->zone_dh_delete_name, curname, 548*087719fdSdp sizeof (handle->zone_dh_delete_name)); 549*087719fdSdp assert(is_renaming(handle)); 550*087719fdSdp } else if (is_renaming(handle)) { 551*087719fdSdp err = zone_get_state(handle->zone_dh_delete_name, &state); 552*087719fdSdp if (err == Z_OK) { 553*087719fdSdp if (state > ZONE_STATE_INSTALLED) 554*087719fdSdp return (Z_BAD_ZONE_STATE); 555*087719fdSdp } else if (err != Z_NO_ZONE) { 556*087719fdSdp return (err); 557*087719fdSdp } 558*087719fdSdp } 559*087719fdSdp 560*087719fdSdp if ((err = setrootattr(handle, DTD_ATTR_NAME, name)) != Z_OK) { 561*087719fdSdp /* 562*087719fdSdp * Restore the deletename to whatever it was at the 563*087719fdSdp * top of the routine, since we've had a failure. 564*087719fdSdp */ 565*087719fdSdp (void) strlcpy(handle->zone_dh_delete_name, old_delname, 566*087719fdSdp sizeof (handle->zone_dh_delete_name)); 567*087719fdSdp return (err); 568*087719fdSdp } 569*087719fdSdp 570*087719fdSdp return (Z_OK); 5717c478bd9Sstevel@tonic-gate } 572a1be23daSdp 573a1be23daSdp int 574a1be23daSdp zonecfg_get_zonepath(zone_dochandle_t handle, char *path, size_t pathsize) 575a1be23daSdp { 576a1be23daSdp return (getrootattr(handle, DTD_ATTR_ZONEPATH, path, pathsize)); 577a1be23daSdp } 578a1be23daSdp 579a1be23daSdp int 580a1be23daSdp zonecfg_set_zonepath(zone_dochandle_t handle, char *zonepath) 581a1be23daSdp { 582a1be23daSdp return (setrootattr(handle, DTD_ATTR_ZONEPATH, zonepath)); 583a1be23daSdp } 584a1be23daSdp 585a1be23daSdp int 586a1be23daSdp zonecfg_get_autoboot(zone_dochandle_t handle, boolean_t *autoboot) 587a1be23daSdp { 588a1be23daSdp char autobootstr[DTD_ENTITY_BOOL_LEN]; 589a1be23daSdp int ret; 590a1be23daSdp 591a1be23daSdp if ((ret = getrootattr(handle, DTD_ATTR_AUTOBOOT, autobootstr, 592a1be23daSdp sizeof (autobootstr))) != Z_OK) 593a1be23daSdp return (ret); 594a1be23daSdp 595a1be23daSdp if (strcmp(autobootstr, DTD_ENTITY_TRUE) == 0) 596a1be23daSdp *autoboot = B_TRUE; 597a1be23daSdp else if (strcmp(autobootstr, DTD_ENTITY_FALSE) == 0) 598a1be23daSdp *autoboot = B_FALSE; 599a1be23daSdp else 600a1be23daSdp ret = Z_BAD_PROPERTY; 601a1be23daSdp return (ret); 602a1be23daSdp } 603a1be23daSdp 604a1be23daSdp int 605a1be23daSdp zonecfg_set_autoboot(zone_dochandle_t handle, boolean_t autoboot) 606a1be23daSdp { 607a1be23daSdp return (setrootattr(handle, DTD_ATTR_AUTOBOOT, 608a1be23daSdp autoboot ? DTD_ENTITY_TRUE : DTD_ENTITY_FALSE)); 609a1be23daSdp } 610a1be23daSdp 611a1be23daSdp int 612a1be23daSdp zonecfg_get_pool(zone_dochandle_t handle, char *pool, size_t poolsize) 613a1be23daSdp { 614a1be23daSdp return (getrootattr(handle, DTD_ATTR_POOL, pool, poolsize)); 615a1be23daSdp } 616a1be23daSdp 617a1be23daSdp int 618a1be23daSdp zonecfg_set_pool(zone_dochandle_t handle, char *pool) 619a1be23daSdp { 620a1be23daSdp return (setrootattr(handle, DTD_ATTR_POOL, pool)); 621a1be23daSdp } 622a1be23daSdp 623a1be23daSdp /* 624a1be23daSdp * /etc/zones/index caches a vital piece of information which is also 625a1be23daSdp * in the <zonename>.xml file: the path to the zone. This is for performance, 626a1be23daSdp * since we need to walk all zonepath's in order to be able to detect conflicts 627a1be23daSdp * (see crosscheck_zonepaths() in the zoneadm command). 628*087719fdSdp * 629*087719fdSdp * An additional complexity is that when doing a rename, we'd like the entire 630*087719fdSdp * index update operation (rename, and potential state changes) to be atomic. 631*087719fdSdp * In general, the operation of this function should succeed or fail as 632*087719fdSdp * a unit. 633a1be23daSdp */ 634a1be23daSdp int 635a1be23daSdp zonecfg_refresh_index_file(zone_dochandle_t handle) 636a1be23daSdp { 637a1be23daSdp char name[ZONENAME_MAX], zonepath[MAXPATHLEN]; 638a1be23daSdp struct zoneent ze; 639a1be23daSdp int err; 640*087719fdSdp int opcode; 641*087719fdSdp char *zn; 642*087719fdSdp 643*087719fdSdp bzero(&ze, sizeof (ze)); 644*087719fdSdp ze.zone_state = -1; /* Preserve existing state in index */ 645a1be23daSdp 646a1be23daSdp if ((err = zonecfg_get_name(handle, name, sizeof (name))) != Z_OK) 647a1be23daSdp return (err); 648*087719fdSdp (void) strlcpy(ze.zone_name, name, sizeof (ze.zone_name)); 649*087719fdSdp 650a1be23daSdp if ((err = zonecfg_get_zonepath(handle, zonepath, 651a1be23daSdp sizeof (zonepath))) != Z_OK) 652a1be23daSdp return (err); 653a1be23daSdp (void) strlcpy(ze.zone_path, zonepath, sizeof (ze.zone_path)); 654*087719fdSdp 655*087719fdSdp if (is_renaming(handle)) { 656*087719fdSdp opcode = PZE_MODIFY; 657*087719fdSdp (void) strlcpy(ze.zone_name, handle->zone_dh_delete_name, 658*087719fdSdp sizeof (ze.zone_name)); 659*087719fdSdp (void) strlcpy(ze.zone_newname, name, sizeof (ze.zone_newname)); 660*087719fdSdp } else if (is_new(handle)) { 661*087719fdSdp FILE *cookie; 662*087719fdSdp /* 663*087719fdSdp * Be tolerant of the zone already existing in the index file, 664*087719fdSdp * since we might be forcibly overwriting an existing 665*087719fdSdp * configuration with a new one (for example 'create -F' 666*087719fdSdp * in zonecfg). 667*087719fdSdp */ 668*087719fdSdp opcode = PZE_ADD; 669*087719fdSdp cookie = setzoneent(); 670*087719fdSdp while ((zn = getzoneent(cookie)) != NULL) { 671*087719fdSdp if (strcmp(zn, name) == 0) { 672*087719fdSdp opcode = PZE_MODIFY; 673*087719fdSdp free(zn); 674*087719fdSdp break; 675*087719fdSdp } 676*087719fdSdp free(zn); 677*087719fdSdp } 678*087719fdSdp endzoneent(cookie); 679*087719fdSdp ze.zone_state = ZONE_STATE_CONFIGURED; 680*087719fdSdp } else { 681*087719fdSdp opcode = PZE_MODIFY; 6827c478bd9Sstevel@tonic-gate } 6837c478bd9Sstevel@tonic-gate 684*087719fdSdp if ((err = putzoneent(&ze, opcode)) != Z_OK) 685*087719fdSdp return (err); 686*087719fdSdp 687*087719fdSdp return (Z_OK); 688*087719fdSdp } 689*087719fdSdp 690*087719fdSdp /* 691*087719fdSdp * The goal of this routine is to cause the index file update and the 692*087719fdSdp * document save to happen as an atomic operation. We do the document 693*087719fdSdp * first, saving a backup copy using a hard link; if that succeeds, we go 694*087719fdSdp * on to the index. If that fails, we roll the document back into place. 695*087719fdSdp * 696*087719fdSdp * Strategy: 697*087719fdSdp * 698*087719fdSdp * New zone 'foo' configuration: 699*087719fdSdp * Create tmpfile (zonecfg.xxxxxx) 700*087719fdSdp * Write XML to tmpfile 701*087719fdSdp * Rename tmpfile to xmlfile (zonecfg.xxxxxx -> foo.xml) 702*087719fdSdp * Add entry to index file 703*087719fdSdp * If it fails, delete foo.xml, leaving nothing behind. 704*087719fdSdp * 705*087719fdSdp * Save existing zone 'foo': 706*087719fdSdp * Make backup of foo.xml -> .backup 707*087719fdSdp * Create tmpfile (zonecfg.xxxxxx) 708*087719fdSdp * Write XML to tmpfile 709*087719fdSdp * Rename tmpfile to xmlfile (zonecfg.xxxxxx -> foo.xml) 710*087719fdSdp * Modify index file as needed 711*087719fdSdp * If it fails, recover from .backup -> foo.xml 712*087719fdSdp * 713*087719fdSdp * Rename 'foo' to 'bar': 714*087719fdSdp * Create tmpfile (zonecfg.xxxxxx) 715*087719fdSdp * Write XML to tmpfile 716*087719fdSdp * Rename tmpfile to xmlfile (zonecfg.xxxxxx -> bar.xml) 717*087719fdSdp * Add entry for 'bar' to index file, Remove entry for 'foo' (refresh) 718*087719fdSdp * If it fails, delete bar.xml; foo.xml is left behind. 719*087719fdSdp */ 7207c478bd9Sstevel@tonic-gate static int 7217c478bd9Sstevel@tonic-gate zonecfg_save_impl(zone_dochandle_t handle, char *filename) 7227c478bd9Sstevel@tonic-gate { 7237c478bd9Sstevel@tonic-gate char tmpfile[MAXPATHLEN]; 724*087719fdSdp char bakdir[MAXPATHLEN], bakbase[MAXPATHLEN], bakfile[MAXPATHLEN]; 725*087719fdSdp int tmpfd, err; 7267c478bd9Sstevel@tonic-gate xmlValidCtxt cvp = { NULL }; 727*087719fdSdp boolean_t backup; 7287c478bd9Sstevel@tonic-gate 7297c478bd9Sstevel@tonic-gate (void) strlcpy(tmpfile, filename, sizeof (tmpfile)); 7307c478bd9Sstevel@tonic-gate (void) dirname(tmpfile); 7317c478bd9Sstevel@tonic-gate (void) strlcat(tmpfile, _PATH_TMPFILE, sizeof (tmpfile)); 7327c478bd9Sstevel@tonic-gate 7337c478bd9Sstevel@tonic-gate tmpfd = mkstemp(tmpfile); 7347c478bd9Sstevel@tonic-gate if (tmpfd == -1) { 7357c478bd9Sstevel@tonic-gate (void) unlink(tmpfile); 7367c478bd9Sstevel@tonic-gate return (Z_TEMP_FILE); 7377c478bd9Sstevel@tonic-gate } 7387c478bd9Sstevel@tonic-gate (void) close(tmpfd); 7397c478bd9Sstevel@tonic-gate 7407c478bd9Sstevel@tonic-gate cvp.error = zonecfg_error_func; 7417c478bd9Sstevel@tonic-gate cvp.warning = zonecfg_error_func; 7427c478bd9Sstevel@tonic-gate 743*087719fdSdp /* 744*087719fdSdp * We do a final validation of the document-- but the library has 745*087719fdSdp * malfunctioned if it fails to validate, so it's an assert. 746*087719fdSdp */ 747*087719fdSdp assert(xmlValidateDocument(&cvp, handle->zone_dh_doc) != 0); 7487c478bd9Sstevel@tonic-gate 7497c478bd9Sstevel@tonic-gate if (xmlSaveFormatFile(tmpfile, handle->zone_dh_doc, 1) <= 0) 7507c478bd9Sstevel@tonic-gate goto err; 751*087719fdSdp 7527c478bd9Sstevel@tonic-gate (void) chmod(tmpfile, 0644); 7537c478bd9Sstevel@tonic-gate 754*087719fdSdp /* 755*087719fdSdp * In the event we are doing a standard save, hard link a copy of the 756*087719fdSdp * original file in .backup.<pid>.filename so we can restore it if 757*087719fdSdp * something goes wrong. 758*087719fdSdp */ 759*087719fdSdp if (!is_new(handle) && !is_renaming(handle)) { 760*087719fdSdp backup = B_TRUE; 761*087719fdSdp 762*087719fdSdp (void) strlcpy(bakdir, filename, sizeof (bakdir)); 763*087719fdSdp (void) strlcpy(bakbase, filename, sizeof (bakbase)); 764*087719fdSdp (void) snprintf(bakfile, sizeof (bakfile), "%s/.backup.%d.%s", 765*087719fdSdp dirname(bakdir), getpid(), basename(bakbase)); 766*087719fdSdp 767*087719fdSdp if (link(filename, bakfile) == -1) { 768*087719fdSdp err = errno; 7697c478bd9Sstevel@tonic-gate (void) unlink(tmpfile); 7707c478bd9Sstevel@tonic-gate if (errno == EACCES) 7717c478bd9Sstevel@tonic-gate return (Z_ACCES); 7727c478bd9Sstevel@tonic-gate return (Z_MISC_FS); 7737c478bd9Sstevel@tonic-gate } 774*087719fdSdp } 775a1be23daSdp 776*087719fdSdp /* 777*087719fdSdp * Move the new document over top of the old. 778*087719fdSdp * i.e.: zonecfg.XXXXXX -> myzone.xml 779*087719fdSdp */ 780*087719fdSdp if (rename(tmpfile, filename) == -1) { 781*087719fdSdp err = errno; 782*087719fdSdp (void) unlink(tmpfile); 783*087719fdSdp if (backup) 784*087719fdSdp (void) unlink(bakfile); 785*087719fdSdp if (err == EACCES) 786*087719fdSdp return (Z_ACCES); 787*087719fdSdp return (Z_MISC_FS); 788*087719fdSdp } 789*087719fdSdp 790*087719fdSdp /* 791*087719fdSdp * If this is a snapshot, we're done-- don't add an index entry. 792*087719fdSdp */ 793*087719fdSdp if (is_snapshot(handle)) 794*087719fdSdp return (Z_OK); 795*087719fdSdp 796*087719fdSdp /* now update the index file to reflect whatever we just did */ 797*087719fdSdp if ((err = zonecfg_refresh_index_file(handle)) != Z_OK) { 798*087719fdSdp if (backup) { 799*087719fdSdp /* 800*087719fdSdp * Try to restore from our backup. 801*087719fdSdp */ 802*087719fdSdp (void) unlink(filename); 803*087719fdSdp (void) rename(bakfile, filename); 804*087719fdSdp } else { 805*087719fdSdp /* 806*087719fdSdp * Either the zone is new, in which case we can delete 807*087719fdSdp * new.xml, or we're doing a rename, so ditto. 808*087719fdSdp */ 809*087719fdSdp assert(is_new(handle) || is_renaming(handle)); 810*087719fdSdp (void) unlink(filename); 811*087719fdSdp } 812*087719fdSdp return (Z_UPDATING_INDEX); 813*087719fdSdp } 814*087719fdSdp 815*087719fdSdp if (backup) 816*087719fdSdp (void) unlink(bakfile); 817*087719fdSdp 818*087719fdSdp return (Z_OK); 8197c478bd9Sstevel@tonic-gate 8207c478bd9Sstevel@tonic-gate err: 8217c478bd9Sstevel@tonic-gate (void) unlink(tmpfile); 8227c478bd9Sstevel@tonic-gate return (Z_SAVING_FILE); 8237c478bd9Sstevel@tonic-gate } 8247c478bd9Sstevel@tonic-gate 8257c478bd9Sstevel@tonic-gate int 8267c478bd9Sstevel@tonic-gate zonecfg_save(zone_dochandle_t handle) 8277c478bd9Sstevel@tonic-gate { 828*087719fdSdp char zname[ZONENAME_MAX], path[MAXPATHLEN]; 829*087719fdSdp char delpath[MAXPATHLEN]; 830*087719fdSdp int err = Z_SAVING_FILE; 8317c478bd9Sstevel@tonic-gate 832*087719fdSdp if (zonecfg_check_handle(handle) != Z_OK) 833*087719fdSdp return (Z_BAD_HANDLE); 834*087719fdSdp 835*087719fdSdp /* 836*087719fdSdp * We don't support saving snapshots at this time. 837*087719fdSdp */ 838*087719fdSdp if (handle->zone_dh_snapshot) 839*087719fdSdp return (Z_INVAL); 840*087719fdSdp 841*087719fdSdp if ((err = zonecfg_get_name(handle, zname, sizeof (zname))) != Z_OK) 8427c478bd9Sstevel@tonic-gate return (err); 843*087719fdSdp 8447c478bd9Sstevel@tonic-gate config_file_path(zname, path); 845*087719fdSdp 846*087719fdSdp addcomment(handle, "\n DO NOT EDIT THIS " 847*087719fdSdp "FILE. Use zonecfg(1M) instead.\n"); 848*087719fdSdp 849*087719fdSdp err = zonecfg_save_impl(handle, path); 850*087719fdSdp 851*087719fdSdp stripcomments(handle); 852*087719fdSdp 853*087719fdSdp if (err != Z_OK) 854*087719fdSdp return (err); 855*087719fdSdp 856*087719fdSdp handle->zone_dh_newzone = B_FALSE; 857*087719fdSdp 858*087719fdSdp if (is_renaming(handle)) { 859*087719fdSdp config_file_path(handle->zone_dh_delete_name, delpath); 860*087719fdSdp (void) unlink(delpath); 861*087719fdSdp handle->zone_dh_delete_name[0] = '\0'; 862*087719fdSdp } 863*087719fdSdp 864*087719fdSdp return (Z_OK); 8657c478bd9Sstevel@tonic-gate } 8667c478bd9Sstevel@tonic-gate 8677c478bd9Sstevel@tonic-gate /* 8687c478bd9Sstevel@tonic-gate * Special case: if access(2) fails with ENOENT, then try again using 8697c478bd9Sstevel@tonic-gate * ZONE_CONFIG_ROOT instead of config_file_path(zonename). This is how we 8707c478bd9Sstevel@tonic-gate * work around the case of a config file which has not been created yet: 8717c478bd9Sstevel@tonic-gate * the user will need access to the directory so use that as a heuristic. 8727c478bd9Sstevel@tonic-gate */ 8737c478bd9Sstevel@tonic-gate 8747c478bd9Sstevel@tonic-gate int 8757c478bd9Sstevel@tonic-gate zonecfg_access(const char *zonename, int amode) 8767c478bd9Sstevel@tonic-gate { 8777c478bd9Sstevel@tonic-gate char path[MAXPATHLEN]; 8787c478bd9Sstevel@tonic-gate 8797c478bd9Sstevel@tonic-gate config_file_path(zonename, path); 8807c478bd9Sstevel@tonic-gate if (access(path, amode) == 0) 8817c478bd9Sstevel@tonic-gate return (Z_OK); 8827c478bd9Sstevel@tonic-gate if (errno == ENOENT && access(ZONE_CONFIG_ROOT, amode) == 0) 8837c478bd9Sstevel@tonic-gate return (Z_OK); 8847c478bd9Sstevel@tonic-gate if (errno == EACCES) 8857c478bd9Sstevel@tonic-gate return (Z_ACCES); 8867c478bd9Sstevel@tonic-gate if (errno == EINVAL) 8877c478bd9Sstevel@tonic-gate return (Z_INVAL); 8887c478bd9Sstevel@tonic-gate return (Z_MISC_FS); 8897c478bd9Sstevel@tonic-gate } 8907c478bd9Sstevel@tonic-gate 8917c478bd9Sstevel@tonic-gate int 8927c478bd9Sstevel@tonic-gate zonecfg_create_snapshot(char *zonename) 8937c478bd9Sstevel@tonic-gate { 8947c478bd9Sstevel@tonic-gate zone_dochandle_t handle; 8957c478bd9Sstevel@tonic-gate char path[MAXPATHLEN], zonepath[MAXPATHLEN], rpath[MAXPATHLEN]; 8967c478bd9Sstevel@tonic-gate int error = Z_OK, res; 8977c478bd9Sstevel@tonic-gate 8987c478bd9Sstevel@tonic-gate if ((handle = zonecfg_init_handle()) == NULL) { 8997c478bd9Sstevel@tonic-gate return (Z_NOMEM); 9007c478bd9Sstevel@tonic-gate } 9017c478bd9Sstevel@tonic-gate 902*087719fdSdp handle->zone_dh_newzone = B_TRUE; 903*087719fdSdp handle->zone_dh_snapshot = B_TRUE; 904*087719fdSdp 9057c478bd9Sstevel@tonic-gate if ((error = zonecfg_get_handle(zonename, handle)) != Z_OK) 9067c478bd9Sstevel@tonic-gate goto out; 9077c478bd9Sstevel@tonic-gate if ((error = operation_prep(handle)) != Z_OK) 9087c478bd9Sstevel@tonic-gate goto out; 9097c478bd9Sstevel@tonic-gate error = zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath)); 9107c478bd9Sstevel@tonic-gate if (error != Z_OK) 9117c478bd9Sstevel@tonic-gate goto out; 9127c478bd9Sstevel@tonic-gate if ((res = resolvepath(zonepath, rpath, sizeof (rpath))) == -1) { 9137c478bd9Sstevel@tonic-gate error = Z_RESOLVED_PATH; 9147c478bd9Sstevel@tonic-gate goto out; 9157c478bd9Sstevel@tonic-gate } 9167c478bd9Sstevel@tonic-gate /* 9177c478bd9Sstevel@tonic-gate * If the resolved path is not the same as the original path, then 9187c478bd9Sstevel@tonic-gate * save the resolved path in the snapshot, thus preventing any 9197c478bd9Sstevel@tonic-gate * potential problems down the line when zoneadmd goes to unmount 9207c478bd9Sstevel@tonic-gate * file systems and depends on initial string matches with resolved 9217c478bd9Sstevel@tonic-gate * paths. 9227c478bd9Sstevel@tonic-gate */ 9237c478bd9Sstevel@tonic-gate rpath[res] = '\0'; 9247c478bd9Sstevel@tonic-gate if (strcmp(zonepath, rpath) != 0) { 9257c478bd9Sstevel@tonic-gate if ((error = zonecfg_set_zonepath(handle, rpath)) != Z_OK) 9267c478bd9Sstevel@tonic-gate goto out; 9277c478bd9Sstevel@tonic-gate } 9287c478bd9Sstevel@tonic-gate if ((mkdir(ZONE_SNAPSHOT_ROOT, S_IRWXU) == -1) && (errno != EEXIST)) { 9297c478bd9Sstevel@tonic-gate error = Z_MISC_FS; 9307c478bd9Sstevel@tonic-gate goto out; 9317c478bd9Sstevel@tonic-gate } 9327c478bd9Sstevel@tonic-gate 9337c478bd9Sstevel@tonic-gate snap_file_path(zonename, path); 934*087719fdSdp 935*087719fdSdp addcomment(handle, "\n DO NOT EDIT THIS FILE. " 936*087719fdSdp "It is a snapshot of running zone state.\n"); 937*087719fdSdp 9387c478bd9Sstevel@tonic-gate error = zonecfg_save_impl(handle, path); 9397c478bd9Sstevel@tonic-gate 940*087719fdSdp stripcomments(handle); 941*087719fdSdp 9427c478bd9Sstevel@tonic-gate out: 9437c478bd9Sstevel@tonic-gate zonecfg_fini_handle(handle); 9447c478bd9Sstevel@tonic-gate return (error); 9457c478bd9Sstevel@tonic-gate } 9467c478bd9Sstevel@tonic-gate 9477c478bd9Sstevel@tonic-gate static int 948a1be23daSdp newprop(xmlNodePtr node, const xmlChar *attrname, char *src) 9497c478bd9Sstevel@tonic-gate { 9507c478bd9Sstevel@tonic-gate xmlAttrPtr newattr; 9517c478bd9Sstevel@tonic-gate 9527c478bd9Sstevel@tonic-gate newattr = xmlNewProp(node, attrname, (xmlChar *)src); 9537c478bd9Sstevel@tonic-gate if (newattr == NULL) { 9547c478bd9Sstevel@tonic-gate xmlUnlinkNode(node); 9557c478bd9Sstevel@tonic-gate xmlFreeNode(node); 9567c478bd9Sstevel@tonic-gate return (Z_BAD_PROPERTY); 9577c478bd9Sstevel@tonic-gate } 9587c478bd9Sstevel@tonic-gate return (Z_OK); 9597c478bd9Sstevel@tonic-gate } 9607c478bd9Sstevel@tonic-gate 9617c478bd9Sstevel@tonic-gate static int 9627c478bd9Sstevel@tonic-gate zonecfg_add_filesystem_core(zone_dochandle_t handle, struct zone_fstab *tabptr) 9637c478bd9Sstevel@tonic-gate { 9647c478bd9Sstevel@tonic-gate xmlNodePtr newnode, cur = handle->zone_dh_cur, options_node; 9657c478bd9Sstevel@tonic-gate zone_fsopt_t *ptr; 9667c478bd9Sstevel@tonic-gate int err; 9677c478bd9Sstevel@tonic-gate 9687c478bd9Sstevel@tonic-gate newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_FS, NULL); 969a1be23daSdp if ((err = newprop(newnode, DTD_ATTR_SPECIAL, 9707c478bd9Sstevel@tonic-gate tabptr->zone_fs_special)) != Z_OK) 9717c478bd9Sstevel@tonic-gate return (err); 9727c478bd9Sstevel@tonic-gate if (tabptr->zone_fs_raw[0] != '\0' && 973a1be23daSdp (err = newprop(newnode, DTD_ATTR_RAW, tabptr->zone_fs_raw)) != Z_OK) 9747c478bd9Sstevel@tonic-gate return (err); 975a1be23daSdp if ((err = newprop(newnode, DTD_ATTR_DIR, tabptr->zone_fs_dir)) != Z_OK) 9767c478bd9Sstevel@tonic-gate return (err); 977a1be23daSdp if ((err = newprop(newnode, DTD_ATTR_TYPE, 9787c478bd9Sstevel@tonic-gate tabptr->zone_fs_type)) != Z_OK) 9797c478bd9Sstevel@tonic-gate return (err); 9807c478bd9Sstevel@tonic-gate if (tabptr->zone_fs_options != NULL) { 9817c478bd9Sstevel@tonic-gate for (ptr = tabptr->zone_fs_options; ptr != NULL; 9827c478bd9Sstevel@tonic-gate ptr = ptr->zone_fsopt_next) { 9837c478bd9Sstevel@tonic-gate options_node = xmlNewTextChild(newnode, NULL, 9847c478bd9Sstevel@tonic-gate DTD_ELEM_FSOPTION, NULL); 985a1be23daSdp if ((err = newprop(options_node, DTD_ATTR_NAME, 9867c478bd9Sstevel@tonic-gate ptr->zone_fsopt_opt)) != Z_OK) 9877c478bd9Sstevel@tonic-gate return (err); 9887c478bd9Sstevel@tonic-gate } 9897c478bd9Sstevel@tonic-gate } 9907c478bd9Sstevel@tonic-gate return (Z_OK); 9917c478bd9Sstevel@tonic-gate } 9927c478bd9Sstevel@tonic-gate 9937c478bd9Sstevel@tonic-gate int 9947c478bd9Sstevel@tonic-gate zonecfg_add_filesystem(zone_dochandle_t handle, struct zone_fstab *tabptr) 9957c478bd9Sstevel@tonic-gate { 9967c478bd9Sstevel@tonic-gate int err; 9977c478bd9Sstevel@tonic-gate 9987c478bd9Sstevel@tonic-gate if (tabptr == NULL) 9997c478bd9Sstevel@tonic-gate return (Z_INVAL); 10007c478bd9Sstevel@tonic-gate 10017c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 10027c478bd9Sstevel@tonic-gate return (err); 10037c478bd9Sstevel@tonic-gate 10047c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_filesystem_core(handle, tabptr)) != Z_OK) 10057c478bd9Sstevel@tonic-gate return (err); 10067c478bd9Sstevel@tonic-gate 10077c478bd9Sstevel@tonic-gate return (Z_OK); 10087c478bd9Sstevel@tonic-gate } 10097c478bd9Sstevel@tonic-gate 10107c478bd9Sstevel@tonic-gate static int 10117c478bd9Sstevel@tonic-gate zonecfg_add_ipd_core(zone_dochandle_t handle, struct zone_fstab *tabptr) 10127c478bd9Sstevel@tonic-gate { 10137c478bd9Sstevel@tonic-gate xmlNodePtr newnode, cur = handle->zone_dh_cur; 10147c478bd9Sstevel@tonic-gate int err; 10157c478bd9Sstevel@tonic-gate 10167c478bd9Sstevel@tonic-gate newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_IPD, NULL); 1017a1be23daSdp if ((err = newprop(newnode, DTD_ATTR_DIR, tabptr->zone_fs_dir)) != Z_OK) 10187c478bd9Sstevel@tonic-gate return (err); 10197c478bd9Sstevel@tonic-gate return (Z_OK); 10207c478bd9Sstevel@tonic-gate } 10217c478bd9Sstevel@tonic-gate 10227c478bd9Sstevel@tonic-gate int 10237c478bd9Sstevel@tonic-gate zonecfg_add_ipd(zone_dochandle_t handle, struct zone_fstab *tabptr) 10247c478bd9Sstevel@tonic-gate { 10257c478bd9Sstevel@tonic-gate int err; 10267c478bd9Sstevel@tonic-gate 10277c478bd9Sstevel@tonic-gate if (tabptr == NULL) 10287c478bd9Sstevel@tonic-gate return (Z_INVAL); 10297c478bd9Sstevel@tonic-gate 10307c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 10317c478bd9Sstevel@tonic-gate return (err); 10327c478bd9Sstevel@tonic-gate 10337c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_ipd_core(handle, tabptr)) != Z_OK) 10347c478bd9Sstevel@tonic-gate return (err); 10357c478bd9Sstevel@tonic-gate 10367c478bd9Sstevel@tonic-gate return (Z_OK); 10377c478bd9Sstevel@tonic-gate } 10387c478bd9Sstevel@tonic-gate 10397c478bd9Sstevel@tonic-gate int 10407c478bd9Sstevel@tonic-gate zonecfg_add_fs_option(struct zone_fstab *tabptr, char *option) 10417c478bd9Sstevel@tonic-gate { 10427c478bd9Sstevel@tonic-gate zone_fsopt_t *last, *old, *new; 10437c478bd9Sstevel@tonic-gate 10447c478bd9Sstevel@tonic-gate last = tabptr->zone_fs_options; 10457c478bd9Sstevel@tonic-gate for (old = last; old != NULL; old = old->zone_fsopt_next) 10467c478bd9Sstevel@tonic-gate last = old; /* walk to the end of the list */ 10477c478bd9Sstevel@tonic-gate new = (zone_fsopt_t *)malloc(sizeof (zone_fsopt_t)); 10487c478bd9Sstevel@tonic-gate if (new == NULL) 10497c478bd9Sstevel@tonic-gate return (Z_NOMEM); 10507c478bd9Sstevel@tonic-gate (void) strlcpy(new->zone_fsopt_opt, option, 10517c478bd9Sstevel@tonic-gate sizeof (new->zone_fsopt_opt)); 10527c478bd9Sstevel@tonic-gate new->zone_fsopt_next = NULL; 10537c478bd9Sstevel@tonic-gate if (last == NULL) 10547c478bd9Sstevel@tonic-gate tabptr->zone_fs_options = new; 10557c478bd9Sstevel@tonic-gate else 10567c478bd9Sstevel@tonic-gate last->zone_fsopt_next = new; 10577c478bd9Sstevel@tonic-gate return (Z_OK); 10587c478bd9Sstevel@tonic-gate } 10597c478bd9Sstevel@tonic-gate 10607c478bd9Sstevel@tonic-gate int 10617c478bd9Sstevel@tonic-gate zonecfg_remove_fs_option(struct zone_fstab *tabptr, char *option) 10627c478bd9Sstevel@tonic-gate { 10637c478bd9Sstevel@tonic-gate zone_fsopt_t *last, *this, *next; 10647c478bd9Sstevel@tonic-gate 10657c478bd9Sstevel@tonic-gate last = tabptr->zone_fs_options; 10667c478bd9Sstevel@tonic-gate for (this = last; this != NULL; this = this->zone_fsopt_next) { 10677c478bd9Sstevel@tonic-gate if (strcmp(this->zone_fsopt_opt, option) == 0) { 10687c478bd9Sstevel@tonic-gate next = this->zone_fsopt_next; 10697c478bd9Sstevel@tonic-gate if (this == tabptr->zone_fs_options) 10707c478bd9Sstevel@tonic-gate tabptr->zone_fs_options = next; 10717c478bd9Sstevel@tonic-gate else 10727c478bd9Sstevel@tonic-gate last->zone_fsopt_next = next; 10737c478bd9Sstevel@tonic-gate free(this); 10747c478bd9Sstevel@tonic-gate return (Z_OK); 10757c478bd9Sstevel@tonic-gate } else 10767c478bd9Sstevel@tonic-gate last = this; 10777c478bd9Sstevel@tonic-gate } 10787c478bd9Sstevel@tonic-gate return (Z_NO_PROPERTY_ID); 10797c478bd9Sstevel@tonic-gate } 10807c478bd9Sstevel@tonic-gate 10817c478bd9Sstevel@tonic-gate void 10827c478bd9Sstevel@tonic-gate zonecfg_free_fs_option_list(zone_fsopt_t *list) 10837c478bd9Sstevel@tonic-gate { 10847c478bd9Sstevel@tonic-gate zone_fsopt_t *this, *next; 10857c478bd9Sstevel@tonic-gate 10867c478bd9Sstevel@tonic-gate for (this = list; this != NULL; this = next) { 10877c478bd9Sstevel@tonic-gate next = this->zone_fsopt_next; 10887c478bd9Sstevel@tonic-gate free(this); 10897c478bd9Sstevel@tonic-gate } 10907c478bd9Sstevel@tonic-gate } 10917c478bd9Sstevel@tonic-gate 10927c478bd9Sstevel@tonic-gate void 10937c478bd9Sstevel@tonic-gate zonecfg_free_rctl_value_list(struct zone_rctlvaltab *valtab) 10947c478bd9Sstevel@tonic-gate { 10957c478bd9Sstevel@tonic-gate if (valtab == NULL) 10967c478bd9Sstevel@tonic-gate return; 10977c478bd9Sstevel@tonic-gate zonecfg_free_rctl_value_list(valtab->zone_rctlval_next); 10987c478bd9Sstevel@tonic-gate free(valtab); 10997c478bd9Sstevel@tonic-gate } 11007c478bd9Sstevel@tonic-gate 11017c478bd9Sstevel@tonic-gate static boolean_t 11027c478bd9Sstevel@tonic-gate match_prop(xmlNodePtr cur, const xmlChar *attr, char *user_prop) 11037c478bd9Sstevel@tonic-gate { 11047c478bd9Sstevel@tonic-gate xmlChar *gotten_prop; 11057c478bd9Sstevel@tonic-gate int prop_result; 11067c478bd9Sstevel@tonic-gate 11077c478bd9Sstevel@tonic-gate gotten_prop = xmlGetProp(cur, attr); 11087c478bd9Sstevel@tonic-gate if (gotten_prop == NULL) /* shouldn't happen */ 11097c478bd9Sstevel@tonic-gate return (B_FALSE); 11107c478bd9Sstevel@tonic-gate prop_result = xmlStrcmp(gotten_prop, (const xmlChar *) user_prop); 11117c478bd9Sstevel@tonic-gate xmlFree(gotten_prop); 11127c478bd9Sstevel@tonic-gate return ((prop_result == 0)); 11137c478bd9Sstevel@tonic-gate } 11147c478bd9Sstevel@tonic-gate 11157c478bd9Sstevel@tonic-gate static int 11167c478bd9Sstevel@tonic-gate zonecfg_delete_filesystem_core(zone_dochandle_t handle, 11177c478bd9Sstevel@tonic-gate struct zone_fstab *tabptr) 11187c478bd9Sstevel@tonic-gate { 11197c478bd9Sstevel@tonic-gate xmlNodePtr cur = handle->zone_dh_cur; 11207c478bd9Sstevel@tonic-gate boolean_t dir_match, spec_match, raw_match, type_match; 11217c478bd9Sstevel@tonic-gate 11227c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 11237c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_FS)) 11247c478bd9Sstevel@tonic-gate continue; 11257c478bd9Sstevel@tonic-gate dir_match = match_prop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir); 11267c478bd9Sstevel@tonic-gate spec_match = match_prop(cur, DTD_ATTR_SPECIAL, 11277c478bd9Sstevel@tonic-gate tabptr->zone_fs_special); 11287c478bd9Sstevel@tonic-gate raw_match = match_prop(cur, DTD_ATTR_RAW, 11297c478bd9Sstevel@tonic-gate tabptr->zone_fs_raw); 11307c478bd9Sstevel@tonic-gate type_match = match_prop(cur, DTD_ATTR_TYPE, 11317c478bd9Sstevel@tonic-gate tabptr->zone_fs_type); 11327c478bd9Sstevel@tonic-gate if (dir_match && spec_match && raw_match && type_match) { 11337c478bd9Sstevel@tonic-gate xmlUnlinkNode(cur); 11347c478bd9Sstevel@tonic-gate xmlFreeNode(cur); 11357c478bd9Sstevel@tonic-gate return (Z_OK); 11367c478bd9Sstevel@tonic-gate } 11377c478bd9Sstevel@tonic-gate } 11387c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 11397c478bd9Sstevel@tonic-gate } 11407c478bd9Sstevel@tonic-gate 11417c478bd9Sstevel@tonic-gate int 11427c478bd9Sstevel@tonic-gate zonecfg_delete_filesystem(zone_dochandle_t handle, struct zone_fstab *tabptr) 11437c478bd9Sstevel@tonic-gate { 11447c478bd9Sstevel@tonic-gate int err; 11457c478bd9Sstevel@tonic-gate 11467c478bd9Sstevel@tonic-gate if (tabptr == NULL) 11477c478bd9Sstevel@tonic-gate return (Z_INVAL); 11487c478bd9Sstevel@tonic-gate 11497c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 11507c478bd9Sstevel@tonic-gate return (err); 11517c478bd9Sstevel@tonic-gate 11527c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_filesystem_core(handle, tabptr)) != Z_OK) 11537c478bd9Sstevel@tonic-gate return (err); 11547c478bd9Sstevel@tonic-gate 11557c478bd9Sstevel@tonic-gate return (Z_OK); 11567c478bd9Sstevel@tonic-gate } 11577c478bd9Sstevel@tonic-gate 11587c478bd9Sstevel@tonic-gate int 11597c478bd9Sstevel@tonic-gate zonecfg_modify_filesystem( 11607c478bd9Sstevel@tonic-gate zone_dochandle_t handle, 11617c478bd9Sstevel@tonic-gate struct zone_fstab *oldtabptr, 11627c478bd9Sstevel@tonic-gate struct zone_fstab *newtabptr) 11637c478bd9Sstevel@tonic-gate { 11647c478bd9Sstevel@tonic-gate int err; 11657c478bd9Sstevel@tonic-gate 11667c478bd9Sstevel@tonic-gate if (oldtabptr == NULL || newtabptr == NULL) 11677c478bd9Sstevel@tonic-gate return (Z_INVAL); 11687c478bd9Sstevel@tonic-gate 11697c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 11707c478bd9Sstevel@tonic-gate return (err); 11717c478bd9Sstevel@tonic-gate 11727c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_filesystem_core(handle, oldtabptr)) != Z_OK) 11737c478bd9Sstevel@tonic-gate return (err); 11747c478bd9Sstevel@tonic-gate 11757c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_filesystem_core(handle, newtabptr)) != Z_OK) 11767c478bd9Sstevel@tonic-gate return (err); 11777c478bd9Sstevel@tonic-gate 11787c478bd9Sstevel@tonic-gate return (Z_OK); 11797c478bd9Sstevel@tonic-gate } 11807c478bd9Sstevel@tonic-gate 11817c478bd9Sstevel@tonic-gate static int 11827c478bd9Sstevel@tonic-gate zonecfg_delete_ipd_core(zone_dochandle_t handle, struct zone_fstab *tabptr) 11837c478bd9Sstevel@tonic-gate { 11847c478bd9Sstevel@tonic-gate xmlNodePtr cur = handle->zone_dh_cur; 11857c478bd9Sstevel@tonic-gate 11867c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 11877c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_IPD)) 11887c478bd9Sstevel@tonic-gate continue; 11897c478bd9Sstevel@tonic-gate if (match_prop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir)) { 11907c478bd9Sstevel@tonic-gate xmlUnlinkNode(cur); 11917c478bd9Sstevel@tonic-gate xmlFreeNode(cur); 11927c478bd9Sstevel@tonic-gate return (Z_OK); 11937c478bd9Sstevel@tonic-gate } 11947c478bd9Sstevel@tonic-gate } 11957c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 11967c478bd9Sstevel@tonic-gate } 11977c478bd9Sstevel@tonic-gate 11987c478bd9Sstevel@tonic-gate int 11997c478bd9Sstevel@tonic-gate zonecfg_delete_ipd(zone_dochandle_t handle, struct zone_fstab *tabptr) 12007c478bd9Sstevel@tonic-gate { 12017c478bd9Sstevel@tonic-gate int err; 12027c478bd9Sstevel@tonic-gate 12037c478bd9Sstevel@tonic-gate if (tabptr == NULL) 12047c478bd9Sstevel@tonic-gate return (Z_INVAL); 12057c478bd9Sstevel@tonic-gate 12067c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 12077c478bd9Sstevel@tonic-gate return (err); 12087c478bd9Sstevel@tonic-gate 12097c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_ipd_core(handle, tabptr)) != Z_OK) 12107c478bd9Sstevel@tonic-gate return (err); 12117c478bd9Sstevel@tonic-gate 12127c478bd9Sstevel@tonic-gate return (Z_OK); 12137c478bd9Sstevel@tonic-gate } 12147c478bd9Sstevel@tonic-gate 12157c478bd9Sstevel@tonic-gate int 12167c478bd9Sstevel@tonic-gate zonecfg_modify_ipd(zone_dochandle_t handle, struct zone_fstab *oldtabptr, 12177c478bd9Sstevel@tonic-gate struct zone_fstab *newtabptr) 12187c478bd9Sstevel@tonic-gate { 12197c478bd9Sstevel@tonic-gate int err; 12207c478bd9Sstevel@tonic-gate 12217c478bd9Sstevel@tonic-gate if (oldtabptr == NULL || newtabptr == NULL) 12227c478bd9Sstevel@tonic-gate return (Z_INVAL); 12237c478bd9Sstevel@tonic-gate 12247c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 12257c478bd9Sstevel@tonic-gate return (err); 12267c478bd9Sstevel@tonic-gate 12277c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_ipd_core(handle, oldtabptr)) != Z_OK) 12287c478bd9Sstevel@tonic-gate return (err); 12297c478bd9Sstevel@tonic-gate 12307c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_ipd_core(handle, newtabptr)) != Z_OK) 12317c478bd9Sstevel@tonic-gate return (err); 12327c478bd9Sstevel@tonic-gate 12337c478bd9Sstevel@tonic-gate return (Z_OK); 12347c478bd9Sstevel@tonic-gate } 12357c478bd9Sstevel@tonic-gate 12367c478bd9Sstevel@tonic-gate static int 12377c478bd9Sstevel@tonic-gate fetchprop(xmlNodePtr cur, const xmlChar *propname, char *dst, size_t dstsize) 12387c478bd9Sstevel@tonic-gate { 12397c478bd9Sstevel@tonic-gate xmlChar *property; 12407c478bd9Sstevel@tonic-gate size_t srcsize; 12417c478bd9Sstevel@tonic-gate 12427c478bd9Sstevel@tonic-gate if ((property = xmlGetProp(cur, propname)) == NULL) 12437c478bd9Sstevel@tonic-gate return (Z_BAD_PROPERTY); 12447c478bd9Sstevel@tonic-gate srcsize = strlcpy(dst, (char *)property, dstsize); 12457c478bd9Sstevel@tonic-gate xmlFree(property); 12467c478bd9Sstevel@tonic-gate if (srcsize >= dstsize) 12477c478bd9Sstevel@tonic-gate return (Z_TOO_BIG); 12487c478bd9Sstevel@tonic-gate return (Z_OK); 12497c478bd9Sstevel@tonic-gate } 12507c478bd9Sstevel@tonic-gate 12517c478bd9Sstevel@tonic-gate int 12527c478bd9Sstevel@tonic-gate zonecfg_lookup_filesystem( 12537c478bd9Sstevel@tonic-gate zone_dochandle_t handle, 12547c478bd9Sstevel@tonic-gate struct zone_fstab *tabptr) 12557c478bd9Sstevel@tonic-gate { 12567c478bd9Sstevel@tonic-gate xmlNodePtr cur, options, firstmatch; 12577c478bd9Sstevel@tonic-gate int err; 12587c478bd9Sstevel@tonic-gate char dirname[MAXPATHLEN], special[MAXPATHLEN], raw[MAXPATHLEN]; 12597c478bd9Sstevel@tonic-gate char type[FSTYPSZ]; 12607c478bd9Sstevel@tonic-gate char options_str[MAX_MNTOPT_STR]; 12617c478bd9Sstevel@tonic-gate 12627c478bd9Sstevel@tonic-gate if (tabptr == NULL) 12637c478bd9Sstevel@tonic-gate return (Z_INVAL); 12647c478bd9Sstevel@tonic-gate 12657c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 12667c478bd9Sstevel@tonic-gate return (err); 12677c478bd9Sstevel@tonic-gate 12687c478bd9Sstevel@tonic-gate /* 12697c478bd9Sstevel@tonic-gate * Walk the list of children looking for matches on any properties 12707c478bd9Sstevel@tonic-gate * specified in the fstab parameter. If more than one resource 12717c478bd9Sstevel@tonic-gate * matches, we return Z_INSUFFICIENT_SPEC; if none match, we return 12727c478bd9Sstevel@tonic-gate * Z_NO_RESOURCE_ID. 12737c478bd9Sstevel@tonic-gate */ 12747c478bd9Sstevel@tonic-gate cur = handle->zone_dh_cur; 12757c478bd9Sstevel@tonic-gate firstmatch = NULL; 12767c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 12777c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_FS)) 12787c478bd9Sstevel@tonic-gate continue; 12797c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_fs_dir) > 0) { 12807c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_DIR, dirname, 12817c478bd9Sstevel@tonic-gate sizeof (dirname)) == Z_OK) && 12827c478bd9Sstevel@tonic-gate (strcmp(tabptr->zone_fs_dir, dirname) == 0)) { 12837c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 12847c478bd9Sstevel@tonic-gate firstmatch = cur; 12857c478bd9Sstevel@tonic-gate else 12867c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 12877c478bd9Sstevel@tonic-gate } 12887c478bd9Sstevel@tonic-gate } 12897c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_fs_special) > 0) { 12907c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_SPECIAL, special, 12917c478bd9Sstevel@tonic-gate sizeof (special)) == Z_OK)) { 12927c478bd9Sstevel@tonic-gate if (strcmp(tabptr->zone_fs_special, 12937c478bd9Sstevel@tonic-gate special) == 0) { 12947c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 12957c478bd9Sstevel@tonic-gate firstmatch = cur; 12967c478bd9Sstevel@tonic-gate else if (firstmatch != cur) 12977c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 12987c478bd9Sstevel@tonic-gate } else { 12997c478bd9Sstevel@tonic-gate /* 13007c478bd9Sstevel@tonic-gate * If another property matched but this 13017c478bd9Sstevel@tonic-gate * one doesn't then reset firstmatch. 13027c478bd9Sstevel@tonic-gate */ 13037c478bd9Sstevel@tonic-gate if (firstmatch == cur) 13047c478bd9Sstevel@tonic-gate firstmatch = NULL; 13057c478bd9Sstevel@tonic-gate } 13067c478bd9Sstevel@tonic-gate } 13077c478bd9Sstevel@tonic-gate } 13087c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_fs_raw) > 0) { 13097c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_RAW, raw, 13107c478bd9Sstevel@tonic-gate sizeof (raw)) == Z_OK)) { 13117c478bd9Sstevel@tonic-gate if (strcmp(tabptr->zone_fs_raw, raw) == 0) { 13127c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 13137c478bd9Sstevel@tonic-gate firstmatch = cur; 13147c478bd9Sstevel@tonic-gate else if (firstmatch != cur) 13157c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 13167c478bd9Sstevel@tonic-gate } else { 13177c478bd9Sstevel@tonic-gate /* 13187c478bd9Sstevel@tonic-gate * If another property matched but this 13197c478bd9Sstevel@tonic-gate * one doesn't then reset firstmatch. 13207c478bd9Sstevel@tonic-gate */ 13217c478bd9Sstevel@tonic-gate if (firstmatch == cur) 13227c478bd9Sstevel@tonic-gate firstmatch = NULL; 13237c478bd9Sstevel@tonic-gate } 13247c478bd9Sstevel@tonic-gate } 13257c478bd9Sstevel@tonic-gate } 13267c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_fs_type) > 0) { 13277c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_TYPE, type, 13287c478bd9Sstevel@tonic-gate sizeof (type)) == Z_OK)) { 13297c478bd9Sstevel@tonic-gate if (strcmp(tabptr->zone_fs_type, type) == 0) { 13307c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 13317c478bd9Sstevel@tonic-gate firstmatch = cur; 13327c478bd9Sstevel@tonic-gate else if (firstmatch != cur) 13337c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 13347c478bd9Sstevel@tonic-gate } else { 13357c478bd9Sstevel@tonic-gate /* 13367c478bd9Sstevel@tonic-gate * If another property matched but this 13377c478bd9Sstevel@tonic-gate * one doesn't then reset firstmatch. 13387c478bd9Sstevel@tonic-gate */ 13397c478bd9Sstevel@tonic-gate if (firstmatch == cur) 13407c478bd9Sstevel@tonic-gate firstmatch = NULL; 13417c478bd9Sstevel@tonic-gate } 13427c478bd9Sstevel@tonic-gate } 13437c478bd9Sstevel@tonic-gate } 13447c478bd9Sstevel@tonic-gate } 13457c478bd9Sstevel@tonic-gate 13467c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 13477c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 13487c478bd9Sstevel@tonic-gate 13497c478bd9Sstevel@tonic-gate cur = firstmatch; 13507c478bd9Sstevel@tonic-gate 13517c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir, 13527c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_dir))) != Z_OK) 13537c478bd9Sstevel@tonic-gate return (err); 13547c478bd9Sstevel@tonic-gate 13557c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_SPECIAL, tabptr->zone_fs_special, 13567c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_special))) != Z_OK) 13577c478bd9Sstevel@tonic-gate return (err); 13587c478bd9Sstevel@tonic-gate 13597c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_RAW, tabptr->zone_fs_raw, 13607c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_raw))) != Z_OK) 13617c478bd9Sstevel@tonic-gate return (err); 13627c478bd9Sstevel@tonic-gate 13637c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_TYPE, tabptr->zone_fs_type, 13647c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_type))) != Z_OK) 13657c478bd9Sstevel@tonic-gate return (err); 13667c478bd9Sstevel@tonic-gate 13677c478bd9Sstevel@tonic-gate /* options are optional */ 13687c478bd9Sstevel@tonic-gate tabptr->zone_fs_options = NULL; 13697c478bd9Sstevel@tonic-gate for (options = cur->xmlChildrenNode; options != NULL; 13707c478bd9Sstevel@tonic-gate options = options->next) { 13717c478bd9Sstevel@tonic-gate if ((fetchprop(options, DTD_ATTR_NAME, options_str, 13727c478bd9Sstevel@tonic-gate sizeof (options_str)) != Z_OK)) 13737c478bd9Sstevel@tonic-gate break; 13747c478bd9Sstevel@tonic-gate if (zonecfg_add_fs_option(tabptr, options_str) != Z_OK) 13757c478bd9Sstevel@tonic-gate break; 13767c478bd9Sstevel@tonic-gate } 13777c478bd9Sstevel@tonic-gate return (Z_OK); 13787c478bd9Sstevel@tonic-gate } 13797c478bd9Sstevel@tonic-gate 13807c478bd9Sstevel@tonic-gate int 13817c478bd9Sstevel@tonic-gate zonecfg_lookup_ipd(zone_dochandle_t handle, struct zone_fstab *tabptr) 13827c478bd9Sstevel@tonic-gate { 13837c478bd9Sstevel@tonic-gate xmlNodePtr cur, match; 13847c478bd9Sstevel@tonic-gate int err; 13857c478bd9Sstevel@tonic-gate char dirname[MAXPATHLEN]; 13867c478bd9Sstevel@tonic-gate 13877c478bd9Sstevel@tonic-gate if (tabptr == NULL) 13887c478bd9Sstevel@tonic-gate return (Z_INVAL); 13897c478bd9Sstevel@tonic-gate 13907c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 13917c478bd9Sstevel@tonic-gate return (err); 13927c478bd9Sstevel@tonic-gate 13937c478bd9Sstevel@tonic-gate /* 13947c478bd9Sstevel@tonic-gate * General algorithm: 13957c478bd9Sstevel@tonic-gate * Walk the list of children looking for matches on any properties 13967c478bd9Sstevel@tonic-gate * specified in the fstab parameter. If more than one resource 13977c478bd9Sstevel@tonic-gate * matches, we return Z_INSUFFICIENT_SPEC; if none match, we return 13987c478bd9Sstevel@tonic-gate * Z_NO_RESOURCE_ID. 13997c478bd9Sstevel@tonic-gate */ 14007c478bd9Sstevel@tonic-gate cur = handle->zone_dh_cur; 14017c478bd9Sstevel@tonic-gate match = NULL; 14027c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 14037c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_IPD)) 14047c478bd9Sstevel@tonic-gate continue; 14057c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_fs_dir) > 0) { 14067c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_DIR, dirname, 14077c478bd9Sstevel@tonic-gate sizeof (dirname)) == Z_OK) && 14087c478bd9Sstevel@tonic-gate (strcmp(tabptr->zone_fs_dir, dirname) == 0)) { 14097c478bd9Sstevel@tonic-gate if (match == NULL) 14107c478bd9Sstevel@tonic-gate match = cur; 14117c478bd9Sstevel@tonic-gate else 14127c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 14137c478bd9Sstevel@tonic-gate } 14147c478bd9Sstevel@tonic-gate } 14157c478bd9Sstevel@tonic-gate } 14167c478bd9Sstevel@tonic-gate 14177c478bd9Sstevel@tonic-gate if (match == NULL) 14187c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 14197c478bd9Sstevel@tonic-gate 14207c478bd9Sstevel@tonic-gate cur = match; 14217c478bd9Sstevel@tonic-gate 14227c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir, 14237c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_dir))) != Z_OK) 14247c478bd9Sstevel@tonic-gate return (err); 14257c478bd9Sstevel@tonic-gate 14267c478bd9Sstevel@tonic-gate return (Z_OK); 14277c478bd9Sstevel@tonic-gate } 14287c478bd9Sstevel@tonic-gate 14297c478bd9Sstevel@tonic-gate /* 14307c478bd9Sstevel@tonic-gate * Compare two IP addresses in string form. Allow for the possibility that 14317c478bd9Sstevel@tonic-gate * one might have "/<prefix-length>" at the end: allow a match on just the 14327c478bd9Sstevel@tonic-gate * IP address (or host name) part. 14337c478bd9Sstevel@tonic-gate */ 14347c478bd9Sstevel@tonic-gate 14357c478bd9Sstevel@tonic-gate boolean_t 14367c478bd9Sstevel@tonic-gate zonecfg_same_net_address(char *a1, char *a2) 14377c478bd9Sstevel@tonic-gate { 14387c478bd9Sstevel@tonic-gate char *slashp, *slashp1, *slashp2; 14397c478bd9Sstevel@tonic-gate int result; 14407c478bd9Sstevel@tonic-gate 14417c478bd9Sstevel@tonic-gate if (strcmp(a1, a2) == 0) 14427c478bd9Sstevel@tonic-gate return (B_TRUE); 14437c478bd9Sstevel@tonic-gate 14447c478bd9Sstevel@tonic-gate /* 14457c478bd9Sstevel@tonic-gate * If neither has a slash or both do, they need to match to be 14467c478bd9Sstevel@tonic-gate * considered the same, but they did not match above, so fail. 14477c478bd9Sstevel@tonic-gate */ 14487c478bd9Sstevel@tonic-gate slashp1 = strchr(a1, '/'); 14497c478bd9Sstevel@tonic-gate slashp2 = strchr(a2, '/'); 14507c478bd9Sstevel@tonic-gate if ((slashp1 == NULL && slashp2 == NULL) || 14517c478bd9Sstevel@tonic-gate (slashp1 != NULL && slashp2 != NULL)) 14527c478bd9Sstevel@tonic-gate return (B_FALSE); 14537c478bd9Sstevel@tonic-gate 14547c478bd9Sstevel@tonic-gate /* 14557c478bd9Sstevel@tonic-gate * Only one had a slash: pick that one, zero out the slash, compare 14567c478bd9Sstevel@tonic-gate * the "address only" strings, restore the slash, and return the 14577c478bd9Sstevel@tonic-gate * result of the comparison. 14587c478bd9Sstevel@tonic-gate */ 14597c478bd9Sstevel@tonic-gate slashp = (slashp1 == NULL) ? slashp2 : slashp1; 14607c478bd9Sstevel@tonic-gate *slashp = '\0'; 14617c478bd9Sstevel@tonic-gate result = strcmp(a1, a2); 14627c478bd9Sstevel@tonic-gate *slashp = '/'; 14637c478bd9Sstevel@tonic-gate return ((result == 0)); 14647c478bd9Sstevel@tonic-gate } 14657c478bd9Sstevel@tonic-gate 14667c478bd9Sstevel@tonic-gate int 14677c478bd9Sstevel@tonic-gate zonecfg_valid_net_address(char *address, struct lifreq *lifr) 14687c478bd9Sstevel@tonic-gate { 14697c478bd9Sstevel@tonic-gate struct sockaddr_in *sin4; 14707c478bd9Sstevel@tonic-gate struct sockaddr_in6 *sin6; 14717c478bd9Sstevel@tonic-gate struct addrinfo hints, *result; 14727c478bd9Sstevel@tonic-gate char *slashp = strchr(address, '/'); 14737c478bd9Sstevel@tonic-gate 14747c478bd9Sstevel@tonic-gate bzero(lifr, sizeof (struct lifreq)); 14757c478bd9Sstevel@tonic-gate sin4 = (struct sockaddr_in *)&lifr->lifr_addr; 14767c478bd9Sstevel@tonic-gate sin6 = (struct sockaddr_in6 *)&lifr->lifr_addr; 14777c478bd9Sstevel@tonic-gate if (slashp != NULL) 14787c478bd9Sstevel@tonic-gate *slashp = '\0'; 14797c478bd9Sstevel@tonic-gate if (inet_pton(AF_INET, address, &sin4->sin_addr) == 1) { 14807c478bd9Sstevel@tonic-gate sin4->sin_family = AF_INET; 14817c478bd9Sstevel@tonic-gate } else if (inet_pton(AF_INET6, address, &sin6->sin6_addr) == 1) { 14827c478bd9Sstevel@tonic-gate if (slashp == NULL) 14837c478bd9Sstevel@tonic-gate return (Z_IPV6_ADDR_PREFIX_LEN); 14847c478bd9Sstevel@tonic-gate sin6->sin6_family = AF_INET6; 14857c478bd9Sstevel@tonic-gate } else { 14867c478bd9Sstevel@tonic-gate /* "address" may be a host name */ 14877c478bd9Sstevel@tonic-gate (void) memset(&hints, 0, sizeof (hints)); 14887c478bd9Sstevel@tonic-gate hints.ai_family = PF_INET; 14897c478bd9Sstevel@tonic-gate if (getaddrinfo(address, NULL, &hints, &result) != 0) 14907c478bd9Sstevel@tonic-gate return (Z_BOGUS_ADDRESS); 14917c478bd9Sstevel@tonic-gate sin4->sin_family = result->ai_family; 1492a1be23daSdp 14937c478bd9Sstevel@tonic-gate (void) memcpy(&sin4->sin_addr, 14947c478bd9Sstevel@tonic-gate /* LINTED E_BAD_PTR_CAST_ALIGN */ 14957c478bd9Sstevel@tonic-gate &((struct sockaddr_in *)result->ai_addr)->sin_addr, 14967c478bd9Sstevel@tonic-gate sizeof (struct in_addr)); 1497a1be23daSdp 14987c478bd9Sstevel@tonic-gate freeaddrinfo(result); 14997c478bd9Sstevel@tonic-gate } 15007c478bd9Sstevel@tonic-gate return (Z_OK); 15017c478bd9Sstevel@tonic-gate } 15027c478bd9Sstevel@tonic-gate 15037c478bd9Sstevel@tonic-gate int 15047c478bd9Sstevel@tonic-gate zonecfg_lookup_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr) 15057c478bd9Sstevel@tonic-gate { 15067c478bd9Sstevel@tonic-gate xmlNodePtr cur, firstmatch; 15077c478bd9Sstevel@tonic-gate int err; 15087c478bd9Sstevel@tonic-gate char address[INET6_ADDRSTRLEN], physical[LIFNAMSIZ]; 15097c478bd9Sstevel@tonic-gate 15107c478bd9Sstevel@tonic-gate if (tabptr == NULL) 15117c478bd9Sstevel@tonic-gate return (Z_INVAL); 15127c478bd9Sstevel@tonic-gate 15137c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 15147c478bd9Sstevel@tonic-gate return (err); 15157c478bd9Sstevel@tonic-gate 15167c478bd9Sstevel@tonic-gate cur = handle->zone_dh_cur; 15177c478bd9Sstevel@tonic-gate firstmatch = NULL; 15187c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 15197c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_NET)) 15207c478bd9Sstevel@tonic-gate continue; 15217c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_nwif_physical) > 0) { 15227c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_PHYSICAL, physical, 15237c478bd9Sstevel@tonic-gate sizeof (physical)) == Z_OK) && 15247c478bd9Sstevel@tonic-gate (strcmp(tabptr->zone_nwif_physical, 15257c478bd9Sstevel@tonic-gate physical) == 0)) { 15267c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 15277c478bd9Sstevel@tonic-gate firstmatch = cur; 15287c478bd9Sstevel@tonic-gate else 15297c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 15307c478bd9Sstevel@tonic-gate } 15317c478bd9Sstevel@tonic-gate } 15327c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_nwif_address) > 0) { 15337c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_ADDRESS, address, 15347c478bd9Sstevel@tonic-gate sizeof (address)) == Z_OK)) { 15357c478bd9Sstevel@tonic-gate if (zonecfg_same_net_address( 15367c478bd9Sstevel@tonic-gate tabptr->zone_nwif_address, address)) { 15377c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 15387c478bd9Sstevel@tonic-gate firstmatch = cur; 15397c478bd9Sstevel@tonic-gate else if (firstmatch != cur) 15407c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 15417c478bd9Sstevel@tonic-gate } else { 15427c478bd9Sstevel@tonic-gate /* 15437c478bd9Sstevel@tonic-gate * If another property matched but this 15447c478bd9Sstevel@tonic-gate * one doesn't then reset firstmatch. 15457c478bd9Sstevel@tonic-gate */ 15467c478bd9Sstevel@tonic-gate if (firstmatch == cur) 15477c478bd9Sstevel@tonic-gate firstmatch = NULL; 15487c478bd9Sstevel@tonic-gate } 15497c478bd9Sstevel@tonic-gate } 15507c478bd9Sstevel@tonic-gate } 15517c478bd9Sstevel@tonic-gate } 15527c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 15537c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 15547c478bd9Sstevel@tonic-gate 15557c478bd9Sstevel@tonic-gate cur = firstmatch; 15567c478bd9Sstevel@tonic-gate 15577c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_PHYSICAL, tabptr->zone_nwif_physical, 15587c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_nwif_physical))) != Z_OK) 15597c478bd9Sstevel@tonic-gate return (err); 15607c478bd9Sstevel@tonic-gate 15617c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_ADDRESS, tabptr->zone_nwif_address, 15627c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_nwif_address))) != Z_OK) 15637c478bd9Sstevel@tonic-gate return (err); 15647c478bd9Sstevel@tonic-gate 15657c478bd9Sstevel@tonic-gate return (Z_OK); 15667c478bd9Sstevel@tonic-gate } 15677c478bd9Sstevel@tonic-gate 15687c478bd9Sstevel@tonic-gate static int 15697c478bd9Sstevel@tonic-gate zonecfg_add_nwif_core(zone_dochandle_t handle, struct zone_nwiftab *tabptr) 15707c478bd9Sstevel@tonic-gate { 15717c478bd9Sstevel@tonic-gate xmlNodePtr newnode, cur = handle->zone_dh_cur; 15727c478bd9Sstevel@tonic-gate int err; 15737c478bd9Sstevel@tonic-gate 15747c478bd9Sstevel@tonic-gate newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_NET, NULL); 1575a1be23daSdp if ((err = newprop(newnode, DTD_ATTR_ADDRESS, 15767c478bd9Sstevel@tonic-gate tabptr->zone_nwif_address)) != Z_OK) 15777c478bd9Sstevel@tonic-gate return (err); 1578a1be23daSdp if ((err = newprop(newnode, DTD_ATTR_PHYSICAL, 15797c478bd9Sstevel@tonic-gate tabptr->zone_nwif_physical)) != Z_OK) 15807c478bd9Sstevel@tonic-gate return (err); 15817c478bd9Sstevel@tonic-gate return (Z_OK); 15827c478bd9Sstevel@tonic-gate } 15837c478bd9Sstevel@tonic-gate 15847c478bd9Sstevel@tonic-gate int 15857c478bd9Sstevel@tonic-gate zonecfg_add_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr) 15867c478bd9Sstevel@tonic-gate { 15877c478bd9Sstevel@tonic-gate int err; 15887c478bd9Sstevel@tonic-gate 15897c478bd9Sstevel@tonic-gate if (tabptr == NULL) 15907c478bd9Sstevel@tonic-gate return (Z_INVAL); 15917c478bd9Sstevel@tonic-gate 15927c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 15937c478bd9Sstevel@tonic-gate return (err); 15947c478bd9Sstevel@tonic-gate 15957c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_nwif_core(handle, tabptr)) != Z_OK) 15967c478bd9Sstevel@tonic-gate return (err); 15977c478bd9Sstevel@tonic-gate 15987c478bd9Sstevel@tonic-gate return (Z_OK); 15997c478bd9Sstevel@tonic-gate } 16007c478bd9Sstevel@tonic-gate 16017c478bd9Sstevel@tonic-gate static int 16027c478bd9Sstevel@tonic-gate zonecfg_delete_nwif_core(zone_dochandle_t handle, struct zone_nwiftab *tabptr) 16037c478bd9Sstevel@tonic-gate { 16047c478bd9Sstevel@tonic-gate xmlNodePtr cur = handle->zone_dh_cur; 16057c478bd9Sstevel@tonic-gate boolean_t addr_match, phys_match; 16067c478bd9Sstevel@tonic-gate 16077c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 16087c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_NET)) 16097c478bd9Sstevel@tonic-gate continue; 16107c478bd9Sstevel@tonic-gate 16117c478bd9Sstevel@tonic-gate addr_match = match_prop(cur, DTD_ATTR_ADDRESS, 16127c478bd9Sstevel@tonic-gate tabptr->zone_nwif_address); 16137c478bd9Sstevel@tonic-gate phys_match = match_prop(cur, DTD_ATTR_PHYSICAL, 16147c478bd9Sstevel@tonic-gate tabptr->zone_nwif_physical); 16157c478bd9Sstevel@tonic-gate 16167c478bd9Sstevel@tonic-gate if (addr_match && phys_match) { 16177c478bd9Sstevel@tonic-gate xmlUnlinkNode(cur); 16187c478bd9Sstevel@tonic-gate xmlFreeNode(cur); 16197c478bd9Sstevel@tonic-gate return (Z_OK); 16207c478bd9Sstevel@tonic-gate } 16217c478bd9Sstevel@tonic-gate } 16227c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 16237c478bd9Sstevel@tonic-gate } 16247c478bd9Sstevel@tonic-gate 16257c478bd9Sstevel@tonic-gate int 16267c478bd9Sstevel@tonic-gate zonecfg_delete_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr) 16277c478bd9Sstevel@tonic-gate { 16287c478bd9Sstevel@tonic-gate int err; 16297c478bd9Sstevel@tonic-gate 16307c478bd9Sstevel@tonic-gate if (tabptr == NULL) 16317c478bd9Sstevel@tonic-gate return (Z_INVAL); 16327c478bd9Sstevel@tonic-gate 16337c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 16347c478bd9Sstevel@tonic-gate return (err); 16357c478bd9Sstevel@tonic-gate 16367c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_nwif_core(handle, tabptr)) != Z_OK) 16377c478bd9Sstevel@tonic-gate return (err); 16387c478bd9Sstevel@tonic-gate 16397c478bd9Sstevel@tonic-gate return (Z_OK); 16407c478bd9Sstevel@tonic-gate } 16417c478bd9Sstevel@tonic-gate 16427c478bd9Sstevel@tonic-gate int 16437c478bd9Sstevel@tonic-gate zonecfg_modify_nwif( 16447c478bd9Sstevel@tonic-gate zone_dochandle_t handle, 16457c478bd9Sstevel@tonic-gate struct zone_nwiftab *oldtabptr, 16467c478bd9Sstevel@tonic-gate struct zone_nwiftab *newtabptr) 16477c478bd9Sstevel@tonic-gate { 16487c478bd9Sstevel@tonic-gate int err; 16497c478bd9Sstevel@tonic-gate 16507c478bd9Sstevel@tonic-gate if (oldtabptr == NULL || newtabptr == NULL) 16517c478bd9Sstevel@tonic-gate return (Z_INVAL); 16527c478bd9Sstevel@tonic-gate 16537c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 16547c478bd9Sstevel@tonic-gate return (err); 16557c478bd9Sstevel@tonic-gate 16567c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_nwif_core(handle, oldtabptr)) != Z_OK) 16577c478bd9Sstevel@tonic-gate return (err); 16587c478bd9Sstevel@tonic-gate 16597c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_nwif_core(handle, newtabptr)) != Z_OK) 16607c478bd9Sstevel@tonic-gate return (err); 16617c478bd9Sstevel@tonic-gate 16627c478bd9Sstevel@tonic-gate return (Z_OK); 16637c478bd9Sstevel@tonic-gate } 16647c478bd9Sstevel@tonic-gate 16657c478bd9Sstevel@tonic-gate int 16667c478bd9Sstevel@tonic-gate zonecfg_lookup_dev(zone_dochandle_t handle, struct zone_devtab *tabptr) 16677c478bd9Sstevel@tonic-gate { 16687c478bd9Sstevel@tonic-gate xmlNodePtr cur, firstmatch; 16697c478bd9Sstevel@tonic-gate int err; 16707c478bd9Sstevel@tonic-gate char match[MAXPATHLEN]; 16717c478bd9Sstevel@tonic-gate 16727c478bd9Sstevel@tonic-gate if (tabptr == NULL) 16737c478bd9Sstevel@tonic-gate return (Z_INVAL); 16747c478bd9Sstevel@tonic-gate 16757c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 16767c478bd9Sstevel@tonic-gate return (err); 16777c478bd9Sstevel@tonic-gate 16787c478bd9Sstevel@tonic-gate cur = handle->zone_dh_cur; 16797c478bd9Sstevel@tonic-gate firstmatch = NULL; 16807c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 16817c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_DEVICE)) 16827c478bd9Sstevel@tonic-gate continue; 16837c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_dev_match) == 0) 16847c478bd9Sstevel@tonic-gate continue; 16857c478bd9Sstevel@tonic-gate 16867c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_MATCH, match, 16877c478bd9Sstevel@tonic-gate sizeof (match)) == Z_OK)) { 16887c478bd9Sstevel@tonic-gate if (strcmp(tabptr->zone_dev_match, 16897c478bd9Sstevel@tonic-gate match) == 0) { 16907c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 16917c478bd9Sstevel@tonic-gate firstmatch = cur; 16927c478bd9Sstevel@tonic-gate else if (firstmatch != cur) 16937c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 16947c478bd9Sstevel@tonic-gate } else { 16957c478bd9Sstevel@tonic-gate /* 16967c478bd9Sstevel@tonic-gate * If another property matched but this 16977c478bd9Sstevel@tonic-gate * one doesn't then reset firstmatch. 16987c478bd9Sstevel@tonic-gate */ 16997c478bd9Sstevel@tonic-gate if (firstmatch == cur) 17007c478bd9Sstevel@tonic-gate firstmatch = NULL; 17017c478bd9Sstevel@tonic-gate } 17027c478bd9Sstevel@tonic-gate } 17037c478bd9Sstevel@tonic-gate } 17047c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 17057c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 17067c478bd9Sstevel@tonic-gate 17077c478bd9Sstevel@tonic-gate cur = firstmatch; 17087c478bd9Sstevel@tonic-gate 17097c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_MATCH, tabptr->zone_dev_match, 17107c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_dev_match))) != Z_OK) 17117c478bd9Sstevel@tonic-gate return (err); 17127c478bd9Sstevel@tonic-gate 17137c478bd9Sstevel@tonic-gate return (Z_OK); 17147c478bd9Sstevel@tonic-gate } 17157c478bd9Sstevel@tonic-gate 17167c478bd9Sstevel@tonic-gate static int 17177c478bd9Sstevel@tonic-gate zonecfg_add_dev_core(zone_dochandle_t handle, struct zone_devtab *tabptr) 17187c478bd9Sstevel@tonic-gate { 17197c478bd9Sstevel@tonic-gate xmlNodePtr newnode, cur = handle->zone_dh_cur; 17207c478bd9Sstevel@tonic-gate int err; 17217c478bd9Sstevel@tonic-gate 17227c478bd9Sstevel@tonic-gate newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_DEVICE, NULL); 17237c478bd9Sstevel@tonic-gate 1724a1be23daSdp if ((err = newprop(newnode, DTD_ATTR_MATCH, 17257c478bd9Sstevel@tonic-gate tabptr->zone_dev_match)) != Z_OK) 17267c478bd9Sstevel@tonic-gate return (err); 17277c478bd9Sstevel@tonic-gate 17287c478bd9Sstevel@tonic-gate return (Z_OK); 17297c478bd9Sstevel@tonic-gate } 17307c478bd9Sstevel@tonic-gate 17317c478bd9Sstevel@tonic-gate int 17327c478bd9Sstevel@tonic-gate zonecfg_add_dev(zone_dochandle_t handle, struct zone_devtab *tabptr) 17337c478bd9Sstevel@tonic-gate { 17347c478bd9Sstevel@tonic-gate int err; 17357c478bd9Sstevel@tonic-gate 17367c478bd9Sstevel@tonic-gate if (tabptr == NULL) 17377c478bd9Sstevel@tonic-gate return (Z_INVAL); 17387c478bd9Sstevel@tonic-gate 17397c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 17407c478bd9Sstevel@tonic-gate return (err); 17417c478bd9Sstevel@tonic-gate 17427c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_dev_core(handle, tabptr)) != Z_OK) 17437c478bd9Sstevel@tonic-gate return (err); 17447c478bd9Sstevel@tonic-gate 17457c478bd9Sstevel@tonic-gate return (Z_OK); 17467c478bd9Sstevel@tonic-gate } 17477c478bd9Sstevel@tonic-gate 17487c478bd9Sstevel@tonic-gate static int 17497c478bd9Sstevel@tonic-gate zonecfg_delete_dev_core(zone_dochandle_t handle, struct zone_devtab *tabptr) 17507c478bd9Sstevel@tonic-gate { 17517c478bd9Sstevel@tonic-gate xmlNodePtr cur = handle->zone_dh_cur; 17527c478bd9Sstevel@tonic-gate int match_match; 17537c478bd9Sstevel@tonic-gate 17547c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 17557c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_DEVICE)) 17567c478bd9Sstevel@tonic-gate continue; 17577c478bd9Sstevel@tonic-gate 17587c478bd9Sstevel@tonic-gate match_match = match_prop(cur, DTD_ATTR_MATCH, 17597c478bd9Sstevel@tonic-gate tabptr->zone_dev_match); 17607c478bd9Sstevel@tonic-gate 17617c478bd9Sstevel@tonic-gate if (match_match) { 17627c478bd9Sstevel@tonic-gate xmlUnlinkNode(cur); 17637c478bd9Sstevel@tonic-gate xmlFreeNode(cur); 17647c478bd9Sstevel@tonic-gate return (Z_OK); 17657c478bd9Sstevel@tonic-gate } 17667c478bd9Sstevel@tonic-gate } 17677c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 17687c478bd9Sstevel@tonic-gate } 17697c478bd9Sstevel@tonic-gate 17707c478bd9Sstevel@tonic-gate int 17717c478bd9Sstevel@tonic-gate zonecfg_delete_dev(zone_dochandle_t handle, struct zone_devtab *tabptr) 17727c478bd9Sstevel@tonic-gate { 17737c478bd9Sstevel@tonic-gate int err; 17747c478bd9Sstevel@tonic-gate 17757c478bd9Sstevel@tonic-gate if (tabptr == NULL) 17767c478bd9Sstevel@tonic-gate return (Z_INVAL); 17777c478bd9Sstevel@tonic-gate 17787c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 17797c478bd9Sstevel@tonic-gate return (err); 17807c478bd9Sstevel@tonic-gate 17817c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_dev_core(handle, tabptr)) != Z_OK) 17827c478bd9Sstevel@tonic-gate return (err); 17837c478bd9Sstevel@tonic-gate 17847c478bd9Sstevel@tonic-gate return (Z_OK); 17857c478bd9Sstevel@tonic-gate } 17867c478bd9Sstevel@tonic-gate 17877c478bd9Sstevel@tonic-gate int 17887c478bd9Sstevel@tonic-gate zonecfg_modify_dev( 17897c478bd9Sstevel@tonic-gate zone_dochandle_t handle, 17907c478bd9Sstevel@tonic-gate struct zone_devtab *oldtabptr, 17917c478bd9Sstevel@tonic-gate struct zone_devtab *newtabptr) 17927c478bd9Sstevel@tonic-gate { 17937c478bd9Sstevel@tonic-gate int err; 17947c478bd9Sstevel@tonic-gate 17957c478bd9Sstevel@tonic-gate if (oldtabptr == NULL || newtabptr == NULL) 17967c478bd9Sstevel@tonic-gate return (Z_INVAL); 17977c478bd9Sstevel@tonic-gate 17987c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 17997c478bd9Sstevel@tonic-gate return (err); 18007c478bd9Sstevel@tonic-gate 18017c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_dev_core(handle, oldtabptr)) != Z_OK) 18027c478bd9Sstevel@tonic-gate return (err); 18037c478bd9Sstevel@tonic-gate 18047c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_dev_core(handle, newtabptr)) != Z_OK) 18057c478bd9Sstevel@tonic-gate return (err); 18067c478bd9Sstevel@tonic-gate 18077c478bd9Sstevel@tonic-gate return (Z_OK); 18087c478bd9Sstevel@tonic-gate } 18097c478bd9Sstevel@tonic-gate 18107c478bd9Sstevel@tonic-gate /* 18117c478bd9Sstevel@tonic-gate * This is the set of devices which must be present in every zone. Users 18127c478bd9Sstevel@tonic-gate * can augment this list with additional device rules in their zone 18137c478bd9Sstevel@tonic-gate * configuration, but at present cannot remove any of the this set of 18147c478bd9Sstevel@tonic-gate * standard devices. All matching is done by /dev pathname (the "/dev" 18157c478bd9Sstevel@tonic-gate * part is implicit. Try to keep rules which match a large number of 18167c478bd9Sstevel@tonic-gate * devices (like the pts rule) first. 18177c478bd9Sstevel@tonic-gate */ 18187c478bd9Sstevel@tonic-gate static const char *standard_devs[] = { 18197c478bd9Sstevel@tonic-gate "pts/*", 18207c478bd9Sstevel@tonic-gate "ptmx", 18217c478bd9Sstevel@tonic-gate "random", 18227c478bd9Sstevel@tonic-gate "urandom", 18237c478bd9Sstevel@tonic-gate "poll", 18247c478bd9Sstevel@tonic-gate "pool", 18257c478bd9Sstevel@tonic-gate "kstat", 18267c478bd9Sstevel@tonic-gate "zero", 18277c478bd9Sstevel@tonic-gate "null", 18287c478bd9Sstevel@tonic-gate "crypto", 18297c478bd9Sstevel@tonic-gate "cryptoadm", 18307c478bd9Sstevel@tonic-gate "ticots", 18317c478bd9Sstevel@tonic-gate "ticotsord", 18327c478bd9Sstevel@tonic-gate "ticlts", 18337c478bd9Sstevel@tonic-gate "lo0", 18347c478bd9Sstevel@tonic-gate "lo1", 18357c478bd9Sstevel@tonic-gate "lo2", 18367c478bd9Sstevel@tonic-gate "lo3", 18377c478bd9Sstevel@tonic-gate "sad/user", 18387c478bd9Sstevel@tonic-gate "tty", 18397c478bd9Sstevel@tonic-gate "logindmux", 18407c478bd9Sstevel@tonic-gate "log", 18417c478bd9Sstevel@tonic-gate "conslog", 18427c478bd9Sstevel@tonic-gate "arp", 18437c478bd9Sstevel@tonic-gate "tcp", 18447c478bd9Sstevel@tonic-gate "tcp6", 18457c478bd9Sstevel@tonic-gate "udp", 18467c478bd9Sstevel@tonic-gate "udp6", 18477c478bd9Sstevel@tonic-gate "sysevent", 18487c478bd9Sstevel@tonic-gate #ifdef __sparc 18497c478bd9Sstevel@tonic-gate "openprom", 18507c478bd9Sstevel@tonic-gate #endif 18517c478bd9Sstevel@tonic-gate "cpu/self/cpuid", 18527c478bd9Sstevel@tonic-gate "dtrace/helper", 18537c478bd9Sstevel@tonic-gate NULL 18547c478bd9Sstevel@tonic-gate }; 18557c478bd9Sstevel@tonic-gate 18567c478bd9Sstevel@tonic-gate /* 18577c478bd9Sstevel@tonic-gate * This function finds everything mounted under a zone's rootpath. 18587c478bd9Sstevel@tonic-gate * This returns the number of mounts under rootpath, or -1 on error. 18597c478bd9Sstevel@tonic-gate * callback is called once per mount found with the first argument 18607c478bd9Sstevel@tonic-gate * pointing to the mount point. 18617c478bd9Sstevel@tonic-gate * 18627c478bd9Sstevel@tonic-gate * If the callback function returns non-zero zonecfg_find_mounts 18637c478bd9Sstevel@tonic-gate * aborts with an error. 18647c478bd9Sstevel@tonic-gate */ 18657c478bd9Sstevel@tonic-gate 18667c478bd9Sstevel@tonic-gate int 18677c478bd9Sstevel@tonic-gate zonecfg_find_mounts(char *rootpath, int (*callback)(const char *, void *), 18687c478bd9Sstevel@tonic-gate void *priv) { 18697c478bd9Sstevel@tonic-gate FILE *mnttab; 18707c478bd9Sstevel@tonic-gate struct mnttab m; 18717c478bd9Sstevel@tonic-gate size_t l; 18727c478bd9Sstevel@tonic-gate int rv = 0; 18737c478bd9Sstevel@tonic-gate 18747c478bd9Sstevel@tonic-gate assert(rootpath != NULL); 18757c478bd9Sstevel@tonic-gate 18767c478bd9Sstevel@tonic-gate l = strlen(rootpath); 18777c478bd9Sstevel@tonic-gate 18787c478bd9Sstevel@tonic-gate mnttab = fopen("/etc/mnttab", "r"); 18797c478bd9Sstevel@tonic-gate 18807c478bd9Sstevel@tonic-gate if (mnttab == NULL) 18817c478bd9Sstevel@tonic-gate return (-1); 18827c478bd9Sstevel@tonic-gate 18837c478bd9Sstevel@tonic-gate if (ioctl(fileno(mnttab), MNTIOC_SHOWHIDDEN, NULL) < 0) { 18847c478bd9Sstevel@tonic-gate rv = -1; 18857c478bd9Sstevel@tonic-gate goto out; 18867c478bd9Sstevel@tonic-gate } 18877c478bd9Sstevel@tonic-gate 18887c478bd9Sstevel@tonic-gate while (!getmntent(mnttab, &m)) { 18897c478bd9Sstevel@tonic-gate if ((strncmp(rootpath, m.mnt_mountp, l) == 0) && 18907c478bd9Sstevel@tonic-gate (m.mnt_mountp[l] == '/')) { 18917c478bd9Sstevel@tonic-gate rv++; 18927c478bd9Sstevel@tonic-gate if (callback == NULL) 18937c478bd9Sstevel@tonic-gate continue; 18947c478bd9Sstevel@tonic-gate if (callback(m.mnt_mountp, priv)) { 18957c478bd9Sstevel@tonic-gate rv = -1; 18967c478bd9Sstevel@tonic-gate goto out; 18977c478bd9Sstevel@tonic-gate 18987c478bd9Sstevel@tonic-gate } 18997c478bd9Sstevel@tonic-gate } 19007c478bd9Sstevel@tonic-gate } 19017c478bd9Sstevel@tonic-gate 19027c478bd9Sstevel@tonic-gate out: 19037c478bd9Sstevel@tonic-gate (void) fclose(mnttab); 19047c478bd9Sstevel@tonic-gate return (rv); 19057c478bd9Sstevel@tonic-gate } 19067c478bd9Sstevel@tonic-gate 19077c478bd9Sstevel@tonic-gate /* 19087c478bd9Sstevel@tonic-gate * This routine is used to determine if a given device should appear in the 19097c478bd9Sstevel@tonic-gate * zone represented by 'handle'. First it consults the list of "standard" 19107c478bd9Sstevel@tonic-gate * zone devices. Then it scans the user-supplied device entries. 19117c478bd9Sstevel@tonic-gate */ 19127c478bd9Sstevel@tonic-gate int 19137c478bd9Sstevel@tonic-gate zonecfg_match_dev(zone_dochandle_t handle, char *devpath, 19147c478bd9Sstevel@tonic-gate struct zone_devtab *out_match) 19157c478bd9Sstevel@tonic-gate { 19167c478bd9Sstevel@tonic-gate int err; 19177c478bd9Sstevel@tonic-gate boolean_t found = B_FALSE; 19187c478bd9Sstevel@tonic-gate char match[MAXPATHLEN]; 19197c478bd9Sstevel@tonic-gate const char **stdmatch; 19207c478bd9Sstevel@tonic-gate xmlNodePtr cur; 19217c478bd9Sstevel@tonic-gate 19227c478bd9Sstevel@tonic-gate if (handle == NULL || devpath == NULL) 19237c478bd9Sstevel@tonic-gate return (Z_INVAL); 19247c478bd9Sstevel@tonic-gate 19257c478bd9Sstevel@tonic-gate /* 19267c478bd9Sstevel@tonic-gate * Check the "standard" devices which we require to be present. 19277c478bd9Sstevel@tonic-gate */ 19287c478bd9Sstevel@tonic-gate for (stdmatch = &standard_devs[0]; *stdmatch != NULL; stdmatch++) { 19297c478bd9Sstevel@tonic-gate /* 19307c478bd9Sstevel@tonic-gate * fnmatch gives us simple but powerful shell-style matching. 19317c478bd9Sstevel@tonic-gate */ 19327c478bd9Sstevel@tonic-gate if (fnmatch(*stdmatch, devpath, FNM_PATHNAME) == 0) { 19337c478bd9Sstevel@tonic-gate if (!out_match) 19347c478bd9Sstevel@tonic-gate return (Z_OK); 19357c478bd9Sstevel@tonic-gate (void) snprintf(out_match->zone_dev_match, 19367c478bd9Sstevel@tonic-gate sizeof (out_match->zone_dev_match), 19377c478bd9Sstevel@tonic-gate "/dev/%s", *stdmatch); 19387c478bd9Sstevel@tonic-gate return (Z_OK); 19397c478bd9Sstevel@tonic-gate } 19407c478bd9Sstevel@tonic-gate } 19417c478bd9Sstevel@tonic-gate 19427c478bd9Sstevel@tonic-gate /* 19437c478bd9Sstevel@tonic-gate * We got no hits in the set of standard devices. On to the user 19447c478bd9Sstevel@tonic-gate * supplied ones. 19457c478bd9Sstevel@tonic-gate */ 19467c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) { 19477c478bd9Sstevel@tonic-gate handle->zone_dh_cur = NULL; 19487c478bd9Sstevel@tonic-gate return (err); 19497c478bd9Sstevel@tonic-gate } 19507c478bd9Sstevel@tonic-gate 19517c478bd9Sstevel@tonic-gate cur = handle->zone_dh_cur; 19527c478bd9Sstevel@tonic-gate cur = cur->xmlChildrenNode; 19537c478bd9Sstevel@tonic-gate if (cur == NULL) 19547c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 19557c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur; 19567c478bd9Sstevel@tonic-gate 19577c478bd9Sstevel@tonic-gate for (; cur != NULL; cur = cur->next) { 19587c478bd9Sstevel@tonic-gate char *m; 19597c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_DEVICE) != 0) 19607c478bd9Sstevel@tonic-gate continue; 19617c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_MATCH, match, 19627c478bd9Sstevel@tonic-gate sizeof (match))) != Z_OK) { 19637c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 19647c478bd9Sstevel@tonic-gate return (err); 19657c478bd9Sstevel@tonic-gate } 19667c478bd9Sstevel@tonic-gate m = match; 19677c478bd9Sstevel@tonic-gate /* 19687c478bd9Sstevel@tonic-gate * fnmatch gives us simple but powerful shell-style matching; 19697c478bd9Sstevel@tonic-gate * but first, we need to strip out /dev/ from the matching rule. 19707c478bd9Sstevel@tonic-gate */ 19717c478bd9Sstevel@tonic-gate if (strncmp(m, "/dev/", 5) == 0) 19727c478bd9Sstevel@tonic-gate m += 5; 19737c478bd9Sstevel@tonic-gate 19747c478bd9Sstevel@tonic-gate if (fnmatch(m, devpath, FNM_PATHNAME) == 0) { 19757c478bd9Sstevel@tonic-gate found = B_TRUE; 19767c478bd9Sstevel@tonic-gate break; 19777c478bd9Sstevel@tonic-gate } 19787c478bd9Sstevel@tonic-gate } 19797c478bd9Sstevel@tonic-gate 19807c478bd9Sstevel@tonic-gate if (!found) 19817c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 19827c478bd9Sstevel@tonic-gate 19837c478bd9Sstevel@tonic-gate if (!out_match) 19847c478bd9Sstevel@tonic-gate return (Z_OK); 19857c478bd9Sstevel@tonic-gate 19867c478bd9Sstevel@tonic-gate (void) strlcpy(out_match->zone_dev_match, match, 19877c478bd9Sstevel@tonic-gate sizeof (out_match->zone_dev_match)); 19887c478bd9Sstevel@tonic-gate return (Z_OK); 19897c478bd9Sstevel@tonic-gate } 19907c478bd9Sstevel@tonic-gate 19917c478bd9Sstevel@tonic-gate int 19927c478bd9Sstevel@tonic-gate zonecfg_lookup_attr(zone_dochandle_t handle, struct zone_attrtab *tabptr) 19937c478bd9Sstevel@tonic-gate { 19947c478bd9Sstevel@tonic-gate xmlNodePtr cur, firstmatch; 19957c478bd9Sstevel@tonic-gate int err; 19967c478bd9Sstevel@tonic-gate char name[MAXNAMELEN], type[MAXNAMELEN], value[MAXNAMELEN]; 19977c478bd9Sstevel@tonic-gate 19987c478bd9Sstevel@tonic-gate if (tabptr == NULL) 19997c478bd9Sstevel@tonic-gate return (Z_INVAL); 20007c478bd9Sstevel@tonic-gate 20017c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 20027c478bd9Sstevel@tonic-gate return (err); 20037c478bd9Sstevel@tonic-gate 20047c478bd9Sstevel@tonic-gate cur = handle->zone_dh_cur; 20057c478bd9Sstevel@tonic-gate firstmatch = NULL; 20067c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 20077c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_ATTR)) 20087c478bd9Sstevel@tonic-gate continue; 20097c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_attr_name) > 0) { 20107c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_NAME, name, 20117c478bd9Sstevel@tonic-gate sizeof (name)) == Z_OK) && 20127c478bd9Sstevel@tonic-gate (strcmp(tabptr->zone_attr_name, name) == 0)) { 20137c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 20147c478bd9Sstevel@tonic-gate firstmatch = cur; 20157c478bd9Sstevel@tonic-gate else 20167c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 20177c478bd9Sstevel@tonic-gate } 20187c478bd9Sstevel@tonic-gate } 20197c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_attr_type) > 0) { 20207c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_TYPE, type, 20217c478bd9Sstevel@tonic-gate sizeof (type)) == Z_OK)) { 20227c478bd9Sstevel@tonic-gate if (strcmp(tabptr->zone_attr_type, type) == 0) { 20237c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 20247c478bd9Sstevel@tonic-gate firstmatch = cur; 20257c478bd9Sstevel@tonic-gate else if (firstmatch != cur) 20267c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 20277c478bd9Sstevel@tonic-gate } else { 20287c478bd9Sstevel@tonic-gate /* 20297c478bd9Sstevel@tonic-gate * If another property matched but this 20307c478bd9Sstevel@tonic-gate * one doesn't then reset firstmatch. 20317c478bd9Sstevel@tonic-gate */ 20327c478bd9Sstevel@tonic-gate if (firstmatch == cur) 20337c478bd9Sstevel@tonic-gate firstmatch = NULL; 20347c478bd9Sstevel@tonic-gate } 20357c478bd9Sstevel@tonic-gate } 20367c478bd9Sstevel@tonic-gate } 20377c478bd9Sstevel@tonic-gate if (strlen(tabptr->zone_attr_value) > 0) { 20387c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_VALUE, value, 20397c478bd9Sstevel@tonic-gate sizeof (value)) == Z_OK)) { 20407c478bd9Sstevel@tonic-gate if (strcmp(tabptr->zone_attr_value, value) == 20417c478bd9Sstevel@tonic-gate 0) { 20427c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 20437c478bd9Sstevel@tonic-gate firstmatch = cur; 20447c478bd9Sstevel@tonic-gate else if (firstmatch != cur) 20457c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 20467c478bd9Sstevel@tonic-gate } else { 20477c478bd9Sstevel@tonic-gate /* 20487c478bd9Sstevel@tonic-gate * If another property matched but this 20497c478bd9Sstevel@tonic-gate * one doesn't then reset firstmatch. 20507c478bd9Sstevel@tonic-gate */ 20517c478bd9Sstevel@tonic-gate if (firstmatch == cur) 20527c478bd9Sstevel@tonic-gate firstmatch = NULL; 20537c478bd9Sstevel@tonic-gate } 20547c478bd9Sstevel@tonic-gate } 20557c478bd9Sstevel@tonic-gate } 20567c478bd9Sstevel@tonic-gate } 20577c478bd9Sstevel@tonic-gate if (firstmatch == NULL) 20587c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 20597c478bd9Sstevel@tonic-gate 20607c478bd9Sstevel@tonic-gate cur = firstmatch; 20617c478bd9Sstevel@tonic-gate 20627c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_NAME, tabptr->zone_attr_name, 20637c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_attr_name))) != Z_OK) 20647c478bd9Sstevel@tonic-gate return (err); 20657c478bd9Sstevel@tonic-gate 20667c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_TYPE, tabptr->zone_attr_type, 20677c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_attr_type))) != Z_OK) 20687c478bd9Sstevel@tonic-gate return (err); 20697c478bd9Sstevel@tonic-gate 20707c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_VALUE, tabptr->zone_attr_value, 20717c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_attr_value))) != Z_OK) 20727c478bd9Sstevel@tonic-gate return (err); 20737c478bd9Sstevel@tonic-gate 20747c478bd9Sstevel@tonic-gate return (Z_OK); 20757c478bd9Sstevel@tonic-gate } 20767c478bd9Sstevel@tonic-gate 20777c478bd9Sstevel@tonic-gate static int 20787c478bd9Sstevel@tonic-gate zonecfg_add_attr_core(zone_dochandle_t handle, struct zone_attrtab *tabptr) 20797c478bd9Sstevel@tonic-gate { 20807c478bd9Sstevel@tonic-gate xmlNodePtr newnode, cur = handle->zone_dh_cur; 20817c478bd9Sstevel@tonic-gate int err; 20827c478bd9Sstevel@tonic-gate 20837c478bd9Sstevel@tonic-gate newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_ATTR, NULL); 2084a1be23daSdp err = newprop(newnode, DTD_ATTR_NAME, tabptr->zone_attr_name); 20857c478bd9Sstevel@tonic-gate if (err != Z_OK) 20867c478bd9Sstevel@tonic-gate return (err); 2087a1be23daSdp err = newprop(newnode, DTD_ATTR_TYPE, tabptr->zone_attr_type); 20887c478bd9Sstevel@tonic-gate if (err != Z_OK) 20897c478bd9Sstevel@tonic-gate return (err); 2090a1be23daSdp err = newprop(newnode, DTD_ATTR_VALUE, tabptr->zone_attr_value); 20917c478bd9Sstevel@tonic-gate if (err != Z_OK) 20927c478bd9Sstevel@tonic-gate return (err); 20937c478bd9Sstevel@tonic-gate return (Z_OK); 20947c478bd9Sstevel@tonic-gate } 20957c478bd9Sstevel@tonic-gate 20967c478bd9Sstevel@tonic-gate int 20977c478bd9Sstevel@tonic-gate zonecfg_add_attr(zone_dochandle_t handle, struct zone_attrtab *tabptr) 20987c478bd9Sstevel@tonic-gate { 20997c478bd9Sstevel@tonic-gate int err; 21007c478bd9Sstevel@tonic-gate 21017c478bd9Sstevel@tonic-gate if (tabptr == NULL) 21027c478bd9Sstevel@tonic-gate return (Z_INVAL); 21037c478bd9Sstevel@tonic-gate 21047c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 21057c478bd9Sstevel@tonic-gate return (err); 21067c478bd9Sstevel@tonic-gate 21077c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_attr_core(handle, tabptr)) != Z_OK) 21087c478bd9Sstevel@tonic-gate return (err); 21097c478bd9Sstevel@tonic-gate 21107c478bd9Sstevel@tonic-gate return (Z_OK); 21117c478bd9Sstevel@tonic-gate } 21127c478bd9Sstevel@tonic-gate 21137c478bd9Sstevel@tonic-gate static int 21147c478bd9Sstevel@tonic-gate zonecfg_delete_attr_core(zone_dochandle_t handle, struct zone_attrtab *tabptr) 21157c478bd9Sstevel@tonic-gate { 21167c478bd9Sstevel@tonic-gate xmlNodePtr cur = handle->zone_dh_cur; 21177c478bd9Sstevel@tonic-gate int name_match, type_match, value_match; 21187c478bd9Sstevel@tonic-gate 21197c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 21207c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_ATTR)) 21217c478bd9Sstevel@tonic-gate continue; 21227c478bd9Sstevel@tonic-gate 21237c478bd9Sstevel@tonic-gate name_match = match_prop(cur, DTD_ATTR_NAME, 21247c478bd9Sstevel@tonic-gate tabptr->zone_attr_name); 21257c478bd9Sstevel@tonic-gate type_match = match_prop(cur, DTD_ATTR_TYPE, 21267c478bd9Sstevel@tonic-gate tabptr->zone_attr_type); 21277c478bd9Sstevel@tonic-gate value_match = match_prop(cur, DTD_ATTR_VALUE, 21287c478bd9Sstevel@tonic-gate tabptr->zone_attr_value); 21297c478bd9Sstevel@tonic-gate 21307c478bd9Sstevel@tonic-gate if (name_match && type_match && value_match) { 21317c478bd9Sstevel@tonic-gate xmlUnlinkNode(cur); 21327c478bd9Sstevel@tonic-gate xmlFreeNode(cur); 21337c478bd9Sstevel@tonic-gate return (Z_OK); 21347c478bd9Sstevel@tonic-gate } 21357c478bd9Sstevel@tonic-gate } 21367c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 21377c478bd9Sstevel@tonic-gate } 21387c478bd9Sstevel@tonic-gate 21397c478bd9Sstevel@tonic-gate int 21407c478bd9Sstevel@tonic-gate zonecfg_delete_attr(zone_dochandle_t handle, struct zone_attrtab *tabptr) 21417c478bd9Sstevel@tonic-gate { 21427c478bd9Sstevel@tonic-gate int err; 21437c478bd9Sstevel@tonic-gate 21447c478bd9Sstevel@tonic-gate if (tabptr == NULL) 21457c478bd9Sstevel@tonic-gate return (Z_INVAL); 21467c478bd9Sstevel@tonic-gate 21477c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 21487c478bd9Sstevel@tonic-gate return (err); 21497c478bd9Sstevel@tonic-gate 21507c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_attr_core(handle, tabptr)) != Z_OK) 21517c478bd9Sstevel@tonic-gate return (err); 21527c478bd9Sstevel@tonic-gate 21537c478bd9Sstevel@tonic-gate return (Z_OK); 21547c478bd9Sstevel@tonic-gate } 21557c478bd9Sstevel@tonic-gate 21567c478bd9Sstevel@tonic-gate int 21577c478bd9Sstevel@tonic-gate zonecfg_modify_attr( 21587c478bd9Sstevel@tonic-gate zone_dochandle_t handle, 21597c478bd9Sstevel@tonic-gate struct zone_attrtab *oldtabptr, 21607c478bd9Sstevel@tonic-gate struct zone_attrtab *newtabptr) 21617c478bd9Sstevel@tonic-gate { 21627c478bd9Sstevel@tonic-gate int err; 21637c478bd9Sstevel@tonic-gate 21647c478bd9Sstevel@tonic-gate if (oldtabptr == NULL || newtabptr == NULL) 21657c478bd9Sstevel@tonic-gate return (Z_INVAL); 21667c478bd9Sstevel@tonic-gate 21677c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 21687c478bd9Sstevel@tonic-gate return (err); 21697c478bd9Sstevel@tonic-gate 21707c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_attr_core(handle, oldtabptr)) != Z_OK) 21717c478bd9Sstevel@tonic-gate return (err); 21727c478bd9Sstevel@tonic-gate 21737c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_attr_core(handle, newtabptr)) != Z_OK) 21747c478bd9Sstevel@tonic-gate return (err); 21757c478bd9Sstevel@tonic-gate 21767c478bd9Sstevel@tonic-gate return (Z_OK); 21777c478bd9Sstevel@tonic-gate } 21787c478bd9Sstevel@tonic-gate 21797c478bd9Sstevel@tonic-gate int 21807c478bd9Sstevel@tonic-gate zonecfg_get_attr_boolean(const struct zone_attrtab *attr, boolean_t *value) 21817c478bd9Sstevel@tonic-gate { 21827c478bd9Sstevel@tonic-gate if (attr == NULL) 21837c478bd9Sstevel@tonic-gate return (Z_INVAL); 21847c478bd9Sstevel@tonic-gate 21857c478bd9Sstevel@tonic-gate if (strcmp(attr->zone_attr_type, DTD_ENTITY_BOOLEAN) != 0) 21867c478bd9Sstevel@tonic-gate return (Z_INVAL); 21877c478bd9Sstevel@tonic-gate 21887c478bd9Sstevel@tonic-gate if (strcmp(attr->zone_attr_value, DTD_ENTITY_TRUE) == 0) { 21897c478bd9Sstevel@tonic-gate *value = B_TRUE; 21907c478bd9Sstevel@tonic-gate return (Z_OK); 21917c478bd9Sstevel@tonic-gate } 21927c478bd9Sstevel@tonic-gate if (strcmp(attr->zone_attr_value, DTD_ENTITY_FALSE) == 0) { 21937c478bd9Sstevel@tonic-gate *value = B_FALSE; 21947c478bd9Sstevel@tonic-gate return (Z_OK); 21957c478bd9Sstevel@tonic-gate } 21967c478bd9Sstevel@tonic-gate return (Z_INVAL); 21977c478bd9Sstevel@tonic-gate } 21987c478bd9Sstevel@tonic-gate 21997c478bd9Sstevel@tonic-gate int 22007c478bd9Sstevel@tonic-gate zonecfg_get_attr_int(const struct zone_attrtab *attr, int64_t *value) 22017c478bd9Sstevel@tonic-gate { 22027c478bd9Sstevel@tonic-gate long long result; 22037c478bd9Sstevel@tonic-gate char *endptr; 22047c478bd9Sstevel@tonic-gate 22057c478bd9Sstevel@tonic-gate if (attr == NULL) 22067c478bd9Sstevel@tonic-gate return (Z_INVAL); 22077c478bd9Sstevel@tonic-gate 22087c478bd9Sstevel@tonic-gate if (strcmp(attr->zone_attr_type, DTD_ENTITY_INT) != 0) 22097c478bd9Sstevel@tonic-gate return (Z_INVAL); 22107c478bd9Sstevel@tonic-gate 22117c478bd9Sstevel@tonic-gate errno = 0; 22127c478bd9Sstevel@tonic-gate result = strtoll(attr->zone_attr_value, &endptr, 10); 22137c478bd9Sstevel@tonic-gate if (errno != 0 || *endptr != '\0') 22147c478bd9Sstevel@tonic-gate return (Z_INVAL); 22157c478bd9Sstevel@tonic-gate *value = result; 22167c478bd9Sstevel@tonic-gate return (Z_OK); 22177c478bd9Sstevel@tonic-gate } 22187c478bd9Sstevel@tonic-gate 22197c478bd9Sstevel@tonic-gate int 22207c478bd9Sstevel@tonic-gate zonecfg_get_attr_string(const struct zone_attrtab *attr, char *value, 22217c478bd9Sstevel@tonic-gate size_t val_sz) 22227c478bd9Sstevel@tonic-gate { 22237c478bd9Sstevel@tonic-gate if (attr == NULL) 22247c478bd9Sstevel@tonic-gate return (Z_INVAL); 22257c478bd9Sstevel@tonic-gate 22267c478bd9Sstevel@tonic-gate if (strcmp(attr->zone_attr_type, DTD_ENTITY_STRING) != 0) 22277c478bd9Sstevel@tonic-gate return (Z_INVAL); 22287c478bd9Sstevel@tonic-gate 22297c478bd9Sstevel@tonic-gate if (strlcpy(value, attr->zone_attr_value, val_sz) >= val_sz) 22307c478bd9Sstevel@tonic-gate return (Z_TOO_BIG); 22317c478bd9Sstevel@tonic-gate return (Z_OK); 22327c478bd9Sstevel@tonic-gate } 22337c478bd9Sstevel@tonic-gate 22347c478bd9Sstevel@tonic-gate int 22357c478bd9Sstevel@tonic-gate zonecfg_get_attr_uint(const struct zone_attrtab *attr, uint64_t *value) 22367c478bd9Sstevel@tonic-gate { 22377c478bd9Sstevel@tonic-gate unsigned long long result; 22387c478bd9Sstevel@tonic-gate long long neg_result; 22397c478bd9Sstevel@tonic-gate char *endptr; 22407c478bd9Sstevel@tonic-gate 22417c478bd9Sstevel@tonic-gate if (attr == NULL) 22427c478bd9Sstevel@tonic-gate return (Z_INVAL); 22437c478bd9Sstevel@tonic-gate 22447c478bd9Sstevel@tonic-gate if (strcmp(attr->zone_attr_type, DTD_ENTITY_UINT) != 0) 22457c478bd9Sstevel@tonic-gate return (Z_INVAL); 22467c478bd9Sstevel@tonic-gate 22477c478bd9Sstevel@tonic-gate errno = 0; 22487c478bd9Sstevel@tonic-gate result = strtoull(attr->zone_attr_value, &endptr, 10); 22497c478bd9Sstevel@tonic-gate if (errno != 0 || *endptr != '\0') 22507c478bd9Sstevel@tonic-gate return (Z_INVAL); 22517c478bd9Sstevel@tonic-gate errno = 0; 22527c478bd9Sstevel@tonic-gate neg_result = strtoll(attr->zone_attr_value, &endptr, 10); 22537c478bd9Sstevel@tonic-gate /* 22547c478bd9Sstevel@tonic-gate * Incredibly, strtoull("<negative number>", ...) will not fail but 22557c478bd9Sstevel@tonic-gate * return whatever (negative) number cast as a u_longlong_t, so we 22567c478bd9Sstevel@tonic-gate * need to look for this here. 22577c478bd9Sstevel@tonic-gate */ 22587c478bd9Sstevel@tonic-gate if (errno == 0 && neg_result < 0) 22597c478bd9Sstevel@tonic-gate return (Z_INVAL); 22607c478bd9Sstevel@tonic-gate *value = result; 22617c478bd9Sstevel@tonic-gate return (Z_OK); 22627c478bd9Sstevel@tonic-gate } 22637c478bd9Sstevel@tonic-gate 22647c478bd9Sstevel@tonic-gate int 22657c478bd9Sstevel@tonic-gate zonecfg_lookup_rctl(zone_dochandle_t handle, struct zone_rctltab *tabptr) 22667c478bd9Sstevel@tonic-gate { 22677c478bd9Sstevel@tonic-gate xmlNodePtr cur, val; 22687c478bd9Sstevel@tonic-gate char savedname[MAXNAMELEN]; 22697c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *valptr; 22707c478bd9Sstevel@tonic-gate int err; 22717c478bd9Sstevel@tonic-gate 22727c478bd9Sstevel@tonic-gate if (tabptr->zone_rctl_name == NULL || 22737c478bd9Sstevel@tonic-gate strlen(tabptr->zone_rctl_name) == 0) 22747c478bd9Sstevel@tonic-gate return (Z_INVAL); 22757c478bd9Sstevel@tonic-gate 22767c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 22777c478bd9Sstevel@tonic-gate return (err); 22787c478bd9Sstevel@tonic-gate 22797c478bd9Sstevel@tonic-gate cur = handle->zone_dh_cur; 22807c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 22817c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_RCTL)) 22827c478bd9Sstevel@tonic-gate continue; 22837c478bd9Sstevel@tonic-gate if ((fetchprop(cur, DTD_ATTR_NAME, savedname, 22847c478bd9Sstevel@tonic-gate sizeof (savedname)) == Z_OK) && 22857c478bd9Sstevel@tonic-gate (strcmp(savedname, tabptr->zone_rctl_name) == 0)) { 22867c478bd9Sstevel@tonic-gate tabptr->zone_rctl_valptr = NULL; 22877c478bd9Sstevel@tonic-gate for (val = cur->xmlChildrenNode; val != NULL; 22887c478bd9Sstevel@tonic-gate val = val->next) { 22897c478bd9Sstevel@tonic-gate valptr = (struct zone_rctlvaltab *)malloc( 22907c478bd9Sstevel@tonic-gate sizeof (struct zone_rctlvaltab)); 22917c478bd9Sstevel@tonic-gate if (valptr == NULL) 22927c478bd9Sstevel@tonic-gate return (Z_NOMEM); 22937c478bd9Sstevel@tonic-gate if ((fetchprop(val, DTD_ATTR_PRIV, 22947c478bd9Sstevel@tonic-gate valptr->zone_rctlval_priv, 22957c478bd9Sstevel@tonic-gate sizeof (valptr->zone_rctlval_priv)) != 22967c478bd9Sstevel@tonic-gate Z_OK)) 22977c478bd9Sstevel@tonic-gate break; 22987c478bd9Sstevel@tonic-gate if ((fetchprop(val, DTD_ATTR_LIMIT, 22997c478bd9Sstevel@tonic-gate valptr->zone_rctlval_limit, 23007c478bd9Sstevel@tonic-gate sizeof (valptr->zone_rctlval_limit)) != 23017c478bd9Sstevel@tonic-gate Z_OK)) 23027c478bd9Sstevel@tonic-gate break; 23037c478bd9Sstevel@tonic-gate if ((fetchprop(val, DTD_ATTR_ACTION, 23047c478bd9Sstevel@tonic-gate valptr->zone_rctlval_action, 23057c478bd9Sstevel@tonic-gate sizeof (valptr->zone_rctlval_action)) != 23067c478bd9Sstevel@tonic-gate Z_OK)) 23077c478bd9Sstevel@tonic-gate break; 23087c478bd9Sstevel@tonic-gate if (zonecfg_add_rctl_value(tabptr, valptr) != 23097c478bd9Sstevel@tonic-gate Z_OK) 23107c478bd9Sstevel@tonic-gate break; 23117c478bd9Sstevel@tonic-gate } 23127c478bd9Sstevel@tonic-gate return (Z_OK); 23137c478bd9Sstevel@tonic-gate } 23147c478bd9Sstevel@tonic-gate } 23157c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 23167c478bd9Sstevel@tonic-gate } 23177c478bd9Sstevel@tonic-gate 23187c478bd9Sstevel@tonic-gate static int 23197c478bd9Sstevel@tonic-gate zonecfg_add_rctl_core(zone_dochandle_t handle, struct zone_rctltab *tabptr) 23207c478bd9Sstevel@tonic-gate { 23217c478bd9Sstevel@tonic-gate xmlNodePtr newnode, cur = handle->zone_dh_cur, valnode; 23227c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *valptr; 23237c478bd9Sstevel@tonic-gate int err; 23247c478bd9Sstevel@tonic-gate 23257c478bd9Sstevel@tonic-gate newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_RCTL, NULL); 2326a1be23daSdp err = newprop(newnode, DTD_ATTR_NAME, tabptr->zone_rctl_name); 23277c478bd9Sstevel@tonic-gate if (err != Z_OK) 23287c478bd9Sstevel@tonic-gate return (err); 23297c478bd9Sstevel@tonic-gate for (valptr = tabptr->zone_rctl_valptr; valptr != NULL; 23307c478bd9Sstevel@tonic-gate valptr = valptr->zone_rctlval_next) { 23317c478bd9Sstevel@tonic-gate valnode = xmlNewTextChild(newnode, NULL, 23327c478bd9Sstevel@tonic-gate DTD_ELEM_RCTLVALUE, NULL); 2333a1be23daSdp err = newprop(valnode, DTD_ATTR_PRIV, 23347c478bd9Sstevel@tonic-gate valptr->zone_rctlval_priv); 23357c478bd9Sstevel@tonic-gate if (err != Z_OK) 23367c478bd9Sstevel@tonic-gate return (err); 2337a1be23daSdp err = newprop(valnode, DTD_ATTR_LIMIT, 23387c478bd9Sstevel@tonic-gate valptr->zone_rctlval_limit); 23397c478bd9Sstevel@tonic-gate if (err != Z_OK) 23407c478bd9Sstevel@tonic-gate return (err); 2341a1be23daSdp err = newprop(valnode, DTD_ATTR_ACTION, 23427c478bd9Sstevel@tonic-gate valptr->zone_rctlval_action); 23437c478bd9Sstevel@tonic-gate if (err != Z_OK) 23447c478bd9Sstevel@tonic-gate return (err); 23457c478bd9Sstevel@tonic-gate } 23467c478bd9Sstevel@tonic-gate return (Z_OK); 23477c478bd9Sstevel@tonic-gate } 23487c478bd9Sstevel@tonic-gate 23497c478bd9Sstevel@tonic-gate int 23507c478bd9Sstevel@tonic-gate zonecfg_add_rctl(zone_dochandle_t handle, struct zone_rctltab *tabptr) 23517c478bd9Sstevel@tonic-gate { 23527c478bd9Sstevel@tonic-gate int err; 23537c478bd9Sstevel@tonic-gate 23547c478bd9Sstevel@tonic-gate if (tabptr == NULL || tabptr->zone_rctl_name == NULL) 23557c478bd9Sstevel@tonic-gate return (Z_INVAL); 23567c478bd9Sstevel@tonic-gate 23577c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 23587c478bd9Sstevel@tonic-gate return (err); 23597c478bd9Sstevel@tonic-gate 23607c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_rctl_core(handle, tabptr)) != Z_OK) 23617c478bd9Sstevel@tonic-gate return (err); 23627c478bd9Sstevel@tonic-gate 23637c478bd9Sstevel@tonic-gate return (Z_OK); 23647c478bd9Sstevel@tonic-gate } 23657c478bd9Sstevel@tonic-gate 23667c478bd9Sstevel@tonic-gate static int 23677c478bd9Sstevel@tonic-gate zonecfg_delete_rctl_core(zone_dochandle_t handle, struct zone_rctltab *tabptr) 23687c478bd9Sstevel@tonic-gate { 23697c478bd9Sstevel@tonic-gate xmlNodePtr cur = handle->zone_dh_cur; 23707c478bd9Sstevel@tonic-gate xmlChar *savedname; 23717c478bd9Sstevel@tonic-gate int name_result; 23727c478bd9Sstevel@tonic-gate 23737c478bd9Sstevel@tonic-gate for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { 23747c478bd9Sstevel@tonic-gate if (xmlStrcmp(cur->name, DTD_ELEM_RCTL)) 23757c478bd9Sstevel@tonic-gate continue; 23767c478bd9Sstevel@tonic-gate 23777c478bd9Sstevel@tonic-gate savedname = xmlGetProp(cur, DTD_ATTR_NAME); 23787c478bd9Sstevel@tonic-gate if (savedname == NULL) /* shouldn't happen */ 23797c478bd9Sstevel@tonic-gate continue; 23807c478bd9Sstevel@tonic-gate name_result = xmlStrcmp(savedname, 23817c478bd9Sstevel@tonic-gate (const xmlChar *) tabptr->zone_rctl_name); 23827c478bd9Sstevel@tonic-gate xmlFree(savedname); 23837c478bd9Sstevel@tonic-gate 23847c478bd9Sstevel@tonic-gate if (name_result == 0) { 23857c478bd9Sstevel@tonic-gate xmlUnlinkNode(cur); 23867c478bd9Sstevel@tonic-gate xmlFreeNode(cur); 23877c478bd9Sstevel@tonic-gate return (Z_OK); 23887c478bd9Sstevel@tonic-gate } 23897c478bd9Sstevel@tonic-gate } 23907c478bd9Sstevel@tonic-gate return (Z_NO_RESOURCE_ID); 23917c478bd9Sstevel@tonic-gate } 23927c478bd9Sstevel@tonic-gate 23937c478bd9Sstevel@tonic-gate int 23947c478bd9Sstevel@tonic-gate zonecfg_delete_rctl(zone_dochandle_t handle, struct zone_rctltab *tabptr) 23957c478bd9Sstevel@tonic-gate { 23967c478bd9Sstevel@tonic-gate int err; 23977c478bd9Sstevel@tonic-gate 23987c478bd9Sstevel@tonic-gate if (tabptr == NULL || tabptr->zone_rctl_name == NULL) 23997c478bd9Sstevel@tonic-gate return (Z_INVAL); 24007c478bd9Sstevel@tonic-gate 24017c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 24027c478bd9Sstevel@tonic-gate return (err); 24037c478bd9Sstevel@tonic-gate 24047c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_rctl_core(handle, tabptr)) != Z_OK) 24057c478bd9Sstevel@tonic-gate return (err); 24067c478bd9Sstevel@tonic-gate 24077c478bd9Sstevel@tonic-gate return (Z_OK); 24087c478bd9Sstevel@tonic-gate } 24097c478bd9Sstevel@tonic-gate 24107c478bd9Sstevel@tonic-gate int 24117c478bd9Sstevel@tonic-gate zonecfg_modify_rctl( 24127c478bd9Sstevel@tonic-gate zone_dochandle_t handle, 24137c478bd9Sstevel@tonic-gate struct zone_rctltab *oldtabptr, 24147c478bd9Sstevel@tonic-gate struct zone_rctltab *newtabptr) 24157c478bd9Sstevel@tonic-gate { 24167c478bd9Sstevel@tonic-gate int err; 24177c478bd9Sstevel@tonic-gate 24187c478bd9Sstevel@tonic-gate if (oldtabptr == NULL || oldtabptr->zone_rctl_name == NULL || 24197c478bd9Sstevel@tonic-gate newtabptr == NULL || newtabptr->zone_rctl_name == NULL) 24207c478bd9Sstevel@tonic-gate return (Z_INVAL); 24217c478bd9Sstevel@tonic-gate 24227c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) 24237c478bd9Sstevel@tonic-gate return (err); 24247c478bd9Sstevel@tonic-gate 24257c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_rctl_core(handle, oldtabptr)) != Z_OK) 24267c478bd9Sstevel@tonic-gate return (err); 24277c478bd9Sstevel@tonic-gate 24287c478bd9Sstevel@tonic-gate if ((err = zonecfg_add_rctl_core(handle, newtabptr)) != Z_OK) 24297c478bd9Sstevel@tonic-gate return (err); 24307c478bd9Sstevel@tonic-gate 24317c478bd9Sstevel@tonic-gate return (Z_OK); 24327c478bd9Sstevel@tonic-gate } 24337c478bd9Sstevel@tonic-gate 24347c478bd9Sstevel@tonic-gate int 24357c478bd9Sstevel@tonic-gate zonecfg_add_rctl_value( 24367c478bd9Sstevel@tonic-gate struct zone_rctltab *tabptr, 24377c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *valtabptr) 24387c478bd9Sstevel@tonic-gate { 24397c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *last, *old, *new; 24407c478bd9Sstevel@tonic-gate rctlblk_t *rctlblk = alloca(rctlblk_size()); 24417c478bd9Sstevel@tonic-gate 24427c478bd9Sstevel@tonic-gate last = tabptr->zone_rctl_valptr; 24437c478bd9Sstevel@tonic-gate for (old = last; old != NULL; old = old->zone_rctlval_next) 24447c478bd9Sstevel@tonic-gate last = old; /* walk to the end of the list */ 24457c478bd9Sstevel@tonic-gate new = valtabptr; /* alloc'd by caller */ 24467c478bd9Sstevel@tonic-gate new->zone_rctlval_next = NULL; 24477c478bd9Sstevel@tonic-gate if (zonecfg_construct_rctlblk(valtabptr, rctlblk) != Z_OK) 24487c478bd9Sstevel@tonic-gate return (Z_INVAL); 24497c478bd9Sstevel@tonic-gate if (!zonecfg_valid_rctlblk(rctlblk)) 24507c478bd9Sstevel@tonic-gate return (Z_INVAL); 24517c478bd9Sstevel@tonic-gate if (last == NULL) 24527c478bd9Sstevel@tonic-gate tabptr->zone_rctl_valptr = new; 24537c478bd9Sstevel@tonic-gate else 24547c478bd9Sstevel@tonic-gate last->zone_rctlval_next = new; 24557c478bd9Sstevel@tonic-gate return (Z_OK); 24567c478bd9Sstevel@tonic-gate } 24577c478bd9Sstevel@tonic-gate 24587c478bd9Sstevel@tonic-gate int 24597c478bd9Sstevel@tonic-gate zonecfg_remove_rctl_value( 24607c478bd9Sstevel@tonic-gate struct zone_rctltab *tabptr, 24617c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *valtabptr) 24627c478bd9Sstevel@tonic-gate { 24637c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *last, *this, *next; 24647c478bd9Sstevel@tonic-gate 24657c478bd9Sstevel@tonic-gate last = tabptr->zone_rctl_valptr; 24667c478bd9Sstevel@tonic-gate for (this = last; this != NULL; this = this->zone_rctlval_next) { 24677c478bd9Sstevel@tonic-gate if (strcmp(this->zone_rctlval_priv, 24687c478bd9Sstevel@tonic-gate valtabptr->zone_rctlval_priv) == 0 && 24697c478bd9Sstevel@tonic-gate strcmp(this->zone_rctlval_limit, 24707c478bd9Sstevel@tonic-gate valtabptr->zone_rctlval_limit) == 0 && 24717c478bd9Sstevel@tonic-gate strcmp(this->zone_rctlval_action, 24727c478bd9Sstevel@tonic-gate valtabptr->zone_rctlval_action) == 0) { 24737c478bd9Sstevel@tonic-gate next = this->zone_rctlval_next; 24747c478bd9Sstevel@tonic-gate if (this == tabptr->zone_rctl_valptr) 24757c478bd9Sstevel@tonic-gate tabptr->zone_rctl_valptr = next; 24767c478bd9Sstevel@tonic-gate else 24777c478bd9Sstevel@tonic-gate last->zone_rctlval_next = next; 24787c478bd9Sstevel@tonic-gate free(this); 24797c478bd9Sstevel@tonic-gate return (Z_OK); 24807c478bd9Sstevel@tonic-gate } else 24817c478bd9Sstevel@tonic-gate last = this; 24827c478bd9Sstevel@tonic-gate } 24837c478bd9Sstevel@tonic-gate return (Z_NO_PROPERTY_ID); 24847c478bd9Sstevel@tonic-gate } 24857c478bd9Sstevel@tonic-gate 24867c478bd9Sstevel@tonic-gate char * 24877c478bd9Sstevel@tonic-gate zonecfg_strerror(int errnum) 24887c478bd9Sstevel@tonic-gate { 24897c478bd9Sstevel@tonic-gate switch (errnum) { 24907c478bd9Sstevel@tonic-gate case Z_OK: 24917c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "OK")); 24927c478bd9Sstevel@tonic-gate case Z_EMPTY_DOCUMENT: 24937c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Empty document")); 24947c478bd9Sstevel@tonic-gate case Z_WRONG_DOC_TYPE: 24957c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Wrong document type")); 24967c478bd9Sstevel@tonic-gate case Z_BAD_PROPERTY: 24977c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Bad document property")); 24987c478bd9Sstevel@tonic-gate case Z_TEMP_FILE: 24997c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, 25007c478bd9Sstevel@tonic-gate "Problem creating temporary file")); 25017c478bd9Sstevel@tonic-gate case Z_SAVING_FILE: 25027c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Problem saving file")); 25037c478bd9Sstevel@tonic-gate case Z_NO_ENTRY: 25047c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "No such entry")); 25057c478bd9Sstevel@tonic-gate case Z_BOGUS_ZONE_NAME: 25067c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Bogus zone name")); 25077c478bd9Sstevel@tonic-gate case Z_REQD_RESOURCE_MISSING: 25087c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Required resource missing")); 25097c478bd9Sstevel@tonic-gate case Z_REQD_PROPERTY_MISSING: 25107c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Required property missing")); 25117c478bd9Sstevel@tonic-gate case Z_BAD_HANDLE: 25127c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Bad handle")); 25137c478bd9Sstevel@tonic-gate case Z_NOMEM: 25147c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Out of memory")); 25157c478bd9Sstevel@tonic-gate case Z_INVAL: 25167c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Invalid argument")); 25177c478bd9Sstevel@tonic-gate case Z_ACCES: 25187c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Permission denied")); 25197c478bd9Sstevel@tonic-gate case Z_TOO_BIG: 25207c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Argument list too long")); 25217c478bd9Sstevel@tonic-gate case Z_MISC_FS: 25227c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, 25237c478bd9Sstevel@tonic-gate "Miscellaneous file system error")); 25247c478bd9Sstevel@tonic-gate case Z_NO_ZONE: 25257c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "No such zone configured")); 25267c478bd9Sstevel@tonic-gate case Z_NO_RESOURCE_TYPE: 25277c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "No such resource type")); 25287c478bd9Sstevel@tonic-gate case Z_NO_RESOURCE_ID: 25297c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "No such resource with that id")); 25307c478bd9Sstevel@tonic-gate case Z_NO_PROPERTY_TYPE: 25317c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "No such property type")); 25327c478bd9Sstevel@tonic-gate case Z_NO_PROPERTY_ID: 25337c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "No such property with that id")); 2534*087719fdSdp case Z_BAD_ZONE_STATE: 25357c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, 2536*087719fdSdp "Zone state is invalid for the requested operation")); 25377c478bd9Sstevel@tonic-gate case Z_INVALID_DOCUMENT: 25387c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Invalid document")); 2539*087719fdSdp case Z_NAME_IN_USE: 2540*087719fdSdp return (dgettext(TEXT_DOMAIN, "Zone name already in use")); 25417c478bd9Sstevel@tonic-gate case Z_NO_SUCH_ID: 25427c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "No such zone ID")); 25437c478bd9Sstevel@tonic-gate case Z_UPDATING_INDEX: 25447c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Problem updating index file")); 25457c478bd9Sstevel@tonic-gate case Z_LOCKING_FILE: 25467c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Locking index file")); 25477c478bd9Sstevel@tonic-gate case Z_UNLOCKING_FILE: 25487c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Unlocking index file")); 25497c478bd9Sstevel@tonic-gate case Z_INSUFFICIENT_SPEC: 25507c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Insufficient specification")); 25517c478bd9Sstevel@tonic-gate case Z_RESOLVED_PATH: 25527c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Resolved path mismatch")); 25537c478bd9Sstevel@tonic-gate case Z_IPV6_ADDR_PREFIX_LEN: 25547c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, 25557c478bd9Sstevel@tonic-gate "IPv6 address missing required prefix length")); 25567c478bd9Sstevel@tonic-gate case Z_BOGUS_ADDRESS: 25577c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, 25587c478bd9Sstevel@tonic-gate "Neither an IPv4 nor an IPv6 address nor a host name")); 25597c478bd9Sstevel@tonic-gate default: 25607c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Unknown error")); 25617c478bd9Sstevel@tonic-gate } 25627c478bd9Sstevel@tonic-gate } 25637c478bd9Sstevel@tonic-gate 25647c478bd9Sstevel@tonic-gate /* 25657c478bd9Sstevel@tonic-gate * Note that the zonecfg_setXent() and zonecfg_endXent() calls are all the 25667c478bd9Sstevel@tonic-gate * same, as they just turn around and call zonecfg_setent() / zonecfg_endent(). 25677c478bd9Sstevel@tonic-gate */ 25687c478bd9Sstevel@tonic-gate 25697c478bd9Sstevel@tonic-gate static int 25707c478bd9Sstevel@tonic-gate zonecfg_setent(zone_dochandle_t handle) 25717c478bd9Sstevel@tonic-gate { 25727c478bd9Sstevel@tonic-gate xmlNodePtr cur; 25737c478bd9Sstevel@tonic-gate int err; 25747c478bd9Sstevel@tonic-gate 25757c478bd9Sstevel@tonic-gate if (handle == NULL) 25767c478bd9Sstevel@tonic-gate return (Z_INVAL); 25777c478bd9Sstevel@tonic-gate 25787c478bd9Sstevel@tonic-gate if ((err = operation_prep(handle)) != Z_OK) { 25797c478bd9Sstevel@tonic-gate handle->zone_dh_cur = NULL; 25807c478bd9Sstevel@tonic-gate return (err); 25817c478bd9Sstevel@tonic-gate } 25827c478bd9Sstevel@tonic-gate cur = handle->zone_dh_cur; 25837c478bd9Sstevel@tonic-gate cur = cur->xmlChildrenNode; 25847c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur; 25857c478bd9Sstevel@tonic-gate return (Z_OK); 25867c478bd9Sstevel@tonic-gate } 25877c478bd9Sstevel@tonic-gate 25887c478bd9Sstevel@tonic-gate static int 25897c478bd9Sstevel@tonic-gate zonecfg_endent(zone_dochandle_t handle) 25907c478bd9Sstevel@tonic-gate { 25917c478bd9Sstevel@tonic-gate if (handle == NULL) 25927c478bd9Sstevel@tonic-gate return (Z_INVAL); 25937c478bd9Sstevel@tonic-gate 25947c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 25957c478bd9Sstevel@tonic-gate return (Z_OK); 25967c478bd9Sstevel@tonic-gate } 25977c478bd9Sstevel@tonic-gate 25987c478bd9Sstevel@tonic-gate int 25997c478bd9Sstevel@tonic-gate zonecfg_setfsent(zone_dochandle_t handle) 26007c478bd9Sstevel@tonic-gate { 26017c478bd9Sstevel@tonic-gate return (zonecfg_setent(handle)); 26027c478bd9Sstevel@tonic-gate } 26037c478bd9Sstevel@tonic-gate 26047c478bd9Sstevel@tonic-gate int 26057c478bd9Sstevel@tonic-gate zonecfg_getfsent(zone_dochandle_t handle, struct zone_fstab *tabptr) 26067c478bd9Sstevel@tonic-gate { 26077c478bd9Sstevel@tonic-gate xmlNodePtr cur, options; 26087c478bd9Sstevel@tonic-gate char options_str[MAX_MNTOPT_STR]; 26097c478bd9Sstevel@tonic-gate int err; 26107c478bd9Sstevel@tonic-gate 26117c478bd9Sstevel@tonic-gate if (handle == NULL) 26127c478bd9Sstevel@tonic-gate return (Z_INVAL); 26137c478bd9Sstevel@tonic-gate 26147c478bd9Sstevel@tonic-gate if ((cur = handle->zone_dh_cur) == NULL) 26157c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 26167c478bd9Sstevel@tonic-gate 26177c478bd9Sstevel@tonic-gate for (; cur != NULL; cur = cur->next) 26187c478bd9Sstevel@tonic-gate if (!xmlStrcmp(cur->name, DTD_ELEM_FS)) 26197c478bd9Sstevel@tonic-gate break; 26207c478bd9Sstevel@tonic-gate if (cur == NULL) { 26217c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 26227c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 26237c478bd9Sstevel@tonic-gate } 26247c478bd9Sstevel@tonic-gate 26257c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_SPECIAL, tabptr->zone_fs_special, 26267c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_special))) != Z_OK) { 26277c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 26287c478bd9Sstevel@tonic-gate return (err); 26297c478bd9Sstevel@tonic-gate } 26307c478bd9Sstevel@tonic-gate 26317c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_RAW, tabptr->zone_fs_raw, 26327c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_raw))) != Z_OK) { 26337c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 26347c478bd9Sstevel@tonic-gate return (err); 26357c478bd9Sstevel@tonic-gate } 26367c478bd9Sstevel@tonic-gate 26377c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir, 26387c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_dir))) != Z_OK) { 26397c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 26407c478bd9Sstevel@tonic-gate return (err); 26417c478bd9Sstevel@tonic-gate } 26427c478bd9Sstevel@tonic-gate 26437c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_TYPE, tabptr->zone_fs_type, 26447c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_type))) != Z_OK) { 26457c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 26467c478bd9Sstevel@tonic-gate return (err); 26477c478bd9Sstevel@tonic-gate } 26487c478bd9Sstevel@tonic-gate 26497c478bd9Sstevel@tonic-gate /* OK for options to be NULL */ 26507c478bd9Sstevel@tonic-gate tabptr->zone_fs_options = NULL; 26517c478bd9Sstevel@tonic-gate for (options = cur->xmlChildrenNode; options != NULL; 26527c478bd9Sstevel@tonic-gate options = options->next) { 26537c478bd9Sstevel@tonic-gate if (fetchprop(options, DTD_ATTR_NAME, options_str, 26547c478bd9Sstevel@tonic-gate sizeof (options_str)) != Z_OK) 26557c478bd9Sstevel@tonic-gate break; 26567c478bd9Sstevel@tonic-gate if (zonecfg_add_fs_option(tabptr, options_str) != Z_OK) 26577c478bd9Sstevel@tonic-gate break; 26587c478bd9Sstevel@tonic-gate } 26597c478bd9Sstevel@tonic-gate 26607c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur->next; 26617c478bd9Sstevel@tonic-gate return (Z_OK); 26627c478bd9Sstevel@tonic-gate } 26637c478bd9Sstevel@tonic-gate 26647c478bd9Sstevel@tonic-gate int 26657c478bd9Sstevel@tonic-gate zonecfg_endfsent(zone_dochandle_t handle) 26667c478bd9Sstevel@tonic-gate { 26677c478bd9Sstevel@tonic-gate return (zonecfg_endent(handle)); 26687c478bd9Sstevel@tonic-gate } 26697c478bd9Sstevel@tonic-gate 26707c478bd9Sstevel@tonic-gate int 26717c478bd9Sstevel@tonic-gate zonecfg_setipdent(zone_dochandle_t handle) 26727c478bd9Sstevel@tonic-gate { 26737c478bd9Sstevel@tonic-gate return (zonecfg_setent(handle)); 26747c478bd9Sstevel@tonic-gate } 26757c478bd9Sstevel@tonic-gate 26767c478bd9Sstevel@tonic-gate int 26777c478bd9Sstevel@tonic-gate zonecfg_getipdent(zone_dochandle_t handle, struct zone_fstab *tabptr) 26787c478bd9Sstevel@tonic-gate { 26797c478bd9Sstevel@tonic-gate xmlNodePtr cur; 26807c478bd9Sstevel@tonic-gate int err; 26817c478bd9Sstevel@tonic-gate 26827c478bd9Sstevel@tonic-gate if (handle == NULL) 26837c478bd9Sstevel@tonic-gate return (Z_INVAL); 26847c478bd9Sstevel@tonic-gate 26857c478bd9Sstevel@tonic-gate if ((cur = handle->zone_dh_cur) == NULL) 26867c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 26877c478bd9Sstevel@tonic-gate 26887c478bd9Sstevel@tonic-gate for (; cur != NULL; cur = cur->next) 26897c478bd9Sstevel@tonic-gate if (!xmlStrcmp(cur->name, DTD_ELEM_IPD)) 26907c478bd9Sstevel@tonic-gate break; 26917c478bd9Sstevel@tonic-gate if (cur == NULL) { 26927c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 26937c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 26947c478bd9Sstevel@tonic-gate } 26957c478bd9Sstevel@tonic-gate 26967c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir, 26977c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_fs_dir))) != Z_OK) { 26987c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 26997c478bd9Sstevel@tonic-gate return (err); 27007c478bd9Sstevel@tonic-gate } 27017c478bd9Sstevel@tonic-gate 27027c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur->next; 27037c478bd9Sstevel@tonic-gate return (Z_OK); 27047c478bd9Sstevel@tonic-gate } 27057c478bd9Sstevel@tonic-gate 27067c478bd9Sstevel@tonic-gate int 27077c478bd9Sstevel@tonic-gate zonecfg_endipdent(zone_dochandle_t handle) 27087c478bd9Sstevel@tonic-gate { 27097c478bd9Sstevel@tonic-gate return (zonecfg_endent(handle)); 27107c478bd9Sstevel@tonic-gate } 27117c478bd9Sstevel@tonic-gate 27127c478bd9Sstevel@tonic-gate int 27137c478bd9Sstevel@tonic-gate zonecfg_setnwifent(zone_dochandle_t handle) 27147c478bd9Sstevel@tonic-gate { 27157c478bd9Sstevel@tonic-gate return (zonecfg_setent(handle)); 27167c478bd9Sstevel@tonic-gate } 27177c478bd9Sstevel@tonic-gate 27187c478bd9Sstevel@tonic-gate int 27197c478bd9Sstevel@tonic-gate zonecfg_getnwifent(zone_dochandle_t handle, struct zone_nwiftab *tabptr) 27207c478bd9Sstevel@tonic-gate { 27217c478bd9Sstevel@tonic-gate xmlNodePtr cur; 27227c478bd9Sstevel@tonic-gate int err; 27237c478bd9Sstevel@tonic-gate 27247c478bd9Sstevel@tonic-gate if (handle == NULL) 27257c478bd9Sstevel@tonic-gate return (Z_INVAL); 27267c478bd9Sstevel@tonic-gate 27277c478bd9Sstevel@tonic-gate if ((cur = handle->zone_dh_cur) == NULL) 27287c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 27297c478bd9Sstevel@tonic-gate 27307c478bd9Sstevel@tonic-gate for (; cur != NULL; cur = cur->next) 27317c478bd9Sstevel@tonic-gate if (!xmlStrcmp(cur->name, DTD_ELEM_NET)) 27327c478bd9Sstevel@tonic-gate break; 27337c478bd9Sstevel@tonic-gate if (cur == NULL) { 27347c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 27357c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 27367c478bd9Sstevel@tonic-gate } 27377c478bd9Sstevel@tonic-gate 27387c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_ADDRESS, tabptr->zone_nwif_address, 27397c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_nwif_address))) != Z_OK) { 27407c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 27417c478bd9Sstevel@tonic-gate return (err); 27427c478bd9Sstevel@tonic-gate } 27437c478bd9Sstevel@tonic-gate 27447c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_PHYSICAL, tabptr->zone_nwif_physical, 27457c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_nwif_physical))) != Z_OK) { 27467c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 27477c478bd9Sstevel@tonic-gate return (err); 27487c478bd9Sstevel@tonic-gate } 27497c478bd9Sstevel@tonic-gate 27507c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur->next; 27517c478bd9Sstevel@tonic-gate return (Z_OK); 27527c478bd9Sstevel@tonic-gate } 27537c478bd9Sstevel@tonic-gate 27547c478bd9Sstevel@tonic-gate int 27557c478bd9Sstevel@tonic-gate zonecfg_endnwifent(zone_dochandle_t handle) 27567c478bd9Sstevel@tonic-gate { 27577c478bd9Sstevel@tonic-gate return (zonecfg_endent(handle)); 27587c478bd9Sstevel@tonic-gate } 27597c478bd9Sstevel@tonic-gate 27607c478bd9Sstevel@tonic-gate int 27617c478bd9Sstevel@tonic-gate zonecfg_setdevent(zone_dochandle_t handle) 27627c478bd9Sstevel@tonic-gate { 27637c478bd9Sstevel@tonic-gate return (zonecfg_setent(handle)); 27647c478bd9Sstevel@tonic-gate } 27657c478bd9Sstevel@tonic-gate 27667c478bd9Sstevel@tonic-gate int 27677c478bd9Sstevel@tonic-gate zonecfg_getdevent(zone_dochandle_t handle, struct zone_devtab *tabptr) 27687c478bd9Sstevel@tonic-gate { 27697c478bd9Sstevel@tonic-gate xmlNodePtr cur; 27707c478bd9Sstevel@tonic-gate int err; 27717c478bd9Sstevel@tonic-gate 27727c478bd9Sstevel@tonic-gate if (handle == NULL) 27737c478bd9Sstevel@tonic-gate return (Z_INVAL); 27747c478bd9Sstevel@tonic-gate 27757c478bd9Sstevel@tonic-gate if ((cur = handle->zone_dh_cur) == NULL) 27767c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 27777c478bd9Sstevel@tonic-gate 27787c478bd9Sstevel@tonic-gate for (; cur != NULL; cur = cur->next) 27797c478bd9Sstevel@tonic-gate if (!xmlStrcmp(cur->name, DTD_ELEM_DEVICE)) 27807c478bd9Sstevel@tonic-gate break; 27817c478bd9Sstevel@tonic-gate if (cur == NULL) { 27827c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 27837c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 27847c478bd9Sstevel@tonic-gate } 27857c478bd9Sstevel@tonic-gate 27867c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_MATCH, tabptr->zone_dev_match, 27877c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_dev_match))) != Z_OK) { 27887c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 27897c478bd9Sstevel@tonic-gate return (err); 27907c478bd9Sstevel@tonic-gate } 27917c478bd9Sstevel@tonic-gate 27927c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur->next; 27937c478bd9Sstevel@tonic-gate return (Z_OK); 27947c478bd9Sstevel@tonic-gate } 27957c478bd9Sstevel@tonic-gate 27967c478bd9Sstevel@tonic-gate int 27977c478bd9Sstevel@tonic-gate zonecfg_enddevent(zone_dochandle_t handle) 27987c478bd9Sstevel@tonic-gate { 27997c478bd9Sstevel@tonic-gate return (zonecfg_endent(handle)); 28007c478bd9Sstevel@tonic-gate } 28017c478bd9Sstevel@tonic-gate 28027c478bd9Sstevel@tonic-gate int 28037c478bd9Sstevel@tonic-gate zonecfg_setrctlent(zone_dochandle_t handle) 28047c478bd9Sstevel@tonic-gate { 28057c478bd9Sstevel@tonic-gate return (zonecfg_setent(handle)); 28067c478bd9Sstevel@tonic-gate } 28077c478bd9Sstevel@tonic-gate 28087c478bd9Sstevel@tonic-gate int 28097c478bd9Sstevel@tonic-gate zonecfg_getrctlent(zone_dochandle_t handle, struct zone_rctltab *tabptr) 28107c478bd9Sstevel@tonic-gate { 28117c478bd9Sstevel@tonic-gate xmlNodePtr cur, val; 28127c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *valptr; 28137c478bd9Sstevel@tonic-gate int err; 28147c478bd9Sstevel@tonic-gate 28157c478bd9Sstevel@tonic-gate if (handle == NULL) 28167c478bd9Sstevel@tonic-gate return (Z_INVAL); 28177c478bd9Sstevel@tonic-gate 28187c478bd9Sstevel@tonic-gate if ((cur = handle->zone_dh_cur) == NULL) 28197c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 28207c478bd9Sstevel@tonic-gate 28217c478bd9Sstevel@tonic-gate for (; cur != NULL; cur = cur->next) 28227c478bd9Sstevel@tonic-gate if (!xmlStrcmp(cur->name, DTD_ELEM_RCTL)) 28237c478bd9Sstevel@tonic-gate break; 28247c478bd9Sstevel@tonic-gate if (cur == NULL) { 28257c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 28267c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 28277c478bd9Sstevel@tonic-gate } 28287c478bd9Sstevel@tonic-gate 28297c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_NAME, tabptr->zone_rctl_name, 28307c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_rctl_name))) != Z_OK) { 28317c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 28327c478bd9Sstevel@tonic-gate return (err); 28337c478bd9Sstevel@tonic-gate } 28347c478bd9Sstevel@tonic-gate 28357c478bd9Sstevel@tonic-gate tabptr->zone_rctl_valptr = NULL; 28367c478bd9Sstevel@tonic-gate for (val = cur->xmlChildrenNode; val != NULL; val = val->next) { 28377c478bd9Sstevel@tonic-gate valptr = (struct zone_rctlvaltab *)malloc( 28387c478bd9Sstevel@tonic-gate sizeof (struct zone_rctlvaltab)); 28397c478bd9Sstevel@tonic-gate if (valptr == NULL) 28407c478bd9Sstevel@tonic-gate return (Z_NOMEM); 28417c478bd9Sstevel@tonic-gate if (fetchprop(val, DTD_ATTR_PRIV, valptr->zone_rctlval_priv, 28427c478bd9Sstevel@tonic-gate sizeof (valptr->zone_rctlval_priv)) != Z_OK) 28437c478bd9Sstevel@tonic-gate break; 28447c478bd9Sstevel@tonic-gate if (fetchprop(val, DTD_ATTR_LIMIT, valptr->zone_rctlval_limit, 28457c478bd9Sstevel@tonic-gate sizeof (valptr->zone_rctlval_limit)) != Z_OK) 28467c478bd9Sstevel@tonic-gate break; 28477c478bd9Sstevel@tonic-gate if (fetchprop(val, DTD_ATTR_ACTION, valptr->zone_rctlval_action, 28487c478bd9Sstevel@tonic-gate sizeof (valptr->zone_rctlval_action)) != Z_OK) 28497c478bd9Sstevel@tonic-gate break; 28507c478bd9Sstevel@tonic-gate if (zonecfg_add_rctl_value(tabptr, valptr) != Z_OK) 28517c478bd9Sstevel@tonic-gate break; 28527c478bd9Sstevel@tonic-gate } 28537c478bd9Sstevel@tonic-gate 28547c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur->next; 28557c478bd9Sstevel@tonic-gate return (Z_OK); 28567c478bd9Sstevel@tonic-gate } 28577c478bd9Sstevel@tonic-gate 28587c478bd9Sstevel@tonic-gate int 28597c478bd9Sstevel@tonic-gate zonecfg_endrctlent(zone_dochandle_t handle) 28607c478bd9Sstevel@tonic-gate { 28617c478bd9Sstevel@tonic-gate return (zonecfg_endent(handle)); 28627c478bd9Sstevel@tonic-gate } 28637c478bd9Sstevel@tonic-gate 28647c478bd9Sstevel@tonic-gate int 28657c478bd9Sstevel@tonic-gate zonecfg_setattrent(zone_dochandle_t handle) 28667c478bd9Sstevel@tonic-gate { 28677c478bd9Sstevel@tonic-gate return (zonecfg_setent(handle)); 28687c478bd9Sstevel@tonic-gate } 28697c478bd9Sstevel@tonic-gate 28707c478bd9Sstevel@tonic-gate int 28717c478bd9Sstevel@tonic-gate zonecfg_getattrent(zone_dochandle_t handle, struct zone_attrtab *tabptr) 28727c478bd9Sstevel@tonic-gate { 28737c478bd9Sstevel@tonic-gate xmlNodePtr cur; 28747c478bd9Sstevel@tonic-gate int err; 28757c478bd9Sstevel@tonic-gate 28767c478bd9Sstevel@tonic-gate if (handle == NULL) 28777c478bd9Sstevel@tonic-gate return (Z_INVAL); 28787c478bd9Sstevel@tonic-gate 28797c478bd9Sstevel@tonic-gate if ((cur = handle->zone_dh_cur) == NULL) 28807c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 28817c478bd9Sstevel@tonic-gate 28827c478bd9Sstevel@tonic-gate for (; cur != NULL; cur = cur->next) 28837c478bd9Sstevel@tonic-gate if (!xmlStrcmp(cur->name, DTD_ELEM_ATTR)) 28847c478bd9Sstevel@tonic-gate break; 28857c478bd9Sstevel@tonic-gate if (cur == NULL) { 28867c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 28877c478bd9Sstevel@tonic-gate return (Z_NO_ENTRY); 28887c478bd9Sstevel@tonic-gate } 28897c478bd9Sstevel@tonic-gate 28907c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_NAME, tabptr->zone_attr_name, 28917c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_attr_name))) != Z_OK) { 28927c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 28937c478bd9Sstevel@tonic-gate return (err); 28947c478bd9Sstevel@tonic-gate } 28957c478bd9Sstevel@tonic-gate 28967c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_TYPE, tabptr->zone_attr_type, 28977c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_attr_type))) != Z_OK) { 28987c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 28997c478bd9Sstevel@tonic-gate return (err); 29007c478bd9Sstevel@tonic-gate } 29017c478bd9Sstevel@tonic-gate 29027c478bd9Sstevel@tonic-gate if ((err = fetchprop(cur, DTD_ATTR_VALUE, tabptr->zone_attr_value, 29037c478bd9Sstevel@tonic-gate sizeof (tabptr->zone_attr_value))) != Z_OK) { 29047c478bd9Sstevel@tonic-gate handle->zone_dh_cur = handle->zone_dh_top; 29057c478bd9Sstevel@tonic-gate return (err); 29067c478bd9Sstevel@tonic-gate } 29077c478bd9Sstevel@tonic-gate 29087c478bd9Sstevel@tonic-gate handle->zone_dh_cur = cur->next; 29097c478bd9Sstevel@tonic-gate return (Z_OK); 29107c478bd9Sstevel@tonic-gate } 29117c478bd9Sstevel@tonic-gate 29127c478bd9Sstevel@tonic-gate int 29137c478bd9Sstevel@tonic-gate zonecfg_endattrent(zone_dochandle_t handle) 29147c478bd9Sstevel@tonic-gate { 29157c478bd9Sstevel@tonic-gate return (zonecfg_endent(handle)); 29167c478bd9Sstevel@tonic-gate } 29177c478bd9Sstevel@tonic-gate 29187c478bd9Sstevel@tonic-gate /* This will ultimately be configurable. */ 29197c478bd9Sstevel@tonic-gate static const char *priv_list[] = { 29207c478bd9Sstevel@tonic-gate PRIV_FILE_CHOWN, 29217c478bd9Sstevel@tonic-gate PRIV_FILE_CHOWN_SELF, 29227c478bd9Sstevel@tonic-gate PRIV_FILE_DAC_EXECUTE, 29237c478bd9Sstevel@tonic-gate PRIV_FILE_DAC_READ, 29247c478bd9Sstevel@tonic-gate PRIV_FILE_DAC_SEARCH, 29257c478bd9Sstevel@tonic-gate PRIV_FILE_DAC_WRITE, 29267c478bd9Sstevel@tonic-gate PRIV_FILE_OWNER, 29277c478bd9Sstevel@tonic-gate PRIV_FILE_SETID, 29287c478bd9Sstevel@tonic-gate PRIV_IPC_DAC_READ, 29297c478bd9Sstevel@tonic-gate PRIV_IPC_DAC_WRITE, 29307c478bd9Sstevel@tonic-gate PRIV_IPC_OWNER, 29317c478bd9Sstevel@tonic-gate PRIV_NET_ICMPACCESS, 29327c478bd9Sstevel@tonic-gate PRIV_NET_PRIVADDR, 29337c478bd9Sstevel@tonic-gate PRIV_PROC_CHROOT, 29347c478bd9Sstevel@tonic-gate PRIV_SYS_AUDIT, 29357c478bd9Sstevel@tonic-gate PRIV_PROC_AUDIT, 29367c478bd9Sstevel@tonic-gate PRIV_PROC_OWNER, 29377c478bd9Sstevel@tonic-gate PRIV_PROC_SETID, 29387c478bd9Sstevel@tonic-gate PRIV_PROC_TASKID, 29397c478bd9Sstevel@tonic-gate PRIV_SYS_ACCT, 29407c478bd9Sstevel@tonic-gate PRIV_SYS_ADMIN, 29417c478bd9Sstevel@tonic-gate PRIV_SYS_MOUNT, 29427c478bd9Sstevel@tonic-gate PRIV_SYS_NFS, 29437c478bd9Sstevel@tonic-gate PRIV_SYS_RESOURCE, 29447c478bd9Sstevel@tonic-gate PRIV_CONTRACT_EVENT, 29457c478bd9Sstevel@tonic-gate PRIV_CONTRACT_OBSERVER, 29467c478bd9Sstevel@tonic-gate NULL 29477c478bd9Sstevel@tonic-gate }; 29487c478bd9Sstevel@tonic-gate 29497c478bd9Sstevel@tonic-gate int 29507c478bd9Sstevel@tonic-gate zonecfg_get_privset(priv_set_t *privs) 29517c478bd9Sstevel@tonic-gate { 29527c478bd9Sstevel@tonic-gate const char **strp; 29537c478bd9Sstevel@tonic-gate priv_set_t *basic = priv_str_to_set("basic", ",", NULL); 29547c478bd9Sstevel@tonic-gate 29557c478bd9Sstevel@tonic-gate if (basic == NULL) 29567c478bd9Sstevel@tonic-gate return (Z_INVAL); 29577c478bd9Sstevel@tonic-gate 29587c478bd9Sstevel@tonic-gate priv_union(basic, privs); 29597c478bd9Sstevel@tonic-gate priv_freeset(basic); 29607c478bd9Sstevel@tonic-gate 29617c478bd9Sstevel@tonic-gate for (strp = priv_list; *strp != NULL; strp++) { 29627c478bd9Sstevel@tonic-gate if (priv_addset(privs, *strp) != 0) { 29637c478bd9Sstevel@tonic-gate return (Z_INVAL); 29647c478bd9Sstevel@tonic-gate } 29657c478bd9Sstevel@tonic-gate } 29667c478bd9Sstevel@tonic-gate return (Z_OK); 29677c478bd9Sstevel@tonic-gate } 29687c478bd9Sstevel@tonic-gate 29697c478bd9Sstevel@tonic-gate int 29707c478bd9Sstevel@tonic-gate zone_get_zonepath(char *zone_name, char *zonepath, size_t rp_sz) 29717c478bd9Sstevel@tonic-gate { 29727c478bd9Sstevel@tonic-gate zone_dochandle_t handle; 29737c478bd9Sstevel@tonic-gate boolean_t found = B_FALSE; 29747c478bd9Sstevel@tonic-gate struct zoneent *ze; 29757c478bd9Sstevel@tonic-gate FILE *cookie; 29767c478bd9Sstevel@tonic-gate int err; 29777c478bd9Sstevel@tonic-gate 29787c478bd9Sstevel@tonic-gate if (zone_name == NULL) 29797c478bd9Sstevel@tonic-gate return (Z_INVAL); 29807c478bd9Sstevel@tonic-gate 29817c478bd9Sstevel@tonic-gate if (strcmp(zone_name, GLOBAL_ZONENAME) == 0) { 29827c478bd9Sstevel@tonic-gate (void) strlcpy(zonepath, "/", rp_sz); 29837c478bd9Sstevel@tonic-gate return (Z_OK); 29847c478bd9Sstevel@tonic-gate } 29857c478bd9Sstevel@tonic-gate 29867c478bd9Sstevel@tonic-gate /* 29877c478bd9Sstevel@tonic-gate * First check the index file. Because older versions did not have 29887c478bd9Sstevel@tonic-gate * a copy of the zone path, allow for it to be zero length, in which 29897c478bd9Sstevel@tonic-gate * case we ignore this result and fall back to the XML files. 29907c478bd9Sstevel@tonic-gate */ 29917c478bd9Sstevel@tonic-gate (void) strlcpy(zonepath, "", rp_sz); 29927c478bd9Sstevel@tonic-gate cookie = setzoneent(); 29937c478bd9Sstevel@tonic-gate while ((ze = getzoneent_private(cookie)) != NULL) { 29947c478bd9Sstevel@tonic-gate if (strcmp(ze->zone_name, zone_name) == 0) { 29957c478bd9Sstevel@tonic-gate found = B_TRUE; 29967c478bd9Sstevel@tonic-gate if (strlen(ze->zone_path) > 0) 29977c478bd9Sstevel@tonic-gate (void) strlcpy(zonepath, ze->zone_path, rp_sz); 29987c478bd9Sstevel@tonic-gate } 29997c478bd9Sstevel@tonic-gate free(ze); 30007c478bd9Sstevel@tonic-gate if (found) 30017c478bd9Sstevel@tonic-gate break; 30027c478bd9Sstevel@tonic-gate } 30037c478bd9Sstevel@tonic-gate endzoneent(cookie); 30047c478bd9Sstevel@tonic-gate if (found && strlen(zonepath) > 0) 30057c478bd9Sstevel@tonic-gate return (Z_OK); 30067c478bd9Sstevel@tonic-gate 30077c478bd9Sstevel@tonic-gate /* Fall back to the XML files. */ 30087c478bd9Sstevel@tonic-gate if ((handle = zonecfg_init_handle()) == NULL) 30097c478bd9Sstevel@tonic-gate return (Z_NOMEM); 30107c478bd9Sstevel@tonic-gate 30117c478bd9Sstevel@tonic-gate /* 30127c478bd9Sstevel@tonic-gate * Check the snapshot first: if a zone is running, its zonepath 30137c478bd9Sstevel@tonic-gate * may have changed. 30147c478bd9Sstevel@tonic-gate */ 30157c478bd9Sstevel@tonic-gate if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) { 30167c478bd9Sstevel@tonic-gate if ((err = zonecfg_get_handle(zone_name, handle)) != Z_OK) 30177c478bd9Sstevel@tonic-gate return (err); 30187c478bd9Sstevel@tonic-gate } 30197c478bd9Sstevel@tonic-gate err = zonecfg_get_zonepath(handle, zonepath, rp_sz); 30207c478bd9Sstevel@tonic-gate zonecfg_fini_handle(handle); 30217c478bd9Sstevel@tonic-gate return (err); 30227c478bd9Sstevel@tonic-gate } 30237c478bd9Sstevel@tonic-gate 30247c478bd9Sstevel@tonic-gate int 30257c478bd9Sstevel@tonic-gate zone_get_rootpath(char *zone_name, char *rootpath, size_t rp_sz) 30267c478bd9Sstevel@tonic-gate { 30277c478bd9Sstevel@tonic-gate int err; 30287c478bd9Sstevel@tonic-gate 30297c478bd9Sstevel@tonic-gate /* This function makes sense for non-global zones only. */ 30307c478bd9Sstevel@tonic-gate if (strcmp(zone_name, GLOBAL_ZONENAME) == 0) 30317c478bd9Sstevel@tonic-gate return (Z_BOGUS_ZONE_NAME); 30327c478bd9Sstevel@tonic-gate if ((err = zone_get_zonepath(zone_name, rootpath, rp_sz)) != Z_OK) 30337c478bd9Sstevel@tonic-gate return (err); 30347c478bd9Sstevel@tonic-gate if (strlcat(rootpath, "/root", rp_sz) >= rp_sz) 30357c478bd9Sstevel@tonic-gate return (Z_TOO_BIG); 30367c478bd9Sstevel@tonic-gate return (Z_OK); 30377c478bd9Sstevel@tonic-gate } 30387c478bd9Sstevel@tonic-gate 30397c478bd9Sstevel@tonic-gate static zone_state_t 30407c478bd9Sstevel@tonic-gate kernel_state_to_user_state(zone_status_t kernel_state) 30417c478bd9Sstevel@tonic-gate { 30427c478bd9Sstevel@tonic-gate assert(kernel_state <= ZONE_MAX_STATE); 30437c478bd9Sstevel@tonic-gate switch (kernel_state) { 30447c478bd9Sstevel@tonic-gate case ZONE_IS_UNINITIALIZED: 30457c478bd9Sstevel@tonic-gate case ZONE_IS_READY: 30467c478bd9Sstevel@tonic-gate return (ZONE_STATE_READY); 30477c478bd9Sstevel@tonic-gate case ZONE_IS_BOOTING: 30487c478bd9Sstevel@tonic-gate case ZONE_IS_RUNNING: 30497c478bd9Sstevel@tonic-gate return (ZONE_STATE_RUNNING); 30507c478bd9Sstevel@tonic-gate case ZONE_IS_SHUTTING_DOWN: 30517c478bd9Sstevel@tonic-gate case ZONE_IS_EMPTY: 30527c478bd9Sstevel@tonic-gate return (ZONE_STATE_SHUTTING_DOWN); 30537c478bd9Sstevel@tonic-gate case ZONE_IS_DOWN: 30547c478bd9Sstevel@tonic-gate case ZONE_IS_DYING: 30557c478bd9Sstevel@tonic-gate case ZONE_IS_DEAD: 30567c478bd9Sstevel@tonic-gate default: 30577c478bd9Sstevel@tonic-gate return (ZONE_STATE_DOWN); 30587c478bd9Sstevel@tonic-gate } 30597c478bd9Sstevel@tonic-gate /* NOTREACHED */ 30607c478bd9Sstevel@tonic-gate } 30617c478bd9Sstevel@tonic-gate 30627c478bd9Sstevel@tonic-gate int 30637c478bd9Sstevel@tonic-gate zone_get_state(char *zone_name, zone_state_t *state_num) 30647c478bd9Sstevel@tonic-gate { 30657c478bd9Sstevel@tonic-gate zone_status_t status; 30667c478bd9Sstevel@tonic-gate zoneid_t zone_id; 30677c478bd9Sstevel@tonic-gate struct zoneent *ze; 30687c478bd9Sstevel@tonic-gate boolean_t found = B_FALSE; 30697c478bd9Sstevel@tonic-gate FILE *cookie; 30707c478bd9Sstevel@tonic-gate 30717c478bd9Sstevel@tonic-gate if (zone_name == NULL) 30727c478bd9Sstevel@tonic-gate return (Z_INVAL); 30737c478bd9Sstevel@tonic-gate 30747c478bd9Sstevel@tonic-gate /* check to see if zone is running */ 30757c478bd9Sstevel@tonic-gate if ((zone_id = getzoneidbyname(zone_name)) != -1 && 30767c478bd9Sstevel@tonic-gate zone_getattr(zone_id, ZONE_ATTR_STATUS, &status, 30777c478bd9Sstevel@tonic-gate sizeof (status)) >= 0) { 30787c478bd9Sstevel@tonic-gate *state_num = kernel_state_to_user_state(status); 30797c478bd9Sstevel@tonic-gate return (Z_OK); 30807c478bd9Sstevel@tonic-gate } 30817c478bd9Sstevel@tonic-gate 30827c478bd9Sstevel@tonic-gate cookie = setzoneent(); 30837c478bd9Sstevel@tonic-gate while ((ze = getzoneent_private(cookie)) != NULL) { 30847c478bd9Sstevel@tonic-gate if (strcmp(ze->zone_name, zone_name) == 0) { 30857c478bd9Sstevel@tonic-gate found = B_TRUE; 30867c478bd9Sstevel@tonic-gate *state_num = ze->zone_state; 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); 30937c478bd9Sstevel@tonic-gate return ((found) ? Z_OK : Z_NO_ZONE); 30947c478bd9Sstevel@tonic-gate } 30957c478bd9Sstevel@tonic-gate 30967c478bd9Sstevel@tonic-gate int 30977c478bd9Sstevel@tonic-gate zone_set_state(char *zone, zone_state_t state) 30987c478bd9Sstevel@tonic-gate { 30997c478bd9Sstevel@tonic-gate struct zoneent ze; 31007c478bd9Sstevel@tonic-gate 31017c478bd9Sstevel@tonic-gate if (state != ZONE_STATE_CONFIGURED && state != ZONE_STATE_INSTALLED && 31027c478bd9Sstevel@tonic-gate state != ZONE_STATE_INCOMPLETE) 31037c478bd9Sstevel@tonic-gate return (Z_INVAL); 31047c478bd9Sstevel@tonic-gate 3105*087719fdSdp bzero(&ze, sizeof (ze)); 31067c478bd9Sstevel@tonic-gate (void) strlcpy(ze.zone_name, zone, sizeof (ze.zone_name)); 31077c478bd9Sstevel@tonic-gate ze.zone_state = state; 31087c478bd9Sstevel@tonic-gate (void) strlcpy(ze.zone_path, "", sizeof (ze.zone_path)); 31097c478bd9Sstevel@tonic-gate return (putzoneent(&ze, PZE_MODIFY)); 31107c478bd9Sstevel@tonic-gate } 31117c478bd9Sstevel@tonic-gate 31127c478bd9Sstevel@tonic-gate /* 31137c478bd9Sstevel@tonic-gate * Get id (if any) for specified zone. There are four possible outcomes: 31147c478bd9Sstevel@tonic-gate * - If the string corresponds to the numeric id of an active (booted) 31157c478bd9Sstevel@tonic-gate * zone, sets *zip to the zone id and returns 0. 31167c478bd9Sstevel@tonic-gate * - If the string corresponds to the name of an active (booted) zone, 31177c478bd9Sstevel@tonic-gate * sets *zip to the zone id and returns 0. 31187c478bd9Sstevel@tonic-gate * - If the string is a name in the configuration but is not booted, 31197c478bd9Sstevel@tonic-gate * sets *zip to ZONE_ID_UNDEFINED and returns 0. 31207c478bd9Sstevel@tonic-gate * - Otherwise, leaves *zip unchanged and returns -1. 31217c478bd9Sstevel@tonic-gate * 31227c478bd9Sstevel@tonic-gate * This function acts as an auxiliary filter on the function of the same 31237c478bd9Sstevel@tonic-gate * name in libc; the linker binds to this version if libzonecfg exists, 31247c478bd9Sstevel@tonic-gate * and the libc version if it doesn't. Any changes to this version of 31257c478bd9Sstevel@tonic-gate * the function should probably be reflected in the libc version as well. 31267c478bd9Sstevel@tonic-gate */ 31277c478bd9Sstevel@tonic-gate int 31287c478bd9Sstevel@tonic-gate zone_get_id(const char *str, zoneid_t *zip) 31297c478bd9Sstevel@tonic-gate { 31307c478bd9Sstevel@tonic-gate zone_dochandle_t hdl; 31317c478bd9Sstevel@tonic-gate zoneid_t zoneid; 31327c478bd9Sstevel@tonic-gate char *cp; 31337c478bd9Sstevel@tonic-gate int err; 31347c478bd9Sstevel@tonic-gate 31357c478bd9Sstevel@tonic-gate /* first try looking for active zone by id */ 31367c478bd9Sstevel@tonic-gate errno = 0; 31377c478bd9Sstevel@tonic-gate zoneid = (zoneid_t)strtol(str, &cp, 0); 31387c478bd9Sstevel@tonic-gate if (errno == 0 && cp != str && *cp == '\0' && 31397c478bd9Sstevel@tonic-gate getzonenamebyid(zoneid, NULL, 0) != -1) { 31407c478bd9Sstevel@tonic-gate *zip = zoneid; 31417c478bd9Sstevel@tonic-gate return (0); 31427c478bd9Sstevel@tonic-gate } 31437c478bd9Sstevel@tonic-gate 31447c478bd9Sstevel@tonic-gate /* then look for active zone by name */ 31457c478bd9Sstevel@tonic-gate if ((zoneid = getzoneidbyname(str)) != -1) { 31467c478bd9Sstevel@tonic-gate *zip = zoneid; 31477c478bd9Sstevel@tonic-gate return (0); 31487c478bd9Sstevel@tonic-gate } 31497c478bd9Sstevel@tonic-gate 31507c478bd9Sstevel@tonic-gate /* if in global zone, try looking up name in configuration database */ 31517c478bd9Sstevel@tonic-gate if (getzoneid() != GLOBAL_ZONEID || 31527c478bd9Sstevel@tonic-gate (hdl = zonecfg_init_handle()) == NULL) 31537c478bd9Sstevel@tonic-gate return (-1); 31547c478bd9Sstevel@tonic-gate 31557c478bd9Sstevel@tonic-gate if (zonecfg_get_handle((char *)str, hdl) == Z_OK) { 31567c478bd9Sstevel@tonic-gate /* zone exists but isn't active */ 31577c478bd9Sstevel@tonic-gate *zip = ZONE_ID_UNDEFINED; 31587c478bd9Sstevel@tonic-gate err = 0; 31597c478bd9Sstevel@tonic-gate } else { 31607c478bd9Sstevel@tonic-gate err = -1; 31617c478bd9Sstevel@tonic-gate } 31627c478bd9Sstevel@tonic-gate 31637c478bd9Sstevel@tonic-gate zonecfg_fini_handle(hdl); 31647c478bd9Sstevel@tonic-gate return (err); 31657c478bd9Sstevel@tonic-gate } 31667c478bd9Sstevel@tonic-gate 31677c478bd9Sstevel@tonic-gate char * 31687c478bd9Sstevel@tonic-gate zone_state_str(zone_state_t state_num) 31697c478bd9Sstevel@tonic-gate { 31707c478bd9Sstevel@tonic-gate switch (state_num) { 31717c478bd9Sstevel@tonic-gate case ZONE_STATE_CONFIGURED: 31727c478bd9Sstevel@tonic-gate return (ZONE_STATE_STR_CONFIGURED); 31737c478bd9Sstevel@tonic-gate case ZONE_STATE_INCOMPLETE: 31747c478bd9Sstevel@tonic-gate return (ZONE_STATE_STR_INCOMPLETE); 31757c478bd9Sstevel@tonic-gate case ZONE_STATE_INSTALLED: 31767c478bd9Sstevel@tonic-gate return (ZONE_STATE_STR_INSTALLED); 31777c478bd9Sstevel@tonic-gate case ZONE_STATE_READY: 31787c478bd9Sstevel@tonic-gate return (ZONE_STATE_STR_READY); 31797c478bd9Sstevel@tonic-gate case ZONE_STATE_RUNNING: 31807c478bd9Sstevel@tonic-gate return (ZONE_STATE_STR_RUNNING); 31817c478bd9Sstevel@tonic-gate case ZONE_STATE_SHUTTING_DOWN: 31827c478bd9Sstevel@tonic-gate return (ZONE_STATE_STR_SHUTTING_DOWN); 31837c478bd9Sstevel@tonic-gate case ZONE_STATE_DOWN: 31847c478bd9Sstevel@tonic-gate return (ZONE_STATE_STR_DOWN); 31857c478bd9Sstevel@tonic-gate default: 31867c478bd9Sstevel@tonic-gate return ("unknown"); 31877c478bd9Sstevel@tonic-gate } 31887c478bd9Sstevel@tonic-gate } 31897c478bd9Sstevel@tonic-gate 31907c478bd9Sstevel@tonic-gate /* 31917c478bd9Sstevel@tonic-gate * File-system convenience functions. 31927c478bd9Sstevel@tonic-gate */ 31937c478bd9Sstevel@tonic-gate boolean_t 31947c478bd9Sstevel@tonic-gate zonecfg_valid_fs_type(const char *type) 31957c478bd9Sstevel@tonic-gate { 31967c478bd9Sstevel@tonic-gate /* 31977c478bd9Sstevel@tonic-gate * We already know which FS types don't work. 31987c478bd9Sstevel@tonic-gate */ 31997c478bd9Sstevel@tonic-gate if (strcmp(type, "proc") == 0 || 32007c478bd9Sstevel@tonic-gate strcmp(type, "mntfs") == 0 || 32017c478bd9Sstevel@tonic-gate strcmp(type, "autofs") == 0 || 32027c478bd9Sstevel@tonic-gate strncmp(type, "nfs", sizeof ("nfs") - 1) == 0 || 32037c478bd9Sstevel@tonic-gate strcmp(type, "cachefs") == 0) 32047c478bd9Sstevel@tonic-gate return (B_FALSE); 32057c478bd9Sstevel@tonic-gate /* 32067c478bd9Sstevel@tonic-gate * The caller may do more detailed verification to make sure other 32077c478bd9Sstevel@tonic-gate * aspects of this filesystem type make sense. 32087c478bd9Sstevel@tonic-gate */ 32097c478bd9Sstevel@tonic-gate return (B_TRUE); 32107c478bd9Sstevel@tonic-gate } 32117c478bd9Sstevel@tonic-gate 32127c478bd9Sstevel@tonic-gate /* 32137c478bd9Sstevel@tonic-gate * Generally uninteresting rctl convenience functions. 32147c478bd9Sstevel@tonic-gate */ 32157c478bd9Sstevel@tonic-gate 32167c478bd9Sstevel@tonic-gate int 32177c478bd9Sstevel@tonic-gate zonecfg_construct_rctlblk(const struct zone_rctlvaltab *rctlval, 32187c478bd9Sstevel@tonic-gate rctlblk_t *rctlblk) 32197c478bd9Sstevel@tonic-gate { 32207c478bd9Sstevel@tonic-gate unsigned long long ull; 32217c478bd9Sstevel@tonic-gate char *endp; 32227c478bd9Sstevel@tonic-gate rctl_priv_t priv; 32237c478bd9Sstevel@tonic-gate rctl_qty_t limit; 32247c478bd9Sstevel@tonic-gate uint_t action; 32257c478bd9Sstevel@tonic-gate 32267c478bd9Sstevel@tonic-gate /* Get the privilege */ 32277c478bd9Sstevel@tonic-gate if (strcmp(rctlval->zone_rctlval_priv, "basic") == 0) { 32287c478bd9Sstevel@tonic-gate priv = RCPRIV_BASIC; 32297c478bd9Sstevel@tonic-gate } else if (strcmp(rctlval->zone_rctlval_priv, "privileged") == 0) { 32307c478bd9Sstevel@tonic-gate priv = RCPRIV_PRIVILEGED; 32317c478bd9Sstevel@tonic-gate } else { 32327c478bd9Sstevel@tonic-gate /* Invalid privilege */ 32337c478bd9Sstevel@tonic-gate return (Z_INVAL); 32347c478bd9Sstevel@tonic-gate } 32357c478bd9Sstevel@tonic-gate 32367c478bd9Sstevel@tonic-gate /* deal with negative input; strtoull(3c) doesn't do what we want */ 32377c478bd9Sstevel@tonic-gate if (rctlval->zone_rctlval_limit[0] == '-') 32387c478bd9Sstevel@tonic-gate return (Z_INVAL); 32397c478bd9Sstevel@tonic-gate /* Get the limit */ 32407c478bd9Sstevel@tonic-gate errno = 0; 32417c478bd9Sstevel@tonic-gate ull = strtoull(rctlval->zone_rctlval_limit, &endp, 0); 32427c478bd9Sstevel@tonic-gate if (errno != 0 || *endp != '\0') { 32437c478bd9Sstevel@tonic-gate /* parse failed */ 32447c478bd9Sstevel@tonic-gate return (Z_INVAL); 32457c478bd9Sstevel@tonic-gate } 32467c478bd9Sstevel@tonic-gate limit = (rctl_qty_t)ull; 32477c478bd9Sstevel@tonic-gate 32487c478bd9Sstevel@tonic-gate /* Get the action */ 32497c478bd9Sstevel@tonic-gate if (strcmp(rctlval->zone_rctlval_action, "none") == 0) { 32507c478bd9Sstevel@tonic-gate action = RCTL_LOCAL_NOACTION; 32517c478bd9Sstevel@tonic-gate } else if (strcmp(rctlval->zone_rctlval_action, "signal") == 0) { 32527c478bd9Sstevel@tonic-gate action = RCTL_LOCAL_SIGNAL; 32537c478bd9Sstevel@tonic-gate } else if (strcmp(rctlval->zone_rctlval_action, "deny") == 0) { 32547c478bd9Sstevel@tonic-gate action = RCTL_LOCAL_DENY; 32557c478bd9Sstevel@tonic-gate } else { 32567c478bd9Sstevel@tonic-gate /* Invalid Action */ 32577c478bd9Sstevel@tonic-gate return (Z_INVAL); 32587c478bd9Sstevel@tonic-gate } 32597c478bd9Sstevel@tonic-gate rctlblk_set_local_action(rctlblk, action, 0); 32607c478bd9Sstevel@tonic-gate rctlblk_set_privilege(rctlblk, priv); 32617c478bd9Sstevel@tonic-gate rctlblk_set_value(rctlblk, limit); 32627c478bd9Sstevel@tonic-gate return (Z_OK); 32637c478bd9Sstevel@tonic-gate } 32647c478bd9Sstevel@tonic-gate 32657c478bd9Sstevel@tonic-gate static int 32667c478bd9Sstevel@tonic-gate rctl_check(const char *rctlname, void *arg) 32677c478bd9Sstevel@tonic-gate { 32687c478bd9Sstevel@tonic-gate const char *attrname = arg; 32697c478bd9Sstevel@tonic-gate 32707c478bd9Sstevel@tonic-gate /* 32717c478bd9Sstevel@tonic-gate * Returning 1 here is our signal to zonecfg_is_rctl() that it is 32727c478bd9Sstevel@tonic-gate * indeed an rctl name recognized by the system. 32737c478bd9Sstevel@tonic-gate */ 32747c478bd9Sstevel@tonic-gate return (strcmp(rctlname, attrname) == 0 ? 1 : 0); 32757c478bd9Sstevel@tonic-gate } 32767c478bd9Sstevel@tonic-gate 32777c478bd9Sstevel@tonic-gate boolean_t 32787c478bd9Sstevel@tonic-gate zonecfg_is_rctl(const char *name) 32797c478bd9Sstevel@tonic-gate { 32807c478bd9Sstevel@tonic-gate return (rctl_walk(rctl_check, (void *)name) == 1); 32817c478bd9Sstevel@tonic-gate } 32827c478bd9Sstevel@tonic-gate 32837c478bd9Sstevel@tonic-gate boolean_t 32847c478bd9Sstevel@tonic-gate zonecfg_valid_rctlname(const char *name) 32857c478bd9Sstevel@tonic-gate { 32867c478bd9Sstevel@tonic-gate const char *c; 32877c478bd9Sstevel@tonic-gate 32887c478bd9Sstevel@tonic-gate if (strncmp(name, "zone.", sizeof ("zone.") - 1) != 0) 32897c478bd9Sstevel@tonic-gate return (B_FALSE); 32907c478bd9Sstevel@tonic-gate if (strlen(name) == sizeof ("zone.") - 1) 32917c478bd9Sstevel@tonic-gate return (B_FALSE); 32927c478bd9Sstevel@tonic-gate for (c = name + sizeof ("zone.") - 1; *c != '\0'; c++) { 32937c478bd9Sstevel@tonic-gate if (!isalpha(*c) && *c != '-') 32947c478bd9Sstevel@tonic-gate return (B_FALSE); 32957c478bd9Sstevel@tonic-gate } 32967c478bd9Sstevel@tonic-gate return (B_TRUE); 32977c478bd9Sstevel@tonic-gate } 32987c478bd9Sstevel@tonic-gate 32997c478bd9Sstevel@tonic-gate boolean_t 33007c478bd9Sstevel@tonic-gate zonecfg_valid_rctlblk(const rctlblk_t *rctlblk) 33017c478bd9Sstevel@tonic-gate { 33027c478bd9Sstevel@tonic-gate rctl_priv_t priv = rctlblk_get_privilege((rctlblk_t *)rctlblk); 33037c478bd9Sstevel@tonic-gate uint_t action = rctlblk_get_local_action((rctlblk_t *)rctlblk, NULL); 33047c478bd9Sstevel@tonic-gate 33057c478bd9Sstevel@tonic-gate if (priv != RCPRIV_PRIVILEGED) 33067c478bd9Sstevel@tonic-gate return (B_FALSE); 33077c478bd9Sstevel@tonic-gate if (action != RCTL_LOCAL_NOACTION && action != RCTL_LOCAL_DENY) 33087c478bd9Sstevel@tonic-gate return (B_FALSE); 33097c478bd9Sstevel@tonic-gate return (B_TRUE); 33107c478bd9Sstevel@tonic-gate } 33117c478bd9Sstevel@tonic-gate 33127c478bd9Sstevel@tonic-gate boolean_t 33137c478bd9Sstevel@tonic-gate zonecfg_valid_rctl(const char *name, const rctlblk_t *rctlblk) 33147c478bd9Sstevel@tonic-gate { 33157c478bd9Sstevel@tonic-gate rctlblk_t *current, *next; 33167c478bd9Sstevel@tonic-gate rctl_qty_t limit = rctlblk_get_value((rctlblk_t *)rctlblk); 33177c478bd9Sstevel@tonic-gate uint_t action = rctlblk_get_local_action((rctlblk_t *)rctlblk, NULL); 33187c478bd9Sstevel@tonic-gate uint_t global_flags; 33197c478bd9Sstevel@tonic-gate 33207c478bd9Sstevel@tonic-gate if (!zonecfg_valid_rctlblk(rctlblk)) 33217c478bd9Sstevel@tonic-gate return (B_FALSE); 33227c478bd9Sstevel@tonic-gate if (!zonecfg_valid_rctlname(name)) 33237c478bd9Sstevel@tonic-gate return (B_FALSE); 33247c478bd9Sstevel@tonic-gate 33257c478bd9Sstevel@tonic-gate current = alloca(rctlblk_size()); 33267c478bd9Sstevel@tonic-gate if (getrctl(name, NULL, current, RCTL_FIRST) != 0) 33277c478bd9Sstevel@tonic-gate return (B_TRUE); /* not an rctl on this system */ 33287c478bd9Sstevel@tonic-gate /* 33297c478bd9Sstevel@tonic-gate * Make sure the proposed value isn't greater than the current system 33307c478bd9Sstevel@tonic-gate * value. 33317c478bd9Sstevel@tonic-gate */ 33327c478bd9Sstevel@tonic-gate next = alloca(rctlblk_size()); 33337c478bd9Sstevel@tonic-gate while (rctlblk_get_privilege(current) != RCPRIV_SYSTEM) { 33347c478bd9Sstevel@tonic-gate rctlblk_t *tmp; 33357c478bd9Sstevel@tonic-gate 33367c478bd9Sstevel@tonic-gate if (getrctl(name, current, next, RCTL_NEXT) != 0) 33377c478bd9Sstevel@tonic-gate return (B_FALSE); /* shouldn't happen */ 33387c478bd9Sstevel@tonic-gate tmp = current; 33397c478bd9Sstevel@tonic-gate current = next; 33407c478bd9Sstevel@tonic-gate next = tmp; 33417c478bd9Sstevel@tonic-gate } 33427c478bd9Sstevel@tonic-gate if (limit > rctlblk_get_value(current)) 33437c478bd9Sstevel@tonic-gate return (B_FALSE); 33447c478bd9Sstevel@tonic-gate 33457c478bd9Sstevel@tonic-gate /* 33467c478bd9Sstevel@tonic-gate * Make sure the proposed action is allowed. 33477c478bd9Sstevel@tonic-gate */ 33487c478bd9Sstevel@tonic-gate global_flags = rctlblk_get_global_flags(current); 33497c478bd9Sstevel@tonic-gate if ((global_flags & RCTL_GLOBAL_DENY_NEVER) && 33507c478bd9Sstevel@tonic-gate action == RCTL_LOCAL_DENY) 33517c478bd9Sstevel@tonic-gate return (B_FALSE); 33527c478bd9Sstevel@tonic-gate if ((global_flags & RCTL_GLOBAL_DENY_ALWAYS) && 33537c478bd9Sstevel@tonic-gate action == RCTL_LOCAL_NOACTION) 33547c478bd9Sstevel@tonic-gate return (B_FALSE); 33557c478bd9Sstevel@tonic-gate 33567c478bd9Sstevel@tonic-gate return (B_TRUE); 33577c478bd9Sstevel@tonic-gate } 3358