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>
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
437c478bd9Sstevel@tonic-gate #include <netdb.h>
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate #include <priv.h>
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate #include <libxml/xmlmemory.h>
487c478bd9Sstevel@tonic-gate #include <libxml/parser.h>
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate #include <libdevinfo.h>
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate #include <libzonecfg.h>
537c478bd9Sstevel@tonic-gate #include "zonecfg_impl.h"
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate #define	_PATH_TMPFILE	"/zonecfg.XXXXXX"
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate /* Hard-code the DTD element/attribute/entity names just once, here. */
587c478bd9Sstevel@tonic-gate #define	DTD_ELEM_ATTR		(const xmlChar *) "attr"
597c478bd9Sstevel@tonic-gate #define	DTD_ELEM_COMMENT	(const xmlChar *) "comment"
607c478bd9Sstevel@tonic-gate #define	DTD_ELEM_DEVICE		(const xmlChar *) "device"
617c478bd9Sstevel@tonic-gate #define	DTD_ELEM_FS		(const xmlChar *) "filesystem"
627c478bd9Sstevel@tonic-gate #define	DTD_ELEM_FSOPTION	(const xmlChar *) "fsoption"
637c478bd9Sstevel@tonic-gate #define	DTD_ELEM_IPD		(const xmlChar *) "inherited-pkg-dir"
647c478bd9Sstevel@tonic-gate #define	DTD_ELEM_NET		(const xmlChar *) "network"
657c478bd9Sstevel@tonic-gate #define	DTD_ELEM_RCTL		(const xmlChar *) "rctl"
667c478bd9Sstevel@tonic-gate #define	DTD_ELEM_RCTLVALUE	(const xmlChar *) "rctl-value"
677c478bd9Sstevel@tonic-gate #define	DTD_ELEM_ZONE		(const xmlChar *) "zone"
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate #define	DTD_ATTR_ACTION		(const xmlChar *) "action"
707c478bd9Sstevel@tonic-gate #define	DTD_ATTR_ADDRESS	(const xmlChar *) "address"
717c478bd9Sstevel@tonic-gate #define	DTD_ATTR_AUTOBOOT	(const xmlChar *) "autoboot"
727c478bd9Sstevel@tonic-gate #define	DTD_ATTR_DIR		(const xmlChar *) "directory"
737c478bd9Sstevel@tonic-gate #define	DTD_ATTR_LIMIT		(const xmlChar *) "limit"
747c478bd9Sstevel@tonic-gate #define	DTD_ATTR_MATCH		(const xmlChar *) "match"
757c478bd9Sstevel@tonic-gate #define	DTD_ATTR_NAME		(const xmlChar *) "name"
767c478bd9Sstevel@tonic-gate #define	DTD_ATTR_PHYSICAL	(const xmlChar *) "physical"
777c478bd9Sstevel@tonic-gate #define	DTD_ATTR_POOL		(const xmlChar *) "pool"
787c478bd9Sstevel@tonic-gate #define	DTD_ATTR_PRIV		(const xmlChar *) "priv"
797c478bd9Sstevel@tonic-gate #define	DTD_ATTR_RAW		(const xmlChar *) "raw"
807c478bd9Sstevel@tonic-gate #define	DTD_ATTR_SPECIAL	(const xmlChar *) "special"
817c478bd9Sstevel@tonic-gate #define	DTD_ATTR_TYPE		(const xmlChar *) "type"
827c478bd9Sstevel@tonic-gate #define	DTD_ATTR_VALUE		(const xmlChar *) "value"
837c478bd9Sstevel@tonic-gate #define	DTD_ATTR_ZONEPATH	(const xmlChar *) "zonepath"
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate #define	DTD_ENTITY_BOOLEAN	"boolean"
867c478bd9Sstevel@tonic-gate #define	DTD_ENTITY_DEVPATH	"devpath"
877c478bd9Sstevel@tonic-gate #define	DTD_ENTITY_DRIVER	"driver"
887c478bd9Sstevel@tonic-gate #define	DTD_ENTITY_DRVMIN	"drv_min"
897c478bd9Sstevel@tonic-gate #define	DTD_ENTITY_FALSE	"false"
907c478bd9Sstevel@tonic-gate #define	DTD_ENTITY_INT		"int"
917c478bd9Sstevel@tonic-gate #define	DTD_ENTITY_STRING	"string"
927c478bd9Sstevel@tonic-gate #define	DTD_ENTITY_TRUE		"true"
937c478bd9Sstevel@tonic-gate #define	DTD_ENTITY_UINT		"uint"
947c478bd9Sstevel@tonic-gate 
95*a1be23daSdp #define	DTD_ENTITY_BOOL_LEN	6	/* "false" */
96*a1be23daSdp 
977c478bd9Sstevel@tonic-gate struct zone_dochandle {
987c478bd9Sstevel@tonic-gate 	char		*zone_dh_rootdir;
997c478bd9Sstevel@tonic-gate 	xmlDocPtr	zone_dh_doc;
1007c478bd9Sstevel@tonic-gate 	xmlNodePtr	zone_dh_cur;
1017c478bd9Sstevel@tonic-gate 	xmlNodePtr	zone_dh_top;
1027c478bd9Sstevel@tonic-gate };
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate /*
1057c478bd9Sstevel@tonic-gate  * For functions which return int, which is most of the functions herein,
1067c478bd9Sstevel@tonic-gate  * the return values should be from the Z_foo set defined in <libzonecfg.h>.
1077c478bd9Sstevel@tonic-gate  * In some instances, we take pains mapping some libc errno values to Z_foo
1087c478bd9Sstevel@tonic-gate  * values from this set.
1097c478bd9Sstevel@tonic-gate  */
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate /*
1127c478bd9Sstevel@tonic-gate  * Callers of the _file_path() functions are expected to have the second
1137c478bd9Sstevel@tonic-gate  * parameter be a (char foo[MAXPATHLEN]).
1147c478bd9Sstevel@tonic-gate  */
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate static void
1177c478bd9Sstevel@tonic-gate config_file_path(const char *zonename, char *answer)
1187c478bd9Sstevel@tonic-gate {
1197c478bd9Sstevel@tonic-gate 	(void) snprintf(answer, MAXPATHLEN,
1207c478bd9Sstevel@tonic-gate 	    "%s/%s.xml", ZONE_CONFIG_ROOT, zonename);
1217c478bd9Sstevel@tonic-gate }
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate static void
1247c478bd9Sstevel@tonic-gate snap_file_path(char *zonename, char *answer)
1257c478bd9Sstevel@tonic-gate {
1267c478bd9Sstevel@tonic-gate 	(void) snprintf(answer, MAXPATHLEN,
1277c478bd9Sstevel@tonic-gate 	    "%s/%s.snapshot.xml", ZONE_SNAPSHOT_ROOT, zonename);
1287c478bd9Sstevel@tonic-gate }
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1317c478bd9Sstevel@tonic-gate static void
1327c478bd9Sstevel@tonic-gate zonecfg_error_func(void *ctx, const char *msg, ...)
1337c478bd9Sstevel@tonic-gate {
1347c478bd9Sstevel@tonic-gate 	/*
1357c478bd9Sstevel@tonic-gate 	 * This function does nothing by design.  Its purpose is to prevent
1367c478bd9Sstevel@tonic-gate 	 * libxml from dumping unwanted messages to stdout/stderr.
1377c478bd9Sstevel@tonic-gate 	 */
1387c478bd9Sstevel@tonic-gate }
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate zone_dochandle_t
1417c478bd9Sstevel@tonic-gate zonecfg_init_handle(void)
1427c478bd9Sstevel@tonic-gate {
1437c478bd9Sstevel@tonic-gate 	zone_dochandle_t handle = malloc(sizeof (struct zone_dochandle));
1447c478bd9Sstevel@tonic-gate 	if (handle == NULL) {
1457c478bd9Sstevel@tonic-gate 		errno = Z_NOMEM;
1467c478bd9Sstevel@tonic-gate 		return (NULL);
1477c478bd9Sstevel@tonic-gate 	}
1487c478bd9Sstevel@tonic-gate 	handle->zone_dh_doc = NULL;
1497c478bd9Sstevel@tonic-gate 	handle->zone_dh_cur = NULL;
1507c478bd9Sstevel@tonic-gate 	handle->zone_dh_top = NULL;
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate 	/* generic libxml initialization */
1537c478bd9Sstevel@tonic-gate 	xmlLineNumbersDefault(1);
1547c478bd9Sstevel@tonic-gate 	xmlLoadExtDtdDefaultValue |= XML_DETECT_IDS;
1557c478bd9Sstevel@tonic-gate 	xmlDoValidityCheckingDefaultValue = 1;
1567c478bd9Sstevel@tonic-gate 	(void) xmlKeepBlanksDefault(0);
1577c478bd9Sstevel@tonic-gate 	xmlGetWarningsDefaultValue = 0;
1587c478bd9Sstevel@tonic-gate 	xmlSetGenericErrorFunc(NULL, zonecfg_error_func);
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate 	return (handle);
1617c478bd9Sstevel@tonic-gate }
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate int
1647c478bd9Sstevel@tonic-gate zonecfg_check_handle(zone_dochandle_t handle)
1657c478bd9Sstevel@tonic-gate {
1667c478bd9Sstevel@tonic-gate 	if (handle == NULL || handle->zone_dh_doc == NULL)
1677c478bd9Sstevel@tonic-gate 		return (Z_BAD_HANDLE);
1687c478bd9Sstevel@tonic-gate 	return (Z_OK);
1697c478bd9Sstevel@tonic-gate }
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate void
1727c478bd9Sstevel@tonic-gate zonecfg_fini_handle(zone_dochandle_t handle)
1737c478bd9Sstevel@tonic-gate {
1747c478bd9Sstevel@tonic-gate 	if (zonecfg_check_handle(handle) == Z_OK)
1757c478bd9Sstevel@tonic-gate 		xmlFreeDoc(handle->zone_dh_doc);
1767c478bd9Sstevel@tonic-gate 	if (handle != NULL)
1777c478bd9Sstevel@tonic-gate 		free(handle);
1787c478bd9Sstevel@tonic-gate }
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate static int
1817c478bd9Sstevel@tonic-gate zonecfg_destroy_impl(char *filename)
1827c478bd9Sstevel@tonic-gate {
1837c478bd9Sstevel@tonic-gate 	if (unlink(filename) == -1) {
1847c478bd9Sstevel@tonic-gate 		if (errno == EACCES)
1857c478bd9Sstevel@tonic-gate 			return (Z_ACCES);
1867c478bd9Sstevel@tonic-gate 		if (errno == ENOENT)
1877c478bd9Sstevel@tonic-gate 			return (Z_NO_ZONE);
1887c478bd9Sstevel@tonic-gate 		return (Z_MISC_FS);
1897c478bd9Sstevel@tonic-gate 	}
1907c478bd9Sstevel@tonic-gate 	return (Z_OK);
1917c478bd9Sstevel@tonic-gate }
1927c478bd9Sstevel@tonic-gate 
1937c478bd9Sstevel@tonic-gate int
1947c478bd9Sstevel@tonic-gate zonecfg_destroy(const char *zonename)
1957c478bd9Sstevel@tonic-gate {
1967c478bd9Sstevel@tonic-gate 	char path[MAXPATHLEN];
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate 	config_file_path(zonename, path);
1997c478bd9Sstevel@tonic-gate 	return (zonecfg_destroy_impl(path));
2007c478bd9Sstevel@tonic-gate }
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate int
2037c478bd9Sstevel@tonic-gate zonecfg_destroy_snapshot(char *zonename)
2047c478bd9Sstevel@tonic-gate {
2057c478bd9Sstevel@tonic-gate 	char path[MAXPATHLEN];
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate 	snap_file_path(zonename, path);
2087c478bd9Sstevel@tonic-gate 	return (zonecfg_destroy_impl(path));
2097c478bd9Sstevel@tonic-gate }
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate static int
212*a1be23daSdp getroot(zone_dochandle_t handle, xmlNodePtr *root)
2137c478bd9Sstevel@tonic-gate {
2147c478bd9Sstevel@tonic-gate 	if (zonecfg_check_handle(handle) == Z_BAD_HANDLE)
2157c478bd9Sstevel@tonic-gate 		return (Z_BAD_HANDLE);
2167c478bd9Sstevel@tonic-gate 
217*a1be23daSdp 	*root = xmlDocGetRootElement(handle->zone_dh_doc);
218*a1be23daSdp 
219*a1be23daSdp 	if (*root == NULL)
2207c478bd9Sstevel@tonic-gate 		return (Z_EMPTY_DOCUMENT);
2217c478bd9Sstevel@tonic-gate 
222*a1be23daSdp 	if (xmlStrcmp((*root)->name, DTD_ELEM_ZONE))
2237c478bd9Sstevel@tonic-gate 		return (Z_WRONG_DOC_TYPE);
224*a1be23daSdp 
225*a1be23daSdp 	return (Z_OK);
226*a1be23daSdp }
227*a1be23daSdp 
228*a1be23daSdp static int
229*a1be23daSdp operation_prep(zone_dochandle_t handle)
230*a1be23daSdp {
231*a1be23daSdp 	xmlNodePtr root;
232*a1be23daSdp 	int err;
233*a1be23daSdp 
234*a1be23daSdp 	if ((err = getroot(handle, &root)) != 0)
235*a1be23daSdp 		return (err);
236*a1be23daSdp 
237*a1be23daSdp 	handle->zone_dh_cur = root;
238*a1be23daSdp 	handle->zone_dh_top = root;
239*a1be23daSdp 	return (Z_OK);
240*a1be23daSdp }
241*a1be23daSdp 
242*a1be23daSdp static int
243*a1be23daSdp getrootattr(zone_dochandle_t handle, const xmlChar *propname,
244*a1be23daSdp     char *propval, size_t propsize)
245*a1be23daSdp {
246*a1be23daSdp 	xmlNodePtr root;
247*a1be23daSdp 	xmlChar *property;
248*a1be23daSdp 	size_t srcsize;
249*a1be23daSdp 	int err;
250*a1be23daSdp 
251*a1be23daSdp 	if ((err = getroot(handle, &root)) != 0)
252*a1be23daSdp 		return (err);
253*a1be23daSdp 
254*a1be23daSdp 	if ((property = xmlGetProp(root, propname)) == NULL)
255*a1be23daSdp 		return (Z_BAD_PROPERTY);
256*a1be23daSdp 	srcsize = strlcpy(propval, (char *)property, propsize);
257*a1be23daSdp 	xmlFree(property);
258*a1be23daSdp 	if (srcsize >= propsize)
259*a1be23daSdp 		return (Z_TOO_BIG);
260*a1be23daSdp 	return (Z_OK);
261*a1be23daSdp }
262*a1be23daSdp 
263*a1be23daSdp static int
264*a1be23daSdp setrootattr(zone_dochandle_t handle, const xmlChar *propname, char *propval)
265*a1be23daSdp {
266*a1be23daSdp 	int err;
267*a1be23daSdp 	xmlNodePtr root;
268*a1be23daSdp 
269*a1be23daSdp 	if (propval == NULL)
270*a1be23daSdp 		return (Z_INVAL);
271*a1be23daSdp 
272*a1be23daSdp 	if ((err = getroot(handle, &root)) != Z_OK)
273*a1be23daSdp 		return (err);
274*a1be23daSdp 
275*a1be23daSdp 	if (xmlSetProp(root, propname, (const xmlChar *) propval) == NULL)
276*a1be23daSdp 		return (Z_INVAL);
2777c478bd9Sstevel@tonic-gate 	return (Z_OK);
2787c478bd9Sstevel@tonic-gate }
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate static int
2817c478bd9Sstevel@tonic-gate zonecfg_get_handle_impl(char *zonename, char *filename, zone_dochandle_t handle)
2827c478bd9Sstevel@tonic-gate {
2837c478bd9Sstevel@tonic-gate 	xmlValidCtxtPtr cvp;
2847c478bd9Sstevel@tonic-gate 	xmlDocPtr top;
2857c478bd9Sstevel@tonic-gate 	xmlNodePtr child, next;
2867c478bd9Sstevel@tonic-gate 	struct stat statbuf;
2877c478bd9Sstevel@tonic-gate 	int valid;
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate 	if (zonename == NULL)
2907c478bd9Sstevel@tonic-gate 		return (Z_NO_ZONE);
2917c478bd9Sstevel@tonic-gate 	if ((handle->zone_dh_doc = xmlParseFile(filename)) == NULL) {
2927c478bd9Sstevel@tonic-gate 		/* distinguish file not found vs. found but not parsed */
2937c478bd9Sstevel@tonic-gate 		if (stat(filename, &statbuf) == 0)
2947c478bd9Sstevel@tonic-gate 			return (Z_INVALID_DOCUMENT);
2957c478bd9Sstevel@tonic-gate 		return (Z_NO_ZONE);
2967c478bd9Sstevel@tonic-gate 	}
2977c478bd9Sstevel@tonic-gate 	if ((cvp = xmlNewValidCtxt()) == NULL)
2987c478bd9Sstevel@tonic-gate 		return (Z_NOMEM);
2997c478bd9Sstevel@tonic-gate 	cvp->error = zonecfg_error_func;
3007c478bd9Sstevel@tonic-gate 	cvp->warning = zonecfg_error_func;
3017c478bd9Sstevel@tonic-gate 	valid = xmlValidateDocument(cvp, handle->zone_dh_doc);
3027c478bd9Sstevel@tonic-gate 	xmlFreeValidCtxt(cvp);
3037c478bd9Sstevel@tonic-gate 	if (valid == 0)
3047c478bd9Sstevel@tonic-gate 		return (Z_INVALID_DOCUMENT);
3057c478bd9Sstevel@tonic-gate 	/* delete any comments such as inherited Sun copyright / ident str */
3067c478bd9Sstevel@tonic-gate 	top = handle->zone_dh_doc;
3077c478bd9Sstevel@tonic-gate 	for (child = top->xmlChildrenNode; child != NULL; child = next) {
3087c478bd9Sstevel@tonic-gate 		next = child->next;
3097c478bd9Sstevel@tonic-gate 		if (child->name == NULL)
3107c478bd9Sstevel@tonic-gate 			continue;
3117c478bd9Sstevel@tonic-gate 		if (xmlStrcmp(child->name, DTD_ELEM_COMMENT) == 0) {
3127c478bd9Sstevel@tonic-gate 			next = child->next;
3137c478bd9Sstevel@tonic-gate 			xmlUnlinkNode(child);
3147c478bd9Sstevel@tonic-gate 			xmlFreeNode(child);
3157c478bd9Sstevel@tonic-gate 		}
3167c478bd9Sstevel@tonic-gate 	}
3177c478bd9Sstevel@tonic-gate 	return (Z_OK);
3187c478bd9Sstevel@tonic-gate }
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate int
3217c478bd9Sstevel@tonic-gate zonecfg_get_handle(char *zonename, zone_dochandle_t handle)
3227c478bd9Sstevel@tonic-gate {
3237c478bd9Sstevel@tonic-gate 	char path[MAXPATHLEN];
3247c478bd9Sstevel@tonic-gate 
3257c478bd9Sstevel@tonic-gate 	config_file_path(zonename, path);
3267c478bd9Sstevel@tonic-gate 	return (zonecfg_get_handle_impl(zonename, path, handle));
3277c478bd9Sstevel@tonic-gate }
3287c478bd9Sstevel@tonic-gate 
3297c478bd9Sstevel@tonic-gate int
3307c478bd9Sstevel@tonic-gate zonecfg_get_snapshot_handle(char *zonename, zone_dochandle_t handle)
3317c478bd9Sstevel@tonic-gate {
3327c478bd9Sstevel@tonic-gate 	char path[MAXPATHLEN];
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate 	snap_file_path(zonename, path);
3357c478bd9Sstevel@tonic-gate 	return (zonecfg_get_handle_impl(zonename, path, handle));
3367c478bd9Sstevel@tonic-gate }
3377c478bd9Sstevel@tonic-gate 
3387c478bd9Sstevel@tonic-gate int
3397c478bd9Sstevel@tonic-gate zonecfg_get_name(zone_dochandle_t handle, char *name, size_t namesize)
3407c478bd9Sstevel@tonic-gate {
341*a1be23daSdp 	return (getrootattr(handle, DTD_ATTR_NAME, name, namesize));
342*a1be23daSdp }
3437c478bd9Sstevel@tonic-gate 
344*a1be23daSdp int
345*a1be23daSdp zonecfg_set_name(zone_dochandle_t handle, char *name)
346*a1be23daSdp {
347*a1be23daSdp 	return (setrootattr(handle, DTD_ATTR_NAME, name));
348*a1be23daSdp }
3497c478bd9Sstevel@tonic-gate 
350*a1be23daSdp int
351*a1be23daSdp zonecfg_get_zonepath(zone_dochandle_t handle, char *path, size_t pathsize)
352*a1be23daSdp {
353*a1be23daSdp 	return (getrootattr(handle, DTD_ATTR_ZONEPATH, path, pathsize));
354*a1be23daSdp }
3557c478bd9Sstevel@tonic-gate 
356*a1be23daSdp int
357*a1be23daSdp zonecfg_set_zonepath(zone_dochandle_t handle, char *zonepath)
358*a1be23daSdp {
359*a1be23daSdp 	return (setrootattr(handle, DTD_ATTR_ZONEPATH, zonepath));
360*a1be23daSdp }
361*a1be23daSdp 
362*a1be23daSdp int
363*a1be23daSdp zonecfg_get_autoboot(zone_dochandle_t handle, boolean_t *autoboot)
364*a1be23daSdp {
365*a1be23daSdp 	char autobootstr[DTD_ENTITY_BOOL_LEN];
366*a1be23daSdp 	int ret;
367*a1be23daSdp 
368*a1be23daSdp 	if ((ret = getrootattr(handle, DTD_ATTR_AUTOBOOT, autobootstr,
369*a1be23daSdp 	    sizeof (autobootstr))) != Z_OK)
370*a1be23daSdp 		return (ret);
371*a1be23daSdp 
372*a1be23daSdp 	if (strcmp(autobootstr, DTD_ENTITY_TRUE) == 0)
373*a1be23daSdp 		*autoboot = B_TRUE;
374*a1be23daSdp 	else if (strcmp(autobootstr, DTD_ENTITY_FALSE) == 0)
375*a1be23daSdp 		*autoboot = B_FALSE;
376*a1be23daSdp 	else
377*a1be23daSdp 		ret = Z_BAD_PROPERTY;
378*a1be23daSdp 	return (ret);
379*a1be23daSdp }
380*a1be23daSdp 
381*a1be23daSdp int
382*a1be23daSdp zonecfg_set_autoboot(zone_dochandle_t handle, boolean_t autoboot)
383*a1be23daSdp {
384*a1be23daSdp 	return (setrootattr(handle, DTD_ATTR_AUTOBOOT,
385*a1be23daSdp 	    autoboot ? DTD_ENTITY_TRUE : DTD_ENTITY_FALSE));
386*a1be23daSdp }
387*a1be23daSdp 
388*a1be23daSdp int
389*a1be23daSdp zonecfg_get_pool(zone_dochandle_t handle, char *pool, size_t poolsize)
390*a1be23daSdp {
391*a1be23daSdp 	return (getrootattr(handle, DTD_ATTR_POOL, pool, poolsize));
392*a1be23daSdp }
393*a1be23daSdp 
394*a1be23daSdp int
395*a1be23daSdp zonecfg_set_pool(zone_dochandle_t handle, char *pool)
396*a1be23daSdp {
397*a1be23daSdp 	return (setrootattr(handle, DTD_ATTR_POOL, pool));
398*a1be23daSdp }
399*a1be23daSdp 
400*a1be23daSdp /*
401*a1be23daSdp  * /etc/zones/index caches a vital piece of information which is also
402*a1be23daSdp  * in the <zonename>.xml file: the path to the zone.  This is for performance,
403*a1be23daSdp  * since we need to walk all zonepath's in order to be able to detect conflicts
404*a1be23daSdp  * (see crosscheck_zonepaths() in the zoneadm command).
405*a1be23daSdp  */
406*a1be23daSdp int
407*a1be23daSdp zonecfg_refresh_index_file(zone_dochandle_t handle)
408*a1be23daSdp {
409*a1be23daSdp 	char name[ZONENAME_MAX], zonepath[MAXPATHLEN];
410*a1be23daSdp 	struct zoneent ze;
411*a1be23daSdp 	int err;
412*a1be23daSdp 
413*a1be23daSdp 	if ((err = zonecfg_get_name(handle, name, sizeof (name))) != Z_OK)
414*a1be23daSdp 		return (err);
415*a1be23daSdp 	if ((err = zonecfg_get_zonepath(handle, zonepath,
416*a1be23daSdp 	    sizeof (zonepath))) != Z_OK)
417*a1be23daSdp 		return (err);
418*a1be23daSdp 	(void) strlcpy(ze.zone_name, name, sizeof (ze.zone_name));
419*a1be23daSdp 	ze.zone_state = -1;
420*a1be23daSdp 	(void) strlcpy(ze.zone_path, zonepath, sizeof (ze.zone_path));
421*a1be23daSdp 	return (putzoneent(&ze, PZE_MODIFY));
4227c478bd9Sstevel@tonic-gate }
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate static int
4257c478bd9Sstevel@tonic-gate zonecfg_save_impl(zone_dochandle_t handle, char *filename)
4267c478bd9Sstevel@tonic-gate {
4277c478bd9Sstevel@tonic-gate 	char tmpfile[MAXPATHLEN];
4287c478bd9Sstevel@tonic-gate 	int tmpfd;
4297c478bd9Sstevel@tonic-gate 	xmlValidCtxt cvp = { NULL };
4307c478bd9Sstevel@tonic-gate 	xmlNodePtr comment;
4317c478bd9Sstevel@tonic-gate 
4327c478bd9Sstevel@tonic-gate 	(void) strlcpy(tmpfile, filename, sizeof (tmpfile));
4337c478bd9Sstevel@tonic-gate 	(void) dirname(tmpfile);
4347c478bd9Sstevel@tonic-gate 	(void) strlcat(tmpfile, _PATH_TMPFILE, sizeof (tmpfile));
4357c478bd9Sstevel@tonic-gate 
4367c478bd9Sstevel@tonic-gate 	tmpfd = mkstemp(tmpfile);
4377c478bd9Sstevel@tonic-gate 	if (tmpfd == -1) {
4387c478bd9Sstevel@tonic-gate 		(void) unlink(tmpfile);
4397c478bd9Sstevel@tonic-gate 		return (Z_TEMP_FILE);
4407c478bd9Sstevel@tonic-gate 	}
4417c478bd9Sstevel@tonic-gate 	(void) close(tmpfd);
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate 	cvp.error = zonecfg_error_func;
4447c478bd9Sstevel@tonic-gate 	cvp.warning = zonecfg_error_func;
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate 	if ((comment = xmlNewComment((xmlChar *) "\n    DO NOT EDIT THIS "
4477c478bd9Sstevel@tonic-gate 	    "FILE.  Use zonecfg(1M) instead.\n")) == NULL)
4487c478bd9Sstevel@tonic-gate 		goto err;
4497c478bd9Sstevel@tonic-gate 	if (xmlAddPrevSibling(handle->zone_dh_top, comment) == 0)
4507c478bd9Sstevel@tonic-gate 		goto err;
4517c478bd9Sstevel@tonic-gate 
4527c478bd9Sstevel@tonic-gate 	if (xmlValidateDocument(&cvp, handle->zone_dh_doc) == 0)
4537c478bd9Sstevel@tonic-gate 		goto err;
4547c478bd9Sstevel@tonic-gate 
4557c478bd9Sstevel@tonic-gate 	if (xmlSaveFormatFile(tmpfile, handle->zone_dh_doc, 1) <= 0)
4567c478bd9Sstevel@tonic-gate 		goto err;
4577c478bd9Sstevel@tonic-gate 	(void) chmod(tmpfile, 0644);
4587c478bd9Sstevel@tonic-gate 
4597c478bd9Sstevel@tonic-gate 	if (rename(tmpfile, filename) == -1) {
4607c478bd9Sstevel@tonic-gate 		(void) unlink(tmpfile);
4617c478bd9Sstevel@tonic-gate 		if (errno == EACCES)
4627c478bd9Sstevel@tonic-gate 			return (Z_ACCES);
4637c478bd9Sstevel@tonic-gate 		return (Z_MISC_FS);
4647c478bd9Sstevel@tonic-gate 	}
465*a1be23daSdp 
466*a1be23daSdp 	/* now update the cached copy of the zone path in the index file */
467*a1be23daSdp 	return (zonecfg_refresh_index_file(handle));
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate err:
4707c478bd9Sstevel@tonic-gate 	(void) unlink(tmpfile);
4717c478bd9Sstevel@tonic-gate 	return (Z_SAVING_FILE);
4727c478bd9Sstevel@tonic-gate }
4737c478bd9Sstevel@tonic-gate 
4747c478bd9Sstevel@tonic-gate int
4757c478bd9Sstevel@tonic-gate zonecfg_save(zone_dochandle_t handle)
4767c478bd9Sstevel@tonic-gate {
4777c478bd9Sstevel@tonic-gate 	char zname[MAXPATHLEN], path[MAXPATHLEN];
4787c478bd9Sstevel@tonic-gate 	int err;
4797c478bd9Sstevel@tonic-gate 
4807c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_get_name(handle, zname, sizeof (zname))) != Z_OK) {
4817c478bd9Sstevel@tonic-gate 		return (err);
4827c478bd9Sstevel@tonic-gate 	}
4837c478bd9Sstevel@tonic-gate 	config_file_path(zname, path);
4847c478bd9Sstevel@tonic-gate 	return (zonecfg_save_impl(handle, path));
4857c478bd9Sstevel@tonic-gate }
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate /*
4887c478bd9Sstevel@tonic-gate  * Special case: if access(2) fails with ENOENT, then try again using
4897c478bd9Sstevel@tonic-gate  * ZONE_CONFIG_ROOT instead of config_file_path(zonename).  This is how we
4907c478bd9Sstevel@tonic-gate  * work around the case of a config file which has not been created yet:
4917c478bd9Sstevel@tonic-gate  * the user will need access to the directory so use that as a heuristic.
4927c478bd9Sstevel@tonic-gate  */
4937c478bd9Sstevel@tonic-gate 
4947c478bd9Sstevel@tonic-gate int
4957c478bd9Sstevel@tonic-gate zonecfg_access(const char *zonename, int amode)
4967c478bd9Sstevel@tonic-gate {
4977c478bd9Sstevel@tonic-gate 	char path[MAXPATHLEN];
4987c478bd9Sstevel@tonic-gate 
4997c478bd9Sstevel@tonic-gate 	config_file_path(zonename, path);
5007c478bd9Sstevel@tonic-gate 	if (access(path, amode) == 0)
5017c478bd9Sstevel@tonic-gate 		return (Z_OK);
5027c478bd9Sstevel@tonic-gate 	if (errno == ENOENT && access(ZONE_CONFIG_ROOT, amode) == 0)
5037c478bd9Sstevel@tonic-gate 		return (Z_OK);
5047c478bd9Sstevel@tonic-gate 	if (errno == EACCES)
5057c478bd9Sstevel@tonic-gate 		return (Z_ACCES);
5067c478bd9Sstevel@tonic-gate 	if (errno == EINVAL)
5077c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
5087c478bd9Sstevel@tonic-gate 	return (Z_MISC_FS);
5097c478bd9Sstevel@tonic-gate }
5107c478bd9Sstevel@tonic-gate 
5117c478bd9Sstevel@tonic-gate int
5127c478bd9Sstevel@tonic-gate zonecfg_create_snapshot(char *zonename)
5137c478bd9Sstevel@tonic-gate {
5147c478bd9Sstevel@tonic-gate 	zone_dochandle_t handle;
5157c478bd9Sstevel@tonic-gate 	char path[MAXPATHLEN], zonepath[MAXPATHLEN], rpath[MAXPATHLEN];
5167c478bd9Sstevel@tonic-gate 	int error = Z_OK, res;
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate 	if ((handle = zonecfg_init_handle()) == NULL) {
5197c478bd9Sstevel@tonic-gate 		return (Z_NOMEM);
5207c478bd9Sstevel@tonic-gate 	}
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate 	if ((error = zonecfg_get_handle(zonename, handle)) != Z_OK)
5237c478bd9Sstevel@tonic-gate 		goto out;
5247c478bd9Sstevel@tonic-gate 	if ((error = operation_prep(handle)) != Z_OK)
5257c478bd9Sstevel@tonic-gate 		goto out;
5267c478bd9Sstevel@tonic-gate 	error = zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath));
5277c478bd9Sstevel@tonic-gate 	if (error != Z_OK)
5287c478bd9Sstevel@tonic-gate 		goto out;
5297c478bd9Sstevel@tonic-gate 	if ((res = resolvepath(zonepath, rpath, sizeof (rpath))) == -1) {
5307c478bd9Sstevel@tonic-gate 		error = Z_RESOLVED_PATH;
5317c478bd9Sstevel@tonic-gate 		goto out;
5327c478bd9Sstevel@tonic-gate 	}
5337c478bd9Sstevel@tonic-gate 	/*
5347c478bd9Sstevel@tonic-gate 	 * If the resolved path is not the same as the original path, then
5357c478bd9Sstevel@tonic-gate 	 * save the resolved path in the snapshot, thus preventing any
5367c478bd9Sstevel@tonic-gate 	 * potential problems down the line when zoneadmd goes to unmount
5377c478bd9Sstevel@tonic-gate 	 * file systems and depends on initial string matches with resolved
5387c478bd9Sstevel@tonic-gate 	 * paths.
5397c478bd9Sstevel@tonic-gate 	 */
5407c478bd9Sstevel@tonic-gate 	rpath[res] = '\0';
5417c478bd9Sstevel@tonic-gate 	if (strcmp(zonepath, rpath) != 0) {
5427c478bd9Sstevel@tonic-gate 		if ((error = zonecfg_set_zonepath(handle, rpath)) != Z_OK)
5437c478bd9Sstevel@tonic-gate 			goto out;
5447c478bd9Sstevel@tonic-gate 	}
5457c478bd9Sstevel@tonic-gate 	if ((mkdir(ZONE_SNAPSHOT_ROOT, S_IRWXU) == -1) && (errno != EEXIST)) {
5467c478bd9Sstevel@tonic-gate 		error = Z_MISC_FS;
5477c478bd9Sstevel@tonic-gate 		goto out;
5487c478bd9Sstevel@tonic-gate 	}
5497c478bd9Sstevel@tonic-gate 
5507c478bd9Sstevel@tonic-gate 	snap_file_path(zonename, path);
5517c478bd9Sstevel@tonic-gate 	error = zonecfg_save_impl(handle, path);
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate out:
5547c478bd9Sstevel@tonic-gate 	zonecfg_fini_handle(handle);
5557c478bd9Sstevel@tonic-gate 	return (error);
5567c478bd9Sstevel@tonic-gate }
5577c478bd9Sstevel@tonic-gate 
5587c478bd9Sstevel@tonic-gate static int
559*a1be23daSdp newprop(xmlNodePtr node, const xmlChar *attrname, char *src)
5607c478bd9Sstevel@tonic-gate {
5617c478bd9Sstevel@tonic-gate 	xmlAttrPtr newattr;
5627c478bd9Sstevel@tonic-gate 
5637c478bd9Sstevel@tonic-gate 	newattr = xmlNewProp(node, attrname, (xmlChar *)src);
5647c478bd9Sstevel@tonic-gate 	if (newattr == NULL) {
5657c478bd9Sstevel@tonic-gate 		xmlUnlinkNode(node);
5667c478bd9Sstevel@tonic-gate 		xmlFreeNode(node);
5677c478bd9Sstevel@tonic-gate 		return (Z_BAD_PROPERTY);
5687c478bd9Sstevel@tonic-gate 	}
5697c478bd9Sstevel@tonic-gate 	return (Z_OK);
5707c478bd9Sstevel@tonic-gate }
5717c478bd9Sstevel@tonic-gate 
5727c478bd9Sstevel@tonic-gate static int
5737c478bd9Sstevel@tonic-gate zonecfg_add_filesystem_core(zone_dochandle_t handle, struct zone_fstab *tabptr)
5747c478bd9Sstevel@tonic-gate {
5757c478bd9Sstevel@tonic-gate 	xmlNodePtr newnode, cur = handle->zone_dh_cur, options_node;
5767c478bd9Sstevel@tonic-gate 	zone_fsopt_t *ptr;
5777c478bd9Sstevel@tonic-gate 	int err;
5787c478bd9Sstevel@tonic-gate 
5797c478bd9Sstevel@tonic-gate 	newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_FS, NULL);
580*a1be23daSdp 	if ((err = newprop(newnode, DTD_ATTR_SPECIAL,
5817c478bd9Sstevel@tonic-gate 	    tabptr->zone_fs_special)) != Z_OK)
5827c478bd9Sstevel@tonic-gate 		return (err);
5837c478bd9Sstevel@tonic-gate 	if (tabptr->zone_fs_raw[0] != '\0' &&
584*a1be23daSdp 	    (err = newprop(newnode, DTD_ATTR_RAW, tabptr->zone_fs_raw)) != Z_OK)
5857c478bd9Sstevel@tonic-gate 		return (err);
586*a1be23daSdp 	if ((err = newprop(newnode, DTD_ATTR_DIR, tabptr->zone_fs_dir)) != Z_OK)
5877c478bd9Sstevel@tonic-gate 		return (err);
588*a1be23daSdp 	if ((err = newprop(newnode, DTD_ATTR_TYPE,
5897c478bd9Sstevel@tonic-gate 	    tabptr->zone_fs_type)) != Z_OK)
5907c478bd9Sstevel@tonic-gate 		return (err);
5917c478bd9Sstevel@tonic-gate 	if (tabptr->zone_fs_options != NULL) {
5927c478bd9Sstevel@tonic-gate 		for (ptr = tabptr->zone_fs_options; ptr != NULL;
5937c478bd9Sstevel@tonic-gate 		    ptr = ptr->zone_fsopt_next) {
5947c478bd9Sstevel@tonic-gate 			options_node = xmlNewTextChild(newnode, NULL,
5957c478bd9Sstevel@tonic-gate 			    DTD_ELEM_FSOPTION, NULL);
596*a1be23daSdp 			if ((err = newprop(options_node, DTD_ATTR_NAME,
5977c478bd9Sstevel@tonic-gate 			    ptr->zone_fsopt_opt)) != Z_OK)
5987c478bd9Sstevel@tonic-gate 				return (err);
5997c478bd9Sstevel@tonic-gate 		}
6007c478bd9Sstevel@tonic-gate 	}
6017c478bd9Sstevel@tonic-gate 	return (Z_OK);
6027c478bd9Sstevel@tonic-gate }
6037c478bd9Sstevel@tonic-gate 
6047c478bd9Sstevel@tonic-gate int
6057c478bd9Sstevel@tonic-gate zonecfg_add_filesystem(zone_dochandle_t handle, struct zone_fstab *tabptr)
6067c478bd9Sstevel@tonic-gate {
6077c478bd9Sstevel@tonic-gate 	int err;
6087c478bd9Sstevel@tonic-gate 
6097c478bd9Sstevel@tonic-gate 	if (tabptr == NULL)
6107c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
6117c478bd9Sstevel@tonic-gate 
6127c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
6137c478bd9Sstevel@tonic-gate 		return (err);
6147c478bd9Sstevel@tonic-gate 
6157c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_add_filesystem_core(handle, tabptr)) != Z_OK)
6167c478bd9Sstevel@tonic-gate 		return (err);
6177c478bd9Sstevel@tonic-gate 
6187c478bd9Sstevel@tonic-gate 	return (Z_OK);
6197c478bd9Sstevel@tonic-gate }
6207c478bd9Sstevel@tonic-gate 
6217c478bd9Sstevel@tonic-gate static int
6227c478bd9Sstevel@tonic-gate zonecfg_add_ipd_core(zone_dochandle_t handle, struct zone_fstab *tabptr)
6237c478bd9Sstevel@tonic-gate {
6247c478bd9Sstevel@tonic-gate 	xmlNodePtr newnode, cur = handle->zone_dh_cur;
6257c478bd9Sstevel@tonic-gate 	int err;
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate 	newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_IPD, NULL);
628*a1be23daSdp 	if ((err = newprop(newnode, DTD_ATTR_DIR, tabptr->zone_fs_dir)) != Z_OK)
6297c478bd9Sstevel@tonic-gate 		return (err);
6307c478bd9Sstevel@tonic-gate 	return (Z_OK);
6317c478bd9Sstevel@tonic-gate }
6327c478bd9Sstevel@tonic-gate 
6337c478bd9Sstevel@tonic-gate int
6347c478bd9Sstevel@tonic-gate zonecfg_add_ipd(zone_dochandle_t handle, struct zone_fstab *tabptr)
6357c478bd9Sstevel@tonic-gate {
6367c478bd9Sstevel@tonic-gate 	int err;
6377c478bd9Sstevel@tonic-gate 
6387c478bd9Sstevel@tonic-gate 	if (tabptr == NULL)
6397c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
6407c478bd9Sstevel@tonic-gate 
6417c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
6427c478bd9Sstevel@tonic-gate 		return (err);
6437c478bd9Sstevel@tonic-gate 
6447c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_add_ipd_core(handle, tabptr)) != Z_OK)
6457c478bd9Sstevel@tonic-gate 		return (err);
6467c478bd9Sstevel@tonic-gate 
6477c478bd9Sstevel@tonic-gate 	return (Z_OK);
6487c478bd9Sstevel@tonic-gate }
6497c478bd9Sstevel@tonic-gate 
6507c478bd9Sstevel@tonic-gate int
6517c478bd9Sstevel@tonic-gate zonecfg_add_fs_option(struct zone_fstab *tabptr, char *option)
6527c478bd9Sstevel@tonic-gate {
6537c478bd9Sstevel@tonic-gate 	zone_fsopt_t *last, *old, *new;
6547c478bd9Sstevel@tonic-gate 
6557c478bd9Sstevel@tonic-gate 	last = tabptr->zone_fs_options;
6567c478bd9Sstevel@tonic-gate 	for (old = last; old != NULL; old = old->zone_fsopt_next)
6577c478bd9Sstevel@tonic-gate 		last = old;	/* walk to the end of the list */
6587c478bd9Sstevel@tonic-gate 	new = (zone_fsopt_t *)malloc(sizeof (zone_fsopt_t));
6597c478bd9Sstevel@tonic-gate 	if (new == NULL)
6607c478bd9Sstevel@tonic-gate 		return (Z_NOMEM);
6617c478bd9Sstevel@tonic-gate 	(void) strlcpy(new->zone_fsopt_opt, option,
6627c478bd9Sstevel@tonic-gate 	    sizeof (new->zone_fsopt_opt));
6637c478bd9Sstevel@tonic-gate 	new->zone_fsopt_next = NULL;
6647c478bd9Sstevel@tonic-gate 	if (last == NULL)
6657c478bd9Sstevel@tonic-gate 		tabptr->zone_fs_options = new;
6667c478bd9Sstevel@tonic-gate 	else
6677c478bd9Sstevel@tonic-gate 		last->zone_fsopt_next = new;
6687c478bd9Sstevel@tonic-gate 	return (Z_OK);
6697c478bd9Sstevel@tonic-gate }
6707c478bd9Sstevel@tonic-gate 
6717c478bd9Sstevel@tonic-gate int
6727c478bd9Sstevel@tonic-gate zonecfg_remove_fs_option(struct zone_fstab *tabptr, char *option)
6737c478bd9Sstevel@tonic-gate {
6747c478bd9Sstevel@tonic-gate 	zone_fsopt_t *last, *this, *next;
6757c478bd9Sstevel@tonic-gate 
6767c478bd9Sstevel@tonic-gate 	last = tabptr->zone_fs_options;
6777c478bd9Sstevel@tonic-gate 	for (this = last; this != NULL; this = this->zone_fsopt_next) {
6787c478bd9Sstevel@tonic-gate 		if (strcmp(this->zone_fsopt_opt, option) == 0) {
6797c478bd9Sstevel@tonic-gate 			next = this->zone_fsopt_next;
6807c478bd9Sstevel@tonic-gate 			if (this == tabptr->zone_fs_options)
6817c478bd9Sstevel@tonic-gate 				tabptr->zone_fs_options = next;
6827c478bd9Sstevel@tonic-gate 			else
6837c478bd9Sstevel@tonic-gate 				last->zone_fsopt_next = next;
6847c478bd9Sstevel@tonic-gate 			free(this);
6857c478bd9Sstevel@tonic-gate 			return (Z_OK);
6867c478bd9Sstevel@tonic-gate 		} else
6877c478bd9Sstevel@tonic-gate 			last = this;
6887c478bd9Sstevel@tonic-gate 	}
6897c478bd9Sstevel@tonic-gate 	return (Z_NO_PROPERTY_ID);
6907c478bd9Sstevel@tonic-gate }
6917c478bd9Sstevel@tonic-gate 
6927c478bd9Sstevel@tonic-gate void
6937c478bd9Sstevel@tonic-gate zonecfg_free_fs_option_list(zone_fsopt_t *list)
6947c478bd9Sstevel@tonic-gate {
6957c478bd9Sstevel@tonic-gate 	zone_fsopt_t *this, *next;
6967c478bd9Sstevel@tonic-gate 
6977c478bd9Sstevel@tonic-gate 	for (this = list; this != NULL; this = next) {
6987c478bd9Sstevel@tonic-gate 		next = this->zone_fsopt_next;
6997c478bd9Sstevel@tonic-gate 		free(this);
7007c478bd9Sstevel@tonic-gate 	}
7017c478bd9Sstevel@tonic-gate }
7027c478bd9Sstevel@tonic-gate 
7037c478bd9Sstevel@tonic-gate void
7047c478bd9Sstevel@tonic-gate zonecfg_free_rctl_value_list(struct zone_rctlvaltab *valtab)
7057c478bd9Sstevel@tonic-gate {
7067c478bd9Sstevel@tonic-gate 	if (valtab == NULL)
7077c478bd9Sstevel@tonic-gate 		return;
7087c478bd9Sstevel@tonic-gate 	zonecfg_free_rctl_value_list(valtab->zone_rctlval_next);
7097c478bd9Sstevel@tonic-gate 	free(valtab);
7107c478bd9Sstevel@tonic-gate }
7117c478bd9Sstevel@tonic-gate 
7127c478bd9Sstevel@tonic-gate static boolean_t
7137c478bd9Sstevel@tonic-gate match_prop(xmlNodePtr cur, const xmlChar *attr, char *user_prop)
7147c478bd9Sstevel@tonic-gate {
7157c478bd9Sstevel@tonic-gate 	xmlChar *gotten_prop;
7167c478bd9Sstevel@tonic-gate 	int prop_result;
7177c478bd9Sstevel@tonic-gate 
7187c478bd9Sstevel@tonic-gate 	gotten_prop = xmlGetProp(cur, attr);
7197c478bd9Sstevel@tonic-gate 	if (gotten_prop == NULL)	/* shouldn't happen */
7207c478bd9Sstevel@tonic-gate 		return (B_FALSE);
7217c478bd9Sstevel@tonic-gate 	prop_result = xmlStrcmp(gotten_prop, (const xmlChar *) user_prop);
7227c478bd9Sstevel@tonic-gate 	xmlFree(gotten_prop);
7237c478bd9Sstevel@tonic-gate 	return ((prop_result == 0));
7247c478bd9Sstevel@tonic-gate }
7257c478bd9Sstevel@tonic-gate 
7267c478bd9Sstevel@tonic-gate static int
7277c478bd9Sstevel@tonic-gate zonecfg_delete_filesystem_core(zone_dochandle_t handle,
7287c478bd9Sstevel@tonic-gate     struct zone_fstab *tabptr)
7297c478bd9Sstevel@tonic-gate {
7307c478bd9Sstevel@tonic-gate 	xmlNodePtr cur = handle->zone_dh_cur;
7317c478bd9Sstevel@tonic-gate 	boolean_t dir_match, spec_match, raw_match, type_match;
7327c478bd9Sstevel@tonic-gate 
7337c478bd9Sstevel@tonic-gate 	for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
7347c478bd9Sstevel@tonic-gate 		if (xmlStrcmp(cur->name, DTD_ELEM_FS))
7357c478bd9Sstevel@tonic-gate 			continue;
7367c478bd9Sstevel@tonic-gate 		dir_match = match_prop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir);
7377c478bd9Sstevel@tonic-gate 		spec_match = match_prop(cur, DTD_ATTR_SPECIAL,
7387c478bd9Sstevel@tonic-gate 		    tabptr->zone_fs_special);
7397c478bd9Sstevel@tonic-gate 		raw_match = match_prop(cur, DTD_ATTR_RAW,
7407c478bd9Sstevel@tonic-gate 		    tabptr->zone_fs_raw);
7417c478bd9Sstevel@tonic-gate 		type_match = match_prop(cur, DTD_ATTR_TYPE,
7427c478bd9Sstevel@tonic-gate 		    tabptr->zone_fs_type);
7437c478bd9Sstevel@tonic-gate 		if (dir_match && spec_match && raw_match && type_match) {
7447c478bd9Sstevel@tonic-gate 			xmlUnlinkNode(cur);
7457c478bd9Sstevel@tonic-gate 			xmlFreeNode(cur);
7467c478bd9Sstevel@tonic-gate 			return (Z_OK);
7477c478bd9Sstevel@tonic-gate 		}
7487c478bd9Sstevel@tonic-gate 	}
7497c478bd9Sstevel@tonic-gate 	return (Z_NO_RESOURCE_ID);
7507c478bd9Sstevel@tonic-gate }
7517c478bd9Sstevel@tonic-gate 
7527c478bd9Sstevel@tonic-gate int
7537c478bd9Sstevel@tonic-gate zonecfg_delete_filesystem(zone_dochandle_t handle, struct zone_fstab *tabptr)
7547c478bd9Sstevel@tonic-gate {
7557c478bd9Sstevel@tonic-gate 	int err;
7567c478bd9Sstevel@tonic-gate 
7577c478bd9Sstevel@tonic-gate 	if (tabptr == NULL)
7587c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
7597c478bd9Sstevel@tonic-gate 
7607c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
7617c478bd9Sstevel@tonic-gate 		return (err);
7627c478bd9Sstevel@tonic-gate 
7637c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_delete_filesystem_core(handle, tabptr)) != Z_OK)
7647c478bd9Sstevel@tonic-gate 		return (err);
7657c478bd9Sstevel@tonic-gate 
7667c478bd9Sstevel@tonic-gate 	return (Z_OK);
7677c478bd9Sstevel@tonic-gate }
7687c478bd9Sstevel@tonic-gate 
7697c478bd9Sstevel@tonic-gate int
7707c478bd9Sstevel@tonic-gate zonecfg_modify_filesystem(
7717c478bd9Sstevel@tonic-gate 	zone_dochandle_t handle,
7727c478bd9Sstevel@tonic-gate 	struct zone_fstab *oldtabptr,
7737c478bd9Sstevel@tonic-gate 	struct zone_fstab *newtabptr)
7747c478bd9Sstevel@tonic-gate {
7757c478bd9Sstevel@tonic-gate 	int err;
7767c478bd9Sstevel@tonic-gate 
7777c478bd9Sstevel@tonic-gate 	if (oldtabptr == NULL || newtabptr == NULL)
7787c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
7797c478bd9Sstevel@tonic-gate 
7807c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
7817c478bd9Sstevel@tonic-gate 		return (err);
7827c478bd9Sstevel@tonic-gate 
7837c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_delete_filesystem_core(handle, oldtabptr)) != Z_OK)
7847c478bd9Sstevel@tonic-gate 		return (err);
7857c478bd9Sstevel@tonic-gate 
7867c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_add_filesystem_core(handle, newtabptr)) != Z_OK)
7877c478bd9Sstevel@tonic-gate 		return (err);
7887c478bd9Sstevel@tonic-gate 
7897c478bd9Sstevel@tonic-gate 	return (Z_OK);
7907c478bd9Sstevel@tonic-gate }
7917c478bd9Sstevel@tonic-gate 
7927c478bd9Sstevel@tonic-gate static int
7937c478bd9Sstevel@tonic-gate zonecfg_delete_ipd_core(zone_dochandle_t handle, struct zone_fstab *tabptr)
7947c478bd9Sstevel@tonic-gate {
7957c478bd9Sstevel@tonic-gate 	xmlNodePtr cur = handle->zone_dh_cur;
7967c478bd9Sstevel@tonic-gate 
7977c478bd9Sstevel@tonic-gate 	for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
7987c478bd9Sstevel@tonic-gate 		if (xmlStrcmp(cur->name, DTD_ELEM_IPD))
7997c478bd9Sstevel@tonic-gate 			continue;
8007c478bd9Sstevel@tonic-gate 		if (match_prop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir)) {
8017c478bd9Sstevel@tonic-gate 			xmlUnlinkNode(cur);
8027c478bd9Sstevel@tonic-gate 			xmlFreeNode(cur);
8037c478bd9Sstevel@tonic-gate 			return (Z_OK);
8047c478bd9Sstevel@tonic-gate 		}
8057c478bd9Sstevel@tonic-gate 	}
8067c478bd9Sstevel@tonic-gate 	return (Z_NO_RESOURCE_ID);
8077c478bd9Sstevel@tonic-gate }
8087c478bd9Sstevel@tonic-gate 
8097c478bd9Sstevel@tonic-gate int
8107c478bd9Sstevel@tonic-gate zonecfg_delete_ipd(zone_dochandle_t handle, struct zone_fstab *tabptr)
8117c478bd9Sstevel@tonic-gate {
8127c478bd9Sstevel@tonic-gate 	int err;
8137c478bd9Sstevel@tonic-gate 
8147c478bd9Sstevel@tonic-gate 	if (tabptr == NULL)
8157c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
8167c478bd9Sstevel@tonic-gate 
8177c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
8187c478bd9Sstevel@tonic-gate 		return (err);
8197c478bd9Sstevel@tonic-gate 
8207c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_delete_ipd_core(handle, tabptr)) != Z_OK)
8217c478bd9Sstevel@tonic-gate 		return (err);
8227c478bd9Sstevel@tonic-gate 
8237c478bd9Sstevel@tonic-gate 	return (Z_OK);
8247c478bd9Sstevel@tonic-gate }
8257c478bd9Sstevel@tonic-gate 
8267c478bd9Sstevel@tonic-gate int
8277c478bd9Sstevel@tonic-gate zonecfg_modify_ipd(zone_dochandle_t handle, struct zone_fstab *oldtabptr,
8287c478bd9Sstevel@tonic-gate     struct zone_fstab *newtabptr)
8297c478bd9Sstevel@tonic-gate {
8307c478bd9Sstevel@tonic-gate 	int err;
8317c478bd9Sstevel@tonic-gate 
8327c478bd9Sstevel@tonic-gate 	if (oldtabptr == NULL || newtabptr == NULL)
8337c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
8347c478bd9Sstevel@tonic-gate 
8357c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
8367c478bd9Sstevel@tonic-gate 		return (err);
8377c478bd9Sstevel@tonic-gate 
8387c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_delete_ipd_core(handle, oldtabptr)) != Z_OK)
8397c478bd9Sstevel@tonic-gate 		return (err);
8407c478bd9Sstevel@tonic-gate 
8417c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_add_ipd_core(handle, newtabptr)) != Z_OK)
8427c478bd9Sstevel@tonic-gate 		return (err);
8437c478bd9Sstevel@tonic-gate 
8447c478bd9Sstevel@tonic-gate 	return (Z_OK);
8457c478bd9Sstevel@tonic-gate }
8467c478bd9Sstevel@tonic-gate 
8477c478bd9Sstevel@tonic-gate static int
8487c478bd9Sstevel@tonic-gate fetchprop(xmlNodePtr cur, const xmlChar *propname, char *dst, size_t dstsize)
8497c478bd9Sstevel@tonic-gate {
8507c478bd9Sstevel@tonic-gate 	xmlChar *property;
8517c478bd9Sstevel@tonic-gate 	size_t srcsize;
8527c478bd9Sstevel@tonic-gate 
8537c478bd9Sstevel@tonic-gate 	if ((property = xmlGetProp(cur, propname)) == NULL)
8547c478bd9Sstevel@tonic-gate 		return (Z_BAD_PROPERTY);
8557c478bd9Sstevel@tonic-gate 	srcsize = strlcpy(dst, (char *)property, dstsize);
8567c478bd9Sstevel@tonic-gate 	xmlFree(property);
8577c478bd9Sstevel@tonic-gate 	if (srcsize >= dstsize)
8587c478bd9Sstevel@tonic-gate 		return (Z_TOO_BIG);
8597c478bd9Sstevel@tonic-gate 	return (Z_OK);
8607c478bd9Sstevel@tonic-gate }
8617c478bd9Sstevel@tonic-gate 
8627c478bd9Sstevel@tonic-gate int
8637c478bd9Sstevel@tonic-gate zonecfg_lookup_filesystem(
8647c478bd9Sstevel@tonic-gate 	zone_dochandle_t handle,
8657c478bd9Sstevel@tonic-gate 	struct zone_fstab *tabptr)
8667c478bd9Sstevel@tonic-gate {
8677c478bd9Sstevel@tonic-gate 	xmlNodePtr cur, options, firstmatch;
8687c478bd9Sstevel@tonic-gate 	int err;
8697c478bd9Sstevel@tonic-gate 	char dirname[MAXPATHLEN], special[MAXPATHLEN], raw[MAXPATHLEN];
8707c478bd9Sstevel@tonic-gate 	char type[FSTYPSZ];
8717c478bd9Sstevel@tonic-gate 	char options_str[MAX_MNTOPT_STR];
8727c478bd9Sstevel@tonic-gate 
8737c478bd9Sstevel@tonic-gate 	if (tabptr == NULL)
8747c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
8757c478bd9Sstevel@tonic-gate 
8767c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
8777c478bd9Sstevel@tonic-gate 		return (err);
8787c478bd9Sstevel@tonic-gate 
8797c478bd9Sstevel@tonic-gate 	/*
8807c478bd9Sstevel@tonic-gate 	 * Walk the list of children looking for matches on any properties
8817c478bd9Sstevel@tonic-gate 	 * specified in the fstab parameter.  If more than one resource
8827c478bd9Sstevel@tonic-gate 	 * matches, we return Z_INSUFFICIENT_SPEC; if none match, we return
8837c478bd9Sstevel@tonic-gate 	 * Z_NO_RESOURCE_ID.
8847c478bd9Sstevel@tonic-gate 	 */
8857c478bd9Sstevel@tonic-gate 	cur = handle->zone_dh_cur;
8867c478bd9Sstevel@tonic-gate 	firstmatch = NULL;
8877c478bd9Sstevel@tonic-gate 	for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
8887c478bd9Sstevel@tonic-gate 		if (xmlStrcmp(cur->name, DTD_ELEM_FS))
8897c478bd9Sstevel@tonic-gate 			continue;
8907c478bd9Sstevel@tonic-gate 		if (strlen(tabptr->zone_fs_dir) > 0) {
8917c478bd9Sstevel@tonic-gate 			if ((fetchprop(cur, DTD_ATTR_DIR, dirname,
8927c478bd9Sstevel@tonic-gate 			    sizeof (dirname)) == Z_OK) &&
8937c478bd9Sstevel@tonic-gate 			    (strcmp(tabptr->zone_fs_dir, dirname) == 0)) {
8947c478bd9Sstevel@tonic-gate 				if (firstmatch == NULL)
8957c478bd9Sstevel@tonic-gate 					firstmatch = cur;
8967c478bd9Sstevel@tonic-gate 				else
8977c478bd9Sstevel@tonic-gate 					return (Z_INSUFFICIENT_SPEC);
8987c478bd9Sstevel@tonic-gate 			}
8997c478bd9Sstevel@tonic-gate 		}
9007c478bd9Sstevel@tonic-gate 		if (strlen(tabptr->zone_fs_special) > 0) {
9017c478bd9Sstevel@tonic-gate 			if ((fetchprop(cur, DTD_ATTR_SPECIAL, special,
9027c478bd9Sstevel@tonic-gate 			    sizeof (special)) == Z_OK)) {
9037c478bd9Sstevel@tonic-gate 				if (strcmp(tabptr->zone_fs_special,
9047c478bd9Sstevel@tonic-gate 				    special) == 0) {
9057c478bd9Sstevel@tonic-gate 					if (firstmatch == NULL)
9067c478bd9Sstevel@tonic-gate 						firstmatch = cur;
9077c478bd9Sstevel@tonic-gate 					else if (firstmatch != cur)
9087c478bd9Sstevel@tonic-gate 						return (Z_INSUFFICIENT_SPEC);
9097c478bd9Sstevel@tonic-gate 				} else {
9107c478bd9Sstevel@tonic-gate 					/*
9117c478bd9Sstevel@tonic-gate 					 * If another property matched but this
9127c478bd9Sstevel@tonic-gate 					 * one doesn't then reset firstmatch.
9137c478bd9Sstevel@tonic-gate 					 */
9147c478bd9Sstevel@tonic-gate 					if (firstmatch == cur)
9157c478bd9Sstevel@tonic-gate 						firstmatch = NULL;
9167c478bd9Sstevel@tonic-gate 				}
9177c478bd9Sstevel@tonic-gate 			}
9187c478bd9Sstevel@tonic-gate 		}
9197c478bd9Sstevel@tonic-gate 		if (strlen(tabptr->zone_fs_raw) > 0) {
9207c478bd9Sstevel@tonic-gate 			if ((fetchprop(cur, DTD_ATTR_RAW, raw,
9217c478bd9Sstevel@tonic-gate 			    sizeof (raw)) == Z_OK)) {
9227c478bd9Sstevel@tonic-gate 				if (strcmp(tabptr->zone_fs_raw, raw) == 0) {
9237c478bd9Sstevel@tonic-gate 					if (firstmatch == NULL)
9247c478bd9Sstevel@tonic-gate 						firstmatch = cur;
9257c478bd9Sstevel@tonic-gate 					else if (firstmatch != cur)
9267c478bd9Sstevel@tonic-gate 						return (Z_INSUFFICIENT_SPEC);
9277c478bd9Sstevel@tonic-gate 				} else {
9287c478bd9Sstevel@tonic-gate 					/*
9297c478bd9Sstevel@tonic-gate 					 * If another property matched but this
9307c478bd9Sstevel@tonic-gate 					 * one doesn't then reset firstmatch.
9317c478bd9Sstevel@tonic-gate 					 */
9327c478bd9Sstevel@tonic-gate 					if (firstmatch == cur)
9337c478bd9Sstevel@tonic-gate 						firstmatch = NULL;
9347c478bd9Sstevel@tonic-gate 				}
9357c478bd9Sstevel@tonic-gate 			}
9367c478bd9Sstevel@tonic-gate 		}
9377c478bd9Sstevel@tonic-gate 		if (strlen(tabptr->zone_fs_type) > 0) {
9387c478bd9Sstevel@tonic-gate 			if ((fetchprop(cur, DTD_ATTR_TYPE, type,
9397c478bd9Sstevel@tonic-gate 			    sizeof (type)) == Z_OK)) {
9407c478bd9Sstevel@tonic-gate 				if (strcmp(tabptr->zone_fs_type, type) == 0) {
9417c478bd9Sstevel@tonic-gate 					if (firstmatch == NULL)
9427c478bd9Sstevel@tonic-gate 						firstmatch = cur;
9437c478bd9Sstevel@tonic-gate 					else if (firstmatch != cur)
9447c478bd9Sstevel@tonic-gate 						return (Z_INSUFFICIENT_SPEC);
9457c478bd9Sstevel@tonic-gate 				} else {
9467c478bd9Sstevel@tonic-gate 					/*
9477c478bd9Sstevel@tonic-gate 					 * If another property matched but this
9487c478bd9Sstevel@tonic-gate 					 * one doesn't then reset firstmatch.
9497c478bd9Sstevel@tonic-gate 					 */
9507c478bd9Sstevel@tonic-gate 					if (firstmatch == cur)
9517c478bd9Sstevel@tonic-gate 						firstmatch = NULL;
9527c478bd9Sstevel@tonic-gate 				}
9537c478bd9Sstevel@tonic-gate 			}
9547c478bd9Sstevel@tonic-gate 		}
9557c478bd9Sstevel@tonic-gate 	}
9567c478bd9Sstevel@tonic-gate 
9577c478bd9Sstevel@tonic-gate 	if (firstmatch == NULL)
9587c478bd9Sstevel@tonic-gate 		return (Z_NO_RESOURCE_ID);
9597c478bd9Sstevel@tonic-gate 
9607c478bd9Sstevel@tonic-gate 	cur = firstmatch;
9617c478bd9Sstevel@tonic-gate 
9627c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir,
9637c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_fs_dir))) != Z_OK)
9647c478bd9Sstevel@tonic-gate 		return (err);
9657c478bd9Sstevel@tonic-gate 
9667c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_SPECIAL, tabptr->zone_fs_special,
9677c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_fs_special))) != Z_OK)
9687c478bd9Sstevel@tonic-gate 		return (err);
9697c478bd9Sstevel@tonic-gate 
9707c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_RAW, tabptr->zone_fs_raw,
9717c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_fs_raw))) != Z_OK)
9727c478bd9Sstevel@tonic-gate 		return (err);
9737c478bd9Sstevel@tonic-gate 
9747c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_TYPE, tabptr->zone_fs_type,
9757c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_fs_type))) != Z_OK)
9767c478bd9Sstevel@tonic-gate 		return (err);
9777c478bd9Sstevel@tonic-gate 
9787c478bd9Sstevel@tonic-gate 	/* options are optional */
9797c478bd9Sstevel@tonic-gate 	tabptr->zone_fs_options = NULL;
9807c478bd9Sstevel@tonic-gate 	for (options = cur->xmlChildrenNode; options != NULL;
9817c478bd9Sstevel@tonic-gate 	    options = options->next) {
9827c478bd9Sstevel@tonic-gate 		if ((fetchprop(options, DTD_ATTR_NAME, options_str,
9837c478bd9Sstevel@tonic-gate 		    sizeof (options_str)) != Z_OK))
9847c478bd9Sstevel@tonic-gate 			break;
9857c478bd9Sstevel@tonic-gate 		if (zonecfg_add_fs_option(tabptr, options_str) != Z_OK)
9867c478bd9Sstevel@tonic-gate 			break;
9877c478bd9Sstevel@tonic-gate 	}
9887c478bd9Sstevel@tonic-gate 	return (Z_OK);
9897c478bd9Sstevel@tonic-gate }
9907c478bd9Sstevel@tonic-gate 
9917c478bd9Sstevel@tonic-gate int
9927c478bd9Sstevel@tonic-gate zonecfg_lookup_ipd(zone_dochandle_t handle, struct zone_fstab *tabptr)
9937c478bd9Sstevel@tonic-gate {
9947c478bd9Sstevel@tonic-gate 	xmlNodePtr cur, match;
9957c478bd9Sstevel@tonic-gate 	int err;
9967c478bd9Sstevel@tonic-gate 	char dirname[MAXPATHLEN];
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 	/*
10057c478bd9Sstevel@tonic-gate 	 * General algorithm:
10067c478bd9Sstevel@tonic-gate 	 * Walk the list of children looking for matches on any properties
10077c478bd9Sstevel@tonic-gate 	 * specified in the fstab parameter.  If more than one resource
10087c478bd9Sstevel@tonic-gate 	 * matches, we return Z_INSUFFICIENT_SPEC; if none match, we return
10097c478bd9Sstevel@tonic-gate 	 * Z_NO_RESOURCE_ID.
10107c478bd9Sstevel@tonic-gate 	 */
10117c478bd9Sstevel@tonic-gate 	cur = handle->zone_dh_cur;
10127c478bd9Sstevel@tonic-gate 	match = NULL;
10137c478bd9Sstevel@tonic-gate 	for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
10147c478bd9Sstevel@tonic-gate 		if (xmlStrcmp(cur->name, DTD_ELEM_IPD))
10157c478bd9Sstevel@tonic-gate 			continue;
10167c478bd9Sstevel@tonic-gate 		if (strlen(tabptr->zone_fs_dir) > 0) {
10177c478bd9Sstevel@tonic-gate 			if ((fetchprop(cur, DTD_ATTR_DIR, dirname,
10187c478bd9Sstevel@tonic-gate 			    sizeof (dirname)) == Z_OK) &&
10197c478bd9Sstevel@tonic-gate 			    (strcmp(tabptr->zone_fs_dir, dirname) == 0)) {
10207c478bd9Sstevel@tonic-gate 				if (match == NULL)
10217c478bd9Sstevel@tonic-gate 					match = cur;
10227c478bd9Sstevel@tonic-gate 				else
10237c478bd9Sstevel@tonic-gate 					return (Z_INSUFFICIENT_SPEC);
10247c478bd9Sstevel@tonic-gate 			}
10257c478bd9Sstevel@tonic-gate 		}
10267c478bd9Sstevel@tonic-gate 	}
10277c478bd9Sstevel@tonic-gate 
10287c478bd9Sstevel@tonic-gate 	if (match == NULL)
10297c478bd9Sstevel@tonic-gate 		return (Z_NO_RESOURCE_ID);
10307c478bd9Sstevel@tonic-gate 
10317c478bd9Sstevel@tonic-gate 	cur = match;
10327c478bd9Sstevel@tonic-gate 
10337c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir,
10347c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_fs_dir))) != Z_OK)
10357c478bd9Sstevel@tonic-gate 		return (err);
10367c478bd9Sstevel@tonic-gate 
10377c478bd9Sstevel@tonic-gate 	return (Z_OK);
10387c478bd9Sstevel@tonic-gate }
10397c478bd9Sstevel@tonic-gate 
10407c478bd9Sstevel@tonic-gate /*
10417c478bd9Sstevel@tonic-gate  * Compare two IP addresses in string form.  Allow for the possibility that
10427c478bd9Sstevel@tonic-gate  * one might have "/<prefix-length>" at the end: allow a match on just the
10437c478bd9Sstevel@tonic-gate  * IP address (or host name) part.
10447c478bd9Sstevel@tonic-gate  */
10457c478bd9Sstevel@tonic-gate 
10467c478bd9Sstevel@tonic-gate boolean_t
10477c478bd9Sstevel@tonic-gate zonecfg_same_net_address(char *a1, char *a2)
10487c478bd9Sstevel@tonic-gate {
10497c478bd9Sstevel@tonic-gate 	char *slashp, *slashp1, *slashp2;
10507c478bd9Sstevel@tonic-gate 	int result;
10517c478bd9Sstevel@tonic-gate 
10527c478bd9Sstevel@tonic-gate 	if (strcmp(a1, a2) == 0)
10537c478bd9Sstevel@tonic-gate 		return (B_TRUE);
10547c478bd9Sstevel@tonic-gate 
10557c478bd9Sstevel@tonic-gate 	/*
10567c478bd9Sstevel@tonic-gate 	 * If neither has a slash or both do, they need to match to be
10577c478bd9Sstevel@tonic-gate 	 * considered the same, but they did not match above, so fail.
10587c478bd9Sstevel@tonic-gate 	 */
10597c478bd9Sstevel@tonic-gate 	slashp1 = strchr(a1, '/');
10607c478bd9Sstevel@tonic-gate 	slashp2 = strchr(a2, '/');
10617c478bd9Sstevel@tonic-gate 	if ((slashp1 == NULL && slashp2 == NULL) ||
10627c478bd9Sstevel@tonic-gate 	    (slashp1 != NULL && slashp2 != NULL))
10637c478bd9Sstevel@tonic-gate 		return (B_FALSE);
10647c478bd9Sstevel@tonic-gate 
10657c478bd9Sstevel@tonic-gate 	/*
10667c478bd9Sstevel@tonic-gate 	 * Only one had a slash: pick that one, zero out the slash, compare
10677c478bd9Sstevel@tonic-gate 	 * the "address only" strings, restore the slash, and return the
10687c478bd9Sstevel@tonic-gate 	 * result of the comparison.
10697c478bd9Sstevel@tonic-gate 	 */
10707c478bd9Sstevel@tonic-gate 	slashp = (slashp1 == NULL) ? slashp2 : slashp1;
10717c478bd9Sstevel@tonic-gate 	*slashp = '\0';
10727c478bd9Sstevel@tonic-gate 	result = strcmp(a1, a2);
10737c478bd9Sstevel@tonic-gate 	*slashp = '/';
10747c478bd9Sstevel@tonic-gate 	return ((result == 0));
10757c478bd9Sstevel@tonic-gate }
10767c478bd9Sstevel@tonic-gate 
10777c478bd9Sstevel@tonic-gate int
10787c478bd9Sstevel@tonic-gate zonecfg_valid_net_address(char *address, struct lifreq *lifr)
10797c478bd9Sstevel@tonic-gate {
10807c478bd9Sstevel@tonic-gate 	struct sockaddr_in *sin4;
10817c478bd9Sstevel@tonic-gate 	struct sockaddr_in6 *sin6;
10827c478bd9Sstevel@tonic-gate 	struct addrinfo hints, *result;
10837c478bd9Sstevel@tonic-gate 	char *slashp = strchr(address, '/');
10847c478bd9Sstevel@tonic-gate 
10857c478bd9Sstevel@tonic-gate 	bzero(lifr, sizeof (struct lifreq));
10867c478bd9Sstevel@tonic-gate 	sin4 = (struct sockaddr_in *)&lifr->lifr_addr;
10877c478bd9Sstevel@tonic-gate 	sin6 = (struct sockaddr_in6 *)&lifr->lifr_addr;
10887c478bd9Sstevel@tonic-gate 	if (slashp != NULL)
10897c478bd9Sstevel@tonic-gate 		*slashp = '\0';
10907c478bd9Sstevel@tonic-gate 	if (inet_pton(AF_INET, address, &sin4->sin_addr) == 1) {
10917c478bd9Sstevel@tonic-gate 		sin4->sin_family = AF_INET;
10927c478bd9Sstevel@tonic-gate 	} else if (inet_pton(AF_INET6, address, &sin6->sin6_addr) == 1) {
10937c478bd9Sstevel@tonic-gate 		if (slashp == NULL)
10947c478bd9Sstevel@tonic-gate 			return (Z_IPV6_ADDR_PREFIX_LEN);
10957c478bd9Sstevel@tonic-gate 		sin6->sin6_family = AF_INET6;
10967c478bd9Sstevel@tonic-gate 	} else {
10977c478bd9Sstevel@tonic-gate 		/* "address" may be a host name */
10987c478bd9Sstevel@tonic-gate 		(void) memset(&hints, 0, sizeof (hints));
10997c478bd9Sstevel@tonic-gate 		hints.ai_family = PF_INET;
11007c478bd9Sstevel@tonic-gate 		if (getaddrinfo(address, NULL, &hints, &result) != 0)
11017c478bd9Sstevel@tonic-gate 			return (Z_BOGUS_ADDRESS);
11027c478bd9Sstevel@tonic-gate 		sin4->sin_family = result->ai_family;
1103*a1be23daSdp 
11047c478bd9Sstevel@tonic-gate 		(void) memcpy(&sin4->sin_addr,
11057c478bd9Sstevel@tonic-gate 		    /* LINTED E_BAD_PTR_CAST_ALIGN */
11067c478bd9Sstevel@tonic-gate 		    &((struct sockaddr_in *)result->ai_addr)->sin_addr,
11077c478bd9Sstevel@tonic-gate 		    sizeof (struct in_addr));
1108*a1be23daSdp 
11097c478bd9Sstevel@tonic-gate 		freeaddrinfo(result);
11107c478bd9Sstevel@tonic-gate 	}
11117c478bd9Sstevel@tonic-gate 	return (Z_OK);
11127c478bd9Sstevel@tonic-gate }
11137c478bd9Sstevel@tonic-gate 
11147c478bd9Sstevel@tonic-gate int
11157c478bd9Sstevel@tonic-gate zonecfg_lookup_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
11167c478bd9Sstevel@tonic-gate {
11177c478bd9Sstevel@tonic-gate 	xmlNodePtr cur, firstmatch;
11187c478bd9Sstevel@tonic-gate 	int err;
11197c478bd9Sstevel@tonic-gate 	char address[INET6_ADDRSTRLEN], physical[LIFNAMSIZ];
11207c478bd9Sstevel@tonic-gate 
11217c478bd9Sstevel@tonic-gate 	if (tabptr == NULL)
11227c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
11237c478bd9Sstevel@tonic-gate 
11247c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
11257c478bd9Sstevel@tonic-gate 		return (err);
11267c478bd9Sstevel@tonic-gate 
11277c478bd9Sstevel@tonic-gate 	cur = handle->zone_dh_cur;
11287c478bd9Sstevel@tonic-gate 	firstmatch = NULL;
11297c478bd9Sstevel@tonic-gate 	for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
11307c478bd9Sstevel@tonic-gate 		if (xmlStrcmp(cur->name, DTD_ELEM_NET))
11317c478bd9Sstevel@tonic-gate 			continue;
11327c478bd9Sstevel@tonic-gate 		if (strlen(tabptr->zone_nwif_physical) > 0) {
11337c478bd9Sstevel@tonic-gate 			if ((fetchprop(cur, DTD_ATTR_PHYSICAL, physical,
11347c478bd9Sstevel@tonic-gate 			    sizeof (physical)) == Z_OK) &&
11357c478bd9Sstevel@tonic-gate 			    (strcmp(tabptr->zone_nwif_physical,
11367c478bd9Sstevel@tonic-gate 			    physical) == 0)) {
11377c478bd9Sstevel@tonic-gate 				if (firstmatch == NULL)
11387c478bd9Sstevel@tonic-gate 					firstmatch = cur;
11397c478bd9Sstevel@tonic-gate 				else
11407c478bd9Sstevel@tonic-gate 					return (Z_INSUFFICIENT_SPEC);
11417c478bd9Sstevel@tonic-gate 			}
11427c478bd9Sstevel@tonic-gate 		}
11437c478bd9Sstevel@tonic-gate 		if (strlen(tabptr->zone_nwif_address) > 0) {
11447c478bd9Sstevel@tonic-gate 			if ((fetchprop(cur, DTD_ATTR_ADDRESS, address,
11457c478bd9Sstevel@tonic-gate 			    sizeof (address)) == Z_OK)) {
11467c478bd9Sstevel@tonic-gate 				if (zonecfg_same_net_address(
11477c478bd9Sstevel@tonic-gate 				    tabptr->zone_nwif_address, address)) {
11487c478bd9Sstevel@tonic-gate 					if (firstmatch == NULL)
11497c478bd9Sstevel@tonic-gate 						firstmatch = cur;
11507c478bd9Sstevel@tonic-gate 					else if (firstmatch != cur)
11517c478bd9Sstevel@tonic-gate 						return (Z_INSUFFICIENT_SPEC);
11527c478bd9Sstevel@tonic-gate 				} else {
11537c478bd9Sstevel@tonic-gate 					/*
11547c478bd9Sstevel@tonic-gate 					 * If another property matched but this
11557c478bd9Sstevel@tonic-gate 					 * one doesn't then reset firstmatch.
11567c478bd9Sstevel@tonic-gate 					 */
11577c478bd9Sstevel@tonic-gate 					if (firstmatch == cur)
11587c478bd9Sstevel@tonic-gate 						firstmatch = NULL;
11597c478bd9Sstevel@tonic-gate 				}
11607c478bd9Sstevel@tonic-gate 			}
11617c478bd9Sstevel@tonic-gate 		}
11627c478bd9Sstevel@tonic-gate 	}
11637c478bd9Sstevel@tonic-gate 	if (firstmatch == NULL)
11647c478bd9Sstevel@tonic-gate 		return (Z_NO_RESOURCE_ID);
11657c478bd9Sstevel@tonic-gate 
11667c478bd9Sstevel@tonic-gate 	cur = firstmatch;
11677c478bd9Sstevel@tonic-gate 
11687c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_PHYSICAL, tabptr->zone_nwif_physical,
11697c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_nwif_physical))) != Z_OK)
11707c478bd9Sstevel@tonic-gate 		return (err);
11717c478bd9Sstevel@tonic-gate 
11727c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_ADDRESS, tabptr->zone_nwif_address,
11737c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_nwif_address))) != Z_OK)
11747c478bd9Sstevel@tonic-gate 		return (err);
11757c478bd9Sstevel@tonic-gate 
11767c478bd9Sstevel@tonic-gate 	return (Z_OK);
11777c478bd9Sstevel@tonic-gate }
11787c478bd9Sstevel@tonic-gate 
11797c478bd9Sstevel@tonic-gate static int
11807c478bd9Sstevel@tonic-gate zonecfg_add_nwif_core(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
11817c478bd9Sstevel@tonic-gate {
11827c478bd9Sstevel@tonic-gate 	xmlNodePtr newnode, cur = handle->zone_dh_cur;
11837c478bd9Sstevel@tonic-gate 	int err;
11847c478bd9Sstevel@tonic-gate 
11857c478bd9Sstevel@tonic-gate 	newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_NET, NULL);
1186*a1be23daSdp 	if ((err = newprop(newnode, DTD_ATTR_ADDRESS,
11877c478bd9Sstevel@tonic-gate 	    tabptr->zone_nwif_address)) != Z_OK)
11887c478bd9Sstevel@tonic-gate 		return (err);
1189*a1be23daSdp 	if ((err = newprop(newnode, DTD_ATTR_PHYSICAL,
11907c478bd9Sstevel@tonic-gate 	    tabptr->zone_nwif_physical)) != Z_OK)
11917c478bd9Sstevel@tonic-gate 		return (err);
11927c478bd9Sstevel@tonic-gate 	return (Z_OK);
11937c478bd9Sstevel@tonic-gate }
11947c478bd9Sstevel@tonic-gate 
11957c478bd9Sstevel@tonic-gate int
11967c478bd9Sstevel@tonic-gate zonecfg_add_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
11977c478bd9Sstevel@tonic-gate {
11987c478bd9Sstevel@tonic-gate 	int err;
11997c478bd9Sstevel@tonic-gate 
12007c478bd9Sstevel@tonic-gate 	if (tabptr == NULL)
12017c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
12027c478bd9Sstevel@tonic-gate 
12037c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
12047c478bd9Sstevel@tonic-gate 		return (err);
12057c478bd9Sstevel@tonic-gate 
12067c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_add_nwif_core(handle, tabptr)) != Z_OK)
12077c478bd9Sstevel@tonic-gate 		return (err);
12087c478bd9Sstevel@tonic-gate 
12097c478bd9Sstevel@tonic-gate 	return (Z_OK);
12107c478bd9Sstevel@tonic-gate }
12117c478bd9Sstevel@tonic-gate 
12127c478bd9Sstevel@tonic-gate static int
12137c478bd9Sstevel@tonic-gate zonecfg_delete_nwif_core(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
12147c478bd9Sstevel@tonic-gate {
12157c478bd9Sstevel@tonic-gate 	xmlNodePtr cur = handle->zone_dh_cur;
12167c478bd9Sstevel@tonic-gate 	boolean_t addr_match, phys_match;
12177c478bd9Sstevel@tonic-gate 
12187c478bd9Sstevel@tonic-gate 	for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
12197c478bd9Sstevel@tonic-gate 		if (xmlStrcmp(cur->name, DTD_ELEM_NET))
12207c478bd9Sstevel@tonic-gate 			continue;
12217c478bd9Sstevel@tonic-gate 
12227c478bd9Sstevel@tonic-gate 		addr_match = match_prop(cur, DTD_ATTR_ADDRESS,
12237c478bd9Sstevel@tonic-gate 		    tabptr->zone_nwif_address);
12247c478bd9Sstevel@tonic-gate 		phys_match = match_prop(cur, DTD_ATTR_PHYSICAL,
12257c478bd9Sstevel@tonic-gate 		    tabptr->zone_nwif_physical);
12267c478bd9Sstevel@tonic-gate 
12277c478bd9Sstevel@tonic-gate 		if (addr_match && phys_match) {
12287c478bd9Sstevel@tonic-gate 			xmlUnlinkNode(cur);
12297c478bd9Sstevel@tonic-gate 			xmlFreeNode(cur);
12307c478bd9Sstevel@tonic-gate 			return (Z_OK);
12317c478bd9Sstevel@tonic-gate 		}
12327c478bd9Sstevel@tonic-gate 	}
12337c478bd9Sstevel@tonic-gate 	return (Z_NO_RESOURCE_ID);
12347c478bd9Sstevel@tonic-gate }
12357c478bd9Sstevel@tonic-gate 
12367c478bd9Sstevel@tonic-gate int
12377c478bd9Sstevel@tonic-gate zonecfg_delete_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
12387c478bd9Sstevel@tonic-gate {
12397c478bd9Sstevel@tonic-gate 	int err;
12407c478bd9Sstevel@tonic-gate 
12417c478bd9Sstevel@tonic-gate 	if (tabptr == NULL)
12427c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
12437c478bd9Sstevel@tonic-gate 
12447c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
12457c478bd9Sstevel@tonic-gate 		return (err);
12467c478bd9Sstevel@tonic-gate 
12477c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_delete_nwif_core(handle, tabptr)) != Z_OK)
12487c478bd9Sstevel@tonic-gate 		return (err);
12497c478bd9Sstevel@tonic-gate 
12507c478bd9Sstevel@tonic-gate 	return (Z_OK);
12517c478bd9Sstevel@tonic-gate }
12527c478bd9Sstevel@tonic-gate 
12537c478bd9Sstevel@tonic-gate int
12547c478bd9Sstevel@tonic-gate zonecfg_modify_nwif(
12557c478bd9Sstevel@tonic-gate 	zone_dochandle_t handle,
12567c478bd9Sstevel@tonic-gate 	struct zone_nwiftab *oldtabptr,
12577c478bd9Sstevel@tonic-gate 	struct zone_nwiftab *newtabptr)
12587c478bd9Sstevel@tonic-gate {
12597c478bd9Sstevel@tonic-gate 	int err;
12607c478bd9Sstevel@tonic-gate 
12617c478bd9Sstevel@tonic-gate 	if (oldtabptr == NULL || newtabptr == NULL)
12627c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
12637c478bd9Sstevel@tonic-gate 
12647c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
12657c478bd9Sstevel@tonic-gate 		return (err);
12667c478bd9Sstevel@tonic-gate 
12677c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_delete_nwif_core(handle, oldtabptr)) != Z_OK)
12687c478bd9Sstevel@tonic-gate 		return (err);
12697c478bd9Sstevel@tonic-gate 
12707c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_add_nwif_core(handle, newtabptr)) != Z_OK)
12717c478bd9Sstevel@tonic-gate 		return (err);
12727c478bd9Sstevel@tonic-gate 
12737c478bd9Sstevel@tonic-gate 	return (Z_OK);
12747c478bd9Sstevel@tonic-gate }
12757c478bd9Sstevel@tonic-gate 
12767c478bd9Sstevel@tonic-gate int
12777c478bd9Sstevel@tonic-gate zonecfg_lookup_dev(zone_dochandle_t handle, struct zone_devtab *tabptr)
12787c478bd9Sstevel@tonic-gate {
12797c478bd9Sstevel@tonic-gate 	xmlNodePtr cur, firstmatch;
12807c478bd9Sstevel@tonic-gate 	int err;
12817c478bd9Sstevel@tonic-gate 	char match[MAXPATHLEN];
12827c478bd9Sstevel@tonic-gate 
12837c478bd9Sstevel@tonic-gate 	if (tabptr == NULL)
12847c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
12857c478bd9Sstevel@tonic-gate 
12867c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
12877c478bd9Sstevel@tonic-gate 		return (err);
12887c478bd9Sstevel@tonic-gate 
12897c478bd9Sstevel@tonic-gate 	cur = handle->zone_dh_cur;
12907c478bd9Sstevel@tonic-gate 	firstmatch = NULL;
12917c478bd9Sstevel@tonic-gate 	for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
12927c478bd9Sstevel@tonic-gate 		if (xmlStrcmp(cur->name, DTD_ELEM_DEVICE))
12937c478bd9Sstevel@tonic-gate 			continue;
12947c478bd9Sstevel@tonic-gate 		if (strlen(tabptr->zone_dev_match) == 0)
12957c478bd9Sstevel@tonic-gate 			continue;
12967c478bd9Sstevel@tonic-gate 
12977c478bd9Sstevel@tonic-gate 		if ((fetchprop(cur, DTD_ATTR_MATCH, match,
12987c478bd9Sstevel@tonic-gate 		    sizeof (match)) == Z_OK)) {
12997c478bd9Sstevel@tonic-gate 			if (strcmp(tabptr->zone_dev_match,
13007c478bd9Sstevel@tonic-gate 			    match) == 0) {
13017c478bd9Sstevel@tonic-gate 				if (firstmatch == NULL)
13027c478bd9Sstevel@tonic-gate 					firstmatch = cur;
13037c478bd9Sstevel@tonic-gate 				else if (firstmatch != cur)
13047c478bd9Sstevel@tonic-gate 					return (Z_INSUFFICIENT_SPEC);
13057c478bd9Sstevel@tonic-gate 			} else {
13067c478bd9Sstevel@tonic-gate 				/*
13077c478bd9Sstevel@tonic-gate 				 * If another property matched but this
13087c478bd9Sstevel@tonic-gate 				 * one doesn't then reset firstmatch.
13097c478bd9Sstevel@tonic-gate 				 */
13107c478bd9Sstevel@tonic-gate 				if (firstmatch == cur)
13117c478bd9Sstevel@tonic-gate 					firstmatch = NULL;
13127c478bd9Sstevel@tonic-gate 			}
13137c478bd9Sstevel@tonic-gate 		}
13147c478bd9Sstevel@tonic-gate 	}
13157c478bd9Sstevel@tonic-gate 	if (firstmatch == NULL)
13167c478bd9Sstevel@tonic-gate 		return (Z_NO_RESOURCE_ID);
13177c478bd9Sstevel@tonic-gate 
13187c478bd9Sstevel@tonic-gate 	cur = firstmatch;
13197c478bd9Sstevel@tonic-gate 
13207c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_MATCH, tabptr->zone_dev_match,
13217c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_dev_match))) != Z_OK)
13227c478bd9Sstevel@tonic-gate 		return (err);
13237c478bd9Sstevel@tonic-gate 
13247c478bd9Sstevel@tonic-gate 	return (Z_OK);
13257c478bd9Sstevel@tonic-gate }
13267c478bd9Sstevel@tonic-gate 
13277c478bd9Sstevel@tonic-gate static int
13287c478bd9Sstevel@tonic-gate zonecfg_add_dev_core(zone_dochandle_t handle, struct zone_devtab *tabptr)
13297c478bd9Sstevel@tonic-gate {
13307c478bd9Sstevel@tonic-gate 	xmlNodePtr newnode, cur = handle->zone_dh_cur;
13317c478bd9Sstevel@tonic-gate 	int err;
13327c478bd9Sstevel@tonic-gate 
13337c478bd9Sstevel@tonic-gate 	newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_DEVICE, NULL);
13347c478bd9Sstevel@tonic-gate 
1335*a1be23daSdp 	if ((err = newprop(newnode, DTD_ATTR_MATCH,
13367c478bd9Sstevel@tonic-gate 	    tabptr->zone_dev_match)) != Z_OK)
13377c478bd9Sstevel@tonic-gate 		return (err);
13387c478bd9Sstevel@tonic-gate 
13397c478bd9Sstevel@tonic-gate 	return (Z_OK);
13407c478bd9Sstevel@tonic-gate }
13417c478bd9Sstevel@tonic-gate 
13427c478bd9Sstevel@tonic-gate int
13437c478bd9Sstevel@tonic-gate zonecfg_add_dev(zone_dochandle_t handle, struct zone_devtab *tabptr)
13447c478bd9Sstevel@tonic-gate {
13457c478bd9Sstevel@tonic-gate 	int err;
13467c478bd9Sstevel@tonic-gate 
13477c478bd9Sstevel@tonic-gate 	if (tabptr == NULL)
13487c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
13497c478bd9Sstevel@tonic-gate 
13507c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
13517c478bd9Sstevel@tonic-gate 		return (err);
13527c478bd9Sstevel@tonic-gate 
13537c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_add_dev_core(handle, tabptr)) != Z_OK)
13547c478bd9Sstevel@tonic-gate 		return (err);
13557c478bd9Sstevel@tonic-gate 
13567c478bd9Sstevel@tonic-gate 	return (Z_OK);
13577c478bd9Sstevel@tonic-gate }
13587c478bd9Sstevel@tonic-gate 
13597c478bd9Sstevel@tonic-gate static int
13607c478bd9Sstevel@tonic-gate zonecfg_delete_dev_core(zone_dochandle_t handle, struct zone_devtab *tabptr)
13617c478bd9Sstevel@tonic-gate {
13627c478bd9Sstevel@tonic-gate 	xmlNodePtr cur = handle->zone_dh_cur;
13637c478bd9Sstevel@tonic-gate 	int match_match;
13647c478bd9Sstevel@tonic-gate 
13657c478bd9Sstevel@tonic-gate 	for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
13667c478bd9Sstevel@tonic-gate 		if (xmlStrcmp(cur->name, DTD_ELEM_DEVICE))
13677c478bd9Sstevel@tonic-gate 			continue;
13687c478bd9Sstevel@tonic-gate 
13697c478bd9Sstevel@tonic-gate 		match_match = match_prop(cur, DTD_ATTR_MATCH,
13707c478bd9Sstevel@tonic-gate 		    tabptr->zone_dev_match);
13717c478bd9Sstevel@tonic-gate 
13727c478bd9Sstevel@tonic-gate 		if (match_match) {
13737c478bd9Sstevel@tonic-gate 			xmlUnlinkNode(cur);
13747c478bd9Sstevel@tonic-gate 			xmlFreeNode(cur);
13757c478bd9Sstevel@tonic-gate 			return (Z_OK);
13767c478bd9Sstevel@tonic-gate 		}
13777c478bd9Sstevel@tonic-gate 	}
13787c478bd9Sstevel@tonic-gate 	return (Z_NO_RESOURCE_ID);
13797c478bd9Sstevel@tonic-gate }
13807c478bd9Sstevel@tonic-gate 
13817c478bd9Sstevel@tonic-gate int
13827c478bd9Sstevel@tonic-gate zonecfg_delete_dev(zone_dochandle_t handle, struct zone_devtab *tabptr)
13837c478bd9Sstevel@tonic-gate {
13847c478bd9Sstevel@tonic-gate 	int err;
13857c478bd9Sstevel@tonic-gate 
13867c478bd9Sstevel@tonic-gate 	if (tabptr == NULL)
13877c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
13887c478bd9Sstevel@tonic-gate 
13897c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
13907c478bd9Sstevel@tonic-gate 		return (err);
13917c478bd9Sstevel@tonic-gate 
13927c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_delete_dev_core(handle, tabptr)) != Z_OK)
13937c478bd9Sstevel@tonic-gate 		return (err);
13947c478bd9Sstevel@tonic-gate 
13957c478bd9Sstevel@tonic-gate 	return (Z_OK);
13967c478bd9Sstevel@tonic-gate }
13977c478bd9Sstevel@tonic-gate 
13987c478bd9Sstevel@tonic-gate int
13997c478bd9Sstevel@tonic-gate zonecfg_modify_dev(
14007c478bd9Sstevel@tonic-gate 	zone_dochandle_t handle,
14017c478bd9Sstevel@tonic-gate 	struct zone_devtab *oldtabptr,
14027c478bd9Sstevel@tonic-gate 	struct zone_devtab *newtabptr)
14037c478bd9Sstevel@tonic-gate {
14047c478bd9Sstevel@tonic-gate 	int err;
14057c478bd9Sstevel@tonic-gate 
14067c478bd9Sstevel@tonic-gate 	if (oldtabptr == NULL || newtabptr == NULL)
14077c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
14087c478bd9Sstevel@tonic-gate 
14097c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
14107c478bd9Sstevel@tonic-gate 		return (err);
14117c478bd9Sstevel@tonic-gate 
14127c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_delete_dev_core(handle, oldtabptr)) != Z_OK)
14137c478bd9Sstevel@tonic-gate 		return (err);
14147c478bd9Sstevel@tonic-gate 
14157c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_add_dev_core(handle, newtabptr)) != Z_OK)
14167c478bd9Sstevel@tonic-gate 		return (err);
14177c478bd9Sstevel@tonic-gate 
14187c478bd9Sstevel@tonic-gate 	return (Z_OK);
14197c478bd9Sstevel@tonic-gate }
14207c478bd9Sstevel@tonic-gate 
14217c478bd9Sstevel@tonic-gate /*
14227c478bd9Sstevel@tonic-gate  * This is the set of devices which must be present in every zone.  Users
14237c478bd9Sstevel@tonic-gate  * can augment this list with additional device rules in their zone
14247c478bd9Sstevel@tonic-gate  * configuration, but at present cannot remove any of the this set of
14257c478bd9Sstevel@tonic-gate  * standard devices.  All matching is done by /dev pathname (the "/dev"
14267c478bd9Sstevel@tonic-gate  * part is implicit.  Try to keep rules which match a large number of
14277c478bd9Sstevel@tonic-gate  * devices (like the pts rule) first.
14287c478bd9Sstevel@tonic-gate  */
14297c478bd9Sstevel@tonic-gate static const char *standard_devs[] = {
14307c478bd9Sstevel@tonic-gate 	"pts/*",
14317c478bd9Sstevel@tonic-gate 	"ptmx",
14327c478bd9Sstevel@tonic-gate 	"random",
14337c478bd9Sstevel@tonic-gate 	"urandom",
14347c478bd9Sstevel@tonic-gate 	"poll",
14357c478bd9Sstevel@tonic-gate 	"pool",
14367c478bd9Sstevel@tonic-gate 	"kstat",
14377c478bd9Sstevel@tonic-gate 	"zero",
14387c478bd9Sstevel@tonic-gate 	"null",
14397c478bd9Sstevel@tonic-gate 	"crypto",
14407c478bd9Sstevel@tonic-gate 	"cryptoadm",
14417c478bd9Sstevel@tonic-gate 	"ticots",
14427c478bd9Sstevel@tonic-gate 	"ticotsord",
14437c478bd9Sstevel@tonic-gate 	"ticlts",
14447c478bd9Sstevel@tonic-gate 	"lo0",
14457c478bd9Sstevel@tonic-gate 	"lo1",
14467c478bd9Sstevel@tonic-gate 	"lo2",
14477c478bd9Sstevel@tonic-gate 	"lo3",
14487c478bd9Sstevel@tonic-gate 	"sad/user",
14497c478bd9Sstevel@tonic-gate 	"tty",
14507c478bd9Sstevel@tonic-gate 	"logindmux",
14517c478bd9Sstevel@tonic-gate 	"log",
14527c478bd9Sstevel@tonic-gate 	"conslog",
14537c478bd9Sstevel@tonic-gate 	"arp",
14547c478bd9Sstevel@tonic-gate 	"tcp",
14557c478bd9Sstevel@tonic-gate 	"tcp6",
14567c478bd9Sstevel@tonic-gate 	"udp",
14577c478bd9Sstevel@tonic-gate 	"udp6",
14587c478bd9Sstevel@tonic-gate 	"sysevent",
14597c478bd9Sstevel@tonic-gate #ifdef __sparc
14607c478bd9Sstevel@tonic-gate 	"openprom",
14617c478bd9Sstevel@tonic-gate #endif
14627c478bd9Sstevel@tonic-gate 	"cpu/self/cpuid",
14637c478bd9Sstevel@tonic-gate 	"dtrace/helper",
14647c478bd9Sstevel@tonic-gate 	NULL
14657c478bd9Sstevel@tonic-gate };
14667c478bd9Sstevel@tonic-gate 
14677c478bd9Sstevel@tonic-gate /*
14687c478bd9Sstevel@tonic-gate  * This function finds everything mounted under a zone's rootpath.
14697c478bd9Sstevel@tonic-gate  * This returns the number of mounts under rootpath, or -1 on error.
14707c478bd9Sstevel@tonic-gate  * callback is called once per mount found with the first argument
14717c478bd9Sstevel@tonic-gate  * pointing to the  mount point.
14727c478bd9Sstevel@tonic-gate  *
14737c478bd9Sstevel@tonic-gate  * If the callback function returns non-zero zonecfg_find_mounts
14747c478bd9Sstevel@tonic-gate  * aborts with an error.
14757c478bd9Sstevel@tonic-gate  */
14767c478bd9Sstevel@tonic-gate 
14777c478bd9Sstevel@tonic-gate int
14787c478bd9Sstevel@tonic-gate zonecfg_find_mounts(char *rootpath, int (*callback)(const char *, void *),
14797c478bd9Sstevel@tonic-gate     void *priv) {
14807c478bd9Sstevel@tonic-gate 	FILE *mnttab;
14817c478bd9Sstevel@tonic-gate 	struct mnttab m;
14827c478bd9Sstevel@tonic-gate 	size_t l;
14837c478bd9Sstevel@tonic-gate 	int rv = 0;
14847c478bd9Sstevel@tonic-gate 
14857c478bd9Sstevel@tonic-gate 	assert(rootpath != NULL);
14867c478bd9Sstevel@tonic-gate 
14877c478bd9Sstevel@tonic-gate 	l = strlen(rootpath);
14887c478bd9Sstevel@tonic-gate 
14897c478bd9Sstevel@tonic-gate 	mnttab = fopen("/etc/mnttab", "r");
14907c478bd9Sstevel@tonic-gate 
14917c478bd9Sstevel@tonic-gate 	if (mnttab == NULL)
14927c478bd9Sstevel@tonic-gate 		return (-1);
14937c478bd9Sstevel@tonic-gate 
14947c478bd9Sstevel@tonic-gate 	if (ioctl(fileno(mnttab), MNTIOC_SHOWHIDDEN, NULL) < 0)  {
14957c478bd9Sstevel@tonic-gate 		rv = -1;
14967c478bd9Sstevel@tonic-gate 		goto out;
14977c478bd9Sstevel@tonic-gate 	}
14987c478bd9Sstevel@tonic-gate 
14997c478bd9Sstevel@tonic-gate 	while (!getmntent(mnttab, &m)) {
15007c478bd9Sstevel@tonic-gate 		if ((strncmp(rootpath, m.mnt_mountp, l) == 0) &&
15017c478bd9Sstevel@tonic-gate 		    (m.mnt_mountp[l] == '/')) {
15027c478bd9Sstevel@tonic-gate 			rv++;
15037c478bd9Sstevel@tonic-gate 			if (callback == NULL)
15047c478bd9Sstevel@tonic-gate 				continue;
15057c478bd9Sstevel@tonic-gate 			if (callback(m.mnt_mountp, priv)) {
15067c478bd9Sstevel@tonic-gate 				rv = -1;
15077c478bd9Sstevel@tonic-gate 				goto out;
15087c478bd9Sstevel@tonic-gate 
15097c478bd9Sstevel@tonic-gate 			}
15107c478bd9Sstevel@tonic-gate 		}
15117c478bd9Sstevel@tonic-gate 	}
15127c478bd9Sstevel@tonic-gate 
15137c478bd9Sstevel@tonic-gate out:
15147c478bd9Sstevel@tonic-gate 	(void) fclose(mnttab);
15157c478bd9Sstevel@tonic-gate 	return (rv);
15167c478bd9Sstevel@tonic-gate }
15177c478bd9Sstevel@tonic-gate 
15187c478bd9Sstevel@tonic-gate /*
15197c478bd9Sstevel@tonic-gate  * This routine is used to determine if a given device should appear in the
15207c478bd9Sstevel@tonic-gate  * zone represented by 'handle'.  First it consults the list of "standard"
15217c478bd9Sstevel@tonic-gate  * zone devices.  Then it scans the user-supplied device entries.
15227c478bd9Sstevel@tonic-gate  */
15237c478bd9Sstevel@tonic-gate int
15247c478bd9Sstevel@tonic-gate zonecfg_match_dev(zone_dochandle_t handle, char *devpath,
15257c478bd9Sstevel@tonic-gate     struct zone_devtab *out_match)
15267c478bd9Sstevel@tonic-gate {
15277c478bd9Sstevel@tonic-gate 	int err;
15287c478bd9Sstevel@tonic-gate 	boolean_t found = B_FALSE;
15297c478bd9Sstevel@tonic-gate 	char match[MAXPATHLEN];
15307c478bd9Sstevel@tonic-gate 	const char **stdmatch;
15317c478bd9Sstevel@tonic-gate 	xmlNodePtr cur;
15327c478bd9Sstevel@tonic-gate 
15337c478bd9Sstevel@tonic-gate 	if (handle == NULL || devpath == NULL)
15347c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
15357c478bd9Sstevel@tonic-gate 
15367c478bd9Sstevel@tonic-gate 	/*
15377c478bd9Sstevel@tonic-gate 	 * Check the "standard" devices which we require to be present.
15387c478bd9Sstevel@tonic-gate 	 */
15397c478bd9Sstevel@tonic-gate 	for (stdmatch = &standard_devs[0]; *stdmatch != NULL; stdmatch++) {
15407c478bd9Sstevel@tonic-gate 		/*
15417c478bd9Sstevel@tonic-gate 		 * fnmatch gives us simple but powerful shell-style matching.
15427c478bd9Sstevel@tonic-gate 		 */
15437c478bd9Sstevel@tonic-gate 		if (fnmatch(*stdmatch, devpath, FNM_PATHNAME) == 0) {
15447c478bd9Sstevel@tonic-gate 			if (!out_match)
15457c478bd9Sstevel@tonic-gate 				return (Z_OK);
15467c478bd9Sstevel@tonic-gate 			(void) snprintf(out_match->zone_dev_match,
15477c478bd9Sstevel@tonic-gate 			    sizeof (out_match->zone_dev_match),
15487c478bd9Sstevel@tonic-gate 			    "/dev/%s", *stdmatch);
15497c478bd9Sstevel@tonic-gate 			return (Z_OK);
15507c478bd9Sstevel@tonic-gate 		}
15517c478bd9Sstevel@tonic-gate 	}
15527c478bd9Sstevel@tonic-gate 
15537c478bd9Sstevel@tonic-gate 	/*
15547c478bd9Sstevel@tonic-gate 	 * We got no hits in the set of standard devices.  On to the user
15557c478bd9Sstevel@tonic-gate 	 * supplied ones.
15567c478bd9Sstevel@tonic-gate 	 */
15577c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK) {
15587c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = NULL;
15597c478bd9Sstevel@tonic-gate 		return (err);
15607c478bd9Sstevel@tonic-gate 	}
15617c478bd9Sstevel@tonic-gate 
15627c478bd9Sstevel@tonic-gate 	cur = handle->zone_dh_cur;
15637c478bd9Sstevel@tonic-gate 	cur = cur->xmlChildrenNode;
15647c478bd9Sstevel@tonic-gate 	if (cur == NULL)
15657c478bd9Sstevel@tonic-gate 		return (Z_NO_ENTRY);
15667c478bd9Sstevel@tonic-gate 	handle->zone_dh_cur = cur;
15677c478bd9Sstevel@tonic-gate 
15687c478bd9Sstevel@tonic-gate 	for (; cur != NULL; cur = cur->next) {
15697c478bd9Sstevel@tonic-gate 		char *m;
15707c478bd9Sstevel@tonic-gate 		if (xmlStrcmp(cur->name, DTD_ELEM_DEVICE) != 0)
15717c478bd9Sstevel@tonic-gate 			continue;
15727c478bd9Sstevel@tonic-gate 		if ((err = fetchprop(cur, DTD_ATTR_MATCH, match,
15737c478bd9Sstevel@tonic-gate 		    sizeof (match))) != Z_OK) {
15747c478bd9Sstevel@tonic-gate 			handle->zone_dh_cur = handle->zone_dh_top;
15757c478bd9Sstevel@tonic-gate 			return (err);
15767c478bd9Sstevel@tonic-gate 		}
15777c478bd9Sstevel@tonic-gate 		m = match;
15787c478bd9Sstevel@tonic-gate 		/*
15797c478bd9Sstevel@tonic-gate 		 * fnmatch gives us simple but powerful shell-style matching;
15807c478bd9Sstevel@tonic-gate 		 * but first, we need to strip out /dev/ from the matching rule.
15817c478bd9Sstevel@tonic-gate 		 */
15827c478bd9Sstevel@tonic-gate 		if (strncmp(m, "/dev/", 5) == 0)
15837c478bd9Sstevel@tonic-gate 			m += 5;
15847c478bd9Sstevel@tonic-gate 
15857c478bd9Sstevel@tonic-gate 		if (fnmatch(m, devpath, FNM_PATHNAME) == 0) {
15867c478bd9Sstevel@tonic-gate 			found = B_TRUE;
15877c478bd9Sstevel@tonic-gate 			break;
15887c478bd9Sstevel@tonic-gate 		}
15897c478bd9Sstevel@tonic-gate 	}
15907c478bd9Sstevel@tonic-gate 
15917c478bd9Sstevel@tonic-gate 	if (!found)
15927c478bd9Sstevel@tonic-gate 		return (Z_NO_ENTRY);
15937c478bd9Sstevel@tonic-gate 
15947c478bd9Sstevel@tonic-gate 	if (!out_match)
15957c478bd9Sstevel@tonic-gate 		return (Z_OK);
15967c478bd9Sstevel@tonic-gate 
15977c478bd9Sstevel@tonic-gate 	(void) strlcpy(out_match->zone_dev_match, match,
15987c478bd9Sstevel@tonic-gate 	    sizeof (out_match->zone_dev_match));
15997c478bd9Sstevel@tonic-gate 	return (Z_OK);
16007c478bd9Sstevel@tonic-gate }
16017c478bd9Sstevel@tonic-gate 
16027c478bd9Sstevel@tonic-gate int
16037c478bd9Sstevel@tonic-gate zonecfg_lookup_attr(zone_dochandle_t handle, struct zone_attrtab *tabptr)
16047c478bd9Sstevel@tonic-gate {
16057c478bd9Sstevel@tonic-gate 	xmlNodePtr cur, firstmatch;
16067c478bd9Sstevel@tonic-gate 	int err;
16077c478bd9Sstevel@tonic-gate 	char name[MAXNAMELEN], type[MAXNAMELEN], value[MAXNAMELEN];
16087c478bd9Sstevel@tonic-gate 
16097c478bd9Sstevel@tonic-gate 	if (tabptr == NULL)
16107c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
16117c478bd9Sstevel@tonic-gate 
16127c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
16137c478bd9Sstevel@tonic-gate 		return (err);
16147c478bd9Sstevel@tonic-gate 
16157c478bd9Sstevel@tonic-gate 	cur = handle->zone_dh_cur;
16167c478bd9Sstevel@tonic-gate 	firstmatch = NULL;
16177c478bd9Sstevel@tonic-gate 	for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
16187c478bd9Sstevel@tonic-gate 		if (xmlStrcmp(cur->name, DTD_ELEM_ATTR))
16197c478bd9Sstevel@tonic-gate 			continue;
16207c478bd9Sstevel@tonic-gate 		if (strlen(tabptr->zone_attr_name) > 0) {
16217c478bd9Sstevel@tonic-gate 			if ((fetchprop(cur, DTD_ATTR_NAME, name,
16227c478bd9Sstevel@tonic-gate 			    sizeof (name)) == Z_OK) &&
16237c478bd9Sstevel@tonic-gate 			    (strcmp(tabptr->zone_attr_name, name) == 0)) {
16247c478bd9Sstevel@tonic-gate 				if (firstmatch == NULL)
16257c478bd9Sstevel@tonic-gate 					firstmatch = cur;
16267c478bd9Sstevel@tonic-gate 				else
16277c478bd9Sstevel@tonic-gate 					return (Z_INSUFFICIENT_SPEC);
16287c478bd9Sstevel@tonic-gate 			}
16297c478bd9Sstevel@tonic-gate 		}
16307c478bd9Sstevel@tonic-gate 		if (strlen(tabptr->zone_attr_type) > 0) {
16317c478bd9Sstevel@tonic-gate 			if ((fetchprop(cur, DTD_ATTR_TYPE, type,
16327c478bd9Sstevel@tonic-gate 			    sizeof (type)) == Z_OK)) {
16337c478bd9Sstevel@tonic-gate 				if (strcmp(tabptr->zone_attr_type, type) == 0) {
16347c478bd9Sstevel@tonic-gate 					if (firstmatch == NULL)
16357c478bd9Sstevel@tonic-gate 						firstmatch = cur;
16367c478bd9Sstevel@tonic-gate 					else if (firstmatch != cur)
16377c478bd9Sstevel@tonic-gate 						return (Z_INSUFFICIENT_SPEC);
16387c478bd9Sstevel@tonic-gate 				} else {
16397c478bd9Sstevel@tonic-gate 					/*
16407c478bd9Sstevel@tonic-gate 					 * If another property matched but this
16417c478bd9Sstevel@tonic-gate 					 * one doesn't then reset firstmatch.
16427c478bd9Sstevel@tonic-gate 					 */
16437c478bd9Sstevel@tonic-gate 					if (firstmatch == cur)
16447c478bd9Sstevel@tonic-gate 						firstmatch = NULL;
16457c478bd9Sstevel@tonic-gate 				}
16467c478bd9Sstevel@tonic-gate 			}
16477c478bd9Sstevel@tonic-gate 		}
16487c478bd9Sstevel@tonic-gate 		if (strlen(tabptr->zone_attr_value) > 0) {
16497c478bd9Sstevel@tonic-gate 			if ((fetchprop(cur, DTD_ATTR_VALUE, value,
16507c478bd9Sstevel@tonic-gate 			    sizeof (value)) == Z_OK)) {
16517c478bd9Sstevel@tonic-gate 				if (strcmp(tabptr->zone_attr_value, value) ==
16527c478bd9Sstevel@tonic-gate 				    0) {
16537c478bd9Sstevel@tonic-gate 					if (firstmatch == NULL)
16547c478bd9Sstevel@tonic-gate 						firstmatch = cur;
16557c478bd9Sstevel@tonic-gate 					else if (firstmatch != cur)
16567c478bd9Sstevel@tonic-gate 						return (Z_INSUFFICIENT_SPEC);
16577c478bd9Sstevel@tonic-gate 				} else {
16587c478bd9Sstevel@tonic-gate 					/*
16597c478bd9Sstevel@tonic-gate 					 * If another property matched but this
16607c478bd9Sstevel@tonic-gate 					 * one doesn't then reset firstmatch.
16617c478bd9Sstevel@tonic-gate 					 */
16627c478bd9Sstevel@tonic-gate 					if (firstmatch == cur)
16637c478bd9Sstevel@tonic-gate 						firstmatch = NULL;
16647c478bd9Sstevel@tonic-gate 				}
16657c478bd9Sstevel@tonic-gate 			}
16667c478bd9Sstevel@tonic-gate 		}
16677c478bd9Sstevel@tonic-gate 	}
16687c478bd9Sstevel@tonic-gate 	if (firstmatch == NULL)
16697c478bd9Sstevel@tonic-gate 		return (Z_NO_RESOURCE_ID);
16707c478bd9Sstevel@tonic-gate 
16717c478bd9Sstevel@tonic-gate 	cur = firstmatch;
16727c478bd9Sstevel@tonic-gate 
16737c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_NAME, tabptr->zone_attr_name,
16747c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_attr_name))) != Z_OK)
16757c478bd9Sstevel@tonic-gate 		return (err);
16767c478bd9Sstevel@tonic-gate 
16777c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_TYPE, tabptr->zone_attr_type,
16787c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_attr_type))) != Z_OK)
16797c478bd9Sstevel@tonic-gate 		return (err);
16807c478bd9Sstevel@tonic-gate 
16817c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_VALUE, tabptr->zone_attr_value,
16827c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_attr_value))) != Z_OK)
16837c478bd9Sstevel@tonic-gate 		return (err);
16847c478bd9Sstevel@tonic-gate 
16857c478bd9Sstevel@tonic-gate 	return (Z_OK);
16867c478bd9Sstevel@tonic-gate }
16877c478bd9Sstevel@tonic-gate 
16887c478bd9Sstevel@tonic-gate static int
16897c478bd9Sstevel@tonic-gate zonecfg_add_attr_core(zone_dochandle_t handle, struct zone_attrtab *tabptr)
16907c478bd9Sstevel@tonic-gate {
16917c478bd9Sstevel@tonic-gate 	xmlNodePtr newnode, cur = handle->zone_dh_cur;
16927c478bd9Sstevel@tonic-gate 	int err;
16937c478bd9Sstevel@tonic-gate 
16947c478bd9Sstevel@tonic-gate 	newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_ATTR, NULL);
1695*a1be23daSdp 	err = newprop(newnode, DTD_ATTR_NAME, tabptr->zone_attr_name);
16967c478bd9Sstevel@tonic-gate 	if (err != Z_OK)
16977c478bd9Sstevel@tonic-gate 		return (err);
1698*a1be23daSdp 	err = newprop(newnode, DTD_ATTR_TYPE, tabptr->zone_attr_type);
16997c478bd9Sstevel@tonic-gate 	if (err != Z_OK)
17007c478bd9Sstevel@tonic-gate 		return (err);
1701*a1be23daSdp 	err = newprop(newnode, DTD_ATTR_VALUE, tabptr->zone_attr_value);
17027c478bd9Sstevel@tonic-gate 	if (err != Z_OK)
17037c478bd9Sstevel@tonic-gate 		return (err);
17047c478bd9Sstevel@tonic-gate 	return (Z_OK);
17057c478bd9Sstevel@tonic-gate }
17067c478bd9Sstevel@tonic-gate 
17077c478bd9Sstevel@tonic-gate int
17087c478bd9Sstevel@tonic-gate zonecfg_add_attr(zone_dochandle_t handle, struct zone_attrtab *tabptr)
17097c478bd9Sstevel@tonic-gate {
17107c478bd9Sstevel@tonic-gate 	int err;
17117c478bd9Sstevel@tonic-gate 
17127c478bd9Sstevel@tonic-gate 	if (tabptr == NULL)
17137c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
17147c478bd9Sstevel@tonic-gate 
17157c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
17167c478bd9Sstevel@tonic-gate 		return (err);
17177c478bd9Sstevel@tonic-gate 
17187c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_add_attr_core(handle, tabptr)) != Z_OK)
17197c478bd9Sstevel@tonic-gate 		return (err);
17207c478bd9Sstevel@tonic-gate 
17217c478bd9Sstevel@tonic-gate 	return (Z_OK);
17227c478bd9Sstevel@tonic-gate }
17237c478bd9Sstevel@tonic-gate 
17247c478bd9Sstevel@tonic-gate static int
17257c478bd9Sstevel@tonic-gate zonecfg_delete_attr_core(zone_dochandle_t handle, struct zone_attrtab *tabptr)
17267c478bd9Sstevel@tonic-gate {
17277c478bd9Sstevel@tonic-gate 	xmlNodePtr cur = handle->zone_dh_cur;
17287c478bd9Sstevel@tonic-gate 	int name_match, type_match, value_match;
17297c478bd9Sstevel@tonic-gate 
17307c478bd9Sstevel@tonic-gate 	for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
17317c478bd9Sstevel@tonic-gate 		if (xmlStrcmp(cur->name, DTD_ELEM_ATTR))
17327c478bd9Sstevel@tonic-gate 			continue;
17337c478bd9Sstevel@tonic-gate 
17347c478bd9Sstevel@tonic-gate 		name_match = match_prop(cur, DTD_ATTR_NAME,
17357c478bd9Sstevel@tonic-gate 		    tabptr->zone_attr_name);
17367c478bd9Sstevel@tonic-gate 		type_match = match_prop(cur, DTD_ATTR_TYPE,
17377c478bd9Sstevel@tonic-gate 		    tabptr->zone_attr_type);
17387c478bd9Sstevel@tonic-gate 		value_match = match_prop(cur, DTD_ATTR_VALUE,
17397c478bd9Sstevel@tonic-gate 		    tabptr->zone_attr_value);
17407c478bd9Sstevel@tonic-gate 
17417c478bd9Sstevel@tonic-gate 		if (name_match && type_match && value_match) {
17427c478bd9Sstevel@tonic-gate 			xmlUnlinkNode(cur);
17437c478bd9Sstevel@tonic-gate 			xmlFreeNode(cur);
17447c478bd9Sstevel@tonic-gate 			return (Z_OK);
17457c478bd9Sstevel@tonic-gate 		}
17467c478bd9Sstevel@tonic-gate 	}
17477c478bd9Sstevel@tonic-gate 	return (Z_NO_RESOURCE_ID);
17487c478bd9Sstevel@tonic-gate }
17497c478bd9Sstevel@tonic-gate 
17507c478bd9Sstevel@tonic-gate int
17517c478bd9Sstevel@tonic-gate zonecfg_delete_attr(zone_dochandle_t handle, struct zone_attrtab *tabptr)
17527c478bd9Sstevel@tonic-gate {
17537c478bd9Sstevel@tonic-gate 	int err;
17547c478bd9Sstevel@tonic-gate 
17557c478bd9Sstevel@tonic-gate 	if (tabptr == NULL)
17567c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
17577c478bd9Sstevel@tonic-gate 
17587c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
17597c478bd9Sstevel@tonic-gate 		return (err);
17607c478bd9Sstevel@tonic-gate 
17617c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_delete_attr_core(handle, tabptr)) != Z_OK)
17627c478bd9Sstevel@tonic-gate 		return (err);
17637c478bd9Sstevel@tonic-gate 
17647c478bd9Sstevel@tonic-gate 	return (Z_OK);
17657c478bd9Sstevel@tonic-gate }
17667c478bd9Sstevel@tonic-gate 
17677c478bd9Sstevel@tonic-gate int
17687c478bd9Sstevel@tonic-gate zonecfg_modify_attr(
17697c478bd9Sstevel@tonic-gate 	zone_dochandle_t handle,
17707c478bd9Sstevel@tonic-gate 	struct zone_attrtab *oldtabptr,
17717c478bd9Sstevel@tonic-gate 	struct zone_attrtab *newtabptr)
17727c478bd9Sstevel@tonic-gate {
17737c478bd9Sstevel@tonic-gate 	int err;
17747c478bd9Sstevel@tonic-gate 
17757c478bd9Sstevel@tonic-gate 	if (oldtabptr == NULL || newtabptr == 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_attr_core(handle, oldtabptr)) != Z_OK)
17827c478bd9Sstevel@tonic-gate 		return (err);
17837c478bd9Sstevel@tonic-gate 
17847c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_add_attr_core(handle, newtabptr)) != Z_OK)
17857c478bd9Sstevel@tonic-gate 		return (err);
17867c478bd9Sstevel@tonic-gate 
17877c478bd9Sstevel@tonic-gate 	return (Z_OK);
17887c478bd9Sstevel@tonic-gate }
17897c478bd9Sstevel@tonic-gate 
17907c478bd9Sstevel@tonic-gate int
17917c478bd9Sstevel@tonic-gate zonecfg_get_attr_boolean(const struct zone_attrtab *attr, boolean_t *value)
17927c478bd9Sstevel@tonic-gate {
17937c478bd9Sstevel@tonic-gate 	if (attr == NULL)
17947c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
17957c478bd9Sstevel@tonic-gate 
17967c478bd9Sstevel@tonic-gate 	if (strcmp(attr->zone_attr_type, DTD_ENTITY_BOOLEAN) != 0)
17977c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
17987c478bd9Sstevel@tonic-gate 
17997c478bd9Sstevel@tonic-gate 	if (strcmp(attr->zone_attr_value, DTD_ENTITY_TRUE) == 0) {
18007c478bd9Sstevel@tonic-gate 		*value = B_TRUE;
18017c478bd9Sstevel@tonic-gate 		return (Z_OK);
18027c478bd9Sstevel@tonic-gate 	}
18037c478bd9Sstevel@tonic-gate 	if (strcmp(attr->zone_attr_value, DTD_ENTITY_FALSE) == 0) {
18047c478bd9Sstevel@tonic-gate 		*value = B_FALSE;
18057c478bd9Sstevel@tonic-gate 		return (Z_OK);
18067c478bd9Sstevel@tonic-gate 	}
18077c478bd9Sstevel@tonic-gate 	return (Z_INVAL);
18087c478bd9Sstevel@tonic-gate }
18097c478bd9Sstevel@tonic-gate 
18107c478bd9Sstevel@tonic-gate int
18117c478bd9Sstevel@tonic-gate zonecfg_get_attr_int(const struct zone_attrtab *attr, int64_t *value)
18127c478bd9Sstevel@tonic-gate {
18137c478bd9Sstevel@tonic-gate 	long long result;
18147c478bd9Sstevel@tonic-gate 	char *endptr;
18157c478bd9Sstevel@tonic-gate 
18167c478bd9Sstevel@tonic-gate 	if (attr == NULL)
18177c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
18187c478bd9Sstevel@tonic-gate 
18197c478bd9Sstevel@tonic-gate 	if (strcmp(attr->zone_attr_type, DTD_ENTITY_INT) != 0)
18207c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
18217c478bd9Sstevel@tonic-gate 
18227c478bd9Sstevel@tonic-gate 	errno = 0;
18237c478bd9Sstevel@tonic-gate 	result = strtoll(attr->zone_attr_value, &endptr, 10);
18247c478bd9Sstevel@tonic-gate 	if (errno != 0 || *endptr != '\0')
18257c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
18267c478bd9Sstevel@tonic-gate 	*value = result;
18277c478bd9Sstevel@tonic-gate 	return (Z_OK);
18287c478bd9Sstevel@tonic-gate }
18297c478bd9Sstevel@tonic-gate 
18307c478bd9Sstevel@tonic-gate int
18317c478bd9Sstevel@tonic-gate zonecfg_get_attr_string(const struct zone_attrtab *attr, char *value,
18327c478bd9Sstevel@tonic-gate     size_t val_sz)
18337c478bd9Sstevel@tonic-gate {
18347c478bd9Sstevel@tonic-gate 	if (attr == NULL)
18357c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
18367c478bd9Sstevel@tonic-gate 
18377c478bd9Sstevel@tonic-gate 	if (strcmp(attr->zone_attr_type, DTD_ENTITY_STRING) != 0)
18387c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
18397c478bd9Sstevel@tonic-gate 
18407c478bd9Sstevel@tonic-gate 	if (strlcpy(value, attr->zone_attr_value, val_sz) >= val_sz)
18417c478bd9Sstevel@tonic-gate 		return (Z_TOO_BIG);
18427c478bd9Sstevel@tonic-gate 	return (Z_OK);
18437c478bd9Sstevel@tonic-gate }
18447c478bd9Sstevel@tonic-gate 
18457c478bd9Sstevel@tonic-gate int
18467c478bd9Sstevel@tonic-gate zonecfg_get_attr_uint(const struct zone_attrtab *attr, uint64_t *value)
18477c478bd9Sstevel@tonic-gate {
18487c478bd9Sstevel@tonic-gate 	unsigned long long result;
18497c478bd9Sstevel@tonic-gate 	long long neg_result;
18507c478bd9Sstevel@tonic-gate 	char *endptr;
18517c478bd9Sstevel@tonic-gate 
18527c478bd9Sstevel@tonic-gate 	if (attr == NULL)
18537c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
18547c478bd9Sstevel@tonic-gate 
18557c478bd9Sstevel@tonic-gate 	if (strcmp(attr->zone_attr_type, DTD_ENTITY_UINT) != 0)
18567c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
18577c478bd9Sstevel@tonic-gate 
18587c478bd9Sstevel@tonic-gate 	errno = 0;
18597c478bd9Sstevel@tonic-gate 	result = strtoull(attr->zone_attr_value, &endptr, 10);
18607c478bd9Sstevel@tonic-gate 	if (errno != 0 || *endptr != '\0')
18617c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
18627c478bd9Sstevel@tonic-gate 	errno = 0;
18637c478bd9Sstevel@tonic-gate 	neg_result = strtoll(attr->zone_attr_value, &endptr, 10);
18647c478bd9Sstevel@tonic-gate 	/*
18657c478bd9Sstevel@tonic-gate 	 * Incredibly, strtoull("<negative number>", ...) will not fail but
18667c478bd9Sstevel@tonic-gate 	 * return whatever (negative) number cast as a u_longlong_t, so we
18677c478bd9Sstevel@tonic-gate 	 * need to look for this here.
18687c478bd9Sstevel@tonic-gate 	 */
18697c478bd9Sstevel@tonic-gate 	if (errno == 0 && neg_result < 0)
18707c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
18717c478bd9Sstevel@tonic-gate 	*value = result;
18727c478bd9Sstevel@tonic-gate 	return (Z_OK);
18737c478bd9Sstevel@tonic-gate }
18747c478bd9Sstevel@tonic-gate 
18757c478bd9Sstevel@tonic-gate int
18767c478bd9Sstevel@tonic-gate zonecfg_lookup_rctl(zone_dochandle_t handle, struct zone_rctltab *tabptr)
18777c478bd9Sstevel@tonic-gate {
18787c478bd9Sstevel@tonic-gate 	xmlNodePtr cur, val;
18797c478bd9Sstevel@tonic-gate 	char savedname[MAXNAMELEN];
18807c478bd9Sstevel@tonic-gate 	struct zone_rctlvaltab *valptr;
18817c478bd9Sstevel@tonic-gate 	int err;
18827c478bd9Sstevel@tonic-gate 
18837c478bd9Sstevel@tonic-gate 	if (tabptr->zone_rctl_name == NULL ||
18847c478bd9Sstevel@tonic-gate 	    strlen(tabptr->zone_rctl_name) == 0)
18857c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
18867c478bd9Sstevel@tonic-gate 
18877c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
18887c478bd9Sstevel@tonic-gate 		return (err);
18897c478bd9Sstevel@tonic-gate 
18907c478bd9Sstevel@tonic-gate 	cur = handle->zone_dh_cur;
18917c478bd9Sstevel@tonic-gate 	for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
18927c478bd9Sstevel@tonic-gate 		if (xmlStrcmp(cur->name, DTD_ELEM_RCTL))
18937c478bd9Sstevel@tonic-gate 			continue;
18947c478bd9Sstevel@tonic-gate 		if ((fetchprop(cur, DTD_ATTR_NAME, savedname,
18957c478bd9Sstevel@tonic-gate 		    sizeof (savedname)) == Z_OK) &&
18967c478bd9Sstevel@tonic-gate 		    (strcmp(savedname, tabptr->zone_rctl_name) == 0)) {
18977c478bd9Sstevel@tonic-gate 			tabptr->zone_rctl_valptr = NULL;
18987c478bd9Sstevel@tonic-gate 			for (val = cur->xmlChildrenNode; val != NULL;
18997c478bd9Sstevel@tonic-gate 			    val = val->next) {
19007c478bd9Sstevel@tonic-gate 				valptr = (struct zone_rctlvaltab *)malloc(
19017c478bd9Sstevel@tonic-gate 				    sizeof (struct zone_rctlvaltab));
19027c478bd9Sstevel@tonic-gate 				if (valptr == NULL)
19037c478bd9Sstevel@tonic-gate 					return (Z_NOMEM);
19047c478bd9Sstevel@tonic-gate 				if ((fetchprop(val, DTD_ATTR_PRIV,
19057c478bd9Sstevel@tonic-gate 				    valptr->zone_rctlval_priv,
19067c478bd9Sstevel@tonic-gate 				    sizeof (valptr->zone_rctlval_priv)) !=
19077c478bd9Sstevel@tonic-gate 				    Z_OK))
19087c478bd9Sstevel@tonic-gate 					break;
19097c478bd9Sstevel@tonic-gate 				if ((fetchprop(val, DTD_ATTR_LIMIT,
19107c478bd9Sstevel@tonic-gate 				    valptr->zone_rctlval_limit,
19117c478bd9Sstevel@tonic-gate 				    sizeof (valptr->zone_rctlval_limit)) !=
19127c478bd9Sstevel@tonic-gate 				    Z_OK))
19137c478bd9Sstevel@tonic-gate 					break;
19147c478bd9Sstevel@tonic-gate 				if ((fetchprop(val, DTD_ATTR_ACTION,
19157c478bd9Sstevel@tonic-gate 				    valptr->zone_rctlval_action,
19167c478bd9Sstevel@tonic-gate 				    sizeof (valptr->zone_rctlval_action)) !=
19177c478bd9Sstevel@tonic-gate 				    Z_OK))
19187c478bd9Sstevel@tonic-gate 					break;
19197c478bd9Sstevel@tonic-gate 				if (zonecfg_add_rctl_value(tabptr, valptr) !=
19207c478bd9Sstevel@tonic-gate 				    Z_OK)
19217c478bd9Sstevel@tonic-gate 					break;
19227c478bd9Sstevel@tonic-gate 			}
19237c478bd9Sstevel@tonic-gate 			return (Z_OK);
19247c478bd9Sstevel@tonic-gate 		}
19257c478bd9Sstevel@tonic-gate 	}
19267c478bd9Sstevel@tonic-gate 	return (Z_NO_RESOURCE_ID);
19277c478bd9Sstevel@tonic-gate }
19287c478bd9Sstevel@tonic-gate 
19297c478bd9Sstevel@tonic-gate static int
19307c478bd9Sstevel@tonic-gate zonecfg_add_rctl_core(zone_dochandle_t handle, struct zone_rctltab *tabptr)
19317c478bd9Sstevel@tonic-gate {
19327c478bd9Sstevel@tonic-gate 	xmlNodePtr newnode, cur = handle->zone_dh_cur, valnode;
19337c478bd9Sstevel@tonic-gate 	struct zone_rctlvaltab *valptr;
19347c478bd9Sstevel@tonic-gate 	int err;
19357c478bd9Sstevel@tonic-gate 
19367c478bd9Sstevel@tonic-gate 	newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_RCTL, NULL);
1937*a1be23daSdp 	err = newprop(newnode, DTD_ATTR_NAME, tabptr->zone_rctl_name);
19387c478bd9Sstevel@tonic-gate 	if (err != Z_OK)
19397c478bd9Sstevel@tonic-gate 		return (err);
19407c478bd9Sstevel@tonic-gate 	for (valptr = tabptr->zone_rctl_valptr; valptr != NULL;
19417c478bd9Sstevel@tonic-gate 	    valptr = valptr->zone_rctlval_next) {
19427c478bd9Sstevel@tonic-gate 		valnode = xmlNewTextChild(newnode, NULL,
19437c478bd9Sstevel@tonic-gate 		    DTD_ELEM_RCTLVALUE, NULL);
1944*a1be23daSdp 		err = newprop(valnode, DTD_ATTR_PRIV,
19457c478bd9Sstevel@tonic-gate 		    valptr->zone_rctlval_priv);
19467c478bd9Sstevel@tonic-gate 		if (err != Z_OK)
19477c478bd9Sstevel@tonic-gate 			return (err);
1948*a1be23daSdp 		err = newprop(valnode, DTD_ATTR_LIMIT,
19497c478bd9Sstevel@tonic-gate 		    valptr->zone_rctlval_limit);
19507c478bd9Sstevel@tonic-gate 		if (err != Z_OK)
19517c478bd9Sstevel@tonic-gate 			return (err);
1952*a1be23daSdp 		err = newprop(valnode, DTD_ATTR_ACTION,
19537c478bd9Sstevel@tonic-gate 		    valptr->zone_rctlval_action);
19547c478bd9Sstevel@tonic-gate 		if (err != Z_OK)
19557c478bd9Sstevel@tonic-gate 			return (err);
19567c478bd9Sstevel@tonic-gate 	}
19577c478bd9Sstevel@tonic-gate 	return (Z_OK);
19587c478bd9Sstevel@tonic-gate }
19597c478bd9Sstevel@tonic-gate 
19607c478bd9Sstevel@tonic-gate int
19617c478bd9Sstevel@tonic-gate zonecfg_add_rctl(zone_dochandle_t handle, struct zone_rctltab *tabptr)
19627c478bd9Sstevel@tonic-gate {
19637c478bd9Sstevel@tonic-gate 	int err;
19647c478bd9Sstevel@tonic-gate 
19657c478bd9Sstevel@tonic-gate 	if (tabptr == NULL || tabptr->zone_rctl_name == NULL)
19667c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
19677c478bd9Sstevel@tonic-gate 
19687c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
19697c478bd9Sstevel@tonic-gate 		return (err);
19707c478bd9Sstevel@tonic-gate 
19717c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_add_rctl_core(handle, tabptr)) != Z_OK)
19727c478bd9Sstevel@tonic-gate 		return (err);
19737c478bd9Sstevel@tonic-gate 
19747c478bd9Sstevel@tonic-gate 	return (Z_OK);
19757c478bd9Sstevel@tonic-gate }
19767c478bd9Sstevel@tonic-gate 
19777c478bd9Sstevel@tonic-gate static int
19787c478bd9Sstevel@tonic-gate zonecfg_delete_rctl_core(zone_dochandle_t handle, struct zone_rctltab *tabptr)
19797c478bd9Sstevel@tonic-gate {
19807c478bd9Sstevel@tonic-gate 	xmlNodePtr cur = handle->zone_dh_cur;
19817c478bd9Sstevel@tonic-gate 	xmlChar *savedname;
19827c478bd9Sstevel@tonic-gate 	int name_result;
19837c478bd9Sstevel@tonic-gate 
19847c478bd9Sstevel@tonic-gate 	for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
19857c478bd9Sstevel@tonic-gate 		if (xmlStrcmp(cur->name, DTD_ELEM_RCTL))
19867c478bd9Sstevel@tonic-gate 			continue;
19877c478bd9Sstevel@tonic-gate 
19887c478bd9Sstevel@tonic-gate 		savedname = xmlGetProp(cur, DTD_ATTR_NAME);
19897c478bd9Sstevel@tonic-gate 		if (savedname == NULL)	/* shouldn't happen */
19907c478bd9Sstevel@tonic-gate 			continue;
19917c478bd9Sstevel@tonic-gate 		name_result = xmlStrcmp(savedname,
19927c478bd9Sstevel@tonic-gate 		    (const xmlChar *) tabptr->zone_rctl_name);
19937c478bd9Sstevel@tonic-gate 		xmlFree(savedname);
19947c478bd9Sstevel@tonic-gate 
19957c478bd9Sstevel@tonic-gate 		if (name_result == 0) {
19967c478bd9Sstevel@tonic-gate 			xmlUnlinkNode(cur);
19977c478bd9Sstevel@tonic-gate 			xmlFreeNode(cur);
19987c478bd9Sstevel@tonic-gate 			return (Z_OK);
19997c478bd9Sstevel@tonic-gate 		}
20007c478bd9Sstevel@tonic-gate 	}
20017c478bd9Sstevel@tonic-gate 	return (Z_NO_RESOURCE_ID);
20027c478bd9Sstevel@tonic-gate }
20037c478bd9Sstevel@tonic-gate 
20047c478bd9Sstevel@tonic-gate int
20057c478bd9Sstevel@tonic-gate zonecfg_delete_rctl(zone_dochandle_t handle, struct zone_rctltab *tabptr)
20067c478bd9Sstevel@tonic-gate {
20077c478bd9Sstevel@tonic-gate 	int err;
20087c478bd9Sstevel@tonic-gate 
20097c478bd9Sstevel@tonic-gate 	if (tabptr == NULL || tabptr->zone_rctl_name == NULL)
20107c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
20117c478bd9Sstevel@tonic-gate 
20127c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
20137c478bd9Sstevel@tonic-gate 		return (err);
20147c478bd9Sstevel@tonic-gate 
20157c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_delete_rctl_core(handle, tabptr)) != Z_OK)
20167c478bd9Sstevel@tonic-gate 		return (err);
20177c478bd9Sstevel@tonic-gate 
20187c478bd9Sstevel@tonic-gate 	return (Z_OK);
20197c478bd9Sstevel@tonic-gate }
20207c478bd9Sstevel@tonic-gate 
20217c478bd9Sstevel@tonic-gate int
20227c478bd9Sstevel@tonic-gate zonecfg_modify_rctl(
20237c478bd9Sstevel@tonic-gate 	zone_dochandle_t handle,
20247c478bd9Sstevel@tonic-gate 	struct zone_rctltab *oldtabptr,
20257c478bd9Sstevel@tonic-gate 	struct zone_rctltab *newtabptr)
20267c478bd9Sstevel@tonic-gate {
20277c478bd9Sstevel@tonic-gate 	int err;
20287c478bd9Sstevel@tonic-gate 
20297c478bd9Sstevel@tonic-gate 	if (oldtabptr == NULL || oldtabptr->zone_rctl_name == NULL ||
20307c478bd9Sstevel@tonic-gate 	    newtabptr == NULL || newtabptr->zone_rctl_name == NULL)
20317c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
20327c478bd9Sstevel@tonic-gate 
20337c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
20347c478bd9Sstevel@tonic-gate 		return (err);
20357c478bd9Sstevel@tonic-gate 
20367c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_delete_rctl_core(handle, oldtabptr)) != Z_OK)
20377c478bd9Sstevel@tonic-gate 		return (err);
20387c478bd9Sstevel@tonic-gate 
20397c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_add_rctl_core(handle, newtabptr)) != Z_OK)
20407c478bd9Sstevel@tonic-gate 		return (err);
20417c478bd9Sstevel@tonic-gate 
20427c478bd9Sstevel@tonic-gate 	return (Z_OK);
20437c478bd9Sstevel@tonic-gate }
20447c478bd9Sstevel@tonic-gate 
20457c478bd9Sstevel@tonic-gate int
20467c478bd9Sstevel@tonic-gate zonecfg_add_rctl_value(
20477c478bd9Sstevel@tonic-gate 	struct zone_rctltab *tabptr,
20487c478bd9Sstevel@tonic-gate 	struct zone_rctlvaltab *valtabptr)
20497c478bd9Sstevel@tonic-gate {
20507c478bd9Sstevel@tonic-gate 	struct zone_rctlvaltab *last, *old, *new;
20517c478bd9Sstevel@tonic-gate 	rctlblk_t *rctlblk = alloca(rctlblk_size());
20527c478bd9Sstevel@tonic-gate 
20537c478bd9Sstevel@tonic-gate 	last = tabptr->zone_rctl_valptr;
20547c478bd9Sstevel@tonic-gate 	for (old = last; old != NULL; old = old->zone_rctlval_next)
20557c478bd9Sstevel@tonic-gate 		last = old;	/* walk to the end of the list */
20567c478bd9Sstevel@tonic-gate 	new = valtabptr;	/* alloc'd by caller */
20577c478bd9Sstevel@tonic-gate 	new->zone_rctlval_next = NULL;
20587c478bd9Sstevel@tonic-gate 	if (zonecfg_construct_rctlblk(valtabptr, rctlblk) != Z_OK)
20597c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
20607c478bd9Sstevel@tonic-gate 	if (!zonecfg_valid_rctlblk(rctlblk))
20617c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
20627c478bd9Sstevel@tonic-gate 	if (last == NULL)
20637c478bd9Sstevel@tonic-gate 		tabptr->zone_rctl_valptr = new;
20647c478bd9Sstevel@tonic-gate 	else
20657c478bd9Sstevel@tonic-gate 		last->zone_rctlval_next = new;
20667c478bd9Sstevel@tonic-gate 	return (Z_OK);
20677c478bd9Sstevel@tonic-gate }
20687c478bd9Sstevel@tonic-gate 
20697c478bd9Sstevel@tonic-gate int
20707c478bd9Sstevel@tonic-gate zonecfg_remove_rctl_value(
20717c478bd9Sstevel@tonic-gate 	struct zone_rctltab *tabptr,
20727c478bd9Sstevel@tonic-gate 	struct zone_rctlvaltab *valtabptr)
20737c478bd9Sstevel@tonic-gate {
20747c478bd9Sstevel@tonic-gate 	struct zone_rctlvaltab *last, *this, *next;
20757c478bd9Sstevel@tonic-gate 
20767c478bd9Sstevel@tonic-gate 	last = tabptr->zone_rctl_valptr;
20777c478bd9Sstevel@tonic-gate 	for (this = last; this != NULL; this = this->zone_rctlval_next) {
20787c478bd9Sstevel@tonic-gate 		if (strcmp(this->zone_rctlval_priv,
20797c478bd9Sstevel@tonic-gate 		    valtabptr->zone_rctlval_priv) == 0 &&
20807c478bd9Sstevel@tonic-gate 		    strcmp(this->zone_rctlval_limit,
20817c478bd9Sstevel@tonic-gate 		    valtabptr->zone_rctlval_limit) == 0 &&
20827c478bd9Sstevel@tonic-gate 		    strcmp(this->zone_rctlval_action,
20837c478bd9Sstevel@tonic-gate 		    valtabptr->zone_rctlval_action) == 0) {
20847c478bd9Sstevel@tonic-gate 			next = this->zone_rctlval_next;
20857c478bd9Sstevel@tonic-gate 			if (this == tabptr->zone_rctl_valptr)
20867c478bd9Sstevel@tonic-gate 				tabptr->zone_rctl_valptr = next;
20877c478bd9Sstevel@tonic-gate 			else
20887c478bd9Sstevel@tonic-gate 				last->zone_rctlval_next = next;
20897c478bd9Sstevel@tonic-gate 			free(this);
20907c478bd9Sstevel@tonic-gate 			return (Z_OK);
20917c478bd9Sstevel@tonic-gate 		} else
20927c478bd9Sstevel@tonic-gate 			last = this;
20937c478bd9Sstevel@tonic-gate 	}
20947c478bd9Sstevel@tonic-gate 	return (Z_NO_PROPERTY_ID);
20957c478bd9Sstevel@tonic-gate }
20967c478bd9Sstevel@tonic-gate 
20977c478bd9Sstevel@tonic-gate char *
20987c478bd9Sstevel@tonic-gate zonecfg_strerror(int errnum)
20997c478bd9Sstevel@tonic-gate {
21007c478bd9Sstevel@tonic-gate 	switch (errnum) {
21017c478bd9Sstevel@tonic-gate 	case Z_OK:
21027c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "OK"));
21037c478bd9Sstevel@tonic-gate 	case Z_EMPTY_DOCUMENT:
21047c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Empty document"));
21057c478bd9Sstevel@tonic-gate 	case Z_WRONG_DOC_TYPE:
21067c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Wrong document type"));
21077c478bd9Sstevel@tonic-gate 	case Z_BAD_PROPERTY:
21087c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Bad document property"));
21097c478bd9Sstevel@tonic-gate 	case Z_TEMP_FILE:
21107c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN,
21117c478bd9Sstevel@tonic-gate 		    "Problem creating temporary file"));
21127c478bd9Sstevel@tonic-gate 	case Z_SAVING_FILE:
21137c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Problem saving file"));
21147c478bd9Sstevel@tonic-gate 	case Z_NO_ENTRY:
21157c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "No such entry"));
21167c478bd9Sstevel@tonic-gate 	case Z_BOGUS_ZONE_NAME:
21177c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Bogus zone name"));
21187c478bd9Sstevel@tonic-gate 	case Z_REQD_RESOURCE_MISSING:
21197c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Required resource missing"));
21207c478bd9Sstevel@tonic-gate 	case Z_REQD_PROPERTY_MISSING:
21217c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Required property missing"));
21227c478bd9Sstevel@tonic-gate 	case Z_BAD_HANDLE:
21237c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Bad handle"));
21247c478bd9Sstevel@tonic-gate 	case Z_NOMEM:
21257c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Out of memory"));
21267c478bd9Sstevel@tonic-gate 	case Z_INVAL:
21277c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Invalid argument"));
21287c478bd9Sstevel@tonic-gate 	case Z_ACCES:
21297c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Permission denied"));
21307c478bd9Sstevel@tonic-gate 	case Z_TOO_BIG:
21317c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Argument list too long"));
21327c478bd9Sstevel@tonic-gate 	case Z_MISC_FS:
21337c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN,
21347c478bd9Sstevel@tonic-gate 		    "Miscellaneous file system error"));
21357c478bd9Sstevel@tonic-gate 	case Z_NO_ZONE:
21367c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "No such zone configured"));
21377c478bd9Sstevel@tonic-gate 	case Z_NO_RESOURCE_TYPE:
21387c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "No such resource type"));
21397c478bd9Sstevel@tonic-gate 	case Z_NO_RESOURCE_ID:
21407c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "No such resource with that id"));
21417c478bd9Sstevel@tonic-gate 	case Z_NO_PROPERTY_TYPE:
21427c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "No such property type"));
21437c478bd9Sstevel@tonic-gate 	case Z_NO_PROPERTY_ID:
21447c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "No such property with that id"));
21457c478bd9Sstevel@tonic-gate 	case Z_RESOURCE_EXISTS:
21467c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN,
21477c478bd9Sstevel@tonic-gate 		    "Resource already exists with that id"));
21487c478bd9Sstevel@tonic-gate 	case Z_INVALID_DOCUMENT:
21497c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Invalid document"));
21507c478bd9Sstevel@tonic-gate 	case Z_ID_IN_USE:
21517c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Zone ID in use"));
21527c478bd9Sstevel@tonic-gate 	case Z_NO_SUCH_ID:
21537c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "No such zone ID"));
21547c478bd9Sstevel@tonic-gate 	case Z_UPDATING_INDEX:
21557c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Problem updating index file"));
21567c478bd9Sstevel@tonic-gate 	case Z_LOCKING_FILE:
21577c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Locking index file"));
21587c478bd9Sstevel@tonic-gate 	case Z_UNLOCKING_FILE:
21597c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Unlocking index file"));
21607c478bd9Sstevel@tonic-gate 	case Z_INSUFFICIENT_SPEC:
21617c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Insufficient specification"));
21627c478bd9Sstevel@tonic-gate 	case Z_RESOLVED_PATH:
21637c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Resolved path mismatch"));
21647c478bd9Sstevel@tonic-gate 	case Z_IPV6_ADDR_PREFIX_LEN:
21657c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN,
21667c478bd9Sstevel@tonic-gate 		    "IPv6 address missing required prefix length"));
21677c478bd9Sstevel@tonic-gate 	case Z_BOGUS_ADDRESS:
21687c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN,
21697c478bd9Sstevel@tonic-gate 		    "Neither an IPv4 nor an IPv6 address nor a host name"));
21707c478bd9Sstevel@tonic-gate 	default:
21717c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Unknown error"));
21727c478bd9Sstevel@tonic-gate 	}
21737c478bd9Sstevel@tonic-gate }
21747c478bd9Sstevel@tonic-gate 
21757c478bd9Sstevel@tonic-gate /*
21767c478bd9Sstevel@tonic-gate  * Note that the zonecfg_setXent() and zonecfg_endXent() calls are all the
21777c478bd9Sstevel@tonic-gate  * same, as they just turn around and call zonecfg_setent() / zonecfg_endent().
21787c478bd9Sstevel@tonic-gate  */
21797c478bd9Sstevel@tonic-gate 
21807c478bd9Sstevel@tonic-gate static int
21817c478bd9Sstevel@tonic-gate zonecfg_setent(zone_dochandle_t handle)
21827c478bd9Sstevel@tonic-gate {
21837c478bd9Sstevel@tonic-gate 	xmlNodePtr cur;
21847c478bd9Sstevel@tonic-gate 	int err;
21857c478bd9Sstevel@tonic-gate 
21867c478bd9Sstevel@tonic-gate 	if (handle == NULL)
21877c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
21887c478bd9Sstevel@tonic-gate 
21897c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK) {
21907c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = NULL;
21917c478bd9Sstevel@tonic-gate 		return (err);
21927c478bd9Sstevel@tonic-gate 	}
21937c478bd9Sstevel@tonic-gate 	cur = handle->zone_dh_cur;
21947c478bd9Sstevel@tonic-gate 	cur = cur->xmlChildrenNode;
21957c478bd9Sstevel@tonic-gate 	handle->zone_dh_cur = cur;
21967c478bd9Sstevel@tonic-gate 	return (Z_OK);
21977c478bd9Sstevel@tonic-gate }
21987c478bd9Sstevel@tonic-gate 
21997c478bd9Sstevel@tonic-gate static int
22007c478bd9Sstevel@tonic-gate zonecfg_endent(zone_dochandle_t handle)
22017c478bd9Sstevel@tonic-gate {
22027c478bd9Sstevel@tonic-gate 	if (handle == NULL)
22037c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
22047c478bd9Sstevel@tonic-gate 
22057c478bd9Sstevel@tonic-gate 	handle->zone_dh_cur = handle->zone_dh_top;
22067c478bd9Sstevel@tonic-gate 	return (Z_OK);
22077c478bd9Sstevel@tonic-gate }
22087c478bd9Sstevel@tonic-gate 
22097c478bd9Sstevel@tonic-gate int
22107c478bd9Sstevel@tonic-gate zonecfg_setfsent(zone_dochandle_t handle)
22117c478bd9Sstevel@tonic-gate {
22127c478bd9Sstevel@tonic-gate 	return (zonecfg_setent(handle));
22137c478bd9Sstevel@tonic-gate }
22147c478bd9Sstevel@tonic-gate 
22157c478bd9Sstevel@tonic-gate int
22167c478bd9Sstevel@tonic-gate zonecfg_getfsent(zone_dochandle_t handle, struct zone_fstab *tabptr)
22177c478bd9Sstevel@tonic-gate {
22187c478bd9Sstevel@tonic-gate 	xmlNodePtr cur, options;
22197c478bd9Sstevel@tonic-gate 	char options_str[MAX_MNTOPT_STR];
22207c478bd9Sstevel@tonic-gate 	int err;
22217c478bd9Sstevel@tonic-gate 
22227c478bd9Sstevel@tonic-gate 	if (handle == NULL)
22237c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
22247c478bd9Sstevel@tonic-gate 
22257c478bd9Sstevel@tonic-gate 	if ((cur = handle->zone_dh_cur) == NULL)
22267c478bd9Sstevel@tonic-gate 		return (Z_NO_ENTRY);
22277c478bd9Sstevel@tonic-gate 
22287c478bd9Sstevel@tonic-gate 	for (; cur != NULL; cur = cur->next)
22297c478bd9Sstevel@tonic-gate 		if (!xmlStrcmp(cur->name, DTD_ELEM_FS))
22307c478bd9Sstevel@tonic-gate 			break;
22317c478bd9Sstevel@tonic-gate 	if (cur == NULL) {
22327c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = handle->zone_dh_top;
22337c478bd9Sstevel@tonic-gate 		return (Z_NO_ENTRY);
22347c478bd9Sstevel@tonic-gate 	}
22357c478bd9Sstevel@tonic-gate 
22367c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_SPECIAL, tabptr->zone_fs_special,
22377c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_fs_special))) != Z_OK) {
22387c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = handle->zone_dh_top;
22397c478bd9Sstevel@tonic-gate 		return (err);
22407c478bd9Sstevel@tonic-gate 	}
22417c478bd9Sstevel@tonic-gate 
22427c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_RAW, tabptr->zone_fs_raw,
22437c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_fs_raw))) != Z_OK) {
22447c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = handle->zone_dh_top;
22457c478bd9Sstevel@tonic-gate 		return (err);
22467c478bd9Sstevel@tonic-gate 	}
22477c478bd9Sstevel@tonic-gate 
22487c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir,
22497c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_fs_dir))) != Z_OK) {
22507c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = handle->zone_dh_top;
22517c478bd9Sstevel@tonic-gate 		return (err);
22527c478bd9Sstevel@tonic-gate 	}
22537c478bd9Sstevel@tonic-gate 
22547c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_TYPE, tabptr->zone_fs_type,
22557c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_fs_type))) != Z_OK) {
22567c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = handle->zone_dh_top;
22577c478bd9Sstevel@tonic-gate 		return (err);
22587c478bd9Sstevel@tonic-gate 	}
22597c478bd9Sstevel@tonic-gate 
22607c478bd9Sstevel@tonic-gate 	/* OK for options to be NULL */
22617c478bd9Sstevel@tonic-gate 	tabptr->zone_fs_options = NULL;
22627c478bd9Sstevel@tonic-gate 	for (options = cur->xmlChildrenNode; options != NULL;
22637c478bd9Sstevel@tonic-gate 	    options = options->next) {
22647c478bd9Sstevel@tonic-gate 		if (fetchprop(options, DTD_ATTR_NAME, options_str,
22657c478bd9Sstevel@tonic-gate 		    sizeof (options_str)) != Z_OK)
22667c478bd9Sstevel@tonic-gate 			break;
22677c478bd9Sstevel@tonic-gate 		if (zonecfg_add_fs_option(tabptr, options_str) != Z_OK)
22687c478bd9Sstevel@tonic-gate 			break;
22697c478bd9Sstevel@tonic-gate 	}
22707c478bd9Sstevel@tonic-gate 
22717c478bd9Sstevel@tonic-gate 	handle->zone_dh_cur = cur->next;
22727c478bd9Sstevel@tonic-gate 	return (Z_OK);
22737c478bd9Sstevel@tonic-gate }
22747c478bd9Sstevel@tonic-gate 
22757c478bd9Sstevel@tonic-gate int
22767c478bd9Sstevel@tonic-gate zonecfg_endfsent(zone_dochandle_t handle)
22777c478bd9Sstevel@tonic-gate {
22787c478bd9Sstevel@tonic-gate 	return (zonecfg_endent(handle));
22797c478bd9Sstevel@tonic-gate }
22807c478bd9Sstevel@tonic-gate 
22817c478bd9Sstevel@tonic-gate int
22827c478bd9Sstevel@tonic-gate zonecfg_setipdent(zone_dochandle_t handle)
22837c478bd9Sstevel@tonic-gate {
22847c478bd9Sstevel@tonic-gate 	return (zonecfg_setent(handle));
22857c478bd9Sstevel@tonic-gate }
22867c478bd9Sstevel@tonic-gate 
22877c478bd9Sstevel@tonic-gate int
22887c478bd9Sstevel@tonic-gate zonecfg_getipdent(zone_dochandle_t handle, struct zone_fstab *tabptr)
22897c478bd9Sstevel@tonic-gate {
22907c478bd9Sstevel@tonic-gate 	xmlNodePtr cur;
22917c478bd9Sstevel@tonic-gate 	int err;
22927c478bd9Sstevel@tonic-gate 
22937c478bd9Sstevel@tonic-gate 	if (handle == NULL)
22947c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
22957c478bd9Sstevel@tonic-gate 
22967c478bd9Sstevel@tonic-gate 	if ((cur = handle->zone_dh_cur) == NULL)
22977c478bd9Sstevel@tonic-gate 		return (Z_NO_ENTRY);
22987c478bd9Sstevel@tonic-gate 
22997c478bd9Sstevel@tonic-gate 	for (; cur != NULL; cur = cur->next)
23007c478bd9Sstevel@tonic-gate 		if (!xmlStrcmp(cur->name, DTD_ELEM_IPD))
23017c478bd9Sstevel@tonic-gate 			break;
23027c478bd9Sstevel@tonic-gate 	if (cur == NULL) {
23037c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = handle->zone_dh_top;
23047c478bd9Sstevel@tonic-gate 		return (Z_NO_ENTRY);
23057c478bd9Sstevel@tonic-gate 	}
23067c478bd9Sstevel@tonic-gate 
23077c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir,
23087c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_fs_dir))) != Z_OK) {
23097c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = handle->zone_dh_top;
23107c478bd9Sstevel@tonic-gate 		return (err);
23117c478bd9Sstevel@tonic-gate 	}
23127c478bd9Sstevel@tonic-gate 
23137c478bd9Sstevel@tonic-gate 	handle->zone_dh_cur = cur->next;
23147c478bd9Sstevel@tonic-gate 	return (Z_OK);
23157c478bd9Sstevel@tonic-gate }
23167c478bd9Sstevel@tonic-gate 
23177c478bd9Sstevel@tonic-gate int
23187c478bd9Sstevel@tonic-gate zonecfg_endipdent(zone_dochandle_t handle)
23197c478bd9Sstevel@tonic-gate {
23207c478bd9Sstevel@tonic-gate 	return (zonecfg_endent(handle));
23217c478bd9Sstevel@tonic-gate }
23227c478bd9Sstevel@tonic-gate 
23237c478bd9Sstevel@tonic-gate int
23247c478bd9Sstevel@tonic-gate zonecfg_setnwifent(zone_dochandle_t handle)
23257c478bd9Sstevel@tonic-gate {
23267c478bd9Sstevel@tonic-gate 	return (zonecfg_setent(handle));
23277c478bd9Sstevel@tonic-gate }
23287c478bd9Sstevel@tonic-gate 
23297c478bd9Sstevel@tonic-gate int
23307c478bd9Sstevel@tonic-gate zonecfg_getnwifent(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
23317c478bd9Sstevel@tonic-gate {
23327c478bd9Sstevel@tonic-gate 	xmlNodePtr cur;
23337c478bd9Sstevel@tonic-gate 	int err;
23347c478bd9Sstevel@tonic-gate 
23357c478bd9Sstevel@tonic-gate 	if (handle == NULL)
23367c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
23377c478bd9Sstevel@tonic-gate 
23387c478bd9Sstevel@tonic-gate 	if ((cur = handle->zone_dh_cur) == NULL)
23397c478bd9Sstevel@tonic-gate 		return (Z_NO_ENTRY);
23407c478bd9Sstevel@tonic-gate 
23417c478bd9Sstevel@tonic-gate 	for (; cur != NULL; cur = cur->next)
23427c478bd9Sstevel@tonic-gate 		if (!xmlStrcmp(cur->name, DTD_ELEM_NET))
23437c478bd9Sstevel@tonic-gate 			break;
23447c478bd9Sstevel@tonic-gate 	if (cur == NULL) {
23457c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = handle->zone_dh_top;
23467c478bd9Sstevel@tonic-gate 		return (Z_NO_ENTRY);
23477c478bd9Sstevel@tonic-gate 	}
23487c478bd9Sstevel@tonic-gate 
23497c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_ADDRESS, tabptr->zone_nwif_address,
23507c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_nwif_address))) != Z_OK) {
23517c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = handle->zone_dh_top;
23527c478bd9Sstevel@tonic-gate 		return (err);
23537c478bd9Sstevel@tonic-gate 	}
23547c478bd9Sstevel@tonic-gate 
23557c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_PHYSICAL, tabptr->zone_nwif_physical,
23567c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_nwif_physical))) != Z_OK) {
23577c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = handle->zone_dh_top;
23587c478bd9Sstevel@tonic-gate 		return (err);
23597c478bd9Sstevel@tonic-gate 	}
23607c478bd9Sstevel@tonic-gate 
23617c478bd9Sstevel@tonic-gate 	handle->zone_dh_cur = cur->next;
23627c478bd9Sstevel@tonic-gate 	return (Z_OK);
23637c478bd9Sstevel@tonic-gate }
23647c478bd9Sstevel@tonic-gate 
23657c478bd9Sstevel@tonic-gate int
23667c478bd9Sstevel@tonic-gate zonecfg_endnwifent(zone_dochandle_t handle)
23677c478bd9Sstevel@tonic-gate {
23687c478bd9Sstevel@tonic-gate 	return (zonecfg_endent(handle));
23697c478bd9Sstevel@tonic-gate }
23707c478bd9Sstevel@tonic-gate 
23717c478bd9Sstevel@tonic-gate int
23727c478bd9Sstevel@tonic-gate zonecfg_setdevent(zone_dochandle_t handle)
23737c478bd9Sstevel@tonic-gate {
23747c478bd9Sstevel@tonic-gate 	return (zonecfg_setent(handle));
23757c478bd9Sstevel@tonic-gate }
23767c478bd9Sstevel@tonic-gate 
23777c478bd9Sstevel@tonic-gate int
23787c478bd9Sstevel@tonic-gate zonecfg_getdevent(zone_dochandle_t handle, struct zone_devtab *tabptr)
23797c478bd9Sstevel@tonic-gate {
23807c478bd9Sstevel@tonic-gate 	xmlNodePtr cur;
23817c478bd9Sstevel@tonic-gate 	int err;
23827c478bd9Sstevel@tonic-gate 
23837c478bd9Sstevel@tonic-gate 	if (handle == NULL)
23847c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
23857c478bd9Sstevel@tonic-gate 
23867c478bd9Sstevel@tonic-gate 	if ((cur = handle->zone_dh_cur) == NULL)
23877c478bd9Sstevel@tonic-gate 		return (Z_NO_ENTRY);
23887c478bd9Sstevel@tonic-gate 
23897c478bd9Sstevel@tonic-gate 	for (; cur != NULL; cur = cur->next)
23907c478bd9Sstevel@tonic-gate 		if (!xmlStrcmp(cur->name, DTD_ELEM_DEVICE))
23917c478bd9Sstevel@tonic-gate 			break;
23927c478bd9Sstevel@tonic-gate 	if (cur == NULL) {
23937c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = handle->zone_dh_top;
23947c478bd9Sstevel@tonic-gate 		return (Z_NO_ENTRY);
23957c478bd9Sstevel@tonic-gate 	}
23967c478bd9Sstevel@tonic-gate 
23977c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_MATCH, tabptr->zone_dev_match,
23987c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_dev_match))) != Z_OK) {
23997c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = handle->zone_dh_top;
24007c478bd9Sstevel@tonic-gate 		return (err);
24017c478bd9Sstevel@tonic-gate 	}
24027c478bd9Sstevel@tonic-gate 
24037c478bd9Sstevel@tonic-gate 	handle->zone_dh_cur = cur->next;
24047c478bd9Sstevel@tonic-gate 	return (Z_OK);
24057c478bd9Sstevel@tonic-gate }
24067c478bd9Sstevel@tonic-gate 
24077c478bd9Sstevel@tonic-gate int
24087c478bd9Sstevel@tonic-gate zonecfg_enddevent(zone_dochandle_t handle)
24097c478bd9Sstevel@tonic-gate {
24107c478bd9Sstevel@tonic-gate 	return (zonecfg_endent(handle));
24117c478bd9Sstevel@tonic-gate }
24127c478bd9Sstevel@tonic-gate 
24137c478bd9Sstevel@tonic-gate int
24147c478bd9Sstevel@tonic-gate zonecfg_setrctlent(zone_dochandle_t handle)
24157c478bd9Sstevel@tonic-gate {
24167c478bd9Sstevel@tonic-gate 	return (zonecfg_setent(handle));
24177c478bd9Sstevel@tonic-gate }
24187c478bd9Sstevel@tonic-gate 
24197c478bd9Sstevel@tonic-gate int
24207c478bd9Sstevel@tonic-gate zonecfg_getrctlent(zone_dochandle_t handle, struct zone_rctltab *tabptr)
24217c478bd9Sstevel@tonic-gate {
24227c478bd9Sstevel@tonic-gate 	xmlNodePtr cur, val;
24237c478bd9Sstevel@tonic-gate 	struct zone_rctlvaltab *valptr;
24247c478bd9Sstevel@tonic-gate 	int err;
24257c478bd9Sstevel@tonic-gate 
24267c478bd9Sstevel@tonic-gate 	if (handle == NULL)
24277c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
24287c478bd9Sstevel@tonic-gate 
24297c478bd9Sstevel@tonic-gate 	if ((cur = handle->zone_dh_cur) == NULL)
24307c478bd9Sstevel@tonic-gate 		return (Z_NO_ENTRY);
24317c478bd9Sstevel@tonic-gate 
24327c478bd9Sstevel@tonic-gate 	for (; cur != NULL; cur = cur->next)
24337c478bd9Sstevel@tonic-gate 		if (!xmlStrcmp(cur->name, DTD_ELEM_RCTL))
24347c478bd9Sstevel@tonic-gate 			break;
24357c478bd9Sstevel@tonic-gate 	if (cur == NULL) {
24367c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = handle->zone_dh_top;
24377c478bd9Sstevel@tonic-gate 		return (Z_NO_ENTRY);
24387c478bd9Sstevel@tonic-gate 	}
24397c478bd9Sstevel@tonic-gate 
24407c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_NAME, tabptr->zone_rctl_name,
24417c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_rctl_name))) != Z_OK) {
24427c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = handle->zone_dh_top;
24437c478bd9Sstevel@tonic-gate 		return (err);
24447c478bd9Sstevel@tonic-gate 	}
24457c478bd9Sstevel@tonic-gate 
24467c478bd9Sstevel@tonic-gate 	tabptr->zone_rctl_valptr = NULL;
24477c478bd9Sstevel@tonic-gate 	for (val = cur->xmlChildrenNode; val != NULL; val = val->next) {
24487c478bd9Sstevel@tonic-gate 		valptr = (struct zone_rctlvaltab *)malloc(
24497c478bd9Sstevel@tonic-gate 		    sizeof (struct zone_rctlvaltab));
24507c478bd9Sstevel@tonic-gate 		if (valptr == NULL)
24517c478bd9Sstevel@tonic-gate 			return (Z_NOMEM);
24527c478bd9Sstevel@tonic-gate 		if (fetchprop(val, DTD_ATTR_PRIV, valptr->zone_rctlval_priv,
24537c478bd9Sstevel@tonic-gate 		    sizeof (valptr->zone_rctlval_priv)) != Z_OK)
24547c478bd9Sstevel@tonic-gate 			break;
24557c478bd9Sstevel@tonic-gate 		if (fetchprop(val, DTD_ATTR_LIMIT, valptr->zone_rctlval_limit,
24567c478bd9Sstevel@tonic-gate 		    sizeof (valptr->zone_rctlval_limit)) != Z_OK)
24577c478bd9Sstevel@tonic-gate 			break;
24587c478bd9Sstevel@tonic-gate 		if (fetchprop(val, DTD_ATTR_ACTION, valptr->zone_rctlval_action,
24597c478bd9Sstevel@tonic-gate 		    sizeof (valptr->zone_rctlval_action)) != Z_OK)
24607c478bd9Sstevel@tonic-gate 			break;
24617c478bd9Sstevel@tonic-gate 		if (zonecfg_add_rctl_value(tabptr, valptr) != Z_OK)
24627c478bd9Sstevel@tonic-gate 			break;
24637c478bd9Sstevel@tonic-gate 	}
24647c478bd9Sstevel@tonic-gate 
24657c478bd9Sstevel@tonic-gate 	handle->zone_dh_cur = cur->next;
24667c478bd9Sstevel@tonic-gate 	return (Z_OK);
24677c478bd9Sstevel@tonic-gate }
24687c478bd9Sstevel@tonic-gate 
24697c478bd9Sstevel@tonic-gate int
24707c478bd9Sstevel@tonic-gate zonecfg_endrctlent(zone_dochandle_t handle)
24717c478bd9Sstevel@tonic-gate {
24727c478bd9Sstevel@tonic-gate 	return (zonecfg_endent(handle));
24737c478bd9Sstevel@tonic-gate }
24747c478bd9Sstevel@tonic-gate 
24757c478bd9Sstevel@tonic-gate int
24767c478bd9Sstevel@tonic-gate zonecfg_setattrent(zone_dochandle_t handle)
24777c478bd9Sstevel@tonic-gate {
24787c478bd9Sstevel@tonic-gate 	return (zonecfg_setent(handle));
24797c478bd9Sstevel@tonic-gate }
24807c478bd9Sstevel@tonic-gate 
24817c478bd9Sstevel@tonic-gate int
24827c478bd9Sstevel@tonic-gate zonecfg_getattrent(zone_dochandle_t handle, struct zone_attrtab *tabptr)
24837c478bd9Sstevel@tonic-gate {
24847c478bd9Sstevel@tonic-gate 	xmlNodePtr cur;
24857c478bd9Sstevel@tonic-gate 	int err;
24867c478bd9Sstevel@tonic-gate 
24877c478bd9Sstevel@tonic-gate 	if (handle == NULL)
24887c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
24897c478bd9Sstevel@tonic-gate 
24907c478bd9Sstevel@tonic-gate 	if ((cur = handle->zone_dh_cur) == NULL)
24917c478bd9Sstevel@tonic-gate 		return (Z_NO_ENTRY);
24927c478bd9Sstevel@tonic-gate 
24937c478bd9Sstevel@tonic-gate 	for (; cur != NULL; cur = cur->next)
24947c478bd9Sstevel@tonic-gate 		if (!xmlStrcmp(cur->name, DTD_ELEM_ATTR))
24957c478bd9Sstevel@tonic-gate 			break;
24967c478bd9Sstevel@tonic-gate 	if (cur == NULL) {
24977c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = handle->zone_dh_top;
24987c478bd9Sstevel@tonic-gate 		return (Z_NO_ENTRY);
24997c478bd9Sstevel@tonic-gate 	}
25007c478bd9Sstevel@tonic-gate 
25017c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_NAME, tabptr->zone_attr_name,
25027c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_attr_name))) != Z_OK) {
25037c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = handle->zone_dh_top;
25047c478bd9Sstevel@tonic-gate 		return (err);
25057c478bd9Sstevel@tonic-gate 	}
25067c478bd9Sstevel@tonic-gate 
25077c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_TYPE, tabptr->zone_attr_type,
25087c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_attr_type))) != Z_OK) {
25097c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = handle->zone_dh_top;
25107c478bd9Sstevel@tonic-gate 		return (err);
25117c478bd9Sstevel@tonic-gate 	}
25127c478bd9Sstevel@tonic-gate 
25137c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_VALUE, tabptr->zone_attr_value,
25147c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_attr_value))) != Z_OK) {
25157c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = handle->zone_dh_top;
25167c478bd9Sstevel@tonic-gate 		return (err);
25177c478bd9Sstevel@tonic-gate 	}
25187c478bd9Sstevel@tonic-gate 
25197c478bd9Sstevel@tonic-gate 	handle->zone_dh_cur = cur->next;
25207c478bd9Sstevel@tonic-gate 	return (Z_OK);
25217c478bd9Sstevel@tonic-gate }
25227c478bd9Sstevel@tonic-gate 
25237c478bd9Sstevel@tonic-gate int
25247c478bd9Sstevel@tonic-gate zonecfg_endattrent(zone_dochandle_t handle)
25257c478bd9Sstevel@tonic-gate {
25267c478bd9Sstevel@tonic-gate 	return (zonecfg_endent(handle));
25277c478bd9Sstevel@tonic-gate }
25287c478bd9Sstevel@tonic-gate 
25297c478bd9Sstevel@tonic-gate /* This will ultimately be configurable. */
25307c478bd9Sstevel@tonic-gate static const char *priv_list[] = {
25317c478bd9Sstevel@tonic-gate 	PRIV_FILE_CHOWN,
25327c478bd9Sstevel@tonic-gate 	PRIV_FILE_CHOWN_SELF,
25337c478bd9Sstevel@tonic-gate 	PRIV_FILE_DAC_EXECUTE,
25347c478bd9Sstevel@tonic-gate 	PRIV_FILE_DAC_READ,
25357c478bd9Sstevel@tonic-gate 	PRIV_FILE_DAC_SEARCH,
25367c478bd9Sstevel@tonic-gate 	PRIV_FILE_DAC_WRITE,
25377c478bd9Sstevel@tonic-gate 	PRIV_FILE_OWNER,
25387c478bd9Sstevel@tonic-gate 	PRIV_FILE_SETID,
25397c478bd9Sstevel@tonic-gate 	PRIV_IPC_DAC_READ,
25407c478bd9Sstevel@tonic-gate 	PRIV_IPC_DAC_WRITE,
25417c478bd9Sstevel@tonic-gate 	PRIV_IPC_OWNER,
25427c478bd9Sstevel@tonic-gate 	PRIV_NET_ICMPACCESS,
25437c478bd9Sstevel@tonic-gate 	PRIV_NET_PRIVADDR,
25447c478bd9Sstevel@tonic-gate 	PRIV_PROC_CHROOT,
25457c478bd9Sstevel@tonic-gate 	PRIV_SYS_AUDIT,
25467c478bd9Sstevel@tonic-gate 	PRIV_PROC_AUDIT,
25477c478bd9Sstevel@tonic-gate 	PRIV_PROC_OWNER,
25487c478bd9Sstevel@tonic-gate 	PRIV_PROC_SETID,
25497c478bd9Sstevel@tonic-gate 	PRIV_PROC_TASKID,
25507c478bd9Sstevel@tonic-gate 	PRIV_SYS_ACCT,
25517c478bd9Sstevel@tonic-gate 	PRIV_SYS_ADMIN,
25527c478bd9Sstevel@tonic-gate 	PRIV_SYS_MOUNT,
25537c478bd9Sstevel@tonic-gate 	PRIV_SYS_NFS,
25547c478bd9Sstevel@tonic-gate 	PRIV_SYS_RESOURCE,
25557c478bd9Sstevel@tonic-gate 	PRIV_CONTRACT_EVENT,
25567c478bd9Sstevel@tonic-gate 	PRIV_CONTRACT_OBSERVER,
25577c478bd9Sstevel@tonic-gate 	NULL
25587c478bd9Sstevel@tonic-gate };
25597c478bd9Sstevel@tonic-gate 
25607c478bd9Sstevel@tonic-gate int
25617c478bd9Sstevel@tonic-gate zonecfg_get_privset(priv_set_t *privs)
25627c478bd9Sstevel@tonic-gate {
25637c478bd9Sstevel@tonic-gate 	const char **strp;
25647c478bd9Sstevel@tonic-gate 	priv_set_t *basic = priv_str_to_set("basic", ",", NULL);
25657c478bd9Sstevel@tonic-gate 
25667c478bd9Sstevel@tonic-gate 	if (basic == NULL)
25677c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
25687c478bd9Sstevel@tonic-gate 
25697c478bd9Sstevel@tonic-gate 	priv_union(basic, privs);
25707c478bd9Sstevel@tonic-gate 	priv_freeset(basic);
25717c478bd9Sstevel@tonic-gate 
25727c478bd9Sstevel@tonic-gate 	for (strp = priv_list; *strp != NULL; strp++) {
25737c478bd9Sstevel@tonic-gate 		if (priv_addset(privs, *strp) != 0) {
25747c478bd9Sstevel@tonic-gate 			return (Z_INVAL);
25757c478bd9Sstevel@tonic-gate 		}
25767c478bd9Sstevel@tonic-gate 	}
25777c478bd9Sstevel@tonic-gate 	return (Z_OK);
25787c478bd9Sstevel@tonic-gate }
25797c478bd9Sstevel@tonic-gate 
25807c478bd9Sstevel@tonic-gate int
25817c478bd9Sstevel@tonic-gate zonecfg_add_index(char *zone, char *path)
25827c478bd9Sstevel@tonic-gate {
25837c478bd9Sstevel@tonic-gate 	struct zoneent ze;
25847c478bd9Sstevel@tonic-gate 
25857c478bd9Sstevel@tonic-gate 	(void) strlcpy(ze.zone_name, zone, sizeof (ze.zone_name));
25867c478bd9Sstevel@tonic-gate 	ze.zone_state = ZONE_STATE_CONFIGURED;
25877c478bd9Sstevel@tonic-gate 	(void) strlcpy(ze.zone_path, path, sizeof (ze.zone_path));
25887c478bd9Sstevel@tonic-gate 	return (putzoneent(&ze, PZE_ADD));
25897c478bd9Sstevel@tonic-gate }
25907c478bd9Sstevel@tonic-gate 
25917c478bd9Sstevel@tonic-gate int
25927c478bd9Sstevel@tonic-gate zonecfg_delete_index(char *zone)
25937c478bd9Sstevel@tonic-gate {
25947c478bd9Sstevel@tonic-gate 	struct zoneent ze;
25957c478bd9Sstevel@tonic-gate 
25967c478bd9Sstevel@tonic-gate 	(void) strlcpy(ze.zone_name, zone, sizeof (ze.zone_name));
25977c478bd9Sstevel@tonic-gate 	return (putzoneent(&ze, PZE_REMOVE));
25987c478bd9Sstevel@tonic-gate }
25997c478bd9Sstevel@tonic-gate 
26007c478bd9Sstevel@tonic-gate int
26017c478bd9Sstevel@tonic-gate zone_get_zonepath(char *zone_name, char *zonepath, size_t rp_sz)
26027c478bd9Sstevel@tonic-gate {
26037c478bd9Sstevel@tonic-gate 	zone_dochandle_t handle;
26047c478bd9Sstevel@tonic-gate 	boolean_t found = B_FALSE;
26057c478bd9Sstevel@tonic-gate 	struct zoneent *ze;
26067c478bd9Sstevel@tonic-gate 	FILE *cookie;
26077c478bd9Sstevel@tonic-gate 	int err;
26087c478bd9Sstevel@tonic-gate 
26097c478bd9Sstevel@tonic-gate 	if (zone_name == NULL)
26107c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
26117c478bd9Sstevel@tonic-gate 
26127c478bd9Sstevel@tonic-gate 	if (strcmp(zone_name, GLOBAL_ZONENAME) == 0) {
26137c478bd9Sstevel@tonic-gate 		(void) strlcpy(zonepath, "/", rp_sz);
26147c478bd9Sstevel@tonic-gate 		return (Z_OK);
26157c478bd9Sstevel@tonic-gate 	}
26167c478bd9Sstevel@tonic-gate 
26177c478bd9Sstevel@tonic-gate 	/*
26187c478bd9Sstevel@tonic-gate 	 * First check the index file.  Because older versions did not have
26197c478bd9Sstevel@tonic-gate 	 * a copy of the zone path, allow for it to be zero length, in which
26207c478bd9Sstevel@tonic-gate 	 * case we ignore this result and fall back to the XML files.
26217c478bd9Sstevel@tonic-gate 	 */
26227c478bd9Sstevel@tonic-gate 	(void) strlcpy(zonepath, "", rp_sz);
26237c478bd9Sstevel@tonic-gate 	cookie = setzoneent();
26247c478bd9Sstevel@tonic-gate 	while ((ze = getzoneent_private(cookie)) != NULL) {
26257c478bd9Sstevel@tonic-gate 		if (strcmp(ze->zone_name, zone_name) == 0) {
26267c478bd9Sstevel@tonic-gate 			found = B_TRUE;
26277c478bd9Sstevel@tonic-gate 			if (strlen(ze->zone_path) > 0)
26287c478bd9Sstevel@tonic-gate 				(void) strlcpy(zonepath, ze->zone_path, rp_sz);
26297c478bd9Sstevel@tonic-gate 		}
26307c478bd9Sstevel@tonic-gate 		free(ze);
26317c478bd9Sstevel@tonic-gate 		if (found)
26327c478bd9Sstevel@tonic-gate 			break;
26337c478bd9Sstevel@tonic-gate 	}
26347c478bd9Sstevel@tonic-gate 	endzoneent(cookie);
26357c478bd9Sstevel@tonic-gate 	if (found && strlen(zonepath) > 0)
26367c478bd9Sstevel@tonic-gate 		return (Z_OK);
26377c478bd9Sstevel@tonic-gate 
26387c478bd9Sstevel@tonic-gate 	/* Fall back to the XML files. */
26397c478bd9Sstevel@tonic-gate 	if ((handle = zonecfg_init_handle()) == NULL)
26407c478bd9Sstevel@tonic-gate 		return (Z_NOMEM);
26417c478bd9Sstevel@tonic-gate 
26427c478bd9Sstevel@tonic-gate 	/*
26437c478bd9Sstevel@tonic-gate 	 * Check the snapshot first: if a zone is running, its zonepath
26447c478bd9Sstevel@tonic-gate 	 * may have changed.
26457c478bd9Sstevel@tonic-gate 	 */
26467c478bd9Sstevel@tonic-gate 	if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) {
26477c478bd9Sstevel@tonic-gate 		if ((err = zonecfg_get_handle(zone_name, handle)) != Z_OK)
26487c478bd9Sstevel@tonic-gate 			return (err);
26497c478bd9Sstevel@tonic-gate 	}
26507c478bd9Sstevel@tonic-gate 	err = zonecfg_get_zonepath(handle, zonepath, rp_sz);
26517c478bd9Sstevel@tonic-gate 	zonecfg_fini_handle(handle);
26527c478bd9Sstevel@tonic-gate 	return (err);
26537c478bd9Sstevel@tonic-gate }
26547c478bd9Sstevel@tonic-gate 
26557c478bd9Sstevel@tonic-gate int
26567c478bd9Sstevel@tonic-gate zone_get_rootpath(char *zone_name, char *rootpath, size_t rp_sz)
26577c478bd9Sstevel@tonic-gate {
26587c478bd9Sstevel@tonic-gate 	int err;
26597c478bd9Sstevel@tonic-gate 
26607c478bd9Sstevel@tonic-gate 	/* This function makes sense for non-global zones only. */
26617c478bd9Sstevel@tonic-gate 	if (strcmp(zone_name, GLOBAL_ZONENAME) == 0)
26627c478bd9Sstevel@tonic-gate 		return (Z_BOGUS_ZONE_NAME);
26637c478bd9Sstevel@tonic-gate 	if ((err = zone_get_zonepath(zone_name, rootpath, rp_sz)) != Z_OK)
26647c478bd9Sstevel@tonic-gate 		return (err);
26657c478bd9Sstevel@tonic-gate 	if (strlcat(rootpath, "/root", rp_sz) >= rp_sz)
26667c478bd9Sstevel@tonic-gate 		return (Z_TOO_BIG);
26677c478bd9Sstevel@tonic-gate 	return (Z_OK);
26687c478bd9Sstevel@tonic-gate }
26697c478bd9Sstevel@tonic-gate 
26707c478bd9Sstevel@tonic-gate static zone_state_t
26717c478bd9Sstevel@tonic-gate kernel_state_to_user_state(zone_status_t kernel_state)
26727c478bd9Sstevel@tonic-gate {
26737c478bd9Sstevel@tonic-gate 	assert(kernel_state <= ZONE_MAX_STATE);
26747c478bd9Sstevel@tonic-gate 	switch (kernel_state) {
26757c478bd9Sstevel@tonic-gate 		case ZONE_IS_UNINITIALIZED:
26767c478bd9Sstevel@tonic-gate 		case ZONE_IS_READY:
26777c478bd9Sstevel@tonic-gate 			return (ZONE_STATE_READY);
26787c478bd9Sstevel@tonic-gate 		case ZONE_IS_BOOTING:
26797c478bd9Sstevel@tonic-gate 		case ZONE_IS_RUNNING:
26807c478bd9Sstevel@tonic-gate 			return (ZONE_STATE_RUNNING);
26817c478bd9Sstevel@tonic-gate 		case ZONE_IS_SHUTTING_DOWN:
26827c478bd9Sstevel@tonic-gate 		case ZONE_IS_EMPTY:
26837c478bd9Sstevel@tonic-gate 			return (ZONE_STATE_SHUTTING_DOWN);
26847c478bd9Sstevel@tonic-gate 		case ZONE_IS_DOWN:
26857c478bd9Sstevel@tonic-gate 		case ZONE_IS_DYING:
26867c478bd9Sstevel@tonic-gate 		case ZONE_IS_DEAD:
26877c478bd9Sstevel@tonic-gate 		default:
26887c478bd9Sstevel@tonic-gate 			return (ZONE_STATE_DOWN);
26897c478bd9Sstevel@tonic-gate 	}
26907c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
26917c478bd9Sstevel@tonic-gate }
26927c478bd9Sstevel@tonic-gate 
26937c478bd9Sstevel@tonic-gate int
26947c478bd9Sstevel@tonic-gate zone_get_state(char *zone_name, zone_state_t *state_num)
26957c478bd9Sstevel@tonic-gate {
26967c478bd9Sstevel@tonic-gate 	zone_status_t status;
26977c478bd9Sstevel@tonic-gate 	zoneid_t zone_id;
26987c478bd9Sstevel@tonic-gate 	struct zoneent *ze;
26997c478bd9Sstevel@tonic-gate 	boolean_t found = B_FALSE;
27007c478bd9Sstevel@tonic-gate 	FILE *cookie;
27017c478bd9Sstevel@tonic-gate 
27027c478bd9Sstevel@tonic-gate 	if (zone_name == NULL)
27037c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
27047c478bd9Sstevel@tonic-gate 
27057c478bd9Sstevel@tonic-gate 	/* check to see if zone is running */
27067c478bd9Sstevel@tonic-gate 	if ((zone_id = getzoneidbyname(zone_name)) != -1 &&
27077c478bd9Sstevel@tonic-gate 	    zone_getattr(zone_id, ZONE_ATTR_STATUS, &status,
27087c478bd9Sstevel@tonic-gate 	    sizeof (status)) >= 0) {
27097c478bd9Sstevel@tonic-gate 		*state_num = kernel_state_to_user_state(status);
27107c478bd9Sstevel@tonic-gate 		return (Z_OK);
27117c478bd9Sstevel@tonic-gate 	}
27127c478bd9Sstevel@tonic-gate 
27137c478bd9Sstevel@tonic-gate 	cookie = setzoneent();
27147c478bd9Sstevel@tonic-gate 	while ((ze = getzoneent_private(cookie)) != NULL) {
27157c478bd9Sstevel@tonic-gate 		if (strcmp(ze->zone_name, zone_name) == 0) {
27167c478bd9Sstevel@tonic-gate 			found = B_TRUE;
27177c478bd9Sstevel@tonic-gate 			*state_num = ze->zone_state;
27187c478bd9Sstevel@tonic-gate 		}
27197c478bd9Sstevel@tonic-gate 		free(ze);
27207c478bd9Sstevel@tonic-gate 		if (found)
27217c478bd9Sstevel@tonic-gate 			break;
27227c478bd9Sstevel@tonic-gate 	}
27237c478bd9Sstevel@tonic-gate 	endzoneent(cookie);
27247c478bd9Sstevel@tonic-gate 	return ((found) ? Z_OK : Z_NO_ZONE);
27257c478bd9Sstevel@tonic-gate }
27267c478bd9Sstevel@tonic-gate 
27277c478bd9Sstevel@tonic-gate int
27287c478bd9Sstevel@tonic-gate zone_set_state(char *zone, zone_state_t state)
27297c478bd9Sstevel@tonic-gate {
27307c478bd9Sstevel@tonic-gate 	struct zoneent ze;
27317c478bd9Sstevel@tonic-gate 
27327c478bd9Sstevel@tonic-gate 	if (state != ZONE_STATE_CONFIGURED && state != ZONE_STATE_INSTALLED &&
27337c478bd9Sstevel@tonic-gate 	    state != ZONE_STATE_INCOMPLETE)
27347c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
27357c478bd9Sstevel@tonic-gate 
27367c478bd9Sstevel@tonic-gate 	(void) strlcpy(ze.zone_name, zone, sizeof (ze.zone_name));
27377c478bd9Sstevel@tonic-gate 	ze.zone_state = state;
27387c478bd9Sstevel@tonic-gate 	(void) strlcpy(ze.zone_path, "", sizeof (ze.zone_path));
27397c478bd9Sstevel@tonic-gate 	return (putzoneent(&ze, PZE_MODIFY));
27407c478bd9Sstevel@tonic-gate }
27417c478bd9Sstevel@tonic-gate 
27427c478bd9Sstevel@tonic-gate /*
27437c478bd9Sstevel@tonic-gate  * Get id (if any) for specified zone.  There are four possible outcomes:
27447c478bd9Sstevel@tonic-gate  * - If the string corresponds to the numeric id of an active (booted)
27457c478bd9Sstevel@tonic-gate  *   zone, sets *zip to the zone id and returns 0.
27467c478bd9Sstevel@tonic-gate  * - If the string corresponds to the name of an active (booted) zone,
27477c478bd9Sstevel@tonic-gate  *   sets *zip to the zone id and returns 0.
27487c478bd9Sstevel@tonic-gate  * - If the string is a name in the configuration but is not booted,
27497c478bd9Sstevel@tonic-gate  *   sets *zip to ZONE_ID_UNDEFINED and returns 0.
27507c478bd9Sstevel@tonic-gate  * - Otherwise, leaves *zip unchanged and returns -1.
27517c478bd9Sstevel@tonic-gate  *
27527c478bd9Sstevel@tonic-gate  * This function acts as an auxiliary filter on the function of the same
27537c478bd9Sstevel@tonic-gate  * name in libc; the linker binds to this version if libzonecfg exists,
27547c478bd9Sstevel@tonic-gate  * and the libc version if it doesn't.  Any changes to this version of
27557c478bd9Sstevel@tonic-gate  * the function should probably be reflected in the libc version as well.
27567c478bd9Sstevel@tonic-gate  */
27577c478bd9Sstevel@tonic-gate int
27587c478bd9Sstevel@tonic-gate zone_get_id(const char *str, zoneid_t *zip)
27597c478bd9Sstevel@tonic-gate {
27607c478bd9Sstevel@tonic-gate 	zone_dochandle_t hdl;
27617c478bd9Sstevel@tonic-gate 	zoneid_t zoneid;
27627c478bd9Sstevel@tonic-gate 	char *cp;
27637c478bd9Sstevel@tonic-gate 	int err;
27647c478bd9Sstevel@tonic-gate 
27657c478bd9Sstevel@tonic-gate 	/* first try looking for active zone by id */
27667c478bd9Sstevel@tonic-gate 	errno = 0;
27677c478bd9Sstevel@tonic-gate 	zoneid = (zoneid_t)strtol(str, &cp, 0);
27687c478bd9Sstevel@tonic-gate 	if (errno == 0 && cp != str && *cp == '\0' &&
27697c478bd9Sstevel@tonic-gate 	    getzonenamebyid(zoneid, NULL, 0) != -1) {
27707c478bd9Sstevel@tonic-gate 		*zip = zoneid;
27717c478bd9Sstevel@tonic-gate 		return (0);
27727c478bd9Sstevel@tonic-gate 	}
27737c478bd9Sstevel@tonic-gate 
27747c478bd9Sstevel@tonic-gate 	/* then look for active zone by name */
27757c478bd9Sstevel@tonic-gate 	if ((zoneid = getzoneidbyname(str)) != -1) {
27767c478bd9Sstevel@tonic-gate 		*zip = zoneid;
27777c478bd9Sstevel@tonic-gate 		return (0);
27787c478bd9Sstevel@tonic-gate 	}
27797c478bd9Sstevel@tonic-gate 
27807c478bd9Sstevel@tonic-gate 	/* if in global zone, try looking up name in configuration database */
27817c478bd9Sstevel@tonic-gate 	if (getzoneid() != GLOBAL_ZONEID ||
27827c478bd9Sstevel@tonic-gate 	    (hdl = zonecfg_init_handle()) == NULL)
27837c478bd9Sstevel@tonic-gate 		return (-1);
27847c478bd9Sstevel@tonic-gate 
27857c478bd9Sstevel@tonic-gate 	if (zonecfg_get_handle((char *)str, hdl) == Z_OK) {
27867c478bd9Sstevel@tonic-gate 		/* zone exists but isn't active */
27877c478bd9Sstevel@tonic-gate 		*zip = ZONE_ID_UNDEFINED;
27887c478bd9Sstevel@tonic-gate 		err = 0;
27897c478bd9Sstevel@tonic-gate 	} else {
27907c478bd9Sstevel@tonic-gate 		err = -1;
27917c478bd9Sstevel@tonic-gate 	}
27927c478bd9Sstevel@tonic-gate 
27937c478bd9Sstevel@tonic-gate 	zonecfg_fini_handle(hdl);
27947c478bd9Sstevel@tonic-gate 	return (err);
27957c478bd9Sstevel@tonic-gate }
27967c478bd9Sstevel@tonic-gate 
27977c478bd9Sstevel@tonic-gate char *
27987c478bd9Sstevel@tonic-gate zone_state_str(zone_state_t state_num)
27997c478bd9Sstevel@tonic-gate {
28007c478bd9Sstevel@tonic-gate 	switch (state_num) {
28017c478bd9Sstevel@tonic-gate 	case ZONE_STATE_CONFIGURED:
28027c478bd9Sstevel@tonic-gate 		return (ZONE_STATE_STR_CONFIGURED);
28037c478bd9Sstevel@tonic-gate 	case ZONE_STATE_INCOMPLETE:
28047c478bd9Sstevel@tonic-gate 		return (ZONE_STATE_STR_INCOMPLETE);
28057c478bd9Sstevel@tonic-gate 	case ZONE_STATE_INSTALLED:
28067c478bd9Sstevel@tonic-gate 		return (ZONE_STATE_STR_INSTALLED);
28077c478bd9Sstevel@tonic-gate 	case ZONE_STATE_READY:
28087c478bd9Sstevel@tonic-gate 		return (ZONE_STATE_STR_READY);
28097c478bd9Sstevel@tonic-gate 	case ZONE_STATE_RUNNING:
28107c478bd9Sstevel@tonic-gate 		return (ZONE_STATE_STR_RUNNING);
28117c478bd9Sstevel@tonic-gate 	case ZONE_STATE_SHUTTING_DOWN:
28127c478bd9Sstevel@tonic-gate 		return (ZONE_STATE_STR_SHUTTING_DOWN);
28137c478bd9Sstevel@tonic-gate 	case ZONE_STATE_DOWN:
28147c478bd9Sstevel@tonic-gate 		return (ZONE_STATE_STR_DOWN);
28157c478bd9Sstevel@tonic-gate 	default:
28167c478bd9Sstevel@tonic-gate 		return ("unknown");
28177c478bd9Sstevel@tonic-gate 	}
28187c478bd9Sstevel@tonic-gate }
28197c478bd9Sstevel@tonic-gate 
28207c478bd9Sstevel@tonic-gate /*
28217c478bd9Sstevel@tonic-gate  * File-system convenience functions.
28227c478bd9Sstevel@tonic-gate  */
28237c478bd9Sstevel@tonic-gate boolean_t
28247c478bd9Sstevel@tonic-gate zonecfg_valid_fs_type(const char *type)
28257c478bd9Sstevel@tonic-gate {
28267c478bd9Sstevel@tonic-gate 	/*
28277c478bd9Sstevel@tonic-gate 	 * We already know which FS types don't work.
28287c478bd9Sstevel@tonic-gate 	 */
28297c478bd9Sstevel@tonic-gate 	if (strcmp(type, "proc") == 0 ||
28307c478bd9Sstevel@tonic-gate 	    strcmp(type, "mntfs") == 0 ||
28317c478bd9Sstevel@tonic-gate 	    strcmp(type, "autofs") == 0 ||
28327c478bd9Sstevel@tonic-gate 	    strncmp(type, "nfs", sizeof ("nfs") - 1) == 0 ||
28337c478bd9Sstevel@tonic-gate 	    strcmp(type, "cachefs") == 0)
28347c478bd9Sstevel@tonic-gate 		return (B_FALSE);
28357c478bd9Sstevel@tonic-gate 	/*
28367c478bd9Sstevel@tonic-gate 	 * The caller may do more detailed verification to make sure other
28377c478bd9Sstevel@tonic-gate 	 * aspects of this filesystem type make sense.
28387c478bd9Sstevel@tonic-gate 	 */
28397c478bd9Sstevel@tonic-gate 	return (B_TRUE);
28407c478bd9Sstevel@tonic-gate }
28417c478bd9Sstevel@tonic-gate 
28427c478bd9Sstevel@tonic-gate /*
28437c478bd9Sstevel@tonic-gate  * Generally uninteresting rctl convenience functions.
28447c478bd9Sstevel@tonic-gate  */
28457c478bd9Sstevel@tonic-gate 
28467c478bd9Sstevel@tonic-gate int
28477c478bd9Sstevel@tonic-gate zonecfg_construct_rctlblk(const struct zone_rctlvaltab *rctlval,
28487c478bd9Sstevel@tonic-gate     rctlblk_t *rctlblk)
28497c478bd9Sstevel@tonic-gate {
28507c478bd9Sstevel@tonic-gate 	unsigned long long ull;
28517c478bd9Sstevel@tonic-gate 	char *endp;
28527c478bd9Sstevel@tonic-gate 	rctl_priv_t priv;
28537c478bd9Sstevel@tonic-gate 	rctl_qty_t limit;
28547c478bd9Sstevel@tonic-gate 	uint_t action;
28557c478bd9Sstevel@tonic-gate 
28567c478bd9Sstevel@tonic-gate 	/* Get the privilege */
28577c478bd9Sstevel@tonic-gate 	if (strcmp(rctlval->zone_rctlval_priv, "basic") == 0) {
28587c478bd9Sstevel@tonic-gate 		priv = RCPRIV_BASIC;
28597c478bd9Sstevel@tonic-gate 	} else if (strcmp(rctlval->zone_rctlval_priv, "privileged") == 0) {
28607c478bd9Sstevel@tonic-gate 		priv = RCPRIV_PRIVILEGED;
28617c478bd9Sstevel@tonic-gate 	} else {
28627c478bd9Sstevel@tonic-gate 		/* Invalid privilege */
28637c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
28647c478bd9Sstevel@tonic-gate 	}
28657c478bd9Sstevel@tonic-gate 
28667c478bd9Sstevel@tonic-gate 	/* deal with negative input; strtoull(3c) doesn't do what we want */
28677c478bd9Sstevel@tonic-gate 	if (rctlval->zone_rctlval_limit[0] == '-')
28687c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
28697c478bd9Sstevel@tonic-gate 	/* Get the limit */
28707c478bd9Sstevel@tonic-gate 	errno = 0;
28717c478bd9Sstevel@tonic-gate 	ull = strtoull(rctlval->zone_rctlval_limit, &endp, 0);
28727c478bd9Sstevel@tonic-gate 	if (errno != 0 || *endp != '\0') {
28737c478bd9Sstevel@tonic-gate 		/* parse failed */
28747c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
28757c478bd9Sstevel@tonic-gate 	}
28767c478bd9Sstevel@tonic-gate 	limit = (rctl_qty_t)ull;
28777c478bd9Sstevel@tonic-gate 
28787c478bd9Sstevel@tonic-gate 	/* Get the action */
28797c478bd9Sstevel@tonic-gate 	if (strcmp(rctlval->zone_rctlval_action, "none") == 0) {
28807c478bd9Sstevel@tonic-gate 		action = RCTL_LOCAL_NOACTION;
28817c478bd9Sstevel@tonic-gate 	} else if (strcmp(rctlval->zone_rctlval_action, "signal") == 0) {
28827c478bd9Sstevel@tonic-gate 		action = RCTL_LOCAL_SIGNAL;
28837c478bd9Sstevel@tonic-gate 	} else if (strcmp(rctlval->zone_rctlval_action, "deny") == 0) {
28847c478bd9Sstevel@tonic-gate 		action = RCTL_LOCAL_DENY;
28857c478bd9Sstevel@tonic-gate 	} else {
28867c478bd9Sstevel@tonic-gate 		/* Invalid Action */
28877c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
28887c478bd9Sstevel@tonic-gate 	}
28897c478bd9Sstevel@tonic-gate 	rctlblk_set_local_action(rctlblk, action, 0);
28907c478bd9Sstevel@tonic-gate 	rctlblk_set_privilege(rctlblk, priv);
28917c478bd9Sstevel@tonic-gate 	rctlblk_set_value(rctlblk, limit);
28927c478bd9Sstevel@tonic-gate 	return (Z_OK);
28937c478bd9Sstevel@tonic-gate }
28947c478bd9Sstevel@tonic-gate 
28957c478bd9Sstevel@tonic-gate static int
28967c478bd9Sstevel@tonic-gate rctl_check(const char *rctlname, void *arg)
28977c478bd9Sstevel@tonic-gate {
28987c478bd9Sstevel@tonic-gate 	const char *attrname = arg;
28997c478bd9Sstevel@tonic-gate 
29007c478bd9Sstevel@tonic-gate 	/*
29017c478bd9Sstevel@tonic-gate 	 * Returning 1 here is our signal to zonecfg_is_rctl() that it is
29027c478bd9Sstevel@tonic-gate 	 * indeed an rctl name recognized by the system.
29037c478bd9Sstevel@tonic-gate 	 */
29047c478bd9Sstevel@tonic-gate 	return (strcmp(rctlname, attrname) == 0 ? 1 : 0);
29057c478bd9Sstevel@tonic-gate }
29067c478bd9Sstevel@tonic-gate 
29077c478bd9Sstevel@tonic-gate boolean_t
29087c478bd9Sstevel@tonic-gate zonecfg_is_rctl(const char *name)
29097c478bd9Sstevel@tonic-gate {
29107c478bd9Sstevel@tonic-gate 	return (rctl_walk(rctl_check, (void *)name) == 1);
29117c478bd9Sstevel@tonic-gate }
29127c478bd9Sstevel@tonic-gate 
29137c478bd9Sstevel@tonic-gate boolean_t
29147c478bd9Sstevel@tonic-gate zonecfg_valid_rctlname(const char *name)
29157c478bd9Sstevel@tonic-gate {
29167c478bd9Sstevel@tonic-gate 	const char *c;
29177c478bd9Sstevel@tonic-gate 
29187c478bd9Sstevel@tonic-gate 	if (strncmp(name, "zone.", sizeof ("zone.") - 1) != 0)
29197c478bd9Sstevel@tonic-gate 		return (B_FALSE);
29207c478bd9Sstevel@tonic-gate 	if (strlen(name) == sizeof ("zone.") - 1)
29217c478bd9Sstevel@tonic-gate 		return (B_FALSE);
29227c478bd9Sstevel@tonic-gate 	for (c = name + sizeof ("zone.") - 1; *c != '\0'; c++) {
29237c478bd9Sstevel@tonic-gate 		if (!isalpha(*c) && *c != '-')
29247c478bd9Sstevel@tonic-gate 			return (B_FALSE);
29257c478bd9Sstevel@tonic-gate 	}
29267c478bd9Sstevel@tonic-gate 	return (B_TRUE);
29277c478bd9Sstevel@tonic-gate }
29287c478bd9Sstevel@tonic-gate 
29297c478bd9Sstevel@tonic-gate boolean_t
29307c478bd9Sstevel@tonic-gate zonecfg_valid_rctlblk(const rctlblk_t *rctlblk)
29317c478bd9Sstevel@tonic-gate {
29327c478bd9Sstevel@tonic-gate 	rctl_priv_t priv = rctlblk_get_privilege((rctlblk_t *)rctlblk);
29337c478bd9Sstevel@tonic-gate 	uint_t action = rctlblk_get_local_action((rctlblk_t *)rctlblk, NULL);
29347c478bd9Sstevel@tonic-gate 
29357c478bd9Sstevel@tonic-gate 	if (priv != RCPRIV_PRIVILEGED)
29367c478bd9Sstevel@tonic-gate 		return (B_FALSE);
29377c478bd9Sstevel@tonic-gate 	if (action != RCTL_LOCAL_NOACTION && action != RCTL_LOCAL_DENY)
29387c478bd9Sstevel@tonic-gate 		return (B_FALSE);
29397c478bd9Sstevel@tonic-gate 	return (B_TRUE);
29407c478bd9Sstevel@tonic-gate }
29417c478bd9Sstevel@tonic-gate 
29427c478bd9Sstevel@tonic-gate boolean_t
29437c478bd9Sstevel@tonic-gate zonecfg_valid_rctl(const char *name, const rctlblk_t *rctlblk)
29447c478bd9Sstevel@tonic-gate {
29457c478bd9Sstevel@tonic-gate 	rctlblk_t *current, *next;
29467c478bd9Sstevel@tonic-gate 	rctl_qty_t limit = rctlblk_get_value((rctlblk_t *)rctlblk);
29477c478bd9Sstevel@tonic-gate 	uint_t action = rctlblk_get_local_action((rctlblk_t *)rctlblk, NULL);
29487c478bd9Sstevel@tonic-gate 	uint_t global_flags;
29497c478bd9Sstevel@tonic-gate 
29507c478bd9Sstevel@tonic-gate 	if (!zonecfg_valid_rctlblk(rctlblk))
29517c478bd9Sstevel@tonic-gate 		return (B_FALSE);
29527c478bd9Sstevel@tonic-gate 	if (!zonecfg_valid_rctlname(name))
29537c478bd9Sstevel@tonic-gate 		return (B_FALSE);
29547c478bd9Sstevel@tonic-gate 
29557c478bd9Sstevel@tonic-gate 	current = alloca(rctlblk_size());
29567c478bd9Sstevel@tonic-gate 	if (getrctl(name, NULL, current, RCTL_FIRST) != 0)
29577c478bd9Sstevel@tonic-gate 		return (B_TRUE);	/* not an rctl on this system */
29587c478bd9Sstevel@tonic-gate 	/*
29597c478bd9Sstevel@tonic-gate 	 * Make sure the proposed value isn't greater than the current system
29607c478bd9Sstevel@tonic-gate 	 * value.
29617c478bd9Sstevel@tonic-gate 	 */
29627c478bd9Sstevel@tonic-gate 	next = alloca(rctlblk_size());
29637c478bd9Sstevel@tonic-gate 	while (rctlblk_get_privilege(current) != RCPRIV_SYSTEM) {
29647c478bd9Sstevel@tonic-gate 		rctlblk_t *tmp;
29657c478bd9Sstevel@tonic-gate 
29667c478bd9Sstevel@tonic-gate 		if (getrctl(name, current, next, RCTL_NEXT) != 0)
29677c478bd9Sstevel@tonic-gate 			return (B_FALSE);	/* shouldn't happen */
29687c478bd9Sstevel@tonic-gate 		tmp = current;
29697c478bd9Sstevel@tonic-gate 		current = next;
29707c478bd9Sstevel@tonic-gate 		next = tmp;
29717c478bd9Sstevel@tonic-gate 	}
29727c478bd9Sstevel@tonic-gate 	if (limit > rctlblk_get_value(current))
29737c478bd9Sstevel@tonic-gate 		return (B_FALSE);
29747c478bd9Sstevel@tonic-gate 
29757c478bd9Sstevel@tonic-gate 	/*
29767c478bd9Sstevel@tonic-gate 	 * Make sure the proposed action is allowed.
29777c478bd9Sstevel@tonic-gate 	 */
29787c478bd9Sstevel@tonic-gate 	global_flags = rctlblk_get_global_flags(current);
29797c478bd9Sstevel@tonic-gate 	if ((global_flags & RCTL_GLOBAL_DENY_NEVER) &&
29807c478bd9Sstevel@tonic-gate 	    action == RCTL_LOCAL_DENY)
29817c478bd9Sstevel@tonic-gate 		return (B_FALSE);
29827c478bd9Sstevel@tonic-gate 	if ((global_flags & RCTL_GLOBAL_DENY_ALWAYS) &&
29837c478bd9Sstevel@tonic-gate 	    action == RCTL_LOCAL_NOACTION)
29847c478bd9Sstevel@tonic-gate 		return (B_FALSE);
29857c478bd9Sstevel@tonic-gate 
29867c478bd9Sstevel@tonic-gate 	return (B_TRUE);
29877c478bd9Sstevel@tonic-gate }
2988