summaryrefslogtreecommitdiff
path: root/net/mac80211/wext.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/wext.c')
-rw-r--r--net/mac80211/wext.c467
1 files changed, 235 insertions, 232 deletions
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c
index 7162d5816f39..935c63ed3dfa 100644
--- a/net/mac80211/wext.c
+++ b/net/mac80211/wext.c
@@ -37,7 +37,14 @@ static int ieee80211_set_encryption(struct ieee80211_sub_if_data *sdata, u8 *sta
struct ieee80211_key *key;
int err;
- if (idx < 0 || idx >= NUM_DEFAULT_KEYS) {
+ if (alg == ALG_AES_CMAC) {
+ if (idx < NUM_DEFAULT_KEYS ||
+ idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) {
+ printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d "
+ "(BIP)\n", sdata->dev->name, idx);
+ return -EINVAL;
+ }
+ } else if (idx < 0 || idx >= NUM_DEFAULT_KEYS) {
printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d\n",
sdata->dev->name, idx);
return -EINVAL;
@@ -103,6 +110,9 @@ static int ieee80211_set_encryption(struct ieee80211_sub_if_data *sdata, u8 *sta
if (set_tx_key || (!sta && !sdata->default_key && key))
ieee80211_set_default_key(sdata, idx);
+ if (alg == ALG_AES_CMAC &&
+ (set_tx_key || (!sta && !sdata->default_mgmt_key && key)))
+ ieee80211_set_default_mgmt_key(sdata, idx);
}
out_unlock:
@@ -122,122 +132,37 @@ static int ieee80211_ioctl_siwgenie(struct net_device *dev,
if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME)
return -EOPNOTSUPP;
- if (sdata->vif.type == NL80211_IFTYPE_STATION ||
- sdata->vif.type == NL80211_IFTYPE_ADHOC) {
+ if (sdata->vif.type == NL80211_IFTYPE_STATION) {
int ret = ieee80211_sta_set_extra_ie(sdata, extra, data->length);
if (ret)
return ret;
- sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
- ieee80211_sta_req_auth(sdata, &sdata->u.sta);
+ sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
+ ieee80211_sta_req_auth(sdata);
return 0;
}
return -EOPNOTSUPP;
}
-static int ieee80211_ioctl_giwrange(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *data, char *extra)
-{
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- struct iw_range *range = (struct iw_range *) extra;
- enum ieee80211_band band;
- int c = 0;
-
- data->length = sizeof(struct iw_range);
- memset(range, 0, sizeof(struct iw_range));
-
- range->we_version_compiled = WIRELESS_EXT;
- range->we_version_source = 21;
- range->retry_capa = IW_RETRY_LIMIT;
- range->retry_flags = IW_RETRY_LIMIT;
- range->min_retry = 0;
- range->max_retry = 255;
- range->min_rts = 0;
- range->max_rts = 2347;
- range->min_frag = 256;
- range->max_frag = 2346;
-
- range->encoding_size[0] = 5;
- range->encoding_size[1] = 13;
- range->num_encoding_sizes = 2;
- range->max_encoding_tokens = NUM_DEFAULT_KEYS;
-
- if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC ||
- local->hw.flags & IEEE80211_HW_SIGNAL_DB)
- range->max_qual.level = local->hw.max_signal;
- else if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
- range->max_qual.level = -110;
- else
- range->max_qual.level = 0;
-
- if (local->hw.flags & IEEE80211_HW_NOISE_DBM)
- range->max_qual.noise = -110;
- else
- range->max_qual.noise = 0;
-
- range->max_qual.qual = 100;
- range->max_qual.updated = local->wstats_flags;
-
- range->avg_qual.qual = 50;
- /* not always true but better than nothing */
- range->avg_qual.level = range->max_qual.level / 2;
- range->avg_qual.noise = range->max_qual.noise / 2;
- range->avg_qual.updated = local->wstats_flags;
-
- range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
- IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
-
-
- for (band = 0; band < IEEE80211_NUM_BANDS; band ++) {
- int i;
- struct ieee80211_supported_band *sband;
-
- sband = local->hw.wiphy->bands[band];
-
- if (!sband)
- continue;
-
- for (i = 0; i < sband->n_channels && c < IW_MAX_FREQUENCIES; i++) {
- struct ieee80211_channel *chan = &sband->channels[i];
-
- if (!(chan->flags & IEEE80211_CHAN_DISABLED)) {
- range->freq[c].i =
- ieee80211_frequency_to_channel(
- chan->center_freq);
- range->freq[c].m = chan->center_freq;
- range->freq[c].e = 6;
- c++;
- }
- }
- }
- range->num_channels = c;
- range->num_frequency = c;
-
- IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
- IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
- IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
-
- range->scan_capa |= IW_SCAN_CAPA_ESSID;
-
- return 0;
-}
-
-
static int ieee80211_ioctl_siwfreq(struct net_device *dev,
struct iw_request_info *info,
struct iw_freq *freq, char *extra)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- if (sdata->vif.type == NL80211_IFTYPE_STATION)
- sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_CHANNEL_SEL;
+ if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
+ sdata->u.ibss.flags &= ~IEEE80211_IBSS_AUTO_CHANNEL_SEL;
+ else if (sdata->vif.type == NL80211_IFTYPE_STATION)
+ sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_CHANNEL_SEL;
/* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */
if (freq->e == 0) {
if (freq->m < 0) {
- if (sdata->vif.type == NL80211_IFTYPE_STATION)
- sdata->u.sta.flags |=
+ if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
+ sdata->u.ibss.flags |=
+ IEEE80211_IBSS_AUTO_CHANNEL_SEL;
+ else if (sdata->vif.type == NL80211_IFTYPE_STATION)
+ sdata->u.mgd.flags |=
IEEE80211_STA_AUTO_CHANNEL_SEL;
return 0;
} else
@@ -274,32 +199,35 @@ static int ieee80211_ioctl_siwessid(struct net_device *dev,
{
struct ieee80211_sub_if_data *sdata;
size_t len = data->length;
+ int ret;
/* iwconfig uses nul termination in SSID.. */
if (len > 0 && ssid[len - 1] == '\0')
len--;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- if (sdata->vif.type == NL80211_IFTYPE_STATION ||
- sdata->vif.type == NL80211_IFTYPE_ADHOC) {
- int ret;
+ if (sdata->vif.type == NL80211_IFTYPE_STATION) {
if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) {
if (len > IEEE80211_MAX_SSID_LEN)
return -EINVAL;
- memcpy(sdata->u.sta.ssid, ssid, len);
- sdata->u.sta.ssid_len = len;
+ memcpy(sdata->u.mgd.ssid, ssid, len);
+ sdata->u.mgd.ssid_len = len;
return 0;
}
+
if (data->flags)
- sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_SSID_SEL;
+ sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_SSID_SEL;
else
- sdata->u.sta.flags |= IEEE80211_STA_AUTO_SSID_SEL;
+ sdata->u.mgd.flags |= IEEE80211_STA_AUTO_SSID_SEL;
+
ret = ieee80211_sta_set_ssid(sdata, ssid, len);
if (ret)
return ret;
- ieee80211_sta_req_auth(sdata, &sdata->u.sta);
+
+ ieee80211_sta_req_auth(sdata);
return 0;
- }
+ } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
+ return ieee80211_ibss_set_ssid(sdata, ssid, len);
return -EOPNOTSUPP;
}
@@ -313,8 +241,7 @@ static int ieee80211_ioctl_giwessid(struct net_device *dev,
struct ieee80211_sub_if_data *sdata;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- if (sdata->vif.type == NL80211_IFTYPE_STATION ||
- sdata->vif.type == NL80211_IFTYPE_ADHOC) {
+ if (sdata->vif.type == NL80211_IFTYPE_STATION) {
int res = ieee80211_sta_get_ssid(sdata, ssid, &len);
if (res == 0) {
data->length = len;
@@ -322,6 +249,14 @@ static int ieee80211_ioctl_giwessid(struct net_device *dev,
} else
data->flags = 0;
return res;
+ } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
+ int res = ieee80211_ibss_get_ssid(sdata, ssid, &len);
+ if (res == 0) {
+ data->length = len;
+ data->flags = 1;
+ } else
+ data->flags = 0;
+ return res;
}
return -EOPNOTSUPP;
@@ -335,26 +270,35 @@ static int ieee80211_ioctl_siwap(struct net_device *dev,
struct ieee80211_sub_if_data *sdata;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- if (sdata->vif.type == NL80211_IFTYPE_STATION ||
- sdata->vif.type == NL80211_IFTYPE_ADHOC) {
+ if (sdata->vif.type == NL80211_IFTYPE_STATION) {
int ret;
if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) {
- memcpy(sdata->u.sta.bssid, (u8 *) &ap_addr->sa_data,
+ memcpy(sdata->u.mgd.bssid, (u8 *) &ap_addr->sa_data,
ETH_ALEN);
return 0;
}
if (is_zero_ether_addr((u8 *) &ap_addr->sa_data))
- sdata->u.sta.flags |= IEEE80211_STA_AUTO_BSSID_SEL |
+ sdata->u.mgd.flags |= IEEE80211_STA_AUTO_BSSID_SEL |
IEEE80211_STA_AUTO_CHANNEL_SEL;
else if (is_broadcast_ether_addr((u8 *) &ap_addr->sa_data))
- sdata->u.sta.flags |= IEEE80211_STA_AUTO_BSSID_SEL;
+ sdata->u.mgd.flags |= IEEE80211_STA_AUTO_BSSID_SEL;
else
- sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
+ sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
ret = ieee80211_sta_set_bssid(sdata, (u8 *) &ap_addr->sa_data);
if (ret)
return ret;
- ieee80211_sta_req_auth(sdata, &sdata->u.sta);
+ ieee80211_sta_req_auth(sdata);
return 0;
+ } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
+ if (is_zero_ether_addr((u8 *) &ap_addr->sa_data))
+ sdata->u.ibss.flags |= IEEE80211_IBSS_AUTO_BSSID_SEL |
+ IEEE80211_IBSS_AUTO_CHANNEL_SEL;
+ else if (is_broadcast_ether_addr((u8 *) &ap_addr->sa_data))
+ sdata->u.ibss.flags |= IEEE80211_IBSS_AUTO_BSSID_SEL;
+ else
+ sdata->u.ibss.flags &= ~IEEE80211_IBSS_AUTO_BSSID_SEL;
+
+ return ieee80211_ibss_set_bssid(sdata, (u8 *) &ap_addr->sa_data);
} else if (sdata->vif.type == NL80211_IFTYPE_WDS) {
/*
* If it is necessary to update the WDS peer address
@@ -383,17 +327,20 @@ static int ieee80211_ioctl_giwap(struct net_device *dev,
struct ieee80211_sub_if_data *sdata;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- if (sdata->vif.type == NL80211_IFTYPE_STATION ||
- sdata->vif.type == NL80211_IFTYPE_ADHOC) {
- if (sdata->u.sta.state == IEEE80211_STA_MLME_ASSOCIATED ||
- sdata->u.sta.state == IEEE80211_STA_MLME_IBSS_JOINED) {
+ if (sdata->vif.type == NL80211_IFTYPE_STATION) {
+ if (sdata->u.mgd.state == IEEE80211_STA_MLME_ASSOCIATED) {
ap_addr->sa_family = ARPHRD_ETHER;
- memcpy(&ap_addr->sa_data, sdata->u.sta.bssid, ETH_ALEN);
- return 0;
- } else {
+ memcpy(&ap_addr->sa_data, sdata->u.mgd.bssid, ETH_ALEN);
+ } else
memset(&ap_addr->sa_data, 0, ETH_ALEN);
- return 0;
- }
+ return 0;
+ } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
+ if (sdata->u.ibss.state == IEEE80211_IBSS_MLME_JOINED) {
+ ap_addr->sa_family = ARPHRD_ETHER;
+ memcpy(&ap_addr->sa_data, sdata->u.ibss.bssid, ETH_ALEN);
+ } else
+ memset(&ap_addr->sa_data, 0, ETH_ALEN);
+ return 0;
} else if (sdata->vif.type == NL80211_IFTYPE_WDS) {
ap_addr->sa_family = ARPHRD_ETHER;
memcpy(&ap_addr->sa_data, sdata->u.wds.remote_addr, ETH_ALEN);
@@ -404,58 +351,6 @@ static int ieee80211_ioctl_giwap(struct net_device *dev,
}
-static int ieee80211_ioctl_siwscan(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- struct iw_scan_req *req = NULL;
- u8 *ssid = NULL;
- size_t ssid_len = 0;
-
- if (!netif_running(dev))
- return -ENETDOWN;
-
- if (sdata->vif.type != NL80211_IFTYPE_STATION &&
- sdata->vif.type != NL80211_IFTYPE_ADHOC &&
- sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
- return -EOPNOTSUPP;
-
- /* if SSID was specified explicitly then use that */
- if (wrqu->data.length == sizeof(struct iw_scan_req) &&
- wrqu->data.flags & IW_SCAN_THIS_ESSID) {
- req = (struct iw_scan_req *)extra;
- ssid = req->essid;
- ssid_len = req->essid_len;
- }
-
- return ieee80211_request_scan(sdata, ssid, ssid_len);
-}
-
-
-static int ieee80211_ioctl_giwscan(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *data, char *extra)
-{
- int res;
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- struct ieee80211_sub_if_data *sdata;
-
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
- if (local->sw_scanning || local->hw_scanning)
- return -EAGAIN;
-
- res = ieee80211_scan_results(local, info, extra, data->length);
- if (res >= 0) {
- data->length = res;
- return 0;
- }
- data->length = 0;
- return res;
-}
-
-
static int ieee80211_ioctl_siwrate(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *rate, char *extra)
@@ -511,7 +406,7 @@ static int ieee80211_ioctl_giwrate(struct net_device *dev,
rcu_read_lock();
- sta = sta_info_get(local, sdata->u.sta.bssid);
+ sta = sta_info_get(local, sdata->u.mgd.bssid);
if (sta && !(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS))
rate->value = sband->bitrates[sta->last_tx_rate.idx].bitrate;
@@ -549,10 +444,9 @@ static int ieee80211_ioctl_siwtxpower(struct net_device *dev,
else /* Automatic power level setting */
new_power_level = chan->max_power;
- if (local->hw.conf.power_level != new_power_level) {
- local->hw.conf.power_level = new_power_level;
+ local->user_power_level = new_power_level;
+ if (local->hw.conf.power_level != new_power_level)
reconf_flags |= IEEE80211_CONF_CHANGE_POWER;
- }
if (local->hw.conf.radio_enabled != !(data->txpower.disabled)) {
local->hw.conf.radio_enabled = !(data->txpower.disabled);
@@ -713,8 +607,7 @@ static int ieee80211_ioctl_siwmlme(struct net_device *dev,
struct iw_mlme *mlme = (struct iw_mlme *) extra;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- if (sdata->vif.type != NL80211_IFTYPE_STATION &&
- sdata->vif.type != NL80211_IFTYPE_ADHOC)
+ if (!(sdata->vif.type == NL80211_IFTYPE_STATION))
return -EINVAL;
switch (mlme->cmd) {
@@ -810,8 +703,7 @@ static int ieee80211_ioctl_giwencode(struct net_device *dev,
erq->flags |= IW_ENCODE_ENABLED;
if (sdata->vif.type == NL80211_IFTYPE_STATION) {
- struct ieee80211_if_sta *ifsta = &sdata->u.sta;
- switch (ifsta->auth_alg) {
+ switch (sdata->u.mgd.auth_alg) {
case WLAN_AUTH_OPEN:
case WLAN_AUTH_LEAP:
erq->flags |= IW_ENCODE_OPEN;
@@ -836,6 +728,9 @@ static int ieee80211_ioctl_siwpower(struct net_device *dev,
int ret = 0, timeout = 0;
bool ps;
+ if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS))
+ return -EOPNOTSUPP;
+
if (sdata->vif.type != NL80211_IFTYPE_STATION)
return -EINVAL;
@@ -852,31 +747,49 @@ static int ieee80211_ioctl_siwpower(struct net_device *dev,
ps = true;
break;
default: /* Otherwise we ignore */
- break;
+ return -EINVAL;
}
+ if (wrq->flags & ~(IW_POWER_MODE | IW_POWER_TIMEOUT))
+ return -EINVAL;
+
if (wrq->flags & IW_POWER_TIMEOUT)
timeout = wrq->value / 1000;
-set:
- if (ps == local->powersave && timeout == local->dynamic_ps_timeout)
+ set:
+ if (ps == local->powersave && timeout == conf->dynamic_ps_timeout)
return ret;
local->powersave = ps;
- local->dynamic_ps_timeout = timeout;
+ conf->dynamic_ps_timeout = timeout;
- if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) {
- if (!(local->hw.flags & IEEE80211_HW_NO_STACK_DYNAMIC_PS) &&
- local->dynamic_ps_timeout > 0)
- mod_timer(&local->dynamic_ps_timer, jiffies +
- msecs_to_jiffies(local->dynamic_ps_timeout));
- else {
- if (local->powersave)
- conf->flags |= IEEE80211_CONF_PS;
- else
- conf->flags &= ~IEEE80211_CONF_PS;
+ if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)
+ ret = ieee80211_hw_config(local,
+ IEEE80211_CONF_CHANGE_DYNPS_TIMEOUT);
+
+ if (!(sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED))
+ return ret;
+
+ if (conf->dynamic_ps_timeout > 0 &&
+ !(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)) {
+ mod_timer(&local->dynamic_ps_timer, jiffies +
+ msecs_to_jiffies(conf->dynamic_ps_timeout));
+ } else {
+ if (local->powersave) {
+ if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
+ ieee80211_send_nullfunc(local, sdata, 1);
+ conf->flags |= IEEE80211_CONF_PS;
+ ret = ieee80211_hw_config(local,
+ IEEE80211_CONF_CHANGE_PS);
+ } else {
+ conf->flags &= ~IEEE80211_CONF_PS;
+ ret = ieee80211_hw_config(local,
+ IEEE80211_CONF_CHANGE_PS);
+ if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
+ ieee80211_send_nullfunc(local, sdata, 0);
+ del_timer_sync(&local->dynamic_ps_timer);
+ cancel_work_sync(&local->dynamic_ps_enable_work);
}
- ret = ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
}
return ret;
@@ -903,11 +816,22 @@ static int ieee80211_ioctl_siwauth(struct net_device *dev,
switch (data->flags & IW_AUTH_INDEX) {
case IW_AUTH_WPA_VERSION:
- case IW_AUTH_CIPHER_PAIRWISE:
case IW_AUTH_CIPHER_GROUP:
case IW_AUTH_WPA_ENABLED:
case IW_AUTH_RX_UNENCRYPTED_EAPOL:
case IW_AUTH_KEY_MGMT:
+ case IW_AUTH_CIPHER_GROUP_MGMT:
+ break;
+ case IW_AUTH_CIPHER_PAIRWISE:
+ if (sdata->vif.type == NL80211_IFTYPE_STATION) {
+ if (data->value & (IW_AUTH_CIPHER_WEP40 |
+ IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_TKIP))
+ sdata->u.mgd.flags |=
+ IEEE80211_STA_TKIP_WEP_USED;
+ else
+ sdata->u.mgd.flags &=
+ ~IEEE80211_STA_TKIP_WEP_USED;
+ }
break;
case IW_AUTH_DROP_UNENCRYPTED:
sdata->drop_unencrypted = !!data->value;
@@ -916,24 +840,45 @@ static int ieee80211_ioctl_siwauth(struct net_device *dev,
if (sdata->vif.type != NL80211_IFTYPE_STATION)
ret = -EINVAL;
else {
- sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED;
+ sdata->u.mgd.flags &= ~IEEE80211_STA_PRIVACY_INVOKED;
/*
* Privacy invoked by wpa_supplicant, store the
* value and allow associating to a protected
* network without having a key up front.
*/
if (data->value)
- sdata->u.sta.flags |=
+ sdata->u.mgd.flags |=
IEEE80211_STA_PRIVACY_INVOKED;
}
break;
case IW_AUTH_80211_AUTH_ALG:
- if (sdata->vif.type == NL80211_IFTYPE_STATION ||
- sdata->vif.type == NL80211_IFTYPE_ADHOC)
- sdata->u.sta.auth_algs = data->value;
+ if (sdata->vif.type == NL80211_IFTYPE_STATION)
+ sdata->u.mgd.auth_algs = data->value;
else
ret = -EOPNOTSUPP;
break;
+ case IW_AUTH_MFP:
+ if (!(sdata->local->hw.flags & IEEE80211_HW_MFP_CAPABLE)) {
+ ret = -EOPNOTSUPP;
+ break;
+ }
+ if (sdata->vif.type == NL80211_IFTYPE_STATION) {
+ switch (data->value) {
+ case IW_AUTH_MFP_DISABLED:
+ sdata->u.mgd.mfp = IEEE80211_MFP_DISABLED;
+ break;
+ case IW_AUTH_MFP_OPTIONAL:
+ sdata->u.mgd.mfp = IEEE80211_MFP_OPTIONAL;
+ break;
+ case IW_AUTH_MFP_REQUIRED:
+ sdata->u.mgd.mfp = IEEE80211_MFP_REQUIRED;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ } else
+ ret = -EOPNOTSUPP;
+ break;
default:
ret = -EOPNOTSUPP;
break;
@@ -951,9 +896,9 @@ static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev
rcu_read_lock();
- if (sdata->vif.type == NL80211_IFTYPE_STATION ||
- sdata->vif.type == NL80211_IFTYPE_ADHOC)
- sta = sta_info_get(local, sdata->u.sta.bssid);
+ if (sdata->vif.type == NL80211_IFTYPE_STATION)
+ sta = sta_info_get(local, sdata->u.mgd.bssid);
+
if (!sta) {
wstats->discard.fragment = 0;
wstats->discard.misc = 0;
@@ -962,10 +907,45 @@ static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev
wstats->qual.noise = 0;
wstats->qual.updated = IW_QUAL_ALL_INVALID;
} else {
- wstats->qual.level = sta->last_signal;
- wstats->qual.qual = sta->last_qual;
- wstats->qual.noise = sta->last_noise;
- wstats->qual.updated = local->wstats_flags;
+ wstats->qual.updated = 0;
+ /*
+ * mirror what cfg80211 does for iwrange/scan results,
+ * otherwise userspace gets confused.
+ */
+ if (local->hw.flags & (IEEE80211_HW_SIGNAL_UNSPEC |
+ IEEE80211_HW_SIGNAL_DBM)) {
+ wstats->qual.updated |= IW_QUAL_LEVEL_UPDATED;
+ wstats->qual.updated |= IW_QUAL_QUAL_UPDATED;
+ } else {
+ wstats->qual.updated |= IW_QUAL_LEVEL_INVALID;
+ wstats->qual.updated |= IW_QUAL_QUAL_INVALID;
+ }
+
+ if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) {
+ wstats->qual.level = sta->last_signal;
+ wstats->qual.qual = sta->last_signal;
+ } else if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
+ int sig = sta->last_signal;
+
+ wstats->qual.updated |= IW_QUAL_DBM;
+ wstats->qual.level = sig;
+ if (sig < -110)
+ sig = -110;
+ else if (sig > -40)
+ sig = -40;
+ wstats->qual.qual = sig + 110;
+ }
+
+ if (local->hw.flags & IEEE80211_HW_NOISE_DBM) {
+ /*
+ * This assumes that if driver reports noise, it also
+ * reports signal in dBm.
+ */
+ wstats->qual.noise = sta->last_noise;
+ wstats->qual.updated |= IW_QUAL_NOISE_UPDATED;
+ } else {
+ wstats->qual.updated |= IW_QUAL_NOISE_INVALID;
+ }
}
rcu_read_unlock();
@@ -982,9 +962,8 @@ static int ieee80211_ioctl_giwauth(struct net_device *dev,
switch (data->flags & IW_AUTH_INDEX) {
case IW_AUTH_80211_AUTH_ALG:
- if (sdata->vif.type == NL80211_IFTYPE_STATION ||
- sdata->vif.type == NL80211_IFTYPE_ADHOC)
- data->value = sdata->u.sta.auth_algs;
+ if (sdata->vif.type == NL80211_IFTYPE_STATION)
+ data->value = sdata->u.mgd.auth_algs;
else
ret = -EOPNOTSUPP;
break;
@@ -1017,6 +996,9 @@ static int ieee80211_ioctl_siwencodeext(struct net_device *dev,
case IW_ENCODE_ALG_CCMP:
alg = ALG_CCMP;
break;
+ case IW_ENCODE_ALG_AES_CMAC:
+ alg = ALG_AES_CMAC;
+ break;
default:
return -EOPNOTSUPP;
}
@@ -1025,20 +1007,41 @@ static int ieee80211_ioctl_siwencodeext(struct net_device *dev,
remove = 1;
idx = erq->flags & IW_ENCODE_INDEX;
- if (idx < 1 || idx > 4) {
- idx = -1;
- if (!sdata->default_key)
- idx = 0;
- else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
- if (sdata->default_key == sdata->keys[i]) {
- idx = i;
- break;
+ if (alg == ALG_AES_CMAC) {
+ if (idx < NUM_DEFAULT_KEYS + 1 ||
+ idx > NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) {
+ idx = -1;
+ if (!sdata->default_mgmt_key)
+ idx = 0;
+ else for (i = NUM_DEFAULT_KEYS;
+ i < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS;
+ i++) {
+ if (sdata->default_mgmt_key == sdata->keys[i])
+ {
+ idx = i;
+ break;
+ }
}
- }
- if (idx < 0)
- return -EINVAL;
- } else
- idx--;
+ if (idx < 0)
+ return -EINVAL;
+ } else
+ idx--;
+ } else {
+ if (idx < 1 || idx > 4) {
+ idx = -1;
+ if (!sdata->default_key)
+ idx = 0;
+ else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
+ if (sdata->default_key == sdata->keys[i]) {
+ idx = i;
+ break;
+ }
+ }
+ if (idx < 0)
+ return -EINVAL;
+ } else
+ idx--;
+ }
return ieee80211_set_encryption(sdata, ext->addr.sa_data, idx, alg,
remove,
@@ -1063,7 +1066,7 @@ static const iw_handler ieee80211_handler[] =
(iw_handler) NULL, /* SIOCSIWSENS */
(iw_handler) NULL, /* SIOCGIWSENS */
(iw_handler) NULL /* not used */, /* SIOCSIWRANGE */
- (iw_handler) ieee80211_ioctl_giwrange, /* SIOCGIWRANGE */
+ (iw_handler) cfg80211_wext_giwrange, /* SIOCGIWRANGE */
(iw_handler) NULL /* not used */, /* SIOCSIWPRIV */
(iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */
(iw_handler) NULL /* not used */, /* SIOCSIWSTATS */
@@ -1076,8 +1079,8 @@ static const iw_handler ieee80211_handler[] =
(iw_handler) ieee80211_ioctl_giwap, /* SIOCGIWAP */
(iw_handler) ieee80211_ioctl_siwmlme, /* SIOCSIWMLME */
(iw_handler) NULL, /* SIOCGIWAPLIST */
- (iw_handler) ieee80211_ioctl_siwscan, /* SIOCSIWSCAN */
- (iw_handler) ieee80211_ioctl_giwscan, /* SIOCGIWSCAN */
+ (iw_handler) cfg80211_wext_siwscan, /* SIOCSIWSCAN */
+ (iw_handler) cfg80211_wext_giwscan, /* SIOCGIWSCAN */
(iw_handler) ieee80211_ioctl_siwessid, /* SIOCSIWESSID */
(iw_handler) ieee80211_ioctl_giwessid, /* SIOCGIWESSID */
(iw_handler) NULL, /* SIOCSIWNICKN */