xref: /onnv-gate/usr/src/lib/libnwam/common/libnwam_object.c (revision 11767:8f30d0e611c6)
1*11767SAnurag.Maskey@Sun.COM /*
2*11767SAnurag.Maskey@Sun.COM  * CDDL HEADER START
3*11767SAnurag.Maskey@Sun.COM  *
4*11767SAnurag.Maskey@Sun.COM  * The contents of this file are subject to the terms of the
5*11767SAnurag.Maskey@Sun.COM  * Common Development and Distribution License (the "License").
6*11767SAnurag.Maskey@Sun.COM  * You may not use this file except in compliance with the License.
7*11767SAnurag.Maskey@Sun.COM  *
8*11767SAnurag.Maskey@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*11767SAnurag.Maskey@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*11767SAnurag.Maskey@Sun.COM  * See the License for the specific language governing permissions
11*11767SAnurag.Maskey@Sun.COM  * and limitations under the License.
12*11767SAnurag.Maskey@Sun.COM  *
13*11767SAnurag.Maskey@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*11767SAnurag.Maskey@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*11767SAnurag.Maskey@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*11767SAnurag.Maskey@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*11767SAnurag.Maskey@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*11767SAnurag.Maskey@Sun.COM  *
19*11767SAnurag.Maskey@Sun.COM  * CDDL HEADER END
20*11767SAnurag.Maskey@Sun.COM  */
21*11767SAnurag.Maskey@Sun.COM 
22*11767SAnurag.Maskey@Sun.COM /*
23*11767SAnurag.Maskey@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
24*11767SAnurag.Maskey@Sun.COM  * Use is subject to license terms.
25*11767SAnurag.Maskey@Sun.COM  */
26*11767SAnurag.Maskey@Sun.COM 
27*11767SAnurag.Maskey@Sun.COM #include <assert.h>
28*11767SAnurag.Maskey@Sun.COM #include <stdlib.h>
29*11767SAnurag.Maskey@Sun.COM #include <strings.h>
30*11767SAnurag.Maskey@Sun.COM #include <string.h>
31*11767SAnurag.Maskey@Sun.COM 
32*11767SAnurag.Maskey@Sun.COM #include "libnwam_impl.h"
33*11767SAnurag.Maskey@Sun.COM #include <libintl.h>
34*11767SAnurag.Maskey@Sun.COM #include <libnwam.h>
35*11767SAnurag.Maskey@Sun.COM 
36*11767SAnurag.Maskey@Sun.COM /*
37*11767SAnurag.Maskey@Sun.COM  * Generic object manipulation functions. Given an object handle and
38*11767SAnurag.Maskey@Sun.COM  * other parameters, create/destroy objects, walk them, walk their
39*11767SAnurag.Maskey@Sun.COM  * properties, modify/retrieve/delete properties, enable/disable them,
40*11767SAnurag.Maskey@Sun.COM  * etc. All object handles are "struct nwam_handle *" objects, sharing
41*11767SAnurag.Maskey@Sun.COM  * the same description based on the object type, name, original name
42*11767SAnurag.Maskey@Sun.COM  * (used in renaming) and associated data representing properties.
43*11767SAnurag.Maskey@Sun.COM  */
44*11767SAnurag.Maskey@Sun.COM 
45*11767SAnurag.Maskey@Sun.COM nwam_error_t
46*11767SAnurag.Maskey@Sun.COM nwam_handle_create(nwam_object_type_t type, const char *name,
47*11767SAnurag.Maskey@Sun.COM     struct nwam_handle **hpp)
48*11767SAnurag.Maskey@Sun.COM {
49*11767SAnurag.Maskey@Sun.COM 
50*11767SAnurag.Maskey@Sun.COM 	assert(name != NULL && hpp != NULL);
51*11767SAnurag.Maskey@Sun.COM 
52*11767SAnurag.Maskey@Sun.COM 	if (strnlen(name, NWAM_MAX_NAME_LEN) > NWAM_MAX_NAME_LEN) {
53*11767SAnurag.Maskey@Sun.COM 		*hpp = NULL;
54*11767SAnurag.Maskey@Sun.COM 		return (NWAM_INVALID_ARG);
55*11767SAnurag.Maskey@Sun.COM 	}
56*11767SAnurag.Maskey@Sun.COM 
57*11767SAnurag.Maskey@Sun.COM 	if ((*hpp = calloc(1, sizeof (struct nwam_handle))) == NULL)
58*11767SAnurag.Maskey@Sun.COM 		return (NWAM_NO_MEMORY);
59*11767SAnurag.Maskey@Sun.COM 
60*11767SAnurag.Maskey@Sun.COM 	(*hpp)->nwh_object_type = type;
61*11767SAnurag.Maskey@Sun.COM 	(void) strlcpy((*hpp)->nwh_name, name, strlen(name) + 1);
62*11767SAnurag.Maskey@Sun.COM 	(*hpp)->nwh_committed = B_FALSE;
63*11767SAnurag.Maskey@Sun.COM 	(*hpp)->nwh_data = NULL;
64*11767SAnurag.Maskey@Sun.COM 
65*11767SAnurag.Maskey@Sun.COM 	return (NWAM_SUCCESS);
66*11767SAnurag.Maskey@Sun.COM }
67*11767SAnurag.Maskey@Sun.COM 
68*11767SAnurag.Maskey@Sun.COM /*
69*11767SAnurag.Maskey@Sun.COM  * Read object of specified type from dbname.
70*11767SAnurag.Maskey@Sun.COM  */
71*11767SAnurag.Maskey@Sun.COM nwam_error_t
72*11767SAnurag.Maskey@Sun.COM nwam_read(nwam_object_type_t type, const char *dbname, const char *name,
73*11767SAnurag.Maskey@Sun.COM     uint64_t flags, struct nwam_handle **hpp)
74*11767SAnurag.Maskey@Sun.COM {
75*11767SAnurag.Maskey@Sun.COM 	nwam_error_t err;
76*11767SAnurag.Maskey@Sun.COM 	char dbname_copy[MAXPATHLEN];
77*11767SAnurag.Maskey@Sun.COM 
78*11767SAnurag.Maskey@Sun.COM 	assert(name != NULL && hpp != NULL);
79*11767SAnurag.Maskey@Sun.COM 
80*11767SAnurag.Maskey@Sun.COM 	if (dbname != NULL)
81*11767SAnurag.Maskey@Sun.COM 		(void) strlcpy(dbname_copy, dbname, sizeof (dbname_copy));
82*11767SAnurag.Maskey@Sun.COM 
83*11767SAnurag.Maskey@Sun.COM 	if ((err = nwam_valid_flags(flags, NWAM_FLAG_BLOCKING)) != NWAM_SUCCESS)
84*11767SAnurag.Maskey@Sun.COM 		return (err);
85*11767SAnurag.Maskey@Sun.COM 	if ((err = nwam_handle_create(type, name, hpp)) != NWAM_SUCCESS)
86*11767SAnurag.Maskey@Sun.COM 		return (err);
87*11767SAnurag.Maskey@Sun.COM 
88*11767SAnurag.Maskey@Sun.COM 	if ((err = nwam_read_object_from_backend
89*11767SAnurag.Maskey@Sun.COM 	    (dbname != NULL ? dbname_copy : NULL,
90*11767SAnurag.Maskey@Sun.COM 	    type == NWAM_OBJECT_TYPE_NCP ? NULL : (*hpp)->nwh_name, flags,
91*11767SAnurag.Maskey@Sun.COM 	    &(*hpp)->nwh_data)) != NWAM_SUCCESS) {
92*11767SAnurag.Maskey@Sun.COM 		free(*hpp);
93*11767SAnurag.Maskey@Sun.COM 		*hpp = NULL;
94*11767SAnurag.Maskey@Sun.COM 		return (err);
95*11767SAnurag.Maskey@Sun.COM 	}
96*11767SAnurag.Maskey@Sun.COM 	if (type == NWAM_OBJECT_TYPE_NCP && dbname != NULL) {
97*11767SAnurag.Maskey@Sun.COM 		char *ncpname;
98*11767SAnurag.Maskey@Sun.COM 
99*11767SAnurag.Maskey@Sun.COM 		/*
100*11767SAnurag.Maskey@Sun.COM 		 * dbname_copy may have been changed due to case-insensitive
101*11767SAnurag.Maskey@Sun.COM 		 * match against the actual NCP configuration file.
102*11767SAnurag.Maskey@Sun.COM 		 */
103*11767SAnurag.Maskey@Sun.COM 		if (nwam_ncp_file_to_name(dbname_copy, &ncpname)
104*11767SAnurag.Maskey@Sun.COM 		    == NWAM_SUCCESS) {
105*11767SAnurag.Maskey@Sun.COM 			(void) strlcpy((*hpp)->nwh_name, ncpname,
106*11767SAnurag.Maskey@Sun.COM 			    sizeof ((*hpp)->nwh_name));
107*11767SAnurag.Maskey@Sun.COM 			free(ncpname);
108*11767SAnurag.Maskey@Sun.COM 		}
109*11767SAnurag.Maskey@Sun.COM 	}
110*11767SAnurag.Maskey@Sun.COM 
111*11767SAnurag.Maskey@Sun.COM 	(*hpp)->nwh_committed = B_TRUE;
112*11767SAnurag.Maskey@Sun.COM 
113*11767SAnurag.Maskey@Sun.COM 	return (NWAM_SUCCESS);
114*11767SAnurag.Maskey@Sun.COM }
115*11767SAnurag.Maskey@Sun.COM 
116*11767SAnurag.Maskey@Sun.COM /*
117*11767SAnurag.Maskey@Sun.COM  * Create simply creates the handle - the object-specific function must
118*11767SAnurag.Maskey@Sun.COM  * then fill in property values.
119*11767SAnurag.Maskey@Sun.COM  */
120*11767SAnurag.Maskey@Sun.COM nwam_error_t
121*11767SAnurag.Maskey@Sun.COM nwam_create(nwam_object_type_t type, const char *dbname, const char *name,
122*11767SAnurag.Maskey@Sun.COM     struct nwam_handle **hpp)
123*11767SAnurag.Maskey@Sun.COM {
124*11767SAnurag.Maskey@Sun.COM 	struct nwam_handle *hp;
125*11767SAnurag.Maskey@Sun.COM 
126*11767SAnurag.Maskey@Sun.COM 	assert(hpp != NULL && name != NULL);
127*11767SAnurag.Maskey@Sun.COM 
128*11767SAnurag.Maskey@Sun.COM 	if (nwam_read(type, dbname, name, 0, &hp) == NWAM_SUCCESS) {
129*11767SAnurag.Maskey@Sun.COM 		nwam_free(hp);
130*11767SAnurag.Maskey@Sun.COM 		return (NWAM_ENTITY_EXISTS);
131*11767SAnurag.Maskey@Sun.COM 	}
132*11767SAnurag.Maskey@Sun.COM 	/* Create handle */
133*11767SAnurag.Maskey@Sun.COM 	return (nwam_handle_create(type, name, hpp));
134*11767SAnurag.Maskey@Sun.COM }
135*11767SAnurag.Maskey@Sun.COM 
136*11767SAnurag.Maskey@Sun.COM nwam_error_t
137*11767SAnurag.Maskey@Sun.COM nwam_get_name(struct nwam_handle *hp, char **namep)
138*11767SAnurag.Maskey@Sun.COM {
139*11767SAnurag.Maskey@Sun.COM 	assert(hp != NULL && namep != NULL);
140*11767SAnurag.Maskey@Sun.COM 
141*11767SAnurag.Maskey@Sun.COM 	if ((*namep = strdup(hp->nwh_name)) == NULL) {
142*11767SAnurag.Maskey@Sun.COM 		*namep = NULL;
143*11767SAnurag.Maskey@Sun.COM 		return (NWAM_NO_MEMORY);
144*11767SAnurag.Maskey@Sun.COM 	}
145*11767SAnurag.Maskey@Sun.COM 	return (NWAM_SUCCESS);
146*11767SAnurag.Maskey@Sun.COM }
147*11767SAnurag.Maskey@Sun.COM 
148*11767SAnurag.Maskey@Sun.COM nwam_error_t
149*11767SAnurag.Maskey@Sun.COM nwam_set_name(struct nwam_handle *hp, const char *name)
150*11767SAnurag.Maskey@Sun.COM {
151*11767SAnurag.Maskey@Sun.COM 	assert(hp != NULL && name != NULL);
152*11767SAnurag.Maskey@Sun.COM 
153*11767SAnurag.Maskey@Sun.COM 	if (hp->nwh_committed)
154*11767SAnurag.Maskey@Sun.COM 		return (NWAM_ENTITY_READ_ONLY);
155*11767SAnurag.Maskey@Sun.COM 
156*11767SAnurag.Maskey@Sun.COM 	if (strlen(name) >= sizeof (hp->nwh_name))
157*11767SAnurag.Maskey@Sun.COM 		return (NWAM_INVALID_ARG);
158*11767SAnurag.Maskey@Sun.COM 
159*11767SAnurag.Maskey@Sun.COM 	(void) strcpy(hp->nwh_name, name);
160*11767SAnurag.Maskey@Sun.COM 
161*11767SAnurag.Maskey@Sun.COM 	return (NWAM_SUCCESS);
162*11767SAnurag.Maskey@Sun.COM }
163*11767SAnurag.Maskey@Sun.COM 
164*11767SAnurag.Maskey@Sun.COM /* Compare object names c1 and c2 using strcasecmp() */
165*11767SAnurag.Maskey@Sun.COM static int
166*11767SAnurag.Maskey@Sun.COM name_cmp(const void *c1, const void *c2)
167*11767SAnurag.Maskey@Sun.COM {
168*11767SAnurag.Maskey@Sun.COM 	nwam_ncu_type_t t1, t2;
169*11767SAnurag.Maskey@Sun.COM 	char		*n1, *n2;
170*11767SAnurag.Maskey@Sun.COM 
171*11767SAnurag.Maskey@Sun.COM 	/* If c1 and c2 are typed NCU names, compare names without the types */
172*11767SAnurag.Maskey@Sun.COM 	if (nwam_ncu_typed_name_to_name(*(const char **)c1, &t1, &n1)
173*11767SAnurag.Maskey@Sun.COM 	    == NWAM_SUCCESS &&
174*11767SAnurag.Maskey@Sun.COM 	    nwam_ncu_typed_name_to_name(*(const char **)c2, &t2, &n2)
175*11767SAnurag.Maskey@Sun.COM 	    == NWAM_SUCCESS) {
176*11767SAnurag.Maskey@Sun.COM 		int ret = strcasecmp(n1, n2);
177*11767SAnurag.Maskey@Sun.COM 		free(n1);
178*11767SAnurag.Maskey@Sun.COM 		free(n2);
179*11767SAnurag.Maskey@Sun.COM 
180*11767SAnurag.Maskey@Sun.COM 		/* For NCUs with the same name, compare their types */
181*11767SAnurag.Maskey@Sun.COM 		if (ret == 0) {
182*11767SAnurag.Maskey@Sun.COM 			if (t1 < t2)
183*11767SAnurag.Maskey@Sun.COM 				ret = -1;
184*11767SAnurag.Maskey@Sun.COM 			else if (t1 > t2)
185*11767SAnurag.Maskey@Sun.COM 				ret = 1;
186*11767SAnurag.Maskey@Sun.COM 		}
187*11767SAnurag.Maskey@Sun.COM 		return (ret);
188*11767SAnurag.Maskey@Sun.COM 	}
189*11767SAnurag.Maskey@Sun.COM 
190*11767SAnurag.Maskey@Sun.COM 	return (strcasecmp(*(const char **)c1, *(const char **)c2));
191*11767SAnurag.Maskey@Sun.COM }
192*11767SAnurag.Maskey@Sun.COM 
193*11767SAnurag.Maskey@Sun.COM /*
194*11767SAnurag.Maskey@Sun.COM  * Generic walk function takes the standard walk arguments, and in addition
195*11767SAnurag.Maskey@Sun.COM  * takes a selection callback that is object-specific. If this returns
196*11767SAnurag.Maskey@Sun.COM  * 0, the object is a valid selection for the walk and the callback is called.
197*11767SAnurag.Maskey@Sun.COM  * Otherwise, it is skipped.
198*11767SAnurag.Maskey@Sun.COM  */
199*11767SAnurag.Maskey@Sun.COM nwam_error_t
200*11767SAnurag.Maskey@Sun.COM nwam_walk(nwam_object_type_t type, const char *dbname,
201*11767SAnurag.Maskey@Sun.COM     int(*cb)(struct nwam_handle *, void *),
202*11767SAnurag.Maskey@Sun.COM     void *data, uint64_t flags, int *retp,
203*11767SAnurag.Maskey@Sun.COM     int(*selectcb)(struct nwam_handle *, uint64_t, void *))
204*11767SAnurag.Maskey@Sun.COM {
205*11767SAnurag.Maskey@Sun.COM 	void *objlist;
206*11767SAnurag.Maskey@Sun.COM 	nwam_value_t value;
207*11767SAnurag.Maskey@Sun.COM 	char **object_names;
208*11767SAnurag.Maskey@Sun.COM 	uint_t i, num_objects = 0;
209*11767SAnurag.Maskey@Sun.COM 	struct nwam_handle *hp;
210*11767SAnurag.Maskey@Sun.COM 	nwam_error_t err;
211*11767SAnurag.Maskey@Sun.COM 	int ret = 0;
212*11767SAnurag.Maskey@Sun.COM 
213*11767SAnurag.Maskey@Sun.COM 	assert(cb != NULL);
214*11767SAnurag.Maskey@Sun.COM 
215*11767SAnurag.Maskey@Sun.COM 	/*
216*11767SAnurag.Maskey@Sun.COM 	 * To walk a set of objects, call nwam_read_object_from_backend()
217*11767SAnurag.Maskey@Sun.COM 	 * with a "dbname" argument set to the container db name and
218*11767SAnurag.Maskey@Sun.COM 	 * the object name set to NULL. This returns an nvlist with one
219*11767SAnurag.Maskey@Sun.COM 	 * member - the NWAM_OBJECT_NAMES_STRING - and the values it contains
220*11767SAnurag.Maskey@Sun.COM 	 * represent the names of the objects.  Read each in turn, calling
221*11767SAnurag.Maskey@Sun.COM 	 * the callback function.
222*11767SAnurag.Maskey@Sun.COM 	 */
223*11767SAnurag.Maskey@Sun.COM 	if ((err = nwam_read_object_from_backend((char *)dbname, NULL, flags,
224*11767SAnurag.Maskey@Sun.COM 	    &objlist)) != NWAM_SUCCESS) {
225*11767SAnurag.Maskey@Sun.COM 		if (err == NWAM_ENTITY_NOT_FOUND) {
226*11767SAnurag.Maskey@Sun.COM 			/*
227*11767SAnurag.Maskey@Sun.COM 			 * This indicates the dbname container is not present.
228*11767SAnurag.Maskey@Sun.COM 			 * Do not pass back an error in this case, since it is
229*11767SAnurag.Maskey@Sun.COM 			 * valid for a container not to exist.
230*11767SAnurag.Maskey@Sun.COM 			 */
231*11767SAnurag.Maskey@Sun.COM 			return (NWAM_SUCCESS);
232*11767SAnurag.Maskey@Sun.COM 		}
233*11767SAnurag.Maskey@Sun.COM 		return (err);
234*11767SAnurag.Maskey@Sun.COM 	}
235*11767SAnurag.Maskey@Sun.COM 
236*11767SAnurag.Maskey@Sun.COM 	if ((err = nwam_get_prop_value(objlist, NWAM_OBJECT_NAMES_STRING,
237*11767SAnurag.Maskey@Sun.COM 	    &value)) != NWAM_SUCCESS) {
238*11767SAnurag.Maskey@Sun.COM 		nwam_free_object_list(objlist);
239*11767SAnurag.Maskey@Sun.COM 		return (err);
240*11767SAnurag.Maskey@Sun.COM 	}
241*11767SAnurag.Maskey@Sun.COM 	err = nwam_value_get_string_array(value, &object_names, &num_objects);
242*11767SAnurag.Maskey@Sun.COM 	nwam_free_object_list(objlist);
243*11767SAnurag.Maskey@Sun.COM 	if (err != NWAM_SUCCESS) {
244*11767SAnurag.Maskey@Sun.COM 		nwam_value_free(value);
245*11767SAnurag.Maskey@Sun.COM 		return (err);
246*11767SAnurag.Maskey@Sun.COM 	}
247*11767SAnurag.Maskey@Sun.COM 
248*11767SAnurag.Maskey@Sun.COM 	/* sort the object names alphabetically */
249*11767SAnurag.Maskey@Sun.COM 	qsort(object_names, num_objects, sizeof (char *), name_cmp);
250*11767SAnurag.Maskey@Sun.COM 
251*11767SAnurag.Maskey@Sun.COM 	for (i = 0; i < num_objects; i++) {
252*11767SAnurag.Maskey@Sun.COM 		err = nwam_read(type, dbname, object_names[i],
253*11767SAnurag.Maskey@Sun.COM 		    flags & NWAM_FLAG_GLOBAL_MASK, &hp);
254*11767SAnurag.Maskey@Sun.COM 		/* An object may have disappeared.  If so, skip it. */
255*11767SAnurag.Maskey@Sun.COM 		if (err == NWAM_ENTITY_NOT_FOUND)
256*11767SAnurag.Maskey@Sun.COM 			continue;
257*11767SAnurag.Maskey@Sun.COM 		if (err != NWAM_SUCCESS) {
258*11767SAnurag.Maskey@Sun.COM 			nwam_value_free(value);
259*11767SAnurag.Maskey@Sun.COM 			return (err);
260*11767SAnurag.Maskey@Sun.COM 		}
261*11767SAnurag.Maskey@Sun.COM 		if ((selectcb == NULL) || (selectcb(hp, flags, data) == 0)) {
262*11767SAnurag.Maskey@Sun.COM 			ret = cb(hp, data);
263*11767SAnurag.Maskey@Sun.COM 			if (ret != 0) {
264*11767SAnurag.Maskey@Sun.COM 				nwam_free(hp);
265*11767SAnurag.Maskey@Sun.COM 				nwam_value_free(value);
266*11767SAnurag.Maskey@Sun.COM 				if (retp != NULL)
267*11767SAnurag.Maskey@Sun.COM 					*retp = ret;
268*11767SAnurag.Maskey@Sun.COM 				return (NWAM_WALK_HALTED);
269*11767SAnurag.Maskey@Sun.COM 			}
270*11767SAnurag.Maskey@Sun.COM 		}
271*11767SAnurag.Maskey@Sun.COM 		nwam_free(hp);
272*11767SAnurag.Maskey@Sun.COM 	}
273*11767SAnurag.Maskey@Sun.COM 	nwam_value_free(value);
274*11767SAnurag.Maskey@Sun.COM 
275*11767SAnurag.Maskey@Sun.COM 	if (retp != NULL)
276*11767SAnurag.Maskey@Sun.COM 		*retp = ret;
277*11767SAnurag.Maskey@Sun.COM 	return (err);
278*11767SAnurag.Maskey@Sun.COM }
279*11767SAnurag.Maskey@Sun.COM 
280*11767SAnurag.Maskey@Sun.COM void
281*11767SAnurag.Maskey@Sun.COM nwam_free(struct nwam_handle *hp)
282*11767SAnurag.Maskey@Sun.COM {
283*11767SAnurag.Maskey@Sun.COM 	if (hp != NULL) {
284*11767SAnurag.Maskey@Sun.COM 		if (hp->nwh_data != NULL)
285*11767SAnurag.Maskey@Sun.COM 			nwam_free_object_list(hp->nwh_data);
286*11767SAnurag.Maskey@Sun.COM 		free(hp);
287*11767SAnurag.Maskey@Sun.COM 	}
288*11767SAnurag.Maskey@Sun.COM }
289*11767SAnurag.Maskey@Sun.COM 
290*11767SAnurag.Maskey@Sun.COM /*
291*11767SAnurag.Maskey@Sun.COM  * Copy object represented by oldhp to an object newname, all in container
292*11767SAnurag.Maskey@Sun.COM  * dbname.
293*11767SAnurag.Maskey@Sun.COM  */
294*11767SAnurag.Maskey@Sun.COM nwam_error_t
295*11767SAnurag.Maskey@Sun.COM nwam_copy(const char *dbname, struct nwam_handle *oldhp, const char *newname,
296*11767SAnurag.Maskey@Sun.COM     struct nwam_handle **newhpp)
297*11767SAnurag.Maskey@Sun.COM {
298*11767SAnurag.Maskey@Sun.COM 	nwam_error_t err;
299*11767SAnurag.Maskey@Sun.COM 	struct nwam_handle *hp;
300*11767SAnurag.Maskey@Sun.COM 
301*11767SAnurag.Maskey@Sun.COM 	assert(oldhp != NULL && newname != NULL && newhpp != NULL);
302*11767SAnurag.Maskey@Sun.COM 
303*11767SAnurag.Maskey@Sun.COM 	if (nwam_read(oldhp->nwh_object_type, dbname, newname, 0, &hp)
304*11767SAnurag.Maskey@Sun.COM 	    == NWAM_SUCCESS) {
305*11767SAnurag.Maskey@Sun.COM 		nwam_free(hp);
306*11767SAnurag.Maskey@Sun.COM 		return (NWAM_ENTITY_EXISTS);
307*11767SAnurag.Maskey@Sun.COM 	}
308*11767SAnurag.Maskey@Sun.COM 
309*11767SAnurag.Maskey@Sun.COM 	if ((err = nwam_handle_create(oldhp->nwh_object_type, newname, newhpp))
310*11767SAnurag.Maskey@Sun.COM 	    != NWAM_SUCCESS)
311*11767SAnurag.Maskey@Sun.COM 		return (err);
312*11767SAnurag.Maskey@Sun.COM 	if ((err = nwam_dup_object_list(oldhp->nwh_data,
313*11767SAnurag.Maskey@Sun.COM 	    &((*newhpp)->nwh_data))) != NWAM_SUCCESS) {
314*11767SAnurag.Maskey@Sun.COM 		nwam_free(*newhpp);
315*11767SAnurag.Maskey@Sun.COM 		*newhpp = NULL;
316*11767SAnurag.Maskey@Sun.COM 		return (err);
317*11767SAnurag.Maskey@Sun.COM 	}
318*11767SAnurag.Maskey@Sun.COM 
319*11767SAnurag.Maskey@Sun.COM 	return (NWAM_SUCCESS);
320*11767SAnurag.Maskey@Sun.COM }
321*11767SAnurag.Maskey@Sun.COM 
322*11767SAnurag.Maskey@Sun.COM /* ARGSUSED3 */
323*11767SAnurag.Maskey@Sun.COM nwam_error_t
324*11767SAnurag.Maskey@Sun.COM nwam_walk_props(struct nwam_handle *hp,
325*11767SAnurag.Maskey@Sun.COM     int (*cb)(const char *, nwam_value_t, void *),
326*11767SAnurag.Maskey@Sun.COM     void *data, uint64_t flags, int *retp)
327*11767SAnurag.Maskey@Sun.COM {
328*11767SAnurag.Maskey@Sun.COM 	char *lastpropname = NULL, *propname;
329*11767SAnurag.Maskey@Sun.COM 	nwam_value_t value;
330*11767SAnurag.Maskey@Sun.COM 	nwam_error_t err;
331*11767SAnurag.Maskey@Sun.COM 	int ret = 0;
332*11767SAnurag.Maskey@Sun.COM 
333*11767SAnurag.Maskey@Sun.COM 	assert(hp != NULL && hp->nwh_data != NULL && cb != NULL);
334*11767SAnurag.Maskey@Sun.COM 
335*11767SAnurag.Maskey@Sun.COM 	if ((err = nwam_valid_flags(flags, 0)) != NWAM_SUCCESS)
336*11767SAnurag.Maskey@Sun.COM 		return (err);
337*11767SAnurag.Maskey@Sun.COM 	while ((err = nwam_next_object_prop(hp->nwh_data, lastpropname,
338*11767SAnurag.Maskey@Sun.COM 	    &propname, &value)) == NWAM_SUCCESS) {
339*11767SAnurag.Maskey@Sun.COM 
340*11767SAnurag.Maskey@Sun.COM 		ret = cb(propname, value, data);
341*11767SAnurag.Maskey@Sun.COM 		if (ret != 0)
342*11767SAnurag.Maskey@Sun.COM 			err = NWAM_WALK_HALTED;
343*11767SAnurag.Maskey@Sun.COM 
344*11767SAnurag.Maskey@Sun.COM 		/* Free value */
345*11767SAnurag.Maskey@Sun.COM 		nwam_value_free(value);
346*11767SAnurag.Maskey@Sun.COM 
347*11767SAnurag.Maskey@Sun.COM 		if (err != NWAM_SUCCESS)
348*11767SAnurag.Maskey@Sun.COM 			break;
349*11767SAnurag.Maskey@Sun.COM 
350*11767SAnurag.Maskey@Sun.COM 		lastpropname = propname;
351*11767SAnurag.Maskey@Sun.COM 	}
352*11767SAnurag.Maskey@Sun.COM 
353*11767SAnurag.Maskey@Sun.COM 	if (retp != NULL)
354*11767SAnurag.Maskey@Sun.COM 		*retp = ret;
355*11767SAnurag.Maskey@Sun.COM 	if (err == NWAM_SUCCESS || err == NWAM_LIST_END)
356*11767SAnurag.Maskey@Sun.COM 		return (NWAM_SUCCESS);
357*11767SAnurag.Maskey@Sun.COM 	return (err);
358*11767SAnurag.Maskey@Sun.COM }
359*11767SAnurag.Maskey@Sun.COM 
360*11767SAnurag.Maskey@Sun.COM /*
361*11767SAnurag.Maskey@Sun.COM  * Note that prior to calling the generic commit function, object-specific
362*11767SAnurag.Maskey@Sun.COM  * validation should be carried out.
363*11767SAnurag.Maskey@Sun.COM  */
364*11767SAnurag.Maskey@Sun.COM nwam_error_t
365*11767SAnurag.Maskey@Sun.COM nwam_commit(const char *dbname, struct nwam_handle *hp, uint64_t flags)
366*11767SAnurag.Maskey@Sun.COM {
367*11767SAnurag.Maskey@Sun.COM 	nwam_error_t err;
368*11767SAnurag.Maskey@Sun.COM 	uint64_t iflags = flags;
369*11767SAnurag.Maskey@Sun.COM 	boolean_t is_ncu;
370*11767SAnurag.Maskey@Sun.COM 	struct nwam_handle *testhp;
371*11767SAnurag.Maskey@Sun.COM 	nwam_action_t action;
372*11767SAnurag.Maskey@Sun.COM 
373*11767SAnurag.Maskey@Sun.COM 	assert(hp != NULL);
374*11767SAnurag.Maskey@Sun.COM 
375*11767SAnurag.Maskey@Sun.COM 	/*
376*11767SAnurag.Maskey@Sun.COM 	 * NWAM_FLAG_ENTITY_KNOWN_WLAN is only used for Known WLANs and
377*11767SAnurag.Maskey@Sun.COM 	 * NWAM_FLAG_ENTITY_ENABLE is used for other objects (during enable
378*11767SAnurag.Maskey@Sun.COM 	 * and disable).
379*11767SAnurag.Maskey@Sun.COM 	 */
380*11767SAnurag.Maskey@Sun.COM 	if ((err = nwam_valid_flags(flags,
381*11767SAnurag.Maskey@Sun.COM 	    NWAM_FLAG_BLOCKING | NWAM_FLAG_CREATE |
382*11767SAnurag.Maskey@Sun.COM 	    (hp->nwh_object_type == NWAM_OBJECT_TYPE_KNOWN_WLAN ?
383*11767SAnurag.Maskey@Sun.COM 	    NWAM_FLAG_ENTITY_KNOWN_WLAN : NWAM_FLAG_ENTITY_ENABLE)))
384*11767SAnurag.Maskey@Sun.COM 	    != NWAM_SUCCESS)
385*11767SAnurag.Maskey@Sun.COM 		return (err);
386*11767SAnurag.Maskey@Sun.COM 
387*11767SAnurag.Maskey@Sun.COM 	is_ncu = (hp->nwh_object_type == NWAM_OBJECT_TYPE_NCU);
388*11767SAnurag.Maskey@Sun.COM 
389*11767SAnurag.Maskey@Sun.COM 	/*
390*11767SAnurag.Maskey@Sun.COM 	 * Does object already exist? If not, action is ADD, otherwise REFRESH.
391*11767SAnurag.Maskey@Sun.COM 	 */
392*11767SAnurag.Maskey@Sun.COM 	switch (nwam_read(hp->nwh_object_type, (char *)dbname, hp->nwh_name, 0,
393*11767SAnurag.Maskey@Sun.COM 	    &testhp)) {
394*11767SAnurag.Maskey@Sun.COM 	case NWAM_ENTITY_NOT_FOUND:
395*11767SAnurag.Maskey@Sun.COM 		action = NWAM_ACTION_ADD;
396*11767SAnurag.Maskey@Sun.COM 		break;
397*11767SAnurag.Maskey@Sun.COM 	case NWAM_SUCCESS:
398*11767SAnurag.Maskey@Sun.COM 		nwam_free(testhp);
399*11767SAnurag.Maskey@Sun.COM 		if (hp->nwh_object_type == NWAM_OBJECT_TYPE_NCP)
400*11767SAnurag.Maskey@Sun.COM 			return (NWAM_ENTITY_EXISTS);
401*11767SAnurag.Maskey@Sun.COM 		/* FALLTHRU */
402*11767SAnurag.Maskey@Sun.COM 	default:
403*11767SAnurag.Maskey@Sun.COM 		action = NWAM_ACTION_REFRESH;
404*11767SAnurag.Maskey@Sun.COM 		break;
405*11767SAnurag.Maskey@Sun.COM 	}
406*11767SAnurag.Maskey@Sun.COM 
407*11767SAnurag.Maskey@Sun.COM 	err = nwam_update_object_in_backend((char *)dbname,
408*11767SAnurag.Maskey@Sun.COM 	    hp->nwh_object_type == NWAM_OBJECT_TYPE_NCP ? NULL : hp->nwh_name,
409*11767SAnurag.Maskey@Sun.COM 	    iflags, hp->nwh_data);
410*11767SAnurag.Maskey@Sun.COM 	if (err != NWAM_SUCCESS)
411*11767SAnurag.Maskey@Sun.COM 		return (err);
412*11767SAnurag.Maskey@Sun.COM 
413*11767SAnurag.Maskey@Sun.COM 	hp->nwh_committed = B_TRUE;
414*11767SAnurag.Maskey@Sun.COM 
415*11767SAnurag.Maskey@Sun.COM 	/*
416*11767SAnurag.Maskey@Sun.COM 	 * Tell nwamd to reread this object.  For NCUs, we need to convert
417*11767SAnurag.Maskey@Sun.COM 	 * the dbname to the NCP name in order to pass it to nwamd.
418*11767SAnurag.Maskey@Sun.COM 	 */
419*11767SAnurag.Maskey@Sun.COM 	if (is_ncu) {
420*11767SAnurag.Maskey@Sun.COM 		char *ncpname;
421*11767SAnurag.Maskey@Sun.COM 
422*11767SAnurag.Maskey@Sun.COM 		if (nwam_ncp_file_to_name(dbname, &ncpname) == NWAM_SUCCESS) {
423*11767SAnurag.Maskey@Sun.COM 			(void) nwam_request_action(hp->nwh_object_type,
424*11767SAnurag.Maskey@Sun.COM 			    hp->nwh_name, ncpname, action);
425*11767SAnurag.Maskey@Sun.COM 			free(ncpname);
426*11767SAnurag.Maskey@Sun.COM 		}
427*11767SAnurag.Maskey@Sun.COM 	} else {
428*11767SAnurag.Maskey@Sun.COM 		(void) nwam_request_action(hp->nwh_object_type, hp->nwh_name,
429*11767SAnurag.Maskey@Sun.COM 		    NULL, action);
430*11767SAnurag.Maskey@Sun.COM 	}
431*11767SAnurag.Maskey@Sun.COM 	return (NWAM_SUCCESS);
432*11767SAnurag.Maskey@Sun.COM }
433*11767SAnurag.Maskey@Sun.COM 
434*11767SAnurag.Maskey@Sun.COM static boolean_t
435*11767SAnurag.Maskey@Sun.COM nwam_is_active(struct nwam_handle *hp)
436*11767SAnurag.Maskey@Sun.COM {
437*11767SAnurag.Maskey@Sun.COM 	nwam_state_t state;
438*11767SAnurag.Maskey@Sun.COM 	nwam_aux_state_t aux;
439*11767SAnurag.Maskey@Sun.COM 
440*11767SAnurag.Maskey@Sun.COM 	return ((nwam_get_state(NULL, hp, &state, &aux) == NWAM_SUCCESS &&
441*11767SAnurag.Maskey@Sun.COM 	    state == NWAM_STATE_ONLINE));
442*11767SAnurag.Maskey@Sun.COM }
443*11767SAnurag.Maskey@Sun.COM 
444*11767SAnurag.Maskey@Sun.COM nwam_error_t
445*11767SAnurag.Maskey@Sun.COM nwam_destroy(const char *dbname, struct nwam_handle *hp, uint64_t flags)
446*11767SAnurag.Maskey@Sun.COM {
447*11767SAnurag.Maskey@Sun.COM 	nwam_error_t err;
448*11767SAnurag.Maskey@Sun.COM 	char *name;
449*11767SAnurag.Maskey@Sun.COM 	boolean_t is_ncp, is_ncu;
450*11767SAnurag.Maskey@Sun.COM 
451*11767SAnurag.Maskey@Sun.COM 	assert(hp != NULL);
452*11767SAnurag.Maskey@Sun.COM 
453*11767SAnurag.Maskey@Sun.COM 	/* NWAM_FLAG_ENTITY_KNOWN_WLAN is only used for Known WLANs */
454*11767SAnurag.Maskey@Sun.COM 	if ((err = nwam_valid_flags(flags,
455*11767SAnurag.Maskey@Sun.COM 	    NWAM_FLAG_BLOCKING | NWAM_FLAG_DO_NOT_FREE |
456*11767SAnurag.Maskey@Sun.COM 	    (hp->nwh_object_type == NWAM_OBJECT_TYPE_KNOWN_WLAN ?
457*11767SAnurag.Maskey@Sun.COM 	    NWAM_FLAG_ENTITY_KNOWN_WLAN : 0))) != NWAM_SUCCESS)
458*11767SAnurag.Maskey@Sun.COM 		return (err);
459*11767SAnurag.Maskey@Sun.COM 
460*11767SAnurag.Maskey@Sun.COM 	is_ncp = hp->nwh_object_type == NWAM_OBJECT_TYPE_NCP;
461*11767SAnurag.Maskey@Sun.COM 	is_ncu = hp->nwh_object_type == NWAM_OBJECT_TYPE_NCU;
462*11767SAnurag.Maskey@Sun.COM 	name = hp->nwh_name;
463*11767SAnurag.Maskey@Sun.COM 
464*11767SAnurag.Maskey@Sun.COM 	/* Check if object is active */
465*11767SAnurag.Maskey@Sun.COM 	if (!is_ncp && !is_ncu && nwam_is_active(hp))
466*11767SAnurag.Maskey@Sun.COM 		return (NWAM_ENTITY_IN_USE);
467*11767SAnurag.Maskey@Sun.COM 
468*11767SAnurag.Maskey@Sun.COM 	/* For NCPs, just remove the dbname file, otherwise remove the object */
469*11767SAnurag.Maskey@Sun.COM 	err = nwam_remove_object_from_backend((char *)dbname,
470*11767SAnurag.Maskey@Sun.COM 	    is_ncp ? NULL : name, flags);
471*11767SAnurag.Maskey@Sun.COM 
472*11767SAnurag.Maskey@Sun.COM 	/*
473*11767SAnurag.Maskey@Sun.COM 	 * Tell nwamd to remove this object.  For NCUs, we need to convert the
474*11767SAnurag.Maskey@Sun.COM 	 * dbname filename to the NCP name to pass it to nwamd.
475*11767SAnurag.Maskey@Sun.COM 	 */
476*11767SAnurag.Maskey@Sun.COM 	if (is_ncu) {
477*11767SAnurag.Maskey@Sun.COM 		char *ncpname;
478*11767SAnurag.Maskey@Sun.COM 
479*11767SAnurag.Maskey@Sun.COM 		if (nwam_ncp_file_to_name(dbname, &ncpname) == NWAM_SUCCESS) {
480*11767SAnurag.Maskey@Sun.COM 			(void) nwam_request_action(hp->nwh_object_type, name,
481*11767SAnurag.Maskey@Sun.COM 			    ncpname, NWAM_ACTION_DESTROY);
482*11767SAnurag.Maskey@Sun.COM 			free(ncpname);
483*11767SAnurag.Maskey@Sun.COM 		}
484*11767SAnurag.Maskey@Sun.COM 	} else {
485*11767SAnurag.Maskey@Sun.COM 		(void) nwam_request_action(hp->nwh_object_type, name, NULL,
486*11767SAnurag.Maskey@Sun.COM 		    NWAM_ACTION_DESTROY);
487*11767SAnurag.Maskey@Sun.COM 	}
488*11767SAnurag.Maskey@Sun.COM 
489*11767SAnurag.Maskey@Sun.COM 	if ((err == NWAM_SUCCESS) && !(flags & NWAM_FLAG_DO_NOT_FREE))
490*11767SAnurag.Maskey@Sun.COM 		nwam_free(hp);
491*11767SAnurag.Maskey@Sun.COM 
492*11767SAnurag.Maskey@Sun.COM 	return (err);
493*11767SAnurag.Maskey@Sun.COM }
494*11767SAnurag.Maskey@Sun.COM 
495*11767SAnurag.Maskey@Sun.COM /*
496*11767SAnurag.Maskey@Sun.COM  * Enable/disable functions assume prior checking of activation mode
497*11767SAnurag.Maskey@Sun.COM  * to ensure an enable/disable action is valid for the object. "parent" in these
498*11767SAnurag.Maskey@Sun.COM  * functions specifies the NCP for NCUs.
499*11767SAnurag.Maskey@Sun.COM  */
500*11767SAnurag.Maskey@Sun.COM nwam_error_t
501*11767SAnurag.Maskey@Sun.COM nwam_enable(const char *parent, struct nwam_handle *hp)
502*11767SAnurag.Maskey@Sun.COM {
503*11767SAnurag.Maskey@Sun.COM 	return (nwam_request_action(hp->nwh_object_type, hp->nwh_name,
504*11767SAnurag.Maskey@Sun.COM 	    parent, NWAM_ACTION_ENABLE));
505*11767SAnurag.Maskey@Sun.COM }
506*11767SAnurag.Maskey@Sun.COM 
507*11767SAnurag.Maskey@Sun.COM nwam_error_t
508*11767SAnurag.Maskey@Sun.COM nwam_disable(const char *parent, struct nwam_handle *hp)
509*11767SAnurag.Maskey@Sun.COM {
510*11767SAnurag.Maskey@Sun.COM 	return (nwam_request_action(hp->nwh_object_type, hp->nwh_name,
511*11767SAnurag.Maskey@Sun.COM 	    parent, NWAM_ACTION_DISABLE));
512*11767SAnurag.Maskey@Sun.COM }
513*11767SAnurag.Maskey@Sun.COM 
514*11767SAnurag.Maskey@Sun.COM nwam_error_t
515*11767SAnurag.Maskey@Sun.COM nwam_get_state(const char *parent, struct nwam_handle *hp, nwam_state_t *statep,
516*11767SAnurag.Maskey@Sun.COM     nwam_aux_state_t *auxp)
517*11767SAnurag.Maskey@Sun.COM {
518*11767SAnurag.Maskey@Sun.COM 	return (nwam_request_state(hp->nwh_object_type, hp->nwh_name, parent,
519*11767SAnurag.Maskey@Sun.COM 	    statep, auxp));
520*11767SAnurag.Maskey@Sun.COM }
521*11767SAnurag.Maskey@Sun.COM 
522*11767SAnurag.Maskey@Sun.COM struct nwam_prop_table_entry *
523*11767SAnurag.Maskey@Sun.COM nwam_get_prop_table_entry(struct nwam_prop_table table, const char *propname)
524*11767SAnurag.Maskey@Sun.COM {
525*11767SAnurag.Maskey@Sun.COM 	struct nwam_prop_table_entry *cur = table.entries;
526*11767SAnurag.Maskey@Sun.COM 	struct nwam_prop_table_entry *end = cur + table.num_entries;
527*11767SAnurag.Maskey@Sun.COM 
528*11767SAnurag.Maskey@Sun.COM 	assert(propname != NULL);
529*11767SAnurag.Maskey@Sun.COM 
530*11767SAnurag.Maskey@Sun.COM 	for (; cur < end; cur++) {
531*11767SAnurag.Maskey@Sun.COM 		if (strcmp(propname, cur->prop_name) == 0)
532*11767SAnurag.Maskey@Sun.COM 			return (cur);
533*11767SAnurag.Maskey@Sun.COM 	}
534*11767SAnurag.Maskey@Sun.COM 	return (NULL);
535*11767SAnurag.Maskey@Sun.COM }
536*11767SAnurag.Maskey@Sun.COM 
537*11767SAnurag.Maskey@Sun.COM nwam_error_t
538*11767SAnurag.Maskey@Sun.COM nwam_get_prop_description(struct nwam_prop_table table, const char *propname,
539*11767SAnurag.Maskey@Sun.COM     const char **descriptionp)
540*11767SAnurag.Maskey@Sun.COM {
541*11767SAnurag.Maskey@Sun.COM 	struct nwam_prop_table_entry *pte;
542*11767SAnurag.Maskey@Sun.COM 
543*11767SAnurag.Maskey@Sun.COM 	assert(propname != NULL && descriptionp != NULL);
544*11767SAnurag.Maskey@Sun.COM 
545*11767SAnurag.Maskey@Sun.COM 	if ((pte = nwam_get_prop_table_entry(table, propname)) == NULL) {
546*11767SAnurag.Maskey@Sun.COM 		*descriptionp = NULL;
547*11767SAnurag.Maskey@Sun.COM 		return (NWAM_INVALID_ARG);
548*11767SAnurag.Maskey@Sun.COM 	}
549*11767SAnurag.Maskey@Sun.COM 
550*11767SAnurag.Maskey@Sun.COM 	*descriptionp = dgettext(TEXT_DOMAIN, pte->prop_description);
551*11767SAnurag.Maskey@Sun.COM 	return (NWAM_SUCCESS);
552*11767SAnurag.Maskey@Sun.COM }
553*11767SAnurag.Maskey@Sun.COM 
554*11767SAnurag.Maskey@Sun.COM nwam_error_t
555*11767SAnurag.Maskey@Sun.COM nwam_get_prop_type(struct nwam_prop_table table, const char *propname,
556*11767SAnurag.Maskey@Sun.COM     nwam_value_type_t *typep)
557*11767SAnurag.Maskey@Sun.COM {
558*11767SAnurag.Maskey@Sun.COM 	struct nwam_prop_table_entry *pte;
559*11767SAnurag.Maskey@Sun.COM 
560*11767SAnurag.Maskey@Sun.COM 	assert(propname != NULL && typep != NULL);
561*11767SAnurag.Maskey@Sun.COM 
562*11767SAnurag.Maskey@Sun.COM 	if ((pte = nwam_get_prop_table_entry(table, propname)) == NULL)
563*11767SAnurag.Maskey@Sun.COM 		return (NWAM_INVALID_ARG);
564*11767SAnurag.Maskey@Sun.COM 
565*11767SAnurag.Maskey@Sun.COM 	*typep = pte->prop_type;
566*11767SAnurag.Maskey@Sun.COM 
567*11767SAnurag.Maskey@Sun.COM 	return (NWAM_SUCCESS);
568*11767SAnurag.Maskey@Sun.COM }
569*11767SAnurag.Maskey@Sun.COM 
570*11767SAnurag.Maskey@Sun.COM nwam_error_t
571*11767SAnurag.Maskey@Sun.COM nwam_prop_multivalued(struct nwam_prop_table table, const char *propname,
572*11767SAnurag.Maskey@Sun.COM     boolean_t *multip)
573*11767SAnurag.Maskey@Sun.COM {
574*11767SAnurag.Maskey@Sun.COM 	struct nwam_prop_table_entry *pte;
575*11767SAnurag.Maskey@Sun.COM 
576*11767SAnurag.Maskey@Sun.COM 	assert(propname != NULL && multip != NULL);
577*11767SAnurag.Maskey@Sun.COM 
578*11767SAnurag.Maskey@Sun.COM 	if ((pte = nwam_get_prop_table_entry(table, propname)) == NULL)
579*11767SAnurag.Maskey@Sun.COM 		return (NWAM_INVALID_ARG);
580*11767SAnurag.Maskey@Sun.COM 
581*11767SAnurag.Maskey@Sun.COM 	if (pte->prop_max_numvalues > 1)
582*11767SAnurag.Maskey@Sun.COM 		*multip = B_TRUE;
583*11767SAnurag.Maskey@Sun.COM 	else
584*11767SAnurag.Maskey@Sun.COM 		*multip = B_FALSE;
585*11767SAnurag.Maskey@Sun.COM 
586*11767SAnurag.Maskey@Sun.COM 	return (NWAM_SUCCESS);
587*11767SAnurag.Maskey@Sun.COM }
588*11767SAnurag.Maskey@Sun.COM 
589*11767SAnurag.Maskey@Sun.COM nwam_error_t
590*11767SAnurag.Maskey@Sun.COM nwam_prop_read_only(struct nwam_prop_table table, const char *propname,
591*11767SAnurag.Maskey@Sun.COM     boolean_t *readp)
592*11767SAnurag.Maskey@Sun.COM {
593*11767SAnurag.Maskey@Sun.COM 	struct nwam_prop_table_entry *pte;
594*11767SAnurag.Maskey@Sun.COM 
595*11767SAnurag.Maskey@Sun.COM 	assert(propname != NULL && readp != NULL);
596*11767SAnurag.Maskey@Sun.COM 
597*11767SAnurag.Maskey@Sun.COM 	if ((pte = nwam_get_prop_table_entry(table, propname)) == NULL)
598*11767SAnurag.Maskey@Sun.COM 		return (NWAM_INVALID_ARG);
599*11767SAnurag.Maskey@Sun.COM 
600*11767SAnurag.Maskey@Sun.COM 	*readp = (pte->prop_is_readonly && !nwam_uid_is_netadm());
601*11767SAnurag.Maskey@Sun.COM 
602*11767SAnurag.Maskey@Sun.COM 	return (NWAM_SUCCESS);
603*11767SAnurag.Maskey@Sun.COM }
604*11767SAnurag.Maskey@Sun.COM 
605*11767SAnurag.Maskey@Sun.COM /*
606*11767SAnurag.Maskey@Sun.COM  * Structure used to pass in prop table and errprop string pointer to internal
607*11767SAnurag.Maskey@Sun.COM  * validate function.
608*11767SAnurag.Maskey@Sun.COM  */
609*11767SAnurag.Maskey@Sun.COM struct validate_internal_arg {
610*11767SAnurag.Maskey@Sun.COM 	struct nwam_prop_table table;
611*11767SAnurag.Maskey@Sun.COM 	const char **errpropp;
612*11767SAnurag.Maskey@Sun.COM };
613*11767SAnurag.Maskey@Sun.COM 
614*11767SAnurag.Maskey@Sun.COM /*
615*11767SAnurag.Maskey@Sun.COM  * Callback used by nwam_walk_props() in nwam_validate(), and
616*11767SAnurag.Maskey@Sun.COM  * by nwam_validate_prop() to determine that the number, type and
617*11767SAnurag.Maskey@Sun.COM  * range of values are correct, and that validation function (if present)
618*11767SAnurag.Maskey@Sun.COM  * succeeds.
619*11767SAnurag.Maskey@Sun.COM  */
620*11767SAnurag.Maskey@Sun.COM static int
621*11767SAnurag.Maskey@Sun.COM nwam_validate_prop_internal(const char *propname, nwam_value_t value,
622*11767SAnurag.Maskey@Sun.COM     void *arg)
623*11767SAnurag.Maskey@Sun.COM {
624*11767SAnurag.Maskey@Sun.COM 	struct validate_internal_arg *via = arg;
625*11767SAnurag.Maskey@Sun.COM 	struct nwam_prop_table table = via->table;
626*11767SAnurag.Maskey@Sun.COM 	const char **errpropp = via->errpropp;
627*11767SAnurag.Maskey@Sun.COM 	struct nwam_prop_table_entry *pte;
628*11767SAnurag.Maskey@Sun.COM 	nwam_error_t err;
629*11767SAnurag.Maskey@Sun.COM 	nwam_value_type_t type;
630*11767SAnurag.Maskey@Sun.COM 	uint_t numvalues;
631*11767SAnurag.Maskey@Sun.COM 	int i;
632*11767SAnurag.Maskey@Sun.COM 
633*11767SAnurag.Maskey@Sun.COM 	if ((err = nwam_value_get_numvalues(value, &numvalues))
634*11767SAnurag.Maskey@Sun.COM 	    != NWAM_SUCCESS ||
635*11767SAnurag.Maskey@Sun.COM 	    (err = nwam_value_get_type(value, &type)) != NWAM_SUCCESS) {
636*11767SAnurag.Maskey@Sun.COM 		if (errpropp != NULL)
637*11767SAnurag.Maskey@Sun.COM 			*errpropp = propname;
638*11767SAnurag.Maskey@Sun.COM 		return (err);
639*11767SAnurag.Maskey@Sun.COM 	}
640*11767SAnurag.Maskey@Sun.COM 	if ((pte = nwam_get_prop_table_entry(table, propname)) == NULL)
641*11767SAnurag.Maskey@Sun.COM 		return (NWAM_INVALID_ARG);
642*11767SAnurag.Maskey@Sun.COM 
643*11767SAnurag.Maskey@Sun.COM 	/* have we get expected number of values? */
644*11767SAnurag.Maskey@Sun.COM 	if (numvalues < pte->prop_min_numvalues ||
645*11767SAnurag.Maskey@Sun.COM 	    numvalues > pte->prop_max_numvalues) {
646*11767SAnurag.Maskey@Sun.COM 		if (errpropp != NULL)
647*11767SAnurag.Maskey@Sun.COM 			*errpropp = propname;
648*11767SAnurag.Maskey@Sun.COM 		if (numvalues < 1)
649*11767SAnurag.Maskey@Sun.COM 			return (NWAM_ENTITY_NO_VALUE);
650*11767SAnurag.Maskey@Sun.COM 		else
651*11767SAnurag.Maskey@Sun.COM 			return (NWAM_ENTITY_INVALID_VALUE);
652*11767SAnurag.Maskey@Sun.COM 	}
653*11767SAnurag.Maskey@Sun.COM 	/* Ensure type matches */
654*11767SAnurag.Maskey@Sun.COM 	if (numvalues > 0) {
655*11767SAnurag.Maskey@Sun.COM 		for (i = 0; i < numvalues; i++) {
656*11767SAnurag.Maskey@Sun.COM 			if (pte->prop_type != type) {
657*11767SAnurag.Maskey@Sun.COM 				if (errpropp != NULL)
658*11767SAnurag.Maskey@Sun.COM 					*errpropp = propname;
659*11767SAnurag.Maskey@Sun.COM 				return (NWAM_ENTITY_TYPE_MISMATCH);
660*11767SAnurag.Maskey@Sun.COM 
661*11767SAnurag.Maskey@Sun.COM 			}
662*11767SAnurag.Maskey@Sun.COM 		}
663*11767SAnurag.Maskey@Sun.COM 	}
664*11767SAnurag.Maskey@Sun.COM 	/* Call property-specific validation function */
665*11767SAnurag.Maskey@Sun.COM 	if (pte->prop_validate != NULL) {
666*11767SAnurag.Maskey@Sun.COM 		err = pte->prop_validate(value);
667*11767SAnurag.Maskey@Sun.COM 		if (err != NWAM_SUCCESS && errpropp != NULL)
668*11767SAnurag.Maskey@Sun.COM 			*errpropp = propname;
669*11767SAnurag.Maskey@Sun.COM 		return (err);
670*11767SAnurag.Maskey@Sun.COM 	}
671*11767SAnurag.Maskey@Sun.COM 
672*11767SAnurag.Maskey@Sun.COM 	return (NWAM_SUCCESS);
673*11767SAnurag.Maskey@Sun.COM }
674*11767SAnurag.Maskey@Sun.COM 
675*11767SAnurag.Maskey@Sun.COM nwam_error_t
676*11767SAnurag.Maskey@Sun.COM nwam_validate_prop(struct nwam_prop_table table, struct nwam_handle *hp,
677*11767SAnurag.Maskey@Sun.COM     const char *propname, nwam_value_t value)
678*11767SAnurag.Maskey@Sun.COM {
679*11767SAnurag.Maskey@Sun.COM 	struct validate_internal_arg via;
680*11767SAnurag.Maskey@Sun.COM 
681*11767SAnurag.Maskey@Sun.COM 	assert(hp != NULL && propname != NULL);
682*11767SAnurag.Maskey@Sun.COM 
683*11767SAnurag.Maskey@Sun.COM 	via.table = table;
684*11767SAnurag.Maskey@Sun.COM 	via.errpropp = NULL;
685*11767SAnurag.Maskey@Sun.COM 
686*11767SAnurag.Maskey@Sun.COM 	return ((nwam_error_t)nwam_validate_prop_internal(propname,
687*11767SAnurag.Maskey@Sun.COM 	    value, &via));
688*11767SAnurag.Maskey@Sun.COM }
689*11767SAnurag.Maskey@Sun.COM 
690*11767SAnurag.Maskey@Sun.COM nwam_error_t
691*11767SAnurag.Maskey@Sun.COM nwam_validate(struct nwam_prop_table table, struct nwam_handle *hp,
692*11767SAnurag.Maskey@Sun.COM     const char **errpropp)
693*11767SAnurag.Maskey@Sun.COM {
694*11767SAnurag.Maskey@Sun.COM 	struct validate_internal_arg via;
695*11767SAnurag.Maskey@Sun.COM 	nwam_error_t err1, err2;
696*11767SAnurag.Maskey@Sun.COM 
697*11767SAnurag.Maskey@Sun.COM 	assert(hp != NULL);
698*11767SAnurag.Maskey@Sun.COM 
699*11767SAnurag.Maskey@Sun.COM 	via.table = table;
700*11767SAnurag.Maskey@Sun.COM 	via.errpropp = errpropp;
701*11767SAnurag.Maskey@Sun.COM 
702*11767SAnurag.Maskey@Sun.COM 	err1 = nwam_walk_props(hp, nwam_validate_prop_internal, &via,
703*11767SAnurag.Maskey@Sun.COM 	    0, (int *)&err2);
704*11767SAnurag.Maskey@Sun.COM 	if (err1 != NWAM_SUCCESS)
705*11767SAnurag.Maskey@Sun.COM 		return (err2);
706*11767SAnurag.Maskey@Sun.COM 	return (NWAM_SUCCESS);
707*11767SAnurag.Maskey@Sun.COM }
708*11767SAnurag.Maskey@Sun.COM 
709*11767SAnurag.Maskey@Sun.COM /*
710*11767SAnurag.Maskey@Sun.COM  * Given the type and class flag representations, return the list of properties
711*11767SAnurag.Maskey@Sun.COM  * that can be set for that type/class combination. Note this list is a complete
712*11767SAnurag.Maskey@Sun.COM  * property list that includes both the required and the optional properties.
713*11767SAnurag.Maskey@Sun.COM  * The type and class flags are only used for NCU objects at present.
714*11767SAnurag.Maskey@Sun.COM  *
715*11767SAnurag.Maskey@Sun.COM  * Caller needs to free prop_list.
716*11767SAnurag.Maskey@Sun.COM  */
717*11767SAnurag.Maskey@Sun.COM nwam_error_t
718*11767SAnurag.Maskey@Sun.COM nwam_get_default_proplist(struct nwam_prop_table table,
719*11767SAnurag.Maskey@Sun.COM     uint64_t type, uint64_t class, const char ***prop_list, uint_t *numvalues)
720*11767SAnurag.Maskey@Sun.COM {
721*11767SAnurag.Maskey@Sun.COM 	struct nwam_prop_table_entry *cur = table.entries;
722*11767SAnurag.Maskey@Sun.COM 	struct nwam_prop_table_entry *end = cur + table.num_entries;
723*11767SAnurag.Maskey@Sun.COM 	int i = 0;
724*11767SAnurag.Maskey@Sun.COM 	const char **list = NULL;
725*11767SAnurag.Maskey@Sun.COM 
726*11767SAnurag.Maskey@Sun.COM 	assert(prop_list != NULL && numvalues != NULL);
727*11767SAnurag.Maskey@Sun.COM 
728*11767SAnurag.Maskey@Sun.COM 	/* Construct a list of all properties for required type/class */
729*11767SAnurag.Maskey@Sun.COM 	list = calloc(table.num_entries, sizeof (char *));
730*11767SAnurag.Maskey@Sun.COM 	if (list == NULL) {
731*11767SAnurag.Maskey@Sun.COM 		*prop_list = NULL;
732*11767SAnurag.Maskey@Sun.COM 		*numvalues = 0;
733*11767SAnurag.Maskey@Sun.COM 		return (NWAM_NO_MEMORY);
734*11767SAnurag.Maskey@Sun.COM 	}
735*11767SAnurag.Maskey@Sun.COM 	for (; cur < end; cur++) {
736*11767SAnurag.Maskey@Sun.COM 		if (((type & cur->prop_type_membership) == 0) ||
737*11767SAnurag.Maskey@Sun.COM 		    ((class & cur->prop_class_membership) == 0))
738*11767SAnurag.Maskey@Sun.COM 			continue;
739*11767SAnurag.Maskey@Sun.COM 		list[i++] = cur->prop_name;
740*11767SAnurag.Maskey@Sun.COM 	}
741*11767SAnurag.Maskey@Sun.COM 	*numvalues = i;
742*11767SAnurag.Maskey@Sun.COM 	*prop_list = list;
743*11767SAnurag.Maskey@Sun.COM 	return (NWAM_SUCCESS);
744*11767SAnurag.Maskey@Sun.COM }
745