Cumulative patch from commit a9491695b30a7f750dc45cb563d813b03f1d4b8d

a9491695b QCA vendor command to set/get NUD statistics
f593b6c11 nl80211: Do not reset vendor_scan_cookie after scan timeout
f2bc34480 wpa_supplicant: Fix global control interface for STA/STA-FIRST/STA-NEXT
cc3dae85b hostapd: Add possibility to send debug messages to syslog
0da355235 FST: Remove WPA_ASSERT from wpas_fst_send_action_cb()
968dce9b1 FST: Silence compiler warning on WPA_ASSERT
17e20b1e2 FST: Remove a bogus WPA_ASSERT()
6a5425fd6 Increase delayed EAPOL RX frame timeout
cef8fac04 wpa_auth: Make struct wpa_auth_callbacks const
30eddf352 Fix or supress various sparse warnings
b301f54e5 IBSS/mesh: Skip VHT channel setup with vht_disabled=1
adc6a5d81 mesh: Check remote peer HT Operation element
9eb5757a8 Define helper function set_disable_ht40()
7813b7c34 nl80211: Fix a memory leak on deinit with HT enabled mesh
6b585f420 mesh: Fix crash on removing virtual mesh interface
5208160b4 FILS: Parse received FILS HLP requests
5732b770f FILS: Allow FILS HLP requests to be added
a1aa2aebc Remove unused WLAN_CIPHER_SUITE_* definitions
a042e39ac nl80211: Use RSN_CIPHER_SUITE_* instead of WLAN_CIPHER_SUITE_*
2373a3117 Define all RSN_CIPHER_SUITE_* values
89ba101e1 Remove unused WLAN_AKM_SUITE_* definitions
bf9f8a052 Use RSN_AUTH_KEY_MGMT_* instead of WLAN_AKM_SUITE_* for wpa_akm_to_suite()
3aa24db95 nl80211: Use RSN_AUTH_KEY_MGMT_* instead of WLAN_AKM_SUITE_*
a1343fa6b Remove unnecessary ifdef from RSN_AUTH_KEY_MGMT_* definitions
afe731004 Fix CONFIG_SAE build without CONFIG_SME
34e8bfd7a Skip EVENT_ACS_CHANNEL_SELECTED also without CONFIG_AP
510fc2dfc Fix AKM suite selectors for FILS and Suite B
d7d0f909f QCA vendor command to carry the reason for power save failure
53b38209f GAS: Cancel gas_query_timeout when AP responds with comeback delay
d5bd94133 MBO: Silence a compiler warning when building without CONFIG_MBO
4c4070005 QCA vendor command to enable host driver offload ACS to user space
4d77d80ed mesh: Add MESH_PMKSA_GET/ADD commands
117875db3 D-Bus: Add GroupMgmt entry into the interface Capabilities dict
3cdb4ac07 D-Bus: Add pmf to global capabilities
adf8f45f8 D-Bus: Implement Pmf property
b98706c14 RSN IBSS: Fix TK clearing on Authentication frame RX
fa67debf4 Fix duplicate Reassociation Request frame dropping
6ff92677a wext: Cancel send_rfkill timeout in deinit
fcd3d6ce3 FILS: Fix PMK and PMKID derivation from ERP
ef495c78d OpenSSL: Implement sha384_vector()
a70cd0db8 nl80211: Don't register for Beacon frames for IEEE 802.11ad AP
a2aa21a3b Assign additional vendor specific elements for early HE testing
f09095d57 wpa_supplicant: Clarify group_rekey documentation
c85dfc6f8 nl80211: Set NL80211_ATTR_IFACE_SOCKET_OWNER for connect and associate
d07f450da Sync with mac80211-next.git include/uapi/linux/nl80211.h
8f315d050 Fix country code in wpa_supplicant AP mode Country element
29065686a D-Bus: Fix BSS Mode getter for invalid DMG BSS
b2442f256 nl80211: Debug prints for TDLS_OPER command and result
2901bc272 bgscan: Remove unnecessary NULL check
9d6eaad6b bgscan: Remove unnecessary NULL check
0f9b4a0f1 bgscan: Deliver beacon loss event to bgscan modules
688556722 nl80211: More complete processing of connection quality monitor events
54736d835 Store FST parameters to configuration file
35c78f7b9 Store osu_dir to configuration file
1f539c78f Store autoscan to configuration file
58ed9e31d Store filter_rssi to configuration file
1fb1bf99d Write sec_device_type to configuration file
b4bdeadfa Make "SET" behavior more consistent for dot11RSNA parameters
e3394c0e2 Make "SET non_pref_chan .." behavior more consistent
f8c201862 Fix cert_in_cb parsing in wpa_supplicant.conf
9284418d0 Fix writing of wpa_supplicant sae_groups configuration parameter
167f78a5e Send BEACON-REQ-TX-STATUS event only for beacon reports
7ba94fc4b RRM: Use wpa_hexdump_buf() instead of wpa_hexdump()
e4ec6bbfd nl80211: Register for Link Measurement Report frames in AP mode
33468e532 RRM: Document Link Measurement Report frame construction steps
40e9a3f32 RRM: Fix beacon report scan channels for VHT 80, 80+80, 160 MHz cases
5cda35089 RRM: Move wpabuf_resize() call into wpas_rrm_report_elem()
f2058f4af RRM: Remove unnecessary cb check
89fa633af nl80211: Fix error while enabling AP mode with driver-SME

The last change 89fa633af cherrypicks a later change that resolves
an issue with starting up AP mode.

Bug: 34681709
Test: Wifi Suite
Change-Id: Iba8c5824009d6480fb736b274d69243c77aef7fe
diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
index 3680fda..a760e3a 100644
--- a/src/ap/ctrl_iface_ap.c
+++ b/src/ap/ctrl_iface_ap.c
@@ -639,3 +639,60 @@
 {
 	wpa_auth_pmksa_flush(hapd->wpa_auth);
 }
+
+
+#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
+#ifdef CONFIG_MESH
+
+int hostapd_ctrl_iface_pmksa_list_mesh(struct hostapd_data *hapd,
+				       const u8 *addr, char *buf, size_t len)
+{
+	return wpa_auth_pmksa_list_mesh(hapd->wpa_auth, addr, buf, len);
+}
+
+
+void * hostapd_ctrl_iface_pmksa_create_entry(const u8 *aa, char *cmd)
+{
+	u8 spa[ETH_ALEN];
+	u8 pmkid[PMKID_LEN];
+	u8 pmk[PMK_LEN_MAX];
+	char *pos;
+	int expiration;
+
+	/*
+	 * Entry format:
+	 * <BSSID> <PMKID> <PMK> <expiration in seconds>
+	 */
+
+	if (hwaddr_aton(cmd, spa))
+		return NULL;
+
+	pos = os_strchr(cmd, ' ');
+	if (!pos)
+		return NULL;
+	pos++;
+
+	if (hexstr2bin(pos, pmkid, PMKID_LEN) < 0)
+		return NULL;
+
+	pos = os_strchr(pos, ' ');
+	if (!pos)
+		return NULL;
+	pos++;
+
+	if (hexstr2bin(pos, pmk, PMK_LEN) < 0)
+		return NULL;
+
+	pos = os_strchr(pos, ' ');
+	if (!pos)
+		return NULL;
+	pos++;
+
+	if (sscanf(pos, "%d", &expiration) != 1)
+		return NULL;
+
+	return wpa_auth_pmksa_create_entry(aa, spa, pmk, pmkid, expiration);
+}
+
+#endif /* CONFIG_MESH */
+#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
diff --git a/src/ap/ctrl_iface_ap.h b/src/ap/ctrl_iface_ap.h
index 4f99680..3b61cac 100644
--- a/src/ap/ctrl_iface_ap.h
+++ b/src/ap/ctrl_iface_ap.h
@@ -32,5 +32,8 @@
 int hostapd_ctrl_iface_pmksa_list(struct hostapd_data *hapd, char *buf,
 				  size_t len);
 void hostapd_ctrl_iface_pmksa_flush(struct hostapd_data *hapd);
+int hostapd_ctrl_iface_pmksa_list_mesh(struct hostapd_data *hapd,
+				       const u8 *addr, char *buf, size_t len);
+void * hostapd_ctrl_iface_pmksa_create_entry(const u8 *aa, char *cmd);
 
 #endif /* CTRL_IFACE_AP_H */
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 09850ef..cceeee0 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -1166,6 +1166,7 @@
 	u8 *ie_buf = NULL;
 	const u8 *pmk = NULL;
 	size_t pmk_len = 0;
+	u8 pmk_buf[PMK_LEN_MAX];
 
 	if (resp != WLAN_STATUS_SUCCESS)
 		goto fail;
@@ -1234,8 +1235,16 @@
 		wpabuf_put_u8(data, WLAN_EID_EXT_FILS_WRAPPED_DATA);
 		wpabuf_put_buf(data, erp_resp);
 
-		pmk = msk;
-		pmk_len = msk_len > PMK_LEN ? PMK_LEN : msk_len;
+		if (fils_rmsk_to_pmk(wpa_auth_sta_key_mgmt(sta->wpa_sm),
+				     msk, msk_len, sta->fils_snonce, fils_nonce,
+				     NULL, 0, pmk_buf, &pmk_len)) {
+			wpa_printf(MSG_DEBUG, "FILS: Failed to derive PMK");
+			resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+			wpabuf_free(data);
+			data = NULL;
+			goto fail;
+		}
+		pmk = pmk_buf;
 	} else if (pmksa) {
 		pmk = pmksa->pmk;
 		pmk_len = pmksa->pmk_len;
@@ -2398,6 +2407,85 @@
 }
 
 
+#ifdef CONFIG_FILS
+
+static void fils_process_hlp_req(struct hostapd_data *hapd,
+				 struct sta_info *sta,
+				 const u8 *pos, size_t len)
+{
+	const u8 *pkt, *end;
+
+	wpa_printf(MSG_DEBUG, "FILS: HLP request from " MACSTR " (dst=" MACSTR
+		   " src=" MACSTR " len=%u)",
+		   MAC2STR(sta->addr), MAC2STR(pos), MAC2STR(pos + ETH_ALEN),
+		   (unsigned int) len);
+	if (os_memcmp(sta->addr, pos + ETH_ALEN, ETH_ALEN) != 0) {
+		wpa_printf(MSG_DEBUG,
+			   "FILS: Ignore HLP request with unexpected source address"
+			   MACSTR, MAC2STR(pos + ETH_ALEN));
+		return;
+	}
+
+	end = pos + len;
+	pkt = pos + 2 * ETH_ALEN;
+	if (end - pkt >= 6 &&
+	    os_memcmp(pkt, "\xaa\xaa\x03\x00\x00\x00", 6) == 0)
+		pkt += 6; /* Remove SNAP/LLC header */
+	wpa_hexdump(MSG_MSGDUMP, "FILS: HLP request packet", pkt, end - pkt);
+}
+
+
+static void fils_process_hlp(struct hostapd_data *hapd, struct sta_info *sta,
+			     const u8 *pos, int left)
+{
+	const u8 *end = pos + left;
+	u8 *tmp, *tmp_pos;
+
+	/* Check if there are any FILS HLP Container elements */
+	while (end - pos >= 2) {
+		if (2 + pos[1] > end - pos)
+			return;
+		if (pos[0] == WLAN_EID_EXTENSION &&
+		    pos[1] >= 1 + 2 * ETH_ALEN &&
+		    pos[2] == WLAN_EID_EXT_FILS_HLP_CONTAINER)
+			break;
+		pos += 2 + pos[1];
+	}
+	if (end - pos < 2)
+		return; /* No FILS HLP Container elements */
+
+	tmp = os_malloc(end - pos);
+	if (!tmp)
+		return;
+
+	while (end - pos >= 2) {
+		if (2 + pos[1] > end - pos ||
+		    pos[0] != WLAN_EID_EXTENSION ||
+		    pos[1] < 1 + 2 * ETH_ALEN ||
+		    pos[2] != WLAN_EID_EXT_FILS_HLP_CONTAINER)
+			break;
+		tmp_pos = tmp;
+		os_memcpy(tmp_pos, pos + 3, pos[1] - 1);
+		tmp_pos += pos[1] - 1;
+		pos += 2 + pos[1];
+
+		/* Add possible fragments */
+		while (end - pos >= 2 && pos[0] == WLAN_EID_FRAGMENT &&
+		       2 + pos[1] <= end - pos) {
+			os_memcpy(tmp_pos, pos + 2, pos[1]);
+			tmp_pos += pos[1];
+			pos += 2 + pos[1];
+		}
+
+		fils_process_hlp_req(hapd, sta, tmp, tmp_pos - tmp);
+	}
+
+	os_free(tmp);
+}
+
+#endif /* CONFIG_FILS */
+
+
 static void handle_assoc(struct hostapd_data *hapd,
 			 const struct ieee80211_mgmt *mgmt, size_t len,
 			 int reassoc)
@@ -2518,8 +2606,8 @@
 	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",
@@ -2669,6 +2757,13 @@
 
 	sta->pending_wds_enable = 0;
 
