diff options
Diffstat (limited to 'net/wireless/wext-sme.c')
-rw-r--r-- | net/wireless/wext-sme.c | 125 |
1 files changed, 88 insertions, 37 deletions
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c index fe1987acb89..6f75aaa7f79 100644 --- a/net/wireless/wext-sme.c +++ b/net/wireless/wext-sme.c @@ -15,6 +15,9 @@ static int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev, { int err; + ASSERT_RDEV_LOCK(rdev); + ASSERT_WDEV_LOCK(wdev); + if (!netif_running(wdev->netdev)) return 0; @@ -24,8 +27,8 @@ static int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev, err = 0; if (wdev->wext.connect.ssid_len != 0) - err = cfg80211_connect(rdev, wdev->netdev, - &wdev->wext.connect); + err = __cfg80211_connect(rdev, wdev->netdev, + &wdev->wext.connect); return err; } @@ -50,33 +53,43 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev, if (chan && (chan->flags & IEEE80211_CHAN_DISABLED)) return -EINVAL; - if (wdev->wext.connect.channel == chan) - return 0; + cfg80211_lock_rdev(rdev); + wdev_lock(wdev); + + if (wdev->wext.connect.channel == chan) { + err = 0; + goto out; + } if (wdev->sme_state != CFG80211_SME_IDLE) { bool event = true; /* if SSID set, we'll try right again, avoid event */ if (wdev->wext.connect.ssid_len) event = false; - err = cfg80211_disconnect(wiphy_to_dev(wdev->wiphy), - dev, WLAN_REASON_DEAUTH_LEAVING, - event); + err = __cfg80211_disconnect(wiphy_to_dev(wdev->wiphy), + dev, WLAN_REASON_DEAUTH_LEAVING, + event); if (err) - return err; + goto out; } + wdev->wext.connect.channel = chan; /* SSID is not set, we just want to switch channel */ if (wdev->wext.connect.ssid_len && chan) { - if (!rdev->ops->set_channel) - return -EOPNOTSUPP; - - return rdev->ops->set_channel(wdev->wiphy, chan, - NL80211_CHAN_NO_HT); + err = -EOPNOTSUPP; + if (rdev->ops->set_channel) + err = rdev->ops->set_channel(wdev->wiphy, chan, + NL80211_CHAN_NO_HT); + goto out; } - return cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev); + err = cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev); + out: + wdev_unlock(wdev); + cfg80211_unlock_rdev(rdev); + return err; } /* temporary symbol - mark GPL - in the future the handler won't be */ EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_siwfreq); @@ -92,10 +105,12 @@ int cfg80211_mgd_wext_giwfreq(struct net_device *dev, if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION)) return -EINVAL; + wdev_lock(wdev); if (wdev->current_bss) chan = wdev->current_bss->pub.channel; else if (wdev->wext.connect.channel) chan = wdev->wext.connect.channel; + wdev_unlock(wdev); if (chan) { freq->m = chan->center_freq; @@ -128,21 +143,26 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev, if (len > 0 && ssid[len - 1] == '\0') len--; + cfg80211_lock_rdev(wiphy_to_dev(wdev->wiphy)); + wdev_lock(wdev); + + err = 0; + if (wdev->wext.connect.ssid && len && len == wdev->wext.connect.ssid_len && memcmp(wdev->wext.connect.ssid, ssid, len)) - return 0; + goto out; if (wdev->sme_state != CFG80211_SME_IDLE) { bool event = true; /* if SSID set now, we'll try to connect, avoid event */ if (len) event = false; - err = cfg80211_disconnect(wiphy_to_dev(wdev->wiphy), - dev, WLAN_REASON_DEAUTH_LEAVING, - event); + err = __cfg80211_disconnect(wiphy_to_dev(wdev->wiphy), + dev, WLAN_REASON_DEAUTH_LEAVING, + event); if (err) - return err; + goto out; } wdev->wext.connect.ssid = wdev->wext.ssid; @@ -151,7 +171,11 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev, wdev->wext.connect.crypto.control_port = false; - return cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev); + err = cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev); + out: + wdev_unlock(wdev); + cfg80211_unlock_rdev(wiphy_to_dev(wdev->wiphy)); + return err; } /* temporary symbol - mark GPL - in the future the handler won't be */ EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_siwessid); @@ -168,6 +192,7 @@ int cfg80211_mgd_wext_giwessid(struct net_device *dev, data->flags = 0; + wdev_lock(wdev); if (wdev->ssid_len) { data->flags = 1; data->length = wdev->ssid_len; @@ -178,6 +203,7 @@ int cfg80211_mgd_wext_giwessid(struct net_device *dev, memcpy(ssid, wdev->wext.connect.ssid, data->length); } else data->flags = 0; + wdev_unlock(wdev); return 0; } @@ -203,21 +229,25 @@ 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(wiphy_to_dev(wdev->wiphy)); + wdev_lock(wdev); + + err = 0; /* both automatic */ if (!bssid && !wdev->wext.connect.bssid) - return 0; + goto out; /* fixed already - and no change */ if (wdev->wext.connect.bssid && bssid && compare_ether_addr(bssid, wdev->wext.connect.bssid) == 0) - return 0; + goto out; if (wdev->sme_state != CFG80211_SME_IDLE) { - err = cfg80211_disconnect(wiphy_to_dev(wdev->wiphy), - dev, WLAN_REASON_DEAUTH_LEAVING, - false); + err = __cfg80211_disconnect(wiphy_to_dev(wdev->wiphy), + dev, WLAN_REASON_DEAUTH_LEAVING, + false); if (err) - return err; + goto out; } if (bssid) { @@ -226,7 +256,11 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev, } else wdev->wext.connect.bssid = NULL; - return cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev); + err = cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev); + out: + wdev_unlock(wdev); + cfg80211_unlock_rdev(wiphy_to_dev(wdev->wiphy)); + return err; } /* temporary symbol - mark GPL - in the future the handler won't be */ EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_siwap); @@ -243,12 +277,14 @@ int cfg80211_mgd_wext_giwap(struct net_device *dev, ap_addr->sa_family = ARPHRD_ETHER; + wdev_lock(wdev); if (wdev->current_bss) memcpy(ap_addr->sa_data, wdev->current_bss->pub.bssid, ETH_ALEN); else if (wdev->wext.connect.bssid) memcpy(ap_addr->sa_data, wdev->wext.connect.bssid, ETH_ALEN); else memset(ap_addr->sa_data, 0, ETH_ALEN); + wdev_unlock(wdev); return 0; } @@ -270,15 +306,20 @@ int cfg80211_wext_siwgenie(struct net_device *dev, if (!ie_len) ie = NULL; + wdev_lock(wdev); + /* no change */ + err = 0; if (wdev->wext.ie_len == ie_len && memcmp(wdev->wext.ie, ie, ie_len) == 0) - return 0; + goto out; if (ie_len) { ie = kmemdup(extra, ie_len, GFP_KERNEL); - if (!ie) - return -ENOMEM; + if (!ie) { + err = -ENOMEM; + goto out; + } } else ie = NULL; @@ -287,14 +328,17 @@ int cfg80211_wext_siwgenie(struct net_device *dev, wdev->wext.ie_len = ie_len; if (wdev->sme_state != CFG80211_SME_IDLE) { - err = cfg80211_disconnect(rdev, dev, - WLAN_REASON_DEAUTH_LEAVING, false); + err = __cfg80211_disconnect(rdev, dev, + WLAN_REASON_DEAUTH_LEAVING, false); if (err) - return err; + goto out; } /* userspace better not think we'll reconnect */ - return 0; + err = 0; + out: + wdev_unlock(wdev); + return err; } EXPORT_SYMBOL_GPL(cfg80211_wext_siwgenie); @@ -305,6 +349,7 @@ int cfg80211_wext_siwmlme(struct net_device *dev, struct wireless_dev *wdev = dev->ieee80211_ptr; struct iw_mlme *mlme = (struct iw_mlme *)extra; struct cfg80211_registered_device *rdev; + int err; if (!wdev) return -EOPNOTSUPP; @@ -317,13 +362,19 @@ int cfg80211_wext_siwmlme(struct net_device *dev, if (mlme->addr.sa_family != ARPHRD_ETHER) return -EINVAL; + wdev_lock(wdev); switch (mlme->cmd) { case IW_MLME_DEAUTH: case IW_MLME_DISASSOC: - return cfg80211_disconnect(rdev, dev, mlme->reason_code, - true); + err = __cfg80211_disconnect(rdev, dev, mlme->reason_code, + true); + break; default: - return -EOPNOTSUPP; + err = -EOPNOTSUPP; + break; } + wdev_unlock(wdev); + + return err; } EXPORT_SYMBOL_GPL(cfg80211_wext_siwmlme); |