/*
* 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 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <libintl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <stddef.h>
#include <string.h>
#include <stropts.h>
#include <libdevinfo.h>
#include <net/if_types.h>
#include <libdlpi.h>
#include <libdllink.h>
#include <libscf.h>
#include <libdlwlan.h>
#include <libdladm_impl.h>
#include <libdlwlan_impl.h>
void *);
int);
int);
int);
int);
int);
int);
int);
int);
int);
int);
boolean_t *);
dladm_wlan_key_t *, uint_t);
int);
int);
static void generate_essid(dladm_wlan_essid_t *);
{ "disconnected", DLADM_WLAN_LINK_DISCONNECTED },
{ "connected", DLADM_WLAN_LINK_CONNECTED }
};
{ "none", DLADM_WLAN_SECMODE_NONE },
{ "wep", DLADM_WLAN_SECMODE_WEP },
{ "wpa", DLADM_WLAN_SECMODE_WPA }
};
{ "very weak", DLADM_WLAN_STRENGTH_VERY_WEAK },
{ "weak", DLADM_WLAN_STRENGTH_WEAK },
{ "good", DLADM_WLAN_STRENGTH_GOOD },
{ "very good", DLADM_WLAN_STRENGTH_VERY_GOOD },
{ "excellent", DLADM_WLAN_STRENGTH_EXCELLENT }
};
{ "a", DLADM_WLAN_MODE_80211A },
{ "b", DLADM_WLAN_MODE_80211B },
{ "g", DLADM_WLAN_MODE_80211G },
{ "n", DLADM_WLAN_MODE_80211GN },
{ "n", DLADM_WLAN_MODE_80211AN }
};
{ "open", DLADM_WLAN_AUTH_OPEN },
{ "shared", DLADM_WLAN_AUTH_SHARED }
};
{ "bss", DLADM_WLAN_BSSTYPE_BSS },
{ "ibss", DLADM_WLAN_BSSTYPE_IBSS },
{ "any", DLADM_WLAN_BSSTYPE_ANY }
};
static dladm_status_t
{
switch (gbuf->wldp_result) {
case WL_SUCCESS:
return (DLADM_STATUS_OK);
case WL_NOTSUPPORTED:
case WL_LACK_FEATURE:
return (DLADM_STATUS_NOTSUP);
case WL_READONLY:
return (DLADM_STATUS_PROPRDONLY);
default:
break;
}
return (DLADM_STATUS_FAILED);
}
static dladm_wlan_mode_t
{
case WL_ERP:
return (wlep->wl_erp_ht_enabled ?
case WL_OFDM:
return (wlop->wl_ofdm_ht_enabled ?
case WL_DSSS:
case WL_FHSS:
return (DLADM_WLAN_MODE_80211B);
default:
break;
}
return (DLADM_WLAN_MODE_NONE);
}
{
switch (wlfp->wl_fhss_subtype) {
case WL_FHSS:
case WL_DSSS:
case WL_IRBASE:
case WL_HRDS:
case WL_ERP:
break;
case WL_OFDM:
break;
default:
return (B_FALSE);
}
return (B_TRUE);
}
static void
{
int i;
if (wlp->wl_ess_conf_reserved[0] > 0)
for (i = 0; i < MAX_SCAN_SUPPORT_RATES; i++) {
}
&attrp->wa_channel))
}
{
int i;
goto done;
sizeof (wl_status));
if (status != DLADM_STATUS_OK)
goto done;
goto done;
goto done;
}
goto done;
}
!= DLADM_STATUS_OK)
goto done;
break;
}
if (wl_status != WL_CONNECTED) {
sizeof (&wl_status));
if (status != DLADM_STATUS_OK)
goto done;
if (wl_status == WL_CONNECTED)
}
done:
return (status);
}
/*
* Structures used in building the list of eligible WLANs to connect to.
* Specifically, `connect_state' has the WLAN attributes that must be matched
* (in `cs_attr') and a growing list of WLANs that matched those attributes
* chained through `cs_list'. Each element in the list is of type `attr_node'
* and has the matching WLAN's attributes and a pointer to the next element.
* For convenience, `cs_count' tracks the number of elements in the list.
*/
typedef struct attr_node {
} attr_node_t;
typedef struct connect_state {
/*
* Compare two sets of WLAN attributes. For now, we only consider strength
* and speed (in that order), which matches the documented default policy for
* dladm_wlan_connect().
*/
static int
{
return (1);
return (-1);
}
/*
* Callback function used by dladm_wlan_connect() to filter out unwanted
* WLANs when scanning for available WLANs. Always returns B_TRUE to
* continue the scan.
*/
static boolean_t
{
goto append;
return (B_TRUE);
DLADM_WLAN_MAX_ESSID_LEN) != 0)
return (B_TRUE);
return (B_TRUE);
return (B_TRUE);
return (B_TRUE);
return (B_TRUE);
}
return (B_TRUE);
DLADM_WLAN_BSSID_LEN) != 0)
return (B_TRUE);
return (B_TRUE);
return (B_TRUE);
}
static dladm_status_t
{
if (status != DLADM_STATUS_OK)
goto fail;
}
goto fail;
goto fail;
goto fail;
if (secmode == DLADM_WLAN_SECMODE_WEP) {
key_count > MAX_NWEPKEYS) {
goto fail;
}
if (status != DLADM_STATUS_OK)
goto fail;
} else if (secmode == DLADM_WLAN_SECMODE_WPA) {
key_count > MAX_NWEPKEYS) {
goto fail;
}
if (status != DLADM_STATUS_OK)
goto fail;
return (DLADM_STATUS_NOTSUP);
}
if (create_ibss) {
if (status != DLADM_STATUS_OK)
goto fail;
if (status != DLADM_STATUS_OK)
goto fail;
}
}
}
if (!essid_valid) {
goto fail;
}
goto fail;
/*
* Because wpa daemon needs getting essid from driver,
* we need call do_set_essid() first, then call wpa_instance_create().
*/
for (;;) {
sizeof (wl_status));
if (status != DLADM_STATUS_OK)
goto fail;
if (wl_status == WL_CONNECTED)
break;
goto fail;
}
}
fail:
return (status);
}
{
int i;
return (status);
sizeof (wl_status))) != DLADM_STATUS_OK)
goto done;
if (wl_status == WL_CONNECTED) {
goto done;
}
if ((flags & DLADM_WLAN_CONNECT_NOSCAN) != 0 ||
goto done;
}
if (status != DLADM_STATUS_OK)
goto done;
if (!create_ibss) {
goto done;
}
goto done;
}
goto done;
}
}
if (status == DLADM_STATUS_OK)
break;
if (!set_authmode) {
if (status == DLADM_STATUS_OK)
break;
}
}
done:
}
return (status);
}
{
return (status);
sizeof (wl_status))) != DLADM_STATUS_OK)
goto done;
if (wl_status != WL_CONNECTED) {
goto done;
}
!= DLADM_STATUS_OK)
goto done;
sizeof (wl_status))) != DLADM_STATUS_OK)
goto done;
if (wl_status == WL_CONNECTED) {
goto done;
}
done:
return (status);
}
{
return (DLADM_STATUS_BADARG);
goto done;
sizeof (wl_status))) != DLADM_STATUS_OK)
goto done;
if (wl_status != WL_CONNECTED)
else
!= DLADM_STATUS_OK)
goto done;
!= DLADM_STATUS_OK)
goto done;
goto done;
}
sizeof (encryption))) != DLADM_STATUS_OK)
goto done;
switch (encryption) {
case WL_NOENCRYPTION:
break;
case WL_ENC_WEP:
break;
case WL_ENC_WPA:
break;
default:
break;
}
!= DLADM_STATUS_OK)
goto done;
goto done;
}
!= DLADM_STATUS_OK)
goto done;
if (ratesp->wl_rates_num > 0) {
uint_t i, r = 0;
for (i = 0; i < ratesp->wl_rates_num; i++) {
if (ratesp->wl_rates_rates[i] > r)
r = ratesp->wl_rates_rates[i];
}
}
sizeof (authmode))) != DLADM_STATUS_OK)
goto done;
switch (authmode) {
case WL_OPENSYSTEM:
break;
case WL_SHAREDKEY:
break;
default:
break;
}
sizeof (bsstype))) != DLADM_STATUS_OK)
goto done;
switch (bsstype) {
case WL_BSS_BSS:
break;
case WL_BSS_IBSS:
break;
case WL_BSS_ANY:
break;
default:
break;
}
sizeof (wl_phy_conf))) != DLADM_STATUS_OK)
goto done;
done:
return (status);
}
/*
* Check to see if the link is wireless.
*/
static dladm_status_t
{
NULL, 0);
if (status == DLADM_STATUS_OK) {
}
return (status);
}
static boolean_t
{
int i;
for (i = 0; i < cnt; i++) {
return (B_TRUE);
}
}
return (B_FALSE);
}
static boolean_t
{
int i;
for (i = 0; i < cnt; i++) {
return (B_TRUE);
}
}
return (B_FALSE);
}
const char *
{
return (buf);
}
const char *
{
IFT_OTHER));
}
static const char *
{
char *s;
s = "";
return (buf);
}
const char *
{
}
const char *
{
}
const char *
{
}
const char *
{
(float)(*speed) / 2);
return (buf);
}
const char *
{
}
const char *
{
}
const char *
{
}
{
return (DLADM_STATUS_BADARG);
return (DLADM_STATUS_OK);
}
{
int len;
return (DLADM_STATUS_BADARG);
if (len != DLADM_WLAN_BSSID_LEN) {
return (DLADM_STATUS_BADARG);
}
return (DLADM_STATUS_OK);
}
{
return (DLADM_STATUS_BADARG);
return (DLADM_STATUS_OK);
}
{
return (DLADM_STATUS_BADARG);
return (DLADM_STATUS_OK);
}
{
return (DLADM_STATUS_BADARG);
return (DLADM_STATUS_OK);
}
{
return (DLADM_STATUS_OK);
}
{
return (DLADM_STATUS_BADARG);
return (DLADM_STATUS_OK);
}
{
return (DLADM_STATUS_BADARG);
return (DLADM_STATUS_OK);
}
{
return (DLADM_STATUS_BADARG);
}
return (DLADM_STATUS_OK);
}
{
return (status);
}
return (DLADM_STATUS_BADARG);
if (!(flags & DLADM_OPT_ACTIVE))
return (DLADM_STATUS_TEMPONLY);
/*
* dlpi_open() is not used here because libdlpi depends on libdladm,
* and we do not want to introduce recursive dependencies.
*/
return (dladm_errno2status(errno));
if (rc > 0) {
/*
* Non-negative return value indicates the specific
* operation failed and the reason for the failure
* was stored in gbuf->wldp_result.
*/
} else {
/*
* Negative return value indicates the ioctl failed.
*/
}
}
return (status);
}
static dladm_status_t
{
return (DLADM_STATUS_NOMEM);
return (status);
}
static dladm_status_t
{
}
static dladm_status_t
int buflen)
{
}
static dladm_status_t
int buflen)
{
}
static dladm_status_t
{
}
static dladm_status_t
{
}
static dladm_status_t
int buflen)
{
}
static dladm_status_t
int buflen)
{
}
static dladm_status_t
{
}
static dladm_status_t
int buflen)
{
}
static dladm_status_t
int buflen)
{
}
static dladm_status_t
int buflen)
{
}
static dladm_status_t
{
}
static dladm_status_t
{
switch (*bsstype) {
case DLADM_WLAN_BSSTYPE_BSS:
break;
case DLADM_WLAN_BSSTYPE_IBSS:
break;
default:
break;
}
}
static dladm_status_t
{
switch (*auth) {
case DLADM_WLAN_AUTH_OPEN:
break;
case DLADM_WLAN_AUTH_SHARED:
break;
default:
return (DLADM_STATUS_NOTSUP);
}
}
static dladm_status_t
{
switch (*secmode) {
case DLADM_WLAN_SECMODE_NONE:
break;
case DLADM_WLAN_SECMODE_WEP:
break;
case DLADM_WLAN_SECMODE_WPA:
return (0);
default:
return (DLADM_STATUS_NOTSUP);
}
}
static dladm_status_t
{
int i;
return (DLADM_STATUS_BADARG);
for (i = 0; i < MAX_NWEPKEYS; i++)
for (i = 0; i < key_count; i++) {
return (DLADM_STATUS_BADARG);
return (DLADM_STATUS_BADARG);
}
}
static dladm_status_t
{
sizeof (iessid.wl_essid_essid));
} else {
return (DLADM_STATUS_BADARG);
}
}
static dladm_status_t
{
if (*channel > MAX_CHANNEL_NUM)
return (DLADM_STATUS_BADVAL);
}
static dladm_status_t
{
}
static void
{
random());
}
static dladm_status_t
int buflen)
{
}
static dladm_status_t
int buflen)
{
B_FALSE));
}
{
int i, n;
return (DLADM_STATUS_NOMEM);
if (status == DLADM_STATUS_OK) {
for (i = 0; i < n; i ++) {
}
*estot = n;
}
return (status);
}
{
return (DLADM_STATUS_BADARG);
return (DLADM_STATUS_NOMEM);
return (status);
}
{
}
{
}
{
switch (cipher) {
case DLADM_WLAN_CIPHER_WEP:
break;
case DLADM_WLAN_CIPHER_TKIP:
break;
break;
break;
case DLADM_WLAN_CIPHER_CKIP:
break;
case DLADM_WLAN_CIPHER_NONE:
break;
default:
return (DLADM_STATUS_BADARG);
}
if (set_tx) {
} else
}
{
switch (op) {
case DLADM_WLAN_MLME_ASSOC:
break;
case DLADM_WLAN_MLME_DISASSOC:
break;
default:
return (DLADM_STATUS_BADARG);
}
}
/*
* routines of create instance
*/
static scf_propertygroup_t *
{
return (NULL);
return (NULL);
}
return (pg);
}
static dladm_status_t
{
goto out;
goto out;
goto out;
goto out;
goto out;
return (DLADM_STATUS_OK);
out:
return (DLADM_STATUS_FAILED);
}
static dladm_status_t
{
goto out;
goto out;
goto out;
}
do {
goto out;
goto out;
}
switch (rv) {
case 1:
goto out;
case 0:
goto out;
}
break;
case -1:
default:
goto out;
}
} while (rv == 0);
out:
}
return (status);
}
static dladm_status_t
const char *instance_name, const char *command)
{
char *buf;
goto out;
if (scf_error() == SCF_ERROR_EXISTS)
/* Let the caller deal with the duplicate instance */
goto out;
}
command) != DLADM_STATUS_OK) {
goto out;
}
/* enabling the instance */
goto out;
if ((smf_disable_instance(buf, 0) != 0) ||
goto out;
}
}
out:
return (status);
}
static dladm_status_t
{
goto out;
goto out;
goto out;
goto out;
out:
(void) scf_handle_unbind(handle);
}
return (status);
}
/*
* routines of delete instance
*/
static void
{
char *state;
SCF_PROPERTY_TIMEOUT)) != NULL) &&
/* incremental wait */
usecs *= 2;
/* Check state after the wait */
return;
}
}
}
static dladm_status_t
{
char *buf;
goto out;
goto out;
goto out;
goto out;
goto out;
goto out;
goto out;
if (scf_errnum == SCF_ERROR_NOT_FOUND)
goto out;
}
goto out;
}
char *state;
if (smf_disable_instance(buf, 0) == 0) {
/*
* Wait for some time till timeout to avoid
* a race with scf_instance_delete() below.
*/
}
}
}
if (scf_instance_delete(instance) != 0) {
goto out;
}
out:
(void) scf_handle_unbind(handle);
}
return (status);
}
static dladm_status_t
{
int size;
/*
*/
instance_name, sizeof (instance_name));
if (status != DLADM_STATUS_OK)
goto out;
goto out;
}
if (status == DLADM_STATUS_EXIST) {
/*
* Delete the existing instance and create a new instance
* with the supplied arguments.
*/
}
}
out:
return (status);
}
static dladm_status_t
{
/*
* the link name).
*/
return (DLADM_STATUS_FAILED);
return (delete_instance(instance_name));
}