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