diff options
author | Yu Wang <yyuwang@codeaurora.org> | 2019-05-10 05:04:52 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2019-05-24 05:26:44 -0400 |
commit | 79c92ca42b5a3e0ea172ea2ce8df8e125af237da (patch) | |
tree | 08884f0a15aadc6b1edf04c21e1d2c3a32a840e2 /net/mac80211/mlme.c | |
parent | 32b5a2c9950b9284000059d752f7afa164deb15e (diff) |
mac80211: handle deauthentication/disassociation from TDLS peer
When receiving a deauthentication/disassociation frame from a TDLS
peer, a station should not disconnect the current AP, but only
disable the current TDLS link if it's enabled.
Without this change, a TDLS issue can be reproduced by following the
steps as below:
1. STA-1 and STA-2 are connected to AP, bidirection traffic is running
between STA-1 and STA-2.
2. Set up TDLS link between STA-1 and STA-2, stay for a while, then
teardown TDLS link.
3. Repeat step #2 and monitor the connection between STA and AP.
During the test, one STA may send a deauthentication/disassociation
frame to another, after TDLS teardown, with reason code 6/7, which
means: Class 2/3 frame received from nonassociated STA.
On receive this frame, the receiver STA will disconnect the current
AP and then reconnect. It's not a expected behavior, purpose of this
frame should be disabling the TDLS link, not the link with AP.
Cc: stable@vger.kernel.org
Signed-off-by: Yu Wang <yyuwang@codeaurora.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r-- | net/mac80211/mlme.c | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index b7a9fe3d5fcb..383b0df100e4 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -2963,7 +2963,7 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, | |||
2963 | #define case_WLAN(type) \ | 2963 | #define case_WLAN(type) \ |
2964 | case WLAN_REASON_##type: return #type | 2964 | case WLAN_REASON_##type: return #type |
2965 | 2965 | ||
2966 | static const char *ieee80211_get_reason_code_string(u16 reason_code) | 2966 | const char *ieee80211_get_reason_code_string(u16 reason_code) |
2967 | { | 2967 | { |
2968 | switch (reason_code) { | 2968 | switch (reason_code) { |
2969 | case_WLAN(UNSPECIFIED); | 2969 | case_WLAN(UNSPECIFIED); |
@@ -3028,6 +3028,11 @@ static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, | |||
3028 | if (len < 24 + 2) | 3028 | if (len < 24 + 2) |
3029 | return; | 3029 | return; |
3030 | 3030 | ||
3031 | if (!ether_addr_equal(mgmt->bssid, mgmt->sa)) { | ||
3032 | ieee80211_tdls_handle_disconnect(sdata, mgmt->sa, reason_code); | ||
3033 | return; | ||
3034 | } | ||
3035 | |||
3031 | if (ifmgd->associated && | 3036 | if (ifmgd->associated && |
3032 | ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid)) { | 3037 | ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid)) { |
3033 | const u8 *bssid = ifmgd->associated->bssid; | 3038 | const u8 *bssid = ifmgd->associated->bssid; |
@@ -3077,6 +3082,11 @@ static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, | |||
3077 | 3082 | ||
3078 | reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); | 3083 | reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); |
3079 | 3084 | ||
3085 | if (!ether_addr_equal(mgmt->bssid, mgmt->sa)) { | ||
3086 | ieee80211_tdls_handle_disconnect(sdata, mgmt->sa, reason_code); | ||
3087 | return; | ||
3088 | } | ||
3089 | |||
3080 | sdata_info(sdata, "disassociated from %pM (Reason: %u=%s)\n", | 3090 | sdata_info(sdata, "disassociated from %pM (Reason: %u=%s)\n", |
3081 | mgmt->sa, reason_code, | 3091 | mgmt->sa, reason_code, |
3082 | ieee80211_get_reason_code_string(reason_code)); | 3092 | ieee80211_get_reason_code_string(reason_code)); |