+#ifdef CONFIG_FILS
+	if (sta->auth_alg == WLAN_AUTH_FILS_SK ||
+	    sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
+	    sta->auth_alg == WLAN_AUTH_FILS_PK)
+		fils_process_hlp(hapd, sta, pos, left);
+#endif /* CONFIG_FILS */
+
  fail:
 	/*
 	 * In case of a successful response, add the station to the driver.
@@ -3409,6 +3504,7 @@
 			     size_t len, int ok)
 {
 	struct sta_info *sta;
+	const struct rrm_measurement_report_element *report;
 
 	if (is_multicast_ether_addr(mgmt->da))
 		return;
@@ -3419,10 +3515,15 @@
 		return;
 	}
 
-	if (len < 24 + 2)
+	if (len < 24 + 5 + sizeof(*report))
 		return;
+	report = (const struct rrm_measurement_report_element *)
+		&mgmt->u.action.u.rrm.variable[2];
 	if (mgmt->u.action.category == WLAN_ACTION_RADIO_MEASUREMENT &&
-	    mgmt->u.action.u.rrm.action == WLAN_RRM_RADIO_MEASUREMENT_REQUEST)
+	    mgmt->u.action.u.rrm.action == WLAN_RRM_RADIO_MEASUREMENT_REQUEST &&
+	    report->eid == WLAN_EID_MEASURE_REQUEST &&
+	    report->len >= 3 &&
+	    report->type == MEASURE_TYPE_BEACON)
 		hostapd_rrm_beacon_req_tx_status(hapd, mgmt, len, ok);
 }
 
diff --git a/src/ap/pmksa_cache_auth.c b/src/ap/pmksa_cache_auth.c
index d610e7e..bce5abf 100644
--- a/src/ap/pmksa_cache_auth.c
+++ b/src/ap/pmksa_cache_auth.c
@@ -282,7 +282,42 @@
 		     const u8 *aa, const u8 *spa, int session_timeout,
 		     struct eapol_state_machine *eapol, int akmp)
 {
-	struct rsn_pmksa_cache_entry *entry, *pos;
+	struct rsn_pmksa_cache_entry *entry;
+
+	entry = pmksa_cache_auth_create_entry(pmk, pmk_len, pmkid, kck, kck_len,
+					      aa, spa, session_timeout, eapol,
+					      akmp);
+
+	if (pmksa_cache_auth_add_entry(pmksa, entry) < 0)
+		return NULL;
+
+	return entry;
+}
+
+
+/**
+ * pmksa_cache_auth_create_entry - Create a PMKSA cache entry
+ * @pmk: The new pairwise master key
+ * @pmk_len: PMK length in bytes, usually PMK_LEN (32)
+ * @pmkid: Calculated PMKID
+ * @kck: Key confirmation key or %NULL if not yet derived
+ * @kck_len: KCK length in bytes
+ * @aa: Authenticator address
+ * @spa: Supplicant address
+ * @session_timeout: Session timeout
+ * @eapol: Pointer to EAPOL state machine data
+ * @akmp: WPA_KEY_MGMT_* used in key derivation
+ * Returns: Pointer to the added PMKSA cache entry or %NULL on error
+ *
+ * This function creates a PMKSA entry.
+ */
+struct rsn_pmksa_cache_entry *
+pmksa_cache_auth_create_entry(const u8 *pmk, size_t pmk_len, const u8 *pmkid,
+			      const u8 *kck, size_t kck_len, const u8 *aa,
+			      const u8 *spa, int session_timeout,
+			      struct eapol_state_machine *eapol, int akmp)
+{
+	struct rsn_pmksa_cache_entry *entry;
 	struct os_reltime now;
 
 	if (pmk_len > PMK_LEN_MAX)
@@ -315,9 +350,30 @@
 	os_memcpy(entry->spa, spa, ETH_ALEN);
 	pmksa_cache_from_eapol_data(entry, eapol);
 
+	return entry;
+}
+
+
+/**
+ * pmksa_cache_auth_add_entry - Add a PMKSA cache entry
+ * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init()
+ * @entry: Pointer to PMKSA cache entry
+ *
+ * This function adds PMKSA cache entry to the PMKSA cache. If an old entry is
+ * already in the cache for the same Supplicant, this entry will be replaced
+ * with the new entry. PMKID will be calculated based on the PMK.
+ */
+int pmksa_cache_auth_add_entry(struct rsn_pmksa_cache *pmksa,
+			       struct rsn_pmksa_cache_entry *entry)
+{
+	struct rsn_pmksa_cache_entry *pos;
+
+	if (entry == NULL)
+		return -1;
+
 	/* Replace an old entry for the same STA (if found) with the new entry
 	 */
-	pos = pmksa_cache_auth_get(pmksa, spa, NULL);
+	pos = pmksa_cache_auth_get(pmksa, entry->spa, NULL);
 	if (pos)
 		pmksa_cache_free_entry(pmksa, pos);
 
@@ -331,7 +387,7 @@
 
 	pmksa_cache_link_entry(pmksa, entry);
 
-	return entry;
+	return 0;
 }
 
 
@@ -605,3 +661,70 @@
 	}
 	return pos - buf;
 }
+
+
+#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
+#ifdef CONFIG_MESH
+
+/**
+ * pmksa_cache_auth_list_mesh - Dump text list of entries in PMKSA cache
+ * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init()
+ * @addr: MAC address of the peer (NULL means any)
+ * @buf: Buffer for the list
+ * @len: Length of the buffer
+ * Returns: Number of bytes written to buffer
+ *
+ * This function is used to generate a text format representation of the
+ * current PMKSA cache contents for the ctrl_iface PMKSA_GET command to store
+ * in external storage.
+ */
+int pmksa_cache_auth_list_mesh(struct rsn_pmksa_cache *pmksa, const u8 *addr,
+			       char *buf, size_t len)
+{
+	int ret;
+	char *pos, *end;
+	struct rsn_pmksa_cache_entry *entry;
+	struct os_reltime now;
+
+	pos = buf;
+	end = buf + len;
+	os_get_reltime(&now);
+
+
+	/*
+	 * Entry format:
+	 * <BSSID> <PMKID> <PMK> <expiration in seconds>
+	 */
+	for (entry = pmksa->pmksa; entry; entry = entry->next) {
+		if (addr && os_memcmp(entry->spa, addr, ETH_ALEN) != 0)
+			continue;
+
+		ret = os_snprintf(pos, end - pos, MACSTR " ",
+				  MAC2STR(entry->spa));
+		if (os_snprintf_error(end - pos, ret))
+			return 0;
+		pos += ret;
+
+		pos += wpa_snprintf_hex(pos, end - pos, entry->pmkid,
+					PMKID_LEN);
+
+		ret = os_snprintf(pos, end - pos, " ");
+		if (os_snprintf_error(end - pos, ret))
+			return 0;
+		pos += ret;
+
+		pos += wpa_snprintf_hex(pos, end - pos, entry->pmk,
+					entry->pmk_len);
+
+		ret = os_snprintf(pos, end - pos, " %d\n",
+				  (int) (entry->expiration - now.sec));
+		if (os_snprintf_error(end - pos, ret))
+			return 0;
+		pos += ret;
+	}
+
+	return pos - buf;
+}
+
+#endif /* CONFIG_MESH */
+#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
diff --git a/src/ap/pmksa_cache_auth.h b/src/ap/pmksa_cache_auth.h
index d8d9c5a..bd1b672 100644
--- a/src/ap/pmksa_cache_auth.h
+++ b/src/ap/pmksa_cache_auth.h
@@ -53,6 +53,13 @@
 		     const u8 *aa, const u8 *spa, int session_timeout,
 		     struct eapol_state_machine *eapol, int akmp);
 struct rsn_pmksa_cache_entry *
+pmksa_cache_auth_create_entry(const u8 *pmk, size_t pmk_len, const u8 *pmkid,
+			      const u8 *kck, size_t kck_len, const u8 *aa,
+			      const u8 *spa, int session_timeout,
+			      struct eapol_state_machine *eapol, int akmp);
+int pmksa_cache_auth_add_entry(struct rsn_pmksa_cache *pmksa,
+			       struct rsn_pmksa_cache_entry *entry);
+struct rsn_pmksa_cache_entry *
 pmksa_cache_add_okc(struct rsn_pmksa_cache *pmksa,
 		    const struct rsn_pmksa_cache_entry *old_entry,
 		    const u8 *aa, const u8 *pmkid);
@@ -65,5 +72,7 @@
 					   struct radius_das_attrs *attr);
 int pmksa_cache_auth_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len);
 void pmksa_cache_auth_flush(struct rsn_pmksa_cache *pmksa);
+int pmksa_cache_auth_list_mesh(struct rsn_pmksa_cache *pmksa, const u8 *addr,
+			       char *buf, size_t len);
 
 #endif /* PMKSA_CACHE_H */
diff --git a/src/ap/taxonomy.c b/src/ap/taxonomy.c
index cea8b72..ae157a7 100644
--- a/src/ap/taxonomy.c
+++ b/src/ap/taxonomy.c
@@ -21,6 +21,7 @@
 #include "common/wpa_ctrl.h"
 #include "hostapd.h"
 #include "sta_info.h"
+#include "taxonomy.h"
 
 
 /* Copy a string with no funny schtuff allowed; only alphanumerics. */
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index 43e3558..69e3a5d 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -75,8 +75,8 @@
 static inline int wpa_auth_mic_failure_report(
 	struct wpa_authenticator *wpa_auth, const u8 *addr)
 {
-	if (wpa_auth->cb.mic_failure_report)
-		return wpa_auth->cb.mic_failure_report(wpa_auth->cb.ctx, addr);
+	if (wpa_auth->cb->mic_failure_report)
+		return wpa_auth->cb->mic_failure_report(wpa_auth->cb_ctx, addr);
 	return 0;
 }
 
@@ -84,8 +84,8 @@
 static inline void wpa_auth_psk_failure_report(
 	struct wpa_authenticator *wpa_auth, const u8 *addr)
 {
-	if (wpa_auth->cb.psk_failure_report)
-		wpa_auth->cb.psk_failure_report(wpa_auth->cb.ctx, addr);
+	if (wpa_auth->cb->psk_failure_report)
+		wpa_auth->cb->psk_failure_report(wpa_auth->cb_ctx, addr);
 }
 
 
@@ -93,17 +93,17 @@
 				      const u8 *addr, wpa_eapol_variable var,
 				      int value)
 {
-	if (wpa_auth->cb.set_eapol)
-		wpa_auth->cb.set_eapol(wpa_auth->cb.ctx, addr, var, value);
+	if (wpa_auth->cb->set_eapol)
+		wpa_auth->cb->set_eapol(wpa_auth->cb_ctx, addr, var, value);
 }
 
 
 static inline int wpa_auth_get_eapol(struct wpa_authenticator *wpa_auth,
 				     const u8 *addr, wpa_eapol_variable var)
 {
-	if (wpa_auth->cb.get_eapol == NULL)
+	if (wpa_auth->cb->get_eapol == NULL)
 		return -1;
-	return wpa_auth->cb.get_eapol(wpa_auth->cb.ctx, addr, var);
+	return wpa_auth->cb->get_eapol(wpa_auth->cb_ctx, addr, var);
 }
 
 
@@ -112,19 +112,19 @@
 					  const u8 *p2p_dev_addr,
 					  const u8 *prev_psk)
 {
-	if (wpa_auth->cb.get_psk == NULL)
+	if (wpa_auth->cb->get_psk == NULL)
 		return NULL;
-	return wpa_auth->cb.get_psk(wpa_auth->cb.ctx, addr, p2p_dev_addr,
-				    prev_psk);
+	return wpa_auth->cb->get_psk(wpa_auth->cb_ctx, addr, p2p_dev_addr,
+				     prev_psk);
 }
 
 
 static inline int wpa_auth_get_msk(struct wpa_authenticator *wpa_auth,
 				   const u8 *addr, u8 *msk, size_t *len)
 {
-	if (wpa_auth->cb.get_msk == NULL)
+	if (wpa_auth->cb->get_msk == NULL)
 		return -1;
-	return wpa_auth->cb.get_msk(wpa_auth->cb.ctx, addr, msk, len);
+	return wpa_auth->cb->get_msk(wpa_auth->cb_ctx, addr, msk, len);
 }
 
 
@@ -133,19 +133,19 @@
 				   enum wpa_alg alg, const u8 *addr, int idx,
 				   u8 *key, size_t key_len)
 {
-	if (wpa_auth->cb.set_key == NULL)
+	if (wpa_auth->cb->set_key == NULL)
 		return -1;
-	return wpa_auth->cb.set_key(wpa_auth->cb.ctx, vlan_id, alg, addr, idx,
-				    key, key_len);
+	return wpa_auth->cb->set_key(wpa_auth->cb_ctx, vlan_id, alg, addr, idx,
+				     key, key_len);
 }
 
 
 static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth,
 				      const u8 *addr, int idx, u8 *seq)
 {
-	if (wpa_auth->cb.get_seqnum == NULL)
+	if (wpa_auth->cb->get_seqnum == NULL)
 		return -1;
-	return wpa_auth->cb.get_seqnum(wpa_auth->cb.ctx, addr, idx, seq);
+	return wpa_auth->cb->get_seqnum(wpa_auth->cb_ctx, addr, idx, seq);
 }
 
 
@@ -153,10 +153,10 @@
 wpa_auth_send_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr,
 		    const u8 *data, size_t data_len, int encrypt)
 {
-	if (wpa_auth->cb.send_eapol == NULL)
+	if (wpa_auth->cb->send_eapol == NULL)
 		return -1;
-	return wpa_auth->cb.send_eapol(wpa_auth->cb.ctx, addr, data, data_len,
-				       encrypt);
+	return wpa_auth->cb->send_eapol(wpa_auth->cb_ctx, addr, data, data_len,
+					encrypt);
 }
 
 
@@ -164,9 +164,9 @@
 static inline int wpa_auth_start_ampe(struct wpa_authenticator *wpa_auth,
 				      const u8 *addr)
 {
-	if (wpa_auth->cb.start_ampe == NULL)
+	if (wpa_auth->cb->start_ampe == NULL)
 		return -1;
-	return wpa_auth->cb.start_ampe(wpa_auth->cb.ctx, addr);
+	return wpa_auth->cb->start_ampe(wpa_auth->cb_ctx, addr);
 }
 #endif /* CONFIG_MESH */
 
@@ -175,9 +175,9 @@
 			  int (*cb)(struct wpa_state_machine *sm, void *ctx),
 			  void *cb_ctx)
 {
-	if (wpa_auth->cb.for_each_sta == NULL)
+	if (wpa_auth->cb->for_each_sta == NULL)
 		return 0;
-	return wpa_auth->cb.for_each_sta(wpa_auth->cb.ctx, cb, cb_ctx);
+	return wpa_auth->cb->for_each_sta(wpa_auth->cb_ctx, cb, cb_ctx);
 }
 
 
@@ -185,18 +185,18 @@
 			   int (*cb)(struct wpa_authenticator *a, void *ctx),
 			   void *cb_ctx)
 {
-	if (wpa_auth->cb.for_each_auth == NULL)
+	if (wpa_auth->cb->for_each_auth == NULL)
 		return 0;
-	return wpa_auth->cb.for_each_auth(wpa_auth->cb.ctx, cb, cb_ctx);
+	return wpa_auth->cb->for_each_auth(wpa_auth->cb_ctx, cb, cb_ctx);
 }
 
 
 void wpa_auth_logger(struct wpa_authenticator *wpa_auth, const u8 *addr,
 		     logger_level level, const char *txt)
 {
-	if (wpa_auth->cb.logger == NULL)
+	if (wpa_auth->cb->logger == NULL)
 		return;
-	wpa_auth->cb.logger(wpa_auth->cb.ctx, addr, level, txt);
+	wpa_auth->cb->logger(wpa_auth->cb_ctx, addr, level, txt);
 }
 
 
@@ -207,7 +207,7 @@
 	int maxlen;
 	va_list ap;
 
-	if (wpa_auth->cb.logger == NULL)
+	if (wpa_auth->cb->logger == NULL)
 		return;
 
 	maxlen = os_strlen(fmt) + 100;
@@ -228,11 +228,11 @@
 static void wpa_sta_disconnect(struct wpa_authenticator *wpa_auth,
 			       const u8 *addr)
 {
-	if (wpa_auth->cb.disconnect == NULL)
+	if (wpa_auth->cb->disconnect == NULL)
 		return;
 	wpa_printf(MSG_DEBUG, "wpa_sta_disconnect STA " MACSTR, MAC2STR(addr));
-	wpa_auth->cb.disconnect(wpa_auth->cb.ctx, addr,
-				WLAN_REASON_PREV_AUTH_NOT_VALID);
+	wpa_auth->cb->disconnect(wpa_auth->cb_ctx, addr,
+				 WLAN_REASON_PREV_AUTH_NOT_VALID);
 }
 
 
