hostapd: backport a few upstream fixes
authorFelix Fietkau <nbd@nbd.name>
Sun, 15 Jan 2017 13:19:43 +0000 (14:19 +0100)
committerFelix Fietkau <nbd@nbd.name>
Sun, 15 Jan 2017 13:53:28 +0000 (14:53 +0100)
Fixes reassoc issues with WDS mode
Fixes reassoc issues in AP mode
Fixes IBSS reauthentication issues

Signed-off-by: Felix Fietkau <nbd@nbd.name>
package/network/services/hostapd/patches/001-Fix-race-condition-between-AssocResp-callback-and-4a.patch [new file with mode: 0644]
package/network/services/hostapd/patches/002-Fix-duplicate-Reassociation-Request-frame-dropping.patch [new file with mode: 0644]
package/network/services/hostapd/patches/003-RSN-IBSS-Fix-TK-clearing-on-Authentication-frame-RX.patch [new file with mode: 0644]
package/network/services/hostapd/patches/100-daemonize_fix.patch
package/network/services/hostapd/patches/600-ubus_support.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;
diff --git a/package/network/services/hostapd/patches/002-Fix-duplicate-Reassociation-Request-frame-dropping.patch b/package/network/services/hostapd/patches/002-Fix-duplicate-Reassociation-Request-frame-dropping.patch
new file mode 100644 (file)
index 0000000..6db1e9b
--- /dev/null
@@ -0,0 +1,36 @@
+From: Jouni Malinen <jouni@qca.qualcomm.com>
+Date: Sat, 14 Jan 2017 01:04:31 +0200
+Subject: [PATCH] Fix duplicate Reassociation Request frame dropping
+
+Relational operators (==) have higher precedence than the ternary
+conditional in C. The last_subtype check for association/reassociation
+was broken due to incorrect assumption about the precedence. Fix this by
+adding parenthesis around the ternary conditional.
+
+The previous implementation worked for Association Request frames by
+accident since WLAN_FC_STYPE_ASSOC_REQ happens to have value 0 and when
+the last receive frame was an Association Request frame, the
+sta->last_subtype == reassoc check was true and non-zero
+WLAN_FC_STYPE_REASSOC_REQ was interpreted as true. However, this was
+broken for Reassociation Request frame. reassoc == 1 in that case could
+have matched received Association Response frame (subtype == 1), but
+those are not received in AP mode and as such, this did not break other
+behavior apart from not being able to drop duplicated Reassociation
+Request frames.
+
+Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
+---
+
+--- a/src/ap/ieee802_11.c
++++ b/src/ap/ieee802_11.c
+@@ -2485,8 +2485,8 @@ static void handle_assoc(struct hostapd_
+       if ((fc & WLAN_FC_RETRY) &&
+           sta->last_seq_ctrl != WLAN_INVALID_MGMT_SEQ &&
+           sta->last_seq_ctrl == seq_ctrl &&
+-          sta->last_subtype == reassoc ? WLAN_FC_STYPE_REASSOC_REQ :
+-          WLAN_FC_STYPE_ASSOC_REQ) {
++          sta->last_subtype == (reassoc ? WLAN_FC_STYPE_REASSOC_REQ :
++                                WLAN_FC_STYPE_ASSOC_REQ)) {
+               hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
+                              HOSTAPD_LEVEL_DEBUG,
+                              "Drop repeated association frame seq_ctrl=0x%x",
diff --git a/package/network/services/hostapd/patches/003-RSN-IBSS-Fix-TK-clearing-on-Authentication-frame-RX.patch b/package/network/services/hostapd/patches/003-RSN-IBSS-Fix-TK-clearing-on-Authentication-frame-RX.patch
new file mode 100644 (file)
index 0000000..0a3c27f
--- /dev/null
@@ -0,0 +1,40 @@
+From: Jouni Malinen <j@w1.fi>
+Date: Sat, 14 Jan 2017 13:56:18 +0200
+Subject: [PATCH] RSN IBSS: Fix TK clearing on Authentication frame RX
+
+When wpa_supplicant was processing a received Authentication frame (seq
+1) from a peer STA for which there was already a TK configured to the
+driver, debug log claimed that the PTK gets cleared, but the actual
+call to clear the key was actually dropped due to AUTH vs. SUPP set_key
+selection. Fix this by explicitly clearing the TK in case it was set
+and an Authentication frame (seq 1) is received.
+
+This fixes some cases where EAPOL-Key frames were sent encrypted using
+the old key when a peer STA restarted itself and lost the key and had to
+re-join the IBSS. Previously, that state required timing out the 4-way
+handshake and Deauthentication frame exchange to recover.
+
+Signed-off-by: Jouni Malinen <j@w1.fi>
+---
+
+--- a/wpa_supplicant/ibss_rsn.c
++++ b/wpa_supplicant/ibss_rsn.c
+@@ -838,6 +838,18 @@ static void ibss_rsn_handle_auth_1_of_2(
+                  MAC2STR(addr));
+       if (peer &&
++          peer->authentication_status & (IBSS_RSN_SET_PTK_SUPP |
++                                         IBSS_RSN_SET_PTK_AUTH)) {
++              /* Clear the TK for this pair to allow recovery from the case
++               * where the peer STA has restarted and lost its key while we
++               * still have a pairwise key configured. */
++              wpa_printf(MSG_DEBUG, "RSN: Clear pairwise key for peer "
++                         MACSTR, MAC2STR(addr));
++              wpa_drv_set_key(ibss_rsn->wpa_s, WPA_ALG_NONE, addr, 0, 0,
++                              NULL, 0, NULL, 0);
++      }
++
++      if (peer &&
+           peer->authentication_status & IBSS_RSN_AUTH_EAPOL_BY_PEER) {
+               if (peer->own_auth_tx.sec) {
+                       struct os_reltime now, diff;
index fad8466..0389406 100644 (file)
 +      if (chdir("/") < 0)
                return -1;
 -      }
--
 -      return 0;
 -}
 -#else /* __APPLE__ */
 -#define os_daemon daemon
 -#endif /* __APPLE__ */
+-
 -
 -int os_daemonize(const char *pid_file)
 -{
index e758afb..ee892e2 100644 (file)
        /*
         * sta->capability is used in check_assoc_ies() for RRM enabled
         * capability element.
-@@ -3023,7 +3049,7 @@ int ieee802_11_mgmt(struct hostapd_data
+@@ -3025,7 +3051,7 @@ int ieee802_11_mgmt(struct hostapd_data
  
  
        if (stype == WLAN_FC_STYPE_PROBE_REQ) {
                return 1;
        }
  
-@@ -3041,17 +3067,17 @@ int ieee802_11_mgmt(struct hostapd_data
+@@ -3043,17 +3069,17 @@ int ieee802_11_mgmt(struct hostapd_data
        switch (stype) {
        case WLAN_FC_STYPE_AUTH:
                wpa_printf(MSG_DEBUG, "mgmt::auth");