diff options
Diffstat (limited to 'net/wireless/wext-sme.c')
| -rw-r--r-- | net/wireless/wext-sme.c | 93 | 
1 files changed, 51 insertions, 42 deletions
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c index 6fffe62d7c2..c7e5c8eb4f2 100644 --- a/net/wireless/wext-sme.c +++ b/net/wireless/wext-sme.c @@ -5,10 +5,12 @@   * Copyright (C) 2009   Intel Corporation. All rights reserved.   */ +#include <linux/export.h>  #include <linux/etherdevice.h>  #include <linux/if_arp.h>  #include <linux/slab.h>  #include <net/cfg80211.h> +#include <net/cfg80211-wext.h>  #include "wext-compat.h"  #include "nl80211.h" @@ -19,7 +21,7 @@ int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,  	const u8 *prev_bssid = NULL;  	int err, i; -	ASSERT_RDEV_LOCK(rdev); +	ASSERT_RTNL();  	ASSERT_WDEV_LOCK(wdev);  	if (!netif_running(wdev->netdev)) @@ -28,6 +30,9 @@ int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,  	wdev->wext.connect.ie = wdev->wext.ie;  	wdev->wext.connect.ie_len = wdev->wext.ie_len; +	/* Use default background scan period */ +	wdev->wext.connect.bg_scan_period = -1; +  	if (wdev->wext.keys) {  		wdev->wext.keys->def = wdev->wext.default_key;  		wdev->wext.keys->defmgmt = wdev->wext.default_mgmt_key; @@ -49,8 +54,8 @@ int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,  	if (wdev->wext.prev_bssid_valid)  		prev_bssid = wdev->wext.prev_bssid; -	err = __cfg80211_connect(rdev, wdev->netdev, -				 &wdev->wext.connect, ck, prev_bssid); +	err = cfg80211_connect(rdev, wdev->netdev, +			       &wdev->wext.connect, ck, prev_bssid);  	if (err)  		kfree(ck); @@ -62,7 +67,7 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev,  			      struct iw_freq *wextfreq, char *extra)  {  	struct wireless_dev *wdev = dev->ieee80211_ptr; -	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); +	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);  	struct ieee80211_channel *chan = NULL;  	int err, freq; @@ -70,7 +75,7 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev,  	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))  		return -EINVAL; -	freq = cfg80211_wext_freq(wdev->wiphy, wextfreq); +	freq = cfg80211_wext_freq(wextfreq);  	if (freq < 0)  		return freq; @@ -82,11 +87,9 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev,  			return -EINVAL;  	} -	cfg80211_lock_rdev(rdev); -	mutex_lock(&rdev->devlist_mtx);  	wdev_lock(wdev); -	if (wdev->sme_state != CFG80211_SME_IDLE) { +	if (wdev->conn) {  		bool event = true;  		if (wdev->wext.connect.channel == chan) { @@ -97,8 +100,8 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev,  		/* if SSID set, we'll try right again, avoid event */  		if (wdev->wext.connect.ssid_len)  			event = false; -		err = __cfg80211_disconnect(rdev, dev, -					    WLAN_REASON_DEAUTH_LEAVING, event); +		err = cfg80211_disconnect(rdev, dev, +					  WLAN_REASON_DEAUTH_LEAVING, event);  		if (err)  			goto out;  	} @@ -106,17 +109,30 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev,  	wdev->wext.connect.channel = chan; -	/* SSID is not set, we just want to switch channel */ +	/* +	 * SSID is not set, we just want to switch monitor channel, +	 * this is really just backward compatibility, if the SSID +	 * is set then we use the channel to select the BSS to use +	 * to connect to instead. If we were connected on another +	 * channel we disconnected above and reconnect below. +	 */  	if (chan && !wdev->wext.connect.ssid_len) { -		err = cfg80211_set_freq(rdev, wdev, freq, NL80211_CHAN_NO_HT); +		struct cfg80211_chan_def chandef = { +			.width = NL80211_CHAN_WIDTH_20_NOHT, +			.center_freq1 = freq, +		}; + +		chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq); +		if (chandef.chan) +			err = cfg80211_set_monitor_channel(rdev, &chandef); +		else +			err = -EINVAL;  		goto out;  	}  	err = cfg80211_mgd_wext_connect(rdev, wdev);   out:  	wdev_unlock(wdev); -	mutex_unlock(&rdev->devlist_mtx); -	cfg80211_unlock_rdev(rdev);  	return err;  } @@ -153,7 +169,7 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,  			       struct iw_point *data, char *ssid)  {  	struct wireless_dev *wdev = dev->ieee80211_ptr; -	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); +	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);  	size_t len = data->length;  	int err; @@ -168,13 +184,11 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,  	if (len > 0 && ssid[len - 1] == '\0')  		len--; -	cfg80211_lock_rdev(rdev); -	mutex_lock(&rdev->devlist_mtx);  	wdev_lock(wdev);  	err = 0; -	if (wdev->sme_state != CFG80211_SME_IDLE) { +	if (wdev->conn) {  		bool event = true;  		if (wdev->wext.connect.ssid && len && @@ -185,8 +199,8 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,  		/* if SSID set now, we'll try to connect, avoid event */  		if (len)  			event = false; -		err = __cfg80211_disconnect(rdev, dev, -					    WLAN_REASON_DEAUTH_LEAVING, event); +		err = cfg80211_disconnect(rdev, dev, +					  WLAN_REASON_DEAUTH_LEAVING, event);  		if (err)  			goto out;  	} @@ -203,8 +217,6 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,  	err = cfg80211_mgd_wext_connect(rdev, wdev);   out:  	wdev_unlock(wdev); -	mutex_unlock(&rdev->devlist_mtx); -	cfg80211_unlock_rdev(rdev);  	return err;  } @@ -222,13 +234,17 @@ int cfg80211_mgd_wext_giwessid(struct net_device *dev,  	wdev_lock(wdev);  	if (wdev->current_bss) { -		const u8 *ie = ieee80211_bss_get_ie(&wdev->current_bss->pub, -						    WLAN_EID_SSID); +		const u8 *ie; + +		rcu_read_lock(); +		ie = ieee80211_bss_get_ie(&wdev->current_bss->pub, +					  WLAN_EID_SSID);  		if (ie) {  			data->flags = 1;  			data->length = ie[1];  			memcpy(ssid, ie + 2, data->length);  		} +		rcu_read_unlock();  	} else if (wdev->wext.connect.ssid && wdev->wext.connect.ssid_len) {  		data->flags = 1;  		data->length = wdev->wext.connect.ssid_len; @@ -244,7 +260,7 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,  			    struct sockaddr *ap_addr, char *extra)  {  	struct wireless_dev *wdev = dev->ieee80211_ptr; -	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); +	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);  	u8 *bssid = ap_addr->sa_data;  	int err; @@ -259,11 +275,9 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,  	if (is_zero_ether_addr(bssid) || is_broadcast_ether_addr(bssid))  		bssid = NULL; -	cfg80211_lock_rdev(rdev); -	mutex_lock(&rdev->devlist_mtx);  	wdev_lock(wdev); -	if (wdev->sme_state != CFG80211_SME_IDLE) { +	if (wdev->conn) {  		err = 0;  		/* both automatic */  		if (!bssid && !wdev->wext.connect.bssid) @@ -271,11 +285,11 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,  		/* fixed already - and no change */  		if (wdev->wext.connect.bssid && bssid && -		    compare_ether_addr(bssid, wdev->wext.connect.bssid) == 0) +		    ether_addr_equal(bssid, wdev->wext.connect.bssid))  			goto out; -		err = __cfg80211_disconnect(rdev, dev, -					    WLAN_REASON_DEAUTH_LEAVING, false); +		err = cfg80211_disconnect(rdev, dev, +					  WLAN_REASON_DEAUTH_LEAVING, false);  		if (err)  			goto out;  	} @@ -289,8 +303,6 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,  	err = cfg80211_mgd_wext_connect(rdev, wdev);   out:  	wdev_unlock(wdev); -	mutex_unlock(&rdev->devlist_mtx); -	cfg80211_unlock_rdev(rdev);  	return err;  } @@ -321,7 +333,7 @@ int cfg80211_wext_siwgenie(struct net_device *dev,  			   struct iw_point *data, char *extra)  {  	struct wireless_dev *wdev = dev->ieee80211_ptr; -	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); +	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);  	u8 *ie = extra;  	int ie_len = data->length, err; @@ -352,9 +364,9 @@ int cfg80211_wext_siwgenie(struct net_device *dev,  	wdev->wext.ie = ie;  	wdev->wext.ie_len = ie_len; -	if (wdev->sme_state != CFG80211_SME_IDLE) { -		err = __cfg80211_disconnect(rdev, dev, -					    WLAN_REASON_DEAUTH_LEAVING, false); +	if (wdev->conn) { +		err = cfg80211_disconnect(rdev, dev, +					  WLAN_REASON_DEAUTH_LEAVING, false);  		if (err)  			goto out;  	} @@ -365,7 +377,6 @@ int cfg80211_wext_siwgenie(struct net_device *dev,  	wdev_unlock(wdev);  	return err;  } -EXPORT_SYMBOL_GPL(cfg80211_wext_siwgenie);  int cfg80211_wext_siwmlme(struct net_device *dev,  			  struct iw_request_info *info, @@ -379,7 +390,7 @@ int cfg80211_wext_siwmlme(struct net_device *dev,  	if (!wdev)  		return -EOPNOTSUPP; -	rdev = wiphy_to_dev(wdev->wiphy); +	rdev = wiphy_to_rdev(wdev->wiphy);  	if (wdev->iftype != NL80211_IFTYPE_STATION)  		return -EINVAL; @@ -391,8 +402,7 @@ int cfg80211_wext_siwmlme(struct net_device *dev,  	switch (mlme->cmd) {  	case IW_MLME_DEAUTH:  	case IW_MLME_DISASSOC: -		err = __cfg80211_disconnect(rdev, dev, mlme->reason_code, -					    true); +		err = cfg80211_disconnect(rdev, dev, mlme->reason_code, true);  		break;  	default:  		err = -EOPNOTSUPP; @@ -402,4 +412,3 @@ int cfg80211_wext_siwmlme(struct net_device *dev,  	return err;  } -EXPORT_SYMBOL_GPL(cfg80211_wext_siwmlme);  | 
