1*6ba597c5SAnurag S. Maskey /*
2*6ba597c5SAnurag S. Maskey  * CDDL HEADER START
3*6ba597c5SAnurag S. Maskey  *
4*6ba597c5SAnurag S. Maskey  * The contents of this file are subject to the terms of the
5*6ba597c5SAnurag S. Maskey  * Common Development and Distribution License (the "License").
6*6ba597c5SAnurag S. Maskey  * You may not use this file except in compliance with the License.
7*6ba597c5SAnurag S. Maskey  *
8*6ba597c5SAnurag S. Maskey  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*6ba597c5SAnurag S. Maskey  * or http://www.opensolaris.org/os/licensing.
10*6ba597c5SAnurag S. Maskey  * See the License for the specific language governing permissions
11*6ba597c5SAnurag S. Maskey  * and limitations under the License.
12*6ba597c5SAnurag S. Maskey  *
13*6ba597c5SAnurag S. Maskey  * When distributing Covered Code, include this CDDL HEADER in each
14*6ba597c5SAnurag S. Maskey  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*6ba597c5SAnurag S. Maskey  * If applicable, add the following below this CDDL HEADER, with the
16*6ba597c5SAnurag S. Maskey  * fields enclosed by brackets "[]" replaced with your own identifying
17*6ba597c5SAnurag S. Maskey  * information: Portions Copyright [yyyy] [name of copyright owner]
18*6ba597c5SAnurag S. Maskey  *
19*6ba597c5SAnurag S. Maskey  * CDDL HEADER END
20*6ba597c5SAnurag S. Maskey  */
21*6ba597c5SAnurag S. Maskey 
22*6ba597c5SAnurag S. Maskey /*
23*6ba597c5SAnurag S. Maskey  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
24*6ba597c5SAnurag S. Maskey  * Use is subject to license terms.
25*6ba597c5SAnurag S. Maskey  */
26*6ba597c5SAnurag S. Maskey 
27*6ba597c5SAnurag S. Maskey #include <assert.h>
28*6ba597c5SAnurag S. Maskey #include <ctype.h>
29*6ba597c5SAnurag S. Maskey #include <sys/param.h>
30*6ba597c5SAnurag S. Maskey #include <sys/types.h>
31*6ba597c5SAnurag S. Maskey #include <sys/stat.h>
32*6ba597c5SAnurag S. Maskey #include <stdio.h>
33*6ba597c5SAnurag S. Maskey #include <stdlib.h>
34*6ba597c5SAnurag S. Maskey #include <strings.h>
35*6ba597c5SAnurag S. Maskey #include <unistd.h>
36*6ba597c5SAnurag S. Maskey #include <libdllink.h>
37*6ba597c5SAnurag S. Maskey #include <libdlwlan.h>
38*6ba597c5SAnurag S. Maskey 
39*6ba597c5SAnurag S. Maskey #include "libnwam_impl.h"
40*6ba597c5SAnurag S. Maskey #include <libnwam_priv.h>
41*6ba597c5SAnurag S. Maskey #include <libnwam.h>
42*6ba597c5SAnurag S. Maskey 
43*6ba597c5SAnurag S. Maskey /*
44*6ba597c5SAnurag S. Maskey  * Functions to support creating, modifying and destroying
45*6ba597c5SAnurag S. Maskey  * known WLAN objects. These represent the WiFi connection history,
46*6ba597c5SAnurag S. Maskey  * and are used by nwamd to identify and connect to known WLANs in
47*6ba597c5SAnurag S. Maskey  * scan results.
48*6ba597c5SAnurag S. Maskey  */
49*6ba597c5SAnurag S. Maskey 
50*6ba597c5SAnurag S. Maskey static nwam_error_t valid_keyname(nwam_value_t);
51*6ba597c5SAnurag S. Maskey static nwam_error_t valid_keyslot(nwam_value_t);
52*6ba597c5SAnurag S. Maskey static nwam_error_t valid_secmode(nwam_value_t);
53*6ba597c5SAnurag S. Maskey 
54*6ba597c5SAnurag S. Maskey struct nwam_prop_table_entry known_wlan_prop_table_entries[] = {
55*6ba597c5SAnurag S. Maskey 	{NWAM_KNOWN_WLAN_PROP_PRIORITY, NWAM_VALUE_TYPE_UINT64, B_FALSE,
56*6ba597c5SAnurag S. Maskey 	    1, 1, nwam_valid_uint64,
57*6ba597c5SAnurag S. Maskey 	    "specifies priority of known WLAN - lower values are prioritized",
58*6ba597c5SAnurag S. Maskey 	    NWAM_TYPE_ANY, NWAM_CLASS_ANY},
59*6ba597c5SAnurag S. Maskey 	{NWAM_KNOWN_WLAN_PROP_BSSIDS, NWAM_VALUE_TYPE_STRING, B_FALSE,
60*6ba597c5SAnurag S. Maskey 	    0, NWAM_MAX_NUM_VALUES, nwam_valid_mac_addr,
61*6ba597c5SAnurag S. Maskey 	    "specifies BSSID(s) (of the form aa:bb:cc:dd:ee:ff) associated "
62*6ba597c5SAnurag S. Maskey 	    "with known WLAN",
63*6ba597c5SAnurag S. Maskey 	    NWAM_TYPE_ANY, NWAM_CLASS_ANY},
64*6ba597c5SAnurag S. Maskey 	{NWAM_KNOWN_WLAN_PROP_KEYNAME, NWAM_VALUE_TYPE_STRING, B_FALSE,
65*6ba597c5SAnurag S. Maskey 	    0, 1, valid_keyname,
66*6ba597c5SAnurag S. Maskey 	    "specifies security key name used with known WLAN",
67*6ba597c5SAnurag S. Maskey 	    NWAM_TYPE_ANY, NWAM_CLASS_ANY},
68*6ba597c5SAnurag S. Maskey 	{NWAM_KNOWN_WLAN_PROP_KEYSLOT, NWAM_VALUE_TYPE_UINT64, B_FALSE,
69*6ba597c5SAnurag S. Maskey 	    0, 1, valid_keyslot,
70*6ba597c5SAnurag S. Maskey 	    "specifies key slot [1-4] for security key used with known WLAN",
71*6ba597c5SAnurag S. Maskey 	    NWAM_TYPE_ANY, NWAM_CLASS_ANY},
72*6ba597c5SAnurag S. Maskey 	{NWAM_KNOWN_WLAN_PROP_SECURITY_MODE, NWAM_VALUE_TYPE_UINT64, B_FALSE,
73*6ba597c5SAnurag S. Maskey 	    0, 1, valid_secmode,
74*6ba597c5SAnurag S. Maskey 	    "specifies security mode used for known WLAN",
75*6ba597c5SAnurag S. Maskey 	    NWAM_TYPE_ANY, NWAM_CLASS_ANY}
76*6ba597c5SAnurag S. Maskey };
77*6ba597c5SAnurag S. Maskey 
78*6ba597c5SAnurag S. Maskey #define	NWAM_NUM_KNOWN_WLAN_PROPS	\
79*6ba597c5SAnurag S. Maskey 		(sizeof (known_wlan_prop_table_entries) / \
80*6ba597c5SAnurag S. Maskey 		sizeof (*known_wlan_prop_table_entries))
81*6ba597c5SAnurag S. Maskey 
82*6ba597c5SAnurag S. Maskey struct nwam_prop_table known_wlan_prop_table =
83*6ba597c5SAnurag S. Maskey 	{ NWAM_NUM_KNOWN_WLAN_PROPS, known_wlan_prop_table_entries };
84*6ba597c5SAnurag S. Maskey 
85*6ba597c5SAnurag S. Maskey nwam_error_t
nwam_known_wlan_read(const char * name,uint64_t flags,nwam_known_wlan_handle_t * kwhp)86*6ba597c5SAnurag S. Maskey nwam_known_wlan_read(const char *name, uint64_t flags,
87*6ba597c5SAnurag S. Maskey     nwam_known_wlan_handle_t *kwhp)
88*6ba597c5SAnurag S. Maskey {
89*6ba597c5SAnurag S. Maskey 	return (nwam_read(NWAM_OBJECT_TYPE_KNOWN_WLAN,
90*6ba597c5SAnurag S. Maskey 	    NWAM_KNOWN_WLAN_CONF_FILE, name, flags, kwhp));
91*6ba597c5SAnurag S. Maskey }
92*6ba597c5SAnurag S. Maskey 
93*6ba597c5SAnurag S. Maskey nwam_error_t
nwam_known_wlan_create(const char * name,nwam_known_wlan_handle_t * kwhp)94*6ba597c5SAnurag S. Maskey nwam_known_wlan_create(const char *name, nwam_known_wlan_handle_t *kwhp)
95*6ba597c5SAnurag S. Maskey {
96*6ba597c5SAnurag S. Maskey 	nwam_error_t err;
97*6ba597c5SAnurag S. Maskey 	nwam_value_t priorityval = NULL;
98*6ba597c5SAnurag S. Maskey 
99*6ba597c5SAnurag S. Maskey 	assert(kwhp != NULL && name != NULL);
100*6ba597c5SAnurag S. Maskey 
101*6ba597c5SAnurag S. Maskey 	if ((err = nwam_create(NWAM_OBJECT_TYPE_KNOWN_WLAN,
102*6ba597c5SAnurag S. Maskey 	    NWAM_KNOWN_WLAN_CONF_FILE, name, kwhp)) != NWAM_SUCCESS)
103*6ba597c5SAnurag S. Maskey 		return (err);
104*6ba597c5SAnurag S. Maskey 
105*6ba597c5SAnurag S. Maskey 	/*
106*6ba597c5SAnurag S. Maskey 	 * Create new object list for known WLAN.  The initial priority is
107*6ba597c5SAnurag S. Maskey 	 * also set.
108*6ba597c5SAnurag S. Maskey 	 */
109*6ba597c5SAnurag S. Maskey 	if ((err = nwam_alloc_object_list(&((*kwhp)->nwh_data)))
110*6ba597c5SAnurag S. Maskey 	    != NWAM_SUCCESS)
111*6ba597c5SAnurag S. Maskey 		goto finish;
112*6ba597c5SAnurag S. Maskey 	if ((err = nwam_value_create_uint64(0, &priorityval)) != NWAM_SUCCESS)
113*6ba597c5SAnurag S. Maskey 		goto finish;
114*6ba597c5SAnurag S. Maskey 	err = nwam_set_prop_value((*kwhp)->nwh_data,
115*6ba597c5SAnurag S. Maskey 	    NWAM_KNOWN_WLAN_PROP_PRIORITY, priorityval);
116*6ba597c5SAnurag S. Maskey 
117*6ba597c5SAnurag S. Maskey finish:
118*6ba597c5SAnurag S. Maskey 	nwam_value_free(priorityval);
119*6ba597c5SAnurag S. Maskey 	if (err != NWAM_SUCCESS) {
120*6ba597c5SAnurag S. Maskey 		nwam_known_wlan_free(*kwhp);
121*6ba597c5SAnurag S. Maskey 		*kwhp = NULL;
122*6ba597c5SAnurag S. Maskey 	}
123*6ba597c5SAnurag S. Maskey 	return (err);
124*6ba597c5SAnurag S. Maskey }
125*6ba597c5SAnurag S. Maskey 
126*6ba597c5SAnurag S. Maskey nwam_error_t
nwam_known_wlan_get_name(nwam_known_wlan_handle_t kwh,char ** namep)127*6ba597c5SAnurag S. Maskey nwam_known_wlan_get_name(nwam_known_wlan_handle_t kwh, char **namep)
128*6ba597c5SAnurag S. Maskey {
129*6ba597c5SAnurag S. Maskey 	return (nwam_get_name(kwh, namep));
130*6ba597c5SAnurag S. Maskey }
131*6ba597c5SAnurag S. Maskey 
132*6ba597c5SAnurag S. Maskey nwam_error_t
nwam_known_wlan_set_name(nwam_known_wlan_handle_t kwh,const char * name)133*6ba597c5SAnurag S. Maskey nwam_known_wlan_set_name(nwam_known_wlan_handle_t kwh, const char *name)
134*6ba597c5SAnurag S. Maskey {
135*6ba597c5SAnurag S. Maskey 	return (nwam_set_name(kwh, name));
136*6ba597c5SAnurag S. Maskey }
137*6ba597c5SAnurag S. Maskey 
138*6ba597c5SAnurag S. Maskey boolean_t
nwam_known_wlan_can_set_name(nwam_known_wlan_handle_t kwh)139*6ba597c5SAnurag S. Maskey nwam_known_wlan_can_set_name(nwam_known_wlan_handle_t kwh)
140*6ba597c5SAnurag S. Maskey {
141*6ba597c5SAnurag S. Maskey 	return (!kwh->nwh_committed);
142*6ba597c5SAnurag S. Maskey }
143*6ba597c5SAnurag S. Maskey 
144*6ba597c5SAnurag S. Maskey /*
145*6ba597c5SAnurag S. Maskey  * Used to store wlan names/priorities for prioritized walk.
146*6ba597c5SAnurag S. Maskey  */
147*6ba597c5SAnurag S. Maskey struct nwam_wlan_info {
148*6ba597c5SAnurag S. Maskey 	char *wlan_name;
149*6ba597c5SAnurag S. Maskey 	uint64_t wlan_priority;
150*6ba597c5SAnurag S. Maskey 	boolean_t wlan_walked;
151*6ba597c5SAnurag S. Maskey };
152*6ba597c5SAnurag S. Maskey 
153*6ba597c5SAnurag S. Maskey struct nwam_wlan_info_list {
154*6ba597c5SAnurag S. Maskey 	struct nwam_wlan_info **list;
155*6ba597c5SAnurag S. Maskey 	uint_t num_wlans;
156*6ba597c5SAnurag S. Maskey };
157*6ba597c5SAnurag S. Maskey 
158*6ba597c5SAnurag S. Maskey /*
159*6ba597c5SAnurag S. Maskey  * Used to read in each known WLAN name/priority.
160*6ba597c5SAnurag S. Maskey  */
161*6ba597c5SAnurag S. Maskey static int
get_wlans_cb(nwam_known_wlan_handle_t kwh,void * data)162*6ba597c5SAnurag S. Maskey get_wlans_cb(nwam_known_wlan_handle_t kwh, void *data)
163*6ba597c5SAnurag S. Maskey {
164*6ba597c5SAnurag S. Maskey 	struct nwam_wlan_info_list *wil = data;
165*6ba597c5SAnurag S. Maskey 	struct nwam_wlan_info **list = wil->list;
166*6ba597c5SAnurag S. Maskey 	struct nwam_wlan_info **newlist = NULL;
167*6ba597c5SAnurag S. Maskey 	nwam_error_t err;
168*6ba597c5SAnurag S. Maskey 	nwam_value_t priorityval = NULL;
169*6ba597c5SAnurag S. Maskey 	uint_t num_wlans = wil->num_wlans;
170*6ba597c5SAnurag S. Maskey 
171*6ba597c5SAnurag S. Maskey 	/* Reallocate WLAN list and allocate new info list element. */
172*6ba597c5SAnurag S. Maskey 	if ((newlist = realloc(list,
173*6ba597c5SAnurag S. Maskey 	    sizeof (struct nwam_wlan_info *) * ++num_wlans)) == NULL ||
174*6ba597c5SAnurag S. Maskey 	    (newlist[num_wlans - 1] = calloc(1,
175*6ba597c5SAnurag S. Maskey 	    sizeof (struct nwam_wlan_info))) == NULL) {
176*6ba597c5SAnurag S. Maskey 		if (newlist != NULL)
177*6ba597c5SAnurag S. Maskey 			free(newlist);
178*6ba597c5SAnurag S. Maskey 		return (NWAM_NO_MEMORY);
179*6ba597c5SAnurag S. Maskey 	}
180*6ba597c5SAnurag S. Maskey 
181*6ba597c5SAnurag S. Maskey 	/* Update list since realloc() may have relocated it */
182*6ba597c5SAnurag S. Maskey 	wil->list = newlist;
183*6ba597c5SAnurag S. Maskey 
184*6ba597c5SAnurag S. Maskey 	/* Retrieve name/priority */
185*6ba597c5SAnurag S. Maskey 	if ((err = nwam_known_wlan_get_name(kwh,
186*6ba597c5SAnurag S. Maskey 	    &((newlist[num_wlans - 1])->wlan_name))) != NWAM_SUCCESS ||
187*6ba597c5SAnurag S. Maskey 	    (err = nwam_known_wlan_get_prop_value(kwh,
188*6ba597c5SAnurag S. Maskey 	    NWAM_KNOWN_WLAN_PROP_PRIORITY, &priorityval)) != NWAM_SUCCESS ||
189*6ba597c5SAnurag S. Maskey 	    (err = nwam_value_get_uint64(priorityval,
190*6ba597c5SAnurag S. Maskey 	    &((newlist[num_wlans - 1])->wlan_priority))) != NWAM_SUCCESS) {
191*6ba597c5SAnurag S. Maskey 		free(newlist[num_wlans - 1]->wlan_name);
192*6ba597c5SAnurag S. Maskey 		nwam_value_free(priorityval);
193*6ba597c5SAnurag S. Maskey 		free(newlist[num_wlans - 1]);
194*6ba597c5SAnurag S. Maskey 		return (err);
195*6ba597c5SAnurag S. Maskey 	}
196*6ba597c5SAnurag S. Maskey 	nwam_value_free(priorityval);
197*6ba597c5SAnurag S. Maskey 
198*6ba597c5SAnurag S. Maskey 	(newlist[num_wlans - 1])->wlan_walked = B_FALSE;
199*6ba597c5SAnurag S. Maskey 
200*6ba597c5SAnurag S. Maskey 	wil->num_wlans = num_wlans;
201*6ba597c5SAnurag S. Maskey 
202*6ba597c5SAnurag S. Maskey 	return (NWAM_SUCCESS);
203*6ba597c5SAnurag S. Maskey }
204*6ba597c5SAnurag S. Maskey 
205*6ba597c5SAnurag S. Maskey /*
206*6ba597c5SAnurag S. Maskey  * Some recursion is required here, since if _WALK_PRIORITY_ORDER is specified,
207*6ba597c5SAnurag S. Maskey  * we need to first walk the list of known WLANs to retrieve names
208*6ba597c5SAnurag S. Maskey  * and priorities, then utilize that list to carry out an in-order walk.
209*6ba597c5SAnurag S. Maskey  */
210*6ba597c5SAnurag S. Maskey nwam_error_t
nwam_walk_known_wlans(int (* cb)(nwam_known_wlan_handle_t,void *),void * data,uint64_t flags,int * retp)211*6ba597c5SAnurag S. Maskey nwam_walk_known_wlans(int(*cb)(nwam_known_wlan_handle_t, void *), void *data,
212*6ba597c5SAnurag S. Maskey     uint64_t flags, int *retp)
213*6ba597c5SAnurag S. Maskey {
214*6ba597c5SAnurag S. Maskey 	nwam_known_wlan_handle_t kwh;
215*6ba597c5SAnurag S. Maskey 	nwam_error_t err;
216*6ba597c5SAnurag S. Maskey 	int ret = 0;
217*6ba597c5SAnurag S. Maskey 
218*6ba597c5SAnurag S. Maskey 	assert(cb != NULL);
219*6ba597c5SAnurag S. Maskey 
220*6ba597c5SAnurag S. Maskey 	if ((err = nwam_valid_flags(flags,
221*6ba597c5SAnurag S. Maskey 	    NWAM_FLAG_KNOWN_WLAN_WALK_PRIORITY_ORDER | NWAM_FLAG_BLOCKING))
222*6ba597c5SAnurag S. Maskey 	    != NWAM_SUCCESS)
223*6ba597c5SAnurag S. Maskey 		return (err);
224*6ba597c5SAnurag S. Maskey 
225*6ba597c5SAnurag S. Maskey 	if ((flags & NWAM_FLAG_KNOWN_WLAN_WALK_PRIORITY_ORDER) != 0) {
226*6ba597c5SAnurag S. Maskey 		struct nwam_wlan_info_list wil = { NULL, 0};
227*6ba597c5SAnurag S. Maskey 		uint64_t iflags = flags &~
228*6ba597c5SAnurag S. Maskey 		    NWAM_FLAG_KNOWN_WLAN_WALK_PRIORITY_ORDER;
229*6ba597c5SAnurag S. Maskey 		uint64_t minpriority;
230*6ba597c5SAnurag S. Maskey 		int errval, i, j, minindex;
231*6ba597c5SAnurag S. Maskey 
232*6ba597c5SAnurag S. Maskey 		if (nwam_walk_known_wlans(get_wlans_cb, &wil, iflags, &errval)
233*6ba597c5SAnurag S. Maskey 		    != NWAM_SUCCESS) {
234*6ba597c5SAnurag S. Maskey 			err = (nwam_error_t)errval;
235*6ba597c5SAnurag S. Maskey 			goto done;
236*6ba597c5SAnurag S. Maskey 		}
237*6ba597c5SAnurag S. Maskey 
238*6ba597c5SAnurag S. Maskey 		err = NWAM_SUCCESS;
239*6ba597c5SAnurag S. Maskey 
240*6ba597c5SAnurag S. Maskey 		for (i = 0; i < wil.num_wlans; i++) {
241*6ba597c5SAnurag S. Maskey 			/* Find lowest priority value not walked so far. */
242*6ba597c5SAnurag S. Maskey 			minpriority = (uint64_t)-1;
243*6ba597c5SAnurag S. Maskey 			for (j = 0; j < wil.num_wlans; j++) {
244*6ba597c5SAnurag S. Maskey 				if (wil.list[j]->wlan_priority < minpriority &&
245*6ba597c5SAnurag S. Maskey 				    !(wil.list[j]->wlan_walked)) {
246*6ba597c5SAnurag S. Maskey 					minpriority =
247*6ba597c5SAnurag S. Maskey 					    wil.list[j]->wlan_priority;
248*6ba597c5SAnurag S. Maskey 					minindex = j;
249*6ba597c5SAnurag S. Maskey 				}
250*6ba597c5SAnurag S. Maskey 			}
251*6ba597c5SAnurag S. Maskey 			wil.list[minindex]->wlan_walked = B_TRUE;
252*6ba597c5SAnurag S. Maskey 			if ((err = nwam_known_wlan_read
253*6ba597c5SAnurag S. Maskey 			    (wil.list[minindex]->wlan_name,
254*6ba597c5SAnurag S. Maskey 			    iflags, &kwh)) != NWAM_SUCCESS) {
255*6ba597c5SAnurag S. Maskey 				goto done;
256*6ba597c5SAnurag S. Maskey 			}
257*6ba597c5SAnurag S. Maskey 			ret = cb(kwh, data);
258*6ba597c5SAnurag S. Maskey 			if (ret != 0) {
259*6ba597c5SAnurag S. Maskey 				nwam_known_wlan_free(kwh);
260*6ba597c5SAnurag S. Maskey 				err = NWAM_WALK_HALTED;
261*6ba597c5SAnurag S. Maskey 				goto done;
262*6ba597c5SAnurag S. Maskey 			}
263*6ba597c5SAnurag S. Maskey 			nwam_known_wlan_free(kwh);
264*6ba597c5SAnurag S. Maskey 		}
265*6ba597c5SAnurag S. Maskey done:
266*6ba597c5SAnurag S. Maskey 		if (wil.list != NULL) {
267*6ba597c5SAnurag S. Maskey 			for (j = 0; j < wil.num_wlans; j++) {
268*6ba597c5SAnurag S. Maskey 				free(wil.list[j]->wlan_name);
269*6ba597c5SAnurag S. Maskey 				free(wil.list[j]);
270*6ba597c5SAnurag S. Maskey 			}
271*6ba597c5SAnurag S. Maskey 			free(wil.list);
272*6ba597c5SAnurag S. Maskey 		}
273*6ba597c5SAnurag S. Maskey 		if (retp != NULL)
274*6ba597c5SAnurag S. Maskey 			*retp = ret;
275*6ba597c5SAnurag S. Maskey 		return (err);
276*6ba597c5SAnurag S. Maskey 	}
277*6ba597c5SAnurag S. Maskey 
278*6ba597c5SAnurag S. Maskey 	return (nwam_walk(NWAM_OBJECT_TYPE_KNOWN_WLAN,
279*6ba597c5SAnurag S. Maskey 	    NWAM_KNOWN_WLAN_CONF_FILE, cb, data, flags, retp, NULL));
280*6ba597c5SAnurag S. Maskey }
281*6ba597c5SAnurag S. Maskey 
282*6ba597c5SAnurag S. Maskey void
nwam_known_wlan_free(nwam_known_wlan_handle_t kwh)283*6ba597c5SAnurag S. Maskey nwam_known_wlan_free(nwam_known_wlan_handle_t kwh)
284*6ba597c5SAnurag S. Maskey {
285*6ba597c5SAnurag S. Maskey 	nwam_free(kwh);
286*6ba597c5SAnurag S. Maskey }
287*6ba597c5SAnurag S. Maskey 
288*6ba597c5SAnurag S. Maskey nwam_error_t
nwam_known_wlan_copy(nwam_known_wlan_handle_t oldkwh,const char * newname,nwam_known_wlan_handle_t * newkwhp)289*6ba597c5SAnurag S. Maskey nwam_known_wlan_copy(nwam_known_wlan_handle_t oldkwh, const char *newname,
290*6ba597c5SAnurag S. Maskey     nwam_known_wlan_handle_t *newkwhp)
291*6ba597c5SAnurag S. Maskey {
292*6ba597c5SAnurag S. Maskey 	return (nwam_copy(NWAM_KNOWN_WLAN_CONF_FILE, oldkwh, newname, newkwhp));
293*6ba597c5SAnurag S. Maskey }
294*6ba597c5SAnurag S. Maskey 
295*6ba597c5SAnurag S. Maskey nwam_error_t
nwam_known_wlan_delete_prop(nwam_known_wlan_handle_t kwh,const char * propname)296*6ba597c5SAnurag S. Maskey nwam_known_wlan_delete_prop(nwam_known_wlan_handle_t kwh, const char *propname)
297*6ba597c5SAnurag S. Maskey {
298*6ba597c5SAnurag S. Maskey 	nwam_error_t err;
299*6ba597c5SAnurag S. Maskey 	void *olddata;
300*6ba597c5SAnurag S. Maskey 
301*6ba597c5SAnurag S. Maskey 	assert(kwh != NULL && propname != NULL);
302*6ba597c5SAnurag S. Maskey 
303*6ba597c5SAnurag S. Maskey 	/*
304*6ba597c5SAnurag S. Maskey 	 * Duplicate data, remove property and validate. If validation
305*6ba597c5SAnurag S. Maskey 	 * fails, revert to data duplicated prior to remove.
306*6ba597c5SAnurag S. Maskey 	 */
307*6ba597c5SAnurag S. Maskey 	if ((err = nwam_dup_object_list(kwh->nwh_data, &olddata))
308*6ba597c5SAnurag S. Maskey 	    != NWAM_SUCCESS)
309*6ba597c5SAnurag S. Maskey 		return (err);
310*6ba597c5SAnurag S. Maskey 	if ((err = nwam_delete_prop(kwh->nwh_data, propname)) != NWAM_SUCCESS) {
311*6ba597c5SAnurag S. Maskey 		nwam_free_object_list(kwh->nwh_data);
312*6ba597c5SAnurag S. Maskey 		kwh->nwh_data = olddata;
313*6ba597c5SAnurag S. Maskey 		return (err);
314*6ba597c5SAnurag S. Maskey 	}
315*6ba597c5SAnurag S. Maskey 	if ((err = nwam_known_wlan_validate(kwh, NULL)) != NWAM_SUCCESS) {
316*6ba597c5SAnurag S. Maskey 		nwam_free_object_list(kwh->nwh_data);
317*6ba597c5SAnurag S. Maskey 		kwh->nwh_data = olddata;
318*6ba597c5SAnurag S. Maskey 		return (err);
319*6ba597c5SAnurag S. Maskey 	}
320*6ba597c5SAnurag S. Maskey 	nwam_free_object_list(olddata);
321*6ba597c5SAnurag S. Maskey 
322*6ba597c5SAnurag S. Maskey 	return (NWAM_SUCCESS);
323*6ba597c5SAnurag S. Maskey }
324*6ba597c5SAnurag S. Maskey 
325*6ba597c5SAnurag S. Maskey nwam_error_t
nwam_known_wlan_set_prop_value(nwam_known_wlan_handle_t kwh,const char * propname,nwam_value_t value)326*6ba597c5SAnurag S. Maskey nwam_known_wlan_set_prop_value(nwam_known_wlan_handle_t kwh,
327*6ba597c5SAnurag S. Maskey     const char *propname, nwam_value_t value)
328*6ba597c5SAnurag S. Maskey {
329*6ba597c5SAnurag S. Maskey 	nwam_error_t err;
330*6ba597c5SAnurag S. Maskey 
331*6ba597c5SAnurag S. Maskey 	assert(kwh != NULL && propname != NULL && value != NULL);
332*6ba597c5SAnurag S. Maskey 
333*6ba597c5SAnurag S. Maskey 	if ((err = nwam_known_wlan_validate_prop(kwh, propname, value))
334*6ba597c5SAnurag S. Maskey 	    != NWAM_SUCCESS)
335*6ba597c5SAnurag S. Maskey 		return (err);
336*6ba597c5SAnurag S. Maskey 
337*6ba597c5SAnurag S. Maskey 	return (nwam_set_prop_value(kwh->nwh_data, propname, value));
338*6ba597c5SAnurag S. Maskey }
339*6ba597c5SAnurag S. Maskey 
340*6ba597c5SAnurag S. Maskey nwam_error_t
nwam_known_wlan_get_prop_value(nwam_known_wlan_handle_t kwh,const char * propname,nwam_value_t * valuep)341*6ba597c5SAnurag S. Maskey nwam_known_wlan_get_prop_value(nwam_known_wlan_handle_t kwh,
342*6ba597c5SAnurag S. Maskey     const char *propname, nwam_value_t *valuep)
343*6ba597c5SAnurag S. Maskey {
344*6ba597c5SAnurag S. Maskey 	return (nwam_get_prop_value(kwh->nwh_data, propname, valuep));
345*6ba597c5SAnurag S. Maskey }
346*6ba597c5SAnurag S. Maskey 
347*6ba597c5SAnurag S. Maskey nwam_error_t
nwam_known_wlan_walk_props(nwam_known_wlan_handle_t kwh,int (* cb)(const char *,nwam_value_t,void *),void * data,uint64_t flags,int * retp)348*6ba597c5SAnurag S. Maskey nwam_known_wlan_walk_props(nwam_known_wlan_handle_t kwh,
349*6ba597c5SAnurag S. Maskey     int (*cb)(const char *, nwam_value_t, void *),
350*6ba597c5SAnurag S. Maskey     void *data, uint64_t flags, int *retp)
351*6ba597c5SAnurag S. Maskey {
352*6ba597c5SAnurag S. Maskey 	return (nwam_walk_props(kwh, cb, data, flags, retp));
353*6ba597c5SAnurag S. Maskey }
354*6ba597c5SAnurag S. Maskey 
355*6ba597c5SAnurag S. Maskey struct priority_collision_data {
356*6ba597c5SAnurag S. Maskey 	char *wlan_name;
357*6ba597c5SAnurag S. Maskey 	uint64_t priority;
358*6ba597c5SAnurag S. Maskey };
359*6ba597c5SAnurag S. Maskey 
360*6ba597c5SAnurag S. Maskey static int
avoid_priority_collisions_cb(nwam_known_wlan_handle_t kwh,void * data)361*6ba597c5SAnurag S. Maskey avoid_priority_collisions_cb(nwam_known_wlan_handle_t kwh, void *data)
362*6ba597c5SAnurag S. Maskey {
363*6ba597c5SAnurag S. Maskey 	nwam_value_t priorityval;
364*6ba597c5SAnurag S. Maskey 	nwam_error_t err;
365*6ba597c5SAnurag S. Maskey 	struct priority_collision_data *pcd = data;
366*6ba597c5SAnurag S. Maskey 	char *name;
367*6ba597c5SAnurag S. Maskey 	uint64_t priority;
368*6ba597c5SAnurag S. Maskey 
369*6ba597c5SAnurag S. Maskey 	err = nwam_known_wlan_get_name(kwh, &name);
370*6ba597c5SAnurag S. Maskey 	if (err != NWAM_SUCCESS)
371*6ba597c5SAnurag S. Maskey 		return (err);
372*6ba597c5SAnurag S. Maskey 	if (strcmp(name, pcd->wlan_name) == 0) {
373*6ba597c5SAnurag S. Maskey 		/* skip to-be-updated wlan */
374*6ba597c5SAnurag S. Maskey 		free(name);
375*6ba597c5SAnurag S. Maskey 		return (NWAM_SUCCESS);
376*6ba597c5SAnurag S. Maskey 	}
377*6ba597c5SAnurag S. Maskey 	free(name);
378*6ba597c5SAnurag S. Maskey 
379*6ba597c5SAnurag S. Maskey 	err = nwam_known_wlan_get_prop_value(kwh, NWAM_KNOWN_WLAN_PROP_PRIORITY,
380*6ba597c5SAnurag S. Maskey 	    &priorityval);
381*6ba597c5SAnurag S. Maskey 	if (err != NWAM_SUCCESS)
382*6ba597c5SAnurag S. Maskey 		return (err);
383*6ba597c5SAnurag S. Maskey 	err = nwam_value_get_uint64(priorityval, &priority);
384*6ba597c5SAnurag S. Maskey 	if (err != NWAM_SUCCESS)
385*6ba597c5SAnurag S. Maskey 		return (err);
386*6ba597c5SAnurag S. Maskey 	nwam_value_free(priorityval);
387*6ba597c5SAnurag S. Maskey 
388*6ba597c5SAnurag S. Maskey 	if (priority < pcd->priority)
389*6ba597c5SAnurag S. Maskey 		return (NWAM_SUCCESS);
390*6ba597c5SAnurag S. Maskey 
391*6ba597c5SAnurag S. Maskey 	if (priority == pcd->priority) {
392*6ba597c5SAnurag S. Maskey 		/* Two priority values collide.  Move this one up. */
393*6ba597c5SAnurag S. Maskey 		err = nwam_value_create_uint64(priority + 1, &priorityval);
394*6ba597c5SAnurag S. Maskey 		if (err != NWAM_SUCCESS)
395*6ba597c5SAnurag S. Maskey 			return (err);
396*6ba597c5SAnurag S. Maskey 		err = nwam_known_wlan_set_prop_value(kwh,
397*6ba597c5SAnurag S. Maskey 		    NWAM_KNOWN_WLAN_PROP_PRIORITY, priorityval);
398*6ba597c5SAnurag S. Maskey 		nwam_value_free(priorityval);
399*6ba597c5SAnurag S. Maskey 		if (err != NWAM_SUCCESS) {
400*6ba597c5SAnurag S. Maskey 			return (err);
401*6ba597c5SAnurag S. Maskey 		}
402*6ba597c5SAnurag S. Maskey 		/*
403*6ba597c5SAnurag S. Maskey 		 * We are doing a walk, and will continue shifting until
404*6ba597c5SAnurag S. Maskey 		 * we find a gap in the priority numbers; thus no need to
405*6ba597c5SAnurag S. Maskey 		 * do collision checking here.
406*6ba597c5SAnurag S. Maskey 		 */
407*6ba597c5SAnurag S. Maskey 		err = nwam_known_wlan_commit(kwh,
408*6ba597c5SAnurag S. Maskey 		    NWAM_FLAG_KNOWN_WLAN_NO_COLLISION_CHECK);
409*6ba597c5SAnurag S. Maskey 		if (err != NWAM_SUCCESS)
410*6ba597c5SAnurag S. Maskey 			return (err);
411*6ba597c5SAnurag S. Maskey 
412*6ba597c5SAnurag S. Maskey 		(pcd->priority)++;
413*6ba597c5SAnurag S. Maskey 		return (NWAM_SUCCESS);
414*6ba597c5SAnurag S. Maskey 	}
415*6ba597c5SAnurag S. Maskey 
416*6ba597c5SAnurag S. Maskey 	/*
417*6ba597c5SAnurag S. Maskey 	 * Only possiblity left at this point is that we're looking
418*6ba597c5SAnurag S. Maskey 	 * at a priority greater than the last one we wrote, so we've
419*6ba597c5SAnurag S. Maskey 	 * found a gap.  We can halt the walk now.
420*6ba597c5SAnurag S. Maskey 	 */
421*6ba597c5SAnurag S. Maskey 	return (NWAM_WALK_HALTED);
422*6ba597c5SAnurag S. Maskey }
423*6ba597c5SAnurag S. Maskey 
424*6ba597c5SAnurag S. Maskey nwam_error_t
nwam_known_wlan_commit(nwam_known_wlan_handle_t kwh,uint64_t flags)425*6ba597c5SAnurag S. Maskey nwam_known_wlan_commit(nwam_known_wlan_handle_t kwh, uint64_t flags)
426*6ba597c5SAnurag S. Maskey {
427*6ba597c5SAnurag S. Maskey 	nwam_error_t err;
428*6ba597c5SAnurag S. Maskey 	nwam_value_t priorityval;
429*6ba597c5SAnurag S. Maskey 	int ret = 0;
430*6ba597c5SAnurag S. Maskey 	struct priority_collision_data pcd;
431*6ba597c5SAnurag S. Maskey 
432*6ba597c5SAnurag S. Maskey 	assert(kwh != NULL && kwh->nwh_data != NULL);
433*6ba597c5SAnurag S. Maskey 
434*6ba597c5SAnurag S. Maskey 	if ((err = nwam_known_wlan_validate(kwh, NULL)) != NWAM_SUCCESS)
435*6ba597c5SAnurag S. Maskey 		return (err);
436*6ba597c5SAnurag S. Maskey 
437*6ba597c5SAnurag S. Maskey 	/*
438*6ba597c5SAnurag S. Maskey 	 * If the NO_COLLISION_CHECK flag is set, no need to check for
439*6ba597c5SAnurag S. Maskey 	 * collision.
440*6ba597c5SAnurag S. Maskey 	 */
441*6ba597c5SAnurag S. Maskey 	if (flags & NWAM_FLAG_KNOWN_WLAN_NO_COLLISION_CHECK)
442*6ba597c5SAnurag S. Maskey 		return (nwam_commit(NWAM_KNOWN_WLAN_CONF_FILE, kwh,
443*6ba597c5SAnurag S. Maskey 		    (flags & NWAM_FLAG_GLOBAL_MASK) |
444*6ba597c5SAnurag S. Maskey 		    NWAM_FLAG_ENTITY_KNOWN_WLAN));
445*6ba597c5SAnurag S. Maskey 
446*6ba597c5SAnurag S. Maskey 	/*
447*6ba597c5SAnurag S. Maskey 	 * We need to do priority checking.  Walk the list, looking
448*6ba597c5SAnurag S. Maskey 	 * for the first entry with priority greater than or equal
449*6ba597c5SAnurag S. Maskey 	 * to the entry we're adding.  Commit the new one (without
450*6ba597c5SAnurag S. Maskey 	 * doing additional checking), and then increment other
451*6ba597c5SAnurag S. Maskey 	 * entries as needed.
452*6ba597c5SAnurag S. Maskey 	 */
453*6ba597c5SAnurag S. Maskey 	err = nwam_known_wlan_get_prop_value(kwh,
454*6ba597c5SAnurag S. Maskey 	    NWAM_KNOWN_WLAN_PROP_PRIORITY, &priorityval);
455*6ba597c5SAnurag S. Maskey 	if (err != NWAM_SUCCESS)
456*6ba597c5SAnurag S. Maskey 		return (err);
457*6ba597c5SAnurag S. Maskey 	err = nwam_value_get_uint64(priorityval, &(pcd.priority));
458*6ba597c5SAnurag S. Maskey 	nwam_value_free(priorityval);
459*6ba597c5SAnurag S. Maskey 	if (err != NWAM_SUCCESS)
460*6ba597c5SAnurag S. Maskey 		return (err);
461*6ba597c5SAnurag S. Maskey 	err = nwam_known_wlan_get_name(kwh, &(pcd.wlan_name));
462*6ba597c5SAnurag S. Maskey 	if (err != NWAM_SUCCESS)
463*6ba597c5SAnurag S. Maskey 		return (err);
464*6ba597c5SAnurag S. Maskey 	err = nwam_walk_known_wlans(avoid_priority_collisions_cb, &pcd,
465*6ba597c5SAnurag S. Maskey 	    NWAM_FLAG_KNOWN_WLAN_WALK_PRIORITY_ORDER, &ret);
466*6ba597c5SAnurag S. Maskey 	free(pcd.wlan_name);
467*6ba597c5SAnurag S. Maskey 	/*
468*6ba597c5SAnurag S. Maskey 	 * a halted walk is okay, it just means we didn't have
469*6ba597c5SAnurag S. Maskey 	 * to walk the entire list to resolve priorities
470*6ba597c5SAnurag S. Maskey 	 */
471*6ba597c5SAnurag S. Maskey 	if (ret != NWAM_SUCCESS && ret != NWAM_WALK_HALTED)
472*6ba597c5SAnurag S. Maskey 		return (ret);
473*6ba597c5SAnurag S. Maskey 
474*6ba597c5SAnurag S. Maskey 	return (nwam_known_wlan_commit(kwh,
475*6ba597c5SAnurag S. Maskey 	    flags | NWAM_FLAG_KNOWN_WLAN_NO_COLLISION_CHECK));
476*6ba597c5SAnurag S. Maskey }
477*6ba597c5SAnurag S. Maskey 
478*6ba597c5SAnurag S. Maskey nwam_error_t
nwam_known_wlan_destroy(nwam_known_wlan_handle_t kwh,uint64_t flags)479*6ba597c5SAnurag S. Maskey nwam_known_wlan_destroy(nwam_known_wlan_handle_t kwh, uint64_t flags)
480*6ba597c5SAnurag S. Maskey {
481*6ba597c5SAnurag S. Maskey 	return (nwam_destroy(NWAM_KNOWN_WLAN_CONF_FILE, kwh,
482*6ba597c5SAnurag S. Maskey 	    flags | NWAM_FLAG_ENTITY_KNOWN_WLAN));
483*6ba597c5SAnurag S. Maskey }
484*6ba597c5SAnurag S. Maskey 
485*6ba597c5SAnurag S. Maskey nwam_error_t
nwam_known_wlan_get_prop_description(const char * propname,const char ** descriptionp)486*6ba597c5SAnurag S. Maskey nwam_known_wlan_get_prop_description(const char *propname,
487*6ba597c5SAnurag S. Maskey     const char **descriptionp)
488*6ba597c5SAnurag S. Maskey {
489*6ba597c5SAnurag S. Maskey 	return (nwam_get_prop_description(known_wlan_prop_table, propname,
490*6ba597c5SAnurag S. Maskey 	    descriptionp));
491*6ba597c5SAnurag S. Maskey }
492*6ba597c5SAnurag S. Maskey 
493*6ba597c5SAnurag S. Maskey /* Property-specific value validation functions should go here. */
494*6ba597c5SAnurag S. Maskey 
495*6ba597c5SAnurag S. Maskey static nwam_error_t
valid_keyname(nwam_value_t value)496*6ba597c5SAnurag S. Maskey valid_keyname(nwam_value_t value)
497*6ba597c5SAnurag S. Maskey {
498*6ba597c5SAnurag S. Maskey 	char *keyname;
499*6ba597c5SAnurag S. Maskey 
500*6ba597c5SAnurag S. Maskey 	if (nwam_value_get_string(value, &keyname) != NWAM_SUCCESS)
501*6ba597c5SAnurag S. Maskey 		return (NWAM_ENTITY_INVALID_VALUE);
502*6ba597c5SAnurag S. Maskey 
503*6ba597c5SAnurag S. Maskey 	if (!dladm_valid_secobj_name(keyname))
504*6ba597c5SAnurag S. Maskey 		return (NWAM_ENTITY_INVALID_VALUE);
505*6ba597c5SAnurag S. Maskey 
506*6ba597c5SAnurag S. Maskey 	return (NWAM_SUCCESS);
507*6ba597c5SAnurag S. Maskey }
508*6ba597c5SAnurag S. Maskey 
509*6ba597c5SAnurag S. Maskey static nwam_error_t
valid_keyslot(nwam_value_t value)510*6ba597c5SAnurag S. Maskey valid_keyslot(nwam_value_t value)
511*6ba597c5SAnurag S. Maskey {
512*6ba597c5SAnurag S. Maskey 	uint64_t keyslot;
513*6ba597c5SAnurag S. Maskey 
514*6ba597c5SAnurag S. Maskey 	if (nwam_value_get_uint64(value, &keyslot) != NWAM_SUCCESS)
515*6ba597c5SAnurag S. Maskey 		return (NWAM_ENTITY_INVALID_VALUE);
516*6ba597c5SAnurag S. Maskey 
517*6ba597c5SAnurag S. Maskey 	if (keyslot < 1 || keyslot > 4)
518*6ba597c5SAnurag S. Maskey 		return (NWAM_ENTITY_INVALID_VALUE);
519*6ba597c5SAnurag S. Maskey 
520*6ba597c5SAnurag S. Maskey 	return (NWAM_SUCCESS);
521*6ba597c5SAnurag S. Maskey }
522*6ba597c5SAnurag S. Maskey 
523*6ba597c5SAnurag S. Maskey static nwam_error_t
valid_secmode(nwam_value_t value)524*6ba597c5SAnurag S. Maskey valid_secmode(nwam_value_t value)
525*6ba597c5SAnurag S. Maskey {
526*6ba597c5SAnurag S. Maskey 	uint64_t secmode;
527*6ba597c5SAnurag S. Maskey 
528*6ba597c5SAnurag S. Maskey 	if (nwam_value_get_uint64(value, &secmode) != NWAM_SUCCESS)
529*6ba597c5SAnurag S. Maskey 		return (NWAM_ENTITY_INVALID_VALUE);
530*6ba597c5SAnurag S. Maskey 
531*6ba597c5SAnurag S. Maskey 	if (secmode != DLADM_WLAN_SECMODE_NONE &&
532*6ba597c5SAnurag S. Maskey 	    secmode != DLADM_WLAN_SECMODE_WEP &&
533*6ba597c5SAnurag S. Maskey 	    secmode != DLADM_WLAN_SECMODE_WPA)
534*6ba597c5SAnurag S. Maskey 		return (NWAM_ENTITY_INVALID_VALUE);
535*6ba597c5SAnurag S. Maskey 
536*6ba597c5SAnurag S. Maskey 	return (NWAM_SUCCESS);
537*6ba597c5SAnurag S. Maskey }
538*6ba597c5SAnurag S. Maskey 
539*6ba597c5SAnurag S. Maskey nwam_error_t
nwam_known_wlan_validate(nwam_known_wlan_handle_t kwh,const char ** errpropp)540*6ba597c5SAnurag S. Maskey nwam_known_wlan_validate(nwam_known_wlan_handle_t kwh, const char **errpropp)
541*6ba597c5SAnurag S. Maskey {
542*6ba597c5SAnurag S. Maskey 	return (nwam_validate(known_wlan_prop_table, kwh, errpropp));
543*6ba597c5SAnurag S. Maskey }
544*6ba597c5SAnurag S. Maskey 
545*6ba597c5SAnurag S. Maskey nwam_error_t
nwam_known_wlan_validate_prop(nwam_known_wlan_handle_t kwh,const char * propname,nwam_value_t value)546*6ba597c5SAnurag S. Maskey nwam_known_wlan_validate_prop(nwam_known_wlan_handle_t kwh,
547*6ba597c5SAnurag S. Maskey     const char *propname, nwam_value_t value)
548*6ba597c5SAnurag S. Maskey {
549*6ba597c5SAnurag S. Maskey 	return (nwam_validate_prop(known_wlan_prop_table, kwh, propname,
550*6ba597c5SAnurag S. Maskey 	    value));
551*6ba597c5SAnurag S. Maskey }
552*6ba597c5SAnurag S. Maskey 
553*6ba597c5SAnurag S. Maskey /*
554*6ba597c5SAnurag S. Maskey  * Given a property, return expected property data type
555*6ba597c5SAnurag S. Maskey  */
556*6ba597c5SAnurag S. Maskey nwam_error_t
nwam_known_wlan_get_prop_type(const char * propname,nwam_value_type_t * typep)557*6ba597c5SAnurag S. Maskey nwam_known_wlan_get_prop_type(const char *propname, nwam_value_type_t *typep)
558*6ba597c5SAnurag S. Maskey {
559*6ba597c5SAnurag S. Maskey 	return (nwam_get_prop_type(known_wlan_prop_table, propname, typep));
560*6ba597c5SAnurag S. Maskey }
561*6ba597c5SAnurag S. Maskey 
562*6ba597c5SAnurag S. Maskey nwam_error_t
nwam_known_wlan_prop_multivalued(const char * propname,boolean_t * multip)563*6ba597c5SAnurag S. Maskey nwam_known_wlan_prop_multivalued(const char *propname, boolean_t *multip)
564*6ba597c5SAnurag S. Maskey {
565*6ba597c5SAnurag S. Maskey 	return (nwam_prop_multivalued(known_wlan_prop_table, propname, multip));
566*6ba597c5SAnurag S. Maskey }
567*6ba597c5SAnurag S. Maskey 
568*6ba597c5SAnurag S. Maskey nwam_error_t
nwam_known_wlan_get_default_proplist(const char *** prop_list,uint_t * numvaluesp)569*6ba597c5SAnurag S. Maskey nwam_known_wlan_get_default_proplist(const char ***prop_list,
570*6ba597c5SAnurag S. Maskey     uint_t *numvaluesp)
571*6ba597c5SAnurag S. Maskey {
572*6ba597c5SAnurag S. Maskey 	return (nwam_get_default_proplist(known_wlan_prop_table,
573*6ba597c5SAnurag S. Maskey 	    NWAM_TYPE_ANY, NWAM_CLASS_ANY, prop_list, numvaluesp));
574*6ba597c5SAnurag S. Maskey }
575*6ba597c5SAnurag S. Maskey 
576*6ba597c5SAnurag S. Maskey /*
577*6ba597c5SAnurag S. Maskey  * Add the given ESSID, BSSID, secmode, keyslot and key name to known WLANs.
578*6ba597c5SAnurag S. Maskey  * BSSID and keyname can be NULL.
579*6ba597c5SAnurag S. Maskey  */
580*6ba597c5SAnurag S. Maskey nwam_error_t
nwam_known_wlan_add_to_known_wlans(const char * essid,const char * bssid,uint32_t secmode,uint_t keyslot,const char * keyname)581*6ba597c5SAnurag S. Maskey nwam_known_wlan_add_to_known_wlans(const char *essid, const char *bssid,
582*6ba597c5SAnurag S. Maskey     uint32_t secmode, uint_t keyslot, const char *keyname)
583*6ba597c5SAnurag S. Maskey {
584*6ba597c5SAnurag S. Maskey 	nwam_known_wlan_handle_t kwh;
585*6ba597c5SAnurag S. Maskey 	nwam_value_t keynameval = NULL, keyslotval = NULL, bssidsval = NULL;
586*6ba597c5SAnurag S. Maskey 	nwam_value_t secmodeval = NULL, priorityval = NULL;
587*6ba597c5SAnurag S. Maskey 	char **old_bssids = NULL, **new_bssids;
588*6ba597c5SAnurag S. Maskey 	uint_t nelem = 0;
589*6ba597c5SAnurag S. Maskey 	nwam_error_t err;
590*6ba597c5SAnurag S. Maskey 	int i, j;
591*6ba597c5SAnurag S. Maskey 
592*6ba597c5SAnurag S. Maskey 	/*
593*6ba597c5SAnurag S. Maskey 	 * Check if the given ESSID already exists as known WLAN.  If so,
594*6ba597c5SAnurag S. Maskey 	 * add the BSSID to the bssids property.  If not, create one with
595*6ba597c5SAnurag S. Maskey 	 * the given ESSID and add BSSID if given.
596*6ba597c5SAnurag S. Maskey 	 */
597*6ba597c5SAnurag S. Maskey 	err = nwam_known_wlan_read(essid, 0, &kwh);
598*6ba597c5SAnurag S. Maskey 
599*6ba597c5SAnurag S. Maskey 	switch (err) {
600*6ba597c5SAnurag S. Maskey 	case NWAM_ENTITY_NOT_FOUND:
601*6ba597c5SAnurag S. Maskey 		if ((err = nwam_known_wlan_create(essid, &kwh)) != NWAM_SUCCESS)
602*6ba597c5SAnurag S. Maskey 			return (err);
603*6ba597c5SAnurag S. Maskey 		/* New known WLAN - set priority to 0 */
604*6ba597c5SAnurag S. Maskey 		if ((err = nwam_value_create_uint64(0, &priorityval))
605*6ba597c5SAnurag S. Maskey 		    != NWAM_SUCCESS) {
606*6ba597c5SAnurag S. Maskey 			nwam_known_wlan_free(kwh);
607*6ba597c5SAnurag S. Maskey 			return (err);
608*6ba597c5SAnurag S. Maskey 		}
609*6ba597c5SAnurag S. Maskey 		err = nwam_known_wlan_set_prop_value(kwh,
610*6ba597c5SAnurag S. Maskey 		    NWAM_KNOWN_WLAN_PROP_PRIORITY, priorityval);
611*6ba597c5SAnurag S. Maskey 		nwam_value_free(priorityval);
612*6ba597c5SAnurag S. Maskey 		if (err != NWAM_SUCCESS) {
613*6ba597c5SAnurag S. Maskey 			nwam_known_wlan_free(kwh);
614*6ba597c5SAnurag S. Maskey 			return (err);
615*6ba597c5SAnurag S. Maskey 		}
616*6ba597c5SAnurag S. Maskey 		/* If BSSID is NULL, nothing more to do here. */
617*6ba597c5SAnurag S. Maskey 		if (bssid == NULL)
618*6ba597c5SAnurag S. Maskey 			break;
619*6ba597c5SAnurag S. Maskey 		if ((err = nwam_value_create_string((char *)bssid, &bssidsval))
620*6ba597c5SAnurag S. Maskey 		    != NWAM_SUCCESS) {
621*6ba597c5SAnurag S. Maskey 			nwam_known_wlan_free(kwh);
622*6ba597c5SAnurag S. Maskey 			return (err);
623*6ba597c5SAnurag S. Maskey 		}
624*6ba597c5SAnurag S. Maskey 		/* Set the bssids property */
625*6ba597c5SAnurag S. Maskey 		err = nwam_known_wlan_set_prop_value(kwh,
626*6ba597c5SAnurag S. Maskey 		    NWAM_KNOWN_WLAN_PROP_BSSIDS, bssidsval);
627*6ba597c5SAnurag S. Maskey 		nwam_value_free(bssidsval);
628*6ba597c5SAnurag S. Maskey 		if (err != NWAM_SUCCESS) {
629*6ba597c5SAnurag S. Maskey 			nwam_known_wlan_free(kwh);
630*6ba597c5SAnurag S. Maskey 			return (err);
631*6ba597c5SAnurag S. Maskey 		}
632*6ba597c5SAnurag S. Maskey 		break;
633*6ba597c5SAnurag S. Maskey 	case NWAM_SUCCESS:
634*6ba597c5SAnurag S. Maskey 		/* If no bssid is specified, nothing to do */
635*6ba597c5SAnurag S. Maskey 		if (bssid == NULL)
636*6ba597c5SAnurag S. Maskey 			break;
637*6ba597c5SAnurag S. Maskey 
638*6ba597c5SAnurag S. Maskey 		/* known WLAN exists, retrieve the existing bssids property */
639*6ba597c5SAnurag S. Maskey 		err = nwam_known_wlan_get_prop_value(kwh,
640*6ba597c5SAnurag S. Maskey 		    NWAM_KNOWN_WLAN_PROP_BSSIDS, &bssidsval);
641*6ba597c5SAnurag S. Maskey 		if (err != NWAM_SUCCESS && err != NWAM_ENTITY_NOT_FOUND) {
642*6ba597c5SAnurag S. Maskey 			nwam_known_wlan_free(kwh);
643*6ba597c5SAnurag S. Maskey 			return (err);
644*6ba597c5SAnurag S. Maskey 		}
645*6ba597c5SAnurag S. Maskey 		if (err == NWAM_SUCCESS) {
646*6ba597c5SAnurag S. Maskey 			if ((err = nwam_value_get_string_array(bssidsval,
647*6ba597c5SAnurag S. Maskey 			    &old_bssids, &nelem)) != NWAM_SUCCESS) {
648*6ba597c5SAnurag S. Maskey 				nwam_value_free(bssidsval);
649*6ba597c5SAnurag S. Maskey 				nwam_known_wlan_free(kwh);
650*6ba597c5SAnurag S. Maskey 				return (err);
651*6ba597c5SAnurag S. Maskey 			}
652*6ba597c5SAnurag S. Maskey 		}
653*6ba597c5SAnurag S. Maskey 		/* Create a new array to append given BSSID */
654*6ba597c5SAnurag S. Maskey 		new_bssids = calloc(nelem + 1, sizeof (char *));
655*6ba597c5SAnurag S. Maskey 		if (new_bssids == NULL) {
656*6ba597c5SAnurag S. Maskey 			nwam_value_free(bssidsval);
657*6ba597c5SAnurag S. Maskey 			nwam_known_wlan_free(kwh);
658*6ba597c5SAnurag S. Maskey 			return (NWAM_NO_MEMORY);
659*6ba597c5SAnurag S. Maskey 		}
660*6ba597c5SAnurag S. Maskey 
661*6ba597c5SAnurag S. Maskey 		/*
662*6ba597c5SAnurag S. Maskey 		 * Copy over existing BSSIDs to the new array.  Also, check
663*6ba597c5SAnurag S. Maskey 		 * to make sure that the given BSSID doesn't already exist
664*6ba597c5SAnurag S. Maskey 		 * in the known WLAN.  If so, do abort copying and return
665*6ba597c5SAnurag S. Maskey 		 * NWAM_SUCCESS.
666*6ba597c5SAnurag S. Maskey 		 */
667*6ba597c5SAnurag S. Maskey 		for (i = 0; i < nelem; i++) {
668*6ba597c5SAnurag S. Maskey 			if (strcmp(old_bssids[i], bssid) == 0) {
669*6ba597c5SAnurag S. Maskey 				/* nothing to do, so free up everything */
670*6ba597c5SAnurag S. Maskey 				for (j = 0; j < i; j++)
671*6ba597c5SAnurag S. Maskey 					free(new_bssids[j]);
672*6ba597c5SAnurag S. Maskey 				free(new_bssids);
673*6ba597c5SAnurag S. Maskey 				nwam_value_free(bssidsval);
674*6ba597c5SAnurag S. Maskey 				goto set_key_info;
675*6ba597c5SAnurag S. Maskey 			}
676*6ba597c5SAnurag S. Maskey 			new_bssids[i] = strdup(old_bssids[i]);
677*6ba597c5SAnurag S. Maskey 		}
678*6ba597c5SAnurag S. Maskey 		new_bssids[nelem] = strdup(bssid);
679*6ba597c5SAnurag S. Maskey 		nwam_value_free(bssidsval);
680*6ba597c5SAnurag S. Maskey 
681*6ba597c5SAnurag S. Maskey 		err = nwam_value_create_string_array(new_bssids, nelem + 1,
682*6ba597c5SAnurag S. Maskey 		    &bssidsval);
683*6ba597c5SAnurag S. Maskey 		for (i = 0; i < nelem + 1; i++)
684*6ba597c5SAnurag S. Maskey 			free(new_bssids[i]);
685*6ba597c5SAnurag S. Maskey 		free(new_bssids);
686*6ba597c5SAnurag S. Maskey 		if (err != NWAM_SUCCESS) {
687*6ba597c5SAnurag S. Maskey 			nwam_known_wlan_free(kwh);
688*6ba597c5SAnurag S. Maskey 			return (err);
689*6ba597c5SAnurag S. Maskey 		}
690*6ba597c5SAnurag S. Maskey 		/* Set the bssids property */
691*6ba597c5SAnurag S. Maskey 		err = nwam_known_wlan_set_prop_value(kwh,
692*6ba597c5SAnurag S. Maskey 		    NWAM_KNOWN_WLAN_PROP_BSSIDS, bssidsval);
693*6ba597c5SAnurag S. Maskey 		nwam_value_free(bssidsval);
694*6ba597c5SAnurag S. Maskey 		if (err != NWAM_SUCCESS) {
695*6ba597c5SAnurag S. Maskey 			nwam_known_wlan_free(kwh);
696*6ba597c5SAnurag S. Maskey 			return (err);
697*6ba597c5SAnurag S. Maskey 		}
698*6ba597c5SAnurag S. Maskey 		break;
699*6ba597c5SAnurag S. Maskey 	default:
700*6ba597c5SAnurag S. Maskey 		return (err);
701*6ba597c5SAnurag S. Maskey 	}
702*6ba597c5SAnurag S. Maskey 
703*6ba597c5SAnurag S. Maskey set_key_info:
704*6ba597c5SAnurag S. Maskey 	/* Set the security mode property */
705*6ba597c5SAnurag S. Maskey 	if ((err = nwam_value_create_uint64(secmode, &secmodeval))
706*6ba597c5SAnurag S. Maskey 	    != NWAM_SUCCESS) {
707*6ba597c5SAnurag S. Maskey 		nwam_known_wlan_free(kwh);
708*6ba597c5SAnurag S. Maskey 		return (err);
709*6ba597c5SAnurag S. Maskey 	}
710*6ba597c5SAnurag S. Maskey 	err = nwam_known_wlan_set_prop_value(kwh,
711*6ba597c5SAnurag S. Maskey 	    NWAM_KNOWN_WLAN_PROP_SECURITY_MODE, secmodeval);
712*6ba597c5SAnurag S. Maskey 	nwam_value_free(secmodeval);
713*6ba597c5SAnurag S. Maskey 
714*6ba597c5SAnurag S. Maskey 	if (err != NWAM_SUCCESS) {
715*6ba597c5SAnurag S. Maskey 		nwam_known_wlan_free(kwh);
716*6ba597c5SAnurag S. Maskey 		return (err);
717*6ba597c5SAnurag S. Maskey 	}
718*6ba597c5SAnurag S. Maskey 
719*6ba597c5SAnurag S. Maskey 	if (keyname != NULL) {
720*6ba597c5SAnurag S. Maskey 		if ((err = nwam_value_create_string((char *)keyname,
721*6ba597c5SAnurag S. Maskey 		    &keynameval)) != NWAM_SUCCESS) {
722*6ba597c5SAnurag S. Maskey 			nwam_known_wlan_free(kwh);
723*6ba597c5SAnurag S. Maskey 			return (err);
724*6ba597c5SAnurag S. Maskey 		}
725*6ba597c5SAnurag S. Maskey 		err = nwam_known_wlan_set_prop_value(kwh,
726*6ba597c5SAnurag S. Maskey 		    NWAM_KNOWN_WLAN_PROP_KEYNAME, keynameval);
727*6ba597c5SAnurag S. Maskey 		nwam_value_free(keynameval);
728*6ba597c5SAnurag S. Maskey 		if (err != NWAM_SUCCESS) {
729*6ba597c5SAnurag S. Maskey 			nwam_known_wlan_free(kwh);
730*6ba597c5SAnurag S. Maskey 			return (err);
731*6ba597c5SAnurag S. Maskey 		}
732*6ba597c5SAnurag S. Maskey 		if ((err = nwam_value_create_uint64(keyslot,
733*6ba597c5SAnurag S. Maskey 		    &keyslotval)) != NWAM_SUCCESS) {
734*6ba597c5SAnurag S. Maskey 			nwam_known_wlan_free(kwh);
735*6ba597c5SAnurag S. Maskey 			return (err);
736*6ba597c5SAnurag S. Maskey 		}
737*6ba597c5SAnurag S. Maskey 		err = nwam_known_wlan_set_prop_value(kwh,
738*6ba597c5SAnurag S. Maskey 		    NWAM_KNOWN_WLAN_PROP_KEYSLOT, keyslotval);
739*6ba597c5SAnurag S. Maskey 		nwam_value_free(keyslotval);
740*6ba597c5SAnurag S. Maskey 	}
741*6ba597c5SAnurag S. Maskey 
742*6ba597c5SAnurag S. Maskey 	err = nwam_known_wlan_commit(kwh, 0);
743*6ba597c5SAnurag S. Maskey 	nwam_known_wlan_free(kwh);
744*6ba597c5SAnurag S. Maskey 
745*6ba597c5SAnurag S. Maskey 	return (err);
746*6ba597c5SAnurag S. Maskey }
747*6ba597c5SAnurag S. Maskey 
748*6ba597c5SAnurag S. Maskey /*
749*6ba597c5SAnurag S. Maskey  * Remove the given BSSID/keyname from the bssids/keyname property for the
750*6ba597c5SAnurag S. Maskey  * given ESSID.
751*6ba597c5SAnurag S. Maskey  */
752*6ba597c5SAnurag S. Maskey nwam_error_t
nwam_known_wlan_remove_from_known_wlans(const char * essid,const char * bssid,const char * keyname)753*6ba597c5SAnurag S. Maskey nwam_known_wlan_remove_from_known_wlans(const char *essid, const char *bssid,
754*6ba597c5SAnurag S. Maskey     const char *keyname)
755*6ba597c5SAnurag S. Maskey {
756*6ba597c5SAnurag S. Maskey 	nwam_known_wlan_handle_t kwh;
757*6ba597c5SAnurag S. Maskey 	nwam_value_t bssidsval;
758*6ba597c5SAnurag S. Maskey 	char **old_bssids, **new_bssids;
759*6ba597c5SAnurag S. Maskey 	uint_t nelem;
760*6ba597c5SAnurag S. Maskey 	nwam_error_t err;
761*6ba597c5SAnurag S. Maskey 	int i, found = -1;
762*6ba597c5SAnurag S. Maskey 
763*6ba597c5SAnurag S. Maskey 	/* Retrieve the existing bssids */
764*6ba597c5SAnurag S. Maskey 	if ((err = nwam_known_wlan_read(essid, 0, &kwh)) != NWAM_SUCCESS)
765*6ba597c5SAnurag S. Maskey 		return (err);
766*6ba597c5SAnurag S. Maskey 	if ((err = nwam_known_wlan_get_prop_value(kwh,
767*6ba597c5SAnurag S. Maskey 	    NWAM_KNOWN_WLAN_PROP_BSSIDS, &bssidsval)) != NWAM_SUCCESS) {
768*6ba597c5SAnurag S. Maskey 		nwam_known_wlan_free(kwh);
769*6ba597c5SAnurag S. Maskey 		return (err);
770*6ba597c5SAnurag S. Maskey 	}
771*6ba597c5SAnurag S. Maskey 	if ((err = nwam_value_get_string_array(bssidsval, &old_bssids, &nelem))
772*6ba597c5SAnurag S. Maskey 	    != NWAM_SUCCESS) {
773*6ba597c5SAnurag S. Maskey 		nwam_value_free(bssidsval);
774*6ba597c5SAnurag S. Maskey 		nwam_known_wlan_free(kwh);
775*6ba597c5SAnurag S. Maskey 		return (err);
776*6ba597c5SAnurag S. Maskey 	}
777*6ba597c5SAnurag S. Maskey 
778*6ba597c5SAnurag S. Maskey 	/* Cycle through the BSSIDs array to find the BSSID to remove */
779*6ba597c5SAnurag S. Maskey 	for (i = 0; i < nelem; i++) {
780*6ba597c5SAnurag S. Maskey 		if (strcmp(old_bssids[i], bssid)  == 0) {
781*6ba597c5SAnurag S. Maskey 			found = i;
782*6ba597c5SAnurag S. Maskey 			break;
783*6ba597c5SAnurag S. Maskey 		}
784*6ba597c5SAnurag S. Maskey 	}
785*6ba597c5SAnurag S. Maskey 
786*6ba597c5SAnurag S. Maskey 	/* Given BSSID was not found in the array */
787*6ba597c5SAnurag S. Maskey 	if (found == -1) {
788*6ba597c5SAnurag S. Maskey 		nwam_value_free(bssidsval);
789*6ba597c5SAnurag S. Maskey 		nwam_known_wlan_free(kwh);
790*6ba597c5SAnurag S. Maskey 		return (NWAM_INVALID_ARG);
791*6ba597c5SAnurag S. Maskey 	}
792*6ba597c5SAnurag S. Maskey 
793*6ba597c5SAnurag S. Maskey 	/* If removing the only BSSID entry, remove the bssids property */
794*6ba597c5SAnurag S. Maskey 	if (nelem == 1) {
795*6ba597c5SAnurag S. Maskey 		nwam_value_free(bssidsval);
796*6ba597c5SAnurag S. Maskey 		if ((err = nwam_known_wlan_delete_prop(kwh,
797*6ba597c5SAnurag S. Maskey 		    NWAM_KNOWN_WLAN_PROP_BSSIDS)) != NWAM_SUCCESS) {
798*6ba597c5SAnurag S. Maskey 			nwam_known_wlan_free(kwh);
799*6ba597c5SAnurag S. Maskey 			return (err);
800*6ba597c5SAnurag S. Maskey 		}
801*6ba597c5SAnurag S. Maskey 		err = nwam_known_wlan_commit(kwh, 0);
802*6ba597c5SAnurag S. Maskey 		nwam_known_wlan_free(kwh);
803*6ba597c5SAnurag S. Maskey 		return (err);
804*6ba597c5SAnurag S. Maskey 	}
805*6ba597c5SAnurag S. Maskey 
806*6ba597c5SAnurag S. Maskey 	new_bssids = calloc(nelem - 1, sizeof (char *));
807*6ba597c5SAnurag S. Maskey 	if (new_bssids == NULL) {
808*6ba597c5SAnurag S. Maskey 		nwam_value_free(bssidsval);
809*6ba597c5SAnurag S. Maskey 		nwam_known_wlan_free(kwh);
810*6ba597c5SAnurag S. Maskey 		return (NWAM_NO_MEMORY);
811*6ba597c5SAnurag S. Maskey 	}
812*6ba597c5SAnurag S. Maskey 
813*6ba597c5SAnurag S. Maskey 	/* Copy over other BSSIDs */
814*6ba597c5SAnurag S. Maskey 	for (i = 0; i < found; i++)
815*6ba597c5SAnurag S. Maskey 		new_bssids[i] = strdup(old_bssids[i]);
816*6ba597c5SAnurag S. Maskey 	for (i = found + 1; i < nelem; i++)
817*6ba597c5SAnurag S. Maskey 		new_bssids[i-1] = strdup(old_bssids[i]);
818*6ba597c5SAnurag S. Maskey 	nwam_value_free(bssidsval);
819*6ba597c5SAnurag S. Maskey 
820*6ba597c5SAnurag S. Maskey 	err = nwam_value_create_string_array(new_bssids, nelem - 1, &bssidsval);
821*6ba597c5SAnurag S. Maskey 	for (i = 0; i < nelem - 1; i++)
822*6ba597c5SAnurag S. Maskey 		free(new_bssids[i]);
823*6ba597c5SAnurag S. Maskey 	free(new_bssids);
824*6ba597c5SAnurag S. Maskey 	if (err != NWAM_SUCCESS) {
825*6ba597c5SAnurag S. Maskey 		nwam_known_wlan_free(kwh);
826*6ba597c5SAnurag S. Maskey 		return (err);
827*6ba597c5SAnurag S. Maskey 	}
828*6ba597c5SAnurag S. Maskey 
829*6ba597c5SAnurag S. Maskey 	/* Set the bssids property */
830*6ba597c5SAnurag S. Maskey 	err = nwam_known_wlan_set_prop_value(kwh, NWAM_KNOWN_WLAN_PROP_BSSIDS,
831*6ba597c5SAnurag S. Maskey 	    bssidsval);
832*6ba597c5SAnurag S. Maskey 	nwam_value_free(bssidsval);
833*6ba597c5SAnurag S. Maskey 	if (err != NWAM_SUCCESS) {
834*6ba597c5SAnurag S. Maskey 		nwam_known_wlan_free(kwh);
835*6ba597c5SAnurag S. Maskey 		return (err);
836*6ba597c5SAnurag S. Maskey 	}
837*6ba597c5SAnurag S. Maskey 
838*6ba597c5SAnurag S. Maskey 	if (keyname != NULL) {
839*6ba597c5SAnurag S. Maskey 		if ((err = nwam_known_wlan_delete_prop(kwh,
840*6ba597c5SAnurag S. Maskey 		    NWAM_KNOWN_WLAN_PROP_KEYNAME)) != NWAM_SUCCESS) {
841*6ba597c5SAnurag S. Maskey 			nwam_known_wlan_free(kwh);
842*6ba597c5SAnurag S. Maskey 			return (err);
843*6ba597c5SAnurag S. Maskey 		}
844*6ba597c5SAnurag S. Maskey 		if ((err = nwam_known_wlan_delete_prop(kwh,
845*6ba597c5SAnurag S. Maskey 		    NWAM_KNOWN_WLAN_PROP_KEYSLOT)) != NWAM_SUCCESS) {
846*6ba597c5SAnurag S. Maskey 			nwam_known_wlan_free(kwh);
847*6ba597c5SAnurag S. Maskey 			return (err);
848*6ba597c5SAnurag S. Maskey 		}
849*6ba597c5SAnurag S. Maskey 	}
850*6ba597c5SAnurag S. Maskey 
851*6ba597c5SAnurag S. Maskey 	err = nwam_known_wlan_commit(kwh, 0);
852*6ba597c5SAnurag S. Maskey 	nwam_known_wlan_free(kwh);
853*6ba597c5SAnurag S. Maskey 
854*6ba597c5SAnurag S. Maskey 	return (err);
855*6ba597c5SAnurag S. Maskey }
856