@@ -416,7 +416,8 @@
  */
 struct wpa_authenticator * wpa_init(const u8 *addr,
 				    struct wpa_auth_config *conf,
-				    struct wpa_auth_callbacks *cb)
+				    const struct wpa_auth_callbacks *cb,
+				    void *cb_ctx)
 {
 	struct wpa_authenticator *wpa_auth;
 
@@ -425,7 +426,8 @@
 		return NULL;
 	os_memcpy(wpa_auth->addr, addr, ETH_ALEN);
 	os_memcpy(&wpa_auth->conf, conf, sizeof(*conf));
-	os_memcpy(&wpa_auth->cb, cb, sizeof(*cb));
+	wpa_auth->cb = cb;
+	wpa_auth->cb_ctx = cb_ctx;
 
 	if (wpa_auth_gen_wpa_ie(wpa_auth)) {
 		wpa_printf(MSG_ERROR, "Could not generate WPA IE.");
@@ -1949,7 +1951,7 @@
 #endif /* CONFIG_IEEE80211R_AP */
 	} else {
 		wpa_printf(MSG_DEBUG, "WPA: Could not get PMK, get_msk: %p",
-			   sm->wpa_auth->cb.get_msk);
+			   sm->wpa_auth->cb->get_msk);
 		sm->Disconnect = TRUE;
 		return;
 	}
@@ -3850,6 +3852,58 @@
 }
 
 
+#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
+#ifdef CONFIG_MESH
+
+int wpa_auth_pmksa_list_mesh(struct wpa_authenticator *wpa_auth, const u8 *addr,
+			     char *buf, size_t len)
+{
+	if (!wpa_auth || !wpa_auth->pmksa)
+		return 0;
+
+	return pmksa_cache_auth_list_mesh(wpa_auth->pmksa, addr, buf, len);
+}
+
+
+struct rsn_pmksa_cache_entry *
+wpa_auth_pmksa_create_entry(const u8 *aa, const u8 *spa, const u8 *pmk,
+			    const u8 *pmkid, int expiration)
+{
+	struct rsn_pmksa_cache_entry *entry;
+	struct os_reltime now;
+
+	entry = pmksa_cache_auth_create_entry(pmk, PMK_LEN, pmkid, NULL, 0, aa,
+					      spa, 0, NULL, WPA_KEY_MGMT_SAE);
+	if (!entry)
+		return NULL;
+
+	os_get_reltime(&now);
+	entry->expiration = now.sec + expiration;
+	return entry;
+}
+
+
+int wpa_auth_pmksa_add_entry(struct wpa_authenticator *wpa_auth,
+			     struct rsn_pmksa_cache_entry *entry)
+{
+	int ret;
+
+	if (!wpa_auth || !wpa_auth->pmksa)
+		return -1;
+
+	ret = pmksa_cache_auth_add_entry(wpa_auth->pmksa, entry);
+	if (ret < 0)
+		wpa_printf(MSG_DEBUG,
+			   "RSN: Failed to store external PMKSA cache for "
+			   MACSTR, MAC2STR(entry->spa));
+
+	return ret;
+}
+
+#endif /* CONFIG_MESH */
+#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
+
+
 struct rsn_pmksa_cache_entry *
 wpa_auth_pmksa_get(struct wpa_authenticator *wpa_auth, const u8 *sta_addr,
 		   const u8 *pmkid)
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index 743f2e6..a44b030 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -198,7 +198,6 @@
 } wpa_eapol_variable;
 
 struct wpa_auth_callbacks {
-	void *ctx;
 	void (*logger)(void *ctx, const u8 *addr, logger_level level,
 		       const char *txt);
 	void (*disconnect)(void *ctx, const u8 *addr, u16 reason);
@@ -235,7 +234,8 @@
 
 struct wpa_authenticator * wpa_init(const u8 *addr,
 				    struct wpa_auth_config *conf,
-				    struct wpa_auth_callbacks *cb);
+				    const struct wpa_auth_callbacks *cb,
+				    void *cb_ctx);
 int wpa_init_keys(struct wpa_authenticator *wpa_auth);
 void wpa_deinit(struct wpa_authenticator *wpa_auth);
 int wpa_reconfig(struct wpa_authenticator *wpa_auth,
@@ -302,6 +302,13 @@
 int wpa_auth_pmksa_list(struct wpa_authenticator *wpa_auth, char *buf,
 			size_t len);
 void wpa_auth_pmksa_flush(struct wpa_authenticator *wpa_auth);
+int wpa_auth_pmksa_list_mesh(struct wpa_authenticator *wpa_auth, const u8 *addr,
+			     char *buf, size_t len);
+struct rsn_pmksa_cache_entry *
+wpa_auth_pmksa_create_entry(const u8 *aa, const u8 *spa, const u8 *pmk,
+			    const u8 *pmkid, int expiration);
+int wpa_auth_pmksa_add_entry(struct wpa_authenticator *wpa_auth,
+			     struct rsn_pmksa_cache_entry *entry);
 struct rsn_pmksa_cache_entry *
 wpa_auth_pmksa_get(struct wpa_authenticator *wpa_auth, const u8 *sta_addr,
 		   const u8 *pmkid);
diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c
index 7ab371f..1fe3c2b 100644
--- a/src/ap/wpa_auth_ft.c
+++ b/src/ap/wpa_auth_ft.c
@@ -33,21 +33,21 @@
 static int wpa_ft_rrb_send(struct wpa_authenticator *wpa_auth, const u8 *dst,
 			   const u8 *data, size_t data_len)
 {
-	if (wpa_auth->cb.send_ether == NULL)
+	if (wpa_auth->cb->send_ether == NULL)
 		return -1;
 	wpa_printf(MSG_DEBUG, "FT: RRB send to " MACSTR, MAC2STR(dst));
-	return wpa_auth->cb.send_ether(wpa_auth->cb.ctx, dst, ETH_P_RRB,
-				       data, data_len);
+	return wpa_auth->cb->send_ether(wpa_auth->cb_ctx, dst, ETH_P_RRB,
+					data, data_len);
 }
 
 
 static int wpa_ft_action_send(struct wpa_authenticator *wpa_auth,
 			      const u8 *dst, const u8 *data, size_t data_len)
 {
-	if (wpa_auth->cb.send_ft_action == NULL)
+	if (wpa_auth->cb->send_ft_action == NULL)
 		return -1;
-	return wpa_auth->cb.send_ft_action(wpa_auth->cb.ctx, dst,
-					   data, data_len);
+	return wpa_auth->cb->send_ft_action(wpa_auth->cb_ctx, dst,
+					    data, data_len);
 }
 
 
@@ -55,19 +55,19 @@
 				 const u8 *addr, const u8 *p2p_dev_addr,
 				 const u8 *prev_psk)
 {
-	if (wpa_auth->cb.get_psk == NULL)
+	if (wpa_auth->cb->get_psk == NULL)
 		return NULL;
-	return wpa_auth->cb.get_psk(wpa_auth->cb.ctx, addr, p2p_dev_addr,
-				    prev_psk);
+	return wpa_auth->cb->get_psk(wpa_auth->cb_ctx, addr, p2p_dev_addr,
+				     prev_psk);
 }
 
 
 static struct wpa_state_machine *
 wpa_ft_add_sta(struct wpa_authenticator *wpa_auth, const u8 *sta_addr)
 {
-	if (wpa_auth->cb.add_sta == NULL)
+	if (wpa_auth->cb->add_sta == NULL)
 		return NULL;
-	return wpa_auth->cb.add_sta(wpa_auth->cb.ctx, sta_addr);
+	return wpa_auth->cb->add_sta(wpa_auth->cb_ctx, sta_addr);
 }
 
 
@@ -75,12 +75,12 @@
 			    const u8 *sta_addr,
 			    u8 *tspec_ie, size_t tspec_ielen)
 {
-	if (wpa_auth->cb.add_tspec == NULL) {
+	if (wpa_auth->cb->add_tspec == NULL) {
 		wpa_printf(MSG_DEBUG, "FT: add_tspec is not initialized");
 		return -1;
 	}
-	return wpa_auth->cb.add_tspec(wpa_auth->cb.ctx, sta_addr, tspec_ie,
-				      tspec_ielen);
+	return wpa_auth->cb->add_tspec(wpa_auth->cb_ctx, sta_addr, tspec_ie,
+				       tspec_ielen);
 }
 
 
@@ -418,9 +418,9 @@
 static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth,
 				      const u8 *addr, int idx, u8 *seq)
 {
-	if (wpa_auth->cb.get_seqnum == NULL)
+	if (wpa_auth->cb->get_seqnum == NULL)
 		return -1;
-	return wpa_auth->cb.get_seqnum(wpa_auth->cb.ctx, addr, idx, seq);
+	return wpa_auth->cb->get_seqnum(wpa_auth->cb_ctx, addr, idx, seq);
 }
 
 
@@ -773,10 +773,10 @@
 				   enum wpa_alg alg, const u8 *addr, int idx,
 				   u8 *key, size_t key_len)
 {
-	if (wpa_auth->cb.set_key == NULL)
+	if (wpa_auth->cb->set_key == NULL)
 		return -1;
-	return wpa_auth->cb.set_key(wpa_auth->cb.ctx, vlan_id, alg, addr, idx,
-				    key, key_len);
+	return wpa_auth->cb->set_key(wpa_auth->cb_ctx, vlan_id, alg, addr, idx,
+				     key, key_len);
 }
 
 
diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
index aabac36..22518a1 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -595,7 +595,27 @@
 int hostapd_setup_wpa(struct hostapd_data *hapd)
 {
 	struct wpa_auth_config _conf;
-	struct wpa_auth_callbacks cb;
+	static const struct wpa_auth_callbacks cb = {
+		.logger = hostapd_wpa_auth_logger,
+		.disconnect = hostapd_wpa_auth_disconnect,
+		.mic_failure_report = hostapd_wpa_auth_mic_failure_report,
+		.psk_failure_report = hostapd_wpa_auth_psk_failure_report,
+		.set_eapol = hostapd_wpa_auth_set_eapol,
+		.get_eapol = hostapd_wpa_auth_get_eapol,
+		.get_psk = hostapd_wpa_auth_get_psk,
+		.get_msk = hostapd_wpa_auth_get_msk,
+		.set_key = hostapd_wpa_auth_set_key,
+		.get_seqnum = hostapd_wpa_auth_get_seqnum,
+		.send_eapol = hostapd_wpa_auth_send_eapol,
+		.for_each_sta = hostapd_wpa_auth_for_each_sta,
+		.for_each_auth = hostapd_wpa_auth_for_each_auth,
+		.send_ether = hostapd_wpa_auth_send_ether,
+#ifdef CONFIG_IEEE80211R_AP
+		.send_ft_action = hostapd_wpa_auth_send_ft_action,
+		.add_sta = hostapd_wpa_auth_add_sta,
+		.add_tspec = hostapd_wpa_auth_add_tspec,
+#endif /* CONFIG_IEEE80211R_AP */
+	};
 	const u8 *wpa_ie;
 	size_t wpa_ie_len;
 
@@ -604,28 +624,7 @@
 		_conf.tx_status = 1;
 	if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_MLME)
 		_conf.ap_mlme = 1;
-	os_memset(&cb, 0, sizeof(cb));
-	cb.ctx = hapd;
-	cb.logger = hostapd_wpa_auth_logger;
-	cb.disconnect = hostapd_wpa_auth_disconnect;
-	cb.mic_failure_report = hostapd_wpa_auth_mic_failure_report;
-	cb.psk_failure_report = hostapd_wpa_auth_psk_failure_report;
-	cb.set_eapol = hostapd_wpa_auth_set_eapol;
-	cb.get_eapol = hostapd_wpa_auth_get_eapol;
-	cb.get_psk = hostapd_wpa_auth_get_psk;
-	cb.get_msk = hostapd_wpa_auth_get_msk;
-	cb.set_key = hostapd_wpa_auth_set_key;
-	cb.get_seqnum = hostapd_wpa_auth_get_seqnum;
-	cb.send_eapol = hostapd_wpa_auth_send_eapol;
-	cb.for_each_sta = hostapd_wpa_auth_for_each_sta;
-	cb.for_each_auth = hostapd_wpa_auth_for_each_auth;
-	cb.send_ether = hostapd_wpa_auth_send_ether;
-#ifdef CONFIG_IEEE80211R_AP
-	cb.send_ft_action = hostapd_wpa_auth_send_ft_action;
-	cb.add_sta = hostapd_wpa_auth_add_sta;
-	cb.add_tspec = hostapd_wpa_auth_add_tspec;
-#endif /* CONFIG_IEEE80211R_AP */
-	hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb);
+	hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb, hapd);
 	if (hapd->wpa_auth == NULL) {
 		wpa_printf(MSG_ERROR, "WPA initialization failed.");
 		return -1;
diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h
index 0c5a457..065a624 100644
--- a/src/ap/wpa_auth_i.h
+++ b/src/ap/wpa_auth_i.h
@@ -203,7 +203,8 @@
 	struct wpa_stsl_negotiation *stsl_negotiations;
 
 	struct wpa_auth_config conf;
-	struct wpa_auth_callbacks cb;
+	const struct wpa_auth_callbacks *cb;
+	void *cb_ctx;
 
 	u8 *wpa_ie;
 	size_t wpa_ie_len;
diff --git a/src/common/hw_features_common.c b/src/common/hw_features_common.c
index 9c37ea6..ef4b59d 100644
--- a/src/common/hw_features_common.c
+++ b/src/common/hw_features_common.c
@@ -453,3 +453,17 @@
 
 	return 0;
 }
+
+
+void set_disable_ht40(struct ieee80211_ht_capabilities *htcaps,
+		      int disabled)
+{
+	/* Masking these out disables HT40 */
+	le16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
+				HT_CAP_INFO_SHORT_GI40MHZ);
+
+	if (disabled)
+		htcaps->ht_capabilities_info &= ~msk;
+	else
+		htcaps->ht_capabilities_info |= msk;
+}
diff --git a/src/common/hw_features_common.h b/src/common/hw_features_common.h
index 7360b4e..234b7bf 100644
--- a/src/common/hw_features_common.h
+++ b/src/common/hw_features_common.h
@@ -35,5 +35,7 @@
 			    int vht_enabled, int sec_channel_offset,
 			    int vht_oper_chwidth, int center_segment0,
 			    int center_segment1, u32 vht_caps);
+void set_disable_ht40(struct ieee80211_ht_capabilities *htcaps,
+		      int disabled);
 
 #endif /* HW_FEATURES_COMMON_H */
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index 5f6fdc4..55eaa82 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -1602,45 +1602,6 @@
 
 #define VENDOR_HT_CAPAB_OUI_TYPE 0x33 /* 00-90-4c:0x33 */
 
