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