aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-02-24 07:50:54 -0500
committerJohn W. Linville <linville@tuxdriver.com>2012-02-29 14:11:34 -0500
commit37ad38887d9ca5ed66c6f2b14a8921794bf3d4c3 (patch)
tree3c594ce2d6201209a65b197720bc2e6081988926 /net/mac80211
parent02d83e60b9864e7920d87b49e1fbedffd32470f8 (diff)
mac80211: make deauth/disassoc sequence more natural
The association sequence looks (roughly) like this now: * set BSSID * set station to EXIST state * send auth * set station to AUTH state * send assoc * set station to ASSOC state * set BSS info to associated In contrast, the deauth/disassoc sequence is the other way around: * clear BSSID/BSS info state * remove station * send deauth/disassoc (in some cases the last two steps are reversed.) This patch encodes the entire sequence in the ieee80211_set_disassoc() function and changes it to be like this, for good measure with an explicit flush: * send deauth/disassoc * flush * remove station * clear BSSID/BSS info state At least iwlwifi gets confused with the other sequence in P2P mode and complains that it wasn't able to flush the queues. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/mlme.c84
1 files changed, 47 insertions, 37 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 379a1d140161..caf97f5a2937 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1389,7 +1389,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
1389} 1389}
1390 1390
1391static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, 1391static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1392 bool remove_sta, bool tx) 1392 u16 stype, u16 reason, bool tx,
1393 u8 *frame_buf)
1393{ 1394{
1394 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 1395 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1395 struct ieee80211_local *local = sdata->local; 1396 struct ieee80211_local *local = sdata->local;
@@ -1399,6 +1400,9 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1399 1400
1400 ASSERT_MGD_MTX(ifmgd); 1401 ASSERT_MGD_MTX(ifmgd);
1401 1402
1403 if (WARN_ON_ONCE(tx && !frame_buf))
1404 return;
1405
1402 if (WARN_ON(!ifmgd->associated)) 1406 if (WARN_ON(!ifmgd->associated))
1403 return; 1407 return;
1404 1408
@@ -1432,6 +1436,19 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1432 } 1436 }
1433 mutex_unlock(&local->sta_mtx); 1437 mutex_unlock(&local->sta_mtx);
1434 1438
1439 /* deauthenticate/disassociate now */
1440 if (tx || frame_buf)
1441 ieee80211_send_deauth_disassoc(sdata, bssid, stype, reason,
1442 tx, frame_buf);
1443
1444 /* flush out frame */
1445 if (tx)
1446 drv_flush(local, false);
1447
1448 /* remove AP and TDLS peers */
1449 sta_info_flush(local, sdata);
1450
1451 /* finally reset all BSS / config parameters */
1435 changed |= ieee80211_reset_erp_info(sdata); 1452 changed |= ieee80211_reset_erp_info(sdata);
1436 1453
1437 ieee80211_led_assoc(local, 0); 1454 ieee80211_led_assoc(local, 0);
@@ -1471,10 +1488,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1471 changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT; 1488 changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT;
1472 ieee80211_bss_info_change_notify(sdata, changed); 1489 ieee80211_bss_info_change_notify(sdata, changed);
1473 1490
1474 /* remove AP and TDLS peers */
1475 if (remove_sta)
1476 sta_info_flush(local, sdata);
1477
1478 del_timer_sync(&sdata->u.mgd.conn_mon_timer); 1491 del_timer_sync(&sdata->u.mgd.conn_mon_timer);
1479 del_timer_sync(&sdata->u.mgd.bcn_mon_timer); 1492 del_timer_sync(&sdata->u.mgd.bcn_mon_timer);
1480 del_timer_sync(&sdata->u.mgd.timer); 1493 del_timer_sync(&sdata->u.mgd.timer);
@@ -1684,17 +1697,15 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata)
1684 printk(KERN_DEBUG "%s: Connection to AP %pM lost.\n", 1697 printk(KERN_DEBUG "%s: Connection to AP %pM lost.\n",
1685 sdata->name, bssid); 1698 sdata->name, bssid);
1686 1699
1687 ieee80211_set_disassoc(sdata, true, false); 1700 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
1701 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
1702 false, frame_buf);
1688 mutex_unlock(&ifmgd->mtx); 1703 mutex_unlock(&ifmgd->mtx);
1689 1704
1690 /* 1705 /*
1691 * must be outside lock due to cfg80211, 1706 * must be outside lock due to cfg80211,
1692 * but that's not a problem. 1707 * but that's not a problem.
1693 */ 1708 */
1694 ieee80211_send_deauth_disassoc(sdata, bssid,
1695 IEEE80211_STYPE_DEAUTH,
1696 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
1697 false, frame_buf);
1698 cfg80211_send_deauth(sdata->dev, frame_buf, DEAUTH_DISASSOC_LEN); 1709 cfg80211_send_deauth(sdata->dev, frame_buf, DEAUTH_DISASSOC_LEN);
1699 1710
1700 mutex_lock(&local->mtx); 1711 mutex_lock(&local->mtx);
@@ -1902,7 +1913,8 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
1902 printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n", 1913 printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n",
1903 sdata->name, bssid, reason_code); 1914 sdata->name, bssid, reason_code);
1904 1915
1905 ieee80211_set_disassoc(sdata, true, false); 1916 ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
1917
1906 mutex_lock(&sdata->local->mtx); 1918 mutex_lock(&sdata->local->mtx);
1907 ieee80211_recalc_idle(sdata->local); 1919 ieee80211_recalc_idle(sdata->local);
1908 mutex_unlock(&sdata->local->mtx); 1920 mutex_unlock(&sdata->local->mtx);
@@ -1932,10 +1944,12 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
1932 printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n", 1944 printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n",
1933 sdata->name, mgmt->sa, reason_code); 1945 sdata->name, mgmt->sa, reason_code);
1934 1946
1935 ieee80211_set_disassoc(sdata, true, false); 1947 ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
1948
1936 mutex_lock(&sdata->local->mtx); 1949 mutex_lock(&sdata->local->mtx);
1937 ieee80211_recalc_idle(sdata->local); 1950 ieee80211_recalc_idle(sdata->local);
1938 mutex_unlock(&sdata->local->mtx); 1951 mutex_unlock(&sdata->local->mtx);
1952
1939 return RX_MGMT_CFG80211_DISASSOC; 1953 return RX_MGMT_CFG80211_DISASSOC;
1940} 1954}
1941 1955
@@ -2699,15 +2713,14 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
2699 ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | 2713 ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL |
2700 IEEE80211_STA_BEACON_POLL); 2714 IEEE80211_STA_BEACON_POLL);
2701 2715
2702 ieee80211_set_disassoc(sdata, true, false); 2716 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, reason,
2717 false, frame_buf);
2703 mutex_unlock(&ifmgd->mtx); 2718 mutex_unlock(&ifmgd->mtx);
2719
2704 /* 2720 /*
2705 * must be outside lock due to cfg80211, 2721 * must be outside lock due to cfg80211,
2706 * but that's not a problem. 2722 * but that's not a problem.
2707 */ 2723 */
2708 ieee80211_send_deauth_disassoc(sdata, bssid,
2709 IEEE80211_STYPE_DEAUTH,
2710 reason, false, frame_buf);
2711 cfg80211_send_deauth(sdata->dev, frame_buf, DEAUTH_DISASSOC_LEN); 2724 cfg80211_send_deauth(sdata->dev, frame_buf, DEAUTH_DISASSOC_LEN);
2712 2725
2713 mutex_lock(&local->mtx); 2726 mutex_lock(&local->mtx);
@@ -3192,7 +3205,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
3192 ifmgd->auth_data = auth_data; 3205 ifmgd->auth_data = auth_data;
3193 3206
3194 if (ifmgd->associated) 3207 if (ifmgd->associated)
3195 ieee80211_set_disassoc(sdata, true, false); 3208 ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
3196 3209
3197 printk(KERN_DEBUG "%s: authenticate with %pM\n", 3210 printk(KERN_DEBUG "%s: authenticate with %pM\n",
3198 sdata->name, req->bss->bssid); 3211 sdata->name, req->bss->bssid);
@@ -3270,7 +3283,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
3270 mutex_lock(&ifmgd->mtx); 3283 mutex_lock(&ifmgd->mtx);
3271 3284
3272 if (ifmgd->associated) 3285 if (ifmgd->associated)
3273 ieee80211_set_disassoc(sdata, true, false); 3286 ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
3274 3287
3275 if (ifmgd->auth_data && !ifmgd->auth_data->done) { 3288 if (ifmgd->auth_data && !ifmgd->auth_data->done) {
3276 err = -EBUSY; 3289 err = -EBUSY;
@@ -3443,31 +3456,32 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
3443 struct cfg80211_deauth_request *req) 3456 struct cfg80211_deauth_request *req)
3444{ 3457{
3445 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 3458 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
3446 bool assoc_bss = false;
3447 u8 frame_buf[DEAUTH_DISASSOC_LEN]; 3459 u8 frame_buf[DEAUTH_DISASSOC_LEN];
3448 3460
3449 mutex_lock(&ifmgd->mtx); 3461 mutex_lock(&ifmgd->mtx);
3450 3462
3451 if (ifmgd->associated && 3463 if (ifmgd->auth_data) {
3452 memcmp(ifmgd->associated->bssid, req->bssid, ETH_ALEN) == 0) {
3453 ieee80211_set_disassoc(sdata, false, true);
3454 assoc_bss = true;
3455 } else if (ifmgd->auth_data) {
3456 ieee80211_destroy_auth_data(sdata, false); 3464 ieee80211_destroy_auth_data(sdata, false);
3457 mutex_unlock(&ifmgd->mtx); 3465 mutex_unlock(&ifmgd->mtx);
3458 return 0; 3466 return 0;
3459 } 3467 }
3460 mutex_unlock(&ifmgd->mtx);
3461 3468
3462 printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n", 3469 printk(KERN_DEBUG
3470 "%s: deauthenticating from %pM by local choice (reason=%d)\n",
3463 sdata->name, req->bssid, req->reason_code); 3471 sdata->name, req->bssid, req->reason_code);
3464 3472
3465 ieee80211_send_deauth_disassoc(sdata, req->bssid, 3473 if (ifmgd->associated &&
3466 IEEE80211_STYPE_DEAUTH, 3474 memcmp(ifmgd->associated->bssid, req->bssid, ETH_ALEN) == 0)
3475 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
3467 req->reason_code, true, frame_buf); 3476 req->reason_code, true, frame_buf);
3477 else
3478 ieee80211_send_deauth_disassoc(sdata, req->bssid,
3479 IEEE80211_STYPE_DEAUTH,
3480 req->reason_code, true,
3481 frame_buf);
3482 mutex_unlock(&ifmgd->mtx);
3483
3468 __cfg80211_send_deauth(sdata->dev, frame_buf, DEAUTH_DISASSOC_LEN); 3484 __cfg80211_send_deauth(sdata->dev, frame_buf, DEAUTH_DISASSOC_LEN);
3469 if (assoc_bss)
3470 sta_info_flush(sdata->local, sdata);
3471 3485
3472 mutex_lock(&sdata->local->mtx); 3486 mutex_lock(&sdata->local->mtx);
3473 ieee80211_recalc_idle(sdata->local); 3487 ieee80211_recalc_idle(sdata->local);
@@ -3500,16 +3514,12 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
3500 sdata->name, req->bss->bssid, req->reason_code); 3514 sdata->name, req->bss->bssid, req->reason_code);
3501 3515
3502 memcpy(bssid, req->bss->bssid, ETH_ALEN); 3516 memcpy(bssid, req->bss->bssid, ETH_ALEN);
3503 ieee80211_set_disassoc(sdata, false, !req->local_state_change); 3517 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DISASSOC,
3504 3518 req->reason_code, !req->local_state_change,
3519 frame_buf);
3505 mutex_unlock(&ifmgd->mtx); 3520 mutex_unlock(&ifmgd->mtx);
3506 3521
3507 ieee80211_send_deauth_disassoc(sdata, req->bss->bssid,
3508 IEEE80211_STYPE_DISASSOC,
3509 req->reason_code,
3510 !req->local_state_change, frame_buf);
3511 __cfg80211_send_disassoc(sdata->dev, frame_buf, DEAUTH_DISASSOC_LEN); 3522 __cfg80211_send_disassoc(sdata->dev, frame_buf, DEAUTH_DISASSOC_LEN);
3512 sta_info_flush(sdata->local, sdata);
3513 3523
3514 mutex_lock(&sdata->local->mtx); 3524 mutex_lock(&sdata->local->mtx);
3515 ieee80211_recalc_idle(sdata->local); 3525 ieee80211_recalc_idle(sdata->local);