-/* cipher suite selectors */
-#define WLAN_CIPHER_SUITE_USE_GROUP	0x000FAC00
-#define WLAN_CIPHER_SUITE_WEP40		0x000FAC01
-#define WLAN_CIPHER_SUITE_TKIP		0x000FAC02
-/* reserved: 				0x000FAC03 */
-#define WLAN_CIPHER_SUITE_CCMP		0x000FAC04
-#define WLAN_CIPHER_SUITE_WEP104	0x000FAC05
-#define WLAN_CIPHER_SUITE_AES_CMAC	0x000FAC06
-#define WLAN_CIPHER_SUITE_NO_GROUP_ADDR	0x000FAC07
-#define WLAN_CIPHER_SUITE_GCMP		0x000FAC08
-#define WLAN_CIPHER_SUITE_GCMP_256	0x000FAC09
-#define WLAN_CIPHER_SUITE_CCMP_256	0x000FAC0A
-#define WLAN_CIPHER_SUITE_BIP_GMAC_128	0x000FAC0B
-#define WLAN_CIPHER_SUITE_BIP_GMAC_256	0x000FAC0C
-#define WLAN_CIPHER_SUITE_BIP_CMAC_256	0x000FAC0D
-
-#define WLAN_CIPHER_SUITE_SMS4		0x00147201
-
-#define WLAN_CIPHER_SUITE_CKIP		0x00409600
-#define WLAN_CIPHER_SUITE_CKIP_CMIC	0x00409601
-#define WLAN_CIPHER_SUITE_CMIC		0x00409602
-#define WLAN_CIPHER_SUITE_KRK		0x004096FF /* for nl80211 use only */
-
-/* AKM suite selectors */
-#define WLAN_AKM_SUITE_8021X		0x000FAC01
-#define WLAN_AKM_SUITE_PSK		0x000FAC02
-#define WLAN_AKM_SUITE_FT_8021X		0x000FAC03
-#define WLAN_AKM_SUITE_FT_PSK		0x000FAC04
-#define WLAN_AKM_SUITE_8021X_SHA256	0x000FAC05
-#define WLAN_AKM_SUITE_PSK_SHA256	0x000FAC06
-#define WLAN_AKM_SUITE_8021X_SUITE_B	0x000FAC11
-#define WLAN_AKM_SUITE_8021X_SUITE_B_192	0x000FAC12
-#define WLAN_AKM_SUITE_FILS_SHA256	0x000FAC14
-#define WLAN_AKM_SUITE_FILS_SHA384	0x000FAC15
-#define WLAN_AKM_SUITE_FT_FILS_SHA256	0x000FAC16
-#define WLAN_AKM_SUITE_FT_FILS_SHA384	0x000FAC17
-#define WLAN_AKM_SUITE_CCKM		0x00409600
-#define WLAN_AKM_SUITE_OSEN		0x506f9a01
-
 
 /* IEEE 802.11v - WNM Action field values */
 enum wnm_action {
diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h
index 46fddff..25800d4 100644
--- a/src/common/qca-vendor.h
+++ b/src/common/qca-vendor.h
@@ -243,6 +243,30 @@
  *	FCC compliance, OEMs require methods to set SAR limits on TX
  *	power of WLAN/WWAN. enum qca_vendor_attr_sar_limits
  *	attributes are used with this command.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS: This command/event is used by the
+ *	host driver for offloading the implementation of Auto Channel Selection
+ *	(ACS) to an external user space entity. This interface is used as the
+ *	event from the host driver to the user space entity and also as the
+ *	request from the user space entity to the host driver. The event from
+ *	the host driver is used by the user space entity as an indication to
+ *	start the ACS functionality. The attributes used by this event are
+ *	represented by the enum qca_wlan_vendor_attr_external_acs_event.
+ *	User space entity uses the same interface to inform the host driver with
+ *	selected channels after the ACS operation using the attributes defined
+ *	by enum qca_wlan_vendor_attr_external_acs_channels.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_CHIP_PWRSAVE_FAILURE: Vendor event carrying the
+ *	requisite information leading to a power save failure. The information
+ *	carried as part of this event is represented by the
+ *	enum qca_attr_chip_power_save_failure attributes.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_SET: Start/Stop the NUD statistics
+ *	collection. Uses attributes defined in enum qca_attr_nud_stats_set.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET: Get the NUD statistics. These
+ *	statistics are represented by the enum qca_attr_nud_stats_get
+ *	attributes.
  */
 enum qca_nl80211_vendor_subcmds {
 	QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0,
@@ -364,6 +388,10 @@
 	/* 144 - reserved for QCA */
 	QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN = 145,
 	QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS = 146,
+	QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS = 147,
+	QCA_NL80211_VENDOR_SUBCMD_CHIP_PWRSAVE_FAILURE = 148,
+	QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_SET = 149,
+	QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET = 150,
 };
 
 
@@ -794,11 +822,39 @@
  *	vendor specific element is defined by the latest P802.11ax draft.
  *	Please note that the draft is still work in progress and this element
  *	payload is subject to change.
+ *
+ * @QCA_VENDOR_ELEM_RAPS: RAPS element (OFDMA-based Random Access Parameter Set
+ *	element).
+ *	This element can be used for pre-standard publication testing of HE
+ *	before P802.11ax draft assigns the element ID extension. The payload of
+ *	this vendor specific element is defined by the latest P802.11ax draft
+ *	(not including the Element ID Extension field). Please note that the
+ *	draft is still work in progress and this element payload is subject to
+ *	change.
+ *
+ * @QCA_VENDOR_ELEM_MU_EDCA_PARAMS: MU EDCA Parameter Set element.
+ *	This element can be used for pre-standard publication testing of HE
+ *	before P802.11ax draft assigns the element ID extension. The payload of
+ *	this vendor specific element is defined by the latest P802.11ax draft
+ *	(not including the Element ID Extension field). Please note that the
+ *	draft is still work in progress and this element payload is subject to
+ *	change.
+ *
+ * @QCA_VENDOR_ELEM_BSS_COLOR_CHANGE: BSS Color Change Announcement element.
+ *	This element can be used for pre-standard publication testing of HE
+ *	before P802.11ax draft assigns the element ID extension. The payload of
+ *	this vendor specific element is defined by the latest P802.11ax draft
+ *	(not including the Element ID Extension field). Please note that the
+ *	draft is still work in progress and this element payload is subject to
+ *	change.
  */
 enum qca_vendor_element_id {
 	QCA_VENDOR_ELEM_P2P_PREF_CHAN_LIST = 0,
 	QCA_VENDOR_ELEM_HE_CAPAB = 1,
 	QCA_VENDOR_ELEM_HE_OPER = 2,
+	QCA_VENDOR_ELEM_RAPS = 3,
+	QCA_VENDOR_ELEM_MU_EDCA_PARAMS = 4,
+	QCA_VENDOR_ELEM_BSS_COLOR_CHANGE = 5,
 };
 
 /**
@@ -2912,4 +2968,340 @@
 	QCA_WLAN_VENDOR_ATTR_PNO_AFTER_LAST - 1,
 };
 
+/**
+ * qca_wlan_vendor_acs_select_reason: This represents the different reasons why
+ * the ACS has to be triggered. These values are used by
+ * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON and
+ * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
+ */
+enum qca_wlan_vendor_acs_select_reason {
+	/* Represents the reason that the ACS triggered during the AP start */
+	QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT,
+	/* Represents the reason that DFS found with the current channel */
+	QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS,
+	/* Represents the reason that LTE co-exist in the current band. */
+	QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX,
+};
+
+/**
+ * qca_wlan_vendor_channel_prop_flags: This represent the flags for a channel.
+ * This is used by QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS.
+ */
+enum qca_wlan_vendor_channel_prop_flags {
+	/* Bits 0, 1, 2, and 3 are reserved */
+
+	/* Turbo channel */
+	QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_TURBO         = 1 << 4,
+	/* CCK channel */
+	QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_CCK           = 1 << 5,
+	/* OFDM channel */
+	QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_OFDM          = 1 << 6,
+	/* 2.4 GHz spectrum channel. */
+	QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_2GHZ          = 1 << 7,
+	/* 5 GHz spectrum channel */
+	QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_5GHZ          = 1 << 8,
+	/* Only passive scan allowed */
+	QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_PASSIVE       = 1 << 9,
+	/* Dynamic CCK-OFDM channel */
+	QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_DYN           = 1 << 10,
+	/* GFSK channel (FHSS PHY) */
+	QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_GFSK          = 1 << 11,
+	/* Radar found on channel */
+	QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_RADAR         = 1 << 12,
+	/* 11a static turbo channel only */
+	QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_STURBO        = 1 << 13,
+	/* Half rate channel */
+	QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HALF          = 1 << 14,
+	/* Quarter rate channel */
+	QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_QUARTER       = 1 << 15,
+	/* HT 20 channel */
+	QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HT20          = 1 << 16,
+	/* HT 40 with extension channel above */
+	QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HT40PLUS      = 1 << 17,
+	/* HT 40 with extension channel below */
+	QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HT40MINUS     = 1 << 18,
+	/* HT 40 intolerant */
+	QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HT40INTOL     = 1 << 19,
+	/* VHT 20 channel */
+	QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_VHT20         = 1 << 20,
+	/* VHT 40 with extension channel above */
+	QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_VHT40PLUS     = 1 << 21,
+	/* VHT 40 with extension channel below */
+	QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_VHT40MINUS    = 1 << 22,
+	/* VHT 80 channel */
+	QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_VHT80         = 1 << 23,
+	/* HT 40 intolerant mark bit for ACS use */
+	QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HT40INTOLMARK = 1 << 24,
+	/* Channel temporarily blocked due to noise */
+	QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_BLOCKED       = 1 << 25,
+	/* VHT 160 channel */
+	QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_VHT160        = 1 << 26,
+	/* VHT 80+80 channel */
+	QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_VHT80_80      = 1 << 27,
+};
+
+/**
+ * qca_wlan_vendor_channel_prop_flags_ext: This represent the extended flags for
+ * each channel. This is used by
+ * QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT.
+ */
+enum qca_wlan_vendor_channel_prop_flags_ext {
+	/* Radar found on channel */
+	QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_RADAR_FOUND     = 1 << 0,
+	/* DFS required on channel */
+	QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_DFS             = 1 << 1,
+	/* DFS required on channel for 2nd band of 80+80 */
+	QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_DFS_CFREQ2      = 1 << 2,
+	/* If channel has been checked for DFS */
+	QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_DFS_CLEAR       = 1 << 3,
+	/* Excluded in 802.11d */
+	QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_11D_EXCLUDED    = 1 << 4,
+	/* Channel Switch Announcement received on this channel */
+	QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_CSA_RECEIVED    = 1 << 5,
+	/* Ad-hoc is not allowed */
+	QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_DISALLOW_ADHOC  = 1 << 6,
+	/* Station only channel */
+	QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_DISALLOW_HOSTAP = 1 << 7,
+	/* DFS radar history for slave device (STA mode) */
+	QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_HISTORY_RADAR   = 1 << 8,
+	/* DFS CAC valid for slave device (STA mode) */
+	QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_CAC_VALID       = 1 << 9,
+};
+
+/**
+ * qca_wlan_vendor_external_acs_event_chan_info_attr: Represents per channel
+ * information. These attributes are sent as part of
+ * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO. Each set of the following
+ * attributes correspond to a single channel.
+ */
+enum qca_wlan_vendor_external_acs_event_chan_info_attr {
+	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_INVALID = 0,
+
+	/* A bitmask (u32) with flags specified in
+	 * enum qca_wlan_vendor_channel_prop_flags.
+	 */
+	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS = 1,
+	/* A bitmask (u32) with flags specified in
+	 * enum qca_wlan_vendor_channel_prop_flags_ext.
+	 */
+	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT = 2,
+	/* frequency in MHz (u32) */
+	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ = 3,
+	/* maximum regulatory transmission power (u32) */
+	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER = 4,
+	/* maximum transmission power (u32) */
+	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER = 5,
+	/* minimum transmission power (u32) */
+	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER = 6,
+	/* regulatory class id (u8) */
+	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID = 7,
+	/* maximum antenna gain in (u8) */
+	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN = 8,
+	/* VHT segment 0 (u8) */
+	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0 = 9,
+	/* VHT segment 1 (u8) */
+	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1 = 10,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_LAST,
+	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX =
+		QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_LAST - 1,
+};
+
+/**
+ * qca_wlan_vendor_attr_pcl: Represents attributes for
+ * preferred channel list (PCL). These attributes are sent as part of
+ * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL.
+ */
+enum qca_wlan_vendor_attr_pcl {
+	QCA_WLAN_VENDOR_ATTR_PCL_INVALID = 0,
+
+	/* Channel number (u8) */
+	QCA_WLAN_VENDOR_ATTR_PCL_CHANNEL = 1,
+	/* Channel weightage (u8) */
+	QCA_WLAN_VENDOR_ATTR_PCL_WEIGHT = 2,
+};
+
+/**
+ * qca_wlan_vendor_attr_external_acs_event: Attribute to vendor sub-command
+ * QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS. This attribute will be sent by
+ * host driver.
+ */
+enum qca_wlan_vendor_attr_external_acs_event {
+	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_INVALID = 0,
+
+	/* This reason (u8) refers to enum qca_wlan_vendor_acs_select_reason.
+	 * This helps ACS module to understand why ACS needs to be started.
+	 */
+	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON = 1,
+	/* Flag attribute to indicate if driver supports spectral scanning */
+	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_SPECTRAL_SUPPORTED = 2,
+	/* Flag attribute to indicate if 11ac is offloaded to firmware */
+	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED = 3,
+	/* Flag attribute to indicate if driver provides additional channel
+	 * capability as part of scan operation */
+	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT = 4,
+	/* Flag attribute to indicate interface status is UP */
+	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_AP_UP = 5,
+	/* Operating mode (u8) of interface. Takes one of enum nl80211_iftype
+	 * values. */
+	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_SAP_MODE = 6,
+	/* Channel width (u8). It takes one of enum nl80211_chan_width values.
+	 * This is the upper bound of channel width. ACS logic should try to get
+	 * a channel with the specified width and if not found, look for lower
+	 * values.
+	 */
+	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH = 7,
+	/* This (u8) will hold values of one of enum nl80211_bands */
+	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND = 8,
+	/* PHY/HW mode (u8). Takes one of enum qca_wlan_vendor_acs_hw_mode
+	 * values */
+	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE = 9,
+	/* Array of (u32) supported frequency list among which ACS should choose
+	 * best frequency.
+	 */
+	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_FREQ_LIST = 10,
+	/* Preferred channel list by the driver which will have array of nested
+	 * values as per enum qca_wlan_vendor_attr_pcl attribute.
+	 */
+	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL = 11,
+	/* Array of nested attribute for each channel. It takes attr as defined
+	 * in enum qca_wlan_vendor_external_acs_event_chan_info_attr.
+	 */
+	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO = 12,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_LAST,
+	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_MAX =
+		QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_LAST - 1,
+};
+
+/**
+ * qca_wlan_vendor_attr_external_acs_channels: Attributes to vendor subcmd
+ * QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS. This carries a list of channels
+ * in priority order as decided after ACS operation in userspace.
+ */
+enum qca_wlan_vendor_attr_external_acs_channels {
+	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_INVALID = 0,
+
+	/* One of reason code (u8) from enum qca_wlan_vendor_acs_select_reason
+	 */
+	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON = 1,
+
+	/* Array of nested values for each channel with following attributes:
+	 * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_BAND,
+	 * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY,
+	 * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY,
+	 * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0,
+	 * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1,
+	 * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
+	 */
+	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST = 2,
+	/* This (u8) will hold values of one of enum nl80211_bands */
+	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_BAND = 3,
+	/* Primary channel (u8) */
+	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY = 4,
+	/* Secondary channel (u8) used for HT 40 MHz channels */
+	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY = 5,
+	/* VHT seg0 channel (u8) */
+	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0 = 6,
+	/* VHT seg1 channel (u8) */
+	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1 = 7,
+	/* Channel width (u8). Takes one of enum nl80211_chan_width values. */
+	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH = 8,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LAST,
+	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX =
+		QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LAST - 1
+};
+
+enum qca_chip_power_save_failure_reason {
+	/* Indicates if the reason for the failure is due to a protocol
+	 * layer/module.
+	 */
+        QCA_CHIP_POWER_SAVE_FAILURE_REASON_PROTOCOL = 0,
+	/* Indicates if the reason for the failure is due to a hardware issue.
+	 */
+        QCA_CHIP_POWER_SAVE_FAILURE_REASON_HARDWARE = 1,
+};
+
+/**
+ * qca_attr_chip_power_save_failure: Attributes to vendor subcmd
+ * QCA_NL80211_VENDOR_SUBCMD_CHIP_PWRSAVE_FAILURE. This carries the requisite
+ * information leading to the power save failure.
+ */
+enum qca_attr_chip_power_save_failure {
+        QCA_ATTR_CHIP_POWER_SAVE_FAILURE_INVALID = 0,
+        /* Reason to cause the power save failure.
+	 * These reasons are represented by
+	 * enum qca_chip_power_save_failure_reason.
+	 */
+        QCA_ATTR_CHIP_POWER_SAVE_FAILURE_REASON = 1,
+
+        /* keep last */
+        QCA_ATTR_CHIP_POWER_SAVE_FAILURE_LAST,
+        QCA_ATTR_CHIP_POWER_SAVE_FAILURE_MAX =
+                QCA_ATTR_CHIP_POWER_SAVE_FAILURE_LAST - 1,
+};
+
+/**
+ * qca_wlan_vendor_attr_nud_stats_set: Attributes to vendor subcmd
+ * QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_SET. This carries the requisite
+ * information to start/stop the NUD statistics collection.
+ */
+enum qca_attr_nud_stats_set {
+	QCA_ATTR_NUD_STATS_SET_INVALID = 0,
+
+	/* Flag to start/stop the NUD statistics collection.
+	 * Start - If included, Stop - If not included
+	 */
+	QCA_ATTR_NUD_STATS_SET_START = 1,
+	/* IPv4 address of the default gateway (in network byte order) */
+	QCA_ATTR_NUD_STATS_GW_IPV4 = 2,
+
+	/* keep last */
+	QCA_ATTR_NUD_STATS_SET_LAST,
+	QCA_ATTR_NUD_STATS_SET_MAX =
+		QCA_ATTR_NUD_STATS_SET_LAST - 1,
+};
+
+/**
+ * qca_attr_nud_stats_get: Attributes to vendor subcmd
+ * QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET. This carries the requisite
+ * NUD statistics collected when queried.
+ */
+enum qca_attr_nud_stats_get {
+	QCA_ATTR_NUD_STATS_GET_INVALID = 0,
+	/* ARP Request count from netdev */
+	QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV = 1,
+	/* ARP Request count sent to lower MAC from upper MAC */
+	QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC = 2,
+	/* ARP Request count received by lower MAC from upper MAC */
+	QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC = 3,
+	/* ARP Request count successfully transmitted by the device */
+	QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS = 4,
+	/* ARP Response count received by lower MAC */
+	QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC = 5,
+	/* ARP Response count received by upper MAC */
+	QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC = 6,
+	/* ARP Response count delivered to netdev */
+	QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV = 7,
+	/* ARP Response count delivered to netdev */
+	QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP = 8,
+	/* Flag indicating if the station's link to the AP is active.
+	 * Active Link - If included, Inactive link - If not included
+	 */
+	QCA_ATTR_NUD_STATS_AP_LINK_ACTIVE= 9,
+	/* Flag indicating if there is any duplicate address detected (DAD).
+	 * Yes - If detected, No - If not detected.
+	 */
+	QCA_ATTR_NUD_STATS_IS_DAD = 9,
+
+	/* keep last */
+	QCA_ATTR_NUD_STATS_GET_LAST,
+	QCA_ATTR_NUD_STATS_GET_MAX =
+		QCA_ATTR_NUD_STATS_GET_LAST - 1,
+};
+
 #endif /* QCA_VENDOR_H */
diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c
index 6eb1e66..79f001b 100644
--- a/src/common/wpa_common.c
+++ b/src/common/wpa_common.c
@@ -230,6 +230,78 @@
 
 #ifdef CONFIG_FILS
 
+int fils_rmsk_to_pmk(int akmp, const u8 *rmsk, size_t rmsk_len,
+		     const u8 *snonce, const u8 *anonce, const u8 *dh_ss,
+		     size_t dh_ss_len, u8 *pmk, size_t *pmk_len)
+{
+	u8 nonces[2 * FILS_NONCE_LEN];
+	const u8 *addr[2];
+	size_t len[2];
+	size_t num_elem;
+	int res;
+
+	/* PMK = HMAC-Hash(SNonce || ANonce, rMSK [ || DHss ]) */
+	wpa_printf(MSG_DEBUG, "FILS: rMSK to PMK derivation");
+
+	if (wpa_key_mgmt_sha384(akmp))
+		*pmk_len = SHA384_MAC_LEN;
+	else if (wpa_key_mgmt_sha256(akmp))
+		*pmk_len = SHA256_MAC_LEN;
+	else
+		return -1;
+
+	wpa_hexdump_key(MSG_DEBUG, "FILS: rMSK", rmsk, rmsk_len);
+	wpa_hexdump(MSG_DEBUG, "FILS: SNonce", snonce, FILS_NONCE_LEN);
+	wpa_hexdump(MSG_DEBUG, "FILS: ANonce", anonce, FILS_NONCE_LEN);
+	wpa_hexdump(MSG_DEBUG, "FILS: DHss", dh_ss, dh_ss_len);
+
+	os_memcpy(nonces, snonce, FILS_NONCE_LEN);
+	os_memcpy(&nonces[FILS_NONCE_LEN], anonce, FILS_NONCE_LEN);
+	addr[0] = rmsk;
+	len[0] = rmsk_len;
+	num_elem = 1;
+	if (dh_ss) {
+		addr[1] = dh_ss;
+		len[1] = dh_ss_len;
+		num_elem++;
+	}
+	if (wpa_key_mgmt_sha384(akmp))
+		res = hmac_sha384_vector(nonces, 2 * FILS_NONCE_LEN, num_elem,
+					 addr, len, pmk);
+	else
+		res = hmac_sha256_vector(nonces, 2 * FILS_NONCE_LEN, num_elem,
+					 addr, len, pmk);
+	if (res == 0)
+		wpa_hexdump_key(MSG_DEBUG, "FILS: PMK", pmk, *pmk_len);
+	return res;
+}
+
+
+int fils_pmkid_erp(int akmp, const u8 *reauth, size_t reauth_len,
+		   u8 *pmkid)
+{
+	const u8 *addr[1];
+	size_t len[1];
+	u8 hash[SHA384_MAC_LEN];
+	int res;
+
+	/* PMKID = Truncate-128(Hash(EAP-Initiate/Reauth)) */
+	addr[0] = reauth;
+	len[0] = reauth_len;
+	if (wpa_key_mgmt_sha384(akmp))
+		res = sha384_vector(1, addr, len, hash);
+	else if (wpa_key_mgmt_sha256(akmp))
+		res = sha256_vector(1, addr, len, hash);
+	else
+		return -1;
+	if (res)
+		return res;
+	os_memcpy(pmkid, hash, PMKID_LEN);
+	wpa_hexdump(MSG_DEBUG, "FILS: PMKID", pmkid, PMKID_LEN);
+	return 0;
+}
+
+
 int fils_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const u8 *spa, const u8 *aa,
 		    const u8 *snonce, const u8 *anonce, struct wpa_ptk *ptk,
 		    u8 *ick, size_t *ick_len, int akmp, int cipher)
