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