Updated userspace MLME instructions for current mac80211

Remove the old code from driver_wext.c since the private ioctl interface is
never going to be used with mac80211. driver_nl80211.c has an
implementation than can be used with mac80211 (with two external patches to
enable userspace MLME configuration are still required, though).
This commit is contained in:
Jouni Malinen 2008-11-18 15:45:25 +02:00 committed by Jouni Malinen
parent bac912e5bd
commit cd35db9fef
3 changed files with 11 additions and 487 deletions

View file

@ -31,126 +31,6 @@
#include "ieee802_11_defs.h" #include "ieee802_11_defs.h"
#include "wpa_common.h" #include "wpa_common.h"
#ifdef CONFIG_CLIENT_MLME
#include <netpacket/packet.h>
/* old definitions from net/mac80211 */
typedef u32 __bitwise __be32;
typedef u64 __bitwise __be64;
#define PRISM2_IOCTL_PRISM2_PARAM (SIOCIWFIRSTPRIV + 0)
#define PRISM2_IOCTL_GET_PRISM2_PARAM (SIOCIWFIRSTPRIV + 1)
#define PRISM2_IOCTL_HOSTAPD (SIOCIWFIRSTPRIV + 3)
#define PRISM2_PARAM_USER_SPACE_MLME 1045
#define PRISM2_PARAM_MGMT_IF 1046
#define PRISM2_HOSTAPD_ADD_STA 2
#define PRISM2_HOSTAPD_REMOVE_STA 3
#define PRISM2_HOSTAPD_GET_HW_FEATURES 1002
#define PRISM2_HOSTAPD_MAX_BUF_SIZE 2048
#ifndef ALIGNED
#define ALIGNED __attribute__ ((aligned))
#endif
struct prism2_hostapd_param {
u32 cmd;
u8 sta_addr[ETH_ALEN];
u8 pad[2];
union {
struct {
u16 aid;
u16 capability;
u8 supp_rates[32];
u8 wds_flags;
#define IEEE80211_STA_DYNAMIC_ENC BIT(0)
u8 enc_flags;
u16 listen_interval;
} add_sta;
struct {
u16 num_modes;
u16 flags;
u8 data[0] ALIGNED; /* num_modes * feature data */
} hw_features;
struct {
u16 mode; /* MODE_* */
u16 num_supported_rates;
u16 num_basic_rates;
u8 data[0] ALIGNED; /* num_supported_rates * u16 +
* num_basic_rates * u16 */
} set_rate_sets;
struct {
u16 mode; /* MODE_* */
u16 chan;
u32 flag;
u8 power_level; /* regulatory limit in dBm */
u8 antenna_max;
} set_channel_flag;
struct {
u32 rd;
} set_regulatory_domain;
struct {
u32 queue;
s32 aifs;
u32 cw_min;
u32 cw_max;
u32 burst_time; /* maximum burst time in 0.1 ms, i.e.,
* 10 = 1 ms */
} tx_queue_params;
} u;
};
struct hostapd_ioctl_hw_modes_hdr {
int mode;
int num_channels;
int num_rates;
};
/*
* frame format for the management interface that is slated
* to be replaced by "cooked monitor" with radiotap
*/
#define IEEE80211_FI_VERSION 0x80211001
struct ieee80211_frame_info {
__be32 version;
__be32 length;
__be64 mactime;
__be64 hosttime;
__be32 phytype;
__be32 channel;
__be32 datarate;
__be32 antenna;
__be32 priority;
__be32 ssi_type;
__be32 ssi_signal;
__be32 ssi_noise;
__be32 preamble;
__be32 encoding;
/* Note: this structure is otherwise identical to capture format used
* in linux-wlan-ng, but this additional field is used to provide meta
* data about the frame to hostapd. This was the easiest method for
* providing this information, but this might change in the future. */
__be32 msg_type;
} __attribute__ ((packed));
/* old mode definitions */
enum {
MODE_IEEE80211A = 0 /* IEEE 802.11a */,
MODE_IEEE80211B = 1 /* IEEE 802.11b only */,
MODE_ATHEROS_TURBO = 2 /* Atheros Turbo mode (2x.11a at 5 GHz) */,
MODE_IEEE80211G = 3 /* IEEE 802.11g (and 802.11b compatibility) */,
MODE_ATHEROS_TURBOG = 4 /* Atheros Turbo mode (2x.11g at 2.4 GHz) */,
NUM_IEEE80211_MODES = 5
};
#ifndef ETH_P_ALL
#define ETH_P_ALL 0x0003
#endif
#endif /* CONFIG_CLIENT_MLME */
static int wpa_driver_wext_flush_pmkid(void *priv); static int wpa_driver_wext_flush_pmkid(void *priv);
static int wpa_driver_wext_get_range(void *priv); static int wpa_driver_wext_get_range(void *priv);
@ -999,46 +879,6 @@ static int wpa_driver_wext_set_ifflags_ifname(struct wpa_driver_wext_data *drv,
} }
#ifdef CONFIG_CLIENT_MLME
static int wpa_driver_prism2_param_set(struct wpa_driver_wext_data *drv,
int param, int value)
{
struct iwreq iwr;
int *i;
os_memset(&iwr, 0, sizeof(iwr));
os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
i = (int *) iwr.u.name;
*i++ = param;
*i++ = value;
return ioctl(drv->ioctl_sock, PRISM2_IOCTL_PRISM2_PARAM, &iwr);
}
static int wpa_driver_prism2_param_get(struct wpa_driver_wext_data *drv,
int param)
{
struct iwreq iwr;
int *i;
os_memset(&iwr, 0, sizeof(iwr));
os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
i = (int *) iwr.u.name;
*i = param;
if (ioctl(drv->ioctl_sock, PRISM2_IOCTL_GET_PRISM2_PARAM, &iwr) < 0) {
perror("ioctl[PRISM2_IOCTL_GET_PRISM2_PARAM]");
return -1;
}
return *i;
}
#endif /* CONFIG_CLIENT_MLME */
/** /**
* wpa_driver_wext_set_ifflags - Set interface flags (SIOCSIFFLAGS) * wpa_driver_wext_set_ifflags - Set interface flags (SIOCSIFFLAGS)
* @drv: driver_wext private data * @drv: driver_wext private data
@ -1193,18 +1033,6 @@ void wpa_driver_wext_deinit(void *priv)
if (wpa_driver_wext_get_ifflags(drv, &flags) == 0) if (wpa_driver_wext_get_ifflags(drv, &flags) == 0)
(void) wpa_driver_wext_set_ifflags(drv, flags & ~IFF_UP); (void) wpa_driver_wext_set_ifflags(drv, flags & ~IFF_UP);
#ifdef CONFIG_CLIENT_MLME
if (drv->mlmedev[0]) {
if (wpa_driver_wext_get_ifflags_ifname(drv, drv->mlmedev,
&flags) == 0)
(void) wpa_driver_wext_set_ifflags_ifname(
drv, drv->mlmedev, flags & ~IFF_UP);
wpa_driver_prism2_param_set(drv, PRISM2_PARAM_MGMT_IF, 0);
wpa_driver_prism2_param_set(drv, PRISM2_PARAM_USER_SPACE_MLME,
0);
}
#endif /* CONFIG_CLIENT_MLME */
close(drv->event_sock); close(drv->event_sock);
close(drv->ioctl_sock); close(drv->ioctl_sock);
if (drv->mlme_sock >= 0) if (drv->mlme_sock >= 0)
@ -2463,304 +2291,6 @@ int wpa_driver_wext_set_operstate(void *priv, int state)
} }
#ifdef CONFIG_CLIENT_MLME
static int hostapd_ioctl(struct wpa_driver_wext_data *drv,
struct prism2_hostapd_param *param, int len)
{
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->ioctl_sock, PRISM2_IOCTL_HOSTAPD, &iwr) < 0) {
perror("ioctl[PRISM2_IOCTL_HOSTAPD]");
return -1;
}
return 0;
}
static struct wpa_hw_modes *
wpa_driver_wext_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags)
{
struct wpa_driver_wext_data *drv = priv;
struct prism2_hostapd_param *param;
u8 *pos, *end;
struct wpa_hw_modes *modes = NULL;
int i;
param = os_zalloc(PRISM2_HOSTAPD_MAX_BUF_SIZE);
if (param == NULL)
return NULL;
param->cmd = PRISM2_HOSTAPD_GET_HW_FEATURES;
if (hostapd_ioctl(drv, param, PRISM2_HOSTAPD_MAX_BUF_SIZE) < 0) {
perror("ioctl[PRISM2_IOCTL_HOSTAPD]");
goto out;
}
*num_modes = param->u.hw_features.num_modes;
*flags = param->u.hw_features.flags;
pos = param->u.hw_features.data;
end = pos + PRISM2_HOSTAPD_MAX_BUF_SIZE -
(param->u.hw_features.data - (u8 *) param);
modes = os_zalloc(*num_modes * sizeof(struct wpa_hw_modes));
if (modes == NULL)
goto out;
for (i = 0; i < *num_modes; i++) {
struct hostapd_ioctl_hw_modes_hdr *hdr;
struct wpa_hw_modes *feature;
int clen, rlen;
hdr = (struct hostapd_ioctl_hw_modes_hdr *) pos;
pos = (u8 *) (hdr + 1);
clen = hdr->num_channels * sizeof(struct wpa_channel_data);
rlen = hdr->num_rates * sizeof(struct wpa_rate_data);
feature = &modes[i];
switch (hdr->mode) {
case MODE_IEEE80211A:
feature->mode = WPA_MODE_IEEE80211A;
break;
case MODE_IEEE80211B:
feature->mode = WPA_MODE_IEEE80211B;
break;
case MODE_IEEE80211G:
feature->mode = WPA_MODE_IEEE80211G;
break;
case MODE_ATHEROS_TURBO:
case MODE_ATHEROS_TURBOG:
wpa_printf(MSG_ERROR, "Skip unsupported hw_mode=%d in "
"get_hw_features data", hdr->mode);
pos += clen + rlen;
continue;
default:
wpa_printf(MSG_ERROR, "Unknown hw_mode=%d in "
"get_hw_features data", hdr->mode);
wpa_supplicant_sta_free_hw_features(modes, *num_modes);
modes = NULL;
break;
}
feature->num_channels = hdr->num_channels;
feature->num_rates = hdr->num_rates;
feature->channels = os_malloc(clen);
feature->rates = os_malloc(rlen);
if (!feature->channels || !feature->rates ||
pos + clen + rlen > end) {
wpa_supplicant_sta_free_hw_features(modes, *num_modes);
modes = NULL;
break;
}
os_memcpy(feature->channels, pos, clen);
pos += clen;
os_memcpy(feature->rates, pos, rlen);
pos += rlen;
}
out:
os_free(param);
return modes;
}
int wpa_driver_wext_set_channel(void *priv, wpa_hw_mode phymode, int chan,
int freq)
{
return wpa_driver_wext_set_freq(priv, freq);
}
static void wpa_driver_wext_mlme_read(int sock, void *eloop_ctx,
void *sock_ctx)
{
struct wpa_driver_wext_data *drv = eloop_ctx;
int len;
unsigned char buf[3000];
struct ieee80211_frame_info *fi;
struct ieee80211_rx_status rx_status;
len = recv(sock, buf, sizeof(buf), 0);
if (len < 0) {
perror("recv[MLME]");
return;
}
if (len < (int) sizeof(struct ieee80211_frame_info)) {
wpa_printf(MSG_DEBUG, "WEXT: Too short MLME frame (len=%d)",
len);
return;
}
fi = (struct ieee80211_frame_info *) buf;
if (ntohl(fi->version) != IEEE80211_FI_VERSION) {
wpa_printf(MSG_DEBUG, "WEXT: Invalid MLME frame info version "
"0x%x", ntohl(fi->version));
return;
}
os_memset(&rx_status, 0, sizeof(rx_status));
rx_status.ssi = ntohl(fi->ssi_signal);
rx_status.channel = ntohl(fi->channel);
wpa_supplicant_sta_rx(drv->ctx,
buf + sizeof(struct ieee80211_frame_info),
len - sizeof(struct ieee80211_frame_info),
&rx_status);
}
static int wpa_driver_wext_open_mlme(struct wpa_driver_wext_data *drv)
{
int flags, ifindex, s;
struct sockaddr_ll addr;
struct ifreq ifr;
if (wpa_driver_prism2_param_set(drv, PRISM2_PARAM_USER_SPACE_MLME, 1) <
0) {
wpa_printf(MSG_ERROR, "WEXT: Failed to configure driver to "
"use user space MLME");
return -1;
}
if (wpa_driver_prism2_param_set(drv, PRISM2_PARAM_MGMT_IF, 1) < 0) {
wpa_printf(MSG_ERROR, "WEXT: Failed to add management "
"interface for user space MLME");
return -1;
}
ifindex = wpa_driver_prism2_param_get(drv, PRISM2_PARAM_MGMT_IF);
if (ifindex <= 0) {
wpa_printf(MSG_ERROR, "WEXT: MLME management device not "
"found");
return -1;
}
os_memset(&ifr, 0, sizeof(ifr));
ifr.ifr_ifindex = ifindex;
if (ioctl(drv->ioctl_sock, SIOCGIFNAME, &ifr) != 0) {
perror("ioctl(SIOCGIFNAME)");
return -1;
}
os_strlcpy(drv->mlmedev, ifr.ifr_name, sizeof(drv->mlmedev));
wpa_printf(MSG_DEBUG, "WEXT: MLME management device '%s'",
drv->mlmedev);
if (wpa_driver_wext_get_ifflags_ifname(drv, drv->mlmedev, &flags) != 0
|| wpa_driver_wext_set_ifflags_ifname(drv, drv->mlmedev,
flags | IFF_UP) != 0) {
wpa_printf(MSG_ERROR, "WEXT: Could not set interface "
"'%s' UP", drv->mlmedev);
return -1;
}
s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (s < 0) {
perror("socket[PF_PACKET,SOCK_RAW]");
return -1;
}
os_memset(&addr, 0, sizeof(addr));
addr.sll_family = AF_PACKET;
addr.sll_ifindex = ifindex;
if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
perror("bind(MLME)");
return -1;
}
if (eloop_register_read_sock(s, wpa_driver_wext_mlme_read, drv, NULL))
{
wpa_printf(MSG_ERROR, "WEXT: Could not register MLME read "
"socket");
close(s);
return -1;
}
return s;
}
static int wpa_driver_wext_send_mlme(void *priv, const u8 *data,
size_t data_len)
{
struct wpa_driver_wext_data *drv = priv;
int ret;
ret = send(drv->mlme_sock, data, data_len, 0);
if (ret < 0) {
perror("send[MLME]");
return -1;
}
return 0;
}
static int wpa_driver_wext_mlme_add_sta(void *priv, const u8 *addr,
const u8 *supp_rates,
size_t supp_rates_len)
{
struct wpa_driver_wext_data *drv = priv;
struct prism2_hostapd_param param;
size_t len;
os_memset(&param, 0, sizeof(param));
param.cmd = PRISM2_HOSTAPD_ADD_STA;
os_memcpy(param.sta_addr, addr, ETH_ALEN);
len = supp_rates_len;
if (len > sizeof(param.u.add_sta.supp_rates))
len = sizeof(param.u.add_sta.supp_rates);
os_memcpy(param.u.add_sta.supp_rates, supp_rates, len);
return hostapd_ioctl(drv, &param, sizeof(param));
}
static int wpa_driver_wext_mlme_remove_sta(void *priv, const u8 *addr)
{
struct wpa_driver_wext_data *drv = priv;
struct prism2_hostapd_param param;
os_memset(&param, 0, sizeof(param));
param.cmd = PRISM2_HOSTAPD_REMOVE_STA;
os_memcpy(param.sta_addr, addr, ETH_ALEN);
return hostapd_ioctl(drv, &param, sizeof(param));
}
#endif /* CONFIG_CLIENT_MLME */
static int wpa_driver_wext_set_param(void *priv, const char *param)
{
#ifdef CONFIG_CLIENT_MLME
struct wpa_driver_wext_data *drv = priv;
if (param == NULL)
return 0;
wpa_printf(MSG_DEBUG, "%s: param='%s'", __func__, param);
if (os_strstr(param, "use_mlme=1")) {
wpa_printf(MSG_DEBUG, "WEXT: Using user space MLME");
drv->capa.flags |= WPA_DRIVER_FLAGS_USER_SPACE_MLME;
drv->mlme_sock = wpa_driver_wext_open_mlme(drv);
if (drv->mlme_sock < 0)
return -1;
}
#endif /* CONFIG_CLIENT_MLME */
return 0;
}
int wpa_driver_wext_get_version(struct wpa_driver_wext_data *drv) int wpa_driver_wext_get_version(struct wpa_driver_wext_data *drv)
{ {
return drv->we_version_compiled; return drv->we_version_compiled;
@ -2785,19 +2315,9 @@ const struct wpa_driver_ops wpa_driver_wext_ops = {
.set_auth_alg = wpa_driver_wext_set_auth_alg, .set_auth_alg = wpa_driver_wext_set_auth_alg,
.init = wpa_driver_wext_init, .init = wpa_driver_wext_init,
.deinit = wpa_driver_wext_deinit, .deinit = wpa_driver_wext_deinit,
.set_param = wpa_driver_wext_set_param,
.add_pmkid = wpa_driver_wext_add_pmkid, .add_pmkid = wpa_driver_wext_add_pmkid,
.remove_pmkid = wpa_driver_wext_remove_pmkid, .remove_pmkid = wpa_driver_wext_remove_pmkid,
.flush_pmkid = wpa_driver_wext_flush_pmkid, .flush_pmkid = wpa_driver_wext_flush_pmkid,
.get_capa = wpa_driver_wext_get_capa, .get_capa = wpa_driver_wext_get_capa,
.set_operstate = wpa_driver_wext_set_operstate, .set_operstate = wpa_driver_wext_set_operstate,
#ifdef CONFIG_CLIENT_MLME
.get_hw_feature_data = wpa_driver_wext_get_hw_feature_data,
.set_channel = wpa_driver_wext_set_channel,
.set_ssid = wpa_driver_wext_set_ssid,
.set_bssid = wpa_driver_wext_set_bssid,
.send_mlme = wpa_driver_wext_send_mlme,
.mlme_add_sta = wpa_driver_wext_mlme_add_sta,
.mlme_remove_sta = wpa_driver_wext_mlme_remove_sta,
#endif /* CONFIG_CLIENT_MLME */
}; };

View file

@ -18,6 +18,9 @@ ChangeLog for wpa_supplicant
session ticket overriding API that was included into the upstream session ticket overriding API that was included into the upstream
OpenSSL 0.9.9 tree on 2008-11-15 (no additional OpenSSL patch is OpenSSL 0.9.9 tree on 2008-11-15 (no additional OpenSSL patch is
needed with that version anymore) needed with that version anymore)
* updated userspace MLME instructions to match with the current Linux
mac80211 implementation; please also note that this can only be used
with driver_nl80211.c (the old code from driver_wext.c was removed)
2008-11-01 - v0.6.5 2008-11-01 - v0.6.5
* added support for SHA-256 as X.509 certificate digest when using the * added support for SHA-256 as X.509 certificate digest when using the

View file

@ -346,14 +346,15 @@ CONFIG_PEERKEY=y
#CONFIG_DYNAMIC_EAP_METHODS=y #CONFIG_DYNAMIC_EAP_METHODS=y
# Include client MLME (management frame processing). # Include client MLME (management frame processing).
# This can be used to move MLME processing of Devicescape IEEE 802.11 stack # This can be used to move MLME processing of Linux mac80211 stack into user
# into user space. # space.
#CONFIG_CLIENT_MLME=y #CONFIG_CLIENT_MLME=y
# Currently, driver_devicescape.c build requires some additional parameters # Currently, driver_nl80211.c build requires some additional parameters to be
# to be able to include some of the kernel header files. Following lines can # able to include some of the kernel header files. Following lines can be used
# be used to set these (WIRELESS_DEV must point to the root directory of the # to set these (WIRELESS_DEV must point to the root directory of the
# wireless-dev.git tree). # wireless-testing.git tree). In addition, mac80211 may need external patches
#WIRELESS_DEV=/usr/src/wireless-dev # to enable userspace MLME support.
#WIRELESS_DEV=/usr/src/wireless-testing
#CFLAGS += -I$(WIRELESS_DEV)/net/mac80211 #CFLAGS += -I$(WIRELESS_DEV)/net/mac80211
# IEEE Std 802.11r-2008 (Fast BSS Transition) # IEEE Std 802.11r-2008 (Fast BSS Transition)