@@ -1412,35 +1484,33 @@
 u32 wpa_akm_to_suite(int akm)
 {
 	if (akm & WPA_KEY_MGMT_FT_IEEE8021X)
-		return WLAN_AKM_SUITE_FT_8021X;
+		return RSN_AUTH_KEY_MGMT_FT_802_1X;
 	if (akm & WPA_KEY_MGMT_FT_PSK)
-		return WLAN_AKM_SUITE_FT_PSK;
-	if (akm & WPA_KEY_MGMT_IEEE8021X)
-		return WLAN_AKM_SUITE_8021X;
+		return RSN_AUTH_KEY_MGMT_FT_PSK;
 	if (akm & WPA_KEY_MGMT_IEEE8021X_SHA256)
-		return WLAN_AKM_SUITE_8021X_SHA256;
+		return RSN_AUTH_KEY_MGMT_802_1X_SHA256;
 	if (akm & WPA_KEY_MGMT_IEEE8021X)
-		return WLAN_AKM_SUITE_8021X;
+		return RSN_AUTH_KEY_MGMT_UNSPEC_802_1X;
 	if (akm & WPA_KEY_MGMT_PSK_SHA256)
-		return WLAN_AKM_SUITE_PSK_SHA256;
+		return RSN_AUTH_KEY_MGMT_PSK_SHA256;
 	if (akm & WPA_KEY_MGMT_PSK)
-		return WLAN_AKM_SUITE_PSK;
+		return RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X;
 	if (akm & WPA_KEY_MGMT_CCKM)
-		return WLAN_AKM_SUITE_CCKM;
+		return RSN_AUTH_KEY_MGMT_CCKM;
 	if (akm & WPA_KEY_MGMT_OSEN)
-		return WLAN_AKM_SUITE_OSEN;
+		return RSN_AUTH_KEY_MGMT_OSEN;
 	if (akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B)
-		return WLAN_AKM_SUITE_8021X_SUITE_B;
+		return RSN_AUTH_KEY_MGMT_802_1X_SUITE_B;
 	if (akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
-		return WLAN_AKM_SUITE_8021X_SUITE_B_192;
+		return RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192;
 	if (akm & WPA_KEY_MGMT_FILS_SHA256)
-		return WLAN_AKM_SUITE_FILS_SHA256;
+		return RSN_AUTH_KEY_MGMT_FILS_SHA256;
 	if (akm & WPA_KEY_MGMT_FILS_SHA384)
-		return WLAN_AKM_SUITE_FILS_SHA384;
+		return RSN_AUTH_KEY_MGMT_FILS_SHA384;
 	if (akm & WPA_KEY_MGMT_FT_FILS_SHA256)
-		return WLAN_AKM_SUITE_FT_FILS_SHA256;
+		return RSN_AUTH_KEY_MGMT_FT_FILS_SHA256;
 	if (akm & WPA_KEY_MGMT_FT_FILS_SHA384)
-		return WLAN_AKM_SUITE_FT_FILS_SHA384;
+		return RSN_AUTH_KEY_MGMT_FT_FILS_SHA384;
 	return 0;
 }
 
diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h
index 4e952c1..4e465f5 100644
--- a/src/common/wpa_common.h
+++ b/src/common/wpa_common.h
@@ -48,10 +48,8 @@
 
 #define RSN_AUTH_KEY_MGMT_UNSPEC_802_1X RSN_SELECTOR(0x00, 0x0f, 0xac, 1)
 #define RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X RSN_SELECTOR(0x00, 0x0f, 0xac, 2)
-#ifdef CONFIG_IEEE80211R
 #define RSN_AUTH_KEY_MGMT_FT_802_1X RSN_SELECTOR(0x00, 0x0f, 0xac, 3)
 #define RSN_AUTH_KEY_MGMT_FT_PSK RSN_SELECTOR(0x00, 0x0f, 0xac, 4)
-#endif /* CONFIG_IEEE80211R */
 #define RSN_AUTH_KEY_MGMT_802_1X_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 5)
 #define RSN_AUTH_KEY_MGMT_PSK_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 6)
 #define RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE RSN_SELECTOR(0x00, 0x0f, 0xac, 7)
@@ -69,11 +67,13 @@
 #define RSN_AUTH_KEY_MGMT_OSEN RSN_SELECTOR(0x50, 0x6f, 0x9a, 0x01)
 
 #define RSN_CIPHER_SUITE_NONE RSN_SELECTOR(0x00, 0x0f, 0xac, 0)
+#define RSN_CIPHER_SUITE_WEP40 RSN_SELECTOR(0x00, 0x0f, 0xac, 1)
 #define RSN_CIPHER_SUITE_TKIP RSN_SELECTOR(0x00, 0x0f, 0xac, 2)
 #if 0
 #define RSN_CIPHER_SUITE_WRAP RSN_SELECTOR(0x00, 0x0f, 0xac, 3)
 #endif
 #define RSN_CIPHER_SUITE_CCMP RSN_SELECTOR(0x00, 0x0f, 0xac, 4)
+#define RSN_CIPHER_SUITE_WEP104 RSN_SELECTOR(0x00, 0x0f, 0xac, 5)
 #define RSN_CIPHER_SUITE_AES_128_CMAC RSN_SELECTOR(0x00, 0x0f, 0xac, 6)
 #define RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED RSN_SELECTOR(0x00, 0x0f, 0xac, 7)
 #define RSN_CIPHER_SUITE_GCMP RSN_SELECTOR(0x00, 0x0f, 0xac, 8)
@@ -82,6 +82,12 @@
 #define RSN_CIPHER_SUITE_BIP_GMAC_128 RSN_SELECTOR(0x00, 0x0f, 0xac, 11)
 #define RSN_CIPHER_SUITE_BIP_GMAC_256 RSN_SELECTOR(0x00, 0x0f, 0xac, 12)
 #define RSN_CIPHER_SUITE_BIP_CMAC_256 RSN_SELECTOR(0x00, 0x0f, 0xac, 13)
+#define RSN_CIPHER_SUITE_SMS4 RSN_SELECTOR(0x00, 0x14, 0x72, 1)
+#define RSN_CIPHER_SUITE_CKIP RSN_SELECTOR(0x00, 0x40, 0x96, 0)
+#define RSN_CIPHER_SUITE_CKIP_CMIC RSN_SELECTOR(0x00, 0x40, 0x96, 1)
+#define RSN_CIPHER_SUITE_CMIC RSN_SELECTOR(0x00, 0x40, 0x96, 2)
+/* KRK is defined for nl80211 use only */
+#define RSN_CIPHER_SUITE_KRK RSN_SELECTOR(0x00, 0x40, 0x96, 255)
 
 /* EAPOL-Key Key Data Encapsulation
  * GroupKey and PeerKey require encryption, otherwise, encryption is optional.
@@ -330,6 +336,11 @@
 		   const u8 *addr1, const u8 *addr2,
 		   const u8 *nonce1, const u8 *nonce2,
 		   struct wpa_ptk *ptk, int akmp, int cipher);
+int fils_rmsk_to_pmk(int akmp, const u8 *rmsk, size_t rmsk_len,
+		     const u8 *snonce, const u8 *anonce, const u8 *dh_ss,
+		     size_t dh_ss_len, u8 *pmk, size_t *pmk_len);
+int fils_pmkid_erp(int akmp, const u8 *reauth, size_t reauth_len,
+		   u8 *pmkid);
 int fils_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const u8 *spa, const u8 *aa,
 		    const u8 *snonce, const u8 *anonce, struct wpa_ptk *ptk,
 		    u8 *ick, size_t *ick_len, int akmp, int cipher);
diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
index ec4e879..766a3fa 100644
--- a/src/common/wpa_ctrl.h
+++ b/src/common/wpa_ctrl.h
@@ -74,6 +74,8 @@
 #define WPA_EVENT_NETWORK_NOT_FOUND "CTRL-EVENT-NETWORK-NOT-FOUND "
 /** Change in the signal level was reported by the driver */
 #define WPA_EVENT_SIGNAL_CHANGE "CTRL-EVENT-SIGNAL-CHANGE "
+/** Beacon loss reported by the driver */
+#define WPA_EVENT_BEACON_LOSS "CTRL-EVENT-BEACON-LOSS "
 /** Regulatory domain channel */
 #define WPA_EVENT_REGDOM_CHANGE "CTRL-EVENT-REGDOM-CHANGE "
 /** Channel switch (followed by freq=<MHz> and other channel parameters) */
diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c
index b3d1b07..02cb391 100644
--- a/src/crypto/crypto_openssl.c
+++ b/src/crypto/crypto_openssl.c
@@ -109,6 +109,9 @@
 #ifdef OPENSSL_NO_SHA256
 #define NO_SHA256_WRAPPER
 #endif
+#ifdef OPENSSL_NO_SHA512
+#define NO_SHA384_WRAPPER
+#endif
 
 static int openssl_digest_vector(const EVP_MD *type, size_t num_elem,
 				 const u8 *addr[], const size_t *len, u8 *mac)
@@ -242,6 +245,14 @@
 }
 #endif /* NO_SHA256_WRAPPER */
 
