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