[PATCH 1/3] AP: add station to driver before sending Assoc Resp
Michal Kazior
michal.kazior
Thu Jul 9 05:26:24 PDT 2015
Station could receive Assoc Resp from AP and start
sending frames back (e.g. NullFunc saying it goes
to sleep) to AP before the AP processed TX_STATUS
for the Assoc Resp. Depending on device driver and
event ordering the station could end up being
Deauthenticated with reason 7 (class 3 from
non-assoc sta) by the AP.
Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
---
src/ap/ieee802_11.c | 96 ++++++++++++++++++++++++++++++++---------------------
1 file changed, 59 insertions(+), 37 deletions(-)
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index db20c8679093..957fd02eff24 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -1561,6 +1561,40 @@ static void send_deauth(struct hostapd_data *hapd, const u8 *addr,
}
+static int add_pre_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta)
+{
+ /*
+ * Remove the STA entry in order to make sure the STA PS state gets
+ * cleared and configuration gets updated in case of reassociation back
+ * to the same AP.
+ */
+ hostapd_drv_sta_remove(hapd, sta->addr);
+
+#ifdef CONFIG_IEEE80211N
+ if (sta->flags & WLAN_STA_HT)
+ hostapd_get_ht_capab(hapd, sta->ht_capabilities, &ht_cap);
+#endif /* CONFIG_IEEE80211N */
+#ifdef CONFIG_IEEE80211AC
+ if (sta->flags & WLAN_STA_VHT)
+ hostapd_get_vht_capab(hapd, sta->vht_capabilities, &vht_cap);
+#endif /* CONFIG_IEEE80211AC */
+
+ if (hostapd_sta_add(hapd, sta->addr, sta->aid, sta->capability,
+ sta->supported_rates, sta->supported_rates_len,
+ sta->listen_interval,
+ sta->flags & WLAN_STA_HT ? &ht_cap : NULL,
+ sta->flags & WLAN_STA_VHT ? &vht_cap : NULL,
+ sta->flags, sta->qosinfo, sta->vht_opmode)) {
+ hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
+ HOSTAPD_LEVEL_NOTICE,
+ "Could not add STA to kernel driver");
+ return -1;
+ }
+
+ return 0;
+}
+
+
static void send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
u16 status_code, int reassoc, const u8 *ies,
size_t ies_len)
@@ -1784,7 +1818,7 @@ static void handle_assoc(struct hostapd_data *hapd,
if (hapd->tkip_countermeasures) {
resp = WLAN_REASON_MICHAEL_MIC_FAILURE;
- goto fail;
+ goto send_resp;
}
if (listen_interval > hapd->conf->max_listen_interval) {
@@ -1793,20 +1827,20 @@ static void handle_assoc(struct hostapd_data *hapd,
"Too large Listen Interval (%d)",
listen_interval);
resp = WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE;
- goto fail;
+ goto send_resp;
}
/* followed by SSID and Supported rates; and HT capabilities if 802.11n
* is used */
resp = check_assoc_ies(hapd, sta, pos, left, reassoc);
if (resp != WLAN_STATUS_SUCCESS)
- goto fail;
+ goto send_resp;
if (hostapd_get_aid(hapd, sta) < 0) {
hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_INFO, "No room for more AIDs");
resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
- goto fail;
+ goto send_resp;
}
sta->capability = capab_info;
@@ -1879,8 +1913,28 @@ static void handle_assoc(struct hostapd_data *hapd,
* remove the STA immediately. */
sta->timeout_next = STA_NULLFUNC;
- fail:
+send_resp:
+ if (resp == WLAN_STATUS_SUCCESS) {
+ /* TODO: The station shouldn't be considered as Associated
+ * until after Assoc Resp ACK is delivered. However some
+ * drivers can get racy and end up deauthing stations before
+ * hostap adds the station entry.
+ *
+ * Currently stations are transitioned from non-existent into
+ * associated state right away. Ideally this should be split so
+ * that station can have 2 transitions: non-existent ->
+ * authenticated, authenticated -> associated.
+ */
+ res = add_pre_assoc_sta(hapd, sta);
+ if (res)
+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ }
+
send_assoc_resp(hapd, sta, resp, reassoc, pos, left);
+
+ if (resp != WLAN_STATUS_SUCCESS)
+ ap_sta_disconnect(hapd, sta, sta->addr,
+ WLAN_REASON_DISASSOC_AP_BUSY);
}
@@ -2415,38 +2469,6 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
sta->sa_query_timed_out = 0;
#endif /* CONFIG_IEEE80211W */
- /*
- * Remove the STA entry in order to make sure the STA PS state gets
- * cleared and configuration gets updated in case of reassociation back
- * to the same AP.
- */
- hostapd_drv_sta_remove(hapd, sta->addr);
-
-#ifdef CONFIG_IEEE80211N
- if (sta->flags & WLAN_STA_HT)
- hostapd_get_ht_capab(hapd, sta->ht_capabilities, &ht_cap);
-#endif /* CONFIG_IEEE80211N */
-#ifdef CONFIG_IEEE80211AC
- if (sta->flags & WLAN_STA_VHT)
- hostapd_get_vht_capab(hapd, sta->vht_capabilities, &vht_cap);
-#endif /* CONFIG_IEEE80211AC */
-
- if (hostapd_sta_add(hapd, sta->addr, sta->aid, sta->capability,
- sta->supported_rates, sta->supported_rates_len,
- sta->listen_interval,
- sta->flags & WLAN_STA_HT ? &ht_cap : NULL,
- sta->flags & WLAN_STA_VHT ? &vht_cap : NULL,
- sta->flags, sta->qosinfo, sta->vht_opmode)) {
- hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
- HOSTAPD_LEVEL_NOTICE,
- "Could not add STA to kernel driver");
-
- ap_sta_disconnect(hapd, sta, sta->addr,
- WLAN_REASON_DISASSOC_AP_BUSY);
-
- return;
- }
-
if (sta->flags & WLAN_STA_WDS) {
int ret;
char ifname_wds[IFNAMSIZ + 1];
--
2.1.4
More information about the Hostap
mailing list