xref: /illumos-gate/usr/src/lib/libnwam/common/libnwam_values.c (revision 5422785d352a2bb398daceab3d1898a8aa64d006)
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 (c) 2010, Oracle and/or its affiliates. All rights reserved.
24  * Copyright 2012 Milan Jurik. All rights reserved.
25  */
26 
27 #include <assert.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <sys/types.h>
32 #include <libdlwlan.h>
33 #include <libnvpair.h>
34 
35 #include "libnwam_impl.h"
36 #include <libnwam_priv.h>
37 #include <libnwam.h>
38 
39 /*
40  * Internal implementation of libnwam in-memory objects and values.  Objects
41  * are nvlists.
42  */
43 
44 void
45 nwam_value_free(nwam_value_t value)
46 {
47 	uint_t i;
48 
49 	if (value == NULL)
50 		return;
51 
52 	switch (value->nwv_value_type) {
53 	case NWAM_VALUE_TYPE_BOOLEAN:
54 		free(value->nwv_values.nwv_boolean);
55 		break;
56 	case NWAM_VALUE_TYPE_INT64:
57 		free(value->nwv_values.nwv_int64);
58 		break;
59 	case NWAM_VALUE_TYPE_UINT64:
60 		free(value->nwv_values.nwv_uint64);
61 		break;
62 	case NWAM_VALUE_TYPE_STRING:
63 		for (i = 0; i < value->nwv_value_numvalues; i++)
64 			free(value->nwv_values.nwv_string[i]);
65 		free(value->nwv_values.nwv_string);
66 		break;
67 	}
68 	free(value);
69 }
70 
71 nwam_error_t
72 nwam_value_create(nwam_value_type_t value_type, void *values, uint_t numvalues,
73     nwam_value_t *valuep)
74 {
75 	nwam_value_t newvalue;
76 	boolean_t *values_boolean;
77 	int64_t *values_int64;
78 	uint64_t *values_uint64;
79 	char **values_string;
80 	int i, j;
81 	nwam_error_t err = NWAM_SUCCESS;
82 
83 	*valuep = NULL;
84 
85 	if ((newvalue = calloc(1, sizeof (struct nwam_value))) == NULL)
86 		return (NWAM_NO_MEMORY);
87 
88 	newvalue->nwv_value_type = value_type;
89 	newvalue->nwv_value_numvalues = numvalues;
90 
91 	switch (value_type) {
92 	case NWAM_VALUE_TYPE_BOOLEAN:
93 		values_boolean = values;
94 		if ((newvalue->nwv_values.nwv_boolean =
95 		    calloc(numvalues, sizeof (boolean_t))) == NULL) {
96 			free(newvalue);
97 			return (NWAM_NO_MEMORY);
98 		}
99 		for (i = 0; i < numvalues; i++)
100 			newvalue->nwv_values.nwv_boolean[i] = values_boolean[i];
101 		break;
102 	case NWAM_VALUE_TYPE_INT64:
103 		values_int64 = values;
104 		if ((newvalue->nwv_values.nwv_int64 =
105 		    calloc(numvalues, sizeof (int64_t))) == NULL) {
106 			free(newvalue);
107 			return (NWAM_NO_MEMORY);
108 		}
109 		for (i = 0; i < numvalues; i++)
110 			newvalue->nwv_values.nwv_int64[i] = values_int64[i];
111 		break;
112 	case NWAM_VALUE_TYPE_UINT64:
113 		values_uint64 = values;
114 		if ((newvalue->nwv_values.nwv_uint64 =
115 		    calloc(numvalues, sizeof (uint64_t))) == NULL) {
116 			free(newvalue);
117 			return (NWAM_NO_MEMORY);
118 		}
119 		for (i = 0; i < numvalues; i++)
120 			newvalue->nwv_values.nwv_uint64[i] = values_uint64[i];
121 		break;
122 	case NWAM_VALUE_TYPE_STRING:
123 		values_string = values;
124 		if ((newvalue->nwv_values.nwv_string =
125 		    calloc(numvalues, sizeof (char *))) == NULL) {
126 			free(newvalue);
127 			return (NWAM_NO_MEMORY);
128 		}
129 		for (i = 0; i < numvalues; i++) {
130 			if (strnlen(values_string[i], NWAM_MAX_VALUE_LEN) ==
131 			    NWAM_MAX_VALUE_LEN) {
132 				err = NWAM_ENTITY_INVALID_VALUE;
133 			} else if ((newvalue->nwv_values.nwv_string[i] =
134 			    strdup(values_string[i])) == NULL) {
135 				err = NWAM_NO_MEMORY;
136 			}
137 			if (err != NWAM_SUCCESS) {
138 				for (j = 0; j < i; j++)
139 					free(
140 					    newvalue->nwv_values.nwv_string[i]);
141 				free(newvalue->nwv_values.nwv_string);
142 				free(newvalue);
143 				return (err);
144 			}
145 		}
146 		break;
147 	default:
148 		break;
149 	}
150 
151 	*valuep = newvalue;
152 	return (NWAM_SUCCESS);
153 }
154 
155 nwam_error_t
156 nwam_value_copy(nwam_value_t old, nwam_value_t *newp)
157 {
158 	void *values;
159 
160 	assert(old != NULL && newp != NULL);
161 
162 	switch (old->nwv_value_type) {
163 	case NWAM_VALUE_TYPE_BOOLEAN:
164 		values = old->nwv_values.nwv_boolean;
165 		break;
166 	case NWAM_VALUE_TYPE_INT64:
167 		values = old->nwv_values.nwv_int64;
168 		break;
169 	case NWAM_VALUE_TYPE_UINT64:
170 		values = old->nwv_values.nwv_uint64;
171 		break;
172 	case NWAM_VALUE_TYPE_STRING:
173 		values = old->nwv_values.nwv_string;
174 		break;
175 	default:
176 		return (NWAM_INVALID_ARG);
177 	}
178 	return (nwam_value_create(old->nwv_value_type, values,
179 	    old->nwv_value_numvalues, newp));
180 }
181 nwam_error_t
182 nwam_value_create_boolean_array(boolean_t *values, uint_t numvalues,
183     nwam_value_t *valuep)
184 {
185 	return (nwam_value_create(NWAM_VALUE_TYPE_BOOLEAN, values, numvalues,
186 	    valuep));
187 }
188 
189 nwam_error_t
190 nwam_value_create_boolean(boolean_t value, nwam_value_t *valuep)
191 {
192 	return (nwam_value_create_boolean_array(&value, 1, valuep));
193 }
194 
195 nwam_error_t
196 nwam_value_create_int64_array(int64_t *values, uint_t numvalues,
197     nwam_value_t *valuep)
198 {
199 	return (nwam_value_create(NWAM_VALUE_TYPE_INT64, values, numvalues,
200 	    valuep));
201 }
202 
203 nwam_error_t
204 nwam_value_create_int64(int64_t value, nwam_value_t *valuep)
205 {
206 	return (nwam_value_create_int64_array(&value, 1, valuep));
207 }
208 
209 nwam_error_t
210 nwam_value_create_uint64_array(uint64_t *values, uint_t numvalues,
211     nwam_value_t *valuep)
212 {
213 	return (nwam_value_create(NWAM_VALUE_TYPE_UINT64, values, numvalues,
214 	    valuep));
215 }
216 
217 nwam_error_t
218 nwam_value_create_uint64(uint64_t value, nwam_value_t *valuep)
219 {
220 	return (nwam_value_create_uint64_array(&value, 1, valuep));
221 }
222 
223 nwam_error_t
224 nwam_value_create_string_array(char **values, uint_t numvalues,
225     nwam_value_t *valuep)
226 {
227 	return (nwam_value_create(NWAM_VALUE_TYPE_STRING, values, numvalues,
228 	    valuep));
229 }
230 
231 nwam_error_t
232 nwam_value_create_string(char *value, nwam_value_t *valuep)
233 {
234 	return (nwam_value_create_string_array(&value, 1, valuep));
235 }
236 
237 nwam_error_t
238 nwam_value_get_boolean_array(nwam_value_t value, boolean_t **valuesp,
239     uint_t *numvaluesp)
240 {
241 	assert(value != NULL && numvaluesp != NULL && valuesp != NULL);
242 
243 	*numvaluesp = value->nwv_value_numvalues;
244 	*valuesp = value->nwv_values.nwv_boolean;
245 	return (NWAM_SUCCESS);
246 }
247 
248 nwam_error_t
249 nwam_value_get_boolean(nwam_value_t value, boolean_t *valuep)
250 {
251 	uint_t numvalues;
252 	boolean_t *myvaluesp;
253 	nwam_error_t err;
254 
255 	err = nwam_value_get_boolean_array(value, &myvaluesp, &numvalues);
256 	if (err != NWAM_SUCCESS)
257 		return (err);
258 	if (numvalues != 1)
259 		return (NWAM_ENTITY_MULTIPLE_VALUES);
260 
261 	*valuep = myvaluesp[0];
262 	return (NWAM_SUCCESS);
263 }
264 
265 nwam_error_t
266 nwam_value_get_int64_array(nwam_value_t value, int64_t **valuesp,
267     uint_t *numvaluesp)
268 {
269 	assert(value != NULL && numvaluesp != NULL && valuesp != NULL);
270 
271 	*numvaluesp = value->nwv_value_numvalues;
272 	*valuesp = value->nwv_values.nwv_int64;
273 	return (NWAM_SUCCESS);
274 }
275 
276 nwam_error_t
277 nwam_value_get_int64(nwam_value_t value, int64_t *valuep)
278 {
279 	uint_t numvalues;
280 	int64_t *myvaluesp;
281 	nwam_error_t err;
282 
283 	err = nwam_value_get_int64_array(value, &myvaluesp, &numvalues);
284 	if (err != NWAM_SUCCESS)
285 		return (err);
286 	if (numvalues != 1)
287 		return (NWAM_ENTITY_MULTIPLE_VALUES);
288 
289 	*valuep = myvaluesp[0];
290 	return (NWAM_SUCCESS);
291 }
292 
293 nwam_error_t
294 nwam_value_get_uint64_array(nwam_value_t value, uint64_t **valuesp,
295     uint_t *numvaluesp)
296 {
297 	assert(value != NULL && numvaluesp != NULL && valuesp != NULL);
298 
299 	*numvaluesp = value->nwv_value_numvalues;
300 	*valuesp = value->nwv_values.nwv_uint64;
301 	return (NWAM_SUCCESS);
302 }
303 
304 nwam_error_t
305 nwam_value_get_uint64(nwam_value_t value, uint64_t *valuep)
306 {
307 	uint_t numvalues;
308 	uint64_t *myvaluesp;
309 	nwam_error_t err;
310 
311 	err = nwam_value_get_uint64_array(value, &myvaluesp, &numvalues);
312 	if (err != NWAM_SUCCESS)
313 		return (err);
314 	if (numvalues != 1)
315 		return (NWAM_ENTITY_MULTIPLE_VALUES);
316 
317 	*valuep = myvaluesp[0];
318 	return (NWAM_SUCCESS);
319 }
320 
321 nwam_error_t
322 nwam_value_get_string_array(nwam_value_t value, char ***valuesp,
323     uint_t *numvaluesp)
324 {
325 	assert(value != NULL && numvaluesp != NULL && valuesp != NULL);
326 
327 	*numvaluesp = value->nwv_value_numvalues;
328 	*valuesp = value->nwv_values.nwv_string;
329 	return (NWAM_SUCCESS);
330 }
331 
332 nwam_error_t
333 nwam_value_get_string(nwam_value_t value, char **valuep)
334 {
335 	uint_t numvalues;
336 	char **myvaluesp;
337 	nwam_error_t err;
338 
339 	err = nwam_value_get_string_array(value, &myvaluesp, &numvalues);
340 	if (err != NWAM_SUCCESS)
341 		return (err);
342 	if (numvalues != 1)
343 		return (NWAM_ENTITY_MULTIPLE_VALUES);
344 
345 	*valuep = myvaluesp[0];
346 	return (NWAM_SUCCESS);
347 }
348 
349 nwam_error_t
350 nwam_value_get_type(nwam_value_t value, nwam_value_type_t *typep)
351 {
352 	*typep = value->nwv_value_type;
353 	return (NWAM_SUCCESS);
354 }
355 
356 nwam_error_t
357 nwam_value_get_numvalues(nwam_value_t value, uint_t *numvaluesp)
358 {
359 	*numvaluesp = value->nwv_value_numvalues;
360 	return (NWAM_SUCCESS);
361 }
362 
363 /*
364  * Generic object data functions. We hide nvlist implementation
365  * from NCP, ENM and location implementations.
366  */
367 nwam_error_t
368 nwam_alloc_object_list(void *list)
369 {
370 	int nverr;
371 
372 	assert(list != NULL);
373 
374 	if ((nverr = nvlist_alloc((nvlist_t **)list, NV_UNIQUE_NAME, 0)) != 0)
375 		return (nwam_errno_to_nwam_error(nverr));
376 
377 	return (NWAM_SUCCESS);
378 }
379 
380 void
381 nwam_free_object_list(void *list)
382 {
383 	if (list != NULL)
384 		nvlist_free(list);
385 }
386 
387 nwam_error_t
388 nwam_dup_object_list(void *oldlist, void *newlist)
389 {
390 	int nverr;
391 
392 	assert(oldlist != NULL && newlist != NULL);
393 
394 	if ((nverr = nvlist_dup(oldlist, newlist, 0)) != 0)
395 		return (nwam_errno_to_nwam_error(nverr));
396 
397 	return (NWAM_SUCCESS);
398 }
399 
400 /* Add child object list to parent object list using property name childname */
401 nwam_error_t
402 nwam_object_list_add_object_list(void *parentlist, char *childname,
403     void *childlist)
404 {
405 	return (nwam_errno_to_nwam_error(nvlist_add_nvlist(parentlist,
406 	    childname, childlist)));
407 }
408 
409 /* Remove object list from parent object list */
410 nwam_error_t
411 nwam_object_list_remove_object_list(void *parentlist, char *childname)
412 {
413 	return (nwam_errno_to_nwam_error(nvlist_remove_all(parentlist,
414 	    childname)));
415 }
416 
417 /*
418  * Get next object list (nvlist) after lastname.  Used to walk NCUs, ENMs and
419  * locations, each of which is internally represented as an nvlist.
420  */
421 nwam_error_t
422 nwam_next_object_list(void *parentlist, char *lastname, char **childnamep,
423     void *childlistp)
424 {
425 	nvpair_t *last = NULL, *next;
426 	int nverr;
427 
428 	if (lastname != NULL) {
429 		if ((nverr = nvlist_lookup_nvpair(parentlist, lastname, &last))
430 		    != 0)
431 			return (nwam_errno_to_nwam_error(nverr));
432 	}
433 	if ((next = nvlist_next_nvpair(parentlist, last)) == NULL)
434 		return (NWAM_LIST_END);
435 
436 	*childnamep = nvpair_name(next);
437 
438 	if (nvpair_type(next) != DATA_TYPE_NVLIST)
439 		return (NWAM_ERROR_INTERNAL);
440 
441 	if ((nverr = nvpair_value_nvlist(next, childlistp)) != NWAM_SUCCESS)
442 		return (nwam_errno_to_nwam_error(nverr));
443 
444 	return (NWAM_SUCCESS);
445 }
446 
447 /*
448  * Pack nvlist into contiguous memory. If packed_listp is NULL, we just
449  * return the size of the memory needed to do so.
450  */
451 nwam_error_t
452 nwam_pack_object_list(void *list, char **packed_listp, size_t *packed_sizep)
453 {
454 	int nverr;
455 
456 	assert(list != NULL && packed_sizep != NULL);
457 
458 	if (packed_listp == NULL) {
459 		nverr = nvlist_size(list, packed_sizep, NV_ENCODE_XDR);
460 	} else {
461 		nverr = nvlist_pack(list, packed_listp, packed_sizep,
462 		    NV_ENCODE_XDR, 0);
463 	}
464 
465 	if (nverr != 0)
466 		return (nwam_errno_to_nwam_error(nverr));
467 
468 	return (NWAM_SUCCESS);
469 }
470 
471 nwam_error_t
472 nwam_unpack_object_list(char *packed_list, size_t packed_size,
473     void *list)
474 {
475 	int nverr;
476 
477 	assert(packed_list != NULL && list != NULL);
478 
479 	*((nvlist_t **)list) = NULL;
480 
481 	nverr = nvlist_unpack(packed_list, packed_size, (nvlist_t **)list, 0);
482 
483 	if (nverr != 0)
484 		return (nwam_errno_to_nwam_error(nverr));
485 
486 	return (NWAM_SUCCESS);
487 }
488 
489 /*
490  * Functions to walk, set and get properties in nvlist, translating
491  * between nwam_value_t and nvlist/nvpair representations.
492  */
493 nwam_error_t
494 nwam_next_object_prop(void *list, char *lastname, char **namep,
495     nwam_value_t *valuep)
496 {
497 	nvpair_t *last = NULL, *next;
498 	int nverr;
499 
500 	if (lastname != NULL) {
501 		if ((nverr = nvlist_lookup_nvpair(list, lastname, &last)) != 0)
502 			return (nwam_errno_to_nwam_error(nverr));
503 	}
504 	if ((next = nvlist_next_nvpair(list, last)) == NULL)
505 		return (NWAM_LIST_END);
506 
507 	*namep = nvpair_name(next);
508 
509 	return (nwam_get_prop_value(list, (const char *)*namep, valuep));
510 }
511 
512 nwam_error_t
513 nwam_get_prop_value(void *list, const char *name, nwam_value_t *valuep)
514 {
515 	nvpair_t *prop;
516 	nwam_error_t err;
517 	int nverr;
518 	boolean_t *valbool;
519 	int64_t *valint64;
520 	uint64_t *valuint64;
521 	char **valstr;
522 	uint_t numvalues;
523 
524 	assert(valuep != NULL);
525 
526 	*valuep = NULL;
527 
528 	if ((nverr = nvlist_lookup_nvpair(list, name, &prop)) != 0) {
529 		/* convert EINVAL to NOT_FOUND */
530 		if (nverr == EINVAL)
531 			return (NWAM_ENTITY_NOT_FOUND);
532 		return (nwam_errno_to_nwam_error(nverr));
533 	}
534 
535 	switch (nvpair_type(prop)) {
536 	case DATA_TYPE_BOOLEAN_ARRAY:
537 		if ((nverr = nvpair_value_boolean_array(prop,
538 		    &valbool, &numvalues)) != 0)
539 			return (nwam_errno_to_nwam_error(nverr));
540 		if ((err = nwam_value_create_boolean_array(valbool, numvalues,
541 		    valuep)) != NWAM_SUCCESS)
542 			return (err);
543 		break;
544 	case DATA_TYPE_INT64_ARRAY:
545 		if ((nverr = nvpair_value_int64_array(prop,
546 		    &valint64, &numvalues)) != 0)
547 			return (nwam_errno_to_nwam_error(nverr));
548 		if ((err = nwam_value_create_int64_array(valint64, numvalues,
549 		    valuep)) != NWAM_SUCCESS)
550 			return (err);
551 		break;
552 	case DATA_TYPE_UINT64_ARRAY:
553 		if ((nverr = nvpair_value_uint64_array(prop,
554 		    &valuint64, &numvalues)) != 0)
555 			return (nwam_errno_to_nwam_error(nverr));
556 		if ((err = nwam_value_create_uint64_array(valuint64, numvalues,
557 		    valuep)) != NWAM_SUCCESS)
558 			return (err);
559 		break;
560 	case DATA_TYPE_STRING_ARRAY:
561 		if ((nverr = nvpair_value_string_array(prop,
562 		    &valstr, &numvalues)) != 0)
563 			return (nwam_errno_to_nwam_error(nverr));
564 		if ((err = nwam_value_create_string_array(valstr, numvalues,
565 		    valuep)) != NWAM_SUCCESS)
566 			return (err);
567 		break;
568 	default:
569 		/* Should not happen */
570 		return (NWAM_ERROR_INTERNAL);
571 	}
572 	return (NWAM_SUCCESS);
573 }
574 
575 nwam_error_t
576 nwam_delete_prop(void *list, const char *name)
577 {
578 	int nverr;
579 
580 	if ((nverr = nvlist_remove_all(list, name)) != 0)
581 		return (nwam_errno_to_nwam_error(nverr));
582 	return (NWAM_SUCCESS);
583 }
584 
585 nwam_error_t
586 nwam_set_prop_value(void *list, const char *propname, nwam_value_t value)
587 {
588 	int nverr;
589 	nwam_error_t err;
590 	nwam_value_type_t type;
591 	uint_t numvalues;
592 	boolean_t *valbool;
593 	int64_t *valint64;
594 	uint64_t *valuint64;
595 	char **valstr;
596 
597 	assert(list != NULL && value != NULL);
598 
599 	if ((err = nwam_value_get_type(value, &type)) != NWAM_SUCCESS)
600 		return (err);
601 
602 	switch (type) {
603 	case NWAM_VALUE_TYPE_BOOLEAN:
604 		if ((err = nwam_value_get_boolean_array(value, &valbool,
605 		    &numvalues)) != NWAM_SUCCESS)
606 			return (err);
607 		if ((nverr = nvlist_add_boolean_array(list, propname,
608 		    valbool, numvalues)) != 0)
609 			return (nwam_errno_to_nwam_error(nverr));
610 		break;
611 	case NWAM_VALUE_TYPE_INT64:
612 		if ((err = nwam_value_get_int64_array(value, &valint64,
613 		    &numvalues)) != NWAM_SUCCESS)
614 			return (err);
615 		if ((nverr = nvlist_add_int64_array(list, propname,
616 		    valint64, numvalues)) != 0)
617 			return (nwam_errno_to_nwam_error(nverr));
618 		break;
619 	case NWAM_VALUE_TYPE_UINT64:
620 		if ((err = nwam_value_get_uint64_array(value, &valuint64,
621 		    &numvalues)) != NWAM_SUCCESS)
622 			return (err);
623 		if ((nverr = nvlist_add_uint64_array(list, propname,
624 		    valuint64, numvalues)) != 0)
625 			return (nwam_errno_to_nwam_error(nverr));
626 		break;
627 	case NWAM_VALUE_TYPE_STRING:
628 		if ((err = nwam_value_get_string_array(value, &valstr,
629 		    &numvalues)) != NWAM_SUCCESS)
630 			return (err);
631 		if ((nverr = nvlist_add_string_array(list, propname,
632 		    valstr, numvalues)) != 0)
633 			return (nwam_errno_to_nwam_error(nverr));
634 		break;
635 	default:
636 		return (NWAM_INVALID_ARG);
637 	}
638 
639 	return (NWAM_SUCCESS);
640 }
641 
642 /* Map uint64 values to their string counterparts */
643 
644 struct nwam_value_entry {
645 	const char	*value_string;
646 	uint64_t		value;
647 };
648 
649 struct nwam_value_entry prop_activation_mode_value_entries[] =
650 {
651 	{ NWAM_ACTIVATION_MODE_MANUAL_STRING, NWAM_ACTIVATION_MODE_MANUAL },
652 	{ NWAM_ACTIVATION_MODE_SYSTEM_STRING, NWAM_ACTIVATION_MODE_SYSTEM },
653 	{ NWAM_ACTIVATION_MODE_CONDITIONAL_ANY_STRING,
654 	NWAM_ACTIVATION_MODE_CONDITIONAL_ANY },
655 	{ NWAM_ACTIVATION_MODE_CONDITIONAL_ALL_STRING,
656 	NWAM_ACTIVATION_MODE_CONDITIONAL_ALL },
657 	{ NWAM_ACTIVATION_MODE_PRIORITIZED_STRING,
658 	NWAM_ACTIVATION_MODE_PRIORITIZED },
659 	{ NULL, 0 }
660 };
661 
662 struct nwam_value_entry ncu_prop_type_entries[] =
663 {
664 	{ NWAM_NCU_TYPE_LINK_STRING, NWAM_NCU_TYPE_LINK },
665 	{ NWAM_NCU_TYPE_INTERFACE_STRING, NWAM_NCU_TYPE_INTERFACE },
666 	{ NULL, 0 }
667 };
668 
669 struct nwam_value_entry ncu_prop_class_entries[] =
670 {
671 	{ NWAM_NCU_CLASS_PHYS_STRING, NWAM_NCU_CLASS_PHYS },
672 	{ NWAM_NCU_CLASS_IP_STRING, NWAM_NCU_CLASS_IP },
673 	{ NULL, 0 }
674 };
675 
676 struct nwam_value_entry ncu_prop_ip_version_entries[] =
677 {
678 	{ NWAM_IP_VERSION_IPV4_STRING, IPV4_VERSION },
679 	{ NWAM_IP_VERSION_IPV6_STRING, IPV6_VERSION },
680 	{ NULL, 0 }
681 };
682 
683 struct nwam_value_entry ncu_prop_ipv4_addrsrc_entries[] =
684 {
685 	{ NWAM_ADDRSRC_DHCP_STRING, NWAM_ADDRSRC_DHCP },
686 	{ NWAM_ADDRSRC_STATIC_STRING, NWAM_ADDRSRC_STATIC },
687 	{ NULL, 0 }
688 };
689 
690 struct nwam_value_entry ncu_prop_ipv6_addrsrc_entries[] =
691 {
692 	{ NWAM_ADDRSRC_DHCP_STRING, NWAM_ADDRSRC_DHCP },
693 	{ NWAM_ADDRSRC_STATIC_STRING, NWAM_ADDRSRC_STATIC },
694 	{ NWAM_ADDRSRC_AUTOCONF_STRING, NWAM_ADDRSRC_AUTOCONF },
695 	{ NULL, 0 }
696 };
697 
698 struct nwam_value_entry ncu_prop_priority_mode_entries[] =
699 {
700 	{ NWAM_PRIORITY_MODE_EXCLUSIVE_STRING, NWAM_PRIORITY_MODE_EXCLUSIVE },
701 	{ NWAM_PRIORITY_MODE_SHARED_STRING, NWAM_PRIORITY_MODE_SHARED },
702 	{ NWAM_PRIORITY_MODE_ALL_STRING, NWAM_PRIORITY_MODE_ALL },
703 	{ NULL, 0 }
704 };
705 
706 struct nwam_value_entry loc_prop_nameservices_entries[] =
707 {
708 	{ NWAM_NAMESERVICES_DNS_STRING, NWAM_NAMESERVICES_DNS },
709 	{ NWAM_NAMESERVICES_FILES_STRING, NWAM_NAMESERVICES_FILES },
710 	{ NWAM_NAMESERVICES_NIS_STRING, NWAM_NAMESERVICES_NIS },
711 	{ NWAM_NAMESERVICES_LDAP_STRING, NWAM_NAMESERVICES_LDAP },
712 	{ NULL, 0 }
713 };
714 
715 struct nwam_value_entry loc_prop_nameservice_configsrc_entries[] =
716 {
717 	{ NWAM_CONFIGSRC_MANUAL_STRING, NWAM_CONFIGSRC_MANUAL },
718 	{ NWAM_CONFIGSRC_DHCP_STRING, NWAM_CONFIGSRC_DHCP },
719 	{ NULL, 0 }
720 };
721 
722 struct nwam_value_entry known_wlan_prop_security_mode_entries[] =
723 {
724 	{ "none", DLADM_WLAN_SECMODE_NONE },
725 	{ "wep", DLADM_WLAN_SECMODE_WEP },
726 	{ "wpa", DLADM_WLAN_SECMODE_WPA },
727 	{ NULL, 0 }
728 };
729 
730 struct nwam_prop_value_entry {
731 	const char		*prop_name;
732 	struct nwam_value_entry	*value_entries;
733 } prop_value_entry_table[] =
734 {
735 	{ NWAM_NCU_PROP_ACTIVATION_MODE, prop_activation_mode_value_entries },
736 	{ NWAM_NCU_PROP_TYPE, ncu_prop_type_entries },
737 	{ NWAM_NCU_PROP_CLASS, ncu_prop_class_entries },
738 	{ NWAM_NCU_PROP_IP_VERSION, ncu_prop_ip_version_entries },
739 	{ NWAM_NCU_PROP_IPV4_ADDRSRC, ncu_prop_ipv4_addrsrc_entries },
740 	{ NWAM_NCU_PROP_IPV6_ADDRSRC, ncu_prop_ipv6_addrsrc_entries },
741 	{ NWAM_NCU_PROP_PRIORITY_MODE, ncu_prop_priority_mode_entries },
742 	{ NWAM_ENM_PROP_ACTIVATION_MODE, prop_activation_mode_value_entries },
743 	{ NWAM_LOC_PROP_ACTIVATION_MODE, prop_activation_mode_value_entries },
744 	{ NWAM_LOC_PROP_NAMESERVICES, loc_prop_nameservices_entries },
745 	{ NWAM_LOC_PROP_DNS_NAMESERVICE_CONFIGSRC,
746 	    loc_prop_nameservice_configsrc_entries },
747 	{ NWAM_LOC_PROP_NIS_NAMESERVICE_CONFIGSRC,
748 	    loc_prop_nameservice_configsrc_entries },
749 	{ NWAM_LOC_PROP_LDAP_NAMESERVICE_CONFIGSRC,
750 	    loc_prop_nameservice_configsrc_entries },
751 	{ NWAM_KNOWN_WLAN_PROP_SECURITY_MODE,
752 	    known_wlan_prop_security_mode_entries },
753 	{ NULL, NULL }
754 };
755 
756 /*
757  * Convert uint64 values for property propname into a string representing
758  * that value. Used by enum values.
759  */
760 nwam_error_t
761 nwam_uint64_get_value_string(const char *propname, uint64_t val,
762     const char **valstrp)
763 {
764 	int i, j;
765 	int max = 0; /* largest enum value seen so far */
766 	struct nwam_value_entry *value_entries;
767 
768 	assert(propname != NULL && valstrp != NULL);
769 
770 	for (i = 0; prop_value_entry_table[i].prop_name != NULL; i++) {
771 		if (strcmp(prop_value_entry_table[i].prop_name, propname) != 0)
772 			continue;
773 
774 		value_entries = prop_value_entry_table[i].value_entries;
775 
776 		for (j = 0; value_entries[j].value_string != NULL; j++) {
777 			if (value_entries[j].value == val) {
778 				*valstrp = value_entries[j].value_string;
779 				return (NWAM_SUCCESS);
780 			}
781 			max = value_entries[j].value > max ?
782 			    value_entries[j].value : max;
783 		}
784 		/*
785 		 * If trying to get the string for an enum value that doesn't
786 		 * exist, return NWAM_LIST_END.  Otherwise, the input enum
787 		 * value doesn't exist for the given property.
788 		 */
789 		if (val > max)
790 			return (NWAM_LIST_END);
791 		else
792 			return (NWAM_ENTITY_INVALID_VALUE);
793 	}
794 	return (NWAM_INVALID_ARG);
795 }
796 
797 /*
798  * Convert string to appropriate uint64 value.
799  */
800 nwam_error_t
801 nwam_value_string_get_uint64(const char *propname, const char *valstr,
802     uint64_t *valp)
803 {
804 	int i, j;
805 	struct nwam_value_entry *value_entries;
806 
807 	assert(propname != NULL && valstr != NULL && valp != NULL);
808 
809 	for (i = 0; prop_value_entry_table[i].prop_name != NULL; i++) {
810 		if (strcmp(prop_value_entry_table[i].prop_name, propname) != 0)
811 			continue;
812 
813 		value_entries = prop_value_entry_table[i].value_entries;
814 
815 		for (j = 0; value_entries[j].value_string != NULL; j++) {
816 			if (strcasecmp(value_entries[j].value_string, valstr)
817 			    == 0) {
818 				*valp = value_entries[j].value;
819 				return (NWAM_SUCCESS);
820 			}
821 		}
822 		return (NWAM_ENTITY_INVALID_VALUE);
823 	}
824 	return (NWAM_INVALID_ARG);
825 }
826 
827 /* Conditional activation functions */
828 
829 nwam_error_t
830 nwam_condition_to_condition_string(nwam_condition_object_type_t object_type,
831     nwam_condition_t condition, const char *object_name, char **stringp)
832 {
833 	char *object_type_string, *condition_string;
834 	char *string;
835 
836 	assert(stringp != NULL);
837 
838 	*stringp = NULL;
839 
840 	switch (object_type) {
841 	case NWAM_CONDITION_OBJECT_TYPE_NCP:
842 		object_type_string = NWAM_CONDITION_OBJECT_TYPE_NCP_STRING;
843 		break;
844 	case NWAM_CONDITION_OBJECT_TYPE_NCU:
845 		object_type_string = NWAM_CONDITION_OBJECT_TYPE_NCU_STRING;
846 		break;
847 	case NWAM_CONDITION_OBJECT_TYPE_ENM:
848 		object_type_string = NWAM_CONDITION_OBJECT_TYPE_ENM_STRING;
849 		break;
850 	case NWAM_CONDITION_OBJECT_TYPE_LOC:
851 		object_type_string = NWAM_CONDITION_OBJECT_TYPE_LOC_STRING;
852 		break;
853 	case NWAM_CONDITION_OBJECT_TYPE_IP_ADDRESS:
854 		object_type_string =
855 		    NWAM_CONDITION_OBJECT_TYPE_IP_ADDRESS_STRING;
856 		break;
857 	case NWAM_CONDITION_OBJECT_TYPE_ADV_DOMAIN:
858 		object_type_string =
859 		    NWAM_CONDITION_OBJECT_TYPE_ADV_DOMAIN_STRING;
860 		break;
861 	case NWAM_CONDITION_OBJECT_TYPE_SYS_DOMAIN:
862 		object_type_string =
863 		    NWAM_CONDITION_OBJECT_TYPE_SYS_DOMAIN_STRING;
864 		break;
865 	case NWAM_CONDITION_OBJECT_TYPE_ESSID:
866 		object_type_string = NWAM_CONDITION_OBJECT_TYPE_ESSID_STRING;
867 		break;
868 	case NWAM_CONDITION_OBJECT_TYPE_BSSID:
869 		object_type_string = NWAM_CONDITION_OBJECT_TYPE_BSSID_STRING;
870 		break;
871 	default:
872 		return (NWAM_INVALID_ARG);
873 
874 	}
875 	switch (condition) {
876 	case NWAM_CONDITION_IS:
877 		condition_string = NWAM_CONDITION_IS_STRING;
878 		break;
879 	case NWAM_CONDITION_IS_NOT:
880 		condition_string = NWAM_CONDITION_IS_NOT_STRING;
881 		break;
882 	case NWAM_CONDITION_CONTAINS:
883 		if (object_type != NWAM_CONDITION_OBJECT_TYPE_SYS_DOMAIN &&
884 		    object_type != NWAM_CONDITION_OBJECT_TYPE_ADV_DOMAIN &&
885 		    object_type != NWAM_CONDITION_OBJECT_TYPE_ESSID)
886 			return (NWAM_INVALID_ARG);
887 		condition_string = NWAM_CONDITION_CONTAINS_STRING;
888 		break;
889 	case NWAM_CONDITION_DOES_NOT_CONTAIN:
890 		if (object_type != NWAM_CONDITION_OBJECT_TYPE_SYS_DOMAIN &&
891 		    object_type != NWAM_CONDITION_OBJECT_TYPE_ADV_DOMAIN &&
892 		    object_type != NWAM_CONDITION_OBJECT_TYPE_ESSID)
893 			return (NWAM_INVALID_ARG);
894 
895 		condition_string = NWAM_CONDITION_DOES_NOT_CONTAIN_STRING;
896 		break;
897 	case NWAM_CONDITION_IS_IN_RANGE:
898 		if (object_type != NWAM_CONDITION_OBJECT_TYPE_IP_ADDRESS)
899 			return (NWAM_INVALID_ARG);
900 		condition_string = NWAM_CONDITION_IS_IN_RANGE_STRING;
901 		break;
902 	case NWAM_CONDITION_IS_NOT_IN_RANGE:
903 		if (object_type != NWAM_CONDITION_OBJECT_TYPE_IP_ADDRESS)
904 			return (NWAM_INVALID_ARG);
905 		condition_string = NWAM_CONDITION_IS_NOT_IN_RANGE_STRING;
906 		break;
907 	default:
908 		return (NWAM_INVALID_ARG);
909 	}
910 	if ((string = malloc(NWAM_MAX_VALUE_LEN)) == NULL)
911 		return (NWAM_NO_MEMORY);
912 	switch (object_type) {
913 	case NWAM_CONDITION_OBJECT_TYPE_NCP:
914 	case NWAM_CONDITION_OBJECT_TYPE_NCU:
915 	case NWAM_CONDITION_OBJECT_TYPE_ENM:
916 	case NWAM_CONDITION_OBJECT_TYPE_LOC:
917 		(void) snprintf(string, NWAM_MAX_VALUE_LEN,
918 		    "%s %s %s active", object_type_string,
919 		    object_name, condition_string);
920 		*stringp = string;
921 		break;
922 
923 	case NWAM_CONDITION_OBJECT_TYPE_IP_ADDRESS:
924 	case NWAM_CONDITION_OBJECT_TYPE_ADV_DOMAIN:
925 	case NWAM_CONDITION_OBJECT_TYPE_SYS_DOMAIN:
926 	case NWAM_CONDITION_OBJECT_TYPE_ESSID:
927 	case NWAM_CONDITION_OBJECT_TYPE_BSSID:
928 		(void) snprintf(string, NWAM_MAX_VALUE_LEN,
929 		    "%s %s %s", object_type_string,
930 		    condition_string, object_name);
931 		*stringp = string;
932 		break;
933 
934 	default:
935 		free(string);
936 		return (NWAM_INVALID_ARG);
937 
938 	}
939 	return (NWAM_SUCCESS);
940 }
941 
942 nwam_error_t
943 nwam_condition_string_to_condition(const char *string,
944     nwam_condition_object_type_t *object_typep,
945     nwam_condition_t *conditionp, char **object_namep)
946 {
947 	char *copy, *lasts;
948 	char *object_type_string, *object_name;
949 	char *condition_string, *active_string;
950 
951 	assert(string != NULL && object_typep != NULL && conditionp != NULL &&
952 	    object_namep != NULL);
953 
954 	if ((copy = strdup(string)) == NULL)
955 		return (NWAM_NO_MEMORY);
956 
957 	if ((object_type_string = strtok_r(copy, " \t", &lasts)) == NULL) {
958 		free(copy);
959 		return (NWAM_INVALID_ARG);
960 	}
961 
962 	if (strcmp(object_type_string, NWAM_CONDITION_OBJECT_TYPE_NCP_STRING)
963 	    == 0)
964 		*object_typep = NWAM_CONDITION_OBJECT_TYPE_NCP;
965 	else if (strcmp(object_type_string,
966 	    NWAM_CONDITION_OBJECT_TYPE_NCU_STRING) == 0)
967 		*object_typep = NWAM_CONDITION_OBJECT_TYPE_NCU;
968 	else if (strcmp(object_type_string,
969 	    NWAM_CONDITION_OBJECT_TYPE_ENM_STRING) == 0)
970 		*object_typep = NWAM_CONDITION_OBJECT_TYPE_ENM;
971 	else if (strcmp(object_type_string,
972 	    NWAM_CONDITION_OBJECT_TYPE_LOC_STRING) == 0)
973 		*object_typep = NWAM_CONDITION_OBJECT_TYPE_LOC;
974 	else if (strcmp(object_type_string,
975 	    NWAM_CONDITION_OBJECT_TYPE_IP_ADDRESS_STRING) == 0)
976 		*object_typep = NWAM_CONDITION_OBJECT_TYPE_IP_ADDRESS;
977 	else if (strcmp(object_type_string,
978 	    NWAM_CONDITION_OBJECT_TYPE_ADV_DOMAIN_STRING) == 0)
979 		*object_typep = NWAM_CONDITION_OBJECT_TYPE_ADV_DOMAIN;
980 	else if (strcmp(object_type_string,
981 	    NWAM_CONDITION_OBJECT_TYPE_SYS_DOMAIN_STRING) == 0)
982 		*object_typep = NWAM_CONDITION_OBJECT_TYPE_SYS_DOMAIN;
983 	else if (strcmp(object_type_string,
984 	    NWAM_CONDITION_OBJECT_TYPE_ESSID_STRING) == 0)
985 		*object_typep = NWAM_CONDITION_OBJECT_TYPE_ESSID;
986 	else if (strcmp(object_type_string,
987 	    NWAM_CONDITION_OBJECT_TYPE_BSSID_STRING) == 0)
988 		*object_typep = NWAM_CONDITION_OBJECT_TYPE_BSSID;
989 	else {
990 		free(copy);
991 		return (NWAM_INVALID_ARG);
992 	}
993 
994 	if (*object_typep == NWAM_CONDITION_OBJECT_TYPE_NCP ||
995 	    *object_typep == NWAM_CONDITION_OBJECT_TYPE_NCU ||
996 	    *object_typep == NWAM_CONDITION_OBJECT_TYPE_ENM ||
997 	    *object_typep == NWAM_CONDITION_OBJECT_TYPE_LOC) {
998 		if ((object_name = strtok_r(NULL, " \t", &lasts)) == NULL) {
999 			free(copy);
1000 			return (NWAM_INVALID_ARG);
1001 		}
1002 		if ((*object_namep = strdup(object_name)) == NULL) {
1003 			free(copy);
1004 			return (NWAM_NO_MEMORY);
1005 		}
1006 
1007 	}
1008 
1009 	if ((condition_string = strtok_r(NULL, " \t", &lasts)) == NULL) {
1010 		free(copy);
1011 		if (*object_namep != NULL)
1012 			free(*object_namep);
1013 		return (NWAM_INVALID_ARG);
1014 	}
1015 	if (strcmp(condition_string, NWAM_CONDITION_IS_STRING) == 0)
1016 		*conditionp = NWAM_CONDITION_IS;
1017 	else if (strcmp(condition_string, NWAM_CONDITION_IS_NOT_STRING) == 0)
1018 		*conditionp = NWAM_CONDITION_IS_NOT;
1019 	else if (strcmp(condition_string, NWAM_CONDITION_CONTAINS_STRING) == 0)
1020 		*conditionp = NWAM_CONDITION_CONTAINS;
1021 	else if (strcmp(condition_string,
1022 	    NWAM_CONDITION_DOES_NOT_CONTAIN_STRING) == 0)
1023 		*conditionp = NWAM_CONDITION_DOES_NOT_CONTAIN;
1024 	else if (strcmp(condition_string,
1025 	    NWAM_CONDITION_IS_IN_RANGE_STRING) == 0)
1026 		*conditionp = NWAM_CONDITION_IS_IN_RANGE;
1027 	else if (strcmp(condition_string,
1028 	    NWAM_CONDITION_IS_NOT_IN_RANGE_STRING) == 0)
1029 		*conditionp = NWAM_CONDITION_IS_NOT_IN_RANGE;
1030 	else {
1031 		free(copy);
1032 		if (*object_namep != NULL)
1033 			free(*object_namep);
1034 		return (NWAM_INVALID_ARG);
1035 	}
1036 
1037 	if (*object_typep == NWAM_CONDITION_OBJECT_TYPE_NCP ||
1038 	    *object_typep == NWAM_CONDITION_OBJECT_TYPE_NCU ||
1039 	    *object_typep == NWAM_CONDITION_OBJECT_TYPE_ENM ||
1040 	    *object_typep == NWAM_CONDITION_OBJECT_TYPE_LOC) {
1041 		if ((*conditionp != NWAM_CONDITION_IS &&
1042 		    *conditionp != NWAM_CONDITION_IS_NOT) ||
1043 		    (active_string = strtok_r(NULL, " \t", &lasts)) == NULL ||
1044 		    strcmp(active_string, NWAM_CONDITION_ACTIVE_STRING) != 0) {
1045 			free(copy);
1046 			free(*object_namep);
1047 			return (NWAM_INVALID_ARG);
1048 		}
1049 	} else {
1050 		switch (*conditionp) {
1051 		case NWAM_CONDITION_CONTAINS:
1052 		case NWAM_CONDITION_DOES_NOT_CONTAIN:
1053 			if (*object_typep !=
1054 			    NWAM_CONDITION_OBJECT_TYPE_ADV_DOMAIN &&
1055 			    *object_typep !=
1056 			    NWAM_CONDITION_OBJECT_TYPE_SYS_DOMAIN &&
1057 			    *object_typep != NWAM_CONDITION_OBJECT_TYPE_ESSID) {
1058 				free(copy);
1059 				free(*object_namep);
1060 				return (NWAM_INVALID_ARG);
1061 			}
1062 			break;
1063 		case NWAM_CONDITION_IS_IN_RANGE:
1064 		case NWAM_CONDITION_IS_NOT_IN_RANGE:
1065 			if (*object_typep !=
1066 			    NWAM_CONDITION_OBJECT_TYPE_IP_ADDRESS) {
1067 				free(copy);
1068 				free(*object_namep);
1069 				return (NWAM_INVALID_ARG);
1070 			}
1071 			break;
1072 		}
1073 
1074 		if ((object_name = strtok_r(NULL, " \t", &lasts)) == NULL) {
1075 			free(copy);
1076 			free(*object_namep);
1077 			return (NWAM_INVALID_ARG);
1078 		}
1079 		if ((*object_namep = strdup(object_name)) == NULL) {
1080 			free(copy);
1081 			free(*object_namep);
1082 			return (NWAM_NO_MEMORY);
1083 		}
1084 	}
1085 
1086 	free(copy);
1087 	return (NWAM_SUCCESS);
1088 }
1089 
1090 nwam_error_t
1091 nwam_condition_rate(nwam_condition_object_type_t object_type,
1092     nwam_condition_t condition, uint64_t *ratep)
1093 {
1094 	assert(ratep != NULL);
1095 
1096 	*ratep = 0;
1097 
1098 	switch (object_type) {
1099 	case NWAM_CONDITION_OBJECT_TYPE_NCP:
1100 	case NWAM_CONDITION_OBJECT_TYPE_NCU:
1101 	case NWAM_CONDITION_OBJECT_TYPE_ENM:
1102 	case NWAM_CONDITION_OBJECT_TYPE_LOC:
1103 		(*ratep)++;
1104 		/* FALLTHRU */
1105 	case NWAM_CONDITION_OBJECT_TYPE_SYS_DOMAIN:
1106 		(*ratep)++;
1107 		/* FALLTHRU */
1108 	case NWAM_CONDITION_OBJECT_TYPE_ADV_DOMAIN:
1109 		(*ratep)++;
1110 		/* FALLTHRU */
1111 	case NWAM_CONDITION_OBJECT_TYPE_IP_ADDRESS:
1112 		(*ratep)++;
1113 		/* FALLTHRU */
1114 	case NWAM_CONDITION_OBJECT_TYPE_BSSID:
1115 		(*ratep)++;
1116 		/* FALLTHRU */
1117 	case NWAM_CONDITION_OBJECT_TYPE_ESSID:
1118 		(*ratep)++;
1119 		break;
1120 	default:
1121 		return (NWAM_INVALID_ARG);
1122 	}
1123 
1124 	switch (condition) {
1125 	case NWAM_CONDITION_IS:
1126 		(*ratep)++;
1127 		/* FALLTHRU */
1128 	case NWAM_CONDITION_CONTAINS:
1129 	case NWAM_CONDITION_IS_IN_RANGE:
1130 		(*ratep)++;
1131 		/* FALLTHRU */
1132 	case NWAM_CONDITION_DOES_NOT_CONTAIN:
1133 	case NWAM_CONDITION_IS_NOT_IN_RANGE:
1134 		(*ratep)++;
1135 		/* FALLTHRU */
1136 	case NWAM_CONDITION_IS_NOT:
1137 		(*ratep)++;
1138 		break;
1139 	default:
1140 		return (NWAM_INVALID_ARG);
1141 	}
1142 	return (NWAM_SUCCESS);
1143 }
1144