/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <libdllink.h>
#include <libdlwlan.h>
#include "libnwam_impl.h"
#include <libnwam_priv.h>
#include <libnwam.h>
/*
* Functions to support creating, modifying and destroying
* known WLAN objects. These represent the WiFi connection history,
* and are used by nwamd to identify and connect to known WLANs in
* scan results.
*/
"specifies priority of known WLAN - lower values are prioritized",
"specifies BSSID(s) (of the form aa:bb:cc:dd:ee:ff) associated "
"with known WLAN",
0, 1, valid_keyname,
"specifies security key name used with known WLAN",
0, 1, valid_keyslot,
"specifies key slot [1-4] for security key used with known WLAN",
0, 1, valid_secmode,
"specifies security mode used for known WLAN",
};
#define NWAM_NUM_KNOWN_WLAN_PROPS \
(sizeof (known_wlan_prop_table_entries) / \
sizeof (*known_wlan_prop_table_entries))
{
return (nwam_read(NWAM_OBJECT_TYPE_KNOWN_WLAN,
}
{
return (err);
/*
* Create new object list for known WLAN. The initial priority is
* also set.
*/
!= NWAM_SUCCESS)
goto finish;
goto finish;
if (err != NWAM_SUCCESS) {
}
return (err);
}
{
}
{
}
{
return (!kwh->nwh_committed);
}
/*
* Used to store wlan names/priorities for prioritized walk.
*/
struct nwam_wlan_info {
char *wlan_name;
};
struct nwam_wlan_info_list {
};
/*
*/
static int
{
/* Reallocate WLAN list and allocate new info list element. */
sizeof (struct nwam_wlan_info))) == NULL) {
return (NWAM_NO_MEMORY);
}
/* Update list since realloc() may have relocated it */
return (err);
}
return (NWAM_SUCCESS);
}
/*
* Some recursion is required here, since if _WALK_PRIORITY_ORDER is specified,
* we need to first walk the list of known WLANs to retrieve names
* and priorities, then utilize that list to carry out an in-order walk.
*/
{
int ret = 0;
!= NWAM_SUCCESS)
return (err);
if ((flags & NWAM_FLAG_KNOWN_WLAN_WALK_PRIORITY_ORDER) != 0) {
!= NWAM_SUCCESS) {
goto done;
}
err = NWAM_SUCCESS;
/* Find lowest priority value not walked so far. */
minindex = j;
}
}
if ((err = nwam_known_wlan_read
goto done;
}
if (ret != 0) {
goto done;
}
}
done:
}
}
return (err);
}
return (nwam_walk(NWAM_OBJECT_TYPE_KNOWN_WLAN,
}
void
{
}
{
}
{
void *olddata;
/*
* Duplicate data, remove property and validate. If validation
* fails, revert to data duplicated prior to remove.
*/
!= NWAM_SUCCESS)
return (err);
return (err);
}
return (err);
}
return (NWAM_SUCCESS);
}
{
!= NWAM_SUCCESS)
return (err);
}
{
}
int (*cb)(const char *, nwam_value_t, void *),
{
}
struct priority_collision_data {
char *wlan_name;
};
static int
{
char *name;
if (err != NWAM_SUCCESS)
return (err);
/* skip to-be-updated wlan */
return (NWAM_SUCCESS);
}
&priorityval);
if (err != NWAM_SUCCESS)
return (err);
if (err != NWAM_SUCCESS)
return (err);
return (NWAM_SUCCESS);
/* Two priority values collide. Move this one up. */
if (err != NWAM_SUCCESS)
return (err);
if (err != NWAM_SUCCESS) {
return (err);
}
/*
* We are doing a walk, and will continue shifting until
* we find a gap in the priority numbers; thus no need to
* do collision checking here.
*/
if (err != NWAM_SUCCESS)
return (err);
return (NWAM_SUCCESS);
}
/*
* Only possiblity left at this point is that we're looking
* at a priority greater than the last one we wrote, so we've
* found a gap. We can halt the walk now.
*/
return (NWAM_WALK_HALTED);
}
{
int ret = 0;
return (err);
/*
* If the NO_COLLISION_CHECK flag is set, no need to check for
* collision.
*/
(flags & NWAM_FLAG_GLOBAL_MASK) |
/*
* We need to do priority checking. Walk the list, looking
* for the first entry with priority greater than or equal
* to the entry we're adding. Commit the new one (without
* doing additional checking), and then increment other
* entries as needed.
*/
if (err != NWAM_SUCCESS)
return (err);
if (err != NWAM_SUCCESS)
return (err);
if (err != NWAM_SUCCESS)
return (err);
/*
* a halted walk is okay, it just means we didn't have
* to walk the entire list to resolve priorities
*/
return (ret);
return (nwam_known_wlan_commit(kwh,
}
{
}
const char **descriptionp)
{
descriptionp));
}
/* Property-specific value validation functions should go here. */
static nwam_error_t
{
char *keyname;
return (NWAM_ENTITY_INVALID_VALUE);
if (!dladm_valid_secobj_name(keyname))
return (NWAM_ENTITY_INVALID_VALUE);
return (NWAM_SUCCESS);
}
static nwam_error_t
{
return (NWAM_ENTITY_INVALID_VALUE);
return (NWAM_ENTITY_INVALID_VALUE);
return (NWAM_SUCCESS);
}
static nwam_error_t
{
return (NWAM_ENTITY_INVALID_VALUE);
if (secmode != DLADM_WLAN_SECMODE_NONE &&
return (NWAM_ENTITY_INVALID_VALUE);
return (NWAM_SUCCESS);
}
{
}
{
value));
}
/*
* Given a property, return expected property data type
*/
{
}
{
}
{
}
/*
* Add the given ESSID, BSSID, secmode, keyslot and key name to known WLANs.
* BSSID and keyname can be NULL.
*/
{
int i, j;
/*
* Check if the given ESSID already exists as known WLAN. If so,
* add the BSSID to the bssids property. If not, create one with
* the given ESSID and add BSSID if given.
*/
switch (err) {
case NWAM_ENTITY_NOT_FOUND:
return (err);
/* New known WLAN - set priority to 0 */
!= NWAM_SUCCESS) {
return (err);
}
if (err != NWAM_SUCCESS) {
return (err);
}
/* If BSSID is NULL, nothing more to do here. */
break;
!= NWAM_SUCCESS) {
return (err);
}
/* Set the bssids property */
if (err != NWAM_SUCCESS) {
return (err);
}
break;
case NWAM_SUCCESS:
/* If no bssid is specified, nothing to do */
break;
/* known WLAN exists, retrieve the existing bssids property */
return (err);
}
if (err == NWAM_SUCCESS) {
return (err);
}
}
/* Create a new array to append given BSSID */
if (new_bssids == NULL) {
return (NWAM_NO_MEMORY);
}
/*
* Copy over existing BSSIDs to the new array. Also, check
* to make sure that the given BSSID doesn't already exist
* in the known WLAN. If so, do abort copying and return
* NWAM_SUCCESS.
*/
for (i = 0; i < nelem; i++) {
/* nothing to do, so free up everything */
for (j = 0; j < i; j++)
free(new_bssids[j]);
goto set_key_info;
}
}
&bssidsval);
for (i = 0; i < nelem + 1; i++)
free(new_bssids[i]);
if (err != NWAM_SUCCESS) {
return (err);
}
/* Set the bssids property */
if (err != NWAM_SUCCESS) {
return (err);
}
break;
default:
return (err);
}
/* Set the security mode property */
!= NWAM_SUCCESS) {
return (err);
}
if (err != NWAM_SUCCESS) {
return (err);
}
&keynameval)) != NWAM_SUCCESS) {
return (err);
}
if (err != NWAM_SUCCESS) {
return (err);
}
&keyslotval)) != NWAM_SUCCESS) {
return (err);
}
}
return (err);
}
/*
* given ESSID.
*/
const char *keyname)
{
/* Retrieve the existing bssids */
return (err);
return (err);
}
!= NWAM_SUCCESS) {
return (err);
}
/* Cycle through the BSSIDs array to find the BSSID to remove */
for (i = 0; i < nelem; i++) {
found = i;
break;
}
}
/* Given BSSID was not found in the array */
if (found == -1) {
return (NWAM_INVALID_ARG);
}
/* If removing the only BSSID entry, remove the bssids property */
if (nelem == 1) {
return (err);
}
return (err);
}
if (new_bssids == NULL) {
return (NWAM_NO_MEMORY);
}
/* Copy over other BSSIDs */
for (i = 0; i < found; i++)
for (i = 0; i < nelem - 1; i++)
free(new_bssids[i]);
if (err != NWAM_SUCCESS) {
return (err);
}
/* Set the bssids property */
if (err != NWAM_SUCCESS) {
return (err);
}
return (err);
}
return (err);
}
}
return (err);
}