summary refs log tree commit diff
path: root/net/mac80211/wext.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/wext.c')
-rw-r--r--net/mac80211/wext.c141
1 files changed, 80 insertions, 61 deletions
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c
index 2b023dce8b24..8a76a979bc92 100644
--- a/net/mac80211/wext.c
+++ b/net/mac80211/wext.c
@@ -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;