cfg80211: hold BSS over association process
authorJohannes Berg <johannes.berg@intel.com>
Wed, 19 Jun 2013 11:21:15 +0000 (13:21 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Wed, 19 Jun 2013 16:55:39 +0000 (18:55 +0200)
This fixes the potential issue that the BSS struct that we use
and later assign to wdev->current_bss is removed from the scan
list while associating.

Also warn when we don't have a BSS struct in connect_result
unless it's from a driver that only has the connect() API.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/wireless/mlme.c
net/wireless/sme.c

index dd6f79d7bd2e13075dde8cbbcedbeed64edb6a67..bfac5e186f579f8b6d526de5d100a77083e45696 100644 (file)
@@ -38,6 +38,7 @@ void cfg80211_rx_assoc_resp(struct net_device *dev, struct cfg80211_bss *bss,
         * frame instead of reassoc.
         */
        if (cfg80211_sme_rx_assoc_resp(wdev, status_code)) {
+               cfg80211_unhold_bss(bss_from_pub(bss));
                cfg80211_put_bss(wiphy, bss);
                return;
        }
@@ -142,6 +143,7 @@ void cfg80211_assoc_timeout(struct net_device *dev, struct cfg80211_bss *bss)
        nl80211_send_assoc_timeout(rdev, dev, bss->bssid, GFP_KERNEL);
        cfg80211_sme_assoc_timeout(wdev);
 
+       cfg80211_unhold_bss(bss_from_pub(bss));
        cfg80211_put_bss(wiphy, bss);
 }
 EXPORT_SYMBOL(cfg80211_assoc_timeout);
@@ -309,6 +311,8 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
                goto out;
 
        err = rdev_assoc(rdev, dev, req);
+       if (!err)
+               cfg80211_hold_bss(bss_from_pub(req->bss));
 
 out:
        if (err)
index ae7e2cbf45cbfe2cc22ac52eff9262833eca5861..c0bf781d4fbea87378d724c5b00d28d6a7a4fb7d 100644 (file)
@@ -615,19 +615,24 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
                kfree(wdev->connect_keys);
                wdev->connect_keys = NULL;
                wdev->ssid_len = 0;
-               cfg80211_put_bss(wdev->wiphy, bss);
+               if (bss) {
+                       cfg80211_unhold_bss(bss_from_pub(bss));
+                       cfg80211_put_bss(wdev->wiphy, bss);
+               }
                return;
        }
 
-       if (!bss)
+       if (!bss) {
+               WARN_ON_ONCE(!wiphy_to_dev(wdev->wiphy)->ops->connect);
                bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
                                       wdev->ssid, wdev->ssid_len,
                                       WLAN_CAPABILITY_ESS,
                                       WLAN_CAPABILITY_ESS);
-       if (WARN_ON(!bss))
-               return;
+               if (WARN_ON(!bss))
+                       return;
+               cfg80211_hold_bss(bss_from_pub(bss));
+       }
 
-       cfg80211_hold_bss(bss_from_pub(bss));
        wdev->current_bss = bss_from_pub(bss);
 
        cfg80211_upload_connect_keys(wdev);