diff options
author | Johannes Berg <johannes.berg@intel.com> | 2012-02-24 07:50:54 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-02-29 14:11:34 -0500 |
commit | 37ad38887d9ca5ed66c6f2b14a8921794bf3d4c3 (patch) | |
tree | 3c594ce2d6201209a65b197720bc2e6081988926 /net/mac80211 | |
parent | 02d83e60b9864e7920d87b49e1fbedffd32470f8 (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.c | 84 |
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 | ||
1391 | static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | 1391 | static 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); |