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