mac80211: split IBSS/managed code

This patch splits out the ibss code and data from managed (station) mode.
The reason to do this is to better separate the state machines, and have
the code be contained better so it gets easier to determine what exactly
a given change will affect, that in turn makes it easier to understand.

This is quite some churn, especially because I split sdata->u.sta into
sdata->u.mgd and sdata->u.ibss, but I think it's easier to maintain that
way. I've also shuffled around some code -- null function sending is only
applicable to managed interfaces so put that into that file, some other
functions are needed from various places so put them into util, and also
rearranged the prototypes in ieee80211_i.h accordingly.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
Johannes Berg
2009-02-15 12:44:28 +01:00
committed by John W. Linville
parent 96f5e66e8a
commit 469002983f
18 changed files with 1803 additions and 1480 deletions

View File

@@ -132,13 +132,12 @@ 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;
}
@@ -255,16 +254,19 @@ static int ieee80211_ioctl_siwfreq(struct net_device *dev,
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->vif.type == NL80211_IFTYPE_ADHOC ||
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_ADHOC ||
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
@@ -301,32 +303,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;
}
@@ -340,8 +345,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;
@@ -349,6 +353,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;
@@ -362,26 +374,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
@@ -410,17 +431,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);
@@ -486,7 +510,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;
@@ -687,8 +711,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) {
@@ -784,8 +807,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;
@@ -849,7 +871,7 @@ static int ieee80211_ioctl_siwpower(struct net_device *dev,
ret = ieee80211_hw_config(local,
IEEE80211_CONF_CHANGE_DYNPS_TIMEOUT);
if (!(sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED))
if (!(sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED))
return ret;
if (conf->dynamic_ps_timeout > 0 &&
@@ -908,10 +930,10 @@ static int ieee80211_ioctl_siwauth(struct net_device *dev,
if (sdata->vif.type == NL80211_IFTYPE_STATION) {
if (data->value & (IW_AUTH_CIPHER_WEP40 |
IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_TKIP))
sdata->u.sta.flags |=
sdata->u.mgd.flags |=
IEEE80211_STA_TKIP_WEP_USED;
else
sdata->u.sta.flags &=
sdata->u.mgd.flags &=
~IEEE80211_STA_TKIP_WEP_USED;
}
break;
@@ -922,21 +944,20 @@ 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;
@@ -945,17 +966,16 @@ static int ieee80211_ioctl_siwauth(struct net_device *dev,
ret = -EOPNOTSUPP;
break;
}
if (sdata->vif.type == NL80211_IFTYPE_STATION ||
sdata->vif.type == NL80211_IFTYPE_ADHOC) {
if (sdata->vif.type == NL80211_IFTYPE_STATION) {
switch (data->value) {
case IW_AUTH_MFP_DISABLED:
sdata->u.sta.mfp = IEEE80211_MFP_DISABLED;
sdata->u.mgd.mfp = IEEE80211_MFP_DISABLED;
break;
case IW_AUTH_MFP_OPTIONAL:
sdata->u.sta.mfp = IEEE80211_MFP_OPTIONAL;
sdata->u.mgd.mfp = IEEE80211_MFP_OPTIONAL;
break;
case IW_AUTH_MFP_REQUIRED:
sdata->u.sta.mfp = IEEE80211_MFP_REQUIRED;
sdata->u.mgd.mfp = IEEE80211_MFP_REQUIRED;
break;
default:
ret = -EINVAL;
@@ -980,9 +1000,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;
@@ -1011,9 +1031,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;