Unleashed v1.4
[unleashed.git] / usr / src / lib / libnwam / common / libnwam_known_wlan.c
blobf182fdba76c54e8947f62f674e41ea9ff21fc6ae
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 = reallocarray(list, ++num_wlans,
173 sizeof (struct nwam_wlan_info *))) == NULL ||
174 (newlist[num_wlans - 1] = calloc(1,
175 sizeof (struct nwam_wlan_info))) == NULL) {
176 free(newlist);
177 return (NWAM_NO_MEMORY);
180 /* Update list since realloc() may have relocated it */
181 wil->list = newlist;
183 /* Retrieve name/priority */
184 if ((err = nwam_known_wlan_get_name(kwh,
185 &((newlist[num_wlans - 1])->wlan_name))) != NWAM_SUCCESS ||
186 (err = nwam_known_wlan_get_prop_value(kwh,
187 NWAM_KNOWN_WLAN_PROP_PRIORITY, &priorityval)) != NWAM_SUCCESS ||
188 (err = nwam_value_get_uint64(priorityval,
189 &((newlist[num_wlans - 1])->wlan_priority))) != NWAM_SUCCESS) {
190 free(newlist[num_wlans - 1]->wlan_name);
191 nwam_value_free(priorityval);
192 free(newlist[num_wlans - 1]);
193 return (err);
195 nwam_value_free(priorityval);
197 (newlist[num_wlans - 1])->wlan_walked = B_FALSE;
199 wil->num_wlans = num_wlans;
201 return (NWAM_SUCCESS);
205 * Some recursion is required here, since if _WALK_PRIORITY_ORDER is specified,
206 * we need to first walk the list of known WLANs to retrieve names
207 * and priorities, then utilize that list to carry out an in-order walk.
209 nwam_error_t
210 nwam_walk_known_wlans(int(*cb)(nwam_known_wlan_handle_t, void *), void *data,
211 uint64_t flags, int *retp)
213 nwam_known_wlan_handle_t kwh;
214 nwam_error_t err;
215 int ret = 0;
217 assert(cb != NULL);
219 if ((err = nwam_valid_flags(flags,
220 NWAM_FLAG_KNOWN_WLAN_WALK_PRIORITY_ORDER | NWAM_FLAG_BLOCKING))
221 != NWAM_SUCCESS)
222 return (err);
224 if ((flags & NWAM_FLAG_KNOWN_WLAN_WALK_PRIORITY_ORDER) != 0) {
225 struct nwam_wlan_info_list wil = { NULL, 0};
226 uint64_t iflags = flags &~
227 NWAM_FLAG_KNOWN_WLAN_WALK_PRIORITY_ORDER;
228 uint64_t minpriority;
229 int errval, i, j, minindex;
231 if (nwam_walk_known_wlans(get_wlans_cb, &wil, iflags, &errval)
232 != NWAM_SUCCESS) {
233 err = (nwam_error_t)errval;
234 goto done;
237 err = NWAM_SUCCESS;
239 for (i = 0; i < wil.num_wlans; i++) {
240 /* Find lowest priority value not walked so far. */
241 minpriority = (uint64_t)-1;
242 for (j = 0; j < wil.num_wlans; j++) {
243 if (wil.list[j]->wlan_priority < minpriority &&
244 !(wil.list[j]->wlan_walked)) {
245 minpriority =
246 wil.list[j]->wlan_priority;
247 minindex = j;
250 wil.list[minindex]->wlan_walked = B_TRUE;
251 if ((err = nwam_known_wlan_read
252 (wil.list[minindex]->wlan_name,
253 iflags, &kwh)) != NWAM_SUCCESS) {
254 goto done;
256 ret = cb(kwh, data);
257 if (ret != 0) {
258 nwam_known_wlan_free(kwh);
259 err = NWAM_WALK_HALTED;
260 goto done;
262 nwam_known_wlan_free(kwh);
264 done:
265 if (wil.list != NULL) {
266 for (j = 0; j < wil.num_wlans; j++) {
267 free(wil.list[j]->wlan_name);
268 free(wil.list[j]);
270 free(wil.list);
272 if (retp != NULL)
273 *retp = ret;
274 return (err);
277 return (nwam_walk(NWAM_OBJECT_TYPE_KNOWN_WLAN,
278 NWAM_KNOWN_WLAN_CONF_FILE, cb, data, flags, retp, NULL));
281 void
282 nwam_known_wlan_free(nwam_known_wlan_handle_t kwh)
284 nwam_free(kwh);
287 nwam_error_t
288 nwam_known_wlan_copy(nwam_known_wlan_handle_t oldkwh, const char *newname,
289 nwam_known_wlan_handle_t *newkwhp)
291 return (nwam_copy(NWAM_KNOWN_WLAN_CONF_FILE, oldkwh, newname, newkwhp));
294 nwam_error_t
295 nwam_known_wlan_delete_prop(nwam_known_wlan_handle_t kwh, const char *propname)
297 nwam_error_t err;
298 void *olddata;
300 assert(kwh != NULL && propname != NULL);
303 * Duplicate data, remove property and validate. If validation
304 * fails, revert to data duplicated prior to remove.
306 if ((err = nwam_dup_object_list(kwh->nwh_data, &olddata))
307 != NWAM_SUCCESS)
308 return (err);
309 if ((err = nwam_delete_prop(kwh->nwh_data, propname)) != NWAM_SUCCESS) {
310 nwam_free_object_list(kwh->nwh_data);
311 kwh->nwh_data = olddata;
312 return (err);
314 if ((err = nwam_known_wlan_validate(kwh, NULL)) != NWAM_SUCCESS) {
315 nwam_free_object_list(kwh->nwh_data);
316 kwh->nwh_data = olddata;
317 return (err);
319 nwam_free_object_list(olddata);
321 return (NWAM_SUCCESS);
324 nwam_error_t
325 nwam_known_wlan_set_prop_value(nwam_known_wlan_handle_t kwh,
326 const char *propname, nwam_value_t value)
328 nwam_error_t err;
330 assert(kwh != NULL && propname != NULL && value != NULL);
332 if ((err = nwam_known_wlan_validate_prop(kwh, propname, value))
333 != NWAM_SUCCESS)
334 return (err);
336 return (nwam_set_prop_value(kwh->nwh_data, propname, value));
339 nwam_error_t
340 nwam_known_wlan_get_prop_value(nwam_known_wlan_handle_t kwh,
341 const char *propname, nwam_value_t *valuep)
343 return (nwam_get_prop_value(kwh->nwh_data, propname, valuep));
346 nwam_error_t
347 nwam_known_wlan_walk_props(nwam_known_wlan_handle_t kwh,
348 int (*cb)(const char *, nwam_value_t, void *),
349 void *data, uint64_t flags, int *retp)
351 return (nwam_walk_props(kwh, cb, data, flags, retp));
354 struct priority_collision_data {
355 char *wlan_name;
356 uint64_t priority;
359 static int
360 avoid_priority_collisions_cb(nwam_known_wlan_handle_t kwh, void *data)
362 nwam_value_t priorityval;
363 nwam_error_t err;
364 struct priority_collision_data *pcd = data;
365 char *name;
366 uint64_t priority;
368 err = nwam_known_wlan_get_name(kwh, &name);
369 if (err != NWAM_SUCCESS)
370 return (err);
371 if (strcmp(name, pcd->wlan_name) == 0) {
372 /* skip to-be-updated wlan */
373 free(name);
374 return (NWAM_SUCCESS);
376 free(name);
378 err = nwam_known_wlan_get_prop_value(kwh, NWAM_KNOWN_WLAN_PROP_PRIORITY,
379 &priorityval);
380 if (err != NWAM_SUCCESS)
381 return (err);
382 err = nwam_value_get_uint64(priorityval, &priority);
383 if (err != NWAM_SUCCESS)
384 return (err);
385 nwam_value_free(priorityval);
387 if (priority < pcd->priority)
388 return (NWAM_SUCCESS);
390 if (priority == pcd->priority) {
391 /* Two priority values collide. Move this one up. */
392 err = nwam_value_create_uint64(priority + 1, &priorityval);
393 if (err != NWAM_SUCCESS)
394 return (err);
395 err = nwam_known_wlan_set_prop_value(kwh,
396 NWAM_KNOWN_WLAN_PROP_PRIORITY, priorityval);
397 nwam_value_free(priorityval);
398 if (err != NWAM_SUCCESS) {
399 return (err);
402 * We are doing a walk, and will continue shifting until
403 * we find a gap in the priority numbers; thus no need to
404 * do collision checking here.
406 err = nwam_known_wlan_commit(kwh,
407 NWAM_FLAG_KNOWN_WLAN_NO_COLLISION_CHECK);
408 if (err != NWAM_SUCCESS)
409 return (err);
411 (pcd->priority)++;
412 return (NWAM_SUCCESS);
416 * Only possiblity left at this point is that we're looking
417 * at a priority greater than the last one we wrote, so we've
418 * found a gap. We can halt the walk now.
420 return (NWAM_WALK_HALTED);
423 nwam_error_t
424 nwam_known_wlan_commit(nwam_known_wlan_handle_t kwh, uint64_t flags)
426 nwam_error_t err;
427 nwam_value_t priorityval;
428 int ret = 0;
429 struct priority_collision_data pcd;
431 assert(kwh != NULL && kwh->nwh_data != NULL);
433 if ((err = nwam_known_wlan_validate(kwh, NULL)) != NWAM_SUCCESS)
434 return (err);
437 * If the NO_COLLISION_CHECK flag is set, no need to check for
438 * collision.
440 if (flags & NWAM_FLAG_KNOWN_WLAN_NO_COLLISION_CHECK)
441 return (nwam_commit(NWAM_KNOWN_WLAN_CONF_FILE, kwh,
442 (flags & NWAM_FLAG_GLOBAL_MASK) |
443 NWAM_FLAG_ENTITY_KNOWN_WLAN));
446 * We need to do priority checking. Walk the list, looking
447 * for the first entry with priority greater than or equal
448 * to the entry we're adding. Commit the new one (without
449 * doing additional checking), and then increment other
450 * entries as needed.
452 err = nwam_known_wlan_get_prop_value(kwh,
453 NWAM_KNOWN_WLAN_PROP_PRIORITY, &priorityval);
454 if (err != NWAM_SUCCESS)
455 return (err);
456 err = nwam_value_get_uint64(priorityval, &(pcd.priority));
457 nwam_value_free(priorityval);
458 if (err != NWAM_SUCCESS)
459 return (err);
460 err = nwam_known_wlan_get_name(kwh, &(pcd.wlan_name));
461 if (err != NWAM_SUCCESS)
462 return (err);
463 err = nwam_walk_known_wlans(avoid_priority_collisions_cb, &pcd,
464 NWAM_FLAG_KNOWN_WLAN_WALK_PRIORITY_ORDER, &ret);
465 free(pcd.wlan_name);
467 * a halted walk is okay, it just means we didn't have
468 * to walk the entire list to resolve priorities
470 if (ret != NWAM_SUCCESS && ret != NWAM_WALK_HALTED)
471 return (ret);
473 return (nwam_known_wlan_commit(kwh,
474 flags | NWAM_FLAG_KNOWN_WLAN_NO_COLLISION_CHECK));
477 nwam_error_t
478 nwam_known_wlan_destroy(nwam_known_wlan_handle_t kwh, uint64_t flags)
480 return (nwam_destroy(NWAM_KNOWN_WLAN_CONF_FILE, kwh,
481 flags | NWAM_FLAG_ENTITY_KNOWN_WLAN));
484 nwam_error_t
485 nwam_known_wlan_get_prop_description(const char *propname,
486 const char **descriptionp)
488 return (nwam_get_prop_description(known_wlan_prop_table, propname,
489 descriptionp));
492 /* Property-specific value validation functions should go here. */
494 static nwam_error_t
495 valid_keyname(nwam_value_t value)
497 char *keyname;
499 if (nwam_value_get_string(value, &keyname) != NWAM_SUCCESS)
500 return (NWAM_ENTITY_INVALID_VALUE);
502 if (!dladm_valid_secobj_name(keyname))
503 return (NWAM_ENTITY_INVALID_VALUE);
505 return (NWAM_SUCCESS);
508 static nwam_error_t
509 valid_keyslot(nwam_value_t value)
511 uint64_t keyslot;
513 if (nwam_value_get_uint64(value, &keyslot) != NWAM_SUCCESS)
514 return (NWAM_ENTITY_INVALID_VALUE);
516 if (keyslot < 1 || keyslot > 4)
517 return (NWAM_ENTITY_INVALID_VALUE);
519 return (NWAM_SUCCESS);
522 static nwam_error_t
523 valid_secmode(nwam_value_t value)
525 uint64_t secmode;
527 if (nwam_value_get_uint64(value, &secmode) != NWAM_SUCCESS)
528 return (NWAM_ENTITY_INVALID_VALUE);
530 if (secmode != DLADM_WLAN_SECMODE_NONE &&
531 secmode != DLADM_WLAN_SECMODE_WEP &&
532 secmode != DLADM_WLAN_SECMODE_WPA)
533 return (NWAM_ENTITY_INVALID_VALUE);
535 return (NWAM_SUCCESS);
538 nwam_error_t
539 nwam_known_wlan_validate(nwam_known_wlan_handle_t kwh, const char **errpropp)
541 return (nwam_validate(known_wlan_prop_table, kwh, errpropp));
544 nwam_error_t
545 nwam_known_wlan_validate_prop(nwam_known_wlan_handle_t kwh,
546 const char *propname, nwam_value_t value)
548 return (nwam_validate_prop(known_wlan_prop_table, kwh, propname,
549 value));
553 * Given a property, return expected property data type
555 nwam_error_t
556 nwam_known_wlan_get_prop_type(const char *propname, nwam_value_type_t *typep)
558 return (nwam_get_prop_type(known_wlan_prop_table, propname, typep));
561 nwam_error_t
562 nwam_known_wlan_prop_multivalued(const char *propname, boolean_t *multip)
564 return (nwam_prop_multivalued(known_wlan_prop_table, propname, multip));
567 nwam_error_t
568 nwam_known_wlan_get_default_proplist(const char ***prop_list,
569 uint_t *numvaluesp)
571 return (nwam_get_default_proplist(known_wlan_prop_table,
572 NWAM_TYPE_ANY, NWAM_CLASS_ANY, prop_list, numvaluesp));
576 * Add the given ESSID, BSSID, secmode, keyslot and key name to known WLANs.
577 * BSSID and keyname can be NULL.
579 nwam_error_t
580 nwam_known_wlan_add_to_known_wlans(const char *essid, const char *bssid,
581 uint32_t secmode, uint_t keyslot, const char *keyname)
583 nwam_known_wlan_handle_t kwh;
584 nwam_value_t keynameval = NULL, keyslotval = NULL, bssidsval = NULL;
585 nwam_value_t secmodeval = NULL, priorityval = NULL;
586 char **old_bssids = NULL, **new_bssids;
587 uint_t nelem = 0;
588 nwam_error_t err;
589 int i, j;
592 * Check if the given ESSID already exists as known WLAN. If so,
593 * add the BSSID to the bssids property. If not, create one with
594 * the given ESSID and add BSSID if given.
596 err = nwam_known_wlan_read(essid, 0, &kwh);
598 switch (err) {
599 case NWAM_ENTITY_NOT_FOUND:
600 if ((err = nwam_known_wlan_create(essid, &kwh)) != NWAM_SUCCESS)
601 return (err);
602 /* New known WLAN - set priority to 0 */
603 if ((err = nwam_value_create_uint64(0, &priorityval))
604 != NWAM_SUCCESS) {
605 nwam_known_wlan_free(kwh);
606 return (err);
608 err = nwam_known_wlan_set_prop_value(kwh,
609 NWAM_KNOWN_WLAN_PROP_PRIORITY, priorityval);
610 nwam_value_free(priorityval);
611 if (err != NWAM_SUCCESS) {
612 nwam_known_wlan_free(kwh);
613 return (err);
615 /* If BSSID is NULL, nothing more to do here. */
616 if (bssid == NULL)
617 break;
618 if ((err = nwam_value_create_string((char *)bssid, &bssidsval))
619 != NWAM_SUCCESS) {
620 nwam_known_wlan_free(kwh);
621 return (err);
623 /* Set the bssids property */
624 err = nwam_known_wlan_set_prop_value(kwh,
625 NWAM_KNOWN_WLAN_PROP_BSSIDS, bssidsval);
626 nwam_value_free(bssidsval);
627 if (err != NWAM_SUCCESS) {
628 nwam_known_wlan_free(kwh);
629 return (err);
631 break;
632 case NWAM_SUCCESS:
633 /* If no bssid is specified, nothing to do */
634 if (bssid == NULL)
635 break;
637 /* known WLAN exists, retrieve the existing bssids property */
638 err = nwam_known_wlan_get_prop_value(kwh,
639 NWAM_KNOWN_WLAN_PROP_BSSIDS, &bssidsval);
640 if (err != NWAM_SUCCESS && err != NWAM_ENTITY_NOT_FOUND) {
641 nwam_known_wlan_free(kwh);
642 return (err);
644 if (err == NWAM_SUCCESS) {
645 if ((err = nwam_value_get_string_array(bssidsval,
646 &old_bssids, &nelem)) != NWAM_SUCCESS) {
647 nwam_value_free(bssidsval);
648 nwam_known_wlan_free(kwh);
649 return (err);
652 /* Create a new array to append given BSSID */
653 new_bssids = calloc(nelem + 1, sizeof (char *));
654 if (new_bssids == NULL) {
655 nwam_value_free(bssidsval);
656 nwam_known_wlan_free(kwh);
657 return (NWAM_NO_MEMORY);
661 * Copy over existing BSSIDs to the new array. Also, check
662 * to make sure that the given BSSID doesn't already exist
663 * in the known WLAN. If so, do abort copying and return
664 * NWAM_SUCCESS.
666 for (i = 0; i < nelem; i++) {
667 if (strcmp(old_bssids[i], bssid) == 0) {
668 /* nothing to do, so free up everything */
669 for (j = 0; j < i; j++)
670 free(new_bssids[j]);
671 free(new_bssids);
672 nwam_value_free(bssidsval);
673 goto set_key_info;
675 new_bssids[i] = strdup(old_bssids[i]);
677 new_bssids[nelem] = strdup(bssid);
678 nwam_value_free(bssidsval);
680 err = nwam_value_create_string_array(new_bssids, nelem + 1,
681 &bssidsval);
682 for (i = 0; i < nelem + 1; i++)
683 free(new_bssids[i]);
684 free(new_bssids);
685 if (err != NWAM_SUCCESS) {
686 nwam_known_wlan_free(kwh);
687 return (err);
689 /* Set the bssids property */
690 err = nwam_known_wlan_set_prop_value(kwh,
691 NWAM_KNOWN_WLAN_PROP_BSSIDS, bssidsval);
692 nwam_value_free(bssidsval);
693 if (err != NWAM_SUCCESS) {
694 nwam_known_wlan_free(kwh);
695 return (err);
697 break;
698 default:
699 return (err);
702 set_key_info:
703 /* Set the security mode property */
704 if ((err = nwam_value_create_uint64(secmode, &secmodeval))
705 != NWAM_SUCCESS) {
706 nwam_known_wlan_free(kwh);
707 return (err);
709 err = nwam_known_wlan_set_prop_value(kwh,
710 NWAM_KNOWN_WLAN_PROP_SECURITY_MODE, secmodeval);
711 nwam_value_free(secmodeval);
713 if (err != NWAM_SUCCESS) {
714 nwam_known_wlan_free(kwh);
715 return (err);
718 if (keyname != NULL) {
719 if ((err = nwam_value_create_string((char *)keyname,
720 &keynameval)) != NWAM_SUCCESS) {
721 nwam_known_wlan_free(kwh);
722 return (err);
724 err = nwam_known_wlan_set_prop_value(kwh,
725 NWAM_KNOWN_WLAN_PROP_KEYNAME, keynameval);
726 nwam_value_free(keynameval);
727 if (err != NWAM_SUCCESS) {
728 nwam_known_wlan_free(kwh);
729 return (err);
731 if ((err = nwam_value_create_uint64(keyslot,
732 &keyslotval)) != NWAM_SUCCESS) {
733 nwam_known_wlan_free(kwh);
734 return (err);
736 err = nwam_known_wlan_set_prop_value(kwh,
737 NWAM_KNOWN_WLAN_PROP_KEYSLOT, keyslotval);
738 nwam_value_free(keyslotval);
741 err = nwam_known_wlan_commit(kwh, 0);
742 nwam_known_wlan_free(kwh);
744 return (err);
748 * Remove the given BSSID/keyname from the bssids/keyname property for the
749 * given ESSID.
751 nwam_error_t
752 nwam_known_wlan_remove_from_known_wlans(const char *essid, const char *bssid,
753 const char *keyname)
755 nwam_known_wlan_handle_t kwh;
756 nwam_value_t bssidsval;
757 char **old_bssids, **new_bssids;
758 uint_t nelem;
759 nwam_error_t err;
760 int i, found = -1;
762 /* Retrieve the existing bssids */
763 if ((err = nwam_known_wlan_read(essid, 0, &kwh)) != NWAM_SUCCESS)
764 return (err);
765 if ((err = nwam_known_wlan_get_prop_value(kwh,
766 NWAM_KNOWN_WLAN_PROP_BSSIDS, &bssidsval)) != NWAM_SUCCESS) {
767 nwam_known_wlan_free(kwh);
768 return (err);
770 if ((err = nwam_value_get_string_array(bssidsval, &old_bssids, &nelem))
771 != NWAM_SUCCESS) {
772 nwam_value_free(bssidsval);
773 nwam_known_wlan_free(kwh);
774 return (err);
777 /* Cycle through the BSSIDs array to find the BSSID to remove */
778 for (i = 0; i < nelem; i++) {
779 if (strcmp(old_bssids[i], bssid) == 0) {
780 found = i;
781 break;
785 /* Given BSSID was not found in the array */
786 if (found == -1) {
787 nwam_value_free(bssidsval);
788 nwam_known_wlan_free(kwh);
789 return (NWAM_INVALID_ARG);
792 /* If removing the only BSSID entry, remove the bssids property */
793 if (nelem == 1) {
794 nwam_value_free(bssidsval);
795 if ((err = nwam_known_wlan_delete_prop(kwh,
796 NWAM_KNOWN_WLAN_PROP_BSSIDS)) != NWAM_SUCCESS) {
797 nwam_known_wlan_free(kwh);
798 return (err);
800 err = nwam_known_wlan_commit(kwh, 0);
801 nwam_known_wlan_free(kwh);
802 return (err);
805 new_bssids = calloc(nelem - 1, sizeof (char *));
806 if (new_bssids == NULL) {
807 nwam_value_free(bssidsval);
808 nwam_known_wlan_free(kwh);
809 return (NWAM_NO_MEMORY);
812 /* Copy over other BSSIDs */
813 for (i = 0; i < found; i++)
814 new_bssids[i] = strdup(old_bssids[i]);
815 for (i = found + 1; i < nelem; i++)
816 new_bssids[i-1] = strdup(old_bssids[i]);
817 nwam_value_free(bssidsval);
819 err = nwam_value_create_string_array(new_bssids, nelem - 1, &bssidsval);
820 for (i = 0; i < nelem - 1; i++)
821 free(new_bssids[i]);
822 free(new_bssids);
823 if (err != NWAM_SUCCESS) {
824 nwam_known_wlan_free(kwh);
825 return (err);
828 /* Set the bssids property */
829 err = nwam_known_wlan_set_prop_value(kwh, NWAM_KNOWN_WLAN_PROP_BSSIDS,
830 bssidsval);
831 nwam_value_free(bssidsval);
832 if (err != NWAM_SUCCESS) {
833 nwam_known_wlan_free(kwh);
834 return (err);
837 if (keyname != NULL) {
838 if ((err = nwam_known_wlan_delete_prop(kwh,
839 NWAM_KNOWN_WLAN_PROP_KEYNAME)) != NWAM_SUCCESS) {
840 nwam_known_wlan_free(kwh);
841 return (err);
843 if ((err = nwam_known_wlan_delete_prop(kwh,
844 NWAM_KNOWN_WLAN_PROP_KEYSLOT)) != NWAM_SUCCESS) {
845 nwam_known_wlan_free(kwh);
846 return (err);
850 err = nwam_known_wlan_commit(kwh, 0);
851 nwam_known_wlan_free(kwh);
853 return (err);