mac80211: send deauth only with channel context
authorJohannes Berg <johannes.berg@intel.com>
Mon, 29 Oct 2012 08:46:31 +0000 (09:46 +0100)
committerJohannes Berg <johannes.berg@intel.com>
Mon, 5 Nov 2012 13:13:33 +0000 (14:13 +0100)
When userspace asks to deauthenticate and we're just
authenticated (or still authenticating) send a deauth
frame instead of deleting the auth request.

On the other hand, if we've just disassociated and
therefore deleted all our state already, drop the
deauth request because we no longer have a channel
context to send it on.

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

index d29762fdd887ae69e0f3b11886918f9daa834c23..02ffe8738243f546594cddded83569c9f95f0776 100644 (file)
@@ -3662,40 +3662,44 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
        bool tx = !req->local_state_change;
+       bool sent_frame = false;
 
        mutex_lock(&ifmgd->mtx);
 
-       if (ifmgd->auth_data) {
-               ieee80211_destroy_auth_data(sdata, false);
-               mutex_unlock(&ifmgd->mtx);
-               return 0;
-       }
-
        sdata_info(sdata,
                   "deauthenticating from %pM by local choice (reason=%d)\n",
                   req->bssid, req->reason_code);
 
-       if (ifmgd->associated &&
-           ether_addr_equal(ifmgd->associated->bssid, req->bssid)) {
-               ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
-                                      req->reason_code, tx, frame_buf);
-       } else {
+       if (ifmgd->auth_data) {
                drv_mgd_prepare_tx(sdata->local, sdata);
                ieee80211_send_deauth_disassoc(sdata, req->bssid,
                                               IEEE80211_STYPE_DEAUTH,
                                               req->reason_code, tx,
                                               frame_buf);
+               ieee80211_destroy_auth_data(sdata, false);
+               mutex_unlock(&ifmgd->mtx);
+
+               sent_frame = tx;
+               goto out;
        }
 
+       if (ifmgd->associated &&
+           ether_addr_equal(ifmgd->associated->bssid, req->bssid)) {
+               ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
+                                      req->reason_code, tx, frame_buf);
+               sent_frame = tx;
+       }
        mutex_unlock(&ifmgd->mtx);
 
-       __cfg80211_send_deauth(sdata->dev, frame_buf,
-                              IEEE80211_DEAUTH_FRAME_LEN);
-
+ out:
        mutex_lock(&sdata->local->mtx);
        ieee80211_recalc_idle(sdata->local);
        mutex_unlock(&sdata->local->mtx);
 
+       if (sent_frame)
+               __cfg80211_send_deauth(sdata->dev, frame_buf,
+                                      IEEE80211_DEAUTH_FRAME_LEN);
+
        return 0;
 }