libwladm.c revision 13994ee84c09002288df157a5da6aa7349a1010f
/*
* 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 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <libintl.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stropts.h>
#include <libdevinfo.h>
#include <net/if_types.h>
#include <libwladm.h>
#include <libwladm_impl.h>
#include <inet/wifi_ioctl.h>
typedef struct val_desc {
char *vd_name;
} val_desc_t;
struct prop_desc;
uint_t, val_desc_t **);
typedef struct prop_desc {
char *pd_name;
} prop_desc_t;
static int do_get_bsstype(int, wldp_t *);
static int do_get_essid(int, wldp_t *);
static int do_get_bssid(int, wldp_t *);
static int do_get_signal(int, wldp_t *);
static int do_get_encryption(int, wldp_t *);
static int do_get_authmode(int, wldp_t *);
static int do_get_linkstatus(int, wldp_t *);
static int do_get_esslist(int, wldp_t *);
static int do_get_rate(int, wldp_t *);
static int do_get_phyconf(int, wldp_t *);
static int do_get_powermode(int, wldp_t *);
static int do_get_radio(int, wldp_t *);
static int do_get_mode(int, wldp_t *);
static int open_link(const char *);
static int do_disconnect(int, wldp_t *);
static void generate_essid(wladm_essid_t *);
static val_desc_t status_vals[] = {
{ "ok", WLADM_STATUS_OK },
{ "invalid argument", WLADM_STATUS_BADARG },
{ "operation failed", WLADM_STATUS_FAILED },
{ "operation not supported", WLADM_STATUS_NOTSUP },
{ "already connected", WLADM_STATUS_ISCONN },
{ "not connected", WLADM_STATUS_NOTCONN },
{ "not found", WLADM_STATUS_NOTFOUND },
{ "value not found", WLADM_STATUS_BADVAL },
{ "invalid link", WLADM_STATUS_LINKINVAL },
{ "insufficient memory", WLADM_STATUS_NOMEM },
{ "operation timed out", WLADM_STATUS_TIMEDOUT },
{ "read-only property", WLADM_STATUS_PROPRDONLY },
{ "not enough space", WLADM_STATUS_TOOSMALL },
{ "invalid number of values", WLADM_STATUS_BADVALCNT }
};
static val_desc_t linkstatus_vals[] = {
{ "disconnected", WLADM_LINK_STATUS_DISCONNECTED },
{ "connected", WLADM_LINK_STATUS_CONNECTED }
};
static val_desc_t secmode_vals[] = {
{ "none", WLADM_SECMODE_NONE },
{ "wep", WLADM_SECMODE_WEP }
};
static val_desc_t strength_vals[] = {
{ "very weak", WLADM_STRENGTH_VERY_WEAK },
{ "weak", WLADM_STRENGTH_WEAK },
{ "good", WLADM_STRENGTH_GOOD },
{ "very good", WLADM_STRENGTH_VERY_GOOD },
{ "excellent", WLADM_STRENGTH_EXCELLENT }
};
static val_desc_t mode_vals[] = {
{ "a", WLADM_MODE_80211A },
{ "b", WLADM_MODE_80211B },
{ "g", WLADM_MODE_80211G },
};
static val_desc_t auth_vals[] = {
{ "open", WLADM_AUTH_OPEN },
{ "shared", WLADM_AUTH_SHARED }
};
static val_desc_t bsstype_vals[] = {
{ "bss", WLADM_BSSTYPE_BSS },
{ "ibss", WLADM_BSSTYPE_IBSS },
{ "any", WLADM_BSSTYPE_ANY }
};
static val_desc_t radio_vals[] = {
{ "on", WLADM_RADIO_ON },
{ "off", WLADM_RADIO_OFF }
};
static val_desc_t powermode_vals[] = {
{ "off", WLADM_PM_OFF },
{ "fast", WLADM_PM_FAST },
{ "max", WLADM_PM_MAX }
};
static prop_desc_t prop_table[] = {
};
/*
* Unfortunately, MAX_SCAN_SUPPORT_RATES is too small to allow all
* rates to be retrieved. However, we cannot increase it at this
* time because it will break binary comatibility with unbundled
* WiFi drivers and utilities. So for now we define an additional
* constant, MAX_SUPPORT_RATES, to allow all rates to be retrieved.
*/
#define MAX_SUPPORT_RATES 64
#define IS_CONNECTED(gbuf) \
static wladm_status_t
{
switch (gbuf->wldp_result) {
case WL_SUCCESS:
return (WLADM_STATUS_OK);
case WL_NOTSUPPORTED:
case WL_LACK_FEATURE:
return (WLADM_STATUS_NOTSUP);
case WL_READONLY:
return (WLADM_STATUS_PROPRDONLY);
default:
break;
}
return (WLADM_STATUS_FAILED);
}
static int
{
char linkname[MAXPATHLEN];
int fd;
return (-1);
return (-1);
return (-1);
}
/*
* Check to see if the link is wireless.
*/
return (-1);
}
return (fd);
}
static wladm_mode_t
{
case WL_ERP:
return (WLADM_MODE_80211G);
case WL_OFDM:
return (WLADM_MODE_80211A);
case WL_DSSS:
case WL_FHSS:
return (WLADM_MODE_80211B);
default:
break;
}
return (WLADM_MODE_NONE);
}
static boolean_t
{
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);
}
#define IEEE80211_RATE 0x7f
static void
{
int i;
for (i = 0; i < MAX_SCAN_SUPPORT_RATES; i++) {
}
&attrp->wa_channel))
}
{
int fd, i;
return (WLADM_STATUS_LINKINVAL);
goto done;
}
goto done;
}
goto done;
}
goto done;
}
break;
}
if (!connected) {
goto done;
}
if (IS_CONNECTED(gbuf))
}
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
* wladm_connect().
*/
static int
{
return (1);
return (-1);
}
/*
* Callback function used by wladm_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);
WLADM_MAX_ESSID_LEN) != 0)
return (B_TRUE);
return (B_TRUE);
return (B_TRUE);
return (B_TRUE);
return (B_TRUE);
}
return (B_TRUE);
WLADM_BSSID_LEN) != 0)
return (B_TRUE);
return (B_TRUE);
return (B_TRUE);
}
static wladm_status_t
{
goto fail;
}
goto fail;
goto fail;
goto fail;
if (secmode == WLADM_SECMODE_WEP) {
return (WLADM_STATUS_BADARG);
goto fail;
}
if (create_ibss) {
goto fail;
goto fail;
}
}
}
if (!essid_valid)
return (WLADM_STATUS_FAILED);
goto fail;
for (;;) {
goto fail;
if (IS_CONNECTED(gbuf))
break;
return (WLADM_STATUS_TIMEDOUT);
}
return (WLADM_STATUS_OK);
fail:
return (wladm_wlresult2status(gbuf));
}
{
int fd, i;
return (WLADM_STATUS_LINKINVAL);
goto done;
}
goto done;
}
if (IS_CONNECTED(gbuf)) {
goto done;
}
if ((flags & WLADM_OPT_NOSCAN) != 0 ||
goto done;
}
if (status != WLADM_STATUS_OK)
goto done;
if (!create_ibss) {
goto done;
}
goto done;
}
goto done;
}
}
if (status == WLADM_STATUS_OK)
break;
if (!set_authmode) {
if (status == WLADM_STATUS_OK)
break;
}
}
done:
}
return (status);
}
wladm_disconnect(const char *link)
{
int fd;
return (WLADM_STATUS_BADARG);
goto done;
}
goto done;
}
if (!IS_CONNECTED(gbuf)) {
goto done;
}
goto done;
}
goto done;
}
if (IS_CONNECTED(gbuf)) {
goto done;
}
done:
return (status);
}
typedef struct wladm_linkname {
char wl_name[MAXNAMELEN];
struct wladm_linkname *wl_next;
typedef struct wladm_walk {
} wladm_walk_t;
/* ARGSUSED */
static int
{
char name[MAXNAMELEN];
return (DI_WALK_CONTINUE);
}
return (DI_WALK_CONTINUE);
}
return (DI_WALK_CONTINUE);
}
{
return (WLADM_STATUS_FAILED);
&state, append_linkname);
/*
* NOTE: even if (*func)() returns B_FALSE, the loop continues
* since all memory must be freed.
*/
if (cont)
}
}
{
int fd;
return (WLADM_STATUS_BADARG);
return (WLADM_STATUS_LINKINVAL);
goto done;
}
goto done;
if (!IS_CONNECTED(gbuf)) {
goto done;
}
goto done;
goto done;
goto done;
switch (encryption) {
case WL_NOENCRYPTION:
break;
case WL_ENC_WEP:
break;
default:
break;
}
goto done;
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];
}
}
goto done;
switch (authmode) {
case WL_OPENSYSTEM:
break;
case WL_SHAREDKEY:
break;
default:
break;
}
goto done;
switch (bsstype) {
case WL_BSS_BSS:
break;
case WL_BSS_IBSS:
break;
case WL_BSS_ANY:
break;
default:
break;
}
goto done;
done:
return (status);
}
wladm_is_valid(const char *link)
{
if (fd < 0)
return (B_FALSE);
return (B_TRUE);
}
/* ARGSUSED */
static wladm_status_t
{
int i;
if (pdp->pd_nmodval == 0)
return (WLADM_STATUS_PROPRDONLY);
if (val_cnt != 1)
return (WLADM_STATUS_BADVALCNT);
for (i = 0; i < pdp->pd_nmodval; i++)
break;
if (i == pdp->pd_nmodval)
return (WLADM_STATUS_BADVAL);
return (WLADM_STATUS_NOMEM);
return (WLADM_STATUS_OK);
}
static wladm_status_t
{
return (WLADM_STATUS_PROPRDONLY);
if (status != WLADM_STATUS_OK)
return (status);
} else {
return (WLADM_STATUS_NOTSUP);
return (WLADM_STATUS_NOMEM);
cnt = 1;
}
if (status == WLADM_STATUS_OK) {
/*
* Some ioctls return 0 but store error code in
* wldp_result. Need to fix them.
*/
}
return (status);
}
{
int fd, i;
return (WLADM_STATUS_BADARG);
return (WLADM_STATUS_LINKINVAL);
goto done;
}
for (i = 0; i < WLADM_MAX_PROPS; i++) {
continue;
status = s;
break;
} else {
if (s != WLADM_STATUS_OK &&
s != WLADM_STATUS_NOTSUP)
status = s;
}
}
if (!found)
done:
return (status);
}
/* ARGSUSED */
{
int i;
for (i = 0; i < WLADM_MAX_PROPS; i++) {
break;
}
return (WLADM_STATUS_OK);
}
{
int fd;
int i;
return (WLADM_STATUS_BADARG);
for (i = 0; i < WLADM_MAX_PROPS; i++)
break;
if (i == WLADM_MAX_PROPS)
return (WLADM_STATUS_NOTFOUND);
return (WLADM_STATUS_LINKINVAL);
goto done;
}
pdp = &prop_table[i];
switch (type) {
case WLADM_PROP_VAL_CURRENT:
break;
case WLADM_PROP_VAL_DEFAULT:
break;
}
*val_cnt = 1;
break;
break;
}
if (cnt == 0) {
} else {
for (i = 0; i < cnt; i++) {
}
}
break;
default:
break;
}
done:
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 *
{
}
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 *
{
}
const char *
{
const char *s;
return (buf);
}
{
if (str[0] == '\0')
return (WLADM_STATUS_BADARG);
return (WLADM_STATUS_OK);
}
{
int len;
return (WLADM_STATUS_BADARG);
if (len != WLADM_BSSID_LEN) {
return (WLADM_STATUS_BADARG);
}
return (WLADM_STATUS_OK);
}
{
return (WLADM_STATUS_BADARG);
return (WLADM_STATUS_OK);
}
{
return (WLADM_STATUS_BADARG);
return (WLADM_STATUS_OK);
}
{
return (WLADM_STATUS_BADARG);
return (WLADM_STATUS_OK);
}
{
return (WLADM_STATUS_OK);
}
{
return (WLADM_STATUS_BADARG);
return (WLADM_STATUS_OK);
}
{
return (WLADM_STATUS_BADARG);
return (WLADM_STATUS_OK);
}
{
&val))
return (WLADM_STATUS_BADARG);
return (WLADM_STATUS_OK);
}
static int
{
int rc;
if (rc > 0)
return (-1);
}
return (0);
}
static int
{
MAX_BUF_LEN));
}
static int
{
}
static int
{
sizeof (wldp_t)));
}
static int
{
}
static int
{
}
static int
{
WLAN_GET_PARAM, sizeof (wldp_t)));
}
static int
{
}
static int
{
}
static int
{
}
static int
{
}
static int
{
}
static int
{
}
static int
{
}
static int
{
}
static int
{
}
static int
{
}
static int
{
}
static int
{
}
static wladm_status_t
{
uint_t i;
return (WLADM_STATUS_TOOSMALL);
if (wrp->wl_rates_rates[0] == 0) {
prop_val[0][0] = '\0';
*val_cnt = 1;
return (WLADM_STATUS_OK);
}
for (i = 0; i < cnt; i++) {
}
return (WLADM_STATUS_OK);
}
static wladm_status_t
{
return (wladm_wlresult2status(gbuf));
}
static wladm_status_t
{
return (WLADM_STATUS_FAILED);
}
static wladm_status_t
{
return (wladm_wlresult2status(gbuf));
return (WLADM_STATUS_NOTFOUND);
*val_cnt = 1;
return (WLADM_STATUS_OK);
}
static wladm_status_t
{
const char *s;
return (wladm_wlresult2status(gbuf));
switch (mode->wl_ps_mode) {
case WL_PM_AM:
s = "off";
break;
case WL_PM_MPS:
s = "max";
break;
case WL_PM_FAST:
s = "fast";
break;
default:
return (WLADM_STATUS_NOTFOUND);
}
*val_cnt = 1;
return (WLADM_STATUS_OK);
}
static wladm_status_t
{
const char *s;
return (wladm_wlresult2status(gbuf));
switch (radio) {
case B_TRUE:
s = "on";
break;
case B_FALSE:
s = "off";
break;
default:
return (WLADM_STATUS_NOTFOUND);
}
*val_cnt = 1;
return (WLADM_STATUS_OK);
}
static int
{
switch (*bsstype) {
case WLADM_BSSTYPE_BSS:
break;
case WLADM_BSSTYPE_IBSS:
break;
default:
break;
}
sizeof (ibsstype)));
}
static int
{
switch (*auth) {
case WLADM_AUTH_OPEN:
break;
case WLADM_AUTH_SHARED:
break;
default:
return (-1);
}
sizeof (auth_mode)));
}
static int
{
switch (*secmode) {
case WLADM_SECMODE_NONE:
break;
case WLADM_SECMODE_WEP:
break;
default:
return (-1);
}
sizeof (encryption)));
}
static int
{
int i;
return (-1);
for (i = 0; i < MAX_NWEPKEYS; i++)
for (i = 0; i < key_count; i++) {
return (-1);
return (-1);
}
sizeof (wepkey_tab)));
}
static int
{
sizeof (iessid.wl_essid_essid));
} else {
return (-1);
}
}
/* ARGSUSED */
static wladm_status_t
{
int i;
if (val_cnt != 1)
return (WLADM_STATUS_BADVALCNT);
goto done;
for (i = 0; i < MAX_SUPPORT_RATES; i++) {
i * WLADM_STRSIZE;
}
if (status != WLADM_STATUS_OK)
goto done;
goto done;
}
for (i = 0; i < modval_cnt; i++) {
break;
}
}
if (i == modval_cnt)
done:
return (status);
}
static wladm_status_t
{
if (val_cnt != 1)
return (WLADM_STATUS_BADVALCNT);
return (wladm_wlresult2status(gbuf));
return (WLADM_STATUS_OK);
}
static int
{
int i;
}
/* ARGSUSED */
static wladm_status_t
{
return (wladm_wlresult2status(gbuf));
return (WLADM_STATUS_OK);
}
static int
{
switch (*pm) {
case WLADM_PM_OFF:
break;
case WLADM_PM_MAX:
break;
case WLADM_PM_FAST:
break;
default:
return (-1);
}
sizeof (ps_mode)));
}
/* ARGSUSED */
static wladm_status_t
{
return (wladm_wlresult2status(gbuf));
return (WLADM_STATUS_OK);
}
static int
{
wl_radio_t r;
switch (*radio) {
case WLADM_RADIO_ON:
r = B_TRUE;
break;
case WLADM_RADIO_OFF:
r = B_FALSE;
break;
default:
return (-1);
}
}
static int
{
if (*channel > MAX_CHANNEL_NUM)
return (-1);
sizeof (phy_conf)));
}
static int
{
}
static void
{
}