+#ifndef NO_SHA384_WRAPPER
+int sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len,
+		  u8 *mac)
+{
+	return openssl_digest_vector(EVP_sha384(), num_elem, addr, len, mac);
+}
+#endif /* NO_SHA384_WRAPPER */
+
 
 static const EVP_CIPHER * aes_get_evp_cipher(size_t keylen)
 {
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 291d4d6..92688a3 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -1,6 +1,6 @@
 /*
  * Driver interface definition
- * Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2017, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -4228,6 +4228,15 @@
 	 * EVENT_P2P_LO_STOP - Notify that P2P listen offload is stopped
 	 */
 	EVENT_P2P_LO_STOP,
+
+	/**
+	 * EVENT_BEACON_LOSS - Beacon loss detected
+	 *
+	 * This event indicates that no Beacon frames has been received from
+	 * the current AP. This may indicate that the AP is not anymore in
+	 * range.
+	 */
+	EVENT_BEACON_LOSS,
 };
 
 
@@ -4817,9 +4826,12 @@
 	/**
 	 * struct low_ack - Data for EVENT_STATION_LOW_ACK events
 	 * @addr: station address
+	 * @num_packets: Number of packets lost (consecutive packets not
+	 * acknowledged)
 	 */
 	struct low_ack {
 		u8 addr[ETH_ALEN];
+		u32 num_packets;
 	} low_ack;
 
 	/**
diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c
index c7107ba..b6bcbca 100644
--- a/src/drivers/driver_common.c
+++ b/src/drivers/driver_common.c
@@ -1,6 +1,6 @@
 /*
  * Common driver-related functions
- * Copyright (c) 2003-2011, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2017, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -81,6 +81,7 @@
 	E2S(ACS_CHANNEL_SELECTED);
 	E2S(DFS_CAC_STARTED);
 	E2S(P2P_LO_STOP);
+	E2S(BEACON_LOSS);
 	}
 
 	return "UNKNOWN";
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 5f0a277..27e22c6 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -29,6 +29,7 @@
 #include "common/qca-vendor-attr.h"
 #include "common/ieee802_11_defs.h"
 #include "common/ieee802_11_common.h"
+#include "common/wpa_common.h"
 #include "l2_packet/l2_packet.h"
 #include "netlink.h"
 #include "linux_defines.h"
@@ -675,6 +676,7 @@
 	struct nl80211_wiphy_data *w;
 	int wiphy_idx, found = 0;
 	struct i802_bss *tmp_bss;
+	u8 channel;
 
 	if (bss->wiphy_data != NULL)
 		return bss->wiphy_data;
@@ -694,29 +696,35 @@
 	dl_list_init(&w->bsss);
 	dl_list_init(&w->drvs);
 
-	w->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
-	if (!w->nl_cb) {
-		os_free(w);
-		return NULL;
-	}
-	nl_cb_set(w->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
-	nl_cb_set(w->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, process_beacon_event,
-		  w);
+	/* Beacon frames not supported in IEEE 802.11ad */
+	if (ieee80211_freq_to_chan(bss->freq, &channel) !=
+	    HOSTAPD_MODE_IEEE80211AD) {
+		w->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
+		if (!w->nl_cb) {
+			os_free(w);
+			return NULL;
+		}
+		nl_cb_set(w->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
+			  no_seq_check, NULL);
+		nl_cb_set(w->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,
+			  process_beacon_event, w);
 
-	w->nl_beacons = nl_create_handle(bss->drv->global->nl_cb,
-					 "wiphy beacons");
-	if (w->nl_beacons == NULL) {
-		os_free(w);
-		return NULL;
-	}
+		w->nl_beacons = nl_create_handle(bss->drv->global->nl_cb,
+						 "wiphy beacons");
+		if (w->nl_beacons == NULL) {
+			os_free(w);
+			return NULL;
+		}
 
-	if (nl80211_register_beacons(bss->drv, w)) {
-		nl_destroy_handles(&w->nl_beacons);
-		os_free(w);
-		return NULL;
-	}
+		if (nl80211_register_beacons(bss->drv, w)) {
+			nl_destroy_handles(&w->nl_beacons);
+			os_free(w);
+			return NULL;
+		}
 
-	nl80211_register_eloop_read(&w->nl_beacons, nl80211_recv_beacons, w);
+		nl80211_register_eloop_read(&w->nl_beacons,
+					    nl80211_recv_beacons, w);
+	}
 
 	dl_list_add(&nl80211_wiphys, &w->list);
 
@@ -763,7 +771,8 @@
 	if (!dl_list_empty(&w->bsss))
 		return;
 
-	nl80211_destroy_eloop_handle(&w->nl_beacons);
+	if (w->nl_beacons)
+		nl80211_destroy_eloop_handle(&w->nl_beacons);
 
 	nl_cb_put(w->nl_cb);
 	dl_list_del(&w->list);
@@ -2164,6 +2173,9 @@
 	/* RRM Measurement Report */
 	if (nl80211_register_action_frame(bss, (u8 *) "\x05\x01", 2) < 0)
 		ret = -1;
+	/* RRM Link Measurement Report */
+	if (nl80211_register_action_frame(bss, (u8 *) "\x05\x03", 2) < 0)
+		ret = -1;
 	/* RRM Neighbor Report Request */
 	if (nl80211_register_action_frame(bss, (u8 *) "\x05\x04", 2) < 0)
 		ret = -1;
@@ -2235,9 +2247,6 @@
 	if (nl80211_register_spurious_class3(bss))
 		goto out_err;
 
-	if (nl80211_get_wiphy_data_ap(bss) == NULL)
-		goto out_err;
-
 	nl80211_mgmt_handle_register_eloop(bss);
 	return 0;
 
@@ -2492,12 +2501,14 @@
 }
 
 
-static int wpa_driver_nl80211_del_beacon(struct wpa_driver_nl80211_data *drv)
+static int wpa_driver_nl80211_del_beacon(struct i802_bss *bss)
 {
 	struct nl_msg *msg;
+	struct wpa_driver_nl80211_data *drv = bss->drv;
 
 	wpa_printf(MSG_DEBUG, "nl80211: Remove beacon (ifindex=%d)",
 		   drv->ifindex);
+	nl80211_put_wiphy_data_ap(bss);
 	msg = nl80211_drv_msg(drv, 0, NL80211_CMD_DEL_BEACON);
 	return send_and_recv_msgs(drv, msg, NULL, NULL);
 }
@@ -2550,7 +2561,7 @@
 	nl80211_remove_monitor_interface(drv);
 
 	if (is_ap_interface(drv->nlmode))
-		wpa_driver_nl80211_del_beacon(drv);
+		wpa_driver_nl80211_del_beacon(bss);
 
 	if (drv->eapol_sock >= 0) {
 		eloop_unregister_read_sock(drv->eapol_sock);
@@ -2624,30 +2635,30 @@
 	switch (alg) {
 	case WPA_ALG_WEP:
 		if (key_len == 5)
-			return WLAN_CIPHER_SUITE_WEP40;
-		return WLAN_CIPHER_SUITE_WEP104;
+			return RSN_CIPHER_SUITE_WEP40;
+		return RSN_CIPHER_SUITE_WEP104;
 	case WPA_ALG_TKIP:
-		return WLAN_CIPHER_SUITE_TKIP;
+		return RSN_CIPHER_SUITE_TKIP;
 	case WPA_ALG_CCMP:
-		return WLAN_CIPHER_SUITE_CCMP;
+		return RSN_CIPHER_SUITE_CCMP;
 	case WPA_ALG_GCMP:
-		return WLAN_CIPHER_SUITE_GCMP;
+		return RSN_CIPHER_SUITE_GCMP;
 	case WPA_ALG_CCMP_256:
-		return WLAN_CIPHER_SUITE_CCMP_256;
+		return RSN_CIPHER_SUITE_CCMP_256;
 	case WPA_ALG_GCMP_256:
-		return WLAN_CIPHER_SUITE_GCMP_256;
+		return RSN_CIPHER_SUITE_GCMP_256;
 	case WPA_ALG_IGTK:
-		return WLAN_CIPHER_SUITE_AES_CMAC;
+		return RSN_CIPHER_SUITE_AES_128_CMAC;
 	case WPA_ALG_BIP_GMAC_128:
-		return WLAN_CIPHER_SUITE_BIP_GMAC_128;
+		return RSN_CIPHER_SUITE_BIP_GMAC_128;
 	case WPA_ALG_BIP_GMAC_256:
-		return WLAN_CIPHER_SUITE_BIP_GMAC_256;
+		return RSN_CIPHER_SUITE_BIP_GMAC_256;
 	case WPA_ALG_BIP_CMAC_256:
-		return WLAN_CIPHER_SUITE_BIP_CMAC_256;
+		return RSN_CIPHER_SUITE_BIP_CMAC_256;
 	case WPA_ALG_SMS4:
-		return WLAN_CIPHER_SUITE_SMS4;
+		return RSN_CIPHER_SUITE_SMS4;
 	case WPA_ALG_KRK:
-		return WLAN_CIPHER_SUITE_KRK;
+		return RSN_CIPHER_SUITE_KRK;
 	case WPA_ALG_NONE:
 	case WPA_ALG_PMK:
 		wpa_printf(MSG_ERROR, "nl80211: Unexpected encryption algorithm %d",
@@ -2665,21 +2676,21 @@
 {
 	switch (cipher) {
 	case WPA_CIPHER_CCMP_256:
-		return WLAN_CIPHER_SUITE_CCMP_256;
+		return RSN_CIPHER_SUITE_CCMP_256;
 	case WPA_CIPHER_GCMP_256:
-		return WLAN_CIPHER_SUITE_GCMP_256;
+		return RSN_CIPHER_SUITE_GCMP_256;
 	case WPA_CIPHER_CCMP:
-		return WLAN_CIPHER_SUITE_CCMP;
+		return RSN_CIPHER_SUITE_CCMP;
 	case WPA_CIPHER_GCMP:
-		return WLAN_CIPHER_SUITE_GCMP;
+		return RSN_CIPHER_SUITE_GCMP;
 	case WPA_CIPHER_TKIP:
-		return WLAN_CIPHER_SUITE_TKIP;
+		return RSN_CIPHER_SUITE_TKIP;
 	case WPA_CIPHER_WEP104:
-		return WLAN_CIPHER_SUITE_WEP104;
+		return RSN_CIPHER_SUITE_WEP104;
 	case WPA_CIPHER_WEP40:
-		return WLAN_CIPHER_SUITE_WEP40;
+		return RSN_CIPHER_SUITE_WEP40;
 	case WPA_CIPHER_GTK_NOT_USED:
-		return WLAN_CIPHER_SUITE_NO_GROUP_ADDR;
+		return RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED;
 	}
 
 	return 0;
@@ -2692,19 +2703,19 @@
 	int num_suites = 0;
 
 	if (num_suites < max_suites && ciphers & WPA_CIPHER_CCMP_256)
-		suites[num_suites++] = WLAN_CIPHER_SUITE_CCMP_256;
+		suites[num_suites++] = RSN_CIPHER_SUITE_CCMP_256;
 	if (num_suites < max_suites && ciphers & WPA_CIPHER_GCMP_256)
-		suites[num_suites++] = WLAN_CIPHER_SUITE_GCMP_256;
+		suites[num_suites++] = RSN_CIPHER_SUITE_GCMP_256;
 	if (num_suites < max_suites && ciphers & WPA_CIPHER_CCMP)
-		suites[num_suites++] = WLAN_CIPHER_SUITE_CCMP;
+		suites[num_suites++] = RSN_CIPHER_SUITE_CCMP;
 	if (num_suites < max_suites && ciphers & WPA_CIPHER_GCMP)
-		suites[num_suites++] = WLAN_CIPHER_SUITE_GCMP;
+		suites[num_suites++] = RSN_CIPHER_SUITE_GCMP;
 	if (num_suites < max_suites && ciphers & WPA_CIPHER_TKIP)
-		suites[num_suites++] = WLAN_CIPHER_SUITE_TKIP;
+		suites[num_suites++] = RSN_CIPHER_SUITE_TKIP;
 	if (num_suites < max_suites && ciphers & WPA_CIPHER_WEP104)
-		suites[num_suites++] = WLAN_CIPHER_SUITE_WEP104;
+		suites[num_suites++] = RSN_CIPHER_SUITE_WEP104;
 	if (num_suites < max_suites && ciphers & WPA_CIPHER_WEP40)
-		suites[num_suites++] = WLAN_CIPHER_SUITE_WEP40;
+		suites[num_suites++] = RSN_CIPHER_SUITE_WEP40;
 
 	return num_suites;
 }
@@ -2962,8 +2973,8 @@
 			    params->wep_key[i]) ||
 		    nla_put_u32(msg, NL80211_KEY_CIPHER,
 				params->wep_key_len[i] == 5 ?
-				WLAN_CIPHER_SUITE_WEP40 :
-				WLAN_CIPHER_SUITE_WEP104) ||
+				RSN_CIPHER_SUITE_WEP40 :
+				RSN_CIPHER_SUITE_WEP104) ||
 		    nla_put_u8(msg, NL80211_KEY_IDX, i) ||
 		    (i == params->wep_tx_keyidx &&
 		     nla_put_flag(msg, NL80211_KEY_DEFAULT)))
