xref: /titanic_44/usr/src/lib/libzonecfg/common/libzonecfg.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <errno.h>
30*7c478bd9Sstevel@tonic-gate #include <fnmatch.h>
31*7c478bd9Sstevel@tonic-gate #include <strings.h>
32*7c478bd9Sstevel@tonic-gate #include <unistd.h>
33*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
34*7c478bd9Sstevel@tonic-gate #include <assert.h>
35*7c478bd9Sstevel@tonic-gate #include <libgen.h>
36*7c478bd9Sstevel@tonic-gate #include <libintl.h>
37*7c478bd9Sstevel@tonic-gate #include <alloca.h>
38*7c478bd9Sstevel@tonic-gate #include <ctype.h>
39*7c478bd9Sstevel@tonic-gate #include <sys/mntio.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/mnttab.h>
41*7c478bd9Sstevel@tonic-gate 
42*7c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
43*7c478bd9Sstevel@tonic-gate #include <netdb.h>
44*7c478bd9Sstevel@tonic-gate 
45*7c478bd9Sstevel@tonic-gate #include <priv.h>
46*7c478bd9Sstevel@tonic-gate 
47*7c478bd9Sstevel@tonic-gate #include <libxml/xmlmemory.h>
48*7c478bd9Sstevel@tonic-gate #include <libxml/parser.h>
49*7c478bd9Sstevel@tonic-gate 
50*7c478bd9Sstevel@tonic-gate #include <libdevinfo.h>
51*7c478bd9Sstevel@tonic-gate 
52*7c478bd9Sstevel@tonic-gate #include <libzonecfg.h>
53*7c478bd9Sstevel@tonic-gate #include "zonecfg_impl.h"
54*7c478bd9Sstevel@tonic-gate 
55*7c478bd9Sstevel@tonic-gate #define	_PATH_TMPFILE	"/zonecfg.XXXXXX"
56*7c478bd9Sstevel@tonic-gate 
57*7c478bd9Sstevel@tonic-gate /* Hard-code the DTD element/attribute/entity names just once, here. */
58*7c478bd9Sstevel@tonic-gate #define	DTD_ELEM_ATTR		(const xmlChar *) "attr"
59*7c478bd9Sstevel@tonic-gate #define	DTD_ELEM_COMMENT	(const xmlChar *) "comment"
60*7c478bd9Sstevel@tonic-gate #define	DTD_ELEM_DEVICE		(const xmlChar *) "device"
61*7c478bd9Sstevel@tonic-gate #define	DTD_ELEM_FS		(const xmlChar *) "filesystem"
62*7c478bd9Sstevel@tonic-gate #define	DTD_ELEM_FSOPTION	(const xmlChar *) "fsoption"
63*7c478bd9Sstevel@tonic-gate #define	DTD_ELEM_IPD		(const xmlChar *) "inherited-pkg-dir"
64*7c478bd9Sstevel@tonic-gate #define	DTD_ELEM_NET		(const xmlChar *) "network"
65*7c478bd9Sstevel@tonic-gate #define	DTD_ELEM_RCTL		(const xmlChar *) "rctl"
66*7c478bd9Sstevel@tonic-gate #define	DTD_ELEM_RCTLVALUE	(const xmlChar *) "rctl-value"
67*7c478bd9Sstevel@tonic-gate #define	DTD_ELEM_ZONE		(const xmlChar *) "zone"
68*7c478bd9Sstevel@tonic-gate 
69*7c478bd9Sstevel@tonic-gate #define	DTD_ATTR_ACTION		(const xmlChar *) "action"
70*7c478bd9Sstevel@tonic-gate #define	DTD_ATTR_ADDRESS	(const xmlChar *) "address"
71*7c478bd9Sstevel@tonic-gate #define	DTD_ATTR_AUTOBOOT	(const xmlChar *) "autoboot"
72*7c478bd9Sstevel@tonic-gate #define	DTD_ATTR_DIR		(const xmlChar *) "directory"
73*7c478bd9Sstevel@tonic-gate #define	DTD_ATTR_LIMIT		(const xmlChar *) "limit"
74*7c478bd9Sstevel@tonic-gate #define	DTD_ATTR_MATCH		(const xmlChar *) "match"
75*7c478bd9Sstevel@tonic-gate #define	DTD_ATTR_NAME		(const xmlChar *) "name"
76*7c478bd9Sstevel@tonic-gate #define	DTD_ATTR_PHYSICAL	(const xmlChar *) "physical"
77*7c478bd9Sstevel@tonic-gate #define	DTD_ATTR_POOL		(const xmlChar *) "pool"
78*7c478bd9Sstevel@tonic-gate #define	DTD_ATTR_PRIV		(const xmlChar *) "priv"
79*7c478bd9Sstevel@tonic-gate #define	DTD_ATTR_RAW		(const xmlChar *) "raw"
80*7c478bd9Sstevel@tonic-gate #define	DTD_ATTR_SPECIAL	(const xmlChar *) "special"
81*7c478bd9Sstevel@tonic-gate #define	DTD_ATTR_TYPE		(const xmlChar *) "type"
82*7c478bd9Sstevel@tonic-gate #define	DTD_ATTR_VALUE		(const xmlChar *) "value"
83*7c478bd9Sstevel@tonic-gate #define	DTD_ATTR_ZONEPATH	(const xmlChar *) "zonepath"
84*7c478bd9Sstevel@tonic-gate 
85*7c478bd9Sstevel@tonic-gate #define	DTD_ENTITY_BOOLEAN	"boolean"
86*7c478bd9Sstevel@tonic-gate #define	DTD_ENTITY_DEVPATH	"devpath"
87*7c478bd9Sstevel@tonic-gate #define	DTD_ENTITY_DRIVER	"driver"
88*7c478bd9Sstevel@tonic-gate #define	DTD_ENTITY_DRVMIN	"drv_min"
89*7c478bd9Sstevel@tonic-gate #define	DTD_ENTITY_FALSE	"false"
90*7c478bd9Sstevel@tonic-gate #define	DTD_ENTITY_INT		"int"
91*7c478bd9Sstevel@tonic-gate #define	DTD_ENTITY_STRING	"string"
92*7c478bd9Sstevel@tonic-gate #define	DTD_ENTITY_TRUE		"true"
93*7c478bd9Sstevel@tonic-gate #define	DTD_ENTITY_UINT		"uint"
94*7c478bd9Sstevel@tonic-gate 
95*7c478bd9Sstevel@tonic-gate struct zone_dochandle {
96*7c478bd9Sstevel@tonic-gate 	char		*zone_dh_rootdir;
97*7c478bd9Sstevel@tonic-gate 	xmlDocPtr	zone_dh_doc;
98*7c478bd9Sstevel@tonic-gate 	xmlNodePtr	zone_dh_cur;
99*7c478bd9Sstevel@tonic-gate 	xmlNodePtr	zone_dh_top;
100*7c478bd9Sstevel@tonic-gate };
101*7c478bd9Sstevel@tonic-gate 
102*7c478bd9Sstevel@tonic-gate /*
103*7c478bd9Sstevel@tonic-gate  * For functions which return int, which is most of the functions herein,
104*7c478bd9Sstevel@tonic-gate  * the return values should be from the Z_foo set defined in <libzonecfg.h>.
105*7c478bd9Sstevel@tonic-gate  * In some instances, we take pains mapping some libc errno values to Z_foo
106*7c478bd9Sstevel@tonic-gate  * values from this set.
107*7c478bd9Sstevel@tonic-gate  */
108*7c478bd9Sstevel@tonic-gate 
109*7c478bd9Sstevel@tonic-gate /*
110*7c478bd9Sstevel@tonic-gate  * Callers of the _file_path() functions are expected to have the second
111*7c478bd9Sstevel@tonic-gate  * parameter be a (char foo[MAXPATHLEN]).
112*7c478bd9Sstevel@tonic-gate  */
113*7c478bd9Sstevel@tonic-gate 
114*7c478bd9Sstevel@tonic-gate static void
115*7c478bd9Sstevel@tonic-gate config_file_path(const char *zonename, char *answer)
116*7c478bd9Sstevel@tonic-gate {
117*7c478bd9Sstevel@tonic-gate 	(void) snprintf(answer, MAXPATHLEN,
118*7c478bd9Sstevel@tonic-gate 	    "%s/%s.xml", ZONE_CONFIG_ROOT, zonename);
119*7c478bd9Sstevel@tonic-gate }
120*7c478bd9Sstevel@tonic-gate 
121*7c478bd9Sstevel@tonic-gate static void
122*7c478bd9Sstevel@tonic-gate snap_file_path(char *zonename, char *answer)
123*7c478bd9Sstevel@tonic-gate {
124*7c478bd9Sstevel@tonic-gate 	(void) snprintf(answer, MAXPATHLEN,
125*7c478bd9Sstevel@tonic-gate 	    "%s/%s.snapshot.xml", ZONE_SNAPSHOT_ROOT, zonename);
126*7c478bd9Sstevel@tonic-gate }
127*7c478bd9Sstevel@tonic-gate 
128*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
129*7c478bd9Sstevel@tonic-gate static void
130*7c478bd9Sstevel@tonic-gate zonecfg_error_func(void *ctx, const char *msg, ...)
131*7c478bd9Sstevel@tonic-gate {
132*7c478bd9Sstevel@tonic-gate 	/*
133*7c478bd9Sstevel@tonic-gate 	 * This function does nothing by design.  Its purpose is to prevent
134*7c478bd9Sstevel@tonic-gate 	 * libxml from dumping unwanted messages to stdout/stderr.
135*7c478bd9Sstevel@tonic-gate 	 */
136*7c478bd9Sstevel@tonic-gate }
137*7c478bd9Sstevel@tonic-gate 
138*7c478bd9Sstevel@tonic-gate zone_dochandle_t
139*7c478bd9Sstevel@tonic-gate zonecfg_init_handle(void)
140*7c478bd9Sstevel@tonic-gate {
141*7c478bd9Sstevel@tonic-gate 	zone_dochandle_t handle = malloc(sizeof (struct zone_dochandle));
142*7c478bd9Sstevel@tonic-gate 	if (handle == NULL) {
143*7c478bd9Sstevel@tonic-gate 		errno = Z_NOMEM;
144*7c478bd9Sstevel@tonic-gate 		return (NULL);
145*7c478bd9Sstevel@tonic-gate 	}
146*7c478bd9Sstevel@tonic-gate 	handle->zone_dh_doc = NULL;
147*7c478bd9Sstevel@tonic-gate 	handle->zone_dh_cur = NULL;
148*7c478bd9Sstevel@tonic-gate 	handle->zone_dh_top = NULL;
149*7c478bd9Sstevel@tonic-gate 
150*7c478bd9Sstevel@tonic-gate 	/* generic libxml initialization */
151*7c478bd9Sstevel@tonic-gate 	xmlLineNumbersDefault(1);
152*7c478bd9Sstevel@tonic-gate 	xmlLoadExtDtdDefaultValue |= XML_DETECT_IDS;
153*7c478bd9Sstevel@tonic-gate 	xmlDoValidityCheckingDefaultValue = 1;
154*7c478bd9Sstevel@tonic-gate 	(void) xmlKeepBlanksDefault(0);
155*7c478bd9Sstevel@tonic-gate 	xmlGetWarningsDefaultValue = 0;
156*7c478bd9Sstevel@tonic-gate 	xmlSetGenericErrorFunc(NULL, zonecfg_error_func);
157*7c478bd9Sstevel@tonic-gate 
158*7c478bd9Sstevel@tonic-gate 	return (handle);
159*7c478bd9Sstevel@tonic-gate }
160*7c478bd9Sstevel@tonic-gate 
161*7c478bd9Sstevel@tonic-gate int
162*7c478bd9Sstevel@tonic-gate zonecfg_check_handle(zone_dochandle_t handle)
163*7c478bd9Sstevel@tonic-gate {
164*7c478bd9Sstevel@tonic-gate 	if (handle == NULL || handle->zone_dh_doc == NULL)
165*7c478bd9Sstevel@tonic-gate 		return (Z_BAD_HANDLE);
166*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
167*7c478bd9Sstevel@tonic-gate }
168*7c478bd9Sstevel@tonic-gate 
169*7c478bd9Sstevel@tonic-gate void
170*7c478bd9Sstevel@tonic-gate zonecfg_fini_handle(zone_dochandle_t handle)
171*7c478bd9Sstevel@tonic-gate {
172*7c478bd9Sstevel@tonic-gate 	if (zonecfg_check_handle(handle) == Z_OK)
173*7c478bd9Sstevel@tonic-gate 		xmlFreeDoc(handle->zone_dh_doc);
174*7c478bd9Sstevel@tonic-gate 	if (handle != NULL)
175*7c478bd9Sstevel@tonic-gate 		free(handle);
176*7c478bd9Sstevel@tonic-gate }
177*7c478bd9Sstevel@tonic-gate 
178*7c478bd9Sstevel@tonic-gate static int
179*7c478bd9Sstevel@tonic-gate zonecfg_destroy_impl(char *filename)
180*7c478bd9Sstevel@tonic-gate {
181*7c478bd9Sstevel@tonic-gate 	if (unlink(filename) == -1) {
182*7c478bd9Sstevel@tonic-gate 		if (errno == EACCES)
183*7c478bd9Sstevel@tonic-gate 			return (Z_ACCES);
184*7c478bd9Sstevel@tonic-gate 		if (errno == ENOENT)
185*7c478bd9Sstevel@tonic-gate 			return (Z_NO_ZONE);
186*7c478bd9Sstevel@tonic-gate 		return (Z_MISC_FS);
187*7c478bd9Sstevel@tonic-gate 	}
188*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
189*7c478bd9Sstevel@tonic-gate }
190*7c478bd9Sstevel@tonic-gate 
191*7c478bd9Sstevel@tonic-gate int
192*7c478bd9Sstevel@tonic-gate zonecfg_destroy(const char *zonename)
193*7c478bd9Sstevel@tonic-gate {
194*7c478bd9Sstevel@tonic-gate 	char path[MAXPATHLEN];
195*7c478bd9Sstevel@tonic-gate 
196*7c478bd9Sstevel@tonic-gate 	config_file_path(zonename, path);
197*7c478bd9Sstevel@tonic-gate 	return (zonecfg_destroy_impl(path));
198*7c478bd9Sstevel@tonic-gate }
199*7c478bd9Sstevel@tonic-gate 
200*7c478bd9Sstevel@tonic-gate int
201*7c478bd9Sstevel@tonic-gate zonecfg_destroy_snapshot(char *zonename)
202*7c478bd9Sstevel@tonic-gate {
203*7c478bd9Sstevel@tonic-gate 	char path[MAXPATHLEN];
204*7c478bd9Sstevel@tonic-gate 
205*7c478bd9Sstevel@tonic-gate 	snap_file_path(zonename, path);
206*7c478bd9Sstevel@tonic-gate 	return (zonecfg_destroy_impl(path));
207*7c478bd9Sstevel@tonic-gate }
208*7c478bd9Sstevel@tonic-gate 
209*7c478bd9Sstevel@tonic-gate static int
210*7c478bd9Sstevel@tonic-gate operation_prep(zone_dochandle_t handle)
211*7c478bd9Sstevel@tonic-gate {
212*7c478bd9Sstevel@tonic-gate 	xmlNodePtr cur;
213*7c478bd9Sstevel@tonic-gate 
214*7c478bd9Sstevel@tonic-gate 	if (zonecfg_check_handle(handle) == Z_BAD_HANDLE)
215*7c478bd9Sstevel@tonic-gate 		return (Z_BAD_HANDLE);
216*7c478bd9Sstevel@tonic-gate 
217*7c478bd9Sstevel@tonic-gate 	if ((cur = xmlDocGetRootElement(handle->zone_dh_doc)) == NULL) {
218*7c478bd9Sstevel@tonic-gate 		zonecfg_fini_handle(handle);
219*7c478bd9Sstevel@tonic-gate 		return (Z_EMPTY_DOCUMENT);
220*7c478bd9Sstevel@tonic-gate 	}
221*7c478bd9Sstevel@tonic-gate 
222*7c478bd9Sstevel@tonic-gate 	if (xmlStrcmp(cur->name, DTD_ELEM_ZONE)) {
223*7c478bd9Sstevel@tonic-gate 		zonecfg_fini_handle(handle);
224*7c478bd9Sstevel@tonic-gate 		return (Z_WRONG_DOC_TYPE);
225*7c478bd9Sstevel@tonic-gate 	}
226*7c478bd9Sstevel@tonic-gate 	handle->zone_dh_cur = cur;
227*7c478bd9Sstevel@tonic-gate 	handle->zone_dh_top = cur;
228*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
229*7c478bd9Sstevel@tonic-gate }
230*7c478bd9Sstevel@tonic-gate 
231*7c478bd9Sstevel@tonic-gate static int
232*7c478bd9Sstevel@tonic-gate zonecfg_get_handle_impl(char *zonename, char *filename, zone_dochandle_t handle)
233*7c478bd9Sstevel@tonic-gate {
234*7c478bd9Sstevel@tonic-gate 	xmlValidCtxtPtr cvp;
235*7c478bd9Sstevel@tonic-gate 	xmlDocPtr top;
236*7c478bd9Sstevel@tonic-gate 	xmlNodePtr child, next;
237*7c478bd9Sstevel@tonic-gate 	struct stat statbuf;
238*7c478bd9Sstevel@tonic-gate 	int valid;
239*7c478bd9Sstevel@tonic-gate 
240*7c478bd9Sstevel@tonic-gate 	if (zonename == NULL)
241*7c478bd9Sstevel@tonic-gate 		return (Z_NO_ZONE);
242*7c478bd9Sstevel@tonic-gate 	if ((handle->zone_dh_doc = xmlParseFile(filename)) == NULL) {
243*7c478bd9Sstevel@tonic-gate 		/* distinguish file not found vs. found but not parsed */
244*7c478bd9Sstevel@tonic-gate 		if (stat(filename, &statbuf) == 0)
245*7c478bd9Sstevel@tonic-gate 			return (Z_INVALID_DOCUMENT);
246*7c478bd9Sstevel@tonic-gate 		return (Z_NO_ZONE);
247*7c478bd9Sstevel@tonic-gate 	}
248*7c478bd9Sstevel@tonic-gate 	if ((cvp = xmlNewValidCtxt()) == NULL)
249*7c478bd9Sstevel@tonic-gate 		return (Z_NOMEM);
250*7c478bd9Sstevel@tonic-gate 	cvp->error = zonecfg_error_func;
251*7c478bd9Sstevel@tonic-gate 	cvp->warning = zonecfg_error_func;
252*7c478bd9Sstevel@tonic-gate 	valid = xmlValidateDocument(cvp, handle->zone_dh_doc);
253*7c478bd9Sstevel@tonic-gate 	xmlFreeValidCtxt(cvp);
254*7c478bd9Sstevel@tonic-gate 	if (valid == 0)
255*7c478bd9Sstevel@tonic-gate 		return (Z_INVALID_DOCUMENT);
256*7c478bd9Sstevel@tonic-gate 	/* delete any comments such as inherited Sun copyright / ident str */
257*7c478bd9Sstevel@tonic-gate 	top = handle->zone_dh_doc;
258*7c478bd9Sstevel@tonic-gate 	for (child = top->xmlChildrenNode; child != NULL; child = next) {
259*7c478bd9Sstevel@tonic-gate 		next = child->next;
260*7c478bd9Sstevel@tonic-gate 		if (child->name == NULL)
261*7c478bd9Sstevel@tonic-gate 			continue;
262*7c478bd9Sstevel@tonic-gate 		if (xmlStrcmp(child->name, DTD_ELEM_COMMENT) == 0) {
263*7c478bd9Sstevel@tonic-gate 			next = child->next;
264*7c478bd9Sstevel@tonic-gate 			xmlUnlinkNode(child);
265*7c478bd9Sstevel@tonic-gate 			xmlFreeNode(child);
266*7c478bd9Sstevel@tonic-gate 		}
267*7c478bd9Sstevel@tonic-gate 	}
268*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
269*7c478bd9Sstevel@tonic-gate }
270*7c478bd9Sstevel@tonic-gate 
271*7c478bd9Sstevel@tonic-gate int
272*7c478bd9Sstevel@tonic-gate zonecfg_get_handle(char *zonename, zone_dochandle_t handle)
273*7c478bd9Sstevel@tonic-gate {
274*7c478bd9Sstevel@tonic-gate 	char path[MAXPATHLEN];
275*7c478bd9Sstevel@tonic-gate 
276*7c478bd9Sstevel@tonic-gate 	config_file_path(zonename, path);
277*7c478bd9Sstevel@tonic-gate 	return (zonecfg_get_handle_impl(zonename, path, handle));
278*7c478bd9Sstevel@tonic-gate }
279*7c478bd9Sstevel@tonic-gate 
280*7c478bd9Sstevel@tonic-gate int
281*7c478bd9Sstevel@tonic-gate zonecfg_get_snapshot_handle(char *zonename, zone_dochandle_t handle)
282*7c478bd9Sstevel@tonic-gate {
283*7c478bd9Sstevel@tonic-gate 	char path[MAXPATHLEN];
284*7c478bd9Sstevel@tonic-gate 
285*7c478bd9Sstevel@tonic-gate 	snap_file_path(zonename, path);
286*7c478bd9Sstevel@tonic-gate 	return (zonecfg_get_handle_impl(zonename, path, handle));
287*7c478bd9Sstevel@tonic-gate }
288*7c478bd9Sstevel@tonic-gate 
289*7c478bd9Sstevel@tonic-gate int
290*7c478bd9Sstevel@tonic-gate zonecfg_get_name(zone_dochandle_t handle, char *name, size_t namesize)
291*7c478bd9Sstevel@tonic-gate {
292*7c478bd9Sstevel@tonic-gate 	xmlNodePtr cur;
293*7c478bd9Sstevel@tonic-gate 	xmlChar *property;
294*7c478bd9Sstevel@tonic-gate 	size_t srcsize;
295*7c478bd9Sstevel@tonic-gate 
296*7c478bd9Sstevel@tonic-gate 	if (handle == NULL)
297*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
298*7c478bd9Sstevel@tonic-gate 
299*7c478bd9Sstevel@tonic-gate 	cur = xmlDocGetRootElement(handle->zone_dh_doc);
300*7c478bd9Sstevel@tonic-gate 	if (cur == NULL) {
301*7c478bd9Sstevel@tonic-gate 		zonecfg_fini_handle(handle);
302*7c478bd9Sstevel@tonic-gate 		return (Z_EMPTY_DOCUMENT);
303*7c478bd9Sstevel@tonic-gate 	}
304*7c478bd9Sstevel@tonic-gate 
305*7c478bd9Sstevel@tonic-gate 	if (xmlStrcmp(cur->name, DTD_ELEM_ZONE)) {
306*7c478bd9Sstevel@tonic-gate 		zonecfg_fini_handle(handle);
307*7c478bd9Sstevel@tonic-gate 		return (Z_WRONG_DOC_TYPE);
308*7c478bd9Sstevel@tonic-gate 	}
309*7c478bd9Sstevel@tonic-gate 	if ((property = xmlGetProp(cur, DTD_ATTR_NAME)) == NULL)
310*7c478bd9Sstevel@tonic-gate 		return (Z_BAD_PROPERTY);
311*7c478bd9Sstevel@tonic-gate 	srcsize = strlcpy(name, (char *)property, namesize);
312*7c478bd9Sstevel@tonic-gate 	xmlFree(property);
313*7c478bd9Sstevel@tonic-gate 	if (srcsize >= namesize)
314*7c478bd9Sstevel@tonic-gate 		return (Z_TOO_BIG);
315*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
316*7c478bd9Sstevel@tonic-gate }
317*7c478bd9Sstevel@tonic-gate 
318*7c478bd9Sstevel@tonic-gate static int
319*7c478bd9Sstevel@tonic-gate zonecfg_save_impl(zone_dochandle_t handle, char *filename)
320*7c478bd9Sstevel@tonic-gate {
321*7c478bd9Sstevel@tonic-gate 	char tmpfile[MAXPATHLEN];
322*7c478bd9Sstevel@tonic-gate 	int tmpfd;
323*7c478bd9Sstevel@tonic-gate 	xmlValidCtxt cvp = { NULL };
324*7c478bd9Sstevel@tonic-gate 	xmlNodePtr comment;
325*7c478bd9Sstevel@tonic-gate 
326*7c478bd9Sstevel@tonic-gate 	(void) strlcpy(tmpfile, filename, sizeof (tmpfile));
327*7c478bd9Sstevel@tonic-gate 	(void) dirname(tmpfile);
328*7c478bd9Sstevel@tonic-gate 	(void) strlcat(tmpfile, _PATH_TMPFILE, sizeof (tmpfile));
329*7c478bd9Sstevel@tonic-gate 
330*7c478bd9Sstevel@tonic-gate 	tmpfd = mkstemp(tmpfile);
331*7c478bd9Sstevel@tonic-gate 	if (tmpfd == -1) {
332*7c478bd9Sstevel@tonic-gate 		(void) unlink(tmpfile);
333*7c478bd9Sstevel@tonic-gate 		return (Z_TEMP_FILE);
334*7c478bd9Sstevel@tonic-gate 	}
335*7c478bd9Sstevel@tonic-gate 	(void) close(tmpfd);
336*7c478bd9Sstevel@tonic-gate 
337*7c478bd9Sstevel@tonic-gate 	cvp.error = zonecfg_error_func;
338*7c478bd9Sstevel@tonic-gate 	cvp.warning = zonecfg_error_func;
339*7c478bd9Sstevel@tonic-gate 
340*7c478bd9Sstevel@tonic-gate 	if ((comment = xmlNewComment((xmlChar *) "\n    DO NOT EDIT THIS "
341*7c478bd9Sstevel@tonic-gate 	    "FILE.  Use zonecfg(1M) instead.\n")) == NULL)
342*7c478bd9Sstevel@tonic-gate 		goto err;
343*7c478bd9Sstevel@tonic-gate 	if (xmlAddPrevSibling(handle->zone_dh_top, comment) == 0)
344*7c478bd9Sstevel@tonic-gate 		goto err;
345*7c478bd9Sstevel@tonic-gate 
346*7c478bd9Sstevel@tonic-gate 	if (xmlValidateDocument(&cvp, handle->zone_dh_doc) == 0)
347*7c478bd9Sstevel@tonic-gate 		goto err;
348*7c478bd9Sstevel@tonic-gate 
349*7c478bd9Sstevel@tonic-gate 	if (xmlSaveFormatFile(tmpfile, handle->zone_dh_doc, 1) <= 0)
350*7c478bd9Sstevel@tonic-gate 		goto err;
351*7c478bd9Sstevel@tonic-gate 	(void) chmod(tmpfile, 0644);
352*7c478bd9Sstevel@tonic-gate 
353*7c478bd9Sstevel@tonic-gate 	if (rename(tmpfile, filename) == -1) {
354*7c478bd9Sstevel@tonic-gate 		(void) unlink(tmpfile);
355*7c478bd9Sstevel@tonic-gate 		if (errno == EACCES)
356*7c478bd9Sstevel@tonic-gate 			return (Z_ACCES);
357*7c478bd9Sstevel@tonic-gate 		return (Z_MISC_FS);
358*7c478bd9Sstevel@tonic-gate 	}
359*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
360*7c478bd9Sstevel@tonic-gate 
361*7c478bd9Sstevel@tonic-gate err:
362*7c478bd9Sstevel@tonic-gate 	(void) unlink(tmpfile);
363*7c478bd9Sstevel@tonic-gate 	return (Z_SAVING_FILE);
364*7c478bd9Sstevel@tonic-gate }
365*7c478bd9Sstevel@tonic-gate 
366*7c478bd9Sstevel@tonic-gate int
367*7c478bd9Sstevel@tonic-gate zonecfg_save(zone_dochandle_t handle)
368*7c478bd9Sstevel@tonic-gate {
369*7c478bd9Sstevel@tonic-gate 	char zname[MAXPATHLEN], path[MAXPATHLEN];
370*7c478bd9Sstevel@tonic-gate 	int err;
371*7c478bd9Sstevel@tonic-gate 
372*7c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_get_name(handle, zname, sizeof (zname))) != Z_OK) {
373*7c478bd9Sstevel@tonic-gate 		return (err);
374*7c478bd9Sstevel@tonic-gate 	}
375*7c478bd9Sstevel@tonic-gate 	config_file_path(zname, path);
376*7c478bd9Sstevel@tonic-gate 	return (zonecfg_save_impl(handle, path));
377*7c478bd9Sstevel@tonic-gate }
378*7c478bd9Sstevel@tonic-gate 
379*7c478bd9Sstevel@tonic-gate /*
380*7c478bd9Sstevel@tonic-gate  * Special case: if access(2) fails with ENOENT, then try again using
381*7c478bd9Sstevel@tonic-gate  * ZONE_CONFIG_ROOT instead of config_file_path(zonename).  This is how we
382*7c478bd9Sstevel@tonic-gate  * work around the case of a config file which has not been created yet:
383*7c478bd9Sstevel@tonic-gate  * the user will need access to the directory so use that as a heuristic.
384*7c478bd9Sstevel@tonic-gate  */
385*7c478bd9Sstevel@tonic-gate 
386*7c478bd9Sstevel@tonic-gate int
387*7c478bd9Sstevel@tonic-gate zonecfg_access(const char *zonename, int amode)
388*7c478bd9Sstevel@tonic-gate {
389*7c478bd9Sstevel@tonic-gate 	char path[MAXPATHLEN];
390*7c478bd9Sstevel@tonic-gate 
391*7c478bd9Sstevel@tonic-gate 	config_file_path(zonename, path);
392*7c478bd9Sstevel@tonic-gate 	if (access(path, amode) == 0)
393*7c478bd9Sstevel@tonic-gate 		return (Z_OK);
394*7c478bd9Sstevel@tonic-gate 	if (errno == ENOENT && access(ZONE_CONFIG_ROOT, amode) == 0)
395*7c478bd9Sstevel@tonic-gate 		return (Z_OK);
396*7c478bd9Sstevel@tonic-gate 	if (errno == EACCES)
397*7c478bd9Sstevel@tonic-gate 		return (Z_ACCES);
398*7c478bd9Sstevel@tonic-gate 	if (errno == EINVAL)
399*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
400*7c478bd9Sstevel@tonic-gate 	return (Z_MISC_FS);
401*7c478bd9Sstevel@tonic-gate }
402*7c478bd9Sstevel@tonic-gate 
403*7c478bd9Sstevel@tonic-gate int
404*7c478bd9Sstevel@tonic-gate zonecfg_create_snapshot(char *zonename)
405*7c478bd9Sstevel@tonic-gate {
406*7c478bd9Sstevel@tonic-gate 	zone_dochandle_t handle;
407*7c478bd9Sstevel@tonic-gate 	char path[MAXPATHLEN], zonepath[MAXPATHLEN], rpath[MAXPATHLEN];
408*7c478bd9Sstevel@tonic-gate 	int error = Z_OK, res;
409*7c478bd9Sstevel@tonic-gate 
410*7c478bd9Sstevel@tonic-gate 	if ((handle = zonecfg_init_handle()) == NULL) {
411*7c478bd9Sstevel@tonic-gate 		return (Z_NOMEM);
412*7c478bd9Sstevel@tonic-gate 	}
413*7c478bd9Sstevel@tonic-gate 
414*7c478bd9Sstevel@tonic-gate 	if ((error = zonecfg_get_handle(zonename, handle)) != Z_OK)
415*7c478bd9Sstevel@tonic-gate 		goto out;
416*7c478bd9Sstevel@tonic-gate 	if ((error = operation_prep(handle)) != Z_OK)
417*7c478bd9Sstevel@tonic-gate 		goto out;
418*7c478bd9Sstevel@tonic-gate 	error = zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath));
419*7c478bd9Sstevel@tonic-gate 	if (error != Z_OK)
420*7c478bd9Sstevel@tonic-gate 		goto out;
421*7c478bd9Sstevel@tonic-gate 	if ((res = resolvepath(zonepath, rpath, sizeof (rpath))) == -1) {
422*7c478bd9Sstevel@tonic-gate 		error = Z_RESOLVED_PATH;
423*7c478bd9Sstevel@tonic-gate 		goto out;
424*7c478bd9Sstevel@tonic-gate 	}
425*7c478bd9Sstevel@tonic-gate 	/*
426*7c478bd9Sstevel@tonic-gate 	 * If the resolved path is not the same as the original path, then
427*7c478bd9Sstevel@tonic-gate 	 * save the resolved path in the snapshot, thus preventing any
428*7c478bd9Sstevel@tonic-gate 	 * potential problems down the line when zoneadmd goes to unmount
429*7c478bd9Sstevel@tonic-gate 	 * file systems and depends on initial string matches with resolved
430*7c478bd9Sstevel@tonic-gate 	 * paths.
431*7c478bd9Sstevel@tonic-gate 	 */
432*7c478bd9Sstevel@tonic-gate 	rpath[res] = '\0';
433*7c478bd9Sstevel@tonic-gate 	if (strcmp(zonepath, rpath) != 0) {
434*7c478bd9Sstevel@tonic-gate 		if ((error = zonecfg_set_zonepath(handle, rpath)) != Z_OK)
435*7c478bd9Sstevel@tonic-gate 			goto out;
436*7c478bd9Sstevel@tonic-gate 	}
437*7c478bd9Sstevel@tonic-gate 	if ((mkdir(ZONE_SNAPSHOT_ROOT, S_IRWXU) == -1) && (errno != EEXIST)) {
438*7c478bd9Sstevel@tonic-gate 		error = Z_MISC_FS;
439*7c478bd9Sstevel@tonic-gate 		goto out;
440*7c478bd9Sstevel@tonic-gate 	}
441*7c478bd9Sstevel@tonic-gate 
442*7c478bd9Sstevel@tonic-gate 	snap_file_path(zonename, path);
443*7c478bd9Sstevel@tonic-gate 	error = zonecfg_save_impl(handle, path);
444*7c478bd9Sstevel@tonic-gate 
445*7c478bd9Sstevel@tonic-gate out:
446*7c478bd9Sstevel@tonic-gate 	zonecfg_fini_handle(handle);
447*7c478bd9Sstevel@tonic-gate 	return (error);
448*7c478bd9Sstevel@tonic-gate }
449*7c478bd9Sstevel@tonic-gate 
450*7c478bd9Sstevel@tonic-gate int
451*7c478bd9Sstevel@tonic-gate zonecfg_set_name(zone_dochandle_t handle, char *name)
452*7c478bd9Sstevel@tonic-gate {
453*7c478bd9Sstevel@tonic-gate 	xmlNodePtr cur;
454*7c478bd9Sstevel@tonic-gate 
455*7c478bd9Sstevel@tonic-gate 	if (handle == NULL || name == NULL)
456*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
457*7c478bd9Sstevel@tonic-gate 
458*7c478bd9Sstevel@tonic-gate 	cur = xmlDocGetRootElement(handle->zone_dh_doc);
459*7c478bd9Sstevel@tonic-gate 	if (cur == NULL) {
460*7c478bd9Sstevel@tonic-gate 		zonecfg_fini_handle(handle);
461*7c478bd9Sstevel@tonic-gate 		return (Z_EMPTY_DOCUMENT);
462*7c478bd9Sstevel@tonic-gate 	}
463*7c478bd9Sstevel@tonic-gate 
464*7c478bd9Sstevel@tonic-gate 	if (xmlStrcmp(cur->name, DTD_ELEM_ZONE)) {
465*7c478bd9Sstevel@tonic-gate 		zonecfg_fini_handle(handle);
466*7c478bd9Sstevel@tonic-gate 		return (Z_WRONG_DOC_TYPE);
467*7c478bd9Sstevel@tonic-gate 	}
468*7c478bd9Sstevel@tonic-gate 	if (xmlSetProp(cur, DTD_ATTR_NAME, (const xmlChar *) name) == NULL)
469*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
470*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
471*7c478bd9Sstevel@tonic-gate }
472*7c478bd9Sstevel@tonic-gate 
473*7c478bd9Sstevel@tonic-gate int
474*7c478bd9Sstevel@tonic-gate zonecfg_get_zonepath(zone_dochandle_t handle, char *path, size_t pathsize)
475*7c478bd9Sstevel@tonic-gate {
476*7c478bd9Sstevel@tonic-gate 	xmlNodePtr cur;
477*7c478bd9Sstevel@tonic-gate 	xmlChar *property;
478*7c478bd9Sstevel@tonic-gate 	size_t srcsize;
479*7c478bd9Sstevel@tonic-gate 
480*7c478bd9Sstevel@tonic-gate 	if (handle == NULL)
481*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
482*7c478bd9Sstevel@tonic-gate 
483*7c478bd9Sstevel@tonic-gate 	cur = xmlDocGetRootElement(handle->zone_dh_doc);
484*7c478bd9Sstevel@tonic-gate 	if (cur == NULL) {
485*7c478bd9Sstevel@tonic-gate 		zonecfg_fini_handle(handle);
486*7c478bd9Sstevel@tonic-gate 		return (Z_EMPTY_DOCUMENT);
487*7c478bd9Sstevel@tonic-gate 	}
488*7c478bd9Sstevel@tonic-gate 
489*7c478bd9Sstevel@tonic-gate 	if (xmlStrcmp(cur->name, DTD_ELEM_ZONE)) {
490*7c478bd9Sstevel@tonic-gate 		zonecfg_fini_handle(handle);
491*7c478bd9Sstevel@tonic-gate 		return (Z_WRONG_DOC_TYPE);
492*7c478bd9Sstevel@tonic-gate 	}
493*7c478bd9Sstevel@tonic-gate 	if ((property = xmlGetProp(cur, DTD_ATTR_ZONEPATH)) == NULL)
494*7c478bd9Sstevel@tonic-gate 		return (Z_BAD_PROPERTY);
495*7c478bd9Sstevel@tonic-gate 	srcsize = strlcpy(path, (char *)property, pathsize);
496*7c478bd9Sstevel@tonic-gate 	xmlFree(property);
497*7c478bd9Sstevel@tonic-gate 	if (srcsize >= pathsize)
498*7c478bd9Sstevel@tonic-gate 		return (Z_TOO_BIG);
499*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
500*7c478bd9Sstevel@tonic-gate }
501*7c478bd9Sstevel@tonic-gate 
502*7c478bd9Sstevel@tonic-gate int
503*7c478bd9Sstevel@tonic-gate zonecfg_set_zonepath(zone_dochandle_t handle, char *zonepath)
504*7c478bd9Sstevel@tonic-gate {
505*7c478bd9Sstevel@tonic-gate 	xmlNodePtr cur;
506*7c478bd9Sstevel@tonic-gate 	char name[ZONENAME_MAX];
507*7c478bd9Sstevel@tonic-gate 	struct zoneent ze;
508*7c478bd9Sstevel@tonic-gate 	int err;
509*7c478bd9Sstevel@tonic-gate 
510*7c478bd9Sstevel@tonic-gate 	if (handle == NULL || zonepath == NULL)
511*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
512*7c478bd9Sstevel@tonic-gate 
513*7c478bd9Sstevel@tonic-gate 	cur = xmlDocGetRootElement(handle->zone_dh_doc);
514*7c478bd9Sstevel@tonic-gate 	if (cur == NULL) {
515*7c478bd9Sstevel@tonic-gate 		zonecfg_fini_handle(handle);
516*7c478bd9Sstevel@tonic-gate 		return (Z_EMPTY_DOCUMENT);
517*7c478bd9Sstevel@tonic-gate 	}
518*7c478bd9Sstevel@tonic-gate 
519*7c478bd9Sstevel@tonic-gate 	if (xmlStrcmp(cur->name, DTD_ELEM_ZONE)) {
520*7c478bd9Sstevel@tonic-gate 		zonecfg_fini_handle(handle);
521*7c478bd9Sstevel@tonic-gate 		return (Z_WRONG_DOC_TYPE);
522*7c478bd9Sstevel@tonic-gate 	}
523*7c478bd9Sstevel@tonic-gate 	if (xmlSetProp(cur, DTD_ATTR_ZONEPATH, (const xmlChar *) zonepath) ==
524*7c478bd9Sstevel@tonic-gate 	    NULL)
525*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
526*7c478bd9Sstevel@tonic-gate 
527*7c478bd9Sstevel@tonic-gate 	/* now set the copy in the index file */
528*7c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_get_name(handle, name, sizeof (name))) != Z_OK)
529*7c478bd9Sstevel@tonic-gate 		return (err);
530*7c478bd9Sstevel@tonic-gate 	(void) strlcpy(ze.zone_name, name, sizeof (ze.zone_name));
531*7c478bd9Sstevel@tonic-gate 	ze.zone_state = -1;
532*7c478bd9Sstevel@tonic-gate 	(void) strlcpy(ze.zone_path, zonepath, sizeof (ze.zone_path));
533*7c478bd9Sstevel@tonic-gate 	return (putzoneent(&ze, PZE_MODIFY));
534*7c478bd9Sstevel@tonic-gate }
535*7c478bd9Sstevel@tonic-gate 
536*7c478bd9Sstevel@tonic-gate int
537*7c478bd9Sstevel@tonic-gate zonecfg_get_autoboot(zone_dochandle_t handle, boolean_t *autoboot)
538*7c478bd9Sstevel@tonic-gate {
539*7c478bd9Sstevel@tonic-gate 	xmlNodePtr cur;
540*7c478bd9Sstevel@tonic-gate 	xmlChar *property;
541*7c478bd9Sstevel@tonic-gate 	int result = Z_OK;
542*7c478bd9Sstevel@tonic-gate 
543*7c478bd9Sstevel@tonic-gate 	if (handle == NULL)
544*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
545*7c478bd9Sstevel@tonic-gate 
546*7c478bd9Sstevel@tonic-gate 	cur = xmlDocGetRootElement(handle->zone_dh_doc);
547*7c478bd9Sstevel@tonic-gate 	if (cur == NULL) {
548*7c478bd9Sstevel@tonic-gate 		zonecfg_fini_handle(handle);
549*7c478bd9Sstevel@tonic-gate 		return (Z_EMPTY_DOCUMENT);
550*7c478bd9Sstevel@tonic-gate 	}
551*7c478bd9Sstevel@tonic-gate 
552*7c478bd9Sstevel@tonic-gate 	if (xmlStrcmp(cur->name, DTD_ELEM_ZONE)) {
553*7c478bd9Sstevel@tonic-gate 		zonecfg_fini_handle(handle);
554*7c478bd9Sstevel@tonic-gate 		return (Z_WRONG_DOC_TYPE);
555*7c478bd9Sstevel@tonic-gate 	}
556*7c478bd9Sstevel@tonic-gate 	if ((property = xmlGetProp(cur, DTD_ATTR_AUTOBOOT)) == NULL)
557*7c478bd9Sstevel@tonic-gate 		return (Z_BAD_PROPERTY);
558*7c478bd9Sstevel@tonic-gate 	if (strcmp((char *)property, DTD_ENTITY_TRUE) == 0)
559*7c478bd9Sstevel@tonic-gate 		*autoboot = B_TRUE;
560*7c478bd9Sstevel@tonic-gate 	else if (strcmp((char *)property, DTD_ENTITY_FALSE) == 0)
561*7c478bd9Sstevel@tonic-gate 		*autoboot = B_FALSE;
562*7c478bd9Sstevel@tonic-gate 	else
563*7c478bd9Sstevel@tonic-gate 		result = Z_BAD_PROPERTY;
564*7c478bd9Sstevel@tonic-gate 	xmlFree(property);
565*7c478bd9Sstevel@tonic-gate 	return (result);
566*7c478bd9Sstevel@tonic-gate }
567*7c478bd9Sstevel@tonic-gate 
568*7c478bd9Sstevel@tonic-gate int
569*7c478bd9Sstevel@tonic-gate zonecfg_set_autoboot(zone_dochandle_t handle, boolean_t autoboot)
570*7c478bd9Sstevel@tonic-gate {
571*7c478bd9Sstevel@tonic-gate 	xmlNodePtr cur;
572*7c478bd9Sstevel@tonic-gate 
573*7c478bd9Sstevel@tonic-gate 	if (handle == NULL)
574*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
575*7c478bd9Sstevel@tonic-gate 
576*7c478bd9Sstevel@tonic-gate 	cur = xmlDocGetRootElement(handle->zone_dh_doc);
577*7c478bd9Sstevel@tonic-gate 	if (cur == NULL) {
578*7c478bd9Sstevel@tonic-gate 		zonecfg_fini_handle(handle);
579*7c478bd9Sstevel@tonic-gate 		return (Z_EMPTY_DOCUMENT);
580*7c478bd9Sstevel@tonic-gate 	}
581*7c478bd9Sstevel@tonic-gate 
582*7c478bd9Sstevel@tonic-gate 	if (xmlStrcmp(cur->name, DTD_ELEM_ZONE)) {
583*7c478bd9Sstevel@tonic-gate 		zonecfg_fini_handle(handle);
584*7c478bd9Sstevel@tonic-gate 		return (Z_WRONG_DOC_TYPE);
585*7c478bd9Sstevel@tonic-gate 	}
586*7c478bd9Sstevel@tonic-gate 	if (xmlSetProp(cur, DTD_ATTR_AUTOBOOT, autoboot ?
587*7c478bd9Sstevel@tonic-gate 	    (const xmlChar *) DTD_ENTITY_TRUE :
588*7c478bd9Sstevel@tonic-gate 	    (const xmlChar *) DTD_ENTITY_FALSE) == NULL)
589*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
590*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
591*7c478bd9Sstevel@tonic-gate }
592*7c478bd9Sstevel@tonic-gate 
593*7c478bd9Sstevel@tonic-gate int
594*7c478bd9Sstevel@tonic-gate zonecfg_get_pool(zone_dochandle_t handle, char *pool, size_t poolsize)
595*7c478bd9Sstevel@tonic-gate {
596*7c478bd9Sstevel@tonic-gate 	xmlNodePtr cur;
597*7c478bd9Sstevel@tonic-gate 	xmlChar *property;
598*7c478bd9Sstevel@tonic-gate 	size_t srcsize;
599*7c478bd9Sstevel@tonic-gate 
600*7c478bd9Sstevel@tonic-gate 	if (handle == NULL)
601*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
602*7c478bd9Sstevel@tonic-gate 
603*7c478bd9Sstevel@tonic-gate 	cur = xmlDocGetRootElement(handle->zone_dh_doc);
604*7c478bd9Sstevel@tonic-gate 	if (cur == NULL) {
605*7c478bd9Sstevel@tonic-gate 		zonecfg_fini_handle(handle);
606*7c478bd9Sstevel@tonic-gate 		return (Z_EMPTY_DOCUMENT);
607*7c478bd9Sstevel@tonic-gate 	}
608*7c478bd9Sstevel@tonic-gate 
609*7c478bd9Sstevel@tonic-gate 	if (xmlStrcmp(cur->name, DTD_ELEM_ZONE)) {
610*7c478bd9Sstevel@tonic-gate 		zonecfg_fini_handle(handle);
611*7c478bd9Sstevel@tonic-gate 		return (Z_WRONG_DOC_TYPE);
612*7c478bd9Sstevel@tonic-gate 	}
613*7c478bd9Sstevel@tonic-gate 	property = xmlGetProp(cur, DTD_ATTR_POOL);
614*7c478bd9Sstevel@tonic-gate 	/*
615*7c478bd9Sstevel@tonic-gate 	 * Because the DTD lists the pool as 'CDATA ""', we will get exactly
616*7c478bd9Sstevel@tonic-gate 	 * that even if no pool is in the configuratin: a zero length string.
617*7c478bd9Sstevel@tonic-gate 	 * So the NULL check below should (in theory) never trigger, but we
618*7c478bd9Sstevel@tonic-gate 	 * have it for consistency with other _get_X() functions.
619*7c478bd9Sstevel@tonic-gate 	 */
620*7c478bd9Sstevel@tonic-gate 	if (property == NULL)
621*7c478bd9Sstevel@tonic-gate 		return (Z_NO_ENTRY);
622*7c478bd9Sstevel@tonic-gate 	srcsize = strlcpy(pool, (char *)property, poolsize);
623*7c478bd9Sstevel@tonic-gate 	xmlFree(property);
624*7c478bd9Sstevel@tonic-gate 	if (srcsize >= poolsize)
625*7c478bd9Sstevel@tonic-gate 		return (Z_TOO_BIG);
626*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
627*7c478bd9Sstevel@tonic-gate }
628*7c478bd9Sstevel@tonic-gate 
629*7c478bd9Sstevel@tonic-gate int
630*7c478bd9Sstevel@tonic-gate zonecfg_set_pool(zone_dochandle_t handle, char *pool)
631*7c478bd9Sstevel@tonic-gate {
632*7c478bd9Sstevel@tonic-gate 	xmlNodePtr cur;
633*7c478bd9Sstevel@tonic-gate 
634*7c478bd9Sstevel@tonic-gate 	if (handle == NULL || pool == NULL)
635*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
636*7c478bd9Sstevel@tonic-gate 
637*7c478bd9Sstevel@tonic-gate 	cur = xmlDocGetRootElement(handle->zone_dh_doc);
638*7c478bd9Sstevel@tonic-gate 	if (cur == NULL) {
639*7c478bd9Sstevel@tonic-gate 		zonecfg_fini_handle(handle);
640*7c478bd9Sstevel@tonic-gate 		return (Z_EMPTY_DOCUMENT);
641*7c478bd9Sstevel@tonic-gate 	}
642*7c478bd9Sstevel@tonic-gate 
643*7c478bd9Sstevel@tonic-gate 	if (xmlStrcmp(cur->name, DTD_ELEM_ZONE)) {
644*7c478bd9Sstevel@tonic-gate 		zonecfg_fini_handle(handle);
645*7c478bd9Sstevel@tonic-gate 		return (Z_WRONG_DOC_TYPE);
646*7c478bd9Sstevel@tonic-gate 	}
647*7c478bd9Sstevel@tonic-gate 	if (xmlSetProp(cur, DTD_ATTR_POOL, (const xmlChar *) pool) == NULL)
648*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
649*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
650*7c478bd9Sstevel@tonic-gate }
651*7c478bd9Sstevel@tonic-gate 
652*7c478bd9Sstevel@tonic-gate static int
653*7c478bd9Sstevel@tonic-gate newprop(zone_dochandle_t handle, xmlNodePtr node, const xmlChar *attrname,
654*7c478bd9Sstevel@tonic-gate     char *src)
655*7c478bd9Sstevel@tonic-gate {
656*7c478bd9Sstevel@tonic-gate 	xmlAttrPtr newattr;
657*7c478bd9Sstevel@tonic-gate 
658*7c478bd9Sstevel@tonic-gate 	newattr = xmlNewProp(node, attrname, (xmlChar *)src);
659*7c478bd9Sstevel@tonic-gate 	if (newattr == NULL) {
660*7c478bd9Sstevel@tonic-gate 		xmlUnlinkNode(node);
661*7c478bd9Sstevel@tonic-gate 		xmlFreeNode(node);
662*7c478bd9Sstevel@tonic-gate 		zonecfg_fini_handle(handle);
663*7c478bd9Sstevel@tonic-gate 		return (Z_BAD_PROPERTY);
664*7c478bd9Sstevel@tonic-gate 	}
665*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
666*7c478bd9Sstevel@tonic-gate }
667*7c478bd9Sstevel@tonic-gate 
668*7c478bd9Sstevel@tonic-gate static int
669*7c478bd9Sstevel@tonic-gate zonecfg_add_filesystem_core(zone_dochandle_t handle, struct zone_fstab *tabptr)
670*7c478bd9Sstevel@tonic-gate {
671*7c478bd9Sstevel@tonic-gate 	xmlNodePtr newnode, cur = handle->zone_dh_cur, options_node;
672*7c478bd9Sstevel@tonic-gate 	zone_fsopt_t *ptr;
673*7c478bd9Sstevel@tonic-gate 	int err;
674*7c478bd9Sstevel@tonic-gate 
675*7c478bd9Sstevel@tonic-gate 	newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_FS, NULL);
676*7c478bd9Sstevel@tonic-gate 	if ((err = newprop(handle, newnode, DTD_ATTR_SPECIAL,
677*7c478bd9Sstevel@tonic-gate 	    tabptr->zone_fs_special)) != Z_OK)
678*7c478bd9Sstevel@tonic-gate 		return (err);
679*7c478bd9Sstevel@tonic-gate 	if (tabptr->zone_fs_raw[0] != '\0' &&
680*7c478bd9Sstevel@tonic-gate 	    (err = newprop(handle, newnode, DTD_ATTR_RAW,
681*7c478bd9Sstevel@tonic-gate 	    tabptr->zone_fs_raw)) != Z_OK)
682*7c478bd9Sstevel@tonic-gate 		return (err);
683*7c478bd9Sstevel@tonic-gate 	if ((err = newprop(handle, newnode, DTD_ATTR_DIR,
684*7c478bd9Sstevel@tonic-gate 	    tabptr->zone_fs_dir)) != Z_OK)
685*7c478bd9Sstevel@tonic-gate 		return (err);
686*7c478bd9Sstevel@tonic-gate 	if ((err = newprop(handle, newnode, DTD_ATTR_TYPE,
687*7c478bd9Sstevel@tonic-gate 	    tabptr->zone_fs_type)) != Z_OK)
688*7c478bd9Sstevel@tonic-gate 		return (err);
689*7c478bd9Sstevel@tonic-gate 	if (tabptr->zone_fs_options != NULL) {
690*7c478bd9Sstevel@tonic-gate 		for (ptr = tabptr->zone_fs_options; ptr != NULL;
691*7c478bd9Sstevel@tonic-gate 		    ptr = ptr->zone_fsopt_next) {
692*7c478bd9Sstevel@tonic-gate 			options_node = xmlNewTextChild(newnode, NULL,
693*7c478bd9Sstevel@tonic-gate 			    DTD_ELEM_FSOPTION, NULL);
694*7c478bd9Sstevel@tonic-gate 			if ((err = newprop(handle, options_node, DTD_ATTR_NAME,
695*7c478bd9Sstevel@tonic-gate 			    ptr->zone_fsopt_opt)) != Z_OK)
696*7c478bd9Sstevel@tonic-gate 				return (err);
697*7c478bd9Sstevel@tonic-gate 		}
698*7c478bd9Sstevel@tonic-gate 	}
699*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
700*7c478bd9Sstevel@tonic-gate }
701*7c478bd9Sstevel@tonic-gate 
702*7c478bd9Sstevel@tonic-gate int
703*7c478bd9Sstevel@tonic-gate zonecfg_add_filesystem(zone_dochandle_t handle, struct zone_fstab *tabptr)
704*7c478bd9Sstevel@tonic-gate {
705*7c478bd9Sstevel@tonic-gate 	int err;
706*7c478bd9Sstevel@tonic-gate 
707*7c478bd9Sstevel@tonic-gate 	if (tabptr == NULL)
708*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
709*7c478bd9Sstevel@tonic-gate 
710*7c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
711*7c478bd9Sstevel@tonic-gate 		return (err);
712*7c478bd9Sstevel@tonic-gate 
713*7c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_add_filesystem_core(handle, tabptr)) != Z_OK)
714*7c478bd9Sstevel@tonic-gate 		return (err);
715*7c478bd9Sstevel@tonic-gate 
716*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
717*7c478bd9Sstevel@tonic-gate }
718*7c478bd9Sstevel@tonic-gate 
719*7c478bd9Sstevel@tonic-gate static int
720*7c478bd9Sstevel@tonic-gate zonecfg_add_ipd_core(zone_dochandle_t handle, struct zone_fstab *tabptr)
721*7c478bd9Sstevel@tonic-gate {
722*7c478bd9Sstevel@tonic-gate 	xmlNodePtr newnode, cur = handle->zone_dh_cur;
723*7c478bd9Sstevel@tonic-gate 	int err;
724*7c478bd9Sstevel@tonic-gate 
725*7c478bd9Sstevel@tonic-gate 	newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_IPD, NULL);
726*7c478bd9Sstevel@tonic-gate 	if ((err = newprop(handle, newnode, DTD_ATTR_DIR,
727*7c478bd9Sstevel@tonic-gate 	    tabptr->zone_fs_dir)) != Z_OK)
728*7c478bd9Sstevel@tonic-gate 		return (err);
729*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
730*7c478bd9Sstevel@tonic-gate }
731*7c478bd9Sstevel@tonic-gate 
732*7c478bd9Sstevel@tonic-gate int
733*7c478bd9Sstevel@tonic-gate zonecfg_add_ipd(zone_dochandle_t handle, struct zone_fstab *tabptr)
734*7c478bd9Sstevel@tonic-gate {
735*7c478bd9Sstevel@tonic-gate 	int err;
736*7c478bd9Sstevel@tonic-gate 
737*7c478bd9Sstevel@tonic-gate 	if (tabptr == NULL)
738*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
739*7c478bd9Sstevel@tonic-gate 
740*7c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
741*7c478bd9Sstevel@tonic-gate 		return (err);
742*7c478bd9Sstevel@tonic-gate 
743*7c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_add_ipd_core(handle, tabptr)) != Z_OK)
744*7c478bd9Sstevel@tonic-gate 		return (err);
745*7c478bd9Sstevel@tonic-gate 
746*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
747*7c478bd9Sstevel@tonic-gate }
748*7c478bd9Sstevel@tonic-gate 
749*7c478bd9Sstevel@tonic-gate int
750*7c478bd9Sstevel@tonic-gate zonecfg_add_fs_option(struct zone_fstab *tabptr, char *option)
751*7c478bd9Sstevel@tonic-gate {
752*7c478bd9Sstevel@tonic-gate 	zone_fsopt_t *last, *old, *new;
753*7c478bd9Sstevel@tonic-gate 
754*7c478bd9Sstevel@tonic-gate 	last = tabptr->zone_fs_options;
755*7c478bd9Sstevel@tonic-gate 	for (old = last; old != NULL; old = old->zone_fsopt_next)
756*7c478bd9Sstevel@tonic-gate 		last = old;	/* walk to the end of the list */
757*7c478bd9Sstevel@tonic-gate 	new = (zone_fsopt_t *)malloc(sizeof (zone_fsopt_t));
758*7c478bd9Sstevel@tonic-gate 	if (new == NULL)
759*7c478bd9Sstevel@tonic-gate 		return (Z_NOMEM);
760*7c478bd9Sstevel@tonic-gate 	(void) strlcpy(new->zone_fsopt_opt, option,
761*7c478bd9Sstevel@tonic-gate 	    sizeof (new->zone_fsopt_opt));
762*7c478bd9Sstevel@tonic-gate 	new->zone_fsopt_next = NULL;
763*7c478bd9Sstevel@tonic-gate 	if (last == NULL)
764*7c478bd9Sstevel@tonic-gate 		tabptr->zone_fs_options = new;
765*7c478bd9Sstevel@tonic-gate 	else
766*7c478bd9Sstevel@tonic-gate 		last->zone_fsopt_next = new;
767*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
768*7c478bd9Sstevel@tonic-gate }
769*7c478bd9Sstevel@tonic-gate 
770*7c478bd9Sstevel@tonic-gate int
771*7c478bd9Sstevel@tonic-gate zonecfg_remove_fs_option(struct zone_fstab *tabptr, char *option)
772*7c478bd9Sstevel@tonic-gate {
773*7c478bd9Sstevel@tonic-gate 	zone_fsopt_t *last, *this, *next;
774*7c478bd9Sstevel@tonic-gate 
775*7c478bd9Sstevel@tonic-gate 	last = tabptr->zone_fs_options;
776*7c478bd9Sstevel@tonic-gate 	for (this = last; this != NULL; this = this->zone_fsopt_next) {
777*7c478bd9Sstevel@tonic-gate 		if (strcmp(this->zone_fsopt_opt, option) == 0) {
778*7c478bd9Sstevel@tonic-gate 			next = this->zone_fsopt_next;
779*7c478bd9Sstevel@tonic-gate 			if (this == tabptr->zone_fs_options)
780*7c478bd9Sstevel@tonic-gate 				tabptr->zone_fs_options = next;
781*7c478bd9Sstevel@tonic-gate 			else
782*7c478bd9Sstevel@tonic-gate 				last->zone_fsopt_next = next;
783*7c478bd9Sstevel@tonic-gate 			free(this);
784*7c478bd9Sstevel@tonic-gate 			return (Z_OK);
785*7c478bd9Sstevel@tonic-gate 		} else
786*7c478bd9Sstevel@tonic-gate 			last = this;
787*7c478bd9Sstevel@tonic-gate 	}
788*7c478bd9Sstevel@tonic-gate 	return (Z_NO_PROPERTY_ID);
789*7c478bd9Sstevel@tonic-gate }
790*7c478bd9Sstevel@tonic-gate 
791*7c478bd9Sstevel@tonic-gate void
792*7c478bd9Sstevel@tonic-gate zonecfg_free_fs_option_list(zone_fsopt_t *list)
793*7c478bd9Sstevel@tonic-gate {
794*7c478bd9Sstevel@tonic-gate 	zone_fsopt_t *this, *next;
795*7c478bd9Sstevel@tonic-gate 
796*7c478bd9Sstevel@tonic-gate 	for (this = list; this != NULL; this = next) {
797*7c478bd9Sstevel@tonic-gate 		next = this->zone_fsopt_next;
798*7c478bd9Sstevel@tonic-gate 		free(this);
799*7c478bd9Sstevel@tonic-gate 	}
800*7c478bd9Sstevel@tonic-gate }
801*7c478bd9Sstevel@tonic-gate 
802*7c478bd9Sstevel@tonic-gate void
803*7c478bd9Sstevel@tonic-gate zonecfg_free_rctl_value_list(struct zone_rctlvaltab *valtab)
804*7c478bd9Sstevel@tonic-gate {
805*7c478bd9Sstevel@tonic-gate 	if (valtab == NULL)
806*7c478bd9Sstevel@tonic-gate 		return;
807*7c478bd9Sstevel@tonic-gate 	zonecfg_free_rctl_value_list(valtab->zone_rctlval_next);
808*7c478bd9Sstevel@tonic-gate 	free(valtab);
809*7c478bd9Sstevel@tonic-gate }
810*7c478bd9Sstevel@tonic-gate 
811*7c478bd9Sstevel@tonic-gate static boolean_t
812*7c478bd9Sstevel@tonic-gate match_prop(xmlNodePtr cur, const xmlChar *attr, char *user_prop)
813*7c478bd9Sstevel@tonic-gate {
814*7c478bd9Sstevel@tonic-gate 	xmlChar *gotten_prop;
815*7c478bd9Sstevel@tonic-gate 	int prop_result;
816*7c478bd9Sstevel@tonic-gate 
817*7c478bd9Sstevel@tonic-gate 	gotten_prop = xmlGetProp(cur, attr);
818*7c478bd9Sstevel@tonic-gate 	if (gotten_prop == NULL)	/* shouldn't happen */
819*7c478bd9Sstevel@tonic-gate 		return (B_FALSE);
820*7c478bd9Sstevel@tonic-gate 	prop_result = xmlStrcmp(gotten_prop, (const xmlChar *) user_prop);
821*7c478bd9Sstevel@tonic-gate 	xmlFree(gotten_prop);
822*7c478bd9Sstevel@tonic-gate 	return ((prop_result == 0));
823*7c478bd9Sstevel@tonic-gate }
824*7c478bd9Sstevel@tonic-gate 
825*7c478bd9Sstevel@tonic-gate static int
826*7c478bd9Sstevel@tonic-gate zonecfg_delete_filesystem_core(zone_dochandle_t handle,
827*7c478bd9Sstevel@tonic-gate     struct zone_fstab *tabptr)
828*7c478bd9Sstevel@tonic-gate {
829*7c478bd9Sstevel@tonic-gate 	xmlNodePtr cur = handle->zone_dh_cur;
830*7c478bd9Sstevel@tonic-gate 	boolean_t dir_match, spec_match, raw_match, type_match;
831*7c478bd9Sstevel@tonic-gate 
832*7c478bd9Sstevel@tonic-gate 	for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
833*7c478bd9Sstevel@tonic-gate 		if (xmlStrcmp(cur->name, DTD_ELEM_FS))
834*7c478bd9Sstevel@tonic-gate 			continue;
835*7c478bd9Sstevel@tonic-gate 		dir_match = match_prop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir);
836*7c478bd9Sstevel@tonic-gate 		spec_match = match_prop(cur, DTD_ATTR_SPECIAL,
837*7c478bd9Sstevel@tonic-gate 		    tabptr->zone_fs_special);
838*7c478bd9Sstevel@tonic-gate 		raw_match = match_prop(cur, DTD_ATTR_RAW,
839*7c478bd9Sstevel@tonic-gate 		    tabptr->zone_fs_raw);
840*7c478bd9Sstevel@tonic-gate 		type_match = match_prop(cur, DTD_ATTR_TYPE,
841*7c478bd9Sstevel@tonic-gate 		    tabptr->zone_fs_type);
842*7c478bd9Sstevel@tonic-gate 		if (dir_match && spec_match && raw_match && type_match) {
843*7c478bd9Sstevel@tonic-gate 			xmlUnlinkNode(cur);
844*7c478bd9Sstevel@tonic-gate 			xmlFreeNode(cur);
845*7c478bd9Sstevel@tonic-gate 			return (Z_OK);
846*7c478bd9Sstevel@tonic-gate 		}
847*7c478bd9Sstevel@tonic-gate 	}
848*7c478bd9Sstevel@tonic-gate 	return (Z_NO_RESOURCE_ID);
849*7c478bd9Sstevel@tonic-gate }
850*7c478bd9Sstevel@tonic-gate 
851*7c478bd9Sstevel@tonic-gate int
852*7c478bd9Sstevel@tonic-gate zonecfg_delete_filesystem(zone_dochandle_t handle, struct zone_fstab *tabptr)
853*7c478bd9Sstevel@tonic-gate {
854*7c478bd9Sstevel@tonic-gate 	int err;
855*7c478bd9Sstevel@tonic-gate 
856*7c478bd9Sstevel@tonic-gate 	if (tabptr == NULL)
857*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
858*7c478bd9Sstevel@tonic-gate 
859*7c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
860*7c478bd9Sstevel@tonic-gate 		return (err);
861*7c478bd9Sstevel@tonic-gate 
862*7c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_delete_filesystem_core(handle, tabptr)) != Z_OK)
863*7c478bd9Sstevel@tonic-gate 		return (err);
864*7c478bd9Sstevel@tonic-gate 
865*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
866*7c478bd9Sstevel@tonic-gate }
867*7c478bd9Sstevel@tonic-gate 
868*7c478bd9Sstevel@tonic-gate int
869*7c478bd9Sstevel@tonic-gate zonecfg_modify_filesystem(
870*7c478bd9Sstevel@tonic-gate 	zone_dochandle_t handle,
871*7c478bd9Sstevel@tonic-gate 	struct zone_fstab *oldtabptr,
872*7c478bd9Sstevel@tonic-gate 	struct zone_fstab *newtabptr)
873*7c478bd9Sstevel@tonic-gate {
874*7c478bd9Sstevel@tonic-gate 	int err;
875*7c478bd9Sstevel@tonic-gate 
876*7c478bd9Sstevel@tonic-gate 	if (oldtabptr == NULL || newtabptr == NULL)
877*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
878*7c478bd9Sstevel@tonic-gate 
879*7c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
880*7c478bd9Sstevel@tonic-gate 		return (err);
881*7c478bd9Sstevel@tonic-gate 
882*7c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_delete_filesystem_core(handle, oldtabptr)) != Z_OK)
883*7c478bd9Sstevel@tonic-gate 		return (err);
884*7c478bd9Sstevel@tonic-gate 
885*7c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_add_filesystem_core(handle, newtabptr)) != Z_OK)
886*7c478bd9Sstevel@tonic-gate 		return (err);
887*7c478bd9Sstevel@tonic-gate 
888*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
889*7c478bd9Sstevel@tonic-gate }
890*7c478bd9Sstevel@tonic-gate 
891*7c478bd9Sstevel@tonic-gate static int
892*7c478bd9Sstevel@tonic-gate zonecfg_delete_ipd_core(zone_dochandle_t handle, struct zone_fstab *tabptr)
893*7c478bd9Sstevel@tonic-gate {
894*7c478bd9Sstevel@tonic-gate 	xmlNodePtr cur = handle->zone_dh_cur;
895*7c478bd9Sstevel@tonic-gate 
896*7c478bd9Sstevel@tonic-gate 	for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
897*7c478bd9Sstevel@tonic-gate 		if (xmlStrcmp(cur->name, DTD_ELEM_IPD))
898*7c478bd9Sstevel@tonic-gate 			continue;
899*7c478bd9Sstevel@tonic-gate 		if (match_prop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir)) {
900*7c478bd9Sstevel@tonic-gate 			xmlUnlinkNode(cur);
901*7c478bd9Sstevel@tonic-gate 			xmlFreeNode(cur);
902*7c478bd9Sstevel@tonic-gate 			return (Z_OK);
903*7c478bd9Sstevel@tonic-gate 		}
904*7c478bd9Sstevel@tonic-gate 	}
905*7c478bd9Sstevel@tonic-gate 	return (Z_NO_RESOURCE_ID);
906*7c478bd9Sstevel@tonic-gate }
907*7c478bd9Sstevel@tonic-gate 
908*7c478bd9Sstevel@tonic-gate int
909*7c478bd9Sstevel@tonic-gate zonecfg_delete_ipd(zone_dochandle_t handle, struct zone_fstab *tabptr)
910*7c478bd9Sstevel@tonic-gate {
911*7c478bd9Sstevel@tonic-gate 	int err;
912*7c478bd9Sstevel@tonic-gate 
913*7c478bd9Sstevel@tonic-gate 	if (tabptr == NULL)
914*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
915*7c478bd9Sstevel@tonic-gate 
916*7c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
917*7c478bd9Sstevel@tonic-gate 		return (err);
918*7c478bd9Sstevel@tonic-gate 
919*7c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_delete_ipd_core(handle, tabptr)) != Z_OK)
920*7c478bd9Sstevel@tonic-gate 		return (err);
921*7c478bd9Sstevel@tonic-gate 
922*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
923*7c478bd9Sstevel@tonic-gate }
924*7c478bd9Sstevel@tonic-gate 
925*7c478bd9Sstevel@tonic-gate int
926*7c478bd9Sstevel@tonic-gate zonecfg_modify_ipd(zone_dochandle_t handle, struct zone_fstab *oldtabptr,
927*7c478bd9Sstevel@tonic-gate     struct zone_fstab *newtabptr)
928*7c478bd9Sstevel@tonic-gate {
929*7c478bd9Sstevel@tonic-gate 	int err;
930*7c478bd9Sstevel@tonic-gate 
931*7c478bd9Sstevel@tonic-gate 	if (oldtabptr == NULL || newtabptr == NULL)
932*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
933*7c478bd9Sstevel@tonic-gate 
934*7c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
935*7c478bd9Sstevel@tonic-gate 		return (err);
936*7c478bd9Sstevel@tonic-gate 
937*7c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_delete_ipd_core(handle, oldtabptr)) != Z_OK)
938*7c478bd9Sstevel@tonic-gate 		return (err);
939*7c478bd9Sstevel@tonic-gate 
940*7c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_add_ipd_core(handle, newtabptr)) != Z_OK)
941*7c478bd9Sstevel@tonic-gate 		return (err);
942*7c478bd9Sstevel@tonic-gate 
943*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
944*7c478bd9Sstevel@tonic-gate }
945*7c478bd9Sstevel@tonic-gate 
946*7c478bd9Sstevel@tonic-gate static int
947*7c478bd9Sstevel@tonic-gate fetchprop(xmlNodePtr cur, const xmlChar *propname, char *dst, size_t dstsize)
948*7c478bd9Sstevel@tonic-gate {
949*7c478bd9Sstevel@tonic-gate 	xmlChar *property;
950*7c478bd9Sstevel@tonic-gate 	size_t srcsize;
951*7c478bd9Sstevel@tonic-gate 
952*7c478bd9Sstevel@tonic-gate 	if ((property = xmlGetProp(cur, propname)) == NULL)
953*7c478bd9Sstevel@tonic-gate 		return (Z_BAD_PROPERTY);
954*7c478bd9Sstevel@tonic-gate 	srcsize = strlcpy(dst, (char *)property, dstsize);
955*7c478bd9Sstevel@tonic-gate 	xmlFree(property);
956*7c478bd9Sstevel@tonic-gate 	if (srcsize >= dstsize)
957*7c478bd9Sstevel@tonic-gate 		return (Z_TOO_BIG);
958*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
959*7c478bd9Sstevel@tonic-gate }
960*7c478bd9Sstevel@tonic-gate 
961*7c478bd9Sstevel@tonic-gate int
962*7c478bd9Sstevel@tonic-gate zonecfg_lookup_filesystem(
963*7c478bd9Sstevel@tonic-gate 	zone_dochandle_t handle,
964*7c478bd9Sstevel@tonic-gate 	struct zone_fstab *tabptr)
965*7c478bd9Sstevel@tonic-gate {
966*7c478bd9Sstevel@tonic-gate 	xmlNodePtr cur, options, firstmatch;
967*7c478bd9Sstevel@tonic-gate 	int err;
968*7c478bd9Sstevel@tonic-gate 	char dirname[MAXPATHLEN], special[MAXPATHLEN], raw[MAXPATHLEN];
969*7c478bd9Sstevel@tonic-gate 	char type[FSTYPSZ];
970*7c478bd9Sstevel@tonic-gate 	char options_str[MAX_MNTOPT_STR];
971*7c478bd9Sstevel@tonic-gate 
972*7c478bd9Sstevel@tonic-gate 	if (tabptr == NULL)
973*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
974*7c478bd9Sstevel@tonic-gate 
975*7c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
976*7c478bd9Sstevel@tonic-gate 		return (err);
977*7c478bd9Sstevel@tonic-gate 
978*7c478bd9Sstevel@tonic-gate 	/*
979*7c478bd9Sstevel@tonic-gate 	 * Walk the list of children looking for matches on any properties
980*7c478bd9Sstevel@tonic-gate 	 * specified in the fstab parameter.  If more than one resource
981*7c478bd9Sstevel@tonic-gate 	 * matches, we return Z_INSUFFICIENT_SPEC; if none match, we return
982*7c478bd9Sstevel@tonic-gate 	 * Z_NO_RESOURCE_ID.
983*7c478bd9Sstevel@tonic-gate 	 */
984*7c478bd9Sstevel@tonic-gate 	cur = handle->zone_dh_cur;
985*7c478bd9Sstevel@tonic-gate 	firstmatch = NULL;
986*7c478bd9Sstevel@tonic-gate 	for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
987*7c478bd9Sstevel@tonic-gate 		if (xmlStrcmp(cur->name, DTD_ELEM_FS))
988*7c478bd9Sstevel@tonic-gate 			continue;
989*7c478bd9Sstevel@tonic-gate 		if (strlen(tabptr->zone_fs_dir) > 0) {
990*7c478bd9Sstevel@tonic-gate 			if ((fetchprop(cur, DTD_ATTR_DIR, dirname,
991*7c478bd9Sstevel@tonic-gate 			    sizeof (dirname)) == Z_OK) &&
992*7c478bd9Sstevel@tonic-gate 			    (strcmp(tabptr->zone_fs_dir, dirname) == 0)) {
993*7c478bd9Sstevel@tonic-gate 				if (firstmatch == NULL)
994*7c478bd9Sstevel@tonic-gate 					firstmatch = cur;
995*7c478bd9Sstevel@tonic-gate 				else
996*7c478bd9Sstevel@tonic-gate 					return (Z_INSUFFICIENT_SPEC);
997*7c478bd9Sstevel@tonic-gate 			}
998*7c478bd9Sstevel@tonic-gate 		}
999*7c478bd9Sstevel@tonic-gate 		if (strlen(tabptr->zone_fs_special) > 0) {
1000*7c478bd9Sstevel@tonic-gate 			if ((fetchprop(cur, DTD_ATTR_SPECIAL, special,
1001*7c478bd9Sstevel@tonic-gate 			    sizeof (special)) == Z_OK)) {
1002*7c478bd9Sstevel@tonic-gate 				if (strcmp(tabptr->zone_fs_special,
1003*7c478bd9Sstevel@tonic-gate 				    special) == 0) {
1004*7c478bd9Sstevel@tonic-gate 					if (firstmatch == NULL)
1005*7c478bd9Sstevel@tonic-gate 						firstmatch = cur;
1006*7c478bd9Sstevel@tonic-gate 					else if (firstmatch != cur)
1007*7c478bd9Sstevel@tonic-gate 						return (Z_INSUFFICIENT_SPEC);
1008*7c478bd9Sstevel@tonic-gate 				} else {
1009*7c478bd9Sstevel@tonic-gate 					/*
1010*7c478bd9Sstevel@tonic-gate 					 * If another property matched but this
1011*7c478bd9Sstevel@tonic-gate 					 * one doesn't then reset firstmatch.
1012*7c478bd9Sstevel@tonic-gate 					 */
1013*7c478bd9Sstevel@tonic-gate 					if (firstmatch == cur)
1014*7c478bd9Sstevel@tonic-gate 						firstmatch = NULL;
1015*7c478bd9Sstevel@tonic-gate 				}
1016*7c478bd9Sstevel@tonic-gate 			}
1017*7c478bd9Sstevel@tonic-gate 		}
1018*7c478bd9Sstevel@tonic-gate 		if (strlen(tabptr->zone_fs_raw) > 0) {
1019*7c478bd9Sstevel@tonic-gate 			if ((fetchprop(cur, DTD_ATTR_RAW, raw,
1020*7c478bd9Sstevel@tonic-gate 			    sizeof (raw)) == Z_OK)) {
1021*7c478bd9Sstevel@tonic-gate 				if (strcmp(tabptr->zone_fs_raw, raw) == 0) {
1022*7c478bd9Sstevel@tonic-gate 					if (firstmatch == NULL)
1023*7c478bd9Sstevel@tonic-gate 						firstmatch = cur;
1024*7c478bd9Sstevel@tonic-gate 					else if (firstmatch != cur)
1025*7c478bd9Sstevel@tonic-gate 						return (Z_INSUFFICIENT_SPEC);
1026*7c478bd9Sstevel@tonic-gate 				} else {
1027*7c478bd9Sstevel@tonic-gate 					/*
1028*7c478bd9Sstevel@tonic-gate 					 * If another property matched but this
1029*7c478bd9Sstevel@tonic-gate 					 * one doesn't then reset firstmatch.
1030*7c478bd9Sstevel@tonic-gate 					 */
1031*7c478bd9Sstevel@tonic-gate 					if (firstmatch == cur)
1032*7c478bd9Sstevel@tonic-gate 						firstmatch = NULL;
1033*7c478bd9Sstevel@tonic-gate 				}
1034*7c478bd9Sstevel@tonic-gate 			}
1035*7c478bd9Sstevel@tonic-gate 		}
1036*7c478bd9Sstevel@tonic-gate 		if (strlen(tabptr->zone_fs_type) > 0) {
1037*7c478bd9Sstevel@tonic-gate 			if ((fetchprop(cur, DTD_ATTR_TYPE, type,
1038*7c478bd9Sstevel@tonic-gate 			    sizeof (type)) == Z_OK)) {
1039*7c478bd9Sstevel@tonic-gate 				if (strcmp(tabptr->zone_fs_type, type) == 0) {
1040*7c478bd9Sstevel@tonic-gate 					if (firstmatch == NULL)
1041*7c478bd9Sstevel@tonic-gate 						firstmatch = cur;
1042*7c478bd9Sstevel@tonic-gate 					else if (firstmatch != cur)
1043*7c478bd9Sstevel@tonic-gate 						return (Z_INSUFFICIENT_SPEC);
1044*7c478bd9Sstevel@tonic-gate 				} else {
1045*7c478bd9Sstevel@tonic-gate 					/*
1046*7c478bd9Sstevel@tonic-gate 					 * If another property matched but this
1047*7c478bd9Sstevel@tonic-gate 					 * one doesn't then reset firstmatch.
1048*7c478bd9Sstevel@tonic-gate 					 */
1049*7c478bd9Sstevel@tonic-gate 					if (firstmatch == cur)
1050*7c478bd9Sstevel@tonic-gate 						firstmatch = NULL;
1051*7c478bd9Sstevel@tonic-gate 				}
1052*7c478bd9Sstevel@tonic-gate 			}
1053*7c478bd9Sstevel@tonic-gate 		}
1054*7c478bd9Sstevel@tonic-gate 	}
1055*7c478bd9Sstevel@tonic-gate 
1056*7c478bd9Sstevel@tonic-gate 	if (firstmatch == NULL)
1057*7c478bd9Sstevel@tonic-gate 		return (Z_NO_RESOURCE_ID);
1058*7c478bd9Sstevel@tonic-gate 
1059*7c478bd9Sstevel@tonic-gate 	cur = firstmatch;
1060*7c478bd9Sstevel@tonic-gate 
1061*7c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir,
1062*7c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_fs_dir))) != Z_OK)
1063*7c478bd9Sstevel@tonic-gate 		return (err);
1064*7c478bd9Sstevel@tonic-gate 
1065*7c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_SPECIAL, tabptr->zone_fs_special,
1066*7c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_fs_special))) != Z_OK)
1067*7c478bd9Sstevel@tonic-gate 		return (err);
1068*7c478bd9Sstevel@tonic-gate 
1069*7c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_RAW, tabptr->zone_fs_raw,
1070*7c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_fs_raw))) != Z_OK)
1071*7c478bd9Sstevel@tonic-gate 		return (err);
1072*7c478bd9Sstevel@tonic-gate 
1073*7c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_TYPE, tabptr->zone_fs_type,
1074*7c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_fs_type))) != Z_OK)
1075*7c478bd9Sstevel@tonic-gate 		return (err);
1076*7c478bd9Sstevel@tonic-gate 
1077*7c478bd9Sstevel@tonic-gate 	/* options are optional */
1078*7c478bd9Sstevel@tonic-gate 	tabptr->zone_fs_options = NULL;
1079*7c478bd9Sstevel@tonic-gate 	for (options = cur->xmlChildrenNode; options != NULL;
1080*7c478bd9Sstevel@tonic-gate 	    options = options->next) {
1081*7c478bd9Sstevel@tonic-gate 		if ((fetchprop(options, DTD_ATTR_NAME, options_str,
1082*7c478bd9Sstevel@tonic-gate 		    sizeof (options_str)) != Z_OK))
1083*7c478bd9Sstevel@tonic-gate 			break;
1084*7c478bd9Sstevel@tonic-gate 		if (zonecfg_add_fs_option(tabptr, options_str) != Z_OK)
1085*7c478bd9Sstevel@tonic-gate 			break;
1086*7c478bd9Sstevel@tonic-gate 	}
1087*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
1088*7c478bd9Sstevel@tonic-gate }
1089*7c478bd9Sstevel@tonic-gate 
1090*7c478bd9Sstevel@tonic-gate int
1091*7c478bd9Sstevel@tonic-gate zonecfg_lookup_ipd(zone_dochandle_t handle, struct zone_fstab *tabptr)
1092*7c478bd9Sstevel@tonic-gate {
1093*7c478bd9Sstevel@tonic-gate 	xmlNodePtr cur, match;
1094*7c478bd9Sstevel@tonic-gate 	int err;
1095*7c478bd9Sstevel@tonic-gate 	char dirname[MAXPATHLEN];
1096*7c478bd9Sstevel@tonic-gate 
1097*7c478bd9Sstevel@tonic-gate 	if (tabptr == NULL)
1098*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
1099*7c478bd9Sstevel@tonic-gate 
1100*7c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
1101*7c478bd9Sstevel@tonic-gate 		return (err);
1102*7c478bd9Sstevel@tonic-gate 
1103*7c478bd9Sstevel@tonic-gate 	/*
1104*7c478bd9Sstevel@tonic-gate 	 * General algorithm:
1105*7c478bd9Sstevel@tonic-gate 	 * Walk the list of children looking for matches on any properties
1106*7c478bd9Sstevel@tonic-gate 	 * specified in the fstab parameter.  If more than one resource
1107*7c478bd9Sstevel@tonic-gate 	 * matches, we return Z_INSUFFICIENT_SPEC; if none match, we return
1108*7c478bd9Sstevel@tonic-gate 	 * Z_NO_RESOURCE_ID.
1109*7c478bd9Sstevel@tonic-gate 	 */
1110*7c478bd9Sstevel@tonic-gate 	cur = handle->zone_dh_cur;
1111*7c478bd9Sstevel@tonic-gate 	match = NULL;
1112*7c478bd9Sstevel@tonic-gate 	for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
1113*7c478bd9Sstevel@tonic-gate 		if (xmlStrcmp(cur->name, DTD_ELEM_IPD))
1114*7c478bd9Sstevel@tonic-gate 			continue;
1115*7c478bd9Sstevel@tonic-gate 		if (strlen(tabptr->zone_fs_dir) > 0) {
1116*7c478bd9Sstevel@tonic-gate 			if ((fetchprop(cur, DTD_ATTR_DIR, dirname,
1117*7c478bd9Sstevel@tonic-gate 			    sizeof (dirname)) == Z_OK) &&
1118*7c478bd9Sstevel@tonic-gate 			    (strcmp(tabptr->zone_fs_dir, dirname) == 0)) {
1119*7c478bd9Sstevel@tonic-gate 				if (match == NULL)
1120*7c478bd9Sstevel@tonic-gate 					match = cur;
1121*7c478bd9Sstevel@tonic-gate 				else
1122*7c478bd9Sstevel@tonic-gate 					return (Z_INSUFFICIENT_SPEC);
1123*7c478bd9Sstevel@tonic-gate 			}
1124*7c478bd9Sstevel@tonic-gate 		}
1125*7c478bd9Sstevel@tonic-gate 	}
1126*7c478bd9Sstevel@tonic-gate 
1127*7c478bd9Sstevel@tonic-gate 	if (match == NULL)
1128*7c478bd9Sstevel@tonic-gate 		return (Z_NO_RESOURCE_ID);
1129*7c478bd9Sstevel@tonic-gate 
1130*7c478bd9Sstevel@tonic-gate 	cur = match;
1131*7c478bd9Sstevel@tonic-gate 
1132*7c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir,
1133*7c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_fs_dir))) != Z_OK)
1134*7c478bd9Sstevel@tonic-gate 		return (err);
1135*7c478bd9Sstevel@tonic-gate 
1136*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
1137*7c478bd9Sstevel@tonic-gate }
1138*7c478bd9Sstevel@tonic-gate 
1139*7c478bd9Sstevel@tonic-gate /*
1140*7c478bd9Sstevel@tonic-gate  * Compare two IP addresses in string form.  Allow for the possibility that
1141*7c478bd9Sstevel@tonic-gate  * one might have "/<prefix-length>" at the end: allow a match on just the
1142*7c478bd9Sstevel@tonic-gate  * IP address (or host name) part.
1143*7c478bd9Sstevel@tonic-gate  */
1144*7c478bd9Sstevel@tonic-gate 
1145*7c478bd9Sstevel@tonic-gate boolean_t
1146*7c478bd9Sstevel@tonic-gate zonecfg_same_net_address(char *a1, char *a2)
1147*7c478bd9Sstevel@tonic-gate {
1148*7c478bd9Sstevel@tonic-gate 	char *slashp, *slashp1, *slashp2;
1149*7c478bd9Sstevel@tonic-gate 	int result;
1150*7c478bd9Sstevel@tonic-gate 
1151*7c478bd9Sstevel@tonic-gate 	if (strcmp(a1, a2) == 0)
1152*7c478bd9Sstevel@tonic-gate 		return (B_TRUE);
1153*7c478bd9Sstevel@tonic-gate 
1154*7c478bd9Sstevel@tonic-gate 	/*
1155*7c478bd9Sstevel@tonic-gate 	 * If neither has a slash or both do, they need to match to be
1156*7c478bd9Sstevel@tonic-gate 	 * considered the same, but they did not match above, so fail.
1157*7c478bd9Sstevel@tonic-gate 	 */
1158*7c478bd9Sstevel@tonic-gate 	slashp1 = strchr(a1, '/');
1159*7c478bd9Sstevel@tonic-gate 	slashp2 = strchr(a2, '/');
1160*7c478bd9Sstevel@tonic-gate 	if ((slashp1 == NULL && slashp2 == NULL) ||
1161*7c478bd9Sstevel@tonic-gate 	    (slashp1 != NULL && slashp2 != NULL))
1162*7c478bd9Sstevel@tonic-gate 		return (B_FALSE);
1163*7c478bd9Sstevel@tonic-gate 
1164*7c478bd9Sstevel@tonic-gate 	/*
1165*7c478bd9Sstevel@tonic-gate 	 * Only one had a slash: pick that one, zero out the slash, compare
1166*7c478bd9Sstevel@tonic-gate 	 * the "address only" strings, restore the slash, and return the
1167*7c478bd9Sstevel@tonic-gate 	 * result of the comparison.
1168*7c478bd9Sstevel@tonic-gate 	 */
1169*7c478bd9Sstevel@tonic-gate 	slashp = (slashp1 == NULL) ? slashp2 : slashp1;
1170*7c478bd9Sstevel@tonic-gate 	*slashp = '\0';
1171*7c478bd9Sstevel@tonic-gate 	result = strcmp(a1, a2);
1172*7c478bd9Sstevel@tonic-gate 	*slashp = '/';
1173*7c478bd9Sstevel@tonic-gate 	return ((result == 0));
1174*7c478bd9Sstevel@tonic-gate }
1175*7c478bd9Sstevel@tonic-gate 
1176*7c478bd9Sstevel@tonic-gate int
1177*7c478bd9Sstevel@tonic-gate zonecfg_valid_net_address(char *address, struct lifreq *lifr)
1178*7c478bd9Sstevel@tonic-gate {
1179*7c478bd9Sstevel@tonic-gate 	struct sockaddr_in *sin4;
1180*7c478bd9Sstevel@tonic-gate 	struct sockaddr_in6 *sin6;
1181*7c478bd9Sstevel@tonic-gate 	struct addrinfo hints, *result;
1182*7c478bd9Sstevel@tonic-gate 	char *slashp = strchr(address, '/');
1183*7c478bd9Sstevel@tonic-gate 
1184*7c478bd9Sstevel@tonic-gate 	bzero(lifr, sizeof (struct lifreq));
1185*7c478bd9Sstevel@tonic-gate 	sin4 = (struct sockaddr_in *)&lifr->lifr_addr;
1186*7c478bd9Sstevel@tonic-gate 	sin6 = (struct sockaddr_in6 *)&lifr->lifr_addr;
1187*7c478bd9Sstevel@tonic-gate 	if (slashp != NULL)
1188*7c478bd9Sstevel@tonic-gate 		*slashp = '\0';
1189*7c478bd9Sstevel@tonic-gate 	if (inet_pton(AF_INET, address, &sin4->sin_addr) == 1) {
1190*7c478bd9Sstevel@tonic-gate 		sin4->sin_family = AF_INET;
1191*7c478bd9Sstevel@tonic-gate 	} else if (inet_pton(AF_INET6, address, &sin6->sin6_addr) == 1) {
1192*7c478bd9Sstevel@tonic-gate 		if (slashp == NULL)
1193*7c478bd9Sstevel@tonic-gate 			return (Z_IPV6_ADDR_PREFIX_LEN);
1194*7c478bd9Sstevel@tonic-gate 		sin6->sin6_family = AF_INET6;
1195*7c478bd9Sstevel@tonic-gate 	} else {
1196*7c478bd9Sstevel@tonic-gate 		/* "address" may be a host name */
1197*7c478bd9Sstevel@tonic-gate 		(void) memset(&hints, 0, sizeof (hints));
1198*7c478bd9Sstevel@tonic-gate 		hints.ai_family = PF_INET;
1199*7c478bd9Sstevel@tonic-gate 		if (getaddrinfo(address, NULL, &hints, &result) != 0)
1200*7c478bd9Sstevel@tonic-gate 			return (Z_BOGUS_ADDRESS);
1201*7c478bd9Sstevel@tonic-gate 		sin4->sin_family = result->ai_family;
1202*7c478bd9Sstevel@tonic-gate 		(void) memcpy(&sin4->sin_addr,
1203*7c478bd9Sstevel@tonic-gate 		    /* LINTED E_BAD_PTR_CAST_ALIGN */
1204*7c478bd9Sstevel@tonic-gate 		    &((struct sockaddr_in *)result->ai_addr)->sin_addr,
1205*7c478bd9Sstevel@tonic-gate 		    sizeof (struct in_addr));
1206*7c478bd9Sstevel@tonic-gate 		freeaddrinfo(result);
1207*7c478bd9Sstevel@tonic-gate 	}
1208*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
1209*7c478bd9Sstevel@tonic-gate }
1210*7c478bd9Sstevel@tonic-gate 
1211*7c478bd9Sstevel@tonic-gate int
1212*7c478bd9Sstevel@tonic-gate zonecfg_lookup_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
1213*7c478bd9Sstevel@tonic-gate {
1214*7c478bd9Sstevel@tonic-gate 	xmlNodePtr cur, firstmatch;
1215*7c478bd9Sstevel@tonic-gate 	int err;
1216*7c478bd9Sstevel@tonic-gate 	char address[INET6_ADDRSTRLEN], physical[LIFNAMSIZ];
1217*7c478bd9Sstevel@tonic-gate 
1218*7c478bd9Sstevel@tonic-gate 	if (tabptr == NULL)
1219*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
1220*7c478bd9Sstevel@tonic-gate 
1221*7c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
1222*7c478bd9Sstevel@tonic-gate 		return (err);
1223*7c478bd9Sstevel@tonic-gate 
1224*7c478bd9Sstevel@tonic-gate 	cur = handle->zone_dh_cur;
1225*7c478bd9Sstevel@tonic-gate 	firstmatch = NULL;
1226*7c478bd9Sstevel@tonic-gate 	for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
1227*7c478bd9Sstevel@tonic-gate 		if (xmlStrcmp(cur->name, DTD_ELEM_NET))
1228*7c478bd9Sstevel@tonic-gate 			continue;
1229*7c478bd9Sstevel@tonic-gate 		if (strlen(tabptr->zone_nwif_physical) > 0) {
1230*7c478bd9Sstevel@tonic-gate 			if ((fetchprop(cur, DTD_ATTR_PHYSICAL, physical,
1231*7c478bd9Sstevel@tonic-gate 			    sizeof (physical)) == Z_OK) &&
1232*7c478bd9Sstevel@tonic-gate 			    (strcmp(tabptr->zone_nwif_physical,
1233*7c478bd9Sstevel@tonic-gate 			    physical) == 0)) {
1234*7c478bd9Sstevel@tonic-gate 				if (firstmatch == NULL)
1235*7c478bd9Sstevel@tonic-gate 					firstmatch = cur;
1236*7c478bd9Sstevel@tonic-gate 				else
1237*7c478bd9Sstevel@tonic-gate 					return (Z_INSUFFICIENT_SPEC);
1238*7c478bd9Sstevel@tonic-gate 			}
1239*7c478bd9Sstevel@tonic-gate 		}
1240*7c478bd9Sstevel@tonic-gate 		if (strlen(tabptr->zone_nwif_address) > 0) {
1241*7c478bd9Sstevel@tonic-gate 			if ((fetchprop(cur, DTD_ATTR_ADDRESS, address,
1242*7c478bd9Sstevel@tonic-gate 			    sizeof (address)) == Z_OK)) {
1243*7c478bd9Sstevel@tonic-gate 				if (zonecfg_same_net_address(
1244*7c478bd9Sstevel@tonic-gate 				    tabptr->zone_nwif_address, address)) {
1245*7c478bd9Sstevel@tonic-gate 					if (firstmatch == NULL)
1246*7c478bd9Sstevel@tonic-gate 						firstmatch = cur;
1247*7c478bd9Sstevel@tonic-gate 					else if (firstmatch != cur)
1248*7c478bd9Sstevel@tonic-gate 						return (Z_INSUFFICIENT_SPEC);
1249*7c478bd9Sstevel@tonic-gate 				} else {
1250*7c478bd9Sstevel@tonic-gate 					/*
1251*7c478bd9Sstevel@tonic-gate 					 * If another property matched but this
1252*7c478bd9Sstevel@tonic-gate 					 * one doesn't then reset firstmatch.
1253*7c478bd9Sstevel@tonic-gate 					 */
1254*7c478bd9Sstevel@tonic-gate 					if (firstmatch == cur)
1255*7c478bd9Sstevel@tonic-gate 						firstmatch = NULL;
1256*7c478bd9Sstevel@tonic-gate 				}
1257*7c478bd9Sstevel@tonic-gate 			}
1258*7c478bd9Sstevel@tonic-gate 		}
1259*7c478bd9Sstevel@tonic-gate 	}
1260*7c478bd9Sstevel@tonic-gate 	if (firstmatch == NULL)
1261*7c478bd9Sstevel@tonic-gate 		return (Z_NO_RESOURCE_ID);
1262*7c478bd9Sstevel@tonic-gate 
1263*7c478bd9Sstevel@tonic-gate 	cur = firstmatch;
1264*7c478bd9Sstevel@tonic-gate 
1265*7c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_PHYSICAL, tabptr->zone_nwif_physical,
1266*7c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_nwif_physical))) != Z_OK)
1267*7c478bd9Sstevel@tonic-gate 		return (err);
1268*7c478bd9Sstevel@tonic-gate 
1269*7c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_ADDRESS, tabptr->zone_nwif_address,
1270*7c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_nwif_address))) != Z_OK)
1271*7c478bd9Sstevel@tonic-gate 		return (err);
1272*7c478bd9Sstevel@tonic-gate 
1273*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
1274*7c478bd9Sstevel@tonic-gate }
1275*7c478bd9Sstevel@tonic-gate 
1276*7c478bd9Sstevel@tonic-gate static int
1277*7c478bd9Sstevel@tonic-gate zonecfg_add_nwif_core(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
1278*7c478bd9Sstevel@tonic-gate {
1279*7c478bd9Sstevel@tonic-gate 	xmlNodePtr newnode, cur = handle->zone_dh_cur;
1280*7c478bd9Sstevel@tonic-gate 	int err;
1281*7c478bd9Sstevel@tonic-gate 
1282*7c478bd9Sstevel@tonic-gate 	newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_NET, NULL);
1283*7c478bd9Sstevel@tonic-gate 	if ((err = newprop(handle, newnode, DTD_ATTR_ADDRESS,
1284*7c478bd9Sstevel@tonic-gate 	    tabptr->zone_nwif_address)) != Z_OK)
1285*7c478bd9Sstevel@tonic-gate 		return (err);
1286*7c478bd9Sstevel@tonic-gate 	if ((err = newprop(handle, newnode, DTD_ATTR_PHYSICAL,
1287*7c478bd9Sstevel@tonic-gate 	    tabptr->zone_nwif_physical)) != Z_OK)
1288*7c478bd9Sstevel@tonic-gate 		return (err);
1289*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
1290*7c478bd9Sstevel@tonic-gate }
1291*7c478bd9Sstevel@tonic-gate 
1292*7c478bd9Sstevel@tonic-gate int
1293*7c478bd9Sstevel@tonic-gate zonecfg_add_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
1294*7c478bd9Sstevel@tonic-gate {
1295*7c478bd9Sstevel@tonic-gate 	int err;
1296*7c478bd9Sstevel@tonic-gate 
1297*7c478bd9Sstevel@tonic-gate 	if (tabptr == NULL)
1298*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
1299*7c478bd9Sstevel@tonic-gate 
1300*7c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
1301*7c478bd9Sstevel@tonic-gate 		return (err);
1302*7c478bd9Sstevel@tonic-gate 
1303*7c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_add_nwif_core(handle, tabptr)) != Z_OK)
1304*7c478bd9Sstevel@tonic-gate 		return (err);
1305*7c478bd9Sstevel@tonic-gate 
1306*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
1307*7c478bd9Sstevel@tonic-gate }
1308*7c478bd9Sstevel@tonic-gate 
1309*7c478bd9Sstevel@tonic-gate static int
1310*7c478bd9Sstevel@tonic-gate zonecfg_delete_nwif_core(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
1311*7c478bd9Sstevel@tonic-gate {
1312*7c478bd9Sstevel@tonic-gate 	xmlNodePtr cur = handle->zone_dh_cur;
1313*7c478bd9Sstevel@tonic-gate 	boolean_t addr_match, phys_match;
1314*7c478bd9Sstevel@tonic-gate 
1315*7c478bd9Sstevel@tonic-gate 	for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
1316*7c478bd9Sstevel@tonic-gate 		if (xmlStrcmp(cur->name, DTD_ELEM_NET))
1317*7c478bd9Sstevel@tonic-gate 			continue;
1318*7c478bd9Sstevel@tonic-gate 
1319*7c478bd9Sstevel@tonic-gate 		addr_match = match_prop(cur, DTD_ATTR_ADDRESS,
1320*7c478bd9Sstevel@tonic-gate 		    tabptr->zone_nwif_address);
1321*7c478bd9Sstevel@tonic-gate 		phys_match = match_prop(cur, DTD_ATTR_PHYSICAL,
1322*7c478bd9Sstevel@tonic-gate 		    tabptr->zone_nwif_physical);
1323*7c478bd9Sstevel@tonic-gate 
1324*7c478bd9Sstevel@tonic-gate 		if (addr_match && phys_match) {
1325*7c478bd9Sstevel@tonic-gate 			xmlUnlinkNode(cur);
1326*7c478bd9Sstevel@tonic-gate 			xmlFreeNode(cur);
1327*7c478bd9Sstevel@tonic-gate 			return (Z_OK);
1328*7c478bd9Sstevel@tonic-gate 		}
1329*7c478bd9Sstevel@tonic-gate 	}
1330*7c478bd9Sstevel@tonic-gate 	return (Z_NO_RESOURCE_ID);
1331*7c478bd9Sstevel@tonic-gate }
1332*7c478bd9Sstevel@tonic-gate 
1333*7c478bd9Sstevel@tonic-gate int
1334*7c478bd9Sstevel@tonic-gate zonecfg_delete_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
1335*7c478bd9Sstevel@tonic-gate {
1336*7c478bd9Sstevel@tonic-gate 	int err;
1337*7c478bd9Sstevel@tonic-gate 
1338*7c478bd9Sstevel@tonic-gate 	if (tabptr == NULL)
1339*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
1340*7c478bd9Sstevel@tonic-gate 
1341*7c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
1342*7c478bd9Sstevel@tonic-gate 		return (err);
1343*7c478bd9Sstevel@tonic-gate 
1344*7c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_delete_nwif_core(handle, tabptr)) != Z_OK)
1345*7c478bd9Sstevel@tonic-gate 		return (err);
1346*7c478bd9Sstevel@tonic-gate 
1347*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
1348*7c478bd9Sstevel@tonic-gate }
1349*7c478bd9Sstevel@tonic-gate 
1350*7c478bd9Sstevel@tonic-gate int
1351*7c478bd9Sstevel@tonic-gate zonecfg_modify_nwif(
1352*7c478bd9Sstevel@tonic-gate 	zone_dochandle_t handle,
1353*7c478bd9Sstevel@tonic-gate 	struct zone_nwiftab *oldtabptr,
1354*7c478bd9Sstevel@tonic-gate 	struct zone_nwiftab *newtabptr)
1355*7c478bd9Sstevel@tonic-gate {
1356*7c478bd9Sstevel@tonic-gate 	int err;
1357*7c478bd9Sstevel@tonic-gate 
1358*7c478bd9Sstevel@tonic-gate 	if (oldtabptr == NULL || newtabptr == NULL)
1359*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
1360*7c478bd9Sstevel@tonic-gate 
1361*7c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
1362*7c478bd9Sstevel@tonic-gate 		return (err);
1363*7c478bd9Sstevel@tonic-gate 
1364*7c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_delete_nwif_core(handle, oldtabptr)) != Z_OK)
1365*7c478bd9Sstevel@tonic-gate 		return (err);
1366*7c478bd9Sstevel@tonic-gate 
1367*7c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_add_nwif_core(handle, newtabptr)) != Z_OK)
1368*7c478bd9Sstevel@tonic-gate 		return (err);
1369*7c478bd9Sstevel@tonic-gate 
1370*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
1371*7c478bd9Sstevel@tonic-gate }
1372*7c478bd9Sstevel@tonic-gate 
1373*7c478bd9Sstevel@tonic-gate int
1374*7c478bd9Sstevel@tonic-gate zonecfg_lookup_dev(zone_dochandle_t handle, struct zone_devtab *tabptr)
1375*7c478bd9Sstevel@tonic-gate {
1376*7c478bd9Sstevel@tonic-gate 	xmlNodePtr cur, firstmatch;
1377*7c478bd9Sstevel@tonic-gate 	int err;
1378*7c478bd9Sstevel@tonic-gate 	char match[MAXPATHLEN];
1379*7c478bd9Sstevel@tonic-gate 
1380*7c478bd9Sstevel@tonic-gate 	if (tabptr == NULL)
1381*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
1382*7c478bd9Sstevel@tonic-gate 
1383*7c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
1384*7c478bd9Sstevel@tonic-gate 		return (err);
1385*7c478bd9Sstevel@tonic-gate 
1386*7c478bd9Sstevel@tonic-gate 	cur = handle->zone_dh_cur;
1387*7c478bd9Sstevel@tonic-gate 	firstmatch = NULL;
1388*7c478bd9Sstevel@tonic-gate 	for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
1389*7c478bd9Sstevel@tonic-gate 		if (xmlStrcmp(cur->name, DTD_ELEM_DEVICE))
1390*7c478bd9Sstevel@tonic-gate 			continue;
1391*7c478bd9Sstevel@tonic-gate 		if (strlen(tabptr->zone_dev_match) == 0)
1392*7c478bd9Sstevel@tonic-gate 			continue;
1393*7c478bd9Sstevel@tonic-gate 
1394*7c478bd9Sstevel@tonic-gate 		if ((fetchprop(cur, DTD_ATTR_MATCH, match,
1395*7c478bd9Sstevel@tonic-gate 		    sizeof (match)) == Z_OK)) {
1396*7c478bd9Sstevel@tonic-gate 			if (strcmp(tabptr->zone_dev_match,
1397*7c478bd9Sstevel@tonic-gate 			    match) == 0) {
1398*7c478bd9Sstevel@tonic-gate 				if (firstmatch == NULL)
1399*7c478bd9Sstevel@tonic-gate 					firstmatch = cur;
1400*7c478bd9Sstevel@tonic-gate 				else if (firstmatch != cur)
1401*7c478bd9Sstevel@tonic-gate 					return (Z_INSUFFICIENT_SPEC);
1402*7c478bd9Sstevel@tonic-gate 			} else {
1403*7c478bd9Sstevel@tonic-gate 				/*
1404*7c478bd9Sstevel@tonic-gate 				 * If another property matched but this
1405*7c478bd9Sstevel@tonic-gate 				 * one doesn't then reset firstmatch.
1406*7c478bd9Sstevel@tonic-gate 				 */
1407*7c478bd9Sstevel@tonic-gate 				if (firstmatch == cur)
1408*7c478bd9Sstevel@tonic-gate 					firstmatch = NULL;
1409*7c478bd9Sstevel@tonic-gate 			}
1410*7c478bd9Sstevel@tonic-gate 		}
1411*7c478bd9Sstevel@tonic-gate 	}
1412*7c478bd9Sstevel@tonic-gate 	if (firstmatch == NULL)
1413*7c478bd9Sstevel@tonic-gate 		return (Z_NO_RESOURCE_ID);
1414*7c478bd9Sstevel@tonic-gate 
1415*7c478bd9Sstevel@tonic-gate 	cur = firstmatch;
1416*7c478bd9Sstevel@tonic-gate 
1417*7c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_MATCH, tabptr->zone_dev_match,
1418*7c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_dev_match))) != Z_OK)
1419*7c478bd9Sstevel@tonic-gate 		return (err);
1420*7c478bd9Sstevel@tonic-gate 
1421*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
1422*7c478bd9Sstevel@tonic-gate }
1423*7c478bd9Sstevel@tonic-gate 
1424*7c478bd9Sstevel@tonic-gate static int
1425*7c478bd9Sstevel@tonic-gate zonecfg_add_dev_core(zone_dochandle_t handle, struct zone_devtab *tabptr)
1426*7c478bd9Sstevel@tonic-gate {
1427*7c478bd9Sstevel@tonic-gate 	xmlNodePtr newnode, cur = handle->zone_dh_cur;
1428*7c478bd9Sstevel@tonic-gate 	int err;
1429*7c478bd9Sstevel@tonic-gate 
1430*7c478bd9Sstevel@tonic-gate 	newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_DEVICE, NULL);
1431*7c478bd9Sstevel@tonic-gate 
1432*7c478bd9Sstevel@tonic-gate 	if ((err = newprop(handle, newnode, DTD_ATTR_MATCH,
1433*7c478bd9Sstevel@tonic-gate 	    tabptr->zone_dev_match)) != Z_OK)
1434*7c478bd9Sstevel@tonic-gate 		return (err);
1435*7c478bd9Sstevel@tonic-gate 
1436*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
1437*7c478bd9Sstevel@tonic-gate }
1438*7c478bd9Sstevel@tonic-gate 
1439*7c478bd9Sstevel@tonic-gate int
1440*7c478bd9Sstevel@tonic-gate zonecfg_add_dev(zone_dochandle_t handle, struct zone_devtab *tabptr)
1441*7c478bd9Sstevel@tonic-gate {
1442*7c478bd9Sstevel@tonic-gate 	int err;
1443*7c478bd9Sstevel@tonic-gate 
1444*7c478bd9Sstevel@tonic-gate 	if (tabptr == NULL)
1445*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
1446*7c478bd9Sstevel@tonic-gate 
1447*7c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
1448*7c478bd9Sstevel@tonic-gate 		return (err);
1449*7c478bd9Sstevel@tonic-gate 
1450*7c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_add_dev_core(handle, tabptr)) != Z_OK)
1451*7c478bd9Sstevel@tonic-gate 		return (err);
1452*7c478bd9Sstevel@tonic-gate 
1453*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
1454*7c478bd9Sstevel@tonic-gate }
1455*7c478bd9Sstevel@tonic-gate 
1456*7c478bd9Sstevel@tonic-gate static int
1457*7c478bd9Sstevel@tonic-gate zonecfg_delete_dev_core(zone_dochandle_t handle, struct zone_devtab *tabptr)
1458*7c478bd9Sstevel@tonic-gate {
1459*7c478bd9Sstevel@tonic-gate 	xmlNodePtr cur = handle->zone_dh_cur;
1460*7c478bd9Sstevel@tonic-gate 	int match_match;
1461*7c478bd9Sstevel@tonic-gate 
1462*7c478bd9Sstevel@tonic-gate 	for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
1463*7c478bd9Sstevel@tonic-gate 		if (xmlStrcmp(cur->name, DTD_ELEM_DEVICE))
1464*7c478bd9Sstevel@tonic-gate 			continue;
1465*7c478bd9Sstevel@tonic-gate 
1466*7c478bd9Sstevel@tonic-gate 		match_match = match_prop(cur, DTD_ATTR_MATCH,
1467*7c478bd9Sstevel@tonic-gate 		    tabptr->zone_dev_match);
1468*7c478bd9Sstevel@tonic-gate 
1469*7c478bd9Sstevel@tonic-gate 		if (match_match) {
1470*7c478bd9Sstevel@tonic-gate 			xmlUnlinkNode(cur);
1471*7c478bd9Sstevel@tonic-gate 			xmlFreeNode(cur);
1472*7c478bd9Sstevel@tonic-gate 			return (Z_OK);
1473*7c478bd9Sstevel@tonic-gate 		}
1474*7c478bd9Sstevel@tonic-gate 	}
1475*7c478bd9Sstevel@tonic-gate 	return (Z_NO_RESOURCE_ID);
1476*7c478bd9Sstevel@tonic-gate }
1477*7c478bd9Sstevel@tonic-gate 
1478*7c478bd9Sstevel@tonic-gate int
1479*7c478bd9Sstevel@tonic-gate zonecfg_delete_dev(zone_dochandle_t handle, struct zone_devtab *tabptr)
1480*7c478bd9Sstevel@tonic-gate {
1481*7c478bd9Sstevel@tonic-gate 	int err;
1482*7c478bd9Sstevel@tonic-gate 
1483*7c478bd9Sstevel@tonic-gate 	if (tabptr == NULL)
1484*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
1485*7c478bd9Sstevel@tonic-gate 
1486*7c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
1487*7c478bd9Sstevel@tonic-gate 		return (err);
1488*7c478bd9Sstevel@tonic-gate 
1489*7c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_delete_dev_core(handle, tabptr)) != Z_OK)
1490*7c478bd9Sstevel@tonic-gate 		return (err);
1491*7c478bd9Sstevel@tonic-gate 
1492*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
1493*7c478bd9Sstevel@tonic-gate }
1494*7c478bd9Sstevel@tonic-gate 
1495*7c478bd9Sstevel@tonic-gate int
1496*7c478bd9Sstevel@tonic-gate zonecfg_modify_dev(
1497*7c478bd9Sstevel@tonic-gate 	zone_dochandle_t handle,
1498*7c478bd9Sstevel@tonic-gate 	struct zone_devtab *oldtabptr,
1499*7c478bd9Sstevel@tonic-gate 	struct zone_devtab *newtabptr)
1500*7c478bd9Sstevel@tonic-gate {
1501*7c478bd9Sstevel@tonic-gate 	int err;
1502*7c478bd9Sstevel@tonic-gate 
1503*7c478bd9Sstevel@tonic-gate 	if (oldtabptr == NULL || newtabptr == NULL)
1504*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
1505*7c478bd9Sstevel@tonic-gate 
1506*7c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
1507*7c478bd9Sstevel@tonic-gate 		return (err);
1508*7c478bd9Sstevel@tonic-gate 
1509*7c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_delete_dev_core(handle, oldtabptr)) != Z_OK)
1510*7c478bd9Sstevel@tonic-gate 		return (err);
1511*7c478bd9Sstevel@tonic-gate 
1512*7c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_add_dev_core(handle, newtabptr)) != Z_OK)
1513*7c478bd9Sstevel@tonic-gate 		return (err);
1514*7c478bd9Sstevel@tonic-gate 
1515*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
1516*7c478bd9Sstevel@tonic-gate }
1517*7c478bd9Sstevel@tonic-gate 
1518*7c478bd9Sstevel@tonic-gate /*
1519*7c478bd9Sstevel@tonic-gate  * This is the set of devices which must be present in every zone.  Users
1520*7c478bd9Sstevel@tonic-gate  * can augment this list with additional device rules in their zone
1521*7c478bd9Sstevel@tonic-gate  * configuration, but at present cannot remove any of the this set of
1522*7c478bd9Sstevel@tonic-gate  * standard devices.  All matching is done by /dev pathname (the "/dev"
1523*7c478bd9Sstevel@tonic-gate  * part is implicit.  Try to keep rules which match a large number of
1524*7c478bd9Sstevel@tonic-gate  * devices (like the pts rule) first.
1525*7c478bd9Sstevel@tonic-gate  */
1526*7c478bd9Sstevel@tonic-gate static const char *standard_devs[] = {
1527*7c478bd9Sstevel@tonic-gate 	"pts/*",
1528*7c478bd9Sstevel@tonic-gate 	"ptmx",
1529*7c478bd9Sstevel@tonic-gate 	"random",
1530*7c478bd9Sstevel@tonic-gate 	"urandom",
1531*7c478bd9Sstevel@tonic-gate 	"poll",
1532*7c478bd9Sstevel@tonic-gate 	"pool",
1533*7c478bd9Sstevel@tonic-gate 	"kstat",
1534*7c478bd9Sstevel@tonic-gate 	"zero",
1535*7c478bd9Sstevel@tonic-gate 	"null",
1536*7c478bd9Sstevel@tonic-gate 	"crypto",
1537*7c478bd9Sstevel@tonic-gate 	"cryptoadm",
1538*7c478bd9Sstevel@tonic-gate 	"ticots",
1539*7c478bd9Sstevel@tonic-gate 	"ticotsord",
1540*7c478bd9Sstevel@tonic-gate 	"ticlts",
1541*7c478bd9Sstevel@tonic-gate 	"lo0",
1542*7c478bd9Sstevel@tonic-gate 	"lo1",
1543*7c478bd9Sstevel@tonic-gate 	"lo2",
1544*7c478bd9Sstevel@tonic-gate 	"lo3",
1545*7c478bd9Sstevel@tonic-gate 	"sad/user",
1546*7c478bd9Sstevel@tonic-gate 	"tty",
1547*7c478bd9Sstevel@tonic-gate 	"logindmux",
1548*7c478bd9Sstevel@tonic-gate 	"log",
1549*7c478bd9Sstevel@tonic-gate 	"conslog",
1550*7c478bd9Sstevel@tonic-gate 	"arp",
1551*7c478bd9Sstevel@tonic-gate 	"tcp",
1552*7c478bd9Sstevel@tonic-gate 	"tcp6",
1553*7c478bd9Sstevel@tonic-gate 	"udp",
1554*7c478bd9Sstevel@tonic-gate 	"udp6",
1555*7c478bd9Sstevel@tonic-gate 	"sysevent",
1556*7c478bd9Sstevel@tonic-gate #ifdef __sparc
1557*7c478bd9Sstevel@tonic-gate 	"openprom",
1558*7c478bd9Sstevel@tonic-gate #endif
1559*7c478bd9Sstevel@tonic-gate 	"cpu/self/cpuid",
1560*7c478bd9Sstevel@tonic-gate 	"dtrace/helper",
1561*7c478bd9Sstevel@tonic-gate 	NULL
1562*7c478bd9Sstevel@tonic-gate };
1563*7c478bd9Sstevel@tonic-gate 
1564*7c478bd9Sstevel@tonic-gate /*
1565*7c478bd9Sstevel@tonic-gate  * This function finds everything mounted under a zone's rootpath.
1566*7c478bd9Sstevel@tonic-gate  * This returns the number of mounts under rootpath, or -1 on error.
1567*7c478bd9Sstevel@tonic-gate  * callback is called once per mount found with the first argument
1568*7c478bd9Sstevel@tonic-gate  * pointing to the  mount point.
1569*7c478bd9Sstevel@tonic-gate  *
1570*7c478bd9Sstevel@tonic-gate  * If the callback function returns non-zero zonecfg_find_mounts
1571*7c478bd9Sstevel@tonic-gate  * aborts with an error.
1572*7c478bd9Sstevel@tonic-gate  */
1573*7c478bd9Sstevel@tonic-gate 
1574*7c478bd9Sstevel@tonic-gate int
1575*7c478bd9Sstevel@tonic-gate zonecfg_find_mounts(char *rootpath, int (*callback)(const char *, void *),
1576*7c478bd9Sstevel@tonic-gate     void *priv) {
1577*7c478bd9Sstevel@tonic-gate 	FILE *mnttab;
1578*7c478bd9Sstevel@tonic-gate 	struct mnttab m;
1579*7c478bd9Sstevel@tonic-gate 	size_t l;
1580*7c478bd9Sstevel@tonic-gate 	int rv = 0;
1581*7c478bd9Sstevel@tonic-gate 
1582*7c478bd9Sstevel@tonic-gate 	assert(rootpath != NULL);
1583*7c478bd9Sstevel@tonic-gate 
1584*7c478bd9Sstevel@tonic-gate 	l = strlen(rootpath);
1585*7c478bd9Sstevel@tonic-gate 
1586*7c478bd9Sstevel@tonic-gate 	mnttab = fopen("/etc/mnttab", "r");
1587*7c478bd9Sstevel@tonic-gate 
1588*7c478bd9Sstevel@tonic-gate 	if (mnttab == NULL)
1589*7c478bd9Sstevel@tonic-gate 		return (-1);
1590*7c478bd9Sstevel@tonic-gate 
1591*7c478bd9Sstevel@tonic-gate 	if (ioctl(fileno(mnttab), MNTIOC_SHOWHIDDEN, NULL) < 0)  {
1592*7c478bd9Sstevel@tonic-gate 		rv = -1;
1593*7c478bd9Sstevel@tonic-gate 		goto out;
1594*7c478bd9Sstevel@tonic-gate 	}
1595*7c478bd9Sstevel@tonic-gate 
1596*7c478bd9Sstevel@tonic-gate 	while (!getmntent(mnttab, &m)) {
1597*7c478bd9Sstevel@tonic-gate 		if ((strncmp(rootpath, m.mnt_mountp, l) == 0) &&
1598*7c478bd9Sstevel@tonic-gate 		    (m.mnt_mountp[l] == '/')) {
1599*7c478bd9Sstevel@tonic-gate 			rv++;
1600*7c478bd9Sstevel@tonic-gate 			if (callback == NULL)
1601*7c478bd9Sstevel@tonic-gate 				continue;
1602*7c478bd9Sstevel@tonic-gate 			if (callback(m.mnt_mountp, priv)) {
1603*7c478bd9Sstevel@tonic-gate 				rv = -1;
1604*7c478bd9Sstevel@tonic-gate 				goto out;
1605*7c478bd9Sstevel@tonic-gate 
1606*7c478bd9Sstevel@tonic-gate 			}
1607*7c478bd9Sstevel@tonic-gate 		}
1608*7c478bd9Sstevel@tonic-gate 	}
1609*7c478bd9Sstevel@tonic-gate 
1610*7c478bd9Sstevel@tonic-gate out:
1611*7c478bd9Sstevel@tonic-gate 	(void) fclose(mnttab);
1612*7c478bd9Sstevel@tonic-gate 	return (rv);
1613*7c478bd9Sstevel@tonic-gate }
1614*7c478bd9Sstevel@tonic-gate 
1615*7c478bd9Sstevel@tonic-gate /*
1616*7c478bd9Sstevel@tonic-gate  * This routine is used to determine if a given device should appear in the
1617*7c478bd9Sstevel@tonic-gate  * zone represented by 'handle'.  First it consults the list of "standard"
1618*7c478bd9Sstevel@tonic-gate  * zone devices.  Then it scans the user-supplied device entries.
1619*7c478bd9Sstevel@tonic-gate  */
1620*7c478bd9Sstevel@tonic-gate int
1621*7c478bd9Sstevel@tonic-gate zonecfg_match_dev(zone_dochandle_t handle, char *devpath,
1622*7c478bd9Sstevel@tonic-gate     struct zone_devtab *out_match)
1623*7c478bd9Sstevel@tonic-gate {
1624*7c478bd9Sstevel@tonic-gate 	int err;
1625*7c478bd9Sstevel@tonic-gate 	boolean_t found = B_FALSE;
1626*7c478bd9Sstevel@tonic-gate 	char match[MAXPATHLEN];
1627*7c478bd9Sstevel@tonic-gate 	const char **stdmatch;
1628*7c478bd9Sstevel@tonic-gate 	xmlNodePtr cur;
1629*7c478bd9Sstevel@tonic-gate 
1630*7c478bd9Sstevel@tonic-gate 	if (handle == NULL || devpath == NULL)
1631*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
1632*7c478bd9Sstevel@tonic-gate 
1633*7c478bd9Sstevel@tonic-gate 	/*
1634*7c478bd9Sstevel@tonic-gate 	 * Check the "standard" devices which we require to be present.
1635*7c478bd9Sstevel@tonic-gate 	 */
1636*7c478bd9Sstevel@tonic-gate 	for (stdmatch = &standard_devs[0]; *stdmatch != NULL; stdmatch++) {
1637*7c478bd9Sstevel@tonic-gate 		/*
1638*7c478bd9Sstevel@tonic-gate 		 * fnmatch gives us simple but powerful shell-style matching.
1639*7c478bd9Sstevel@tonic-gate 		 */
1640*7c478bd9Sstevel@tonic-gate 		if (fnmatch(*stdmatch, devpath, FNM_PATHNAME) == 0) {
1641*7c478bd9Sstevel@tonic-gate 			if (!out_match)
1642*7c478bd9Sstevel@tonic-gate 				return (Z_OK);
1643*7c478bd9Sstevel@tonic-gate 			(void) snprintf(out_match->zone_dev_match,
1644*7c478bd9Sstevel@tonic-gate 			    sizeof (out_match->zone_dev_match),
1645*7c478bd9Sstevel@tonic-gate 			    "/dev/%s", *stdmatch);
1646*7c478bd9Sstevel@tonic-gate 			return (Z_OK);
1647*7c478bd9Sstevel@tonic-gate 		}
1648*7c478bd9Sstevel@tonic-gate 	}
1649*7c478bd9Sstevel@tonic-gate 
1650*7c478bd9Sstevel@tonic-gate 	/*
1651*7c478bd9Sstevel@tonic-gate 	 * We got no hits in the set of standard devices.  On to the user
1652*7c478bd9Sstevel@tonic-gate 	 * supplied ones.
1653*7c478bd9Sstevel@tonic-gate 	 */
1654*7c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK) {
1655*7c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = NULL;
1656*7c478bd9Sstevel@tonic-gate 		return (err);
1657*7c478bd9Sstevel@tonic-gate 	}
1658*7c478bd9Sstevel@tonic-gate 
1659*7c478bd9Sstevel@tonic-gate 	cur = handle->zone_dh_cur;
1660*7c478bd9Sstevel@tonic-gate 	cur = cur->xmlChildrenNode;
1661*7c478bd9Sstevel@tonic-gate 	if (cur == NULL)
1662*7c478bd9Sstevel@tonic-gate 		return (Z_NO_ENTRY);
1663*7c478bd9Sstevel@tonic-gate 	handle->zone_dh_cur = cur;
1664*7c478bd9Sstevel@tonic-gate 
1665*7c478bd9Sstevel@tonic-gate 	for (; cur != NULL; cur = cur->next) {
1666*7c478bd9Sstevel@tonic-gate 		char *m;
1667*7c478bd9Sstevel@tonic-gate 		if (xmlStrcmp(cur->name, DTD_ELEM_DEVICE) != 0)
1668*7c478bd9Sstevel@tonic-gate 			continue;
1669*7c478bd9Sstevel@tonic-gate 		if ((err = fetchprop(cur, DTD_ATTR_MATCH, match,
1670*7c478bd9Sstevel@tonic-gate 		    sizeof (match))) != Z_OK) {
1671*7c478bd9Sstevel@tonic-gate 			handle->zone_dh_cur = handle->zone_dh_top;
1672*7c478bd9Sstevel@tonic-gate 			return (err);
1673*7c478bd9Sstevel@tonic-gate 		}
1674*7c478bd9Sstevel@tonic-gate 		m = match;
1675*7c478bd9Sstevel@tonic-gate 		/*
1676*7c478bd9Sstevel@tonic-gate 		 * fnmatch gives us simple but powerful shell-style matching;
1677*7c478bd9Sstevel@tonic-gate 		 * but first, we need to strip out /dev/ from the matching rule.
1678*7c478bd9Sstevel@tonic-gate 		 */
1679*7c478bd9Sstevel@tonic-gate 		if (strncmp(m, "/dev/", 5) == 0)
1680*7c478bd9Sstevel@tonic-gate 			m += 5;
1681*7c478bd9Sstevel@tonic-gate 
1682*7c478bd9Sstevel@tonic-gate 		if (fnmatch(m, devpath, FNM_PATHNAME) == 0) {
1683*7c478bd9Sstevel@tonic-gate 			found = B_TRUE;
1684*7c478bd9Sstevel@tonic-gate 			break;
1685*7c478bd9Sstevel@tonic-gate 		}
1686*7c478bd9Sstevel@tonic-gate 	}
1687*7c478bd9Sstevel@tonic-gate 
1688*7c478bd9Sstevel@tonic-gate 	if (!found)
1689*7c478bd9Sstevel@tonic-gate 		return (Z_NO_ENTRY);
1690*7c478bd9Sstevel@tonic-gate 
1691*7c478bd9Sstevel@tonic-gate 	if (!out_match)
1692*7c478bd9Sstevel@tonic-gate 		return (Z_OK);
1693*7c478bd9Sstevel@tonic-gate 
1694*7c478bd9Sstevel@tonic-gate 	(void) strlcpy(out_match->zone_dev_match, match,
1695*7c478bd9Sstevel@tonic-gate 	    sizeof (out_match->zone_dev_match));
1696*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
1697*7c478bd9Sstevel@tonic-gate }
1698*7c478bd9Sstevel@tonic-gate 
1699*7c478bd9Sstevel@tonic-gate int
1700*7c478bd9Sstevel@tonic-gate zonecfg_lookup_attr(zone_dochandle_t handle, struct zone_attrtab *tabptr)
1701*7c478bd9Sstevel@tonic-gate {
1702*7c478bd9Sstevel@tonic-gate 	xmlNodePtr cur, firstmatch;
1703*7c478bd9Sstevel@tonic-gate 	int err;
1704*7c478bd9Sstevel@tonic-gate 	char name[MAXNAMELEN], type[MAXNAMELEN], value[MAXNAMELEN];
1705*7c478bd9Sstevel@tonic-gate 
1706*7c478bd9Sstevel@tonic-gate 	if (tabptr == NULL)
1707*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
1708*7c478bd9Sstevel@tonic-gate 
1709*7c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
1710*7c478bd9Sstevel@tonic-gate 		return (err);
1711*7c478bd9Sstevel@tonic-gate 
1712*7c478bd9Sstevel@tonic-gate 	cur = handle->zone_dh_cur;
1713*7c478bd9Sstevel@tonic-gate 	firstmatch = NULL;
1714*7c478bd9Sstevel@tonic-gate 	for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
1715*7c478bd9Sstevel@tonic-gate 		if (xmlStrcmp(cur->name, DTD_ELEM_ATTR))
1716*7c478bd9Sstevel@tonic-gate 			continue;
1717*7c478bd9Sstevel@tonic-gate 		if (strlen(tabptr->zone_attr_name) > 0) {
1718*7c478bd9Sstevel@tonic-gate 			if ((fetchprop(cur, DTD_ATTR_NAME, name,
1719*7c478bd9Sstevel@tonic-gate 			    sizeof (name)) == Z_OK) &&
1720*7c478bd9Sstevel@tonic-gate 			    (strcmp(tabptr->zone_attr_name, name) == 0)) {
1721*7c478bd9Sstevel@tonic-gate 				if (firstmatch == NULL)
1722*7c478bd9Sstevel@tonic-gate 					firstmatch = cur;
1723*7c478bd9Sstevel@tonic-gate 				else
1724*7c478bd9Sstevel@tonic-gate 					return (Z_INSUFFICIENT_SPEC);
1725*7c478bd9Sstevel@tonic-gate 			}
1726*7c478bd9Sstevel@tonic-gate 		}
1727*7c478bd9Sstevel@tonic-gate 		if (strlen(tabptr->zone_attr_type) > 0) {
1728*7c478bd9Sstevel@tonic-gate 			if ((fetchprop(cur, DTD_ATTR_TYPE, type,
1729*7c478bd9Sstevel@tonic-gate 			    sizeof (type)) == Z_OK)) {
1730*7c478bd9Sstevel@tonic-gate 				if (strcmp(tabptr->zone_attr_type, type) == 0) {
1731*7c478bd9Sstevel@tonic-gate 					if (firstmatch == NULL)
1732*7c478bd9Sstevel@tonic-gate 						firstmatch = cur;
1733*7c478bd9Sstevel@tonic-gate 					else if (firstmatch != cur)
1734*7c478bd9Sstevel@tonic-gate 						return (Z_INSUFFICIENT_SPEC);
1735*7c478bd9Sstevel@tonic-gate 				} else {
1736*7c478bd9Sstevel@tonic-gate 					/*
1737*7c478bd9Sstevel@tonic-gate 					 * If another property matched but this
1738*7c478bd9Sstevel@tonic-gate 					 * one doesn't then reset firstmatch.
1739*7c478bd9Sstevel@tonic-gate 					 */
1740*7c478bd9Sstevel@tonic-gate 					if (firstmatch == cur)
1741*7c478bd9Sstevel@tonic-gate 						firstmatch = NULL;
1742*7c478bd9Sstevel@tonic-gate 				}
1743*7c478bd9Sstevel@tonic-gate 			}
1744*7c478bd9Sstevel@tonic-gate 		}
1745*7c478bd9Sstevel@tonic-gate 		if (strlen(tabptr->zone_attr_value) > 0) {
1746*7c478bd9Sstevel@tonic-gate 			if ((fetchprop(cur, DTD_ATTR_VALUE, value,
1747*7c478bd9Sstevel@tonic-gate 			    sizeof (value)) == Z_OK)) {
1748*7c478bd9Sstevel@tonic-gate 				if (strcmp(tabptr->zone_attr_value, value) ==
1749*7c478bd9Sstevel@tonic-gate 				    0) {
1750*7c478bd9Sstevel@tonic-gate 					if (firstmatch == NULL)
1751*7c478bd9Sstevel@tonic-gate 						firstmatch = cur;
1752*7c478bd9Sstevel@tonic-gate 					else if (firstmatch != cur)
1753*7c478bd9Sstevel@tonic-gate 						return (Z_INSUFFICIENT_SPEC);
1754*7c478bd9Sstevel@tonic-gate 				} else {
1755*7c478bd9Sstevel@tonic-gate 					/*
1756*7c478bd9Sstevel@tonic-gate 					 * If another property matched but this
1757*7c478bd9Sstevel@tonic-gate 					 * one doesn't then reset firstmatch.
1758*7c478bd9Sstevel@tonic-gate 					 */
1759*7c478bd9Sstevel@tonic-gate 					if (firstmatch == cur)
1760*7c478bd9Sstevel@tonic-gate 						firstmatch = NULL;
1761*7c478bd9Sstevel@tonic-gate 				}
1762*7c478bd9Sstevel@tonic-gate 			}
1763*7c478bd9Sstevel@tonic-gate 		}
1764*7c478bd9Sstevel@tonic-gate 	}
1765*7c478bd9Sstevel@tonic-gate 	if (firstmatch == NULL)
1766*7c478bd9Sstevel@tonic-gate 		return (Z_NO_RESOURCE_ID);
1767*7c478bd9Sstevel@tonic-gate 
1768*7c478bd9Sstevel@tonic-gate 	cur = firstmatch;
1769*7c478bd9Sstevel@tonic-gate 
1770*7c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_NAME, tabptr->zone_attr_name,
1771*7c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_attr_name))) != Z_OK)
1772*7c478bd9Sstevel@tonic-gate 		return (err);
1773*7c478bd9Sstevel@tonic-gate 
1774*7c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_TYPE, tabptr->zone_attr_type,
1775*7c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_attr_type))) != Z_OK)
1776*7c478bd9Sstevel@tonic-gate 		return (err);
1777*7c478bd9Sstevel@tonic-gate 
1778*7c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_VALUE, tabptr->zone_attr_value,
1779*7c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_attr_value))) != Z_OK)
1780*7c478bd9Sstevel@tonic-gate 		return (err);
1781*7c478bd9Sstevel@tonic-gate 
1782*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
1783*7c478bd9Sstevel@tonic-gate }
1784*7c478bd9Sstevel@tonic-gate 
1785*7c478bd9Sstevel@tonic-gate static int
1786*7c478bd9Sstevel@tonic-gate zonecfg_add_attr_core(zone_dochandle_t handle, struct zone_attrtab *tabptr)
1787*7c478bd9Sstevel@tonic-gate {
1788*7c478bd9Sstevel@tonic-gate 	xmlNodePtr newnode, cur = handle->zone_dh_cur;
1789*7c478bd9Sstevel@tonic-gate 	int err;
1790*7c478bd9Sstevel@tonic-gate 
1791*7c478bd9Sstevel@tonic-gate 	newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_ATTR, NULL);
1792*7c478bd9Sstevel@tonic-gate 	err = newprop(handle, newnode, DTD_ATTR_NAME, tabptr->zone_attr_name);
1793*7c478bd9Sstevel@tonic-gate 	if (err != Z_OK)
1794*7c478bd9Sstevel@tonic-gate 		return (err);
1795*7c478bd9Sstevel@tonic-gate 	err = newprop(handle, newnode, DTD_ATTR_TYPE, tabptr->zone_attr_type);
1796*7c478bd9Sstevel@tonic-gate 	if (err != Z_OK)
1797*7c478bd9Sstevel@tonic-gate 		return (err);
1798*7c478bd9Sstevel@tonic-gate 	err = newprop(handle, newnode, DTD_ATTR_VALUE, tabptr->zone_attr_value);
1799*7c478bd9Sstevel@tonic-gate 	if (err != Z_OK)
1800*7c478bd9Sstevel@tonic-gate 		return (err);
1801*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
1802*7c478bd9Sstevel@tonic-gate }
1803*7c478bd9Sstevel@tonic-gate 
1804*7c478bd9Sstevel@tonic-gate int
1805*7c478bd9Sstevel@tonic-gate zonecfg_add_attr(zone_dochandle_t handle, struct zone_attrtab *tabptr)
1806*7c478bd9Sstevel@tonic-gate {
1807*7c478bd9Sstevel@tonic-gate 	int err;
1808*7c478bd9Sstevel@tonic-gate 
1809*7c478bd9Sstevel@tonic-gate 	if (tabptr == NULL)
1810*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
1811*7c478bd9Sstevel@tonic-gate 
1812*7c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
1813*7c478bd9Sstevel@tonic-gate 		return (err);
1814*7c478bd9Sstevel@tonic-gate 
1815*7c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_add_attr_core(handle, tabptr)) != Z_OK)
1816*7c478bd9Sstevel@tonic-gate 		return (err);
1817*7c478bd9Sstevel@tonic-gate 
1818*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
1819*7c478bd9Sstevel@tonic-gate }
1820*7c478bd9Sstevel@tonic-gate 
1821*7c478bd9Sstevel@tonic-gate static int
1822*7c478bd9Sstevel@tonic-gate zonecfg_delete_attr_core(zone_dochandle_t handle, struct zone_attrtab *tabptr)
1823*7c478bd9Sstevel@tonic-gate {
1824*7c478bd9Sstevel@tonic-gate 	xmlNodePtr cur = handle->zone_dh_cur;
1825*7c478bd9Sstevel@tonic-gate 	int name_match, type_match, value_match;
1826*7c478bd9Sstevel@tonic-gate 
1827*7c478bd9Sstevel@tonic-gate 	for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
1828*7c478bd9Sstevel@tonic-gate 		if (xmlStrcmp(cur->name, DTD_ELEM_ATTR))
1829*7c478bd9Sstevel@tonic-gate 			continue;
1830*7c478bd9Sstevel@tonic-gate 
1831*7c478bd9Sstevel@tonic-gate 		name_match = match_prop(cur, DTD_ATTR_NAME,
1832*7c478bd9Sstevel@tonic-gate 		    tabptr->zone_attr_name);
1833*7c478bd9Sstevel@tonic-gate 		type_match = match_prop(cur, DTD_ATTR_TYPE,
1834*7c478bd9Sstevel@tonic-gate 		    tabptr->zone_attr_type);
1835*7c478bd9Sstevel@tonic-gate 		value_match = match_prop(cur, DTD_ATTR_VALUE,
1836*7c478bd9Sstevel@tonic-gate 		    tabptr->zone_attr_value);
1837*7c478bd9Sstevel@tonic-gate 
1838*7c478bd9Sstevel@tonic-gate 		if (name_match && type_match && value_match) {
1839*7c478bd9Sstevel@tonic-gate 			xmlUnlinkNode(cur);
1840*7c478bd9Sstevel@tonic-gate 			xmlFreeNode(cur);
1841*7c478bd9Sstevel@tonic-gate 			return (Z_OK);
1842*7c478bd9Sstevel@tonic-gate 		}
1843*7c478bd9Sstevel@tonic-gate 	}
1844*7c478bd9Sstevel@tonic-gate 	return (Z_NO_RESOURCE_ID);
1845*7c478bd9Sstevel@tonic-gate }
1846*7c478bd9Sstevel@tonic-gate 
1847*7c478bd9Sstevel@tonic-gate int
1848*7c478bd9Sstevel@tonic-gate zonecfg_delete_attr(zone_dochandle_t handle, struct zone_attrtab *tabptr)
1849*7c478bd9Sstevel@tonic-gate {
1850*7c478bd9Sstevel@tonic-gate 	int err;
1851*7c478bd9Sstevel@tonic-gate 
1852*7c478bd9Sstevel@tonic-gate 	if (tabptr == NULL)
1853*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
1854*7c478bd9Sstevel@tonic-gate 
1855*7c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
1856*7c478bd9Sstevel@tonic-gate 		return (err);
1857*7c478bd9Sstevel@tonic-gate 
1858*7c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_delete_attr_core(handle, tabptr)) != Z_OK)
1859*7c478bd9Sstevel@tonic-gate 		return (err);
1860*7c478bd9Sstevel@tonic-gate 
1861*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
1862*7c478bd9Sstevel@tonic-gate }
1863*7c478bd9Sstevel@tonic-gate 
1864*7c478bd9Sstevel@tonic-gate int
1865*7c478bd9Sstevel@tonic-gate zonecfg_modify_attr(
1866*7c478bd9Sstevel@tonic-gate 	zone_dochandle_t handle,
1867*7c478bd9Sstevel@tonic-gate 	struct zone_attrtab *oldtabptr,
1868*7c478bd9Sstevel@tonic-gate 	struct zone_attrtab *newtabptr)
1869*7c478bd9Sstevel@tonic-gate {
1870*7c478bd9Sstevel@tonic-gate 	int err;
1871*7c478bd9Sstevel@tonic-gate 
1872*7c478bd9Sstevel@tonic-gate 	if (oldtabptr == NULL || newtabptr == NULL)
1873*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
1874*7c478bd9Sstevel@tonic-gate 
1875*7c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
1876*7c478bd9Sstevel@tonic-gate 		return (err);
1877*7c478bd9Sstevel@tonic-gate 
1878*7c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_delete_attr_core(handle, oldtabptr)) != Z_OK)
1879*7c478bd9Sstevel@tonic-gate 		return (err);
1880*7c478bd9Sstevel@tonic-gate 
1881*7c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_add_attr_core(handle, newtabptr)) != Z_OK)
1882*7c478bd9Sstevel@tonic-gate 		return (err);
1883*7c478bd9Sstevel@tonic-gate 
1884*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
1885*7c478bd9Sstevel@tonic-gate }
1886*7c478bd9Sstevel@tonic-gate 
1887*7c478bd9Sstevel@tonic-gate int
1888*7c478bd9Sstevel@tonic-gate zonecfg_get_attr_boolean(const struct zone_attrtab *attr, boolean_t *value)
1889*7c478bd9Sstevel@tonic-gate {
1890*7c478bd9Sstevel@tonic-gate 	if (attr == NULL)
1891*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
1892*7c478bd9Sstevel@tonic-gate 
1893*7c478bd9Sstevel@tonic-gate 	if (strcmp(attr->zone_attr_type, DTD_ENTITY_BOOLEAN) != 0)
1894*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
1895*7c478bd9Sstevel@tonic-gate 
1896*7c478bd9Sstevel@tonic-gate 	if (strcmp(attr->zone_attr_value, DTD_ENTITY_TRUE) == 0) {
1897*7c478bd9Sstevel@tonic-gate 		*value = B_TRUE;
1898*7c478bd9Sstevel@tonic-gate 		return (Z_OK);
1899*7c478bd9Sstevel@tonic-gate 	}
1900*7c478bd9Sstevel@tonic-gate 	if (strcmp(attr->zone_attr_value, DTD_ENTITY_FALSE) == 0) {
1901*7c478bd9Sstevel@tonic-gate 		*value = B_FALSE;
1902*7c478bd9Sstevel@tonic-gate 		return (Z_OK);
1903*7c478bd9Sstevel@tonic-gate 	}
1904*7c478bd9Sstevel@tonic-gate 	return (Z_INVAL);
1905*7c478bd9Sstevel@tonic-gate }
1906*7c478bd9Sstevel@tonic-gate 
1907*7c478bd9Sstevel@tonic-gate int
1908*7c478bd9Sstevel@tonic-gate zonecfg_get_attr_int(const struct zone_attrtab *attr, int64_t *value)
1909*7c478bd9Sstevel@tonic-gate {
1910*7c478bd9Sstevel@tonic-gate 	long long result;
1911*7c478bd9Sstevel@tonic-gate 	char *endptr;
1912*7c478bd9Sstevel@tonic-gate 
1913*7c478bd9Sstevel@tonic-gate 	if (attr == NULL)
1914*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
1915*7c478bd9Sstevel@tonic-gate 
1916*7c478bd9Sstevel@tonic-gate 	if (strcmp(attr->zone_attr_type, DTD_ENTITY_INT) != 0)
1917*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
1918*7c478bd9Sstevel@tonic-gate 
1919*7c478bd9Sstevel@tonic-gate 	errno = 0;
1920*7c478bd9Sstevel@tonic-gate 	result = strtoll(attr->zone_attr_value, &endptr, 10);
1921*7c478bd9Sstevel@tonic-gate 	if (errno != 0 || *endptr != '\0')
1922*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
1923*7c478bd9Sstevel@tonic-gate 	*value = result;
1924*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
1925*7c478bd9Sstevel@tonic-gate }
1926*7c478bd9Sstevel@tonic-gate 
1927*7c478bd9Sstevel@tonic-gate int
1928*7c478bd9Sstevel@tonic-gate zonecfg_get_attr_string(const struct zone_attrtab *attr, char *value,
1929*7c478bd9Sstevel@tonic-gate     size_t val_sz)
1930*7c478bd9Sstevel@tonic-gate {
1931*7c478bd9Sstevel@tonic-gate 	if (attr == NULL)
1932*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
1933*7c478bd9Sstevel@tonic-gate 
1934*7c478bd9Sstevel@tonic-gate 	if (strcmp(attr->zone_attr_type, DTD_ENTITY_STRING) != 0)
1935*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
1936*7c478bd9Sstevel@tonic-gate 
1937*7c478bd9Sstevel@tonic-gate 	if (strlcpy(value, attr->zone_attr_value, val_sz) >= val_sz)
1938*7c478bd9Sstevel@tonic-gate 		return (Z_TOO_BIG);
1939*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
1940*7c478bd9Sstevel@tonic-gate }
1941*7c478bd9Sstevel@tonic-gate 
1942*7c478bd9Sstevel@tonic-gate int
1943*7c478bd9Sstevel@tonic-gate zonecfg_get_attr_uint(const struct zone_attrtab *attr, uint64_t *value)
1944*7c478bd9Sstevel@tonic-gate {
1945*7c478bd9Sstevel@tonic-gate 	unsigned long long result;
1946*7c478bd9Sstevel@tonic-gate 	long long neg_result;
1947*7c478bd9Sstevel@tonic-gate 	char *endptr;
1948*7c478bd9Sstevel@tonic-gate 
1949*7c478bd9Sstevel@tonic-gate 	if (attr == NULL)
1950*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
1951*7c478bd9Sstevel@tonic-gate 
1952*7c478bd9Sstevel@tonic-gate 	if (strcmp(attr->zone_attr_type, DTD_ENTITY_UINT) != 0)
1953*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
1954*7c478bd9Sstevel@tonic-gate 
1955*7c478bd9Sstevel@tonic-gate 	errno = 0;
1956*7c478bd9Sstevel@tonic-gate 	result = strtoull(attr->zone_attr_value, &endptr, 10);
1957*7c478bd9Sstevel@tonic-gate 	if (errno != 0 || *endptr != '\0')
1958*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
1959*7c478bd9Sstevel@tonic-gate 	errno = 0;
1960*7c478bd9Sstevel@tonic-gate 	neg_result = strtoll(attr->zone_attr_value, &endptr, 10);
1961*7c478bd9Sstevel@tonic-gate 	/*
1962*7c478bd9Sstevel@tonic-gate 	 * Incredibly, strtoull("<negative number>", ...) will not fail but
1963*7c478bd9Sstevel@tonic-gate 	 * return whatever (negative) number cast as a u_longlong_t, so we
1964*7c478bd9Sstevel@tonic-gate 	 * need to look for this here.
1965*7c478bd9Sstevel@tonic-gate 	 */
1966*7c478bd9Sstevel@tonic-gate 	if (errno == 0 && neg_result < 0)
1967*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
1968*7c478bd9Sstevel@tonic-gate 	*value = result;
1969*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
1970*7c478bd9Sstevel@tonic-gate }
1971*7c478bd9Sstevel@tonic-gate 
1972*7c478bd9Sstevel@tonic-gate int
1973*7c478bd9Sstevel@tonic-gate zonecfg_lookup_rctl(zone_dochandle_t handle, struct zone_rctltab *tabptr)
1974*7c478bd9Sstevel@tonic-gate {
1975*7c478bd9Sstevel@tonic-gate 	xmlNodePtr cur, val;
1976*7c478bd9Sstevel@tonic-gate 	char savedname[MAXNAMELEN];
1977*7c478bd9Sstevel@tonic-gate 	struct zone_rctlvaltab *valptr;
1978*7c478bd9Sstevel@tonic-gate 	int err;
1979*7c478bd9Sstevel@tonic-gate 
1980*7c478bd9Sstevel@tonic-gate 	if (tabptr->zone_rctl_name == NULL ||
1981*7c478bd9Sstevel@tonic-gate 	    strlen(tabptr->zone_rctl_name) == 0)
1982*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
1983*7c478bd9Sstevel@tonic-gate 
1984*7c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
1985*7c478bd9Sstevel@tonic-gate 		return (err);
1986*7c478bd9Sstevel@tonic-gate 
1987*7c478bd9Sstevel@tonic-gate 	cur = handle->zone_dh_cur;
1988*7c478bd9Sstevel@tonic-gate 	for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
1989*7c478bd9Sstevel@tonic-gate 		if (xmlStrcmp(cur->name, DTD_ELEM_RCTL))
1990*7c478bd9Sstevel@tonic-gate 			continue;
1991*7c478bd9Sstevel@tonic-gate 		if ((fetchprop(cur, DTD_ATTR_NAME, savedname,
1992*7c478bd9Sstevel@tonic-gate 		    sizeof (savedname)) == Z_OK) &&
1993*7c478bd9Sstevel@tonic-gate 		    (strcmp(savedname, tabptr->zone_rctl_name) == 0)) {
1994*7c478bd9Sstevel@tonic-gate 			tabptr->zone_rctl_valptr = NULL;
1995*7c478bd9Sstevel@tonic-gate 			for (val = cur->xmlChildrenNode; val != NULL;
1996*7c478bd9Sstevel@tonic-gate 			    val = val->next) {
1997*7c478bd9Sstevel@tonic-gate 				valptr = (struct zone_rctlvaltab *)malloc(
1998*7c478bd9Sstevel@tonic-gate 				    sizeof (struct zone_rctlvaltab));
1999*7c478bd9Sstevel@tonic-gate 				if (valptr == NULL)
2000*7c478bd9Sstevel@tonic-gate 					return (Z_NOMEM);
2001*7c478bd9Sstevel@tonic-gate 				if ((fetchprop(val, DTD_ATTR_PRIV,
2002*7c478bd9Sstevel@tonic-gate 				    valptr->zone_rctlval_priv,
2003*7c478bd9Sstevel@tonic-gate 				    sizeof (valptr->zone_rctlval_priv)) !=
2004*7c478bd9Sstevel@tonic-gate 				    Z_OK))
2005*7c478bd9Sstevel@tonic-gate 					break;
2006*7c478bd9Sstevel@tonic-gate 				if ((fetchprop(val, DTD_ATTR_LIMIT,
2007*7c478bd9Sstevel@tonic-gate 				    valptr->zone_rctlval_limit,
2008*7c478bd9Sstevel@tonic-gate 				    sizeof (valptr->zone_rctlval_limit)) !=
2009*7c478bd9Sstevel@tonic-gate 				    Z_OK))
2010*7c478bd9Sstevel@tonic-gate 					break;
2011*7c478bd9Sstevel@tonic-gate 				if ((fetchprop(val, DTD_ATTR_ACTION,
2012*7c478bd9Sstevel@tonic-gate 				    valptr->zone_rctlval_action,
2013*7c478bd9Sstevel@tonic-gate 				    sizeof (valptr->zone_rctlval_action)) !=
2014*7c478bd9Sstevel@tonic-gate 				    Z_OK))
2015*7c478bd9Sstevel@tonic-gate 					break;
2016*7c478bd9Sstevel@tonic-gate 				if (zonecfg_add_rctl_value(tabptr, valptr) !=
2017*7c478bd9Sstevel@tonic-gate 				    Z_OK)
2018*7c478bd9Sstevel@tonic-gate 					break;
2019*7c478bd9Sstevel@tonic-gate 			}
2020*7c478bd9Sstevel@tonic-gate 			return (Z_OK);
2021*7c478bd9Sstevel@tonic-gate 		}
2022*7c478bd9Sstevel@tonic-gate 	}
2023*7c478bd9Sstevel@tonic-gate 	return (Z_NO_RESOURCE_ID);
2024*7c478bd9Sstevel@tonic-gate }
2025*7c478bd9Sstevel@tonic-gate 
2026*7c478bd9Sstevel@tonic-gate static int
2027*7c478bd9Sstevel@tonic-gate zonecfg_add_rctl_core(zone_dochandle_t handle, struct zone_rctltab *tabptr)
2028*7c478bd9Sstevel@tonic-gate {
2029*7c478bd9Sstevel@tonic-gate 	xmlNodePtr newnode, cur = handle->zone_dh_cur, valnode;
2030*7c478bd9Sstevel@tonic-gate 	struct zone_rctlvaltab *valptr;
2031*7c478bd9Sstevel@tonic-gate 	int err;
2032*7c478bd9Sstevel@tonic-gate 
2033*7c478bd9Sstevel@tonic-gate 	newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_RCTL, NULL);
2034*7c478bd9Sstevel@tonic-gate 	err = newprop(handle, newnode, DTD_ATTR_NAME, tabptr->zone_rctl_name);
2035*7c478bd9Sstevel@tonic-gate 	if (err != Z_OK)
2036*7c478bd9Sstevel@tonic-gate 		return (err);
2037*7c478bd9Sstevel@tonic-gate 	for (valptr = tabptr->zone_rctl_valptr; valptr != NULL;
2038*7c478bd9Sstevel@tonic-gate 	    valptr = valptr->zone_rctlval_next) {
2039*7c478bd9Sstevel@tonic-gate 		valnode = xmlNewTextChild(newnode, NULL,
2040*7c478bd9Sstevel@tonic-gate 		    DTD_ELEM_RCTLVALUE, NULL);
2041*7c478bd9Sstevel@tonic-gate 		err = newprop(handle, valnode, DTD_ATTR_PRIV,
2042*7c478bd9Sstevel@tonic-gate 		    valptr->zone_rctlval_priv);
2043*7c478bd9Sstevel@tonic-gate 		if (err != Z_OK)
2044*7c478bd9Sstevel@tonic-gate 			return (err);
2045*7c478bd9Sstevel@tonic-gate 		err = newprop(handle, valnode, DTD_ATTR_LIMIT,
2046*7c478bd9Sstevel@tonic-gate 		    valptr->zone_rctlval_limit);
2047*7c478bd9Sstevel@tonic-gate 		if (err != Z_OK)
2048*7c478bd9Sstevel@tonic-gate 			return (err);
2049*7c478bd9Sstevel@tonic-gate 		err = newprop(handle, valnode, DTD_ATTR_ACTION,
2050*7c478bd9Sstevel@tonic-gate 		    valptr->zone_rctlval_action);
2051*7c478bd9Sstevel@tonic-gate 		if (err != Z_OK)
2052*7c478bd9Sstevel@tonic-gate 			return (err);
2053*7c478bd9Sstevel@tonic-gate 	}
2054*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
2055*7c478bd9Sstevel@tonic-gate }
2056*7c478bd9Sstevel@tonic-gate 
2057*7c478bd9Sstevel@tonic-gate int
2058*7c478bd9Sstevel@tonic-gate zonecfg_add_rctl(zone_dochandle_t handle, struct zone_rctltab *tabptr)
2059*7c478bd9Sstevel@tonic-gate {
2060*7c478bd9Sstevel@tonic-gate 	int err;
2061*7c478bd9Sstevel@tonic-gate 
2062*7c478bd9Sstevel@tonic-gate 	if (tabptr == NULL || tabptr->zone_rctl_name == NULL)
2063*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
2064*7c478bd9Sstevel@tonic-gate 
2065*7c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
2066*7c478bd9Sstevel@tonic-gate 		return (err);
2067*7c478bd9Sstevel@tonic-gate 
2068*7c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_add_rctl_core(handle, tabptr)) != Z_OK)
2069*7c478bd9Sstevel@tonic-gate 		return (err);
2070*7c478bd9Sstevel@tonic-gate 
2071*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
2072*7c478bd9Sstevel@tonic-gate }
2073*7c478bd9Sstevel@tonic-gate 
2074*7c478bd9Sstevel@tonic-gate static int
2075*7c478bd9Sstevel@tonic-gate zonecfg_delete_rctl_core(zone_dochandle_t handle, struct zone_rctltab *tabptr)
2076*7c478bd9Sstevel@tonic-gate {
2077*7c478bd9Sstevel@tonic-gate 	xmlNodePtr cur = handle->zone_dh_cur;
2078*7c478bd9Sstevel@tonic-gate 	xmlChar *savedname;
2079*7c478bd9Sstevel@tonic-gate 	int name_result;
2080*7c478bd9Sstevel@tonic-gate 
2081*7c478bd9Sstevel@tonic-gate 	for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
2082*7c478bd9Sstevel@tonic-gate 		if (xmlStrcmp(cur->name, DTD_ELEM_RCTL))
2083*7c478bd9Sstevel@tonic-gate 			continue;
2084*7c478bd9Sstevel@tonic-gate 
2085*7c478bd9Sstevel@tonic-gate 		savedname = xmlGetProp(cur, DTD_ATTR_NAME);
2086*7c478bd9Sstevel@tonic-gate 		if (savedname == NULL)	/* shouldn't happen */
2087*7c478bd9Sstevel@tonic-gate 			continue;
2088*7c478bd9Sstevel@tonic-gate 		name_result = xmlStrcmp(savedname,
2089*7c478bd9Sstevel@tonic-gate 		    (const xmlChar *) tabptr->zone_rctl_name);
2090*7c478bd9Sstevel@tonic-gate 		xmlFree(savedname);
2091*7c478bd9Sstevel@tonic-gate 
2092*7c478bd9Sstevel@tonic-gate 		if (name_result == 0) {
2093*7c478bd9Sstevel@tonic-gate 			xmlUnlinkNode(cur);
2094*7c478bd9Sstevel@tonic-gate 			xmlFreeNode(cur);
2095*7c478bd9Sstevel@tonic-gate 			return (Z_OK);
2096*7c478bd9Sstevel@tonic-gate 		}
2097*7c478bd9Sstevel@tonic-gate 	}
2098*7c478bd9Sstevel@tonic-gate 	return (Z_NO_RESOURCE_ID);
2099*7c478bd9Sstevel@tonic-gate }
2100*7c478bd9Sstevel@tonic-gate 
2101*7c478bd9Sstevel@tonic-gate int
2102*7c478bd9Sstevel@tonic-gate zonecfg_delete_rctl(zone_dochandle_t handle, struct zone_rctltab *tabptr)
2103*7c478bd9Sstevel@tonic-gate {
2104*7c478bd9Sstevel@tonic-gate 	int err;
2105*7c478bd9Sstevel@tonic-gate 
2106*7c478bd9Sstevel@tonic-gate 	if (tabptr == NULL || tabptr->zone_rctl_name == NULL)
2107*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
2108*7c478bd9Sstevel@tonic-gate 
2109*7c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
2110*7c478bd9Sstevel@tonic-gate 		return (err);
2111*7c478bd9Sstevel@tonic-gate 
2112*7c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_delete_rctl_core(handle, tabptr)) != Z_OK)
2113*7c478bd9Sstevel@tonic-gate 		return (err);
2114*7c478bd9Sstevel@tonic-gate 
2115*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
2116*7c478bd9Sstevel@tonic-gate }
2117*7c478bd9Sstevel@tonic-gate 
2118*7c478bd9Sstevel@tonic-gate int
2119*7c478bd9Sstevel@tonic-gate zonecfg_modify_rctl(
2120*7c478bd9Sstevel@tonic-gate 	zone_dochandle_t handle,
2121*7c478bd9Sstevel@tonic-gate 	struct zone_rctltab *oldtabptr,
2122*7c478bd9Sstevel@tonic-gate 	struct zone_rctltab *newtabptr)
2123*7c478bd9Sstevel@tonic-gate {
2124*7c478bd9Sstevel@tonic-gate 	int err;
2125*7c478bd9Sstevel@tonic-gate 
2126*7c478bd9Sstevel@tonic-gate 	if (oldtabptr == NULL || oldtabptr->zone_rctl_name == NULL ||
2127*7c478bd9Sstevel@tonic-gate 	    newtabptr == NULL || newtabptr->zone_rctl_name == NULL)
2128*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
2129*7c478bd9Sstevel@tonic-gate 
2130*7c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK)
2131*7c478bd9Sstevel@tonic-gate 		return (err);
2132*7c478bd9Sstevel@tonic-gate 
2133*7c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_delete_rctl_core(handle, oldtabptr)) != Z_OK)
2134*7c478bd9Sstevel@tonic-gate 		return (err);
2135*7c478bd9Sstevel@tonic-gate 
2136*7c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_add_rctl_core(handle, newtabptr)) != Z_OK)
2137*7c478bd9Sstevel@tonic-gate 		return (err);
2138*7c478bd9Sstevel@tonic-gate 
2139*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
2140*7c478bd9Sstevel@tonic-gate }
2141*7c478bd9Sstevel@tonic-gate 
2142*7c478bd9Sstevel@tonic-gate int
2143*7c478bd9Sstevel@tonic-gate zonecfg_add_rctl_value(
2144*7c478bd9Sstevel@tonic-gate 	struct zone_rctltab *tabptr,
2145*7c478bd9Sstevel@tonic-gate 	struct zone_rctlvaltab *valtabptr)
2146*7c478bd9Sstevel@tonic-gate {
2147*7c478bd9Sstevel@tonic-gate 	struct zone_rctlvaltab *last, *old, *new;
2148*7c478bd9Sstevel@tonic-gate 	rctlblk_t *rctlblk = alloca(rctlblk_size());
2149*7c478bd9Sstevel@tonic-gate 
2150*7c478bd9Sstevel@tonic-gate 	last = tabptr->zone_rctl_valptr;
2151*7c478bd9Sstevel@tonic-gate 	for (old = last; old != NULL; old = old->zone_rctlval_next)
2152*7c478bd9Sstevel@tonic-gate 		last = old;	/* walk to the end of the list */
2153*7c478bd9Sstevel@tonic-gate 	new = valtabptr;	/* alloc'd by caller */
2154*7c478bd9Sstevel@tonic-gate 	new->zone_rctlval_next = NULL;
2155*7c478bd9Sstevel@tonic-gate 	if (zonecfg_construct_rctlblk(valtabptr, rctlblk) != Z_OK)
2156*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
2157*7c478bd9Sstevel@tonic-gate 	if (!zonecfg_valid_rctlblk(rctlblk))
2158*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
2159*7c478bd9Sstevel@tonic-gate 	if (last == NULL)
2160*7c478bd9Sstevel@tonic-gate 		tabptr->zone_rctl_valptr = new;
2161*7c478bd9Sstevel@tonic-gate 	else
2162*7c478bd9Sstevel@tonic-gate 		last->zone_rctlval_next = new;
2163*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
2164*7c478bd9Sstevel@tonic-gate }
2165*7c478bd9Sstevel@tonic-gate 
2166*7c478bd9Sstevel@tonic-gate int
2167*7c478bd9Sstevel@tonic-gate zonecfg_remove_rctl_value(
2168*7c478bd9Sstevel@tonic-gate 	struct zone_rctltab *tabptr,
2169*7c478bd9Sstevel@tonic-gate 	struct zone_rctlvaltab *valtabptr)
2170*7c478bd9Sstevel@tonic-gate {
2171*7c478bd9Sstevel@tonic-gate 	struct zone_rctlvaltab *last, *this, *next;
2172*7c478bd9Sstevel@tonic-gate 
2173*7c478bd9Sstevel@tonic-gate 	last = tabptr->zone_rctl_valptr;
2174*7c478bd9Sstevel@tonic-gate 	for (this = last; this != NULL; this = this->zone_rctlval_next) {
2175*7c478bd9Sstevel@tonic-gate 		if (strcmp(this->zone_rctlval_priv,
2176*7c478bd9Sstevel@tonic-gate 		    valtabptr->zone_rctlval_priv) == 0 &&
2177*7c478bd9Sstevel@tonic-gate 		    strcmp(this->zone_rctlval_limit,
2178*7c478bd9Sstevel@tonic-gate 		    valtabptr->zone_rctlval_limit) == 0 &&
2179*7c478bd9Sstevel@tonic-gate 		    strcmp(this->zone_rctlval_action,
2180*7c478bd9Sstevel@tonic-gate 		    valtabptr->zone_rctlval_action) == 0) {
2181*7c478bd9Sstevel@tonic-gate 			next = this->zone_rctlval_next;
2182*7c478bd9Sstevel@tonic-gate 			if (this == tabptr->zone_rctl_valptr)
2183*7c478bd9Sstevel@tonic-gate 				tabptr->zone_rctl_valptr = next;
2184*7c478bd9Sstevel@tonic-gate 			else
2185*7c478bd9Sstevel@tonic-gate 				last->zone_rctlval_next = next;
2186*7c478bd9Sstevel@tonic-gate 			free(this);
2187*7c478bd9Sstevel@tonic-gate 			return (Z_OK);
2188*7c478bd9Sstevel@tonic-gate 		} else
2189*7c478bd9Sstevel@tonic-gate 			last = this;
2190*7c478bd9Sstevel@tonic-gate 	}
2191*7c478bd9Sstevel@tonic-gate 	return (Z_NO_PROPERTY_ID);
2192*7c478bd9Sstevel@tonic-gate }
2193*7c478bd9Sstevel@tonic-gate 
2194*7c478bd9Sstevel@tonic-gate char *
2195*7c478bd9Sstevel@tonic-gate zonecfg_strerror(int errnum)
2196*7c478bd9Sstevel@tonic-gate {
2197*7c478bd9Sstevel@tonic-gate 	switch (errnum) {
2198*7c478bd9Sstevel@tonic-gate 	case Z_OK:
2199*7c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "OK"));
2200*7c478bd9Sstevel@tonic-gate 	case Z_EMPTY_DOCUMENT:
2201*7c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Empty document"));
2202*7c478bd9Sstevel@tonic-gate 	case Z_WRONG_DOC_TYPE:
2203*7c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Wrong document type"));
2204*7c478bd9Sstevel@tonic-gate 	case Z_BAD_PROPERTY:
2205*7c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Bad document property"));
2206*7c478bd9Sstevel@tonic-gate 	case Z_TEMP_FILE:
2207*7c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN,
2208*7c478bd9Sstevel@tonic-gate 		    "Problem creating temporary file"));
2209*7c478bd9Sstevel@tonic-gate 	case Z_SAVING_FILE:
2210*7c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Problem saving file"));
2211*7c478bd9Sstevel@tonic-gate 	case Z_NO_ENTRY:
2212*7c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "No such entry"));
2213*7c478bd9Sstevel@tonic-gate 	case Z_BOGUS_ZONE_NAME:
2214*7c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Bogus zone name"));
2215*7c478bd9Sstevel@tonic-gate 	case Z_REQD_RESOURCE_MISSING:
2216*7c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Required resource missing"));
2217*7c478bd9Sstevel@tonic-gate 	case Z_REQD_PROPERTY_MISSING:
2218*7c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Required property missing"));
2219*7c478bd9Sstevel@tonic-gate 	case Z_BAD_HANDLE:
2220*7c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Bad handle"));
2221*7c478bd9Sstevel@tonic-gate 	case Z_NOMEM:
2222*7c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Out of memory"));
2223*7c478bd9Sstevel@tonic-gate 	case Z_INVAL:
2224*7c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Invalid argument"));
2225*7c478bd9Sstevel@tonic-gate 	case Z_ACCES:
2226*7c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Permission denied"));
2227*7c478bd9Sstevel@tonic-gate 	case Z_TOO_BIG:
2228*7c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Argument list too long"));
2229*7c478bd9Sstevel@tonic-gate 	case Z_MISC_FS:
2230*7c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN,
2231*7c478bd9Sstevel@tonic-gate 		    "Miscellaneous file system error"));
2232*7c478bd9Sstevel@tonic-gate 	case Z_NO_ZONE:
2233*7c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "No such zone configured"));
2234*7c478bd9Sstevel@tonic-gate 	case Z_NO_RESOURCE_TYPE:
2235*7c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "No such resource type"));
2236*7c478bd9Sstevel@tonic-gate 	case Z_NO_RESOURCE_ID:
2237*7c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "No such resource with that id"));
2238*7c478bd9Sstevel@tonic-gate 	case Z_NO_PROPERTY_TYPE:
2239*7c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "No such property type"));
2240*7c478bd9Sstevel@tonic-gate 	case Z_NO_PROPERTY_ID:
2241*7c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "No such property with that id"));
2242*7c478bd9Sstevel@tonic-gate 	case Z_RESOURCE_EXISTS:
2243*7c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN,
2244*7c478bd9Sstevel@tonic-gate 		    "Resource already exists with that id"));
2245*7c478bd9Sstevel@tonic-gate 	case Z_INVALID_DOCUMENT:
2246*7c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Invalid document"));
2247*7c478bd9Sstevel@tonic-gate 	case Z_ID_IN_USE:
2248*7c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Zone ID in use"));
2249*7c478bd9Sstevel@tonic-gate 	case Z_NO_SUCH_ID:
2250*7c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "No such zone ID"));
2251*7c478bd9Sstevel@tonic-gate 	case Z_UPDATING_INDEX:
2252*7c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Problem updating index file"));
2253*7c478bd9Sstevel@tonic-gate 	case Z_LOCKING_FILE:
2254*7c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Locking index file"));
2255*7c478bd9Sstevel@tonic-gate 	case Z_UNLOCKING_FILE:
2256*7c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Unlocking index file"));
2257*7c478bd9Sstevel@tonic-gate 	case Z_INSUFFICIENT_SPEC:
2258*7c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Insufficient specification"));
2259*7c478bd9Sstevel@tonic-gate 	case Z_RESOLVED_PATH:
2260*7c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Resolved path mismatch"));
2261*7c478bd9Sstevel@tonic-gate 	case Z_IPV6_ADDR_PREFIX_LEN:
2262*7c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN,
2263*7c478bd9Sstevel@tonic-gate 		    "IPv6 address missing required prefix length"));
2264*7c478bd9Sstevel@tonic-gate 	case Z_BOGUS_ADDRESS:
2265*7c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN,
2266*7c478bd9Sstevel@tonic-gate 		    "Neither an IPv4 nor an IPv6 address nor a host name"));
2267*7c478bd9Sstevel@tonic-gate 	default:
2268*7c478bd9Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Unknown error"));
2269*7c478bd9Sstevel@tonic-gate 	}
2270*7c478bd9Sstevel@tonic-gate }
2271*7c478bd9Sstevel@tonic-gate 
2272*7c478bd9Sstevel@tonic-gate /*
2273*7c478bd9Sstevel@tonic-gate  * Note that the zonecfg_setXent() and zonecfg_endXent() calls are all the
2274*7c478bd9Sstevel@tonic-gate  * same, as they just turn around and call zonecfg_setent() / zonecfg_endent().
2275*7c478bd9Sstevel@tonic-gate  */
2276*7c478bd9Sstevel@tonic-gate 
2277*7c478bd9Sstevel@tonic-gate static int
2278*7c478bd9Sstevel@tonic-gate zonecfg_setent(zone_dochandle_t handle)
2279*7c478bd9Sstevel@tonic-gate {
2280*7c478bd9Sstevel@tonic-gate 	xmlNodePtr cur;
2281*7c478bd9Sstevel@tonic-gate 	int err;
2282*7c478bd9Sstevel@tonic-gate 
2283*7c478bd9Sstevel@tonic-gate 	if (handle == NULL)
2284*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
2285*7c478bd9Sstevel@tonic-gate 
2286*7c478bd9Sstevel@tonic-gate 	if ((err = operation_prep(handle)) != Z_OK) {
2287*7c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = NULL;
2288*7c478bd9Sstevel@tonic-gate 		return (err);
2289*7c478bd9Sstevel@tonic-gate 	}
2290*7c478bd9Sstevel@tonic-gate 	cur = handle->zone_dh_cur;
2291*7c478bd9Sstevel@tonic-gate 	cur = cur->xmlChildrenNode;
2292*7c478bd9Sstevel@tonic-gate 	handle->zone_dh_cur = cur;
2293*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
2294*7c478bd9Sstevel@tonic-gate }
2295*7c478bd9Sstevel@tonic-gate 
2296*7c478bd9Sstevel@tonic-gate static int
2297*7c478bd9Sstevel@tonic-gate zonecfg_endent(zone_dochandle_t handle)
2298*7c478bd9Sstevel@tonic-gate {
2299*7c478bd9Sstevel@tonic-gate 	if (handle == NULL)
2300*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
2301*7c478bd9Sstevel@tonic-gate 
2302*7c478bd9Sstevel@tonic-gate 	handle->zone_dh_cur = handle->zone_dh_top;
2303*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
2304*7c478bd9Sstevel@tonic-gate }
2305*7c478bd9Sstevel@tonic-gate 
2306*7c478bd9Sstevel@tonic-gate int
2307*7c478bd9Sstevel@tonic-gate zonecfg_setfsent(zone_dochandle_t handle)
2308*7c478bd9Sstevel@tonic-gate {
2309*7c478bd9Sstevel@tonic-gate 	return (zonecfg_setent(handle));
2310*7c478bd9Sstevel@tonic-gate }
2311*7c478bd9Sstevel@tonic-gate 
2312*7c478bd9Sstevel@tonic-gate int
2313*7c478bd9Sstevel@tonic-gate zonecfg_getfsent(zone_dochandle_t handle, struct zone_fstab *tabptr)
2314*7c478bd9Sstevel@tonic-gate {
2315*7c478bd9Sstevel@tonic-gate 	xmlNodePtr cur, options;
2316*7c478bd9Sstevel@tonic-gate 	char options_str[MAX_MNTOPT_STR];
2317*7c478bd9Sstevel@tonic-gate 	int err;
2318*7c478bd9Sstevel@tonic-gate 
2319*7c478bd9Sstevel@tonic-gate 	if (handle == NULL)
2320*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
2321*7c478bd9Sstevel@tonic-gate 
2322*7c478bd9Sstevel@tonic-gate 	if ((cur = handle->zone_dh_cur) == NULL)
2323*7c478bd9Sstevel@tonic-gate 		return (Z_NO_ENTRY);
2324*7c478bd9Sstevel@tonic-gate 
2325*7c478bd9Sstevel@tonic-gate 	for (; cur != NULL; cur = cur->next)
2326*7c478bd9Sstevel@tonic-gate 		if (!xmlStrcmp(cur->name, DTD_ELEM_FS))
2327*7c478bd9Sstevel@tonic-gate 			break;
2328*7c478bd9Sstevel@tonic-gate 	if (cur == NULL) {
2329*7c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = handle->zone_dh_top;
2330*7c478bd9Sstevel@tonic-gate 		return (Z_NO_ENTRY);
2331*7c478bd9Sstevel@tonic-gate 	}
2332*7c478bd9Sstevel@tonic-gate 
2333*7c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_SPECIAL, tabptr->zone_fs_special,
2334*7c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_fs_special))) != Z_OK) {
2335*7c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = handle->zone_dh_top;
2336*7c478bd9Sstevel@tonic-gate 		return (err);
2337*7c478bd9Sstevel@tonic-gate 	}
2338*7c478bd9Sstevel@tonic-gate 
2339*7c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_RAW, tabptr->zone_fs_raw,
2340*7c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_fs_raw))) != Z_OK) {
2341*7c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = handle->zone_dh_top;
2342*7c478bd9Sstevel@tonic-gate 		return (err);
2343*7c478bd9Sstevel@tonic-gate 	}
2344*7c478bd9Sstevel@tonic-gate 
2345*7c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir,
2346*7c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_fs_dir))) != Z_OK) {
2347*7c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = handle->zone_dh_top;
2348*7c478bd9Sstevel@tonic-gate 		return (err);
2349*7c478bd9Sstevel@tonic-gate 	}
2350*7c478bd9Sstevel@tonic-gate 
2351*7c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_TYPE, tabptr->zone_fs_type,
2352*7c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_fs_type))) != Z_OK) {
2353*7c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = handle->zone_dh_top;
2354*7c478bd9Sstevel@tonic-gate 		return (err);
2355*7c478bd9Sstevel@tonic-gate 	}
2356*7c478bd9Sstevel@tonic-gate 
2357*7c478bd9Sstevel@tonic-gate 	/* OK for options to be NULL */
2358*7c478bd9Sstevel@tonic-gate 	tabptr->zone_fs_options = NULL;
2359*7c478bd9Sstevel@tonic-gate 	for (options = cur->xmlChildrenNode; options != NULL;
2360*7c478bd9Sstevel@tonic-gate 	    options = options->next) {
2361*7c478bd9Sstevel@tonic-gate 		if (fetchprop(options, DTD_ATTR_NAME, options_str,
2362*7c478bd9Sstevel@tonic-gate 		    sizeof (options_str)) != Z_OK)
2363*7c478bd9Sstevel@tonic-gate 			break;
2364*7c478bd9Sstevel@tonic-gate 		if (zonecfg_add_fs_option(tabptr, options_str) != Z_OK)
2365*7c478bd9Sstevel@tonic-gate 			break;
2366*7c478bd9Sstevel@tonic-gate 	}
2367*7c478bd9Sstevel@tonic-gate 
2368*7c478bd9Sstevel@tonic-gate 	handle->zone_dh_cur = cur->next;
2369*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
2370*7c478bd9Sstevel@tonic-gate }
2371*7c478bd9Sstevel@tonic-gate 
2372*7c478bd9Sstevel@tonic-gate int
2373*7c478bd9Sstevel@tonic-gate zonecfg_endfsent(zone_dochandle_t handle)
2374*7c478bd9Sstevel@tonic-gate {
2375*7c478bd9Sstevel@tonic-gate 	return (zonecfg_endent(handle));
2376*7c478bd9Sstevel@tonic-gate }
2377*7c478bd9Sstevel@tonic-gate 
2378*7c478bd9Sstevel@tonic-gate int
2379*7c478bd9Sstevel@tonic-gate zonecfg_setipdent(zone_dochandle_t handle)
2380*7c478bd9Sstevel@tonic-gate {
2381*7c478bd9Sstevel@tonic-gate 	return (zonecfg_setent(handle));
2382*7c478bd9Sstevel@tonic-gate }
2383*7c478bd9Sstevel@tonic-gate 
2384*7c478bd9Sstevel@tonic-gate int
2385*7c478bd9Sstevel@tonic-gate zonecfg_getipdent(zone_dochandle_t handle, struct zone_fstab *tabptr)
2386*7c478bd9Sstevel@tonic-gate {
2387*7c478bd9Sstevel@tonic-gate 	xmlNodePtr cur;
2388*7c478bd9Sstevel@tonic-gate 	int err;
2389*7c478bd9Sstevel@tonic-gate 
2390*7c478bd9Sstevel@tonic-gate 	if (handle == NULL)
2391*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
2392*7c478bd9Sstevel@tonic-gate 
2393*7c478bd9Sstevel@tonic-gate 	if ((cur = handle->zone_dh_cur) == NULL)
2394*7c478bd9Sstevel@tonic-gate 		return (Z_NO_ENTRY);
2395*7c478bd9Sstevel@tonic-gate 
2396*7c478bd9Sstevel@tonic-gate 	for (; cur != NULL; cur = cur->next)
2397*7c478bd9Sstevel@tonic-gate 		if (!xmlStrcmp(cur->name, DTD_ELEM_IPD))
2398*7c478bd9Sstevel@tonic-gate 			break;
2399*7c478bd9Sstevel@tonic-gate 	if (cur == NULL) {
2400*7c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = handle->zone_dh_top;
2401*7c478bd9Sstevel@tonic-gate 		return (Z_NO_ENTRY);
2402*7c478bd9Sstevel@tonic-gate 	}
2403*7c478bd9Sstevel@tonic-gate 
2404*7c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_DIR, tabptr->zone_fs_dir,
2405*7c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_fs_dir))) != Z_OK) {
2406*7c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = handle->zone_dh_top;
2407*7c478bd9Sstevel@tonic-gate 		return (err);
2408*7c478bd9Sstevel@tonic-gate 	}
2409*7c478bd9Sstevel@tonic-gate 
2410*7c478bd9Sstevel@tonic-gate 	handle->zone_dh_cur = cur->next;
2411*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
2412*7c478bd9Sstevel@tonic-gate }
2413*7c478bd9Sstevel@tonic-gate 
2414*7c478bd9Sstevel@tonic-gate int
2415*7c478bd9Sstevel@tonic-gate zonecfg_endipdent(zone_dochandle_t handle)
2416*7c478bd9Sstevel@tonic-gate {
2417*7c478bd9Sstevel@tonic-gate 	return (zonecfg_endent(handle));
2418*7c478bd9Sstevel@tonic-gate }
2419*7c478bd9Sstevel@tonic-gate 
2420*7c478bd9Sstevel@tonic-gate int
2421*7c478bd9Sstevel@tonic-gate zonecfg_setnwifent(zone_dochandle_t handle)
2422*7c478bd9Sstevel@tonic-gate {
2423*7c478bd9Sstevel@tonic-gate 	return (zonecfg_setent(handle));
2424*7c478bd9Sstevel@tonic-gate }
2425*7c478bd9Sstevel@tonic-gate 
2426*7c478bd9Sstevel@tonic-gate int
2427*7c478bd9Sstevel@tonic-gate zonecfg_getnwifent(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
2428*7c478bd9Sstevel@tonic-gate {
2429*7c478bd9Sstevel@tonic-gate 	xmlNodePtr cur;
2430*7c478bd9Sstevel@tonic-gate 	int err;
2431*7c478bd9Sstevel@tonic-gate 
2432*7c478bd9Sstevel@tonic-gate 	if (handle == NULL)
2433*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
2434*7c478bd9Sstevel@tonic-gate 
2435*7c478bd9Sstevel@tonic-gate 	if ((cur = handle->zone_dh_cur) == NULL)
2436*7c478bd9Sstevel@tonic-gate 		return (Z_NO_ENTRY);
2437*7c478bd9Sstevel@tonic-gate 
2438*7c478bd9Sstevel@tonic-gate 	for (; cur != NULL; cur = cur->next)
2439*7c478bd9Sstevel@tonic-gate 		if (!xmlStrcmp(cur->name, DTD_ELEM_NET))
2440*7c478bd9Sstevel@tonic-gate 			break;
2441*7c478bd9Sstevel@tonic-gate 	if (cur == NULL) {
2442*7c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = handle->zone_dh_top;
2443*7c478bd9Sstevel@tonic-gate 		return (Z_NO_ENTRY);
2444*7c478bd9Sstevel@tonic-gate 	}
2445*7c478bd9Sstevel@tonic-gate 
2446*7c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_ADDRESS, tabptr->zone_nwif_address,
2447*7c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_nwif_address))) != Z_OK) {
2448*7c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = handle->zone_dh_top;
2449*7c478bd9Sstevel@tonic-gate 		return (err);
2450*7c478bd9Sstevel@tonic-gate 	}
2451*7c478bd9Sstevel@tonic-gate 
2452*7c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_PHYSICAL, tabptr->zone_nwif_physical,
2453*7c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_nwif_physical))) != Z_OK) {
2454*7c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = handle->zone_dh_top;
2455*7c478bd9Sstevel@tonic-gate 		return (err);
2456*7c478bd9Sstevel@tonic-gate 	}
2457*7c478bd9Sstevel@tonic-gate 
2458*7c478bd9Sstevel@tonic-gate 	handle->zone_dh_cur = cur->next;
2459*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
2460*7c478bd9Sstevel@tonic-gate }
2461*7c478bd9Sstevel@tonic-gate 
2462*7c478bd9Sstevel@tonic-gate int
2463*7c478bd9Sstevel@tonic-gate zonecfg_endnwifent(zone_dochandle_t handle)
2464*7c478bd9Sstevel@tonic-gate {
2465*7c478bd9Sstevel@tonic-gate 	return (zonecfg_endent(handle));
2466*7c478bd9Sstevel@tonic-gate }
2467*7c478bd9Sstevel@tonic-gate 
2468*7c478bd9Sstevel@tonic-gate int
2469*7c478bd9Sstevel@tonic-gate zonecfg_setdevent(zone_dochandle_t handle)
2470*7c478bd9Sstevel@tonic-gate {
2471*7c478bd9Sstevel@tonic-gate 	return (zonecfg_setent(handle));
2472*7c478bd9Sstevel@tonic-gate }
2473*7c478bd9Sstevel@tonic-gate 
2474*7c478bd9Sstevel@tonic-gate int
2475*7c478bd9Sstevel@tonic-gate zonecfg_getdevent(zone_dochandle_t handle, struct zone_devtab *tabptr)
2476*7c478bd9Sstevel@tonic-gate {
2477*7c478bd9Sstevel@tonic-gate 	xmlNodePtr cur;
2478*7c478bd9Sstevel@tonic-gate 	int err;
2479*7c478bd9Sstevel@tonic-gate 
2480*7c478bd9Sstevel@tonic-gate 	if (handle == NULL)
2481*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
2482*7c478bd9Sstevel@tonic-gate 
2483*7c478bd9Sstevel@tonic-gate 	if ((cur = handle->zone_dh_cur) == NULL)
2484*7c478bd9Sstevel@tonic-gate 		return (Z_NO_ENTRY);
2485*7c478bd9Sstevel@tonic-gate 
2486*7c478bd9Sstevel@tonic-gate 	for (; cur != NULL; cur = cur->next)
2487*7c478bd9Sstevel@tonic-gate 		if (!xmlStrcmp(cur->name, DTD_ELEM_DEVICE))
2488*7c478bd9Sstevel@tonic-gate 			break;
2489*7c478bd9Sstevel@tonic-gate 	if (cur == NULL) {
2490*7c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = handle->zone_dh_top;
2491*7c478bd9Sstevel@tonic-gate 		return (Z_NO_ENTRY);
2492*7c478bd9Sstevel@tonic-gate 	}
2493*7c478bd9Sstevel@tonic-gate 
2494*7c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_MATCH, tabptr->zone_dev_match,
2495*7c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_dev_match))) != Z_OK) {
2496*7c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = handle->zone_dh_top;
2497*7c478bd9Sstevel@tonic-gate 		return (err);
2498*7c478bd9Sstevel@tonic-gate 	}
2499*7c478bd9Sstevel@tonic-gate 
2500*7c478bd9Sstevel@tonic-gate 	handle->zone_dh_cur = cur->next;
2501*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
2502*7c478bd9Sstevel@tonic-gate }
2503*7c478bd9Sstevel@tonic-gate 
2504*7c478bd9Sstevel@tonic-gate int
2505*7c478bd9Sstevel@tonic-gate zonecfg_enddevent(zone_dochandle_t handle)
2506*7c478bd9Sstevel@tonic-gate {
2507*7c478bd9Sstevel@tonic-gate 	return (zonecfg_endent(handle));
2508*7c478bd9Sstevel@tonic-gate }
2509*7c478bd9Sstevel@tonic-gate 
2510*7c478bd9Sstevel@tonic-gate int
2511*7c478bd9Sstevel@tonic-gate zonecfg_setrctlent(zone_dochandle_t handle)
2512*7c478bd9Sstevel@tonic-gate {
2513*7c478bd9Sstevel@tonic-gate 	return (zonecfg_setent(handle));
2514*7c478bd9Sstevel@tonic-gate }
2515*7c478bd9Sstevel@tonic-gate 
2516*7c478bd9Sstevel@tonic-gate int
2517*7c478bd9Sstevel@tonic-gate zonecfg_getrctlent(zone_dochandle_t handle, struct zone_rctltab *tabptr)
2518*7c478bd9Sstevel@tonic-gate {
2519*7c478bd9Sstevel@tonic-gate 	xmlNodePtr cur, val;
2520*7c478bd9Sstevel@tonic-gate 	struct zone_rctlvaltab *valptr;
2521*7c478bd9Sstevel@tonic-gate 	int err;
2522*7c478bd9Sstevel@tonic-gate 
2523*7c478bd9Sstevel@tonic-gate 	if (handle == NULL)
2524*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
2525*7c478bd9Sstevel@tonic-gate 
2526*7c478bd9Sstevel@tonic-gate 	if ((cur = handle->zone_dh_cur) == NULL)
2527*7c478bd9Sstevel@tonic-gate 		return (Z_NO_ENTRY);
2528*7c478bd9Sstevel@tonic-gate 
2529*7c478bd9Sstevel@tonic-gate 	for (; cur != NULL; cur = cur->next)
2530*7c478bd9Sstevel@tonic-gate 		if (!xmlStrcmp(cur->name, DTD_ELEM_RCTL))
2531*7c478bd9Sstevel@tonic-gate 			break;
2532*7c478bd9Sstevel@tonic-gate 	if (cur == NULL) {
2533*7c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = handle->zone_dh_top;
2534*7c478bd9Sstevel@tonic-gate 		return (Z_NO_ENTRY);
2535*7c478bd9Sstevel@tonic-gate 	}
2536*7c478bd9Sstevel@tonic-gate 
2537*7c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_NAME, tabptr->zone_rctl_name,
2538*7c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_rctl_name))) != Z_OK) {
2539*7c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = handle->zone_dh_top;
2540*7c478bd9Sstevel@tonic-gate 		return (err);
2541*7c478bd9Sstevel@tonic-gate 	}
2542*7c478bd9Sstevel@tonic-gate 
2543*7c478bd9Sstevel@tonic-gate 	tabptr->zone_rctl_valptr = NULL;
2544*7c478bd9Sstevel@tonic-gate 	for (val = cur->xmlChildrenNode; val != NULL; val = val->next) {
2545*7c478bd9Sstevel@tonic-gate 		valptr = (struct zone_rctlvaltab *)malloc(
2546*7c478bd9Sstevel@tonic-gate 		    sizeof (struct zone_rctlvaltab));
2547*7c478bd9Sstevel@tonic-gate 		if (valptr == NULL)
2548*7c478bd9Sstevel@tonic-gate 			return (Z_NOMEM);
2549*7c478bd9Sstevel@tonic-gate 		if (fetchprop(val, DTD_ATTR_PRIV, valptr->zone_rctlval_priv,
2550*7c478bd9Sstevel@tonic-gate 		    sizeof (valptr->zone_rctlval_priv)) != Z_OK)
2551*7c478bd9Sstevel@tonic-gate 			break;
2552*7c478bd9Sstevel@tonic-gate 		if (fetchprop(val, DTD_ATTR_LIMIT, valptr->zone_rctlval_limit,
2553*7c478bd9Sstevel@tonic-gate 		    sizeof (valptr->zone_rctlval_limit)) != Z_OK)
2554*7c478bd9Sstevel@tonic-gate 			break;
2555*7c478bd9Sstevel@tonic-gate 		if (fetchprop(val, DTD_ATTR_ACTION, valptr->zone_rctlval_action,
2556*7c478bd9Sstevel@tonic-gate 		    sizeof (valptr->zone_rctlval_action)) != Z_OK)
2557*7c478bd9Sstevel@tonic-gate 			break;
2558*7c478bd9Sstevel@tonic-gate 		if (zonecfg_add_rctl_value(tabptr, valptr) != Z_OK)
2559*7c478bd9Sstevel@tonic-gate 			break;
2560*7c478bd9Sstevel@tonic-gate 	}
2561*7c478bd9Sstevel@tonic-gate 
2562*7c478bd9Sstevel@tonic-gate 	handle->zone_dh_cur = cur->next;
2563*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
2564*7c478bd9Sstevel@tonic-gate }
2565*7c478bd9Sstevel@tonic-gate 
2566*7c478bd9Sstevel@tonic-gate int
2567*7c478bd9Sstevel@tonic-gate zonecfg_endrctlent(zone_dochandle_t handle)
2568*7c478bd9Sstevel@tonic-gate {
2569*7c478bd9Sstevel@tonic-gate 	return (zonecfg_endent(handle));
2570*7c478bd9Sstevel@tonic-gate }
2571*7c478bd9Sstevel@tonic-gate 
2572*7c478bd9Sstevel@tonic-gate int
2573*7c478bd9Sstevel@tonic-gate zonecfg_setattrent(zone_dochandle_t handle)
2574*7c478bd9Sstevel@tonic-gate {
2575*7c478bd9Sstevel@tonic-gate 	return (zonecfg_setent(handle));
2576*7c478bd9Sstevel@tonic-gate }
2577*7c478bd9Sstevel@tonic-gate 
2578*7c478bd9Sstevel@tonic-gate int
2579*7c478bd9Sstevel@tonic-gate zonecfg_getattrent(zone_dochandle_t handle, struct zone_attrtab *tabptr)
2580*7c478bd9Sstevel@tonic-gate {
2581*7c478bd9Sstevel@tonic-gate 	xmlNodePtr cur;
2582*7c478bd9Sstevel@tonic-gate 	int err;
2583*7c478bd9Sstevel@tonic-gate 
2584*7c478bd9Sstevel@tonic-gate 	if (handle == NULL)
2585*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
2586*7c478bd9Sstevel@tonic-gate 
2587*7c478bd9Sstevel@tonic-gate 	if ((cur = handle->zone_dh_cur) == NULL)
2588*7c478bd9Sstevel@tonic-gate 		return (Z_NO_ENTRY);
2589*7c478bd9Sstevel@tonic-gate 
2590*7c478bd9Sstevel@tonic-gate 	for (; cur != NULL; cur = cur->next)
2591*7c478bd9Sstevel@tonic-gate 		if (!xmlStrcmp(cur->name, DTD_ELEM_ATTR))
2592*7c478bd9Sstevel@tonic-gate 			break;
2593*7c478bd9Sstevel@tonic-gate 	if (cur == NULL) {
2594*7c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = handle->zone_dh_top;
2595*7c478bd9Sstevel@tonic-gate 		return (Z_NO_ENTRY);
2596*7c478bd9Sstevel@tonic-gate 	}
2597*7c478bd9Sstevel@tonic-gate 
2598*7c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_NAME, tabptr->zone_attr_name,
2599*7c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_attr_name))) != Z_OK) {
2600*7c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = handle->zone_dh_top;
2601*7c478bd9Sstevel@tonic-gate 		return (err);
2602*7c478bd9Sstevel@tonic-gate 	}
2603*7c478bd9Sstevel@tonic-gate 
2604*7c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_TYPE, tabptr->zone_attr_type,
2605*7c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_attr_type))) != Z_OK) {
2606*7c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = handle->zone_dh_top;
2607*7c478bd9Sstevel@tonic-gate 		return (err);
2608*7c478bd9Sstevel@tonic-gate 	}
2609*7c478bd9Sstevel@tonic-gate 
2610*7c478bd9Sstevel@tonic-gate 	if ((err = fetchprop(cur, DTD_ATTR_VALUE, tabptr->zone_attr_value,
2611*7c478bd9Sstevel@tonic-gate 	    sizeof (tabptr->zone_attr_value))) != Z_OK) {
2612*7c478bd9Sstevel@tonic-gate 		handle->zone_dh_cur = handle->zone_dh_top;
2613*7c478bd9Sstevel@tonic-gate 		return (err);
2614*7c478bd9Sstevel@tonic-gate 	}
2615*7c478bd9Sstevel@tonic-gate 
2616*7c478bd9Sstevel@tonic-gate 	handle->zone_dh_cur = cur->next;
2617*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
2618*7c478bd9Sstevel@tonic-gate }
2619*7c478bd9Sstevel@tonic-gate 
2620*7c478bd9Sstevel@tonic-gate int
2621*7c478bd9Sstevel@tonic-gate zonecfg_endattrent(zone_dochandle_t handle)
2622*7c478bd9Sstevel@tonic-gate {
2623*7c478bd9Sstevel@tonic-gate 	return (zonecfg_endent(handle));
2624*7c478bd9Sstevel@tonic-gate }
2625*7c478bd9Sstevel@tonic-gate 
2626*7c478bd9Sstevel@tonic-gate /* This will ultimately be configurable. */
2627*7c478bd9Sstevel@tonic-gate static const char *priv_list[] = {
2628*7c478bd9Sstevel@tonic-gate 	PRIV_FILE_CHOWN,
2629*7c478bd9Sstevel@tonic-gate 	PRIV_FILE_CHOWN_SELF,
2630*7c478bd9Sstevel@tonic-gate 	PRIV_FILE_DAC_EXECUTE,
2631*7c478bd9Sstevel@tonic-gate 	PRIV_FILE_DAC_READ,
2632*7c478bd9Sstevel@tonic-gate 	PRIV_FILE_DAC_SEARCH,
2633*7c478bd9Sstevel@tonic-gate 	PRIV_FILE_DAC_WRITE,
2634*7c478bd9Sstevel@tonic-gate 	PRIV_FILE_OWNER,
2635*7c478bd9Sstevel@tonic-gate 	PRIV_FILE_SETID,
2636*7c478bd9Sstevel@tonic-gate 	PRIV_IPC_DAC_READ,
2637*7c478bd9Sstevel@tonic-gate 	PRIV_IPC_DAC_WRITE,
2638*7c478bd9Sstevel@tonic-gate 	PRIV_IPC_OWNER,
2639*7c478bd9Sstevel@tonic-gate 	PRIV_NET_ICMPACCESS,
2640*7c478bd9Sstevel@tonic-gate 	PRIV_NET_PRIVADDR,
2641*7c478bd9Sstevel@tonic-gate 	PRIV_PROC_CHROOT,
2642*7c478bd9Sstevel@tonic-gate 	PRIV_SYS_AUDIT,
2643*7c478bd9Sstevel@tonic-gate 	PRIV_PROC_AUDIT,
2644*7c478bd9Sstevel@tonic-gate 	PRIV_PROC_OWNER,
2645*7c478bd9Sstevel@tonic-gate 	PRIV_PROC_SETID,
2646*7c478bd9Sstevel@tonic-gate 	PRIV_PROC_TASKID,
2647*7c478bd9Sstevel@tonic-gate 	PRIV_SYS_ACCT,
2648*7c478bd9Sstevel@tonic-gate 	PRIV_SYS_ADMIN,
2649*7c478bd9Sstevel@tonic-gate 	PRIV_SYS_MOUNT,
2650*7c478bd9Sstevel@tonic-gate 	PRIV_SYS_NFS,
2651*7c478bd9Sstevel@tonic-gate 	PRIV_SYS_RESOURCE,
2652*7c478bd9Sstevel@tonic-gate 	PRIV_CONTRACT_EVENT,
2653*7c478bd9Sstevel@tonic-gate 	PRIV_CONTRACT_OBSERVER,
2654*7c478bd9Sstevel@tonic-gate 	NULL
2655*7c478bd9Sstevel@tonic-gate };
2656*7c478bd9Sstevel@tonic-gate 
2657*7c478bd9Sstevel@tonic-gate int
2658*7c478bd9Sstevel@tonic-gate zonecfg_get_privset(priv_set_t *privs)
2659*7c478bd9Sstevel@tonic-gate {
2660*7c478bd9Sstevel@tonic-gate 	const char **strp;
2661*7c478bd9Sstevel@tonic-gate 	priv_set_t *basic = priv_str_to_set("basic", ",", NULL);
2662*7c478bd9Sstevel@tonic-gate 
2663*7c478bd9Sstevel@tonic-gate 	if (basic == NULL)
2664*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
2665*7c478bd9Sstevel@tonic-gate 
2666*7c478bd9Sstevel@tonic-gate 	priv_union(basic, privs);
2667*7c478bd9Sstevel@tonic-gate 	priv_freeset(basic);
2668*7c478bd9Sstevel@tonic-gate 
2669*7c478bd9Sstevel@tonic-gate 	for (strp = priv_list; *strp != NULL; strp++) {
2670*7c478bd9Sstevel@tonic-gate 		if (priv_addset(privs, *strp) != 0) {
2671*7c478bd9Sstevel@tonic-gate 			return (Z_INVAL);
2672*7c478bd9Sstevel@tonic-gate 		}
2673*7c478bd9Sstevel@tonic-gate 	}
2674*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
2675*7c478bd9Sstevel@tonic-gate }
2676*7c478bd9Sstevel@tonic-gate 
2677*7c478bd9Sstevel@tonic-gate int
2678*7c478bd9Sstevel@tonic-gate zonecfg_add_index(char *zone, char *path)
2679*7c478bd9Sstevel@tonic-gate {
2680*7c478bd9Sstevel@tonic-gate 	struct zoneent ze;
2681*7c478bd9Sstevel@tonic-gate 
2682*7c478bd9Sstevel@tonic-gate 	(void) strlcpy(ze.zone_name, zone, sizeof (ze.zone_name));
2683*7c478bd9Sstevel@tonic-gate 	ze.zone_state = ZONE_STATE_CONFIGURED;
2684*7c478bd9Sstevel@tonic-gate 	(void) strlcpy(ze.zone_path, path, sizeof (ze.zone_path));
2685*7c478bd9Sstevel@tonic-gate 	return (putzoneent(&ze, PZE_ADD));
2686*7c478bd9Sstevel@tonic-gate }
2687*7c478bd9Sstevel@tonic-gate 
2688*7c478bd9Sstevel@tonic-gate int
2689*7c478bd9Sstevel@tonic-gate zonecfg_delete_index(char *zone)
2690*7c478bd9Sstevel@tonic-gate {
2691*7c478bd9Sstevel@tonic-gate 	struct zoneent ze;
2692*7c478bd9Sstevel@tonic-gate 
2693*7c478bd9Sstevel@tonic-gate 	(void) strlcpy(ze.zone_name, zone, sizeof (ze.zone_name));
2694*7c478bd9Sstevel@tonic-gate 	return (putzoneent(&ze, PZE_REMOVE));
2695*7c478bd9Sstevel@tonic-gate }
2696*7c478bd9Sstevel@tonic-gate 
2697*7c478bd9Sstevel@tonic-gate int
2698*7c478bd9Sstevel@tonic-gate zone_get_zonepath(char *zone_name, char *zonepath, size_t rp_sz)
2699*7c478bd9Sstevel@tonic-gate {
2700*7c478bd9Sstevel@tonic-gate 	zone_dochandle_t handle;
2701*7c478bd9Sstevel@tonic-gate 	boolean_t found = B_FALSE;
2702*7c478bd9Sstevel@tonic-gate 	struct zoneent *ze;
2703*7c478bd9Sstevel@tonic-gate 	FILE *cookie;
2704*7c478bd9Sstevel@tonic-gate 	int err;
2705*7c478bd9Sstevel@tonic-gate 
2706*7c478bd9Sstevel@tonic-gate 	if (zone_name == NULL)
2707*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
2708*7c478bd9Sstevel@tonic-gate 
2709*7c478bd9Sstevel@tonic-gate 	if (strcmp(zone_name, GLOBAL_ZONENAME) == 0) {
2710*7c478bd9Sstevel@tonic-gate 		(void) strlcpy(zonepath, "/", rp_sz);
2711*7c478bd9Sstevel@tonic-gate 		return (Z_OK);
2712*7c478bd9Sstevel@tonic-gate 	}
2713*7c478bd9Sstevel@tonic-gate 
2714*7c478bd9Sstevel@tonic-gate 	/*
2715*7c478bd9Sstevel@tonic-gate 	 * First check the index file.  Because older versions did not have
2716*7c478bd9Sstevel@tonic-gate 	 * a copy of the zone path, allow for it to be zero length, in which
2717*7c478bd9Sstevel@tonic-gate 	 * case we ignore this result and fall back to the XML files.
2718*7c478bd9Sstevel@tonic-gate 	 */
2719*7c478bd9Sstevel@tonic-gate 	(void) strlcpy(zonepath, "", rp_sz);
2720*7c478bd9Sstevel@tonic-gate 	cookie = setzoneent();
2721*7c478bd9Sstevel@tonic-gate 	while ((ze = getzoneent_private(cookie)) != NULL) {
2722*7c478bd9Sstevel@tonic-gate 		if (strcmp(ze->zone_name, zone_name) == 0) {
2723*7c478bd9Sstevel@tonic-gate 			found = B_TRUE;
2724*7c478bd9Sstevel@tonic-gate 			if (strlen(ze->zone_path) > 0)
2725*7c478bd9Sstevel@tonic-gate 				(void) strlcpy(zonepath, ze->zone_path, rp_sz);
2726*7c478bd9Sstevel@tonic-gate 		}
2727*7c478bd9Sstevel@tonic-gate 		free(ze);
2728*7c478bd9Sstevel@tonic-gate 		if (found)
2729*7c478bd9Sstevel@tonic-gate 			break;
2730*7c478bd9Sstevel@tonic-gate 	}
2731*7c478bd9Sstevel@tonic-gate 	endzoneent(cookie);
2732*7c478bd9Sstevel@tonic-gate 	if (found && strlen(zonepath) > 0)
2733*7c478bd9Sstevel@tonic-gate 		return (Z_OK);
2734*7c478bd9Sstevel@tonic-gate 
2735*7c478bd9Sstevel@tonic-gate 	/* Fall back to the XML files. */
2736*7c478bd9Sstevel@tonic-gate 	if ((handle = zonecfg_init_handle()) == NULL)
2737*7c478bd9Sstevel@tonic-gate 		return (Z_NOMEM);
2738*7c478bd9Sstevel@tonic-gate 
2739*7c478bd9Sstevel@tonic-gate 	/*
2740*7c478bd9Sstevel@tonic-gate 	 * Check the snapshot first: if a zone is running, its zonepath
2741*7c478bd9Sstevel@tonic-gate 	 * may have changed.
2742*7c478bd9Sstevel@tonic-gate 	 */
2743*7c478bd9Sstevel@tonic-gate 	if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) {
2744*7c478bd9Sstevel@tonic-gate 		if ((err = zonecfg_get_handle(zone_name, handle)) != Z_OK)
2745*7c478bd9Sstevel@tonic-gate 			return (err);
2746*7c478bd9Sstevel@tonic-gate 	}
2747*7c478bd9Sstevel@tonic-gate 	err = zonecfg_get_zonepath(handle, zonepath, rp_sz);
2748*7c478bd9Sstevel@tonic-gate 	zonecfg_fini_handle(handle);
2749*7c478bd9Sstevel@tonic-gate 	return (err);
2750*7c478bd9Sstevel@tonic-gate }
2751*7c478bd9Sstevel@tonic-gate 
2752*7c478bd9Sstevel@tonic-gate int
2753*7c478bd9Sstevel@tonic-gate zone_get_rootpath(char *zone_name, char *rootpath, size_t rp_sz)
2754*7c478bd9Sstevel@tonic-gate {
2755*7c478bd9Sstevel@tonic-gate 	int err;
2756*7c478bd9Sstevel@tonic-gate 
2757*7c478bd9Sstevel@tonic-gate 	/* This function makes sense for non-global zones only. */
2758*7c478bd9Sstevel@tonic-gate 	if (strcmp(zone_name, GLOBAL_ZONENAME) == 0)
2759*7c478bd9Sstevel@tonic-gate 		return (Z_BOGUS_ZONE_NAME);
2760*7c478bd9Sstevel@tonic-gate 	if ((err = zone_get_zonepath(zone_name, rootpath, rp_sz)) != Z_OK)
2761*7c478bd9Sstevel@tonic-gate 		return (err);
2762*7c478bd9Sstevel@tonic-gate 	if (strlcat(rootpath, "/root", rp_sz) >= rp_sz)
2763*7c478bd9Sstevel@tonic-gate 		return (Z_TOO_BIG);
2764*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
2765*7c478bd9Sstevel@tonic-gate }
2766*7c478bd9Sstevel@tonic-gate 
2767*7c478bd9Sstevel@tonic-gate static zone_state_t
2768*7c478bd9Sstevel@tonic-gate kernel_state_to_user_state(zone_status_t kernel_state)
2769*7c478bd9Sstevel@tonic-gate {
2770*7c478bd9Sstevel@tonic-gate 	assert(kernel_state <= ZONE_MAX_STATE);
2771*7c478bd9Sstevel@tonic-gate 	switch (kernel_state) {
2772*7c478bd9Sstevel@tonic-gate 		case ZONE_IS_UNINITIALIZED:
2773*7c478bd9Sstevel@tonic-gate 		case ZONE_IS_READY:
2774*7c478bd9Sstevel@tonic-gate 			return (ZONE_STATE_READY);
2775*7c478bd9Sstevel@tonic-gate 		case ZONE_IS_BOOTING:
2776*7c478bd9Sstevel@tonic-gate 		case ZONE_IS_RUNNING:
2777*7c478bd9Sstevel@tonic-gate 			return (ZONE_STATE_RUNNING);
2778*7c478bd9Sstevel@tonic-gate 		case ZONE_IS_SHUTTING_DOWN:
2779*7c478bd9Sstevel@tonic-gate 		case ZONE_IS_EMPTY:
2780*7c478bd9Sstevel@tonic-gate 			return (ZONE_STATE_SHUTTING_DOWN);
2781*7c478bd9Sstevel@tonic-gate 		case ZONE_IS_DOWN:
2782*7c478bd9Sstevel@tonic-gate 		case ZONE_IS_DYING:
2783*7c478bd9Sstevel@tonic-gate 		case ZONE_IS_DEAD:
2784*7c478bd9Sstevel@tonic-gate 		default:
2785*7c478bd9Sstevel@tonic-gate 			return (ZONE_STATE_DOWN);
2786*7c478bd9Sstevel@tonic-gate 	}
2787*7c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
2788*7c478bd9Sstevel@tonic-gate }
2789*7c478bd9Sstevel@tonic-gate 
2790*7c478bd9Sstevel@tonic-gate int
2791*7c478bd9Sstevel@tonic-gate zone_get_state(char *zone_name, zone_state_t *state_num)
2792*7c478bd9Sstevel@tonic-gate {
2793*7c478bd9Sstevel@tonic-gate 	zone_status_t status;
2794*7c478bd9Sstevel@tonic-gate 	zoneid_t zone_id;
2795*7c478bd9Sstevel@tonic-gate 	struct zoneent *ze;
2796*7c478bd9Sstevel@tonic-gate 	boolean_t found = B_FALSE;
2797*7c478bd9Sstevel@tonic-gate 	FILE *cookie;
2798*7c478bd9Sstevel@tonic-gate 
2799*7c478bd9Sstevel@tonic-gate 	if (zone_name == NULL)
2800*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
2801*7c478bd9Sstevel@tonic-gate 
2802*7c478bd9Sstevel@tonic-gate 	/* check to see if zone is running */
2803*7c478bd9Sstevel@tonic-gate 	if ((zone_id = getzoneidbyname(zone_name)) != -1 &&
2804*7c478bd9Sstevel@tonic-gate 	    zone_getattr(zone_id, ZONE_ATTR_STATUS, &status,
2805*7c478bd9Sstevel@tonic-gate 	    sizeof (status)) >= 0) {
2806*7c478bd9Sstevel@tonic-gate 		*state_num = kernel_state_to_user_state(status);
2807*7c478bd9Sstevel@tonic-gate 		return (Z_OK);
2808*7c478bd9Sstevel@tonic-gate 	}
2809*7c478bd9Sstevel@tonic-gate 
2810*7c478bd9Sstevel@tonic-gate 	cookie = setzoneent();
2811*7c478bd9Sstevel@tonic-gate 	while ((ze = getzoneent_private(cookie)) != NULL) {
2812*7c478bd9Sstevel@tonic-gate 		if (strcmp(ze->zone_name, zone_name) == 0) {
2813*7c478bd9Sstevel@tonic-gate 			found = B_TRUE;
2814*7c478bd9Sstevel@tonic-gate 			*state_num = ze->zone_state;
2815*7c478bd9Sstevel@tonic-gate 		}
2816*7c478bd9Sstevel@tonic-gate 		free(ze);
2817*7c478bd9Sstevel@tonic-gate 		if (found)
2818*7c478bd9Sstevel@tonic-gate 			break;
2819*7c478bd9Sstevel@tonic-gate 	}
2820*7c478bd9Sstevel@tonic-gate 	endzoneent(cookie);
2821*7c478bd9Sstevel@tonic-gate 	return ((found) ? Z_OK : Z_NO_ZONE);
2822*7c478bd9Sstevel@tonic-gate }
2823*7c478bd9Sstevel@tonic-gate 
2824*7c478bd9Sstevel@tonic-gate int
2825*7c478bd9Sstevel@tonic-gate zone_set_state(char *zone, zone_state_t state)
2826*7c478bd9Sstevel@tonic-gate {
2827*7c478bd9Sstevel@tonic-gate 	struct zoneent ze;
2828*7c478bd9Sstevel@tonic-gate 
2829*7c478bd9Sstevel@tonic-gate 	if (state != ZONE_STATE_CONFIGURED && state != ZONE_STATE_INSTALLED &&
2830*7c478bd9Sstevel@tonic-gate 	    state != ZONE_STATE_INCOMPLETE)
2831*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
2832*7c478bd9Sstevel@tonic-gate 
2833*7c478bd9Sstevel@tonic-gate 	(void) strlcpy(ze.zone_name, zone, sizeof (ze.zone_name));
2834*7c478bd9Sstevel@tonic-gate 	ze.zone_state = state;
2835*7c478bd9Sstevel@tonic-gate 	(void) strlcpy(ze.zone_path, "", sizeof (ze.zone_path));
2836*7c478bd9Sstevel@tonic-gate 	return (putzoneent(&ze, PZE_MODIFY));
2837*7c478bd9Sstevel@tonic-gate }
2838*7c478bd9Sstevel@tonic-gate 
2839*7c478bd9Sstevel@tonic-gate /*
2840*7c478bd9Sstevel@tonic-gate  * Get id (if any) for specified zone.  There are four possible outcomes:
2841*7c478bd9Sstevel@tonic-gate  * - If the string corresponds to the numeric id of an active (booted)
2842*7c478bd9Sstevel@tonic-gate  *   zone, sets *zip to the zone id and returns 0.
2843*7c478bd9Sstevel@tonic-gate  * - If the string corresponds to the name of an active (booted) zone,
2844*7c478bd9Sstevel@tonic-gate  *   sets *zip to the zone id and returns 0.
2845*7c478bd9Sstevel@tonic-gate  * - If the string is a name in the configuration but is not booted,
2846*7c478bd9Sstevel@tonic-gate  *   sets *zip to ZONE_ID_UNDEFINED and returns 0.
2847*7c478bd9Sstevel@tonic-gate  * - Otherwise, leaves *zip unchanged and returns -1.
2848*7c478bd9Sstevel@tonic-gate  *
2849*7c478bd9Sstevel@tonic-gate  * This function acts as an auxiliary filter on the function of the same
2850*7c478bd9Sstevel@tonic-gate  * name in libc; the linker binds to this version if libzonecfg exists,
2851*7c478bd9Sstevel@tonic-gate  * and the libc version if it doesn't.  Any changes to this version of
2852*7c478bd9Sstevel@tonic-gate  * the function should probably be reflected in the libc version as well.
2853*7c478bd9Sstevel@tonic-gate  */
2854*7c478bd9Sstevel@tonic-gate int
2855*7c478bd9Sstevel@tonic-gate zone_get_id(const char *str, zoneid_t *zip)
2856*7c478bd9Sstevel@tonic-gate {
2857*7c478bd9Sstevel@tonic-gate 	zone_dochandle_t hdl;
2858*7c478bd9Sstevel@tonic-gate 	zoneid_t zoneid;
2859*7c478bd9Sstevel@tonic-gate 	char *cp;
2860*7c478bd9Sstevel@tonic-gate 	int err;
2861*7c478bd9Sstevel@tonic-gate 
2862*7c478bd9Sstevel@tonic-gate 	/* first try looking for active zone by id */
2863*7c478bd9Sstevel@tonic-gate 	errno = 0;
2864*7c478bd9Sstevel@tonic-gate 	zoneid = (zoneid_t)strtol(str, &cp, 0);
2865*7c478bd9Sstevel@tonic-gate 	if (errno == 0 && cp != str && *cp == '\0' &&
2866*7c478bd9Sstevel@tonic-gate 	    getzonenamebyid(zoneid, NULL, 0) != -1) {
2867*7c478bd9Sstevel@tonic-gate 		*zip = zoneid;
2868*7c478bd9Sstevel@tonic-gate 		return (0);
2869*7c478bd9Sstevel@tonic-gate 	}
2870*7c478bd9Sstevel@tonic-gate 
2871*7c478bd9Sstevel@tonic-gate 	/* then look for active zone by name */
2872*7c478bd9Sstevel@tonic-gate 	if ((zoneid = getzoneidbyname(str)) != -1) {
2873*7c478bd9Sstevel@tonic-gate 		*zip = zoneid;
2874*7c478bd9Sstevel@tonic-gate 		return (0);
2875*7c478bd9Sstevel@tonic-gate 	}
2876*7c478bd9Sstevel@tonic-gate 
2877*7c478bd9Sstevel@tonic-gate 	/* if in global zone, try looking up name in configuration database */
2878*7c478bd9Sstevel@tonic-gate 	if (getzoneid() != GLOBAL_ZONEID ||
2879*7c478bd9Sstevel@tonic-gate 	    (hdl = zonecfg_init_handle()) == NULL)
2880*7c478bd9Sstevel@tonic-gate 		return (-1);
2881*7c478bd9Sstevel@tonic-gate 
2882*7c478bd9Sstevel@tonic-gate 	if (zonecfg_get_handle((char *)str, hdl) == Z_OK) {
2883*7c478bd9Sstevel@tonic-gate 		/* zone exists but isn't active */
2884*7c478bd9Sstevel@tonic-gate 		*zip = ZONE_ID_UNDEFINED;
2885*7c478bd9Sstevel@tonic-gate 		err = 0;
2886*7c478bd9Sstevel@tonic-gate 	} else {
2887*7c478bd9Sstevel@tonic-gate 		err = -1;
2888*7c478bd9Sstevel@tonic-gate 	}
2889*7c478bd9Sstevel@tonic-gate 
2890*7c478bd9Sstevel@tonic-gate 	zonecfg_fini_handle(hdl);
2891*7c478bd9Sstevel@tonic-gate 	return (err);
2892*7c478bd9Sstevel@tonic-gate }
2893*7c478bd9Sstevel@tonic-gate 
2894*7c478bd9Sstevel@tonic-gate char *
2895*7c478bd9Sstevel@tonic-gate zone_state_str(zone_state_t state_num)
2896*7c478bd9Sstevel@tonic-gate {
2897*7c478bd9Sstevel@tonic-gate 	switch (state_num) {
2898*7c478bd9Sstevel@tonic-gate 	case ZONE_STATE_CONFIGURED:
2899*7c478bd9Sstevel@tonic-gate 		return (ZONE_STATE_STR_CONFIGURED);
2900*7c478bd9Sstevel@tonic-gate 	case ZONE_STATE_INCOMPLETE:
2901*7c478bd9Sstevel@tonic-gate 		return (ZONE_STATE_STR_INCOMPLETE);
2902*7c478bd9Sstevel@tonic-gate 	case ZONE_STATE_INSTALLED:
2903*7c478bd9Sstevel@tonic-gate 		return (ZONE_STATE_STR_INSTALLED);
2904*7c478bd9Sstevel@tonic-gate 	case ZONE_STATE_READY:
2905*7c478bd9Sstevel@tonic-gate 		return (ZONE_STATE_STR_READY);
2906*7c478bd9Sstevel@tonic-gate 	case ZONE_STATE_RUNNING:
2907*7c478bd9Sstevel@tonic-gate 		return (ZONE_STATE_STR_RUNNING);
2908*7c478bd9Sstevel@tonic-gate 	case ZONE_STATE_SHUTTING_DOWN:
2909*7c478bd9Sstevel@tonic-gate 		return (ZONE_STATE_STR_SHUTTING_DOWN);
2910*7c478bd9Sstevel@tonic-gate 	case ZONE_STATE_DOWN:
2911*7c478bd9Sstevel@tonic-gate 		return (ZONE_STATE_STR_DOWN);
2912*7c478bd9Sstevel@tonic-gate 	default:
2913*7c478bd9Sstevel@tonic-gate 		return ("unknown");
2914*7c478bd9Sstevel@tonic-gate 	}
2915*7c478bd9Sstevel@tonic-gate }
2916*7c478bd9Sstevel@tonic-gate 
2917*7c478bd9Sstevel@tonic-gate /*
2918*7c478bd9Sstevel@tonic-gate  * File-system convenience functions.
2919*7c478bd9Sstevel@tonic-gate  */
2920*7c478bd9Sstevel@tonic-gate boolean_t
2921*7c478bd9Sstevel@tonic-gate zonecfg_valid_fs_type(const char *type)
2922*7c478bd9Sstevel@tonic-gate {
2923*7c478bd9Sstevel@tonic-gate 	/*
2924*7c478bd9Sstevel@tonic-gate 	 * We already know which FS types don't work.
2925*7c478bd9Sstevel@tonic-gate 	 */
2926*7c478bd9Sstevel@tonic-gate 	if (strcmp(type, "proc") == 0 ||
2927*7c478bd9Sstevel@tonic-gate 	    strcmp(type, "mntfs") == 0 ||
2928*7c478bd9Sstevel@tonic-gate 	    strcmp(type, "autofs") == 0 ||
2929*7c478bd9Sstevel@tonic-gate 	    strncmp(type, "nfs", sizeof ("nfs") - 1) == 0 ||
2930*7c478bd9Sstevel@tonic-gate 	    strcmp(type, "cachefs") == 0)
2931*7c478bd9Sstevel@tonic-gate 		return (B_FALSE);
2932*7c478bd9Sstevel@tonic-gate 	/*
2933*7c478bd9Sstevel@tonic-gate 	 * The caller may do more detailed verification to make sure other
2934*7c478bd9Sstevel@tonic-gate 	 * aspects of this filesystem type make sense.
2935*7c478bd9Sstevel@tonic-gate 	 */
2936*7c478bd9Sstevel@tonic-gate 	return (B_TRUE);
2937*7c478bd9Sstevel@tonic-gate }
2938*7c478bd9Sstevel@tonic-gate 
2939*7c478bd9Sstevel@tonic-gate /*
2940*7c478bd9Sstevel@tonic-gate  * Generally uninteresting rctl convenience functions.
2941*7c478bd9Sstevel@tonic-gate  */
2942*7c478bd9Sstevel@tonic-gate 
2943*7c478bd9Sstevel@tonic-gate int
2944*7c478bd9Sstevel@tonic-gate zonecfg_construct_rctlblk(const struct zone_rctlvaltab *rctlval,
2945*7c478bd9Sstevel@tonic-gate     rctlblk_t *rctlblk)
2946*7c478bd9Sstevel@tonic-gate {
2947*7c478bd9Sstevel@tonic-gate 	unsigned long long ull;
2948*7c478bd9Sstevel@tonic-gate 	char *endp;
2949*7c478bd9Sstevel@tonic-gate 	rctl_priv_t priv;
2950*7c478bd9Sstevel@tonic-gate 	rctl_qty_t limit;
2951*7c478bd9Sstevel@tonic-gate 	uint_t action;
2952*7c478bd9Sstevel@tonic-gate 
2953*7c478bd9Sstevel@tonic-gate 	/* Get the privilege */
2954*7c478bd9Sstevel@tonic-gate 	if (strcmp(rctlval->zone_rctlval_priv, "basic") == 0) {
2955*7c478bd9Sstevel@tonic-gate 		priv = RCPRIV_BASIC;
2956*7c478bd9Sstevel@tonic-gate 	} else if (strcmp(rctlval->zone_rctlval_priv, "privileged") == 0) {
2957*7c478bd9Sstevel@tonic-gate 		priv = RCPRIV_PRIVILEGED;
2958*7c478bd9Sstevel@tonic-gate 	} else {
2959*7c478bd9Sstevel@tonic-gate 		/* Invalid privilege */
2960*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
2961*7c478bd9Sstevel@tonic-gate 	}
2962*7c478bd9Sstevel@tonic-gate 
2963*7c478bd9Sstevel@tonic-gate 	/* deal with negative input; strtoull(3c) doesn't do what we want */
2964*7c478bd9Sstevel@tonic-gate 	if (rctlval->zone_rctlval_limit[0] == '-')
2965*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
2966*7c478bd9Sstevel@tonic-gate 	/* Get the limit */
2967*7c478bd9Sstevel@tonic-gate 	errno = 0;
2968*7c478bd9Sstevel@tonic-gate 	ull = strtoull(rctlval->zone_rctlval_limit, &endp, 0);
2969*7c478bd9Sstevel@tonic-gate 	if (errno != 0 || *endp != '\0') {
2970*7c478bd9Sstevel@tonic-gate 		/* parse failed */
2971*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
2972*7c478bd9Sstevel@tonic-gate 	}
2973*7c478bd9Sstevel@tonic-gate 	limit = (rctl_qty_t)ull;
2974*7c478bd9Sstevel@tonic-gate 
2975*7c478bd9Sstevel@tonic-gate 	/* Get the action */
2976*7c478bd9Sstevel@tonic-gate 	if (strcmp(rctlval->zone_rctlval_action, "none") == 0) {
2977*7c478bd9Sstevel@tonic-gate 		action = RCTL_LOCAL_NOACTION;
2978*7c478bd9Sstevel@tonic-gate 	} else if (strcmp(rctlval->zone_rctlval_action, "signal") == 0) {
2979*7c478bd9Sstevel@tonic-gate 		action = RCTL_LOCAL_SIGNAL;
2980*7c478bd9Sstevel@tonic-gate 	} else if (strcmp(rctlval->zone_rctlval_action, "deny") == 0) {
2981*7c478bd9Sstevel@tonic-gate 		action = RCTL_LOCAL_DENY;
2982*7c478bd9Sstevel@tonic-gate 	} else {
2983*7c478bd9Sstevel@tonic-gate 		/* Invalid Action */
2984*7c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
2985*7c478bd9Sstevel@tonic-gate 	}
2986*7c478bd9Sstevel@tonic-gate 	rctlblk_set_local_action(rctlblk, action, 0);
2987*7c478bd9Sstevel@tonic-gate 	rctlblk_set_privilege(rctlblk, priv);
2988*7c478bd9Sstevel@tonic-gate 	rctlblk_set_value(rctlblk, limit);
2989*7c478bd9Sstevel@tonic-gate 	return (Z_OK);
2990*7c478bd9Sstevel@tonic-gate }
2991*7c478bd9Sstevel@tonic-gate 
2992*7c478bd9Sstevel@tonic-gate static int
2993*7c478bd9Sstevel@tonic-gate rctl_check(const char *rctlname, void *arg)
2994*7c478bd9Sstevel@tonic-gate {
2995*7c478bd9Sstevel@tonic-gate 	const char *attrname = arg;
2996*7c478bd9Sstevel@tonic-gate 
2997*7c478bd9Sstevel@tonic-gate 	/*
2998*7c478bd9Sstevel@tonic-gate 	 * Returning 1 here is our signal to zonecfg_is_rctl() that it is
2999*7c478bd9Sstevel@tonic-gate 	 * indeed an rctl name recognized by the system.
3000*7c478bd9Sstevel@tonic-gate 	 */
3001*7c478bd9Sstevel@tonic-gate 	return (strcmp(rctlname, attrname) == 0 ? 1 : 0);
3002*7c478bd9Sstevel@tonic-gate }
3003*7c478bd9Sstevel@tonic-gate 
3004*7c478bd9Sstevel@tonic-gate boolean_t
3005*7c478bd9Sstevel@tonic-gate zonecfg_is_rctl(const char *name)
3006*7c478bd9Sstevel@tonic-gate {
3007*7c478bd9Sstevel@tonic-gate 	return (rctl_walk(rctl_check, (void *)name) == 1);
3008*7c478bd9Sstevel@tonic-gate }
3009*7c478bd9Sstevel@tonic-gate 
3010*7c478bd9Sstevel@tonic-gate boolean_t
3011*7c478bd9Sstevel@tonic-gate zonecfg_valid_rctlname(const char *name)
3012*7c478bd9Sstevel@tonic-gate {
3013*7c478bd9Sstevel@tonic-gate 	const char *c;
3014*7c478bd9Sstevel@tonic-gate 
3015*7c478bd9Sstevel@tonic-gate 	if (strncmp(name, "zone.", sizeof ("zone.") - 1) != 0)
3016*7c478bd9Sstevel@tonic-gate 		return (B_FALSE);
3017*7c478bd9Sstevel@tonic-gate 	if (strlen(name) == sizeof ("zone.") - 1)
3018*7c478bd9Sstevel@tonic-gate 		return (B_FALSE);
3019*7c478bd9Sstevel@tonic-gate 	for (c = name + sizeof ("zone.") - 1; *c != '\0'; c++) {
3020*7c478bd9Sstevel@tonic-gate 		if (!isalpha(*c) && *c != '-')
3021*7c478bd9Sstevel@tonic-gate 			return (B_FALSE);
3022*7c478bd9Sstevel@tonic-gate 	}
3023*7c478bd9Sstevel@tonic-gate 	return (B_TRUE);
3024*7c478bd9Sstevel@tonic-gate }
3025*7c478bd9Sstevel@tonic-gate 
3026*7c478bd9Sstevel@tonic-gate boolean_t
3027*7c478bd9Sstevel@tonic-gate zonecfg_valid_rctlblk(const rctlblk_t *rctlblk)
3028*7c478bd9Sstevel@tonic-gate {
3029*7c478bd9Sstevel@tonic-gate 	rctl_priv_t priv = rctlblk_get_privilege((rctlblk_t *)rctlblk);
3030*7c478bd9Sstevel@tonic-gate 	uint_t action = rctlblk_get_local_action((rctlblk_t *)rctlblk, NULL);
3031*7c478bd9Sstevel@tonic-gate 
3032*7c478bd9Sstevel@tonic-gate 	if (priv != RCPRIV_PRIVILEGED)
3033*7c478bd9Sstevel@tonic-gate 		return (B_FALSE);
3034*7c478bd9Sstevel@tonic-gate 	if (action != RCTL_LOCAL_NOACTION && action != RCTL_LOCAL_DENY)
3035*7c478bd9Sstevel@tonic-gate 		return (B_FALSE);
3036*7c478bd9Sstevel@tonic-gate 	return (B_TRUE);
3037*7c478bd9Sstevel@tonic-gate }
3038*7c478bd9Sstevel@tonic-gate 
3039*7c478bd9Sstevel@tonic-gate boolean_t
3040*7c478bd9Sstevel@tonic-gate zonecfg_valid_rctl(const char *name, const rctlblk_t *rctlblk)
3041*7c478bd9Sstevel@tonic-gate {
3042*7c478bd9Sstevel@tonic-gate 	rctlblk_t *current, *next;
3043*7c478bd9Sstevel@tonic-gate 	rctl_qty_t limit = rctlblk_get_value((rctlblk_t *)rctlblk);
3044*7c478bd9Sstevel@tonic-gate 	uint_t action = rctlblk_get_local_action((rctlblk_t *)rctlblk, NULL);
3045*7c478bd9Sstevel@tonic-gate 	uint_t global_flags;
3046*7c478bd9Sstevel@tonic-gate 
3047*7c478bd9Sstevel@tonic-gate 	if (!zonecfg_valid_rctlblk(rctlblk))
3048*7c478bd9Sstevel@tonic-gate 		return (B_FALSE);
3049*7c478bd9Sstevel@tonic-gate 	if (!zonecfg_valid_rctlname(name))
3050*7c478bd9Sstevel@tonic-gate 		return (B_FALSE);
3051*7c478bd9Sstevel@tonic-gate 
3052*7c478bd9Sstevel@tonic-gate 	current = alloca(rctlblk_size());
3053*7c478bd9Sstevel@tonic-gate 	if (getrctl(name, NULL, current, RCTL_FIRST) != 0)
3054*7c478bd9Sstevel@tonic-gate 		return (B_TRUE);	/* not an rctl on this system */
3055*7c478bd9Sstevel@tonic-gate 	/*
3056*7c478bd9Sstevel@tonic-gate 	 * Make sure the proposed value isn't greater than the current system
3057*7c478bd9Sstevel@tonic-gate 	 * value.
3058*7c478bd9Sstevel@tonic-gate 	 */
3059*7c478bd9Sstevel@tonic-gate 	next = alloca(rctlblk_size());
3060*7c478bd9Sstevel@tonic-gate 	while (rctlblk_get_privilege(current) != RCPRIV_SYSTEM) {
3061*7c478bd9Sstevel@tonic-gate 		rctlblk_t *tmp;
3062*7c478bd9Sstevel@tonic-gate 
3063*7c478bd9Sstevel@tonic-gate 		if (getrctl(name, current, next, RCTL_NEXT) != 0)
3064*7c478bd9Sstevel@tonic-gate 			return (B_FALSE);	/* shouldn't happen */
3065*7c478bd9Sstevel@tonic-gate 		tmp = current;
3066*7c478bd9Sstevel@tonic-gate 		current = next;
3067*7c478bd9Sstevel@tonic-gate 		next = tmp;
3068*7c478bd9Sstevel@tonic-gate 	}
3069*7c478bd9Sstevel@tonic-gate 	if (limit > rctlblk_get_value(current))
3070*7c478bd9Sstevel@tonic-gate 		return (B_FALSE);
3071*7c478bd9Sstevel@tonic-gate 
3072*7c478bd9Sstevel@tonic-gate 	/*
3073*7c478bd9Sstevel@tonic-gate 	 * Make sure the proposed action is allowed.
3074*7c478bd9Sstevel@tonic-gate 	 */
3075*7c478bd9Sstevel@tonic-gate 	global_flags = rctlblk_get_global_flags(current);
3076*7c478bd9Sstevel@tonic-gate 	if ((global_flags & RCTL_GLOBAL_DENY_NEVER) &&
3077*7c478bd9Sstevel@tonic-gate 	    action == RCTL_LOCAL_DENY)
3078*7c478bd9Sstevel@tonic-gate 		return (B_FALSE);
3079*7c478bd9Sstevel@tonic-gate 	if ((global_flags & RCTL_GLOBAL_DENY_ALWAYS) &&
3080*7c478bd9Sstevel@tonic-gate 	    action == RCTL_LOCAL_NOACTION)
3081*7c478bd9Sstevel@tonic-gate 		return (B_FALSE);
3082*7c478bd9Sstevel@tonic-gate 
3083*7c478bd9Sstevel@tonic-gate 	return (B_TRUE);
3084*7c478bd9Sstevel@tonic-gate }
3085