From 9e8fde21348bbdcd8c6d9892820106f93d7738f1 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 15 Jan 2016 19:28:58 +0200 Subject: [PATCH] AP: Fix Deauth/Disassoc TX status timeout handling The ap_sta_deauth_cb and ap_sta_disassoc_cb eloop timeouts are used to clear a disconnecting STA from the kernel driver if the STA did not ACK the Deauthentication/Disassociation frame from the AP within two seconds. However, it was possible for a STA to not ACK such a frame, e.g., when the disconnection happened due to hostapd pruning old associations from other BSSes and the STA was not on the old channel anymore. If that same STA then started a new authentication/association with the BSS, the two second timeout could trigger during this new association and result in the STA entry getting removed from the kernel. Fix this by canceling these eloop timeouts when receiving an indication of a new authentication or association. Signed-off-by: Jouni Malinen --- src/ap/ap_mlme.c | 3 +++ src/ap/hostapd.c | 1 + src/ap/sta_info.c | 19 +++++++++++++++++-- src/ap/sta_info.h | 2 ++ 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/ap/ap_mlme.c b/src/ap/ap_mlme.c index 13604ed..e7308a0 100644 --- a/src/ap/ap_mlme.c +++ b/src/ap/ap_mlme.c @@ -59,6 +59,7 @@ void mlme_authenticate_indication(struct hostapd_data *hapd, MAC2STR(sta->addr), mlme_auth_alg_str(sta->auth_alg)); if (sta->auth_alg != WLAN_AUTH_FT && !(sta->flags & WLAN_STA_MFP)) mlme_deletekeys_request(hapd, sta); + ap_sta_clear_disconnect_timeouts(hapd, sta); } @@ -106,6 +107,7 @@ void mlme_associate_indication(struct hostapd_data *hapd, struct sta_info *sta) MAC2STR(sta->addr)); if (sta->auth_alg != WLAN_AUTH_FT) mlme_deletekeys_request(hapd, sta); + ap_sta_clear_disconnect_timeouts(hapd, sta); } @@ -130,6 +132,7 @@ void mlme_reassociate_indication(struct hostapd_data *hapd, MAC2STR(sta->addr)); if (sta->auth_alg != WLAN_AUTH_FT) mlme_deletekeys_request(hapd, sta); + ap_sta_clear_disconnect_timeouts(hapd, sta); } diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index b10b454..8e04d6c 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -2634,6 +2634,7 @@ void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta, } hostapd_prune_associations(hapd, sta->addr); + ap_sta_clear_disconnect_timeouts(hapd, sta); /* IEEE 802.11F (IAPP) */ if (hapd->conf->ieee802_11f) diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c index 68fff4c..c3105aa 100644 --- a/src/ap/sta_info.c +++ b/src/ap/sta_info.c @@ -249,8 +249,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) eloop_cancel_timeout(ap_handle_timer, hapd, sta); eloop_cancel_timeout(ap_handle_session_timer, hapd, sta); eloop_cancel_timeout(ap_handle_session_warning_timer, hapd, sta); - eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta); - eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta); + ap_sta_clear_disconnect_timeouts(hapd, sta); sae_clear_retransmit_timer(hapd, sta); ieee802_1x_free_station(hapd, sta); @@ -1117,6 +1116,22 @@ void ap_sta_disassoc_cb(struct hostapd_data *hapd, struct sta_info *sta) } +void ap_sta_clear_disconnect_timeouts(struct hostapd_data *hapd, + struct sta_info *sta) +{ + if (eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta) > 0) + wpa_printf(MSG_DEBUG, + "%s: Removed ap_sta_deauth_cb_timeout timeout for " + MACSTR, + hapd->conf->iface, MAC2STR(sta->addr)); + if (eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta) > 0) + wpa_printf(MSG_DEBUG, + "%s: Removed ap_sta_disassoc_cb_timeout timeout for " + MACSTR, + hapd->conf->iface, MAC2STR(sta->addr)); +} + + int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen) { int res; diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h index 09deac6..e3b4915 100644 --- a/src/ap/sta_info.h +++ b/src/ap/sta_info.h @@ -236,6 +236,8 @@ static inline int ap_sta_is_authorized(struct sta_info *sta) void ap_sta_deauth_cb(struct hostapd_data *hapd, struct sta_info *sta); void ap_sta_disassoc_cb(struct hostapd_data *hapd, struct sta_info *sta); +void ap_sta_clear_disconnect_timeouts(struct hostapd_data *hapd, + struct sta_info *sta); int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen); -- 2.1.4