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