hostapd: backport a few upstream fixes
[openwrt/openwrt.git] / package / network / services / hostapd / patches / 001-Fix-race-condition-between-AssocResp-callback-and-4a.patch
diff --git a/package/network/services/hostapd/patches/001-Fix-race-condition-between-AssocResp-callback-and-4a.patch b/package/network/services/hostapd/patches/001-Fix-race-condition-between-AssocResp-callback-and-4a.patch
new file mode 100644 (file)
index 0000000..bf54e9d
--- /dev/null
@@ -0,0 +1,83 @@
+From: Jouni Malinen <jouni@qca.qualcomm.com>
+Date: Tue, 20 Dec 2016 01:30:09 +0200
+Subject: [PATCH] Fix race condition between AssocResp callback and 4addr event
+
+It is apparently possible for the NL80211_CMD_UNEXPECTED_4ADDR_FRAME
+event to be delivered to hostapd before the NL80211_CMD_FRAME_TX_STATUS
+event for (Re)Association Response frame. This resulted in the 4-address
+WDS mode not getting enabled for a STA. This could occur in particular
+when operating under heavy load and the STA is reconnecting to the same
+AP in a sequence where Deauthentication frame is followed immediately by
+Authentication frame and the driver event processing gets delayed due to
+removal of the previous netdev taking time in the middle of this
+sequence.
+
+Fix this by recording a pending item for 4-address WDS enabling if the
+NL80211_CMD_UNEXPECTED_4ADDR_FRAME event would have been dropped due to
+incompleted association and then process this pending item if the TX
+status for the (Re)Association Response frame is received and it shows
+that the frame was acknowledged.
+
+Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
+---
+
+--- a/src/ap/ieee802_11.c
++++ b/src/ap/ieee802_11.c
+@@ -2634,6 +2634,8 @@ static void handle_assoc(struct hostapd_
+       taxonomy_sta_info_assoc_req(hapd, sta, pos, left);
+ #endif /* CONFIG_TAXONOMY */
++      sta->pending_wds_enable = 0;
++
+  fail:
+       /*
+        * In case of a successful response, add the station to the driver.
+@@ -3248,6 +3250,14 @@ static void handle_assoc_cb(struct hosta
+       hostapd_set_sta_flags(hapd, sta);
++      if (!(sta->flags & WLAN_STA_WDS) && sta->pending_wds_enable) {
++              wpa_printf(MSG_DEBUG, "Enable 4-address WDS mode for STA "
++                         MACSTR " based on pending request",
++                         MAC2STR(sta->addr));
++              sta->pending_wds_enable = 0;
++              sta->flags |= WLAN_STA_WDS;
++      }
++
+       if (sta->flags & WLAN_STA_WDS) {
+               int ret;
+               char ifname_wds[IFNAMSIZ + 1];
+@@ -3512,10 +3522,22 @@ void ieee802_11_rx_from_unknown(struct h
+       struct sta_info *sta;
+       sta = ap_get_sta(hapd, src);
+-      if (sta && (sta->flags & WLAN_STA_ASSOC)) {
++      if (sta &&
++          ((sta->flags & WLAN_STA_ASSOC) ||
++           ((sta->flags & WLAN_STA_ASSOC_REQ_OK) && wds))) {
+               if (!hapd->conf->wds_sta)
+                       return;
++              if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK)) ==
++                  WLAN_STA_ASSOC_REQ_OK) {
++                      wpa_printf(MSG_DEBUG,
++                                 "Postpone 4-address WDS mode enabling for STA "
++                                 MACSTR " since TX status for AssocResp is not yet known",
++                                 MAC2STR(sta->addr));
++                      sta->pending_wds_enable = 1;
++                      return;
++              }
++
+               if (wds && !(sta->flags & WLAN_STA_WDS)) {
+                       int ret;
+                       char ifname_wds[IFNAMSIZ + 1];
+--- a/src/ap/sta_info.h
++++ b/src/ap/sta_info.h
+@@ -115,6 +115,7 @@ struct sta_info {
+       unsigned int radius_das_match:1;
+       unsigned int ecsa_supported:1;
+       unsigned int added_unassoc:1;
++      unsigned int pending_wds_enable:1;
+       u16 auth_alg;