@@ -3775,6 +3786,9 @@
 		   beacon_set);
 	if (beacon_set)
 		cmd = NL80211_CMD_SET_BEACON;
+	else if (!drv->device_ap_sme && !drv->use_monitor &&
+		 !nl80211_get_wiphy_data_ap(bss))
+		return -ENOBUFS;
 
 	wpa_hexdump(MSG_DEBUG, "nl80211: Beacon head",
 		    params->head, params->head_len);
@@ -3856,9 +3870,9 @@
 		   params->key_mgmt_suites);
 	num_suites = 0;
 	if (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X)
-		suites[num_suites++] = WLAN_AKM_SUITE_8021X;
+		suites[num_suites++] = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X;
 	if (params->key_mgmt_suites & WPA_KEY_MGMT_PSK)
-		suites[num_suites++] = WLAN_AKM_SUITE_PSK;
+		suites[num_suites++] = RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X;
 	if (num_suites &&
 	    nla_put(msg, NL80211_ATTR_AKM_SUITES, num_suites * sizeof(u32),
 		    suites))
@@ -4706,6 +4720,7 @@
 	else
 		nl80211_mgmt_unsubscribe(bss, "AP teardown");
 
+	nl80211_put_wiphy_data_ap(bss);
 	bss->beacon_set = 0;
 }
 
