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]
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
29 #include <sys/param.h>
30 #include <sys/types.h>
36 #include <libdllink.h>
37 #include <libdlwlan.h>
39 #include "libnwam_impl.h"
40 #include <libnwam_priv.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
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 "
63 NWAM_TYPE_ANY
, NWAM_CLASS_ANY
},
64 {NWAM_KNOWN_WLAN_PROP_KEYNAME
, NWAM_VALUE_TYPE_STRING
, B_FALSE
,
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
,
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
,
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
};
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
));
94 nwam_known_wlan_create(const char *name
, nwam_known_wlan_handle_t
*kwhp
)
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
)
106 * Create new object list for known WLAN. The initial priority is
109 if ((err
= nwam_alloc_object_list(&((*kwhp
)->nwh_data
)))
112 if ((err
= nwam_value_create_uint64(0, &priorityval
)) != NWAM_SUCCESS
)
114 err
= nwam_set_prop_value((*kwhp
)->nwh_data
,
115 NWAM_KNOWN_WLAN_PROP_PRIORITY
, priorityval
);
118 nwam_value_free(priorityval
);
119 if (err
!= NWAM_SUCCESS
) {
120 nwam_known_wlan_free(*kwhp
);
127 nwam_known_wlan_get_name(nwam_known_wlan_handle_t kwh
, char **namep
)
129 return (nwam_get_name(kwh
, namep
));
133 nwam_known_wlan_set_name(nwam_known_wlan_handle_t kwh
, const char *name
)
135 return (nwam_set_name(kwh
, name
));
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
{
149 uint64_t wlan_priority
;
150 boolean_t wlan_walked
;
153 struct nwam_wlan_info_list
{
154 struct nwam_wlan_info
**list
;
159 * Used to read in each known WLAN name/priority.
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
;
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
) {
178 return (NWAM_NO_MEMORY
);
181 /* Update list since realloc() may have relocated it */
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]);
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.
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
;
220 if ((err
= nwam_valid_flags(flags
,
221 NWAM_FLAG_KNOWN_WLAN_WALK_PRIORITY_ORDER
| NWAM_FLAG_BLOCKING
))
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
)
234 err
= (nwam_error_t
)errval
;
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
)) {
247 wil
.list
[j
]->wlan_priority
;
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
) {
259 nwam_known_wlan_free(kwh
);
260 err
= NWAM_WALK_HALTED
;
263 nwam_known_wlan_free(kwh
);
266 if (wil
.list
!= NULL
) {
267 for (j
= 0; j
< wil
.num_wlans
; j
++) {
268 free(wil
.list
[j
]->wlan_name
);
278 return (nwam_walk(NWAM_OBJECT_TYPE_KNOWN_WLAN
,
279 NWAM_KNOWN_WLAN_CONF_FILE
, cb
, data
, flags
, retp
, NULL
));
283 nwam_known_wlan_free(nwam_known_wlan_handle_t kwh
)
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
));
296 nwam_known_wlan_delete_prop(nwam_known_wlan_handle_t kwh
, const char *propname
)
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
))
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
;
315 if ((err
= nwam_known_wlan_validate(kwh
, NULL
)) != NWAM_SUCCESS
) {
316 nwam_free_object_list(kwh
->nwh_data
);
317 kwh
->nwh_data
= olddata
;
320 nwam_free_object_list(olddata
);
322 return (NWAM_SUCCESS
);
326 nwam_known_wlan_set_prop_value(nwam_known_wlan_handle_t kwh
,
327 const char *propname
, nwam_value_t value
)
331 assert(kwh
!= NULL
&& propname
!= NULL
&& value
!= NULL
);
333 if ((err
= nwam_known_wlan_validate_prop(kwh
, propname
, value
))
337 return (nwam_set_prop_value(kwh
->nwh_data
, propname
, value
));
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
));
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
{
361 avoid_priority_collisions_cb(nwam_known_wlan_handle_t kwh
, void *data
)
363 nwam_value_t priorityval
;
365 struct priority_collision_data
*pcd
= data
;
369 err
= nwam_known_wlan_get_name(kwh
, &name
);
370 if (err
!= NWAM_SUCCESS
)
372 if (strcmp(name
, pcd
->wlan_name
) == 0) {
373 /* skip to-be-updated wlan */
375 return (NWAM_SUCCESS
);
379 err
= nwam_known_wlan_get_prop_value(kwh
, NWAM_KNOWN_WLAN_PROP_PRIORITY
,
381 if (err
!= NWAM_SUCCESS
)
383 err
= nwam_value_get_uint64(priorityval
, &priority
);
384 if (err
!= NWAM_SUCCESS
)
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
)
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
) {
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
)
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
);
425 nwam_known_wlan_commit(nwam_known_wlan_handle_t kwh
, uint64_t flags
)
428 nwam_value_t priorityval
;
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
)
438 * If the NO_COLLISION_CHECK flag is set, no need to check for
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
453 err
= nwam_known_wlan_get_prop_value(kwh
,
454 NWAM_KNOWN_WLAN_PROP_PRIORITY
, &priorityval
);
455 if (err
!= NWAM_SUCCESS
)
457 err
= nwam_value_get_uint64(priorityval
, &(pcd
.priority
));
458 nwam_value_free(priorityval
);
459 if (err
!= NWAM_SUCCESS
)
461 err
= nwam_known_wlan_get_name(kwh
, &(pcd
.wlan_name
));
462 if (err
!= NWAM_SUCCESS
)
464 err
= nwam_walk_known_wlans(avoid_priority_collisions_cb
, &pcd
,
465 NWAM_FLAG_KNOWN_WLAN_WALK_PRIORITY_ORDER
, &ret
);
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
)
474 return (nwam_known_wlan_commit(kwh
,
475 flags
| NWAM_FLAG_KNOWN_WLAN_NO_COLLISION_CHECK
));
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
));
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
,
493 /* Property-specific value validation functions should go here. */
496 valid_keyname(nwam_value_t value
)
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
);
510 valid_keyslot(nwam_value_t value
)
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
);
524 valid_secmode(nwam_value_t value
)
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
);
540 nwam_known_wlan_validate(nwam_known_wlan_handle_t kwh
, const char **errpropp
)
542 return (nwam_validate(known_wlan_prop_table
, kwh
, errpropp
));
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
,
554 * Given a property, return expected property data type
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
));
563 nwam_known_wlan_prop_multivalued(const char *propname
, boolean_t
*multip
)
565 return (nwam_prop_multivalued(known_wlan_prop_table
, propname
, multip
));
569 nwam_known_wlan_get_default_proplist(const char ***prop_list
,
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.
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
;
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
);
600 case NWAM_ENTITY_NOT_FOUND
:
601 if ((err
= nwam_known_wlan_create(essid
, &kwh
)) != NWAM_SUCCESS
)
603 /* New known WLAN - set priority to 0 */
604 if ((err
= nwam_value_create_uint64(0, &priorityval
))
606 nwam_known_wlan_free(kwh
);
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
);
616 /* If BSSID is NULL, nothing more to do here. */
619 if ((err
= nwam_value_create_string((char *)bssid
, &bssidsval
))
621 nwam_known_wlan_free(kwh
);
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
);
634 /* If no bssid is specified, nothing to do */
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
);
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
);
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
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
++)
673 nwam_value_free(bssidsval
);
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,
683 for (i
= 0; i
< nelem
+ 1; i
++)
686 if (err
!= NWAM_SUCCESS
) {
687 nwam_known_wlan_free(kwh
);
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
);
704 /* Set the security mode property */
705 if ((err
= nwam_value_create_uint64(secmode
, &secmodeval
))
707 nwam_known_wlan_free(kwh
);
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
);
719 if (keyname
!= NULL
) {
720 if ((err
= nwam_value_create_string((char *)keyname
,
721 &keynameval
)) != NWAM_SUCCESS
) {
722 nwam_known_wlan_free(kwh
);
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
);
732 if ((err
= nwam_value_create_uint64(keyslot
,
733 &keyslotval
)) != NWAM_SUCCESS
) {
734 nwam_known_wlan_free(kwh
);
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
);
749 * Remove the given BSSID/keyname from the bssids/keyname property for the
753 nwam_known_wlan_remove_from_known_wlans(const char *essid
, const char *bssid
,
756 nwam_known_wlan_handle_t kwh
;
757 nwam_value_t bssidsval
;
758 char **old_bssids
, **new_bssids
;
763 /* Retrieve the existing bssids */
764 if ((err
= nwam_known_wlan_read(essid
, 0, &kwh
)) != NWAM_SUCCESS
)
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
);
771 if ((err
= nwam_value_get_string_array(bssidsval
, &old_bssids
, &nelem
))
773 nwam_value_free(bssidsval
);
774 nwam_known_wlan_free(kwh
);
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) {
786 /* Given BSSID was not found in the array */
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 */
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
);
801 err
= nwam_known_wlan_commit(kwh
, 0);
802 nwam_known_wlan_free(kwh
);
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
++)
824 if (err
!= NWAM_SUCCESS
) {
825 nwam_known_wlan_free(kwh
);
829 /* Set the bssids property */
830 err
= nwam_known_wlan_set_prop_value(kwh
, NWAM_KNOWN_WLAN_PROP_BSSIDS
,
832 nwam_value_free(bssidsval
);
833 if (err
!= NWAM_SUCCESS
) {
834 nwam_known_wlan_free(kwh
);
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
);
844 if ((err
= nwam_known_wlan_delete_prop(kwh
,
845 NWAM_KNOWN_WLAN_PROP_KEYSLOT
)) != NWAM_SUCCESS
) {
846 nwam_known_wlan_free(kwh
);
851 err
= nwam_known_wlan_commit(kwh
, 0);
852 nwam_known_wlan_free(kwh
);