From 40e4c342fd49175b7f367655fac38850435667d4 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 15 Jan 2017 14:19:43 +0100 Subject: [PATCH] hostapd: backport a few upstream fixes Fixes reassoc issues with WDS mode Fixes reassoc issues in AP mode Fixes IBSS reauthentication issues Signed-off-by: Felix Fietkau --- ...on-between-AssocResp-callback-and-4a.patch | 83 +++++++++++++++++++ ...Reassociation-Request-frame-dropping.patch | 36 ++++++++ ...-clearing-on-Authentication-frame-RX.patch | 40 +++++++++ .../hostapd/patches/100-daemonize_fix.patch | 4 +- .../hostapd/patches/600-ubus_support.patch | 4 +- 5 files changed, 163 insertions(+), 4 deletions(-) create mode 100644 package/network/services/hostapd/patches/001-Fix-race-condition-between-AssocResp-callback-and-4a.patch create mode 100644 package/network/services/hostapd/patches/002-Fix-duplicate-Reassociation-Request-frame-dropping.patch create mode 100644 package/network/services/hostapd/patches/003-RSN-IBSS-Fix-TK-clearing-on-Authentication-frame-RX.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 index 000000000000..bf54e9df3294 --- /dev/null +++ b/package/network/services/hostapd/patches/001-Fix-race-condition-between-AssocResp-callback-and-4a.patch @@ -0,0 +1,83 @@ +From: Jouni Malinen +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 +--- + +--- 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 index 000000000000..6db1e9b34bf8 --- /dev/null +++ b/package/network/services/hostapd/patches/002-Fix-duplicate-Reassociation-Request-frame-dropping.patch @@ -0,0 +1,36 @@ +From: Jouni Malinen +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 +--- + +--- 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 index 000000000000..0a3c27f89e3c --- /dev/null +++ b/package/network/services/hostapd/patches/003-RSN-IBSS-Fix-TK-clearing-on-Authentication-frame-RX.patch @@ -0,0 +1,40 @@ +From: Jouni Malinen +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 +--- + +--- 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; diff --git a/package/network/services/hostapd/patches/100-daemonize_fix.patch b/package/network/services/hostapd/patches/100-daemonize_fix.patch index fad84669a6b6..0389406a98a1 100644 --- a/package/network/services/hostapd/patches/100-daemonize_fix.patch +++ b/package/network/services/hostapd/patches/100-daemonize_fix.patch @@ -60,13 +60,13 @@ + if (chdir("/") < 0) return -1; - } -- + - return 0; -} -#else /* __APPLE__ */ -#define os_daemon daemon -#endif /* __APPLE__ */ - +- - -int os_daemonize(const char *pid_file) -{ diff --git a/package/network/services/hostapd/patches/600-ubus_support.patch b/package/network/services/hostapd/patches/600-ubus_support.patch index e758afb17d51..ee892e2bae14 100644 --- a/package/network/services/hostapd/patches/600-ubus_support.patch +++ b/package/network/services/hostapd/patches/600-ubus_support.patch @@ -156,7 +156,7 @@ /* * 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) { @@ -165,7 +165,7 @@ 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"); -- 2.30.2