@@ -5054,6 +5069,9 @@
 				  struct wpa_driver_associate_params *params,
 				  struct nl_msg *msg)
 {
+	if (nla_put_flag(msg, NL80211_ATTR_IFACE_SOCKET_OWNER))
+		return -1;
+
 	if (params->bssid) {
 		wpa_printf(MSG_DEBUG, "  * bssid=" MACSTR,
 			   MAC2STR(params->bssid));
@@ -5155,39 +5173,39 @@
 	    params->key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
 	    params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
 	    params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
-		int mgmt = WLAN_AKM_SUITE_PSK;
+		int mgmt = RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X;
 
 		switch (params->key_mgmt_suite) {
 		case WPA_KEY_MGMT_CCKM:
-			mgmt = WLAN_AKM_SUITE_CCKM;
+			mgmt = RSN_AUTH_KEY_MGMT_CCKM;
 			break;
 		case WPA_KEY_MGMT_IEEE8021X:
-			mgmt = WLAN_AKM_SUITE_8021X;
+			mgmt = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X;
 			break;
 		case WPA_KEY_MGMT_FT_IEEE8021X:
-			mgmt = WLAN_AKM_SUITE_FT_8021X;
+			mgmt = RSN_AUTH_KEY_MGMT_FT_802_1X;
 			break;
 		case WPA_KEY_MGMT_FT_PSK:
-			mgmt = WLAN_AKM_SUITE_FT_PSK;
+			mgmt = RSN_AUTH_KEY_MGMT_FT_PSK;
 			break;
 		case WPA_KEY_MGMT_IEEE8021X_SHA256:
-			mgmt = WLAN_AKM_SUITE_8021X_SHA256;
+			mgmt = RSN_AUTH_KEY_MGMT_802_1X_SHA256;
 			break;
 		case WPA_KEY_MGMT_PSK_SHA256:
-			mgmt = WLAN_AKM_SUITE_PSK_SHA256;
+			mgmt = RSN_AUTH_KEY_MGMT_PSK_SHA256;
 			break;
 		case WPA_KEY_MGMT_OSEN:
-			mgmt = WLAN_AKM_SUITE_OSEN;
+			mgmt = RSN_AUTH_KEY_MGMT_OSEN;
 			break;
 		case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
-			mgmt = WLAN_AKM_SUITE_8021X_SUITE_B;
+			mgmt = RSN_AUTH_KEY_MGMT_802_1X_SUITE_B;
 			break;
 		case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
-			mgmt = WLAN_AKM_SUITE_8021X_SUITE_B_192;
+			mgmt = RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192;
 			break;
 		case WPA_KEY_MGMT_PSK:
 		default:
-			mgmt = WLAN_AKM_SUITE_PSK;
+			mgmt = RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X;
 			break;
 		}
 		wpa_printf(MSG_DEBUG, "  * akm=0x%x", mgmt);
@@ -6739,7 +6757,7 @@
 		wpa_printf(MSG_DEBUG, "nl80211: First BSS - reassign context");
 		nl80211_teardown_ap(bss);
 		if (!bss->added_if && !drv->first_bss->next)
-			wpa_driver_nl80211_del_beacon(drv);
+			wpa_driver_nl80211_del_beacon(bss);
 		nl80211_destroy_bss(bss);
 		if (!bss->added_if)
 			i802_set_iface_flags(bss, 0);
@@ -7101,7 +7119,7 @@
 	struct wpa_driver_nl80211_data *drv = bss->drv;
 	if (!is_ap_interface(drv->nlmode))
 		return -1;
-	wpa_driver_nl80211_del_beacon(drv);
+	wpa_driver_nl80211_del_beacon(bss);
 	bss->beacon_set = 0;
 
 	/*
@@ -7121,7 +7139,7 @@
 	struct wpa_driver_nl80211_data *drv = bss->drv;
 	if (!is_ap_interface(drv->nlmode))
 		return -1;
-	wpa_driver_nl80211_del_beacon(drv);
+	wpa_driver_nl80211_del_beacon(bss);
 	bss->beacon_set = 0;
 	return 0;
 }
@@ -7810,6 +7828,7 @@
 	struct wpa_driver_nl80211_data *drv = bss->drv;
 	struct nl_msg *msg;
 	enum nl80211_tdls_operation nl80211_oper;
+	int res;
 
 	if (!(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT))
 		return -EOPNOTSUPP;
@@ -7845,7 +7864,11 @@
 		return -ENOBUFS;
 	}
 
-	return send_and_recv_msgs(drv, msg, NULL, NULL);
+	res = send_and_recv_msgs(drv, msg, NULL, NULL);
+	wpa_printf(MSG_DEBUG, "nl80211: TDLS_OPER: oper=%d mac=" MACSTR
+		   " --> res=%d (%s)", nl80211_oper, MAC2STR(peer), res,
+		   strerror(-res));
+	return res;
 }
 
 
diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
index cad3970..3d85316 100644
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -12,8 +12,8 @@
 #include <netlink/genl/genl.h>
 
 #include "utils/common.h"
-#include "common/ieee802_11_defs.h"
 #include "common/ieee802_11_common.h"
+#include "common/wpa_common.h"
 #include "common/qca-vendor.h"
 #include "common/qca-vendor-attr.h"
 #include "driver_nl80211.h"
@@ -266,40 +266,40 @@
 			   c >> 24, (c >> 16) & 0xff,
 			   (c >> 8) & 0xff, c & 0xff);
 		switch (c) {
-		case WLAN_CIPHER_SUITE_CCMP_256:
+		case RSN_CIPHER_SUITE_CCMP_256:
 			info->capa->enc |= WPA_DRIVER_CAPA_ENC_CCMP_256;
 			break;
-		case WLAN_CIPHER_SUITE_GCMP_256:
+		case RSN_CIPHER_SUITE_GCMP_256:
 			info->capa->enc |= WPA_DRIVER_CAPA_ENC_GCMP_256;
 			break;
-		case WLAN_CIPHER_SUITE_CCMP:
+		case RSN_CIPHER_SUITE_CCMP:
 			info->capa->enc |= WPA_DRIVER_CAPA_ENC_CCMP;
 			break;
-		case WLAN_CIPHER_SUITE_GCMP:
+		case RSN_CIPHER_SUITE_GCMP:
 			info->capa->enc |= WPA_DRIVER_CAPA_ENC_GCMP;
 			break;
-		case WLAN_CIPHER_SUITE_TKIP:
+		case RSN_CIPHER_SUITE_TKIP:
 			info->capa->enc |= WPA_DRIVER_CAPA_ENC_TKIP;
 			break;
-		case WLAN_CIPHER_SUITE_WEP104:
+		case RSN_CIPHER_SUITE_WEP104:
 			info->capa->enc |= WPA_DRIVER_CAPA_ENC_WEP104;
 			break;
-		case WLAN_CIPHER_SUITE_WEP40:
+		case RSN_CIPHER_SUITE_WEP40:
 			info->capa->enc |= WPA_DRIVER_CAPA_ENC_WEP40;
 			break;
-		case WLAN_CIPHER_SUITE_AES_CMAC:
+		case RSN_CIPHER_SUITE_AES_128_CMAC:
 			info->capa->enc |= WPA_DRIVER_CAPA_ENC_BIP;
 			break;
-		case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+		case RSN_CIPHER_SUITE_BIP_GMAC_128:
 			info->capa->enc |= WPA_DRIVER_CAPA_ENC_BIP_GMAC_128;
 			break;
-		case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+		case RSN_CIPHER_SUITE_BIP_GMAC_256:
 			info->capa->enc |= WPA_DRIVER_CAPA_ENC_BIP_GMAC_256;
 			break;
-		case WLAN_CIPHER_SUITE_BIP_CMAC_256:
+		case RSN_CIPHER_SUITE_BIP_CMAC_256:
 			info->capa->enc |= WPA_DRIVER_CAPA_ENC_BIP_CMAC_256;
 			break;
-		case WLAN_CIPHER_SUITE_NO_GROUP_ADDR:
+		case RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED:
 			info->capa->enc |= WPA_DRIVER_CAPA_ENC_GTK_NOT_USED;
 			break;
 		}
diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
index de539b1..c18fc22 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -1,6 +1,6 @@
 /*
  * Driver interaction with Linux nl80211/cfg80211 - Event processing
- * Copyright (c) 2002-2014, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2017, Jouni Malinen <j@w1.fi>
  * Copyright (c) 2007, Johannes Berg <johannes@sipsolutions.net>
  * Copyright (c) 2009-2010, Atheros Communications
  *
@@ -1132,6 +1132,10 @@
 		[NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U8 },
 		[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 },
 		[NL80211_ATTR_CQM_PKT_LOSS_EVENT] = { .type = NLA_U32 },
+		[NL80211_ATTR_CQM_TXE_RATE] = { .type = NLA_U32 },
+		[NL80211_ATTR_CQM_TXE_PKTS] = { .type = NLA_U32 },
+		[NL80211_ATTR_CQM_TXE_INTVL] = { .type = NLA_U32 },
+		[NL80211_ATTR_CQM_BEACON_LOSS_EVENT] = { .type = NLA_FLAG },
 	};
 	struct nlattr *cqm[NL80211_ATTR_CQM_MAX + 1];
 	enum nl80211_cqm_rssi_threshold_event event;
@@ -1153,12 +1157,39 @@
 			return;
 		os_memcpy(ed.low_ack.addr, nla_data(tb[NL80211_ATTR_MAC]),
 			  ETH_ALEN);
+		ed.low_ack.num_packets =
+			nla_get_u32(cqm[NL80211_ATTR_CQM_PKT_LOSS_EVENT]);
+		wpa_printf(MSG_DEBUG, "nl80211: Packet loss event for " MACSTR
+			   " (num_packets %u)",
+			   MAC2STR(ed.low_ack.addr), ed.low_ack.num_packets);
 		wpa_supplicant_event(drv->ctx, EVENT_STATION_LOW_ACK, &ed);
 		return;
 	}
 
-	if (cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] == NULL)
+	if (cqm[NL80211_ATTR_CQM_BEACON_LOSS_EVENT]) {
+		wpa_printf(MSG_DEBUG, "nl80211: Beacon loss event");
+		wpa_supplicant_event(drv->ctx, EVENT_BEACON_LOSS, NULL);
 		return;
+	}
+
+	if (cqm[NL80211_ATTR_CQM_TXE_RATE] &&
+	    cqm[NL80211_ATTR_CQM_TXE_PKTS] &&
+	    cqm[NL80211_ATTR_CQM_TXE_INTVL] &&
+	    cqm[NL80211_ATTR_MAC]) {
+		wpa_printf(MSG_DEBUG, "nl80211: CQM TXE event for " MACSTR
+			   " (rate: %u pkts: %u interval: %u)",
+			   MAC2STR((u8 *) nla_data(cqm[NL80211_ATTR_MAC])),
+			   nla_get_u32(cqm[NL80211_ATTR_CQM_TXE_RATE]),
+			   nla_get_u32(cqm[NL80211_ATTR_CQM_TXE_PKTS]),
+			   nla_get_u32(cqm[NL80211_ATTR_CQM_TXE_INTVL]));
+		return;
+	}
+
+	if (cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] == NULL) {
+		wpa_printf(MSG_DEBUG,
+			   "nl80211: Not a CQM RSSI threshold event");
+		return;
+	}
 	event = nla_get_u32(cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT]);
 
 	if (event == NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH) {
@@ -1169,8 +1200,12 @@
 		wpa_printf(MSG_DEBUG, "nl80211: Connection quality monitor "
 			   "event: RSSI low");
 		ed.signal_change.above_threshold = 0;
-	} else
+	} else {
+		wpa_printf(MSG_DEBUG,
+			   "nl80211: Unknown CQM RSSI threshold event: %d",
+			   event);
 		return;
+	}
 
 	res = nl80211_get_link_signal(drv, &sig);
 	if (res == 0) {
diff --git a/src/drivers/driver_nl80211_scan.c b/src/drivers/driver_nl80211_scan.c
index 7dcfae2..b577531 100644
--- a/src/drivers/driver_nl80211_scan.c
+++ b/src/drivers/driver_nl80211_scan.c
@@ -156,10 +156,8 @@
 	wpa_printf(MSG_DEBUG, "nl80211: Scan timeout - try to abort it");
 #ifdef CONFIG_DRIVER_NL80211_QCA
 	if (drv->vendor_scan_cookie &&
-	    nl80211_abort_vendor_scan(drv, drv->vendor_scan_cookie) == 0) {
-		drv->vendor_scan_cookie = 0;
+	    nl80211_abort_vendor_scan(drv, drv->vendor_scan_cookie) == 0)
 		return;
-	}
 #endif /* CONFIG_DRIVER_NL80211_QCA */
 	if (!drv->vendor_scan_cookie &&
 	    nl80211_abort_scan(drv->first_bss) == 0)
diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c
index 791cd5d..458d458 100644
--- a/src/drivers/driver_wext.c
+++ b/src/drivers/driver_wext.c
@@ -1042,6 +1042,7 @@
 	wpa_driver_wext_set_auth_param(drv, IW_AUTH_WPA_ENABLED, 0);
 
 	eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv, drv->ctx);
+	eloop_cancel_timeout(wpa_driver_wext_send_rfkill, drv, drv->ctx);
 
 	/*
 	 * Clear possibly configured driver parameters in order to make it
diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h
index 259c9c7..174f4b3 100644
--- a/src/drivers/nl80211_copy.h
+++ b/src/drivers/nl80211_copy.h
@@ -323,7 +323,7 @@
  * @NL80211_CMD_GET_SCAN: get scan results
  * @NL80211_CMD_TRIGGER_SCAN: trigger a new scan with the given parameters
  *	%NL80211_ATTR_TX_NO_CCK_RATE is used to decide whether to send the
- *	probe requests at CCK rate or not. %NL80211_ATTR_MAC can be used to
+ *	probe requests at CCK rate or not. %NL80211_ATTR_BSSID can be used to
  *	specify a BSSID to scan for; if not included, the wildcard BSSID will
  *	be used.
  * @NL80211_CMD_NEW_SCAN_RESULTS: scan notification (as a reply to
@@ -1820,6 +1820,8 @@
  *	and remove functions. NAN notifications will be sent in unicast to that
  *	socket. Without this attribute, any socket can add functions and the
  *	notifications will be sent to the %NL80211_MCGRP_NAN multicast group.
+ *	If set during %NL80211_CMD_ASSOCIATE or %NL80211_CMD_CONNECT the
+ *	station will deauthenticate when the socket is closed.
  *
  * @NL80211_ATTR_TDLS_INITIATOR: flag attribute indicating the current end is
  *	the TDLS link initiator.
@@ -1977,6 +1979,9 @@
  * @NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED: Indicates whether or not multicast
  *	packets should be send out as unicast to all stations (flag attribute).
  *
+ * @NL80211_ATTR_BSSID: The BSSID of the AP. Note that %NL80211_ATTR_MAC is also
+ *	used in various commands/events for specifying the BSSID.
+ *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2381,6 +2386,8 @@
 
 	NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED,
 
+	NL80211_ATTR_BSSID,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -4959,8 +4966,9 @@
 /**
  * struct nl80211_bss_select_rssi_adjust - RSSI adjustment parameters.
  *
- * @band: band of BSS that must match for RSSI value adjustment.
- * @delta: value used to adjust the RSSI value of matching BSS.
+ * @band: band of BSS that must match for RSSI value adjustment. The value
+ *	of this field is according to &enum nl80211_band.
+ * @delta: value used to adjust the RSSI value of matching BSS in dB.
  */
 struct nl80211_bss_select_rssi_adjust {
 	__u8 band;
diff --git a/src/fst/fst_group.c b/src/fst/fst_group.c
index 321d40d..a4ae016 100644
--- a/src/fst/fst_group.c
+++ b/src/fst/fst_group.c
@@ -29,7 +29,7 @@
 		const struct multi_band_ie *mbie =
 			(const struct multi_band_ie *) p;
 		WPA_ASSERT(mbie->eid == WLAN_EID_MULTI_BAND);
-		WPA_ASSERT(2 + mbie->len >= sizeof(*mbie));
+		WPA_ASSERT(2U + mbie->len >= sizeof(*mbie));
 
 		fst_printf(MSG_WARNING,
 			   "%s: %s: mb_ctrl=%u band_id=%u op_class=%u chan=%u bssid="
diff --git a/src/fst/fst_iface.h b/src/fst/fst_iface.h
index 0eb2732..cbaa7d8 100644
--- a/src/fst/fst_iface.h
+++ b/src/fst/fst_iface.h
@@ -106,7 +106,7 @@
 					  const u8 *addr,
 					  const u8 *buf, size_t size)
 {
-	return i->iface_obj.update_mb_ie(i->iface_obj.ctx, addr, buf, size);
+	i->iface_obj.update_mb_ie(i->iface_obj.ctx, addr, buf, size);
 }
 
 static inline const u8 * fst_iface_get_peer_first(struct fst_iface *i,
diff --git a/src/fst/fst_session.c b/src/fst/fst_session.c
index 76e2c78..a02a93e 100644
--- a/src/fst/fst_session.c
+++ b/src/fst/fst_session.c
@@ -756,8 +756,6 @@
 	struct fst_session *s;
 	u32 id;
 
-	WPA_ASSERT(!is_zero_ether_addr(own_addr));
-
 	id = fst_find_free_session_id();
 	if (id == FST_INVALID_SESSION_ID) {
 		fst_printf(MSG_ERROR, "Cannot assign new session ID");
diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c
index f57311e..e4ac24f 100644
--- a/src/rsn_supp/tdls.c
+++ b/src/rsn_supp/tdls.c
@@ -1201,9 +1201,10 @@
 
 #ifdef CONFIG_TDLS_TESTING
 	if (tdls_testing & TDLS_TESTING_DIFF_BSSID) {
+		struct wpa_tdls_lnkid *l = (struct wpa_tdls_lnkid *) pos;
+
 		wpa_printf(MSG_DEBUG, "TDLS: Testing - use incorrect BSSID in "
 			   "Link Identifier");
-		struct wpa_tdls_lnkid *l = (struct wpa_tdls_lnkid *) pos;
 		wpa_tdls_linkid(sm, peer, l);
 		l->bssid[5] ^= 0x01;
 		pos += sizeof(*l);
diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index 365845f..696ea04 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -17,6 +17,7 @@
 #include "crypto/aes_siv.h"
 #include "common/ieee802_11_defs.h"
 #include "common/ieee802_11_common.h"
+#include "eap_common/eap_defs.h"
 #include "eapol_supp/eapol_supp_sm.h"
 #include "wpa.h"
 #include "eloop.h"
@@ -3302,12 +3303,19 @@
 	wpabuf_put_data(buf, sm->fils_session, FILS_SESSION_LEN);
 
 	/* FILS Wrapped Data */
+	sm->fils_erp_pmkid_set = 0;
 	if (erp_msg) {
 		wpabuf_put_u8(buf, WLAN_EID_EXTENSION); /* Element ID */
 		wpabuf_put_u8(buf, 1 + wpabuf_len(erp_msg)); /* Length */
 		/* Element ID Extension */
 		wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_WRAPPED_DATA);
 		wpabuf_put_buf(buf, erp_msg);
+		/* Calculate pending PMKID here so that we do not need to
+		 * maintain a copy of the EAP-Initiate/Reauth message. */
+		if (fils_pmkid_erp(sm->key_mgmt, wpabuf_head(erp_msg),
+				   wpabuf_len(erp_msg),
+				   sm->fils_erp_pmkid) == 0)
+			sm->fils_erp_pmkid_set = 1;
 	}
 
 	wpa_hexdump_buf(MSG_DEBUG, "RSN: FILS fields for Authentication frame",
@@ -3407,6 +3415,9 @@
 
 	/* FILS Wrapped Data */
 	if (!sm->cur_pmksa && elems.fils_wrapped_data) {
+		u8 rmsk[ERP_MAX_KEY_LEN];
+		size_t rmsk_len;
+
 		wpa_hexdump(MSG_DEBUG, "FILS: Wrapped Data",
 			    elems.fils_wrapped_data,
 			    elems.fils_wrapped_data_len);
@@ -3415,14 +3426,30 @@
 		if (eapol_sm_failed(sm->eapol))
 			return -1;
 
-		res = eapol_sm_get_key(sm->eapol, sm->pmk, PMK_LEN);
+		rmsk_len = ERP_MAX_KEY_LEN;
+		res = eapol_sm_get_key(sm->eapol, rmsk, rmsk_len);
+		if (res == PMK_LEN) {
+			rmsk_len = PMK_LEN;
+			res = eapol_sm_get_key(sm->eapol, rmsk, rmsk_len);
+		}
 		if (res)
 			return -1;
 
+		res = fils_rmsk_to_pmk(sm->key_mgmt, rmsk, rmsk_len,
+				       sm->fils_nonce, sm->fils_anonce, NULL, 0,
+				       sm->pmk, &sm->pmk_len);
+		os_memset(rmsk, 0, sizeof(rmsk));
+
+		if (!sm->fils_erp_pmkid_set) {
+			wpa_printf(MSG_DEBUG, "FILS: PMKID not available");
+			return -1;
+		}
+		wpa_hexdump(MSG_DEBUG, "FILS: PMKID", sm->fils_erp_pmkid,
+			    PMKID_LEN);
 		wpa_printf(MSG_DEBUG, "FILS: ERP processing succeeded - add PMKSA cache entry for the result");
-		sm->cur_pmksa = pmksa_cache_add(sm->pmksa, sm->pmk, PMK_LEN,
-						NULL, NULL, 0, sm->bssid,
-						sm->own_addr,
+		sm->cur_pmksa = pmksa_cache_add(sm->pmksa, sm->pmk, sm->pmk_len,
+						sm->fils_erp_pmkid, NULL, 0,
+						sm->bssid, sm->own_addr,
 						sm->network_ctx, sm->key_mgmt);
 	}
 
@@ -3456,11 +3483,18 @@
 
 struct wpabuf * fils_build_assoc_req(struct wpa_sm *sm, const u8 **kek,
 				     size_t *kek_len, const u8 **snonce,
-				     const u8 **anonce)
+				     const u8 **anonce,
+				     const struct wpabuf **hlp,
+				     unsigned int num_hlp)
 {
 	struct wpabuf *buf;
+	size_t len;
+	unsigned int i;
 
-	buf = wpabuf_alloc(1000);
+	len = 1000;
+	for (i = 0; hlp && i < num_hlp; i++)
+		len += 10 + wpabuf_len(hlp[i]);
+	buf = wpabuf_alloc(len);
 	if (!buf)
 		return NULL;
 
@@ -3483,7 +3517,34 @@
 	wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_KEY_CONFIRM);
 	wpabuf_put_data(buf, sm->fils_key_auth_sta, sm->fils_key_auth_len);
 
-	/* TODO: FILS HLP Container */
+	/* FILS HLP Container */
+	for (i = 0; hlp && i < num_hlp; i++) {
+		const u8 *pos = wpabuf_head(hlp[i]);
+		size_t left = wpabuf_len(hlp[i]);
+
+		wpabuf_put_u8(buf, WLAN_EID_EXTENSION); /* Element ID */
+		if (left <= 254)
+			len = 1 + left;
+		else
+			len = 255;
+		wpabuf_put_u8(buf, len); /* Length */
+		/* Element ID Extension */
+		wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_HLP_CONTAINER);
+		/* Destination MAC Address, Source MAC Address, HLP Packet.
+		 * HLP Packet is in MSDU format (i.e., included the LLC/SNAP
+		 * header when LPD is used). */
+		wpabuf_put_data(buf, pos, len - 1);
+		pos += len - 1;
+		left -= len - 1;
+		while (left) {
+			wpabuf_put_u8(buf, WLAN_EID_FRAGMENT);
+			len = left > 255 ? 255 : left;
+			wpabuf_put_u8(buf, len);
+			wpabuf_put_data(buf, pos, len);
+			pos += len;
+			left -= len;
+		}
+	}
 
 	/* TODO: FILS IP Address Assignment */
 
diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
index c9f278a..f0eeec8 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -436,7 +436,9 @@
 int fils_process_auth(struct wpa_sm *sm, const u8 *data, size_t len);
 struct wpabuf * fils_build_assoc_req(struct wpa_sm *sm, const u8 **kek,
 				     size_t *kek_len, const u8 **snonce,
-				     const u8 **anonce);
+				     const u8 **anonce,
+				     const struct wpabuf **hlp,
+				     unsigned int num_hlp);
 int fils_process_assoc_resp(struct wpa_sm *sm, const u8 *resp, size_t len);
 int wpa_fils_is_completed(struct wpa_sm *sm);
 
diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h
index 180d468..491fc98 100644
--- a/src/rsn_supp/wpa_i.h
+++ b/src/rsn_supp/wpa_i.h
@@ -147,6 +147,8 @@
 	u8 fils_key_auth_sta[FILS_MAX_KEY_AUTH_LEN];
 	size_t fils_key_auth_len;
 	unsigned int fils_completed:1;
+	unsigned int fils_erp_pmkid_set:1;
+	u8 fils_erp_pmkid[PMKID_LEN];
 #endif /* CONFIG_FILS */
 };
 
diff --git a/src/utils/os_unix.c b/src/utils/os_unix.c
index 65c6fa4..26fd172 100644
--- a/src/utils/os_unix.c
+++ b/src/utils/os_unix.c
@@ -80,6 +80,9 @@
 	struct timespec ts;
 	int res;
 
+	if (TEST_FAIL())
+		return -1;
+
 	while (1) {
 		res = clock_gettime(clock_id, &ts);
 		if (res == 0) {
diff --git a/src/utils/wpa_debug.c b/src/utils/wpa_debug.c
index f7acf6b..62758d8 100644
--- a/src/utils/wpa_debug.c
+++ b/src/utils/wpa_debug.c
@@ -13,7 +13,7 @@
 #ifdef CONFIG_DEBUG_SYSLOG
 #include <syslog.h>
 
-static int wpa_debug_syslog = 0;
+int wpa_debug_syslog = 0;
 #endif /* CONFIG_DEBUG_SYSLOG */
 
 #ifdef CONFIG_DEBUG_LINUX_TRACING
diff --git a/src/utils/wpa_debug.h b/src/utils/wpa_debug.h
index 17d8f96..1fe0b7d 100644
--- a/src/utils/wpa_debug.h
+++ b/src/utils/wpa_debug.h
@@ -14,6 +14,9 @@
 extern int wpa_debug_level;
 extern int wpa_debug_show_keys;
 extern int wpa_debug_timestamp;
+#ifdef CONFIG_DEBUG_SYSLOG
+extern int wpa_debug_syslog;
+#endif /* CONFIG_DEBUG_SYSLOG */
 
 /* Debugging function - conditional printf and hex dump. Driver wrappers can
  * use these for debugging purposes. */