--- /dev/null
+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;
+
--- /dev/null
+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",
--- /dev/null
+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;
+ if (chdir("/") < 0)
return -1;
- }
--
+
- return 0;
-}
-#else /* __APPLE__ */
-#define os_daemon daemon
-#endif /* __APPLE__ */
-
+-
-
-int os_daemonize(const char *pid_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");