Remove station functionality from hostap and madwifi driver wrappers

This has been obsoleted by the more generic Linux WEXT (driver_wext.c)
support. The hostap and madwifi driver wrappers can now be used only
with hostapd. The old station interface remains available in releases up
to 1.x.

Signed-hostap: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2011-11-13 11:13:13 +02:00
parent 3962b65858
commit b6c8df695c
5 changed files with 44 additions and 1121 deletions

View file

@ -23,8 +23,6 @@
#include "driver_hostap.h"
#ifdef HOSTAPD
#include <net/if_arp.h>
#include <netpacket/packet.h>
@ -1171,492 +1169,11 @@ static void wpa_driver_hostap_poll_client(void *priv, const u8 *own_addr,
hostap_send_mlme(priv, (u8 *)&hdr, sizeof(hdr));
}
#else /* HOSTAPD */
struct wpa_driver_hostap_data {
void *wext; /* private data for driver_wext */
void *ctx;
char ifname[IFNAMSIZ + 1];
int sock;
int current_mode; /* infra/adhoc */
};
static int wpa_driver_hostap_set_auth_alg(void *priv, int auth_alg);
static int hostapd_ioctl(struct wpa_driver_hostap_data *drv,
struct prism2_hostapd_param *param,
int len, int show_err)
{
struct iwreq iwr;
os_memset(&iwr, 0, sizeof(iwr));
os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
iwr.u.data.pointer = (caddr_t) param;
iwr.u.data.length = len;
if (ioctl(drv->sock, PRISM2_IOCTL_HOSTAPD, &iwr) < 0) {
int ret = errno;
if (show_err)
perror("ioctl[PRISM2_IOCTL_HOSTAPD]");
return ret;
}
return 0;
}
static int wpa_driver_hostap_set_wpa_ie(struct wpa_driver_hostap_data *drv,
const u8 *wpa_ie, size_t wpa_ie_len)
{
struct prism2_hostapd_param *param;
int res;
size_t blen = PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN + wpa_ie_len;
if (blen < sizeof(*param))
blen = sizeof(*param);
param = os_zalloc(blen);
if (param == NULL)
return -1;
param->cmd = PRISM2_HOSTAPD_SET_GENERIC_ELEMENT;
param->u.generic_elem.len = wpa_ie_len;
os_memcpy(param->u.generic_elem.data, wpa_ie, wpa_ie_len);
res = hostapd_ioctl(drv, param, blen, 1);
os_free(param);
return res;
}
static int prism2param(struct wpa_driver_hostap_data *drv, int param,
int value)
{
struct iwreq iwr;
int *i, ret = 0;
os_memset(&iwr, 0, sizeof(iwr));
os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
i = (int *) iwr.u.name;
*i++ = param;
*i++ = value;
if (ioctl(drv->sock, PRISM2_IOCTL_PRISM2_PARAM, &iwr) < 0) {
perror("ioctl[PRISM2_IOCTL_PRISM2_PARAM]");
ret = -1;
}
return ret;
}
static int wpa_driver_hostap_set_wpa(void *priv, int enabled)
{
struct wpa_driver_hostap_data *drv = priv;
int ret = 0;
wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
if (!enabled && wpa_driver_hostap_set_wpa_ie(drv, NULL, 0) < 0)
ret = -1;
if (prism2param(drv, PRISM2_PARAM_HOST_ROAMING, enabled ? 2 : 0) < 0)
ret = -1;
if (prism2param(drv, PRISM2_PARAM_WPA, enabled) < 0)
ret = -1;
return ret;
}
static void show_set_key_error(struct prism2_hostapd_param *param)
{
switch (param->u.crypt.err) {
case HOSTAP_CRYPT_ERR_UNKNOWN_ALG:
wpa_printf(MSG_INFO, "Unknown algorithm '%s'.",
param->u.crypt.alg);
wpa_printf(MSG_INFO, "You may need to load kernel module to "
"register that algorithm.");
wpa_printf(MSG_INFO, "E.g., 'modprobe hostap_crypt_wep' for "
"WEP.");
break;
case HOSTAP_CRYPT_ERR_UNKNOWN_ADDR:
wpa_printf(MSG_INFO, "Unknown address " MACSTR ".",
MAC2STR(param->sta_addr));
break;
case HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED:
wpa_printf(MSG_INFO, "Crypt algorithm initialization failed.");
break;
case HOSTAP_CRYPT_ERR_KEY_SET_FAILED:
wpa_printf(MSG_INFO, "Key setting failed.");
break;
case HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED:
wpa_printf(MSG_INFO, "TX key index setting failed.");
break;
case HOSTAP_CRYPT_ERR_CARD_CONF_FAILED:
wpa_printf(MSG_INFO, "Card configuration failed.");
break;
}
}
static int wpa_driver_hostap_set_key(const char *ifname, void *priv,
enum wpa_alg alg, const u8 *addr,
int key_idx, int set_tx,
const u8 *seq, size_t seq_len,
const u8 *key, size_t key_len)
{
struct wpa_driver_hostap_data *drv = priv;
struct prism2_hostapd_param *param;
u8 *buf;
size_t blen;
int ret = 0;
char *alg_name;
switch (alg) {
case WPA_ALG_NONE:
alg_name = "none";
break;
case WPA_ALG_WEP:
alg_name = "WEP";
break;
case WPA_ALG_TKIP:
alg_name = "TKIP";
break;
case WPA_ALG_CCMP:
alg_name = "CCMP";
break;
default:
return -1;
}
wpa_printf(MSG_DEBUG, "%s: alg=%s key_idx=%d set_tx=%d seq_len=%lu "
"key_len=%lu", __FUNCTION__, alg_name, key_idx, set_tx,
(unsigned long) seq_len, (unsigned long) key_len);
if (seq_len > 8)
return -2;
blen = sizeof(*param) + key_len;
buf = os_zalloc(blen);
if (buf == NULL)
return -1;
param = (struct prism2_hostapd_param *) buf;
param->cmd = PRISM2_SET_ENCRYPTION;
/* TODO: In theory, STA in client mode can use five keys; four default
* keys for receiving (with keyidx 0..3) and one individual key for
* both transmitting and receiving (keyidx 0) _unicast_ packets. Now,
* keyidx 0 is reserved for this unicast use and default keys can only
* use keyidx 1..3 (i.e., default key with keyidx 0 is not supported).
* This should be fine for more or less all cases, but for completeness
* sake, the driver could be enhanced to support the missing key. */
#if 0
if (addr == NULL)
os_memset(param->sta_addr, 0xff, ETH_ALEN);
else
os_memcpy(param->sta_addr, addr, ETH_ALEN);
#else
os_memset(param->sta_addr, 0xff, ETH_ALEN);
#endif
os_strlcpy((char *) param->u.crypt.alg, alg_name,
HOSTAP_CRYPT_ALG_NAME_LEN);
param->u.crypt.flags = set_tx ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0;
param->u.crypt.idx = key_idx;
if (seq)
os_memcpy(param->u.crypt.seq, seq, seq_len);
param->u.crypt.key_len = key_len;
os_memcpy((u8 *) (param + 1), key, key_len);
if (hostapd_ioctl(drv, param, blen, 1)) {
wpa_printf(MSG_WARNING, "Failed to set encryption.");
show_set_key_error(param);
ret = -1;
}
os_free(buf);
return ret;
}
static int wpa_driver_hostap_set_countermeasures(void *priv, int enabled)
{
struct wpa_driver_hostap_data *drv = priv;
wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
return prism2param(drv, PRISM2_PARAM_TKIP_COUNTERMEASURES, enabled);
}
static int wpa_driver_hostap_reset(struct wpa_driver_hostap_data *drv,
int type)
{
struct iwreq iwr;
int *i, ret = 0;
wpa_printf(MSG_DEBUG, "%s: type=%d", __FUNCTION__, type);
os_memset(&iwr, 0, sizeof(iwr));
os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
i = (int *) iwr.u.name;
*i++ = type;
if (ioctl(drv->sock, PRISM2_IOCTL_RESET, &iwr) < 0) {
perror("ioctl[PRISM2_IOCTL_RESET]");
ret = -1;
}
return ret;
}
static int wpa_driver_hostap_mlme(struct wpa_driver_hostap_data *drv,
const u8 *addr, int cmd, int reason_code)
{
struct prism2_hostapd_param param;
int ret;
/* There does not seem to be a better way of deauthenticating or
* disassociating with Prism2/2.5/3 than sending the management frame
* and then resetting the Port0 to make sure both the AP and the STA
* end up in disconnected state. */
os_memset(&param, 0, sizeof(param));
param.cmd = PRISM2_HOSTAPD_MLME;
os_memcpy(param.sta_addr, addr, ETH_ALEN);
param.u.mlme.cmd = cmd;
param.u.mlme.reason_code = reason_code;
ret = hostapd_ioctl(drv, &param, sizeof(param), 1);
if (ret == 0) {
os_sleep(0, 100000);
ret = wpa_driver_hostap_reset(drv, 2);
}
return ret;
}
static int wpa_driver_hostap_deauthenticate(void *priv, const u8 *addr,
int reason_code)
{
struct wpa_driver_hostap_data *drv = priv;
wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
return wpa_driver_hostap_mlme(drv, addr, MLME_STA_DEAUTH,
reason_code);
}
static int wpa_driver_hostap_disassociate(void *priv, const u8 *addr,
int reason_code)
{
struct wpa_driver_hostap_data *drv = priv;
wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
return wpa_driver_hostap_mlme(drv, addr, MLME_STA_DISASSOC,
reason_code);
}
static int
wpa_driver_hostap_associate(void *priv,
struct wpa_driver_associate_params *params)
{
struct wpa_driver_hostap_data *drv = priv;
int ret = 0;
int allow_unencrypted_eapol;
wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
if (prism2param(drv, PRISM2_PARAM_DROP_UNENCRYPTED,
params->drop_unencrypted) < 0)
ret = -1;
if (wpa_driver_hostap_set_auth_alg(drv, params->auth_alg) < 0)
ret = -1;
if (params->mode != drv->current_mode) {
/* At the moment, Host AP driver requires host_roaming=2 for
* infrastructure mode and host_roaming=0 for adhoc. */
if (prism2param(drv, PRISM2_PARAM_HOST_ROAMING,
params->mode == IEEE80211_MODE_IBSS ? 0 : 2) <
0) {
wpa_printf(MSG_DEBUG, "%s: failed to set host_roaming",
__func__);
}
drv->current_mode = params->mode;
}
if (prism2param(drv, PRISM2_PARAM_PRIVACY_INVOKED,
params->key_mgmt_suite != KEY_MGMT_NONE) < 0)
ret = -1;
if (wpa_driver_hostap_set_wpa_ie(drv, params->wpa_ie,
params->wpa_ie_len) < 0)
ret = -1;
if (wpa_driver_wext_set_mode(drv->wext, params->mode) < 0)
ret = -1;
if (params->freq &&
wpa_driver_wext_set_freq(drv->wext, params->freq) < 0)
ret = -1;
if (wpa_driver_wext_set_ssid(drv->wext, params->ssid, params->ssid_len)
< 0)
ret = -1;
if (wpa_driver_wext_set_bssid(drv->wext, params->bssid) < 0)
ret = -1;
/* Allow unencrypted EAPOL messages even if pairwise keys are set when
* not using WPA. IEEE 802.1X specifies that these frames are not
* encrypted, but WPA encrypts them when pairwise keys are in use. */
if (params->key_mgmt_suite == KEY_MGMT_802_1X ||
params->key_mgmt_suite == KEY_MGMT_PSK)
allow_unencrypted_eapol = 0;
else
allow_unencrypted_eapol = 1;
if (prism2param(drv, PRISM2_PARAM_IEEE_802_1X,
allow_unencrypted_eapol) < 0) {
wpa_printf(MSG_DEBUG, "hostap: Failed to configure "
"ieee_802_1x param");
/* Ignore this error.. driver_hostap.c can also be used with
* other drivers that do not support this prism2_param. */
}
return ret;
}
static int wpa_driver_hostap_scan(void *priv,
struct wpa_driver_scan_params *params)
{
struct wpa_driver_hostap_data *drv = priv;
struct prism2_hostapd_param param;
int ret;
const u8 *ssid = params->ssids[0].ssid;
size_t ssid_len = params->ssids[0].ssid_len;
if (ssid == NULL) {
/* Use standard Linux Wireless Extensions ioctl if possible
* because some drivers using hostap code in wpa_supplicant
* might not support Host AP specific scan request (with SSID
* info). */
return wpa_driver_wext_scan(drv->wext, params);
}
if (ssid_len > 32)
ssid_len = 32;
os_memset(&param, 0, sizeof(param));
param.cmd = PRISM2_HOSTAPD_SCAN_REQ;
param.u.scan_req.ssid_len = ssid_len;
os_memcpy(param.u.scan_req.ssid, ssid, ssid_len);
ret = hostapd_ioctl(drv, &param, sizeof(param), 1);
/* Not all drivers generate "scan completed" wireless event, so try to
* read results after a timeout. */
eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv->wext,
drv->ctx);
eloop_register_timeout(3, 0, wpa_driver_wext_scan_timeout, drv->wext,
drv->ctx);
return ret;
}
static int wpa_driver_hostap_set_auth_alg(void *priv, int auth_alg)
{
struct wpa_driver_hostap_data *drv = priv;
int algs = 0;
if (auth_alg & WPA_AUTH_ALG_OPEN)
algs |= 1;
if (auth_alg & WPA_AUTH_ALG_SHARED)
algs |= 2;
if (auth_alg & WPA_AUTH_ALG_LEAP)
algs |= 4;
if (algs == 0)
algs = 1; /* at least one algorithm should be set */
return prism2param(drv, PRISM2_PARAM_AP_AUTH_ALGS, algs);
}
static int wpa_driver_hostap_get_bssid(void *priv, u8 *bssid)
{
struct wpa_driver_hostap_data *drv = priv;
return wpa_driver_wext_get_bssid(drv->wext, bssid);
}
static int wpa_driver_hostap_get_ssid(void *priv, u8 *ssid)
{
struct wpa_driver_hostap_data *drv = priv;
return wpa_driver_wext_get_ssid(drv->wext, ssid);
}
static struct wpa_scan_results * wpa_driver_hostap_get_scan_results(void *priv)
{
struct wpa_driver_hostap_data *drv = priv;
return wpa_driver_wext_get_scan_results(drv->wext);
}
static int wpa_driver_hostap_set_operstate(void *priv, int state)
{
struct wpa_driver_hostap_data *drv = priv;
return wpa_driver_wext_set_operstate(drv->wext, state);
}
static void * wpa_driver_hostap_init(void *ctx, const char *ifname)
{
struct wpa_driver_hostap_data *drv;
drv = os_zalloc(sizeof(*drv));
if (drv == NULL)
return NULL;
drv->wext = wpa_driver_wext_init(ctx, ifname);
if (drv->wext == NULL) {
os_free(drv);
return NULL;
}
drv->ctx = ctx;
os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
if (drv->sock < 0) {
perror("socket");
wpa_driver_wext_deinit(drv->wext);
os_free(drv);
return NULL;
}
if (os_strncmp(ifname, "wlan", 4) == 0) {
/*
* Host AP driver may use both wlan# and wifi# interface in
* wireless events.
*/
char ifname2[IFNAMSIZ + 1];
os_strlcpy(ifname2, ifname, sizeof(ifname2));
os_memcpy(ifname2, "wifi", 4);
wpa_driver_wext_alternative_ifindex(drv->wext, ifname2);
}
wpa_driver_hostap_set_wpa(drv, 1);
return drv;
}
static void wpa_driver_hostap_deinit(void *priv)
{
struct wpa_driver_hostap_data *drv = priv;
wpa_driver_hostap_set_wpa(drv, 0);
wpa_driver_wext_deinit(drv->wext);
close(drv->sock);
os_free(drv);
}
#endif /* HOSTAPD */
const struct wpa_driver_ops wpa_driver_hostap_ops = {
.name = "hostap",
.desc = "Host AP driver (Intersil Prism2/2.5/3)",
.set_key = wpa_driver_hostap_set_key,
#ifdef HOSTAPD
.hapd_init = hostap_init,
.hapd_deinit = hostap_driver_deinit,
.set_ieee8021x = hostap_set_ieee8021x,
@ -1679,17 +1196,4 @@ const struct wpa_driver_ops wpa_driver_hostap_ops = {
.set_ap_wps_ie = hostap_set_ap_wps_ie,
.set_freq = hostap_set_freq,
.poll_client = wpa_driver_hostap_poll_client,
#else /* HOSTAPD */
.get_bssid = wpa_driver_hostap_get_bssid,
.get_ssid = wpa_driver_hostap_get_ssid,
.set_countermeasures = wpa_driver_hostap_set_countermeasures,
.scan2 = wpa_driver_hostap_scan,
.get_scan_results2 = wpa_driver_hostap_get_scan_results,
.deauthenticate = wpa_driver_hostap_deauthenticate,
.disassociate = wpa_driver_hostap_disassociate,
.associate = wpa_driver_hostap_associate,
.init = wpa_driver_hostap_init,
.deinit = wpa_driver_hostap_deinit,
.set_operstate = wpa_driver_hostap_set_operstate,
#endif /* HOSTAPD */
};

View file

@ -71,8 +71,6 @@
#define WPA_KEY_RSC_LEN 8
#ifdef HOSTAPD
#include "priv_netlink.h"
#include "netlink.h"
#include "linux_ioctl.h"
@ -1294,554 +1292,11 @@ madwifi_commit(void *priv)
return linux_set_iface_flags(drv->ioctl_sock, drv->iface, 1);
}
#else /* HOSTAPD */
struct wpa_driver_madwifi_data {
void *wext; /* private data for driver_wext */
void *ctx;
char ifname[IFNAMSIZ + 1];
int sock;
};
static int wpa_driver_madwifi_set_auth_alg(void *priv, int auth_alg);
static int wpa_driver_madwifi_set_probe_req_ie(void *priv, const u8 *ies,
size_t ies_len);
static int
set80211priv(struct wpa_driver_madwifi_data *drv, int op, void *data, int len,
int show_err)
{
struct iwreq iwr;
os_memset(&iwr, 0, sizeof(iwr));
os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
if (len < IFNAMSIZ &&
op != IEEE80211_IOCTL_SET_APPIEBUF) {
/*
* Argument data fits inline; put it there.
*/
os_memcpy(iwr.u.name, data, len);
} else {
/*
* Argument data too big for inline transfer; setup a
* parameter block instead; the kernel will transfer
* the data for the driver.
*/
iwr.u.data.pointer = data;
iwr.u.data.length = len;
}
if (ioctl(drv->sock, op, &iwr) < 0) {
if (show_err) {
#ifdef MADWIFI_NG
int first = IEEE80211_IOCTL_SETPARAM;
int last = IEEE80211_IOCTL_KICKMAC;
static const char *opnames[] = {
"ioctl[IEEE80211_IOCTL_SETPARAM]",
"ioctl[IEEE80211_IOCTL_GETPARAM]",
"ioctl[IEEE80211_IOCTL_SETMODE]",
"ioctl[IEEE80211_IOCTL_GETMODE]",
"ioctl[IEEE80211_IOCTL_SETWMMPARAMS]",
"ioctl[IEEE80211_IOCTL_GETWMMPARAMS]",
"ioctl[IEEE80211_IOCTL_SETCHANLIST]",
"ioctl[IEEE80211_IOCTL_GETCHANLIST]",
"ioctl[IEEE80211_IOCTL_CHANSWITCH]",
NULL,
"ioctl[IEEE80211_IOCTL_SET_APPIEBUF]",
"ioctl[IEEE80211_IOCTL_GETSCANRESULTS]",
NULL,
"ioctl[IEEE80211_IOCTL_GETCHANINFO]",
"ioctl[IEEE80211_IOCTL_SETOPTIE]",
"ioctl[IEEE80211_IOCTL_GETOPTIE]",
"ioctl[IEEE80211_IOCTL_SETMLME]",
NULL,
"ioctl[IEEE80211_IOCTL_SETKEY]",
NULL,
"ioctl[IEEE80211_IOCTL_DELKEY]",
NULL,
"ioctl[IEEE80211_IOCTL_ADDMAC]",
NULL,
"ioctl[IEEE80211_IOCTL_DELMAC]",
NULL,
"ioctl[IEEE80211_IOCTL_WDSMAC]",
NULL,
"ioctl[IEEE80211_IOCTL_WDSDELMAC]",
NULL,
"ioctl[IEEE80211_IOCTL_KICKMAC]",
};
#else /* MADWIFI_NG */
int first = IEEE80211_IOCTL_SETPARAM;
int last = IEEE80211_IOCTL_CHANLIST;
static const char *opnames[] = {
"ioctl[IEEE80211_IOCTL_SETPARAM]",
"ioctl[IEEE80211_IOCTL_GETPARAM]",
"ioctl[IEEE80211_IOCTL_SETKEY]",
"ioctl[IEEE80211_IOCTL_GETKEY]",
"ioctl[IEEE80211_IOCTL_DELKEY]",
NULL,
"ioctl[IEEE80211_IOCTL_SETMLME]",
NULL,
"ioctl[IEEE80211_IOCTL_SETOPTIE]",
"ioctl[IEEE80211_IOCTL_GETOPTIE]",
"ioctl[IEEE80211_IOCTL_ADDMAC]",
NULL,
"ioctl[IEEE80211_IOCTL_DELMAC]",
NULL,
"ioctl[IEEE80211_IOCTL_CHANLIST]",
};
#endif /* MADWIFI_NG */
int idx = op - first;
if (first <= op && op <= last &&
idx < (int) (sizeof(opnames) / sizeof(opnames[0]))
&& opnames[idx])
perror(opnames[idx]);
else
perror("ioctl[unknown???]");
}
return -1;
}
return 0;
}
static int
set80211param(struct wpa_driver_madwifi_data *drv, int op, int arg,
int show_err)
{
struct iwreq iwr;
os_memset(&iwr, 0, sizeof(iwr));
os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
iwr.u.mode = op;
os_memcpy(iwr.u.name+sizeof(u32), &arg, sizeof(arg));
if (ioctl(drv->sock, IEEE80211_IOCTL_SETPARAM, &iwr) < 0) {
if (show_err)
perror("ioctl[IEEE80211_IOCTL_SETPARAM]");
return -1;
}
return 0;
}
static int
wpa_driver_madwifi_set_wpa_ie(struct wpa_driver_madwifi_data *drv,
const u8 *wpa_ie, size_t wpa_ie_len)
{
struct iwreq iwr;
os_memset(&iwr, 0, sizeof(iwr));
os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
/* NB: SETOPTIE is not fixed-size so must not be inlined */
iwr.u.data.pointer = (void *) wpa_ie;
iwr.u.data.length = wpa_ie_len;
if (ioctl(drv->sock, IEEE80211_IOCTL_SETOPTIE, &iwr) < 0) {
perror("ioctl[IEEE80211_IOCTL_SETOPTIE]");
return -1;
}
return 0;
}
static int
wpa_driver_madwifi_del_key(struct wpa_driver_madwifi_data *drv, int key_idx,
const u8 *addr)
{
struct ieee80211req_del_key wk;
wpa_printf(MSG_DEBUG, "%s: keyidx=%d", __FUNCTION__, key_idx);
os_memset(&wk, 0, sizeof(wk));
wk.idk_keyix = key_idx;
if (addr != NULL)
os_memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN);
return set80211priv(drv, IEEE80211_IOCTL_DELKEY, &wk, sizeof(wk), 1);
}
static int
wpa_driver_madwifi_set_key(const char *ifname, void *priv, enum wpa_alg alg,
const u8 *addr, int key_idx, int set_tx,
const u8 *seq, size_t seq_len,
const u8 *key, size_t key_len)
{
struct wpa_driver_madwifi_data *drv = priv;
struct ieee80211req_key wk;
char *alg_name;
u_int8_t cipher;
if (alg == WPA_ALG_NONE)
return wpa_driver_madwifi_del_key(drv, key_idx, addr);
switch (alg) {
case WPA_ALG_WEP:
if (addr == NULL || os_memcmp(addr, "\xff\xff\xff\xff\xff\xff",
ETH_ALEN) == 0) {
/*
* madwifi did not seem to like static WEP key
* configuration with IEEE80211_IOCTL_SETKEY, so use
* Linux wireless extensions ioctl for this.
*/
return wpa_driver_wext_set_key(ifname, drv->wext, alg,
addr, key_idx, set_tx,
seq, seq_len,
key, key_len);
}
alg_name = "WEP";
cipher = IEEE80211_CIPHER_WEP;
break;
case WPA_ALG_TKIP:
alg_name = "TKIP";
cipher = IEEE80211_CIPHER_TKIP;
break;
case WPA_ALG_CCMP:
alg_name = "CCMP";
cipher = IEEE80211_CIPHER_AES_CCM;
break;
default:
wpa_printf(MSG_DEBUG, "%s: unknown/unsupported algorithm %d",
__FUNCTION__, alg);
return -1;
}
wpa_printf(MSG_DEBUG, "%s: alg=%s key_idx=%d set_tx=%d seq_len=%lu "
"key_len=%lu", __FUNCTION__, alg_name, key_idx, set_tx,
(unsigned long) seq_len, (unsigned long) key_len);
if (seq_len > sizeof(u_int64_t)) {
wpa_printf(MSG_DEBUG, "%s: seq_len %lu too big",
__FUNCTION__, (unsigned long) seq_len);
return -2;
}
if (key_len > sizeof(wk.ik_keydata)) {
wpa_printf(MSG_DEBUG, "%s: key length %lu too big",
__FUNCTION__, (unsigned long) key_len);
return -3;
}
os_memset(&wk, 0, sizeof(wk));
wk.ik_type = cipher;
wk.ik_flags = IEEE80211_KEY_RECV;
if (addr == NULL ||
os_memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0)
wk.ik_flags |= IEEE80211_KEY_GROUP;
if (set_tx) {
wk.ik_flags |= IEEE80211_KEY_XMIT | IEEE80211_KEY_DEFAULT;
os_memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
} else
os_memset(wk.ik_macaddr, 0, IEEE80211_ADDR_LEN);
wk.ik_keyix = key_idx;
wk.ik_keylen = key_len;
#ifdef WORDS_BIGENDIAN
if (seq) {
size_t i;
u8 tmp[WPA_KEY_RSC_LEN];
os_memset(tmp, 0, sizeof(tmp));
for (i = 0; i < seq_len; i++)
tmp[WPA_KEY_RSC_LEN - i - 1] = seq[i];
os_memcpy(&wk.ik_keyrsc, tmp, WPA_KEY_RSC_LEN);
}
#else /* WORDS_BIGENDIAN */
if (seq)
os_memcpy(&wk.ik_keyrsc, seq, seq_len);
#endif /* WORDS_BIGENDIAN */
os_memcpy(wk.ik_keydata, key, key_len);
return set80211priv(drv, IEEE80211_IOCTL_SETKEY, &wk, sizeof(wk), 1);
}
static int
wpa_driver_madwifi_set_countermeasures(void *priv, int enabled)
{
struct wpa_driver_madwifi_data *drv = priv;
wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
return set80211param(drv, IEEE80211_PARAM_COUNTERMEASURES, enabled, 1);
}
static int
wpa_driver_madwifi_deauthenticate(void *priv, const u8 *addr, int reason_code)
{
struct wpa_driver_madwifi_data *drv = priv;
struct ieee80211req_mlme mlme;
wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
mlme.im_op = IEEE80211_MLME_DEAUTH;
mlme.im_reason = reason_code;
os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
return set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme), 1);
}
static int
wpa_driver_madwifi_disassociate(void *priv, const u8 *addr, int reason_code)
{
struct wpa_driver_madwifi_data *drv = priv;
struct ieee80211req_mlme mlme;
wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
mlme.im_op = IEEE80211_MLME_DISASSOC;
mlme.im_reason = reason_code;
os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
return set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme), 1);
}
static int
wpa_driver_madwifi_associate(void *priv,
struct wpa_driver_associate_params *params)
{
struct wpa_driver_madwifi_data *drv = priv;
struct ieee80211req_mlme mlme;
int ret = 0, privacy = 1;
wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
if (set80211param(drv, IEEE80211_PARAM_DROPUNENCRYPTED,
params->drop_unencrypted, 1) < 0)
ret = -1;
if (wpa_driver_madwifi_set_auth_alg(drv, params->auth_alg) < 0)
ret = -1;
/*
* NB: Don't need to set the freq or cipher-related state as
* this is implied by the bssid which is used to locate
* the scanned node state which holds it. The ssid is
* needed to disambiguate an AP that broadcasts multiple
* ssid's but uses the same bssid.
*/
/* XXX error handling is wrong but unclear what to do... */
if (wpa_driver_madwifi_set_wpa_ie(drv, params->wpa_ie,
params->wpa_ie_len) < 0)
ret = -1;
if (params->pairwise_suite == CIPHER_NONE &&
params->group_suite == CIPHER_NONE &&
params->key_mgmt_suite == KEY_MGMT_NONE &&
params->wpa_ie_len == 0)
privacy = 0;
if (set80211param(drv, IEEE80211_PARAM_PRIVACY, privacy, 1) < 0)
ret = -1;
if (params->wpa_ie_len &&
set80211param(drv, IEEE80211_PARAM_WPA,
params->wpa_ie[0] == WLAN_EID_RSN ? 2 : 1, 1) < 0)
ret = -1;
if (params->bssid == NULL) {
/* ap_scan=2 mode - driver takes care of AP selection and
* roaming */
/* FIX: this does not seem to work; would probably need to
* change something in the driver */
if (set80211param(drv, IEEE80211_PARAM_ROAMING, 0, 1) < 0)
ret = -1;
if (wpa_driver_wext_set_ssid(drv->wext, params->ssid,
params->ssid_len) < 0)
ret = -1;
} else {
if (set80211param(drv, IEEE80211_PARAM_ROAMING, 2, 1) < 0)
ret = -1;
if (wpa_driver_wext_set_ssid(drv->wext, params->ssid,
params->ssid_len) < 0)
ret = -1;
os_memset(&mlme, 0, sizeof(mlme));
mlme.im_op = IEEE80211_MLME_ASSOC;
os_memcpy(mlme.im_macaddr, params->bssid, IEEE80211_ADDR_LEN);
if (set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme,
sizeof(mlme), 1) < 0) {
wpa_printf(MSG_DEBUG, "%s: SETMLME[ASSOC] failed",
__func__);
ret = -1;
}
}
return ret;
}
static int
wpa_driver_madwifi_set_auth_alg(void *priv, int auth_alg)
{
struct wpa_driver_madwifi_data *drv = priv;
int authmode;
if ((auth_alg & WPA_AUTH_ALG_OPEN) &&
(auth_alg & WPA_AUTH_ALG_SHARED))
authmode = IEEE80211_AUTH_AUTO;
else if (auth_alg & WPA_AUTH_ALG_SHARED)
authmode = IEEE80211_AUTH_SHARED;
else
authmode = IEEE80211_AUTH_OPEN;
return set80211param(drv, IEEE80211_PARAM_AUTHMODE, authmode, 1);
}
static int
wpa_driver_madwifi_scan(void *priv, struct wpa_driver_scan_params *params)
{
struct wpa_driver_madwifi_data *drv = priv;
struct iwreq iwr;
int ret = 0;
const u8 *ssid = params->ssids[0].ssid;
size_t ssid_len = params->ssids[0].ssid_len;
wpa_driver_madwifi_set_probe_req_ie(drv, params->extra_ies,
params->extra_ies_len);
os_memset(&iwr, 0, sizeof(iwr));
os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
/* set desired ssid before scan */
/* FIX: scan should not break the current association, so using
* set_ssid may not be the best way of doing this.. */
if (wpa_driver_wext_set_ssid(drv->wext, ssid, ssid_len) < 0)
ret = -1;
if (ioctl(drv->sock, SIOCSIWSCAN, &iwr) < 0) {
perror("ioctl[SIOCSIWSCAN]");
ret = -1;
}
/*
* madwifi delivers a scan complete event so no need to poll, but
* register a backup timeout anyway to make sure that we recover even
* if the driver does not send this event for any reason. This timeout
* will only be used if the event is not delivered (event handler will
* cancel the timeout).
*/
eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv->wext,
drv->ctx);
eloop_register_timeout(30, 0, wpa_driver_wext_scan_timeout, drv->wext,
drv->ctx);
return ret;
}
static int wpa_driver_madwifi_get_bssid(void *priv, u8 *bssid)
{
struct wpa_driver_madwifi_data *drv = priv;
return wpa_driver_wext_get_bssid(drv->wext, bssid);
}
static int wpa_driver_madwifi_get_ssid(void *priv, u8 *ssid)
{
struct wpa_driver_madwifi_data *drv = priv;
return wpa_driver_wext_get_ssid(drv->wext, ssid);
}
static struct wpa_scan_results *
wpa_driver_madwifi_get_scan_results(void *priv)
{
struct wpa_driver_madwifi_data *drv = priv;
return wpa_driver_wext_get_scan_results(drv->wext);
}
static int wpa_driver_madwifi_set_operstate(void *priv, int state)
{
struct wpa_driver_madwifi_data *drv = priv;
return wpa_driver_wext_set_operstate(drv->wext, state);
}
static int wpa_driver_madwifi_set_probe_req_ie(void *priv, const u8 *ies,
size_t ies_len)
{
struct ieee80211req_getset_appiebuf *probe_req_ie;
int ret;
probe_req_ie = os_malloc(sizeof(*probe_req_ie) + ies_len);
if (probe_req_ie == NULL)
return -1;
probe_req_ie->app_frmtype = IEEE80211_APPIE_FRAME_PROBE_REQ;
probe_req_ie->app_buflen = ies_len;
os_memcpy(probe_req_ie->app_buf, ies, ies_len);
ret = set80211priv(priv, IEEE80211_IOCTL_SET_APPIEBUF, probe_req_ie,
sizeof(struct ieee80211req_getset_appiebuf) +
ies_len, 1);
os_free(probe_req_ie);
return ret;
}
static void * wpa_driver_madwifi_init(void *ctx, const char *ifname)
{
struct wpa_driver_madwifi_data *drv;
drv = os_zalloc(sizeof(*drv));
if (drv == NULL)
return NULL;
drv->wext = wpa_driver_wext_init(ctx, ifname);
if (drv->wext == NULL)
goto fail;
drv->ctx = ctx;
os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
if (drv->sock < 0)
goto fail2;
if (set80211param(drv, IEEE80211_PARAM_ROAMING, 2, 1) < 0) {
wpa_printf(MSG_DEBUG, "%s: failed to set wpa_supplicant-based "
"roaming", __FUNCTION__);
goto fail3;
}
if (set80211param(drv, IEEE80211_PARAM_WPA, 3, 1) < 0) {
wpa_printf(MSG_DEBUG, "%s: failed to enable WPA support",
__FUNCTION__);
goto fail3;
}
return drv;
fail3:
close(drv->sock);
fail2:
wpa_driver_wext_deinit(drv->wext);
fail:
os_free(drv);
return NULL;
}
static void wpa_driver_madwifi_deinit(void *priv)
{
struct wpa_driver_madwifi_data *drv = priv;
if (wpa_driver_madwifi_set_wpa_ie(drv, NULL, 0) < 0) {
wpa_printf(MSG_DEBUG, "%s: failed to clear WPA IE",
__FUNCTION__);
}
if (set80211param(drv, IEEE80211_PARAM_ROAMING, 0, 1) < 0) {
wpa_printf(MSG_DEBUG, "%s: failed to enable driver-based "
"roaming", __FUNCTION__);
}
if (set80211param(drv, IEEE80211_PARAM_PRIVACY, 0, 1) < 0) {
wpa_printf(MSG_DEBUG, "%s: failed to disable forced Privacy "
"flag", __FUNCTION__);
}
if (set80211param(drv, IEEE80211_PARAM_WPA, 0, 1) < 0) {
wpa_printf(MSG_DEBUG, "%s: failed to disable WPA",
__FUNCTION__);
}
wpa_driver_wext_deinit(drv->wext);
close(drv->sock);
os_free(drv);
}
#endif /* HOSTAPD */
const struct wpa_driver_ops wpa_driver_madwifi_ops = {
.name = "madwifi",
.desc = "MADWIFI 802.11 support (Atheros, etc.)",
.set_key = wpa_driver_madwifi_set_key,
#ifdef HOSTAPD
.hapd_init = madwifi_init,
.hapd_deinit = madwifi_deinit,
.set_ieee8021x = madwifi_set_ieee8021x,
@ -1861,17 +1316,4 @@ const struct wpa_driver_ops wpa_driver_madwifi_ops = {
.commit = madwifi_commit,
.set_ap_wps_ie = madwifi_set_ap_wps_ie,
.set_freq = madwifi_set_freq,
#else /* HOSTAPD */
.get_bssid = wpa_driver_madwifi_get_bssid,
.get_ssid = wpa_driver_madwifi_get_ssid,
.init = wpa_driver_madwifi_init,
.deinit = wpa_driver_madwifi_deinit,
.set_countermeasures = wpa_driver_madwifi_set_countermeasures,
.scan2 = wpa_driver_madwifi_scan,
.get_scan_results2 = wpa_driver_madwifi_get_scan_results,
.deauthenticate = wpa_driver_madwifi_deauthenticate,
.disassociate = wpa_driver_madwifi_disassociate,
.associate = wpa_driver_madwifi_associate,
.set_operstate = wpa_driver_madwifi_set_operstate,
#endif /* HOSTAPD */
};

View file

@ -12,29 +12,11 @@ DRV_AP_LIBS =
##### COMMON DRIVERS
ifdef CONFIG_DRIVER_HOSTAP
DRV_CFLAGS += -DCONFIG_DRIVER_HOSTAP
DRV_OBJS += ../src/drivers/driver_hostap.o
CONFIG_WIRELESS_EXTENSION=y
NEED_AP_MLME=y
NEED_NETLINK=y
NEED_LINUX_IOCTL=y
endif
ifdef CONFIG_DRIVER_WIRED
DRV_CFLAGS += -DCONFIG_DRIVER_WIRED
DRV_OBJS += ../src/drivers/driver_wired.o
endif
ifdef CONFIG_DRIVER_MADWIFI
DRV_CFLAGS += -DCONFIG_DRIVER_MADWIFI
DRV_OBJS += ../src/drivers/driver_madwifi.o
CONFIG_WIRELESS_EXTENSION=y
CONFIG_L2_PACKET=linux
NEED_NETLINK=y
NEED_LINUX_IOCTL=y
endif
ifdef CONFIG_DRIVER_NL80211
DRV_CFLAGS += -DCONFIG_DRIVER_NL80211
DRV_OBJS += ../src/drivers/driver_nl80211.o
@ -79,6 +61,24 @@ endif
##### PURE AP DRIVERS
ifdef CONFIG_DRIVER_HOSTAP
DRV_AP_CFLAGS += -DCONFIG_DRIVER_HOSTAP
DRV_AP_OBJS += ../src/drivers/driver_hostap.o
CONFIG_WIRELESS_EXTENSION=y
NEED_AP_MLME=y
NEED_NETLINK=y
NEED_LINUX_IOCTL=y
endif
ifdef CONFIG_DRIVER_MADWIFI
DRV_AP_CFLAGS += -DCONFIG_DRIVER_MADWIFI
DRV_AP_OBJS += ../src/drivers/driver_madwifi.o
CONFIG_WIRELESS_EXTENSION=y
CONFIG_L2_PACKET=linux
NEED_NETLINK=y
NEED_LINUX_IOCTL=y
endif
ifdef CONFIG_DRIVER_ATHEROS
DRV_AP_CFLAGS += -DCONFIG_DRIVER_ATHEROS
DRV_AP_OBJS += ../src/drivers/driver_atheros.o

View file

@ -12,29 +12,11 @@ DRV_AP_LIBS =
##### COMMON DRIVERS
ifdef CONFIG_DRIVER_HOSTAP
DRV_CFLAGS += -DCONFIG_DRIVER_HOSTAP
DRV_OBJS += src/drivers/driver_hostap.c
CONFIG_WIRELESS_EXTENSION=y
NEED_AP_MLME=y
NEED_NETLINK=y
NEED_LINUX_IOCTL=y
endif
ifdef CONFIG_DRIVER_WIRED
DRV_CFLAGS += -DCONFIG_DRIVER_WIRED
DRV_OBJS += src/drivers/driver_wired.c
endif
ifdef CONFIG_DRIVER_MADWIFI
DRV_CFLAGS += -DCONFIG_DRIVER_MADWIFI
DRV_OBJS += src/drivers/driver_madwifi.c
CONFIG_WIRELESS_EXTENSION=y
CONFIG_L2_PACKET=linux
NEED_NETLINK=y
NEED_LINUX_IOCTL=y
endif
ifdef CONFIG_DRIVER_NL80211
DRV_CFLAGS += -DCONFIG_DRIVER_NL80211
DRV_OBJS += src/drivers/driver_nl80211.c
@ -79,6 +61,24 @@ endif
##### PURE AP DRIVERS
ifdef CONFIG_DRIVER_HOSTAP
DRV_AP_CFLAGS += -DCONFIG_DRIVER_HOSTAP
DRV_AP_OBJS += src/drivers/driver_hostap.c
CONFIG_WIRELESS_EXTENSION=y
NEED_AP_MLME=y
NEED_NETLINK=y
NEED_LINUX_IOCTL=y
endif
ifdef CONFIG_DRIVER_MADWIFI
DRV_AP_CFLAGS += -DCONFIG_DRIVER_MADWIFI
DRV_AP_OBJS += src/drivers/driver_madwifi.c
CONFIG_WIRELESS_EXTENSION=y
CONFIG_L2_PACKET=linux
NEED_NETLINK=y
NEED_LINUX_IOCTL=y
endif
ifdef CONFIG_DRIVER_ATHEROS
DRV_AP_CFLAGS += -DCONFIG_DRIVER_ATHEROS
DRV_AP_OBJS += src/drivers/driver_atheros.c

View file

@ -138,24 +138,6 @@ Current hardware/software requirements:
default option to start with before falling back to driver specific
interface.
Host AP driver for Prism2/2.5/3 (development snapshot/v0.2.x)
(http://hostap.epitest.fi/)
Driver need to be set in Managed mode ('iwconfig wlan0 mode managed').
Please note that station firmware version needs to be 1.7.0 or newer
to work in WPA mode.
Linuxant DriverLoader (http://www.linuxant.com/driverloader/)
with Windows NDIS driver for your wlan card supporting WPA.
madwifi driver for cards based on Atheros chip set (ar521x)
(http://sourceforge.net/projects/madwifi/)
Please note that you will need to modify the wpa_supplicant .config
file to use the correct path for the madwifi driver root directory
(CFLAGS += -I../madwifi/wpa line in example defconfig).
Linux ndiswrapper (http://ndiswrapper.sourceforge.net/) with
Windows NDIS driver.
In theory, any driver that supports Linux wireless extensions can be
used with IEEE 802.1X (i.e., not WPA) when using ap_scan=0 option in
configuration file.
@ -332,7 +314,7 @@ and a list of available options and additional notes.
The build time configuration can be used to select only the needed
features and limit the binary size and requirements for external
libraries. The main configuration parts are the selection of which
driver interfaces (e.g., hostap, madwifi, ..) and which authentication
driver interfaces (e.g., nl80211, wext, ..) and which authentication
methods (e.g., EAP-TLS, EAP-PEAP, ..) are included.
Following build time configuration options are used to control IEEE
@ -367,17 +349,15 @@ CONFIG_PCSC=y
Following options can be added to .config to select which driver
interfaces are included.
CONFIG_DRIVER_HOSTAP=y
CONFIG_DRIVER_MADWIFI=y
CONFIG_DRIVER_NL80211=y
CONFIG_DRIVER_WEXT=y
CONFIG_DRIVER_BSD=y
CONFIG_DRIVER_NDIS=y
Following example includes all features and driver interfaces that are
included in the wpa_supplicant package:
Following example includes some more features and driver interfaces that
are included in the wpa_supplicant package:
CONFIG_DRIVER_HOSTAP=y
CONFIG_DRIVER_MADWIFI=y
CONFIG_DRIVER_NL80211=y
CONFIG_DRIVER_WEXT=y
CONFIG_DRIVER_BSD=y
CONFIG_DRIVER_NDIS=y
@ -471,9 +451,6 @@ options:
-N = start describing new interface
drivers:
hostap = Host AP driver (Intersil Prism2/2.5/3) [default]
(this can also be used with Linuxant DriverLoader)
madwifi = MADWIFI 802.11 support (Atheros, etc.) (deprecated; use wext)
wext = Linux wireless extensions (generic)
wired = wpa_supplicant wired Ethernet driver
roboswitch = wpa_supplicant Broadcom switch driver
@ -507,15 +484,15 @@ separated with -N argument. As an example, following command would
start wpa_supplicant for two interfaces:
wpa_supplicant \
-c wpa1.conf -i wlan0 -D hostap -N \
-c wpa2.conf -i ath0 -D madwifi
-c wpa1.conf -i wlan0 -D nl80211 -N \
-c wpa2.conf -i wlan1 -D wext
If the interface is added in a Linux bridge (e.g., br0), the bridge
interface needs to be configured to wpa_supplicant in addition to the
main interface:
wpa_supplicant -cw.conf -Dmadwifi -iath0 -bbr0
wpa_supplicant -cw.conf -Dwext -iwlan0 -bbr0
Configuration file