[wpa_supplicant] Cumulative patch from 9fde14607

Changes include required updates to DPP R2.

Bug: 143479699
Test: Device boots up and connects to WPA3/OWE wifi networks, run traffic.
Test: Able to turn on/off softap, associate wifi STA, run traffic.
Test: Regression test Passed (Bug: 143485775)

9fde14607 Allow scans triggered by D-Bus to use MAC address randomization
10f8351d6 D-Bus: Add MAC address randomization endpoints
bb66d4675 Move ownership of MAC address randomization mask to scan params
6c2f70cc6 DPP: Mention ssid and pass parameters for DPP_AUTH_INIT in documentation
1030dec1f JSON: Fix escaping of characters that have MSB=1 with signed char
7800725af dbus: Export OWE capability and OWE BSS key_mgmt
b2ad4e6b2 D-Bus: Fix P2P NULL dereference after interface removal
937644aa2 nl80211: Indicate SUITE_B_192 capa only when CCMP-256/GCMP-256 supported
1b5865a53 SAE: Ignore commit message when waiting for confirm in STA mode
50a2c8c90 Do not indicate possible PSK failure when using SAE
df3b2e22a nl80211: Add STA node details in AP through QCA vendor subcommand
f273b2a5c Add QCA vendor cmd for setting BT coex chain mode
4dc860680 Extend QCA OEM data vendor subcmd to allow use as an event
93a1e275a SAE: Determine H2E vs. looping when restarting SAE auth in AP mode
de580bf6c crypto: Remove unused crypto_bignum_sqrtmod()
9b292a48f SAE: Drop sqrt() alternative from SSWU (H2E)
305369038 wpa_supplicant: Fix arithmetic on void pointer
00ddc1cc2 common: Fix same expression checked twice in fils_key_auth_sk()
327d09aa0 HE: Add 11ax info to ap mode ctrl iface STATUS command
d7678a084 Fix AP Extended Capability length determination
a592f2a9e P2P: Continue listening next request if no post-PD operations
a32acf391 Fix hostapd build with CONFIG_WPA_TRACE but no CONFIG_WPA_TRACE_BFD
b38c8c9cb dbus: Suppress to show NULL string
6807eee9c Interworking: Check NULL string to avoid compiler warning
ec1c0d154 Fix name of DBus interface in defconfig
f73dd0a69 FT-SAE: Add RSNXE into FT MIC
cb9925977 Add RSNXE into (Re)Association Response frames
865721c69 Merge wpa_supplicant and hostapd EAPOL-Key KDE parsers
898b6d58f SAE: Verify that STA negotiated H2E if it claims to support it
74866f537 RSN: Verify RSNXE match between (Re)AssocReq and EAPOL-Key msg 2/4
9981d5bf3 Add RSNXE into AP KDE parser
d3516cad7 Store a copy of Association Request RSNXE in AP mode for later use
6d6c88775 SAE: Add RSNXE in Association Request and EAPOL-Key msg 2/4
8401cdc8d Add RSNXE into IE parser
0b0ed907d WPS: Check SHA256 result success
8dda97c75 QCA vendor command for adding a STA node
b41dc61af Add a new QCA vendor attribute to carry device info for OEM data
bf185bfd5 QCA vendor attributes to indicate BW-based agile spectral capability
1317ea2c0 nl80211: Allow external auth based on SAE/FT-SAE key mgmt
cdb5774f4 FST: Update FST about MAC address change
49e95ee1e AP: Publish only HE capabilities and operation IEs on 6 GHz band
d7c2c5c98 AP: Add initial support for 6 GHz band
a5b2faa71 AP: Add op_class config item to specify 6 GHz channels uniquely
89450024a wpa_supplicant: Pass in operating class for channel validity checks
032c8264d SAE: Check that peer's rejected groups are not enabled in AP
a5dc2a5c1 SAE: H2E version of SAE commit message handling for AP
43b20b437 SAE: Derive H2E PT in AP when starting the AP
444d76f74 SAE: Check that peer's rejected groups are not enabled
cfe1ea5c9 SAE: H2E version of SAE commit message handling for STA
447cd5f2d SAE: Collect list of rejected groups for H2E in STA
05a2fb0d1 SAE: Derive H2E PT in STA before connection
146889e3c RSN: Verify RSNXE match between Beacon/ProbeResp and EAPOL-Key msg 3/4
3134bb13a SAE: Advertise Extended RSN Capabilities when H2E is enabled
293a01f3b SAE: Handle BSS membership selector indication for H2E-only in STA mode
cc0da0ff4 SAE: Advertise BSS membership selector for H2E-only case
85e64e634 SAE: Add sae_pwe configuration parameter for wpa_supplicant
a36e13a7c SAE: Add sae_pwe configuration parameter for hostapd
af4487148 tests: Module test for SAE hash-to-element crypto routines
cf84246eb SAE: Add Rejected Groups element into H2E Commit
efd428529 SAE: Hash algorithm selection for H2E KCK/CN()
aeb022f8e SAE: Implement hash-to-element PT/PWE crypto routines
ecd711407 SAE: Parse Rejected Groups element from H2E SAE commit
86f608486 SAE: Tell sae_parse_commit() whether H2E is used
316156739 SAE: H2E protocol defines
1766e608b wolfSSL: Fix crypto_bignum_sub()
2a1c84f4e crypto: Add more bignum/EC helper functions
9c08bfbd9 DPP: Fix confusing debug entry from Configurator
f7fe05522 SAE: Allow AP behavior for SAE Confirm to be configured
d6a7de60c wpa_cli: Clean up unnecessarily complex CONFIG_MESH use
8b426ab1e wpa_supplicant: Pass AP mode EDMG config to hostapd struct
a82aee1f4 wpa_supplicant: Add support for EDMG channels
35aed771f Indicate EDMG in scan results
f6f8c6ade AP: Show EDMG channel info in STATUS output
241dd76cf hostapd: Check EDMG configuration against capability
dc3457cc4 hostapd: Check usability of EDMG channel
bebd91e9c Add EDMG parameters to set_freq functions
fdd0fef2c EDMG: Helper functions for parameter encoding/checking
e8ff22f47 wpa_supplicant: Add EDMG channel configuration parameters
5c5ff22ef hostapd: Add EDMG channel configuration parameters
dda5d9e31 nl80211: Add support for EDMG channels
a19913c17 IEEE P802.11ay/D4.0 defines for EDMG
c34917403 MBO/OCE: Update disable_mbo_oce flag after association
b719a1568 DPP2: Parse AKM suite selector version of akm node
68fea9603 DPP2: Allow Configurator to use AKM suite selectors in Config Object
52d469de1 DPP2: Support multiple Config Objects in Enrollee
7eb06a336 DPP2: Allow multiple Config Objects to be build on Configurator
99918e069 DPP: Cleaned up netrole indication for config object building
e0d22c842 FILS+FT: Fix MFPR flag in RSNE during FILS exchange for FT
d0a4ed6a1 Allow SAE to be used in wpa_supplicant AP mode
7846e8d60 NetBSD: Fix compile
2e06cef80 MBO/OCE: Work around misbehaving MBO/OCE APs that use RSN without PMF
722c7d195 wlantest: Process VLAN tagged Data frames
83b83b461 nl80211: Migrate to current netlink key message format
7a4b01c87 AP: Provide correct keyid to wpa_send_eapol() for EAPOL-Key msg 3/4
a3ebf7175 BSD: Add support for route(4) message filtering
d9286d099 ACS: Stop before scan if no channels in chanlist are available
f32aa244e DPP: Debug print configRequest bandSupport on Configurator
8f8c423a5 DPP: Add bandSupport JSON array into config request
6d3dc9ba1 mka: Check OLPN for exhaustion on SAKuse decode
84851007d mka: Check OLPN for exhaustion on SAKuse encode
547ba732d mka: Clear out old/latest key values on CHANGE in CP state machine
536a7cfcf mka: Don't set newSAK to FALSE on ABANDON in CP state machine
0fedfba2e mka: Change RECEIVE and RETIRE states to match the standard
3f2641e7a Fix wpa_supplicant build with CONFIG_PCSC=y
5a5639b06 DPP: Allow name and mudurl to be configured for Config Request
3394def5a More consistent SA check for unexpected Data frames
16ef233bf DPP2: Connection status result (Enrollee)
b10e01a79 DPP2: Connection status result (Configurator)
e501a2eb5 DPP2: Connection status result defines
cc8399528 DPP2: Move dpp_build_conf_result() to be within ifdef block
3a6736fe8 DPP2: Fix a memory leak on error path for Config Result
21dc1627f wpa_supplicant: Don't return an error when successfully parsing WMM rules
8214b45ba P2P: Use latest BSS entry if multiple P2P Device Addr matches found
dc6c3be4e wpa_supplicant: Add support for 60 GHz band channels 5 and 6
018edec9b Remove IAPP functionality from hostapd
d86d66dc0 AP: Silently ignore management frame from unexpected source address
a84bf4438 HE: Send the AP's OBSS PD settings to the kernel
262b71eea Sync with mac80211-next.git include/uapi/linux/nl80211.h
8788a314d WPS: Update MAC address on address changes
39042d7f7 os_sleep: Use nanosleep for POSIX versions 2008 and higher
a69742c2f wpa_cli: Do not pick p2p-dev-* interfaces by default
d842e00bd SAE: Return result from confirm CN() operation to the caller
a8bfc6fff FILS: Update connect params after sending connection notification
0df82a3da Correct the type/usage of QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST
6bf6c6fec DPP: Fix hostapd build dependencies for DPP-only build
1eff2e7bf DPP2: Fix wpa_supplicant build dependencies for CONFIG_AP=y build
d2bae5763 DPP: Fix wpa_supplicant build dependencies for DPP-only build
7d2ed8bae Remove CONFIG_IEEE80211W build parameter
022926187 DFS offload: Fix hostapd state and CAC info in STATUS output
4d78ba990 EAP-TEAP peer: Clear Phase 2 EAP method on new Identity exchange
681618246 EAP-TEAP peer: Add support for machine credentials using certificates
ebee8232d Do not try to include net/ethernet.h in MinGW/Windows builds
bf15b1559 Fix Windows error code definition workaround
043de65f1 EAP peer config: Move ocsp param to phase1/phase2
8d76e0ad7 EAP server: Configurable maximum number of authentication message rounds
b99c4cadb EAP peer: Move certificate configuration params into shared struct
6e711e7ab mesh: Do not enable HE on 5 GHz without VHT
0497e4148 HE: Fix HE Capabilities element size
a2e0cc9e0 Add nl80211 vendor ACS trigger reasons related to interference
69e8e7817 HS 2.0: Do not add two copies of OSEN element into Beacon/Probe Resp
a762ba8b1 HS 2.0 AP: Do not mandate PMF for HS 2.0 Indication in open OSU network
e49ce2990 IEEE 802.1X authenticator: Coding style cleanup
31aaddc90 Clean up IEEE 802.1X authentication debug messages for EAP code
71419119f EAP-TEAP peer: Fix protected indication of inner EAP method failure
93cd29d2b EAP-TEAP server: Add support for requiring user and machine credentials
c38c62ff7 wlantest: Derive PMK-R1 and PTK for FT protocol cases
c41936566 EAP-TEAP peer: Add support for machine authentication
c724a0a16 EAP peer: Add a concept of a separate machine credential
9ce3bfaf4 RADIUS server: Abort startup on allocation failures
fa1f0751c RADIUS server: Use struct eap_config to avoid duplicated definitions
a00cb1b1f EAP-TEAP server: Fix eap_teap_pac_no_inner configuration
986033ff3 EAP-TEAP server: Fix Crypto-Binding check in PAC no-inner-auth case
e54cfbb56 EAP-TEAP server: Allow a specific Identity-Type to be requested/required
f186ec54c EAP-TEAP peer: Support Identity-Type TLV
cc661c160 EAP-TEAP: Add parsing and generation routines for Identity-Type TLV
100b2edb2 OpenSSL: Write peer certificate chain details in debug log
7eb157f1e EAP: Increase the maximum number of message exchanges
822e7c66a EAP server: Use struct eap_config to avoid duplicated definitions
62af2b18f EAP-TEAP peer: Support vendor EAP method in Phase 2
aba8dc82f EAP-PEAP server: Support vendor EAP types in Phase 2
357c1062d EAP-FAST peer: Support vendor EAP method in Phase 2
f32f76231 EAP-FAST server: Support vendor EAP types in Phase 2
887d8703b EAP-PEAP peer: Support vendor EAP method in Phase 2
f2ef4f255 EAP peer: Allow VENDOR-TEST method in Phase 2
5ddbd9e96 EAP-TTLS peer: Support vendor EAP method in Phase 2
5e94e7f23 EAP-TTLS server: Support vendor EAP types in Phase 2
5f2301a6d Replace EapType typedef with enum eap_type
76ddfae6e EAP-TEAP server: Testing mechanism for Result TLV in a separate message
4c327146f EAP-TEAP peer: Allow Result TLV without Crypto-Binding TLV
128d46be9 EAP-TEAP: Add parsing of Error TLV
234489efd EAP-TEAP server: Require Intermediate-Result TLV even with Result TLV
0f7c91f2b EAP-TEAP peer: Add Intermediate-Result TLV with Crypto-Binding TLV
a66e53c41 EAP-TEAP: Fix TLS-PRF for TLS ciphersuites that use SHA384
52069c7ef Add TLS-PRF using HMAC with P_SHA384 for TEAP
a647a0ad7 Extend server certificate TOD policy reporting to include TOD-TOFU
346d10cf8 SAE: Conditionally set PMKID while notifying the external auth status
b7cd64876 SAE: Use BSSID stored in ext_auth_bssid for set_pmk
e0b331d89 OWE: Update connect params with new DH attributes to the driver
c574a3ff1 nl80211: Request update connection params only for drivers with SME
528f263c4 FT: Reject over-the-DS response with MFPC=0 if PMF is required
ae05b6a21 RSN: Do not allow connection to proceed without MFPC=1 if PMF required
ded56f2fa FT: Fix MFPR flag in RSNE during FT protocol
0028d627c OCE: Mandate PMF for WPA2 association with OCE AP
84ebc759a HS 2.0: Match credentials based on required_roaming_consortium
d2b208384 SAE: Allow PMKID to be added into Association Request frame following SAE
2ca23faf1 Make wpa_insert_pmkid() more generic
05822609d HE: MCS size is always a minimum of 4 bytes
df4f95998 nl80211: Don't force VHT channel definition with HE
dd0153fce Check for LEAP before doing FT
6126e5f97 Fix a typo in hostapd config documentation
698a0067c Fix check_crl_strict documentation
485dd425b Add QCA vendor command for avoid frequency feature
6ae1247bf Update QCA vendor attributes for 6 GHz band support
aa23ece3d Add QCA vendor channel attribute to restart AP
85508ecf6 Add QCA vendor command to configure ACS policy
2395fdb67 Add QCA vendor attributes to enhance roaming configuration
1425caac2 Rename qca_wlan_vendor_attr_roam_subcmd to represent subcmds
f13119631 Document the attributes used by QCA_NL80211_VENDOR_SUBCMD_ROAM
b0b25c5bb Clear external eapSuccess setting in driver-authorized cases
fa1d5ec18 The master branch is now used for v2.10 development
ca8c2bd28 Preparations for v2.8 release
3263fca28 Set the default scan IEs on interface restart
d776bf8c6 EAP-TEAP peer: Fix fragmentation of final message
1c7e61a35 wolfssl: Avoid void pointer arithmetic
7122a02fa SAE: Fix order_len for FFC groups
422e73d62 DPP: Indicate authentication success on ConfReqRX if needed
d001fe31a OpenSSL: Handle EVP_PKEY_derive() secret_len changes for ECDH
29ef1c5ee DPP: Use a common helper function for ECDH operations
ac734a342 SAE: Fix KCK, PMK, and PMKID derivation for groups 22, 23, 24
c65168ccd OpenSSL: Fix crypto_bignum_to_bin() with padlen == 0
cb28bd52e nl80211: Use separate flag for 4-way handshake offload
6bb11c7a4 EAP-SIM/AKA server: Allow pseudonym/fast reauth to be disabled
c1b236521 EAP-SIM/AKA: Do not allow anonymous@realm "pseudonym" to be cleared
cc2fd9425 D-Bus: Demote timeout/flush messages to MSG_MSGDUMP
3b726df82 nl80211: Missing sysctl flags aren't fatal
f4111ff3d Extra RADIUS request attributes from SQLite
74707def8 Move hostapd_parse_radius_attr() into ap_config.c
1e5ea68d1 mka: Accept last two used MNs in Peers List of a received MKPDU
013686403 P2P: Pass HE flag to GO negotiation result
876c5eaa6 dragonfly: Disable use of groups using Brainpool curves
968520da8 nl80211: Add WMM parameters while updating TDLS peer entry
5a511924b wpa_cli: Add support to process DPP action events in action script
64e37be94 Avoid nested enum wpas_mode declaration to allow C++ compilation
fe2e1edf4 EAP-SIM server: Avoid void pointer arithmetic
cfc9ebea0 EAP-AKA server: Avoid void pointer arithmetic
bd0414043 trace: Avoid void pointer arithmetic
fc03ea2c1 DPP: Avoid void pointer arithmetic
d1b1f9fa9 Report WPA/RSN protocol and AKM suite selector in STA MIB
43aafef8d Add missed wpa_akm_to_suite() selectors
bfb6a482f dragonfly: SAE/EAP-pwd min PWE derivation iteration count to shared code
226da33d7 EAP-pwd peer: Configurable set of groups with reduced default
6a4406c01 Add QCA vendor attributes for ELNA bypass
176c133e9 Add a vendor attribute to configure disconnect IEs
123895228 Add QCA vendor command to support OEM data

Change-Id: Iaa497edcda7c5dcdad19db9d09ab09ef74e508bd
diff --git a/src/ap/Makefile b/src/ap/Makefile
index 48f8f23..54e48a0 100644
--- a/src/ap/Makefile
+++ b/src/ap/Makefile
@@ -15,11 +15,9 @@
 CFLAGS += -DCONFIG_INTERWORKING
 CFLAGS += -DCONFIG_IEEE80211R
 CFLAGS += -DCONFIG_IEEE80211R_AP
-CFLAGS += -DCONFIG_IEEE80211W
 CFLAGS += -DCONFIG_WPS
 CFLAGS += -DCONFIG_PROXYARP
 CFLAGS += -DCONFIG_IPV6
-CFLAGS += -DCONFIG_IAPP
 CFLAGS += -DCONFIG_AIRTIME_POLICY
 
 LIB_OBJS= \
@@ -42,7 +40,6 @@
 	hostapd.o \
 	hs20.o \
 	hw_features.o \
-	iapp.o \
 	ieee802_11_auth.o \
 	ieee802_11.o \
 	ieee802_11_ht.o \
diff --git a/src/ap/accounting.c b/src/ap/accounting.c
index 0aacc3c..9fc1886 100644
--- a/src/ap/accounting.c
+++ b/src/ap/accounting.c
@@ -97,6 +97,9 @@
 				   msg) < 0)
 		goto fail;
 
+	if (sta && add_sqlite_radius_attr(hapd, sta, msg, 1) < 0)
+		goto fail;
+
 	if (sta) {
 		for (i = 0; ; i++) {
 			val = ieee802_1x_get_radius_class(sta->eapol_sm, &len,
diff --git a/src/ap/acs.c b/src/ap/acs.c
index 11178a1..f12539f 100644
--- a/src/ap/acs.c
+++ b/src/ap/acs.c
@@ -942,6 +942,12 @@
 	}
 	*freq = 0;
 
+	if (params.freqs == freq) {
+		wpa_printf(MSG_ERROR, "ACS: No available channels found");
+		os_free(params.freqs);
+		return -1;
+	}
+
 	iface->scan_cb = acs_scan_complete;
 
 	wpa_printf(MSG_DEBUG, "ACS: Scanning %d / %d",
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index a061bd8..58fc3e9 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -16,6 +16,7 @@
 #include "common/ieee802_1x_defs.h"
 #include "common/eapol_common.h"
 #include "common/dhcp.h"
+#include "common/sae.h"
 #include "eap_common/eap_wsc_common.h"
 #include "eap_server/eap.h"
 #include "wpa_auth.h"
@@ -78,6 +79,7 @@
 
 	bss->radius_server_auth_port = 1812;
 	bss->eap_sim_db_timeout = 1;
+	bss->eap_sim_id = 3;
 	bss->ap_max_inactivity = AP_MAX_INACTIVITY;
 	bss->eapol_version = EAPOL_VERSION;
 
@@ -85,11 +87,9 @@
 
 	bss->pwd_group = 19; /* ECC: GF(p=256) */
 
-#ifdef CONFIG_IEEE80211W
 	bss->assoc_sa_query_max_timeout = 1000;
 	bss->assoc_sa_query_retry_timeout = 201;
 	bss->group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC;
-#endif /* CONFIG_IEEE80211W */
 #ifdef EAP_SERVER_FAST
 	 /* both anonymous and authenticated provisioning */
 	bss->eap_fast_prov = 3;
@@ -134,6 +134,9 @@
 	 * completed and tested with other implementations. */
 	bss->tls_flags = TLS_CONN_DISABLE_TLSv1_3;
 
+	bss->max_auth_rounds = 100;
+	bss->max_auth_rounds_short = 50;
+
 	bss->send_probe_response = 1;
 
 #ifdef CONFIG_HS20
@@ -432,10 +435,50 @@
 }
 
 
+int hostapd_setup_sae_pt(struct hostapd_bss_config *conf)
+{
+#ifdef CONFIG_SAE
+	struct hostapd_ssid *ssid = &conf->ssid;
+	struct sae_password_entry *pw;
+
+	if (conf->sae_pwe == 0)
+		return 0; /* PT not needed */
+
+	sae_deinit_pt(ssid->pt);
+	ssid->pt = NULL;
+	if (ssid->wpa_passphrase) {
+		ssid->pt = sae_derive_pt(conf->sae_groups, ssid->ssid,
+					 ssid->ssid_len,
+					 (const u8 *) ssid->wpa_passphrase,
+					 os_strlen(ssid->wpa_passphrase),
+					 NULL);
+		if (!ssid->pt)
+			return -1;
+	}
+
+	for (pw = conf->sae_passwords; pw; pw = pw->next) {
+		sae_deinit_pt(pw->pt);
+		pw->pt = sae_derive_pt(conf->sae_groups, ssid->ssid,
+				       ssid->ssid_len,
+				       (const u8 *) pw->password,
+				       os_strlen(pw->password),
+				       pw->identifier);
+		if (!pw->pt)
+			return -1;
+	}
+#endif /* CONFIG_SAE */
+
+	return 0;
+}
+
+
 int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf)
 {
 	struct hostapd_ssid *ssid = &conf->ssid;
 
+	if (hostapd_setup_sae_pt(conf) < 0)
+		return -1;
+
 	if (ssid->wpa_passphrase != NULL) {
 		if (ssid->wpa_psk != NULL) {
 			wpa_printf(MSG_DEBUG, "Using pre-configured WPA PSK "
@@ -476,7 +519,76 @@
 }
 
 
-static void hostapd_config_free_radius_attr(struct hostapd_radius_attr *attr)
+struct hostapd_radius_attr * hostapd_parse_radius_attr(const char *value)
+{
+	const char *pos;
+	char syntax;
+	struct hostapd_radius_attr *attr;
+	size_t len;
+
+	attr = os_zalloc(sizeof(*attr));
+	if (!attr)
+		return NULL;
+
+	attr->type = atoi(value);
+
+	pos = os_strchr(value, ':');
+	if (!pos) {
+		attr->val = wpabuf_alloc(1);
+		if (!attr->val) {
+			os_free(attr);
+			return NULL;
+		}
+		wpabuf_put_u8(attr->val, 0);
+		return attr;
+	}
+
+	pos++;
+	if (pos[0] == '\0' || pos[1] != ':') {
+		os_free(attr);
+		return NULL;
+	}
+	syntax = *pos++;
+	pos++;
+
+	switch (syntax) {
+	case 's':
+		attr->val = wpabuf_alloc_copy(pos, os_strlen(pos));
+		break;
+	case 'x':
+		len = os_strlen(pos);
+		if (len & 1)
+			break;
+		len /= 2;
+		attr->val = wpabuf_alloc(len);
+		if (!attr->val)
+			break;
+		if (hexstr2bin(pos, wpabuf_put(attr->val, len), len) < 0) {
+			wpabuf_free(attr->val);
+			os_free(attr);
+			return NULL;
+		}
+		break;
+	case 'd':
+		attr->val = wpabuf_alloc(4);
+		if (attr->val)
+			wpabuf_put_be32(attr->val, atoi(pos));
+		break;
+	default:
+		os_free(attr);
+		return NULL;
+	}
+
+	if (!attr->val) {
+		os_free(attr);
+		return NULL;
+	}
+
+	return attr;
+}
+
+
+void hostapd_config_free_radius_attr(struct hostapd_radius_attr *attr)
 {
 	struct hostapd_radius_attr *prev;
 
@@ -572,6 +684,9 @@
 		pw = pw->next;
 		str_clear_free(tmp->password);
 		os_free(tmp->identifier);
+#ifdef CONFIG_SAE
+		sae_deinit_pt(tmp->pt);
+#endif /* CONFIG_SAE */
 		os_free(tmp);
 	}
 }
@@ -608,6 +723,9 @@
 #ifdef CONFIG_FULL_DYNAMIC_VLAN
 	os_free(conf->ssid.vlan_tagged_interface);
 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
+#ifdef CONFIG_SAE
+	sae_deinit_pt(conf->ssid.pt);
+#endif /* CONFIG_SAE */
 
 	hostapd_config_free_eap_users(conf->eap_user);
 	os_free(conf->eap_user_sqlite);
@@ -625,6 +743,7 @@
 	}
 	hostapd_config_free_radius_attr(conf->radius_auth_req_attr);
 	hostapd_config_free_radius_attr(conf->radius_acct_req_attr);
+	os_free(conf->radius_req_attr_sqlite);
 	os_free(conf->rsn_preauth_interfaces);
 	os_free(conf->ctrl_interface);
 	os_free(conf->ca_cert);
@@ -769,6 +888,8 @@
 	hostapd_config_free_fils_realms(conf);
 
 #ifdef CONFIG_DPP
+	os_free(conf->dpp_name);
+	os_free(conf->dpp_mud_url);
 	os_free(conf->dpp_connector);
 	wpabuf_free(conf->dpp_netaccesskey);
 	wpabuf_free(conf->dpp_csign);
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index eebf898..2a0c984 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -99,6 +99,7 @@
 	struct hostapd_wpa_psk *wpa_psk;
 	char *wpa_passphrase;
 	char *wpa_psk_file;
+	struct sae_pt *pt;
 
 	struct hostapd_wep_keys wep;
 
@@ -251,6 +252,7 @@
 	char *identifier;
 	u8 peer_addr[ETH_ALEN];
 	int vlan_id;
+	struct sae_pt *pt;
 };
 
 struct dpp_controller_conf {
@@ -301,6 +303,7 @@
 	int radius_request_cui;
 	struct hostapd_radius_attr *radius_auth_req_attr;
 	struct hostapd_radius_attr *radius_acct_req_attr;
+	char *radius_req_attr_sqlite;
 	int radius_das_port;
 	unsigned int radius_das_time_window;
 	int radius_das_require_event_timestamp;
@@ -324,10 +327,6 @@
 	int erp_send_reauth_start;
 	char *erp_domain;
 
-	int ieee802_11f; /* use IEEE 802.11f (IAPP) */
-	char iapp_iface[IFNAMSIZ + 1]; /* interface used with IAPP broadcast
-					* frames */
-
 	enum macaddr_acl {
 		ACCEPT_UNLESS_DENIED = 0,
 		DENY_UNLESS_ACCEPTED = 1,
@@ -346,14 +345,12 @@
 
 	int wpa; /* bitfield of WPA_PROTO_WPA, WPA_PROTO_RSN */
 	int wpa_key_mgmt;
-#ifdef CONFIG_IEEE80211W
 	enum mfp_options ieee80211w;
 	int group_mgmt_cipher;
 	/* dot11AssociationSAQueryMaximumTimeout (in TUs) */
 	unsigned int assoc_sa_query_max_timeout;
 	/* dot11AssociationSAQueryRetryTimeout (in TUs) */
 	int assoc_sa_query_retry_timeout;
-#endif /* CONFIG_IEEE80211W */
 #ifdef CONFIG_OCV
 	int ocv; /* Operating Channel Validation */
 #endif /* CONFIG_OCV */
@@ -414,6 +411,8 @@
 	unsigned int crl_reload_interval;
 	unsigned int tls_session_lifetime;
 	unsigned int tls_flags;
+	unsigned int max_auth_rounds;
+	unsigned int max_auth_rounds_short;
 	char *ocsp_stapling_response;
 	char *ocsp_stapling_response_multi;
 	char *dh_file;
@@ -428,7 +427,10 @@
 	int pac_key_refresh_time;
 	int eap_teap_auth;
 	int eap_teap_pac_no_inner;
+	int eap_teap_separate_result;
+	int eap_teap_id;
 	int eap_sim_aka_result_ind;
+	int eap_sim_id;
 	int tnc;
 	int fragment_size;
 	u16 pwd_group;
@@ -649,6 +651,8 @@
 	unsigned int sae_anti_clogging_threshold;
 	unsigned int sae_sync;
 	int sae_require_mfp;
+	int sae_confirm_immediate;
+	int sae_pwe;
 	int *sae_groups;
 	struct sae_password_entry *sae_passwords;
 
@@ -707,6 +711,8 @@
 	int broadcast_deauth;
 
 #ifdef CONFIG_DPP
+	char *dpp_name;
+	char *dpp_mud_url;
 	char *dpp_connector;
 	struct wpabuf *dpp_netaccesskey;
 	unsigned int dpp_netaccesskey_expiry;
@@ -869,7 +875,10 @@
 	u16 beacon_int;
 	int rts_threshold;
 	int fragm_threshold;
+	u8 op_class;
 	u8 channel;
+	int enable_edmg;
+	u8 edmg_channel;
 	u8 acs;
 	struct wpa_freq_range_list acs_ch_list;
 	int acs_exclude_dfs;
@@ -1074,6 +1083,7 @@
 int hostapd_mac_comp(const void *a, const void *b);
 struct hostapd_config * hostapd_config_defaults(void);
 void hostapd_config_defaults_bss(struct hostapd_bss_config *bss);
+void hostapd_config_free_radius_attr(struct hostapd_radius_attr *attr);
 void hostapd_config_free_eap_user(struct hostapd_eap_user *user);
 void hostapd_config_free_eap_users(struct hostapd_eap_user *user);
 void hostapd_config_clear_wpa_psk(struct hostapd_wpa_psk **p);
@@ -1092,9 +1102,11 @@
 					int vlan_id);
 struct hostapd_radius_attr *
 hostapd_config_get_radius_attr(struct hostapd_radius_attr *attr, u8 type);
+struct hostapd_radius_attr * hostapd_parse_radius_attr(const char *value);
 int hostapd_config_check(struct hostapd_config *conf, int full_config);
 void hostapd_set_security_params(struct hostapd_bss_config *bss,
 				 int full_config);
 int hostapd_sae_pw_id_in_use(struct hostapd_bss_config *conf);
+int hostapd_setup_sae_pt(struct hostapd_bss_config *conf);
 
 #endif /* HOSTAPD_CONFIG_H */
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index c0ededa..204274f 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -107,6 +107,10 @@
 		goto fail;
 #endif /* CONFIG_FILS */
 
+	pos = hostapd_eid_rsnxe(hapd, buf, sizeof(buf));
+	if (add_buf_data(&assocresp, buf, pos - buf) < 0)
+		goto fail;
+
 	if (add_buf(&beacon, hapd->wps_beacon_ie) < 0 ||
 	    add_buf(&proberesp, hapd->wps_probe_resp_ie) < 0)
 		goto fail;
@@ -305,9 +309,7 @@
 			params.wpa_pairwise = hapd->conf->wpa_pairwise;
 		params.wpa_key_mgmt = hapd->conf->wpa_key_mgmt;
 		params.rsn_preauth = hapd->conf->rsn_preauth;
-#ifdef CONFIG_IEEE80211W
 		params.ieee80211w = hapd->conf->ieee80211w;
-#endif /* CONFIG_IEEE80211W */
 	}
 	return hostapd_set_ieee8021x(hapd, &params);
 }
@@ -348,7 +350,7 @@
 			 u16 auth_alg)
 {
 	if (hapd->driver == NULL || hapd->driver->add_sta_node == NULL)
-		return 0;
+		return -EOPNOTSUPP;
 	return hapd->driver->add_sta_node(hapd->drv_priv, addr, auth_alg);
 }
 
@@ -540,7 +542,8 @@
 
 
 int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode,
-		     int freq, int channel, int ht_enabled, int vht_enabled,
+		     int freq, int channel, int edmg, u8 edmg_channel,
+		     int ht_enabled, int vht_enabled,
 		     int he_enabled,
 		     int sec_channel_offset, int oper_chwidth,
 		     int center_segment0, int center_segment1)
@@ -548,7 +551,8 @@
 	struct hostapd_freq_params data;
 	struct hostapd_hw_modes *cmode = hapd->iface->current_mode;
 
-	if (hostapd_set_freq_params(&data, mode, freq, channel, ht_enabled,
+	if (hostapd_set_freq_params(&data, mode, freq, channel, edmg,
+				    edmg_channel, ht_enabled,
 				    vht_enabled, he_enabled, sec_channel_offset,
 				    oper_chwidth,
 				    center_segment0, center_segment1,
@@ -810,7 +814,8 @@
 		return -1;
 	}
 
-	if (hostapd_set_freq_params(&data, mode, freq, channel, ht_enabled,
+	if (hostapd_set_freq_params(&data, mode, freq, channel, 0, 0,
+				    ht_enabled,
 				    vht_enabled, he_enabled, sec_channel_offset,
 				    oper_chwidth, center_segment0,
 				    center_segment1,
diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
index ca7f7ab..79b1302 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -62,7 +62,8 @@
 		       const u8 *addr, int idx, u8 *seq);
 int hostapd_flush(struct hostapd_data *hapd);
 int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode,
-		     int freq, int channel, int ht_enabled, int vht_enabled,
+		     int freq, int channel, int edmg, u8 edmg_channel,
+		     int ht_enabled, int vht_enabled,
 		     int he_enabled, int sec_channel_offset, int oper_chwidth,
 		     int center_segment0, int center_segment1);
 int hostapd_set_rts(struct hostapd_data *hapd, int rts);
diff --git a/src/ap/authsrv.c b/src/ap/authsrv.c
index b3d9107..8e12daf 100644
--- a/src/ap/authsrv.c
+++ b/src/ap/authsrv.c
@@ -110,27 +110,10 @@
 	srv.auth_port = conf->radius_server_auth_port;
 	srv.acct_port = conf->radius_server_acct_port;
 	srv.conf_ctx = hapd;
-	srv.eap_sim_db_priv = hapd->eap_sim_db_priv;
-	srv.ssl_ctx = hapd->ssl_ctx;
-	srv.msg_ctx = hapd->msg_ctx;
-	srv.pac_opaque_encr_key = conf->pac_opaque_encr_key;
-	srv.eap_fast_a_id = conf->eap_fast_a_id;
-	srv.eap_fast_a_id_len = conf->eap_fast_a_id_len;
-	srv.eap_fast_a_id_info = conf->eap_fast_a_id_info;
-	srv.eap_fast_prov = conf->eap_fast_prov;
-	srv.pac_key_lifetime = conf->pac_key_lifetime;
-	srv.pac_key_refresh_time = conf->pac_key_refresh_time;
-	srv.eap_teap_auth = conf->eap_teap_auth;
-	srv.eap_teap_pac_no_inner = conf->eap_teap_pac_no_inner;
-	srv.eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind;
-	srv.tnc = conf->tnc;
-	srv.wps = hapd->wps;
 	srv.ipv6 = conf->radius_server_ipv6;
 	srv.get_eap_user = hostapd_radius_get_eap_user;
 	srv.eap_req_id_text = conf->eap_req_id_text;
 	srv.eap_req_id_text_len = conf->eap_req_id_text_len;
-	srv.pwd_group = conf->pwd_group;
-	srv.server_id = conf->server_id ? conf->server_id : "hostapd";
 	srv.sqlite_file = conf->eap_user_sqlite;
 #ifdef CONFIG_RADIUS_TEST
 	srv.dump_msk_file = conf->dump_msk_file;
@@ -141,10 +124,8 @@
 	srv.hs20_sim_provisioning_url = conf->hs20_sim_provisioning_url;
 	srv.t_c_server_url = conf->t_c_server_url;
 #endif /* CONFIG_HS20 */
-	srv.erp = conf->eap_server_erp;
 	srv.erp_domain = conf->erp_domain;
-	srv.tls_session_lifetime = conf->tls_session_lifetime;
-	srv.tls_flags = conf->tls_flags;
+	srv.eap_cfg = hapd->eap_cfg;
 
 	hapd->radius_srv = radius_server_init(&srv);
 	if (hapd->radius_srv == NULL) {
@@ -192,6 +173,60 @@
 #endif /* EAP_TLS_FUNCS */
 
 
+static struct eap_config * authsrv_eap_config(struct hostapd_data *hapd)
+{
+	struct eap_config *cfg;
+
+	cfg = os_zalloc(sizeof(*cfg));
+	if (!cfg)
+		return NULL;
+
+	cfg->eap_server = hapd->conf->eap_server;
+	cfg->ssl_ctx = hapd->ssl_ctx;
+	cfg->msg_ctx = hapd->msg_ctx;
+	cfg->eap_sim_db_priv = hapd->eap_sim_db_priv;
+	cfg->tls_session_lifetime = hapd->conf->tls_session_lifetime;
+	cfg->tls_flags = hapd->conf->tls_flags;
+	cfg->max_auth_rounds = hapd->conf->max_auth_rounds;
+	cfg->max_auth_rounds_short = hapd->conf->max_auth_rounds_short;
+	if (hapd->conf->pac_opaque_encr_key)
+		cfg->pac_opaque_encr_key =
+			os_memdup(hapd->conf->pac_opaque_encr_key, 16);
+	if (hapd->conf->eap_fast_a_id) {
+		cfg->eap_fast_a_id = os_memdup(hapd->conf->eap_fast_a_id,
+					       hapd->conf->eap_fast_a_id_len);
+		cfg->eap_fast_a_id_len = hapd->conf->eap_fast_a_id_len;
+	}
+	if (hapd->conf->eap_fast_a_id_info)
+		cfg->eap_fast_a_id_info =
+			os_strdup(hapd->conf->eap_fast_a_id_info);
+	cfg->eap_fast_prov = hapd->conf->eap_fast_prov;
+	cfg->pac_key_lifetime = hapd->conf->pac_key_lifetime;
+	cfg->pac_key_refresh_time = hapd->conf->pac_key_refresh_time;
+	cfg->eap_teap_auth = hapd->conf->eap_teap_auth;
+	cfg->eap_teap_pac_no_inner = hapd->conf->eap_teap_pac_no_inner;
+	cfg->eap_teap_separate_result = hapd->conf->eap_teap_separate_result;
+	cfg->eap_teap_id = hapd->conf->eap_teap_id;
+	cfg->eap_sim_aka_result_ind = hapd->conf->eap_sim_aka_result_ind;
+	cfg->eap_sim_id = hapd->conf->eap_sim_id;
+	cfg->tnc = hapd->conf->tnc;
+	cfg->wps = hapd->wps;
+	cfg->fragment_size = hapd->conf->fragment_size;
+	cfg->pwd_group = hapd->conf->pwd_group;
+	cfg->pbc_in_m1 = hapd->conf->pbc_in_m1;
+	if (hapd->conf->server_id) {
+		cfg->server_id = (u8 *) os_strdup(hapd->conf->server_id);
+		cfg->server_id_len = os_strlen(hapd->conf->server_id);
+	} else {
+		cfg->server_id = (u8 *) os_strdup("hostapd");
+		cfg->server_id_len = 7;
+	}
+	cfg->erp = hapd->conf->eap_server_erp;
+
+	return cfg;
+}
+
+
 int authsrv_init(struct hostapd_data *hapd)
 {
 #ifdef EAP_TLS_FUNCS
@@ -272,6 +307,14 @@
 	}
 #endif /* EAP_SIM_DB */
 
+	hapd->eap_cfg = authsrv_eap_config(hapd);
+	if (!hapd->eap_cfg) {
+		wpa_printf(MSG_ERROR,
+			   "Failed to build EAP server configuration");
+		authsrv_deinit(hapd);
+		return -1;
+	}
+
 #ifdef RADIUS_SERVER
 	if (hapd->conf->radius_server_clients &&
 	    hostapd_setup_radius_srv(hapd))
@@ -302,4 +345,7 @@
 		hapd->eap_sim_db_priv = NULL;
 	}
 #endif /* EAP_SIM_DB */
+
+	eap_server_config_free(hapd->eap_cfg);
+	hapd->eap_cfg = NULL;
 }
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index a51b949..331c09b 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -456,7 +456,8 @@
 	pos = hostapd_eid_ext_supp_rates(hapd, pos);
 
 	/* RSN, MDIE */
-	if (hapd->conf->wpa != WPA_PROTO_WPA)
+	if (!(hapd->conf->wpa == WPA_PROTO_WPA ||
+	      (hapd->conf->osen && !hapd->conf->wpa)))
 		pos = hostapd_eid_wpa(hapd, pos, epos - pos);
 
 	pos = hostapd_eid_bss_load(hapd, pos, epos - pos);
@@ -498,7 +499,8 @@
 #endif /* CONFIG_FST */
 
 #ifdef CONFIG_IEEE80211AC
-	if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) {
+	if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac &&
+	    !is_6ghz_op_class(hapd->iconf->op_class)) {
 		pos = hostapd_eid_vht_capabilities(hapd, pos, 0);
 		pos = hostapd_eid_vht_operation(hapd, pos);
 		pos = hostapd_eid_txpower_envelope(hapd, pos);
@@ -523,7 +525,8 @@
 #endif /* CONFIG_IEEE80211AC */
 
 	/* WPA */
-	if (hapd->conf->wpa == WPA_PROTO_WPA)
+	if (hapd->conf->wpa == WPA_PROTO_WPA ||
+	    (hapd->conf->osen && !hapd->conf->wpa))
 		pos = hostapd_eid_wpa(hapd, pos, epos - pos);
 
 	/* Wi-Fi Alliance WMM */
@@ -553,7 +556,6 @@
 
 #ifdef CONFIG_HS20
 	pos = hostapd_eid_hs20_indication(hapd, pos);
-	pos = hostapd_eid_osen(hapd, pos);
 #endif /* CONFIG_HS20 */
 
 	pos = hostapd_eid_mbo(hapd, pos, (u8 *) resp + buflen - pos);
@@ -1164,7 +1166,8 @@
 	tailpos = hostapd_eid_ext_supp_rates(hapd, tailpos);
 
 	/* RSN, MDIE */
-	if (hapd->conf->wpa != WPA_PROTO_WPA)
+	if (!(hapd->conf->wpa == WPA_PROTO_WPA ||
+	      (hapd->conf->osen && !hapd->conf->wpa)))
 		tailpos = hostapd_eid_wpa(hapd, tailpos,
 					  tail + BEACON_TAIL_BUF_SIZE -
 					  tailpos);
@@ -1240,7 +1243,8 @@
 #endif /* CONFIG_IEEE80211AC */
 
 	/* WPA */
-	if (hapd->conf->wpa == WPA_PROTO_WPA)
+	if (hapd->conf->wpa == WPA_PROTO_WPA ||
+	    (hapd->conf->osen && !hapd->conf->wpa))
 		tailpos = hostapd_eid_wpa(hapd, tailpos,
 					  tail + BEACON_TAIL_BUF_SIZE -
 					  tailpos);
@@ -1271,7 +1275,6 @@
 
 #ifdef CONFIG_HS20
 	tailpos = hostapd_eid_hs20_indication(hapd, tailpos);
-	tailpos = hostapd_eid_osen(hapd, tailpos);
 #endif /* CONFIG_HS20 */
 
 	tailpos = hostapd_eid_mbo(hapd, tailpos, tail + tail_len - tailpos);
@@ -1421,11 +1424,19 @@
 	params.proberesp_ies = proberesp;
 	params.assocresp_ies = assocresp;
 	params.reenable = hapd->reenable_beacon;
+#ifdef CONFIG_IEEE80211AX
+	params.he_spr = !!hapd->iface->conf->spr.sr_control;
+	params.he_spr_srg_obss_pd_min_offset =
+		hapd->iface->conf->spr.srg_obss_pd_min_offset;
+	params.he_spr_srg_obss_pd_max_offset =
+		hapd->iface->conf->spr.srg_obss_pd_max_offset;
+#endif /* CONFIG_IEEE80211AX */
 	hapd->reenable_beacon = 0;
 
 	if (cmode &&
 	    hostapd_set_freq_params(&freq, iconf->hw_mode, iface->freq,
-				    iconf->channel, iconf->ieee80211n,
+				    iconf->channel, iconf->enable_edmg,
+				    iconf->edmg_channel, iconf->ieee80211n,
 				    iconf->ieee80211ac, iconf->ieee80211ax,
 				    iconf->secondary_channel,
 				    hostapd_get_oper_chwidth(iconf),
diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
index 2c4953d..bde61ee 100644
--- a/src/ap/ctrl_iface_ap.c
+++ b/src/ap/ctrl_iface_ap.c
@@ -709,6 +709,8 @@
 
 	ret = os_snprintf(buf + len, buflen - len,
 			  "channel=%u\n"
+			  "edmg_enable=%d\n"
+			  "edmg_channel=%d\n"
 			  "secondary_channel=%d\n"
 			  "ieee80211n=%d\n"
 			  "ieee80211ac=%d\n"
@@ -716,6 +718,8 @@
 			  "beacon_int=%u\n"
 			  "dtim_period=%d\n",
 			  iface->conf->channel,
+			  iface->conf->enable_edmg,
+			  iface->conf->edmg_channel,
 			  iface->conf->ieee80211n && !hapd->conf->disable_11n ?
 			  iface->conf->secondary_channel : 0,
 			  iface->conf->ieee80211n && !hapd->conf->disable_11n,
@@ -727,6 +731,22 @@
 	if (os_snprintf_error(buflen - len, ret))
 		return len;
 	len += ret;
+
+#ifdef CONFIG_IEEE80211AX
+	if (iface->conf->ieee80211ax) {
+		ret = os_snprintf(buf + len, buflen - len,
+				  "he_oper_chwidth=%d\n"
+				  "he_oper_centr_freq_seg0_idx=%d\n"
+				  "he_oper_centr_freq_seg1_idx=%d\n",
+				  iface->conf->he_oper_chwidth,
+				  iface->conf->he_oper_centr_freq_seg0_idx,
+				  iface->conf->he_oper_centr_freq_seg1_idx);
+		if (os_snprintf_error(buflen - len, ret))
+			return len;
+		len += ret;
+	}
+#endif /* CONFIG_IEEE80211AX */
+
 	if (iface->conf->ieee80211ac && !hapd->conf->disable_11ac) {
 		ret = os_snprintf(buf + len, buflen - len,
 				  "vht_oper_chwidth=%d\n"
diff --git a/src/ap/dfs.c b/src/ap/dfs.c
index ac23c2b..c4c00fc 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -960,6 +960,8 @@
 				      iface->conf->hw_mode,
 				      channel->freq,
 				      channel->chan,
+				      iface->conf->enable_edmg,
+				      iface->conf->edmg_channel,
 				      iface->conf->ieee80211n,
 				      iface->conf->ieee80211ac,
 				      iface->conf->ieee80211ax,
@@ -1093,11 +1095,18 @@
 			  int ht_enabled, int chan_offset, int chan_width,
 			  int cf1, int cf2)
 {
+	/* This is called when the driver indicates that an offloaded DFS has
+	 * started CAC. */
+	hostapd_set_state(iface, HAPD_IFACE_DFS);
+	/* TODO: How to check CAC time for ETSI weather channels? */
+	iface->dfs_cac_ms = 60000;
 	wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_START
 		"freq=%d chan=%d chan_offset=%d width=%d seg0=%d "
 		"seg1=%d cac_time=%ds",
-		freq, (freq - 5000) / 5, chan_offset, chan_width, cf1, cf2, 60);
+		freq, (freq - 5000) / 5, chan_offset, chan_width, cf1, cf2,
+		iface->dfs_cac_ms / 1000);
 	iface->cac_started = 1;
+	os_get_reltime(&iface->dfs_cac_start);
 	return 0;
 }
 
diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c
index 697c3ba..085d423 100644
--- a/src/ap/dpp_hostapd.c
+++ b/src/ap/dpp_hostapd.c
@@ -607,47 +607,48 @@
 
 
 static void hostapd_dpp_handle_config_obj(struct hostapd_data *hapd,
-					  struct dpp_authentication *auth)
+					  struct dpp_authentication *auth,
+					  struct dpp_config_obj *conf)
 {
 	wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
 	wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_AKM "%s",
-		dpp_akm_str(auth->akm));
-	if (auth->ssid_len)
+		dpp_akm_str(conf->akm));
+	if (conf->ssid_len)
 		wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s",
-			wpa_ssid_txt(auth->ssid, auth->ssid_len));
-	if (auth->connector) {
+			wpa_ssid_txt(conf->ssid, conf->ssid_len));
+	if (conf->connector) {
 		/* TODO: Save the Connector and consider using a command
 		 * to fetch the value instead of sending an event with
 		 * it. The Connector could end up being larger than what
 		 * most clients are ready to receive as an event
 		 * message. */
 		wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
-			auth->connector);
-	} else if (auth->passphrase[0]) {
+			conf->connector);
+	} else if (conf->passphrase[0]) {
 		char hex[64 * 2 + 1];
 
 		wpa_snprintf_hex(hex, sizeof(hex),
-				 (const u8 *) auth->passphrase,
-				 os_strlen(auth->passphrase));
+				 (const u8 *) conf->passphrase,
+				 os_strlen(conf->passphrase));
 		wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_PASS "%s",
 			hex);
-	} else if (auth->psk_set) {
+	} else if (conf->psk_set) {
 		char hex[PMK_LEN * 2 + 1];
 
-		wpa_snprintf_hex(hex, sizeof(hex), auth->psk, PMK_LEN);
+		wpa_snprintf_hex(hex, sizeof(hex), conf->psk, PMK_LEN);
 		wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_PSK "%s",
 			hex);
 	}
-	if (auth->c_sign_key) {
+	if (conf->c_sign_key) {
 		char *hex;
 		size_t hexlen;
 
-		hexlen = 2 * wpabuf_len(auth->c_sign_key) + 1;
+		hexlen = 2 * wpabuf_len(conf->c_sign_key) + 1;
 		hex = os_malloc(hexlen);
 		if (hex) {
 			wpa_snprintf_hex(hex, hexlen,
-					 wpabuf_head(auth->c_sign_key),
-					 wpabuf_len(auth->c_sign_key));
+					 wpabuf_head(conf->c_sign_key),
+					 wpabuf_len(conf->c_sign_key));
 			wpa_msg(hapd->msg_ctx, MSG_INFO,
 				DPP_EVENT_C_SIGN_KEY "%s", hex);
 			os_free(hex);
@@ -720,7 +721,7 @@
 		goto fail;
 	}
 
-	hostapd_dpp_handle_config_obj(hapd, auth);
+	hostapd_dpp_handle_config_obj(hapd, auth, &auth->conf_obj[0]);
 	status = DPP_STATUS_OK;
 #ifdef CONFIG_TESTING_OPTIONS
 	if (dpp_test == DPP_TEST_REJECT_CONFIG) {
@@ -765,18 +766,10 @@
 {
 	struct dpp_authentication *auth = hapd->dpp_auth;
 	struct wpabuf *buf;
-	char json[100];
 	int res;
-	int netrole_ap = 1;
 
-	os_snprintf(json, sizeof(json),
-		    "{\"name\":\"Test\","
-		    "\"wi-fi_tech\":\"infra\","
-		    "\"netRole\":\"%s\"}",
-		    netrole_ap ? "ap" : "sta");
-	wpa_printf(MSG_DEBUG, "DPP: GAS Config Attributes: %s", json);
-
-	buf = dpp_build_conf_req(auth, json);
+	buf = dpp_build_conf_req_helper(auth, hapd->conf->dpp_name, 1,
+					hapd->conf->dpp_mud_url, NULL);
 	if (!buf) {
 		wpa_printf(MSG_DEBUG,
 			   "DPP: No configuration request data available");
@@ -922,6 +915,24 @@
 }
 
 
+static void hostapd_dpp_conn_status_result_wait_timeout(void *eloop_ctx,
+							void *timeout_ctx)
+{
+	struct hostapd_data *hapd = eloop_ctx;
+	struct dpp_authentication *auth = hapd->dpp_auth;
+
+	if (!auth || !auth->waiting_conf_result)
+		return;
+
+	wpa_printf(MSG_DEBUG,
+		   "DPP: Timeout while waiting for Connection Status Result");
+	wpa_msg(hapd->msg_ctx, MSG_INFO,
+		DPP_EVENT_CONN_STATUS_RESULT "timeout");
+	dpp_auth_deinit(auth);
+	hapd->dpp_auth = NULL;
+}
+
+
 static void hostapd_dpp_rx_conf_result(struct hostapd_data *hapd, const u8 *src,
 				       const u8 *hdr, const u8 *buf, size_t len)
 {
@@ -945,6 +956,20 @@
 
 	status = dpp_conf_result_rx(auth, hdr, buf, len);
 
+	if (status == DPP_STATUS_OK && auth->send_conn_status) {
+		wpa_msg(hapd->msg_ctx, MSG_INFO,
+			DPP_EVENT_CONF_SENT "wait_conn_status=1");
+		wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
+		eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout,
+				     hapd, NULL);
+		eloop_cancel_timeout(
+			hostapd_dpp_conn_status_result_wait_timeout,
+			hapd, NULL);
+		eloop_register_timeout(
+			16, 0, hostapd_dpp_conn_status_result_wait_timeout,
+			hapd, NULL);
+		return;
+	}
 	hostapd_drv_send_action_cancel_wait(hapd);
 	hostapd_dpp_listen_stop(hapd);
 	if (status == DPP_STATUS_OK)
@@ -957,6 +982,41 @@
 			     NULL);
 }
 
+
+static void hostapd_dpp_rx_conn_status_result(struct hostapd_data *hapd,
+					      const u8 *src, const u8 *hdr,
+					      const u8 *buf, size_t len)
+{
+	struct dpp_authentication *auth = hapd->dpp_auth;
+	enum dpp_status_error status;
+	u8 ssid[SSID_MAX_LEN];
+	size_t ssid_len = 0;
+	char *channel_list = NULL;
+
+	wpa_printf(MSG_DEBUG, "DPP: Connection Status Result");
+
+	if (!auth || !auth->waiting_conn_status_result) {
+		wpa_printf(MSG_DEBUG,
+			   "DPP: No DPP Configuration waiting for connection status result - drop");
+		return;
+	}
+
+	status = dpp_conn_status_result_rx(auth, hdr, buf, len,
+					   ssid, &ssid_len, &channel_list);
+	wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT
+		"result=%d ssid=%s channel_list=%s",
+		status, wpa_ssid_txt(ssid, ssid_len),
+		channel_list ? channel_list : "N/A");
+	os_free(channel_list);
+	hostapd_drv_send_action_cancel_wait(hapd);
+	hostapd_dpp_listen_stop(hapd);
+	dpp_auth_deinit(auth);
+	hapd->dpp_auth = NULL;
+	eloop_cancel_timeout(hostapd_dpp_conn_status_result_wait_timeout,
+			     hapd, NULL);
+}
+
+
 #endif /* CONFIG_DPP2 */
 
 
@@ -1403,6 +1463,9 @@
 	case DPP_PA_CONFIGURATION_RESULT:
 		hostapd_dpp_rx_conf_result(hapd, src, hdr, buf, len);
 		break;
+	case DPP_PA_CONNECTION_STATUS_RESULT:
+		hostapd_dpp_rx_conn_status_result(hapd, src, hdr, buf, len);
+		break;
 #endif /* CONFIG_DPP2 */
 	default:
 		wpa_printf(MSG_DEBUG,
@@ -1506,7 +1569,7 @@
 	if (dpp_set_configurator(hapd->iface->interfaces->dpp, hapd->msg_ctx,
 				 auth, cmd) == 0 &&
 	    dpp_configurator_own_config(auth, curve, 1) == 0) {
-		hostapd_dpp_handle_config_obj(hapd, auth);
+		hostapd_dpp_handle_config_obj(hapd, auth, &auth->conf_obj[0]);
 		ret = 0;
 	}
 
@@ -1715,6 +1778,8 @@
 #ifdef CONFIG_DPP2
 	eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout, hapd,
 			     NULL);
+	eloop_cancel_timeout(hostapd_dpp_conn_status_result_wait_timeout, hapd,
+			     NULL);
 #endif /* CONFIG_DPP2 */
 	dpp_auth_deinit(hapd->dpp_auth);
 	hapd->dpp_auth = NULL;
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index 3158768..3198bd5 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -16,6 +16,7 @@
 #include "common/ieee802_11_common.h"
 #include "common/wpa_ctrl.h"
 #include "common/dpp.h"
+#include "common/sae.h"
 #include "crypto/random.h"
 #include "p2p/p2p.h"
 #include "wps/wps.h"
@@ -111,10 +112,8 @@
 	struct ieee802_11_elems elems;
 	const u8 *ie;
 	size_t ielen;
-#if defined(CONFIG_IEEE80211R_AP) || defined(CONFIG_IEEE80211W) || defined(CONFIG_FILS) || defined(CONFIG_OWE)
 	u8 buf[sizeof(struct ieee80211_mgmt) + 1024];
 	u8 *p = buf;
-#endif /* CONFIG_IEEE80211R_AP || CONFIG_IEEE80211W || CONFIG_FILS || CONFIG_OWE */
 	u16 reason = WLAN_REASON_UNSPECIFIED;
 	u16 status = WLAN_STATUS_SUCCESS;
 	const u8 *p2p_dev_addr = NULL;
@@ -131,6 +130,19 @@
 			   "hostapd_notif_assoc: Skip event with no address");
 		return -1;
 	}
+
+	if (is_multicast_ether_addr(addr) ||
+	    is_zero_ether_addr(addr) ||
+	    os_memcmp(addr, hapd->own_addr, ETH_ALEN) == 0) {
+		/* Do not process any frames with unexpected/invalid SA so that
+		 * we do not add any state for unexpected STA addresses or end
+		 * up sending out frames to unexpected destination. */
+		wpa_printf(MSG_DEBUG, "%s: Invalid SA=" MACSTR
+			   " in received indication - ignore this indication silently",
+			   __func__, MAC2STR(addr));
+		return 0;
+	}
+
 	random_add_randomness(addr, ETH_ALEN);
 
 	hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
@@ -308,6 +320,8 @@
 		res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
 					  hapd->iface->freq,
 					  ie, ielen,
+					  elems.rsnxe ? elems.rsnxe - 2 : NULL,
+					  elems.rsnxe ? elems.rsnxe_len + 2 : 0,
 					  elems.mdie, elems.mdie_len,
 					  elems.owe_dh, elems.owe_dh_len);
 		if (res != WPA_IE_OK) {
@@ -324,23 +338,19 @@
 			} else if (res == WPA_INVALID_AKMP) {
 				reason = WLAN_REASON_AKMP_NOT_VALID;
 				status = WLAN_STATUS_AKMP_NOT_VALID;
-			}
-#ifdef CONFIG_IEEE80211W
-			else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION) {
+			} else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION) {
 				reason = WLAN_REASON_INVALID_IE;
 				status = WLAN_STATUS_INVALID_IE;
 			} else if (res == WPA_INVALID_MGMT_GROUP_CIPHER) {
 				reason = WLAN_REASON_CIPHER_SUITE_REJECTED;
 				status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
-			}
-#endif /* CONFIG_IEEE80211W */
-			else {
+			} else {
 				reason = WLAN_REASON_INVALID_IE;
 				status = WLAN_STATUS_INVALID_IE;
 			}
 			goto fail;
 		}
-#ifdef CONFIG_IEEE80211W
+
 		if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_MFP)) ==
 		    (WLAN_STA_ASSOC | WLAN_STA_MFP) &&
 		    !sta->sa_query_timed_out &&
@@ -373,7 +383,6 @@
 			sta->flags |= WLAN_STA_MFP;
 		else
 			sta->flags &= ~WLAN_STA_MFP;
-#endif /* CONFIG_IEEE80211W */
 
 #ifdef CONFIG_IEEE80211R_AP
 		if (sta->auth_alg == WLAN_AUTH_FT) {
@@ -390,6 +399,20 @@
 			}
 		}
 #endif /* CONFIG_IEEE80211R_AP */
+#ifdef CONFIG_SAE
+		if (hapd->conf->sae_pwe == 2 &&
+		    sta->auth_alg == WLAN_AUTH_SAE &&
+		    sta->sae && sta->sae->tmp && !sta->sae->tmp->h2e &&
+		    elems.rsnxe && elems.rsnxe_len >= 1 &&
+		    (elems.rsnxe[0] & BIT(WLAN_RSNX_CAPAB_SAE_H2E))) {
+			wpa_printf(MSG_INFO, "SAE: " MACSTR
+				   " indicates support for SAE H2E, but did not use it",
+				   MAC2STR(sta->addr));
+			status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+			reason = WLAN_REASON_UNSPECIFIED;
+			goto fail;
+		}
+#endif /* CONFIG_SAE */
 	} else if (hapd->conf->wps_state) {
 #ifdef CONFIG_WPS
 		struct wpabuf *wps;
@@ -1164,12 +1187,10 @@
 		return;
 	}
 #endif /* CONFIG_IEEE80211R_AP */
-#ifdef CONFIG_IEEE80211W
 	if (mgmt->u.action.category == WLAN_ACTION_SA_QUERY) {
 		ieee802_11_sa_query_action(hapd, mgmt, drv_mgmt->frame_len);
 		return;
 	}
-#endif /* CONFIG_IEEE80211W */
 #ifdef CONFIG_WNM_AP
 	if (mgmt->u.action.category == WLAN_ACTION_WNM) {
 		ieee802_11_rx_wnm_action_ap(hapd, mgmt, drv_mgmt->frame_len);
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index cc75a77..3686438 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -7,6 +7,9 @@
  */
 
 #include "utils/includes.h"
+#ifdef CONFIG_SQLITE
+#include <sqlite3.h>
+#endif /* CONFIG_SQLITE */
 
 #include "utils/common.h"
 #include "utils/eloop.h"
@@ -25,7 +28,6 @@
 #include "accounting.h"
 #include "ap_list.h"
 #include "beacon.h"
-#include "iapp.h"
 #include "ieee802_1x.h"
 #include "ieee802_11_auth.h"
 #include "vlan_init.h"
@@ -296,7 +298,6 @@
 				   ifname, i);
 		}
 	}
-#ifdef CONFIG_IEEE80211W
 	if (hapd->conf->ieee80211w) {
 		for (i = NUM_WEP_KEYS; i < NUM_WEP_KEYS + 2; i++) {
 			if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_NONE,
@@ -308,7 +309,6 @@
 			}
 		}
 	}
-#endif /* CONFIG_IEEE80211W */
 }
 
 
@@ -360,8 +360,6 @@
 	hapd->beacon_set_done = 0;
 
 	wpa_printf(MSG_DEBUG, "%s(%s)", __func__, hapd->conf->iface);
-	iapp_deinit(hapd->iapp);
-	hapd->iapp = NULL;
 	accounting_deinit(hapd);
 	hostapd_deinit_wpa(hapd);
 	vlan_deinit(hapd);
@@ -1025,6 +1023,43 @@
 #define hostapd_das_coa NULL
 #endif /* CONFIG_HS20 */
 
+
+#ifdef CONFIG_SQLITE
+
+static int db_table_exists(sqlite3 *db, const char *name)
+{
+	char cmd[128];
+
+	os_snprintf(cmd, sizeof(cmd), "SELECT 1 FROM %s;", name);
+	return sqlite3_exec(db, cmd, NULL, NULL, NULL) == SQLITE_OK;
+}
+
+
+static int db_table_create_radius_attributes(sqlite3 *db)
+{
+	char *err = NULL;
+	const char *sql =
+		"CREATE TABLE radius_attributes("
+		" id INTEGER PRIMARY KEY,"
+		" sta TEXT,"
+		" reqtype TEXT,"
+		" attr TEXT"
+		");"
+		"CREATE INDEX idx_sta_reqtype ON radius_attributes(sta,reqtype);";
+
+	wpa_printf(MSG_DEBUG,
+		   "Adding database table for RADIUS attribute information");
+	if (sqlite3_exec(db, sql, NULL, NULL, &err) != SQLITE_OK) {
+		wpa_printf(MSG_ERROR, "SQLite error: %s", err);
+		sqlite3_free(err);
+		return -1;
+	}
+
+	return 0;
+}
+
+#endif /* CONFIG_SQLITE */
+
 #endif /* CONFIG_NO_RADIUS */
 
 
@@ -1178,6 +1213,24 @@
 	if (wpa_debug_level <= MSG_MSGDUMP)
 		conf->radius->msg_dumps = 1;
 #ifndef CONFIG_NO_RADIUS
+
+#ifdef CONFIG_SQLITE
+	if (conf->radius_req_attr_sqlite) {
+		if (sqlite3_open(conf->radius_req_attr_sqlite,
+				 &hapd->rad_attr_db)) {
+			wpa_printf(MSG_ERROR, "Could not open SQLite file '%s'",
+				   conf->radius_req_attr_sqlite);
+			return -1;
+		}
+
+		wpa_printf(MSG_DEBUG, "Opening RADIUS attribute database: %s",
+			   conf->radius_req_attr_sqlite);
+		if (!db_table_exists(hapd->rad_attr_db, "radius_attributes") &&
+		    db_table_create_radius_attributes(hapd->rad_attr_db) < 0)
+			return -1;
+	}
+#endif /* CONFIG_SQLITE */
+
 	hapd->radius = radius_client_init(hapd, conf->radius);
 	if (hapd->radius == NULL) {
 		wpa_printf(MSG_ERROR, "RADIUS client initialization failed.");
@@ -1240,13 +1293,6 @@
 		return -1;
 	}
 
-	if (conf->ieee802_11f &&
-	    (hapd->iapp = iapp_init(hapd, conf->iapp_iface)) == NULL) {
-		wpa_printf(MSG_ERROR, "IEEE 802.11F (IAPP) initialization "
-			   "failed.");
-		return -1;
-	}
-
 #ifdef CONFIG_INTERWORKING
 	if (gas_serv_init(hapd)) {
 		wpa_printf(MSG_ERROR, "GAS server initialization failed");
@@ -1544,6 +1590,9 @@
 			wpa_printf(MSG_DEBUG, "Interface initialization will be completed in a callback (ACS)");
 			return 0;
 		}
+		ret = hostapd_check_edmg_capab(iface);
+		if (ret < 0)
+			goto fail;
 		ret = hostapd_check_ht_capab(iface);
 		if (ret < 0)
 			goto fail;
@@ -1868,6 +1917,8 @@
 		if (!delay_apply_cfg &&
 		    hostapd_set_freq(hapd, hapd->iconf->hw_mode, iface->freq,
 				     hapd->iconf->channel,
+				     hapd->iconf->enable_edmg,
+				     hapd->iconf->edmg_channel,
 				     hapd->iconf->ieee80211n,
 				     hapd->iconf->ieee80211ac,
 				     hapd->iconf->ieee80211ax,
@@ -2194,6 +2245,12 @@
 		   hapd->conf ? hapd->conf->iface : "N/A");
 	hostapd_bss_deinit_no_free(hapd);
 	wpa_msg(hapd->msg_ctx, MSG_INFO, AP_EVENT_DISABLED);
+#ifdef CONFIG_SQLITE
+	if (hapd->rad_attr_db) {
+		sqlite3_close(hapd->rad_attr_db);
+		hapd->rad_attr_db = NULL;
+	}
+#endif /* CONFIG_SQLITE */
 	hostapd_cleanup(hapd);
 }
 
@@ -2994,10 +3051,6 @@
 	hostapd_prune_associations(hapd, sta->addr);
 	ap_sta_clear_disconnect_timeouts(hapd, sta);
 
-	/* IEEE 802.11F (IAPP) */
-	if (hapd->conf->ieee802_11f)
-		iapp_new_station(hapd->iapp, sta);
-
 #ifdef CONFIG_P2P
 	if (sta->p2p_ie == NULL && !sta->no_p2p_set) {
 		sta->no_p2p_set = 1;
@@ -3234,7 +3287,8 @@
 	if (old_params &&
 	    hostapd_set_freq_params(old_params, conf->hw_mode,
 				    hostapd_hw_get_freq(hapd, conf->channel),
-				    conf->channel, conf->ieee80211n,
+				    conf->channel, conf->enable_edmg,
+				    conf->edmg_channel, conf->ieee80211n,
 				    conf->ieee80211ac, conf->ieee80211ax,
 				    conf->secondary_channel,
 				    hostapd_get_oper_chwidth(conf),
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index 44ef753..016fe3b 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -9,6 +9,10 @@
 #ifndef HOSTAPD_H
 #define HOSTAPD_H
 
+#ifdef CONFIG_SQLITE
+#include <sqlite3.h>
+#endif /* CONFIG_SQLITE */
+
 #include "common/defs.h"
 #include "utils/list.h"
 #include "ap_config.h"
@@ -175,13 +179,12 @@
 	u64 acct_session_id;
 	struct radius_das_data *radius_das;
 
-	struct iapp_data *iapp;
-
 	struct hostapd_cached_radius_acl *acl_cache;
 	struct hostapd_acl_query_data *acl_queries;
 
 	struct wpa_authenticator *wpa_auth;
 	struct eapol_authenticator *eapol_auth;
+	struct eap_config *eap_cfg;
 
 	struct rsn_preauth_interface *preauth_iface;
 	struct os_reltime michael_mic_failure;
@@ -333,12 +336,10 @@
 	u8 last_gtk[WPA_GTK_MAX_LEN];
 	size_t last_gtk_len;
 
-#ifdef CONFIG_IEEE80211W
 	enum wpa_alg last_igtk_alg;
 	int last_igtk_key_idx;
 	u8 last_igtk[WPA_IGTK_MAX_LEN];
 	size_t last_igtk_len;
-#endif /* CONFIG_IEEE80211W */
 #endif /* CONFIG_TESTING_OPTIONS */
 
 #ifdef CONFIG_MBO
@@ -390,6 +391,10 @@
 #endif /* CONFIG_AIRTIME_POLICY */
 
 	u8 last_1x_eapol_key_replay_counter[8];
+
+#ifdef CONFIG_SQLITE
+	sqlite3 *rad_attr_db;
+#endif /* CONFIG_SQLITE */
 };
 
 
diff --git a/src/ap/hs20.c b/src/ap/hs20.c
index 532580e..543fa33 100644
--- a/src/ap/hs20.c
+++ b/src/ap/hs20.c
@@ -80,13 +80,11 @@
 		/* 4 PTKSA replay counters when using WMM */
 		capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2);
 	}
-#ifdef CONFIG_IEEE80211W
 	if (hapd->conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
 		capab |= WPA_CAPABILITY_MFPC;
 		if (hapd->conf->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED)
 			capab |= WPA_CAPABILITY_MFPR;
 	}
-#endif /* CONFIG_IEEE80211W */
 #ifdef CONFIG_OCV
 	if (hapd->conf->ocv)
 		capab |= WPA_CAPABILITY_OCVC;
diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
index c1f19e2..2fefaf8 100644
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -704,6 +704,32 @@
 }
 
 
+int hostapd_check_edmg_capab(struct hostapd_iface *iface)
+{
+	struct hostapd_hw_modes *mode = iface->hw_features;
+	struct ieee80211_edmg_config edmg;
+
+	if (!iface->conf->enable_edmg)
+		return 0;
+
+	hostapd_encode_edmg_chan(iface->conf->enable_edmg,
+				 iface->conf->edmg_channel,
+				 iface->conf->channel,
+				 &edmg);
+
+	if (mode->edmg.channels && ieee802_edmg_is_allowed(mode->edmg, edmg))
+		return 0;
+
+	wpa_printf(MSG_WARNING, "Requested EDMG configuration is not valid");
+	wpa_printf(MSG_INFO, "EDMG capab: channels 0x%x, bw_config %d",
+		   mode->edmg.channels, mode->edmg.bw_config);
+	wpa_printf(MSG_INFO,
+		   "Requested EDMG configuration: channels 0x%x, bw_config %d",
+		   edmg.channels, edmg.bw_config);
+	return -1;
+}
+
+
 static int hostapd_is_usable_chan(struct hostapd_iface *iface,
 				  int channel, int primary)
 {
@@ -730,6 +756,67 @@
 }
 
 
+static int hostapd_is_usable_edmg(struct hostapd_iface *iface)
+{
+	int i, contiguous = 0;
+	int num_of_enabled = 0;
+	int max_contiguous = 0;
+	struct ieee80211_edmg_config edmg;
+
+	if (!iface->conf->enable_edmg)
+		return 1;
+
+	hostapd_encode_edmg_chan(iface->conf->enable_edmg,
+				 iface->conf->edmg_channel,
+				 iface->conf->channel,
+				 &edmg);
+	if (!(edmg.channels & BIT(iface->conf->channel - 1)))
+		return 0;
+
+	/* 60 GHz channels 1..6 */
+	for (i = 0; i < 6; i++) {
+		if (edmg.channels & BIT(i)) {
+			contiguous++;
+			num_of_enabled++;
+		} else {
+			contiguous = 0;
+			continue;
+		}
+
+		/* P802.11ay defines that the total number of subfields
+		 * set to one does not exceed 4.
+		 */
+		if (num_of_enabled > 4)
+			return 0;
+
+		if (!hostapd_is_usable_chan(iface, i + 1, 1))
+			return 0;
+
+		if (contiguous > max_contiguous)
+			max_contiguous = contiguous;
+	}
+
+	/* Check if the EDMG configuration is valid under the limitations
+	 * of P802.11ay.
+	 */
+	/* check bw_config against contiguous EDMG channels */
+	switch (edmg.bw_config) {
+	case EDMG_BW_CONFIG_4:
+		if (!max_contiguous)
+			return 0;
+		break;
+	case EDMG_BW_CONFIG_5:
+		if (max_contiguous < 2)
+			return 0;
+		break;
+	default:
+		return 0;
+	}
+
+	return 1;
+}
+
+
 static int hostapd_is_usable_chans(struct hostapd_iface *iface)
 {
 	int secondary_chan;
@@ -743,6 +830,9 @@
 	if (!hostapd_is_usable_chan(iface, iface->conf->channel, 1))
 		return 0;
 
+	if (!hostapd_is_usable_edmg(iface))
+		return 0;
+
 	if (!iface->conf->secondary_channel)
 		return 1;
 
@@ -871,6 +961,7 @@
 int hostapd_select_hw_mode(struct hostapd_iface *iface)
 {
 	int i;
+	int freq = -1;
 
 	if (iface->num_hw_features < 1)
 		return -1;
@@ -887,9 +978,14 @@
 	}
 
 	iface->current_mode = NULL;
+	if (iface->conf->channel && iface->conf->op_class)
+		freq = ieee80211_chan_to_freq(NULL, iface->conf->op_class,
+					      iface->conf->channel);
 	for (i = 0; i < iface->num_hw_features; i++) {
 		struct hostapd_hw_modes *mode = &iface->hw_features[i];
 		if (mode->mode == iface->conf->hw_mode) {
+			if (freq > 0 && !hw_get_chan(mode, freq))
+				continue;
 			iface->current_mode = mode;
 			break;
 		}
diff --git a/src/ap/hw_features.h b/src/ap/hw_features.h
index ca7f22b..902a19f 100644
--- a/src/ap/hw_features.h
+++ b/src/ap/hw_features.h
@@ -21,6 +21,7 @@
 int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan);
 int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq);
 int hostapd_check_ht_capab(struct hostapd_iface *iface);
+int hostapd_check_edmg_capab(struct hostapd_iface *iface);
 int hostapd_prepare_rates(struct hostapd_iface *iface,
 			  struct hostapd_hw_modes *mode);
 void hostapd_stop_setup_timers(struct hostapd_iface *iface);
@@ -61,6 +62,11 @@
 	return 0;
 }
 
+static inline int hostapd_check_edmg_capab(struct hostapd_iface *iface)
+{
+	return 0;
+}
+
 static inline int hostapd_prepare_rates(struct hostapd_iface *iface,
 					struct hostapd_hw_modes *mode)
 {
diff --git a/src/ap/iapp.c b/src/ap/iapp.c
deleted file mode 100644
index 2556da3..0000000
--- a/src/ap/iapp.c
+++ /dev/null
@@ -1,542 +0,0 @@
-/*
- * hostapd / IEEE 802.11F-2003 Inter-Access Point Protocol (IAPP)
- * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- *
- * Note: IEEE 802.11F-2003 was a experimental use specification. It has expired
- * and IEEE has withdrawn it. In other words, it is likely better to look at
- * using some other mechanism for AP-to-AP communication than extending the
- * implementation here.
- */
-
-/* TODO:
- * Level 1: no administrative or security support
- *	(e.g., static BSSID to IP address mapping in each AP)
- * Level 2: support for dynamic mapping of BSSID to IP address
- * Level 3: support for encryption and authentication of IAPP messages
- * - add support for MOVE-notify and MOVE-response (this requires support for
- *   finding out IP address for previous AP using RADIUS)
- * - add support for Send- and ACK-Security-Block to speedup IEEE 802.1X during
- *   reassociation to another AP
- * - implement counters etc. for IAPP MIB
- * - verify endianness of fields in IAPP messages; are they big-endian as
- *   used here?
- * - RADIUS connection for AP registration and BSSID to IP address mapping
- * - TCP connection for IAPP MOVE, CACHE
- * - broadcast ESP for IAPP ADD-notify
- * - ESP for IAPP MOVE messages
- * - security block sending/processing
- * - IEEE 802.11 context transfer
- */
-
-#include "utils/includes.h"
-#include <net/if.h>
-#include <sys/ioctl.h>
-#include <netpacket/packet.h>
-
-#include "utils/common.h"
-#include "utils/eloop.h"
-#include "common/ieee802_11_defs.h"
-#include "hostapd.h"
-#include "ap_config.h"
-#include "ieee802_11.h"
-#include "sta_info.h"
-#include "iapp.h"
-
-
-#define IAPP_MULTICAST "224.0.1.178"
-#define IAPP_UDP_PORT 3517
-#define IAPP_TCP_PORT 3517
-
-struct iapp_hdr {
-	u8 version;
-	u8 command;
-	be16 identifier;
-	be16 length;
-	/* followed by length-6 octets of data */
-} __attribute__ ((packed));
-
-#define IAPP_VERSION 0
-
-enum IAPP_COMMAND {
-	IAPP_CMD_ADD_notify = 0,
-	IAPP_CMD_MOVE_notify = 1,
-	IAPP_CMD_MOVE_response = 2,
-	IAPP_CMD_Send_Security_Block = 3,
-	IAPP_CMD_ACK_Security_Block = 4,
-	IAPP_CMD_CACHE_notify = 5,
-	IAPP_CMD_CACHE_response = 6,
-};
-
-
-/* ADD-notify - multicast UDP on the local LAN */
-struct iapp_add_notify {
-	u8 addr_len; /* ETH_ALEN */
-	u8 reserved;
-	u8 mac_addr[ETH_ALEN];
-	be16 seq_num;
-} __attribute__ ((packed));
-
-
-/* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */
-struct iapp_layer2_update {
-	u8 da[ETH_ALEN]; /* broadcast */
-	u8 sa[ETH_ALEN]; /* STA addr */
-	be16 len; /* 6 */
-	u8 dsap; /* null DSAP address */
-	u8 ssap; /* null SSAP address, CR=Response */
-	u8 control;
-	u8 xid_info[3];
-} __attribute__ ((packed));
-
-
-/* MOVE-notify - unicast TCP */
-struct iapp_move_notify {
-	u8 addr_len; /* ETH_ALEN */
-	u8 reserved;
-	u8 mac_addr[ETH_ALEN];
-	u16 seq_num;
-	u16 ctx_block_len;
-	/* followed by ctx_block_len bytes */
-} __attribute__ ((packed));
-
-
-/* MOVE-response - unicast TCP */
-struct iapp_move_response {
-	u8 addr_len; /* ETH_ALEN */
-	u8 status;
-	u8 mac_addr[ETH_ALEN];
-	u16 seq_num;
-	u16 ctx_block_len;
-	/* followed by ctx_block_len bytes */
-} __attribute__ ((packed));
-
-enum {
-	IAPP_MOVE_SUCCESSFUL = 0,
-	IAPP_MOVE_DENIED = 1,
-	IAPP_MOVE_STALE_MOVE = 2,
-};
-
-
-/* CACHE-notify */
-struct iapp_cache_notify {
-	u8 addr_len; /* ETH_ALEN */
-	u8 reserved;
-	u8 mac_addr[ETH_ALEN];
-	u16 seq_num;
-	u8 current_ap[ETH_ALEN];
-	u16 ctx_block_len;
-	/* ctx_block_len bytes of context block followed by 16-bit context
-	 * timeout */
-} __attribute__ ((packed));
-
-
-/* CACHE-response - unicast TCP */
-struct iapp_cache_response {
-	u8 addr_len; /* ETH_ALEN */
-	u8 status;
-	u8 mac_addr[ETH_ALEN];
-	u16 seq_num;
-} __attribute__ ((packed));
-
-enum {
-	IAPP_CACHE_SUCCESSFUL = 0,
-	IAPP_CACHE_STALE_CACHE = 1,
-};
-
-
-/* Send-Security-Block - unicast TCP */
-struct iapp_send_security_block {
-	u8 iv[8];
-	u16 sec_block_len;
-	/* followed by sec_block_len bytes of security block */
-} __attribute__ ((packed));
-
-
-/* ACK-Security-Block - unicast TCP */
-struct iapp_ack_security_block {
-	u8 iv[8];
-	u8 new_ap_ack_authenticator[48];
-} __attribute__ ((packed));
-
-
-struct iapp_data {
-	struct hostapd_data *hapd;
-	u16 identifier; /* next IAPP identifier */
-	struct in_addr own, multicast;
-	int udp_sock;
-	int packet_sock;
-};
-
-
-static void iapp_send_add(struct iapp_data *iapp, u8 *mac_addr, u16 seq_num)
-{
-	char buf[128];
-	struct iapp_hdr *hdr;
-	struct iapp_add_notify *add;
-	struct sockaddr_in addr;
-
-	/* Send IAPP ADD-notify to remove possible association from other APs
-	 */
-
-	hdr = (struct iapp_hdr *) buf;
-	hdr->version = IAPP_VERSION;
-	hdr->command = IAPP_CMD_ADD_notify;
-	hdr->identifier = host_to_be16(iapp->identifier++);
-	hdr->length = host_to_be16(sizeof(*hdr) + sizeof(*add));
-
-	add = (struct iapp_add_notify *) (hdr + 1);
-	add->addr_len = ETH_ALEN;
-	add->reserved = 0;
-	os_memcpy(add->mac_addr, mac_addr, ETH_ALEN);
-
-	add->seq_num = host_to_be16(seq_num);
-	
-	os_memset(&addr, 0, sizeof(addr));
-	addr.sin_family = AF_INET;
-	addr.sin_addr.s_addr = iapp->multicast.s_addr;
-	addr.sin_port = htons(IAPP_UDP_PORT);
-	if (sendto(iapp->udp_sock, buf, (char *) (add + 1) - buf, 0,
-		   (struct sockaddr *) &addr, sizeof(addr)) < 0)
-		wpa_printf(MSG_INFO, "sendto[IAPP-ADD]: %s", strerror(errno));
-}
-
-
-static void iapp_send_layer2_update(struct iapp_data *iapp, u8 *addr)
-{
-	struct iapp_layer2_update msg;
-
-	/* Send Level 2 Update Frame to update forwarding tables in layer 2
-	 * bridge devices */
-
-	/* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID)
-	 * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */
-
-	os_memset(msg.da, 0xff, ETH_ALEN);
-	os_memcpy(msg.sa, addr, ETH_ALEN);
-	msg.len = host_to_be16(6);
-	msg.dsap = 0; /* NULL DSAP address */
-	msg.ssap = 0x01; /* NULL SSAP address, CR Bit: Response */
-	msg.control = 0xaf; /* XID response lsb.1111F101.
-			     * F=0 (no poll command; unsolicited frame) */
-	msg.xid_info[0] = 0x81; /* XID format identifier */
-	msg.xid_info[1] = 1; /* LLC types/classes: Type 1 LLC */
-	msg.xid_info[2] = 1 << 1; /* XID sender's receive window size (RW)
-				   * FIX: what is correct RW with 802.11? */
-
-	if (send(iapp->packet_sock, &msg, sizeof(msg), 0) < 0)
-		wpa_printf(MSG_INFO, "send[L2 Update]: %s", strerror(errno));
-}
-
-
-/**
- * iapp_new_station - IAPP processing for a new STA
- * @iapp: IAPP data
- * @sta: The associated station
- */
-void iapp_new_station(struct iapp_data *iapp, struct sta_info *sta)
-{
-	u16 seq = 0; /* TODO */
-
-	if (iapp == NULL)
-		return;
-
-	/* IAPP-ADD.request(MAC Address, Sequence Number, Timeout) */
-	hostapd_logger(iapp->hapd, sta->addr, HOSTAPD_MODULE_IAPP,
-		       HOSTAPD_LEVEL_DEBUG, "IAPP-ADD.request(seq=%d)", seq);
-	iapp_send_layer2_update(iapp, sta->addr);
-	iapp_send_add(iapp, sta->addr, seq);
-
-	/* TODO: If this was reassociation:
-	 * IAPP-MOVE.request(MAC Address, Sequence Number, Old AP,
-	 *                   Context Block, Timeout)
-	 * TODO: Send IAPP-MOVE to the old AP; Map Old AP BSSID to
-	 * IP address */
-}
-
-
-static void iapp_process_add_notify(struct iapp_data *iapp,
-				    struct sockaddr_in *from,
-				    struct iapp_hdr *hdr, int len)
-{
-	struct iapp_add_notify *add = (struct iapp_add_notify *) (hdr + 1);
-	struct sta_info *sta;
-
-	if (len != sizeof(*add)) {
-		wpa_printf(MSG_INFO, "Invalid IAPP-ADD packet length %d (expected %lu)",
-			   len, (unsigned long) sizeof(*add));
-		return;
-	}
-
-	sta = ap_get_sta(iapp->hapd, add->mac_addr);
-
-	/* IAPP-ADD.indication(MAC Address, Sequence Number) */
-	hostapd_logger(iapp->hapd, add->mac_addr, HOSTAPD_MODULE_IAPP,
-		       HOSTAPD_LEVEL_INFO,
-		       "Received IAPP ADD-notify (seq# %d) from %s:%d%s",
-		       be_to_host16(add->seq_num),
-		       inet_ntoa(from->sin_addr), ntohs(from->sin_port),
-		       sta ? "" : " (STA not found)");
-
-	if (!sta)
-		return;
-
-	/* TODO: could use seq_num to try to determine whether last association
-	 * to this AP is newer than the one advertised in IAPP-ADD. Although,
-	 * this is not really a reliable verification. */
-
-	hostapd_logger(iapp->hapd, add->mac_addr, HOSTAPD_MODULE_IAPP,
-		       HOSTAPD_LEVEL_DEBUG,
-		       "Removing STA due to IAPP ADD-notify");
-	ap_sta_disconnect(iapp->hapd, sta, NULL, 0);
-}
-
-
-/**
- * iapp_receive_udp - Process IAPP UDP frames
- * @sock: File descriptor for the socket
- * @eloop_ctx: IAPP data (struct iapp_data *)
- * @sock_ctx: Not used
- */
-static void iapp_receive_udp(int sock, void *eloop_ctx, void *sock_ctx)
-{
-	struct iapp_data *iapp = eloop_ctx;
-	int len, hlen;
-	unsigned char buf[128];
-	struct sockaddr_in from;
-	socklen_t fromlen;
-	struct iapp_hdr *hdr;
-
-	/* Handle incoming IAPP frames (over UDP/IP) */
-
-	fromlen = sizeof(from);
-	len = recvfrom(iapp->udp_sock, buf, sizeof(buf), 0,
-		       (struct sockaddr *) &from, &fromlen);
-	if (len < 0) {
-		wpa_printf(MSG_INFO, "iapp_receive_udp - recvfrom: %s",
-			   strerror(errno));
-		return;
-	}
-
-	if (from.sin_addr.s_addr == iapp->own.s_addr)
-		return; /* ignore own IAPP messages */
-
-	hostapd_logger(iapp->hapd, NULL, HOSTAPD_MODULE_IAPP,
-		       HOSTAPD_LEVEL_DEBUG,
-		       "Received %d byte IAPP frame from %s%s\n",
-		       len, inet_ntoa(from.sin_addr),
-		       len < (int) sizeof(*hdr) ? " (too short)" : "");
-
-	if (len < (int) sizeof(*hdr))
-		return;
-
-	hdr = (struct iapp_hdr *) buf;
-	hlen = be_to_host16(hdr->length);
-	hostapd_logger(iapp->hapd, NULL, HOSTAPD_MODULE_IAPP,
-		       HOSTAPD_LEVEL_DEBUG,
-		       "RX: version=%d command=%d id=%d len=%d\n",
-		       hdr->version, hdr->command,
-		       be_to_host16(hdr->identifier), hlen);
-	if (hdr->version != IAPP_VERSION) {
-		wpa_printf(MSG_INFO, "Dropping IAPP frame with unknown version %d",
-			   hdr->version);
-		return;
-	}
-	if (hlen > len) {
-		wpa_printf(MSG_INFO, "Underflow IAPP frame (hlen=%d len=%d)",
-			   hlen, len);
-		return;
-	}
-	if (hlen < len) {
-		wpa_printf(MSG_INFO, "Ignoring %d extra bytes from IAPP frame",
-			   len - hlen);
-		len = hlen;
-	}
-
-	switch (hdr->command) {
-	case IAPP_CMD_ADD_notify:
-		iapp_process_add_notify(iapp, &from, hdr, len - sizeof(*hdr));
-		break;
-	case IAPP_CMD_MOVE_notify:
-		/* TODO: MOVE is using TCP; so move this to TCP handler once it
-		 * is implemented.. */
-		/* IAPP-MOVE.indication(MAC Address, New BSSID,
-		 * Sequence Number, AP Address, Context Block) */
-		/* TODO: process */
-		break;
-	default:
-		wpa_printf(MSG_INFO, "Unknown IAPP command %d", hdr->command);
-		break;
-	}
-}
-
-
-struct iapp_data * iapp_init(struct hostapd_data *hapd, const char *iface)
-{
-	struct ifreq ifr;
-	struct sockaddr_ll addr;
-	int ifindex;
-	struct sockaddr_in *paddr, uaddr;
-	struct iapp_data *iapp;
-	struct ip_mreqn mreq;
-	int reuseaddr = 1;
-
-	iapp = os_zalloc(sizeof(*iapp));
-	if (iapp == NULL)
-		return NULL;
-	iapp->hapd = hapd;
-	iapp->udp_sock = iapp->packet_sock = -1;
-
-	/* TODO:
-	 * open socket for sending and receiving IAPP frames over TCP
-	 */
-
-	iapp->udp_sock = socket(PF_INET, SOCK_DGRAM, 0);
-	if (iapp->udp_sock < 0) {
-		wpa_printf(MSG_INFO, "iapp_init - socket[PF_INET,SOCK_DGRAM]: %s",
-			   strerror(errno));
-		iapp_deinit(iapp);
-		return NULL;
-	}
-
-	os_memset(&ifr, 0, sizeof(ifr));
-	os_strlcpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name));
-	if (ioctl(iapp->udp_sock, SIOCGIFINDEX, &ifr) != 0) {
-		wpa_printf(MSG_INFO, "iapp_init - ioctl(SIOCGIFINDEX): %s",
-			   strerror(errno));
-		iapp_deinit(iapp);
-		return NULL;
-	}
-	ifindex = ifr.ifr_ifindex;
-
-	if (ioctl(iapp->udp_sock, SIOCGIFADDR, &ifr) != 0) {
-		wpa_printf(MSG_INFO, "iapp_init - ioctl(SIOCGIFADDR): %s",
-			   strerror(errno));
-		iapp_deinit(iapp);
-		return NULL;
-	}
-	paddr = (struct sockaddr_in *) &ifr.ifr_addr;
-	if (paddr->sin_family != AF_INET) {
-		wpa_printf(MSG_INFO, "IAPP: Invalid address family %i (SIOCGIFADDR)",
-			   paddr->sin_family);
-		iapp_deinit(iapp);
-		return NULL;
-	}
-	iapp->own.s_addr = paddr->sin_addr.s_addr;
-
-	if (ioctl(iapp->udp_sock, SIOCGIFBRDADDR, &ifr) != 0) {
-		wpa_printf(MSG_INFO, "iapp_init - ioctl(SIOCGIFBRDADDR): %s",
-			   strerror(errno));
-		iapp_deinit(iapp);
-		return NULL;
-	}
-	paddr = (struct sockaddr_in *) &ifr.ifr_addr;
-	if (paddr->sin_family != AF_INET) {
-		wpa_printf(MSG_INFO, "Invalid address family %i (SIOCGIFBRDADDR)",
-			   paddr->sin_family);
-		iapp_deinit(iapp);
-		return NULL;
-	}
-	inet_aton(IAPP_MULTICAST, &iapp->multicast);
-
-	os_memset(&uaddr, 0, sizeof(uaddr));
-	uaddr.sin_family = AF_INET;
-	uaddr.sin_port = htons(IAPP_UDP_PORT);
-
-	if (setsockopt(iapp->udp_sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,
-		       sizeof(reuseaddr)) < 0) {
-		wpa_printf(MSG_INFO,
-			   "iapp_init - setsockopt[UDP,SO_REUSEADDR]: %s",
-			   strerror(errno));
-		/*
-		 * Ignore this and try to continue. This is fine for single
-		 * BSS cases, but may fail if multiple BSSes enable IAPP.
-		 */
-	}
-
-	if (bind(iapp->udp_sock, (struct sockaddr *) &uaddr,
-		 sizeof(uaddr)) < 0) {
-		wpa_printf(MSG_INFO, "iapp_init - bind[UDP]: %s",
-			   strerror(errno));
-		iapp_deinit(iapp);
-		return NULL;
-	}
-
-	os_memset(&mreq, 0, sizeof(mreq));
-	mreq.imr_multiaddr = iapp->multicast;
-	mreq.imr_address.s_addr = INADDR_ANY;
-	mreq.imr_ifindex = 0;
-	if (setsockopt(iapp->udp_sock, SOL_IP, IP_ADD_MEMBERSHIP, &mreq,
-		       sizeof(mreq)) < 0) {
-		wpa_printf(MSG_INFO, "iapp_init - setsockopt[UDP,IP_ADD_MEMBERSHIP]: %s",
-			   strerror(errno));
-		iapp_deinit(iapp);
-		return NULL;
-	}
-
-	iapp->packet_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
-	if (iapp->packet_sock < 0) {
-		wpa_printf(MSG_INFO, "iapp_init - socket[PF_PACKET,SOCK_RAW]: %s",
-			   strerror(errno));
-		iapp_deinit(iapp);
-		return NULL;
-	}
-
-	os_memset(&addr, 0, sizeof(addr));
-	addr.sll_family = AF_PACKET;
-	addr.sll_ifindex = ifindex;
-	if (bind(iapp->packet_sock, (struct sockaddr *) &addr,
-		 sizeof(addr)) < 0) {
-		wpa_printf(MSG_INFO, "iapp_init - bind[PACKET]: %s",
-			   strerror(errno));
-		iapp_deinit(iapp);
-		return NULL;
-	}
-
-	if (eloop_register_read_sock(iapp->udp_sock, iapp_receive_udp,
-				     iapp, NULL)) {
-		wpa_printf(MSG_INFO, "Could not register read socket for IAPP");
-		iapp_deinit(iapp);
-		return NULL;
-	}
-
-	wpa_printf(MSG_INFO, "IEEE 802.11F (IAPP) using interface %s", iface);
-
-	/* TODO: For levels 2 and 3: send RADIUS Initiate-Request, receive
-	 * RADIUS Initiate-Accept or Initiate-Reject. IAPP port should actually
-	 * be openned only after receiving Initiate-Accept. If Initiate-Reject
-	 * is received, IAPP is not started. */
-
-	return iapp;
-}
-
-
-void iapp_deinit(struct iapp_data *iapp)
-{
-	struct ip_mreqn mreq;
-
-	if (iapp == NULL)
-		return;
-
-	if (iapp->udp_sock >= 0) {
-		os_memset(&mreq, 0, sizeof(mreq));
-		mreq.imr_multiaddr = iapp->multicast;
-		mreq.imr_address.s_addr = INADDR_ANY;
-		mreq.imr_ifindex = 0;
-		if (setsockopt(iapp->udp_sock, SOL_IP, IP_DROP_MEMBERSHIP,
-			       &mreq, sizeof(mreq)) < 0) {
-			wpa_printf(MSG_INFO, "iapp_deinit - setsockopt[UDP,IP_DEL_MEMBERSHIP]: %s",
-				   strerror(errno));
-		}
-
-		eloop_unregister_read_sock(iapp->udp_sock);
-		close(iapp->udp_sock);
-	}
-	if (iapp->packet_sock >= 0) {
-		eloop_unregister_read_sock(iapp->packet_sock);
-		close(iapp->packet_sock);
-	}
-	os_free(iapp);
-}
diff --git a/src/ap/iapp.h b/src/ap/iapp.h
deleted file mode 100644
index c221183..0000000
--- a/src/ap/iapp.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * hostapd / IEEE 802.11F-2003 Inter-Access Point Protocol (IAPP)
- * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#ifndef IAPP_H
-#define IAPP_H
-
-struct iapp_data;
-
-#ifdef CONFIG_IAPP
-
-void iapp_new_station(struct iapp_data *iapp, struct sta_info *sta);
-struct iapp_data * iapp_init(struct hostapd_data *hapd, const char *iface);
-void iapp_deinit(struct iapp_data *iapp);
-
-#else /* CONFIG_IAPP */
-
-static inline void iapp_new_station(struct iapp_data *iapp,
-				    struct sta_info *sta)
-{
-}
-
-static inline struct iapp_data * iapp_init(struct hostapd_data *hapd,
-					   const char *iface)
-{
-	return NULL;
-}
-
-static inline void iapp_deinit(struct iapp_data *iapp)
-{
-}
-
-#endif /* CONFIG_IAPP */
-
-#endif /* IAPP_H */
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index fff35b7..4d30bae 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -98,6 +98,8 @@
 		num++;
 	if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht)
 		num++;
+	if (hapd->conf->sae_pwe == 1)
+		num++;
 	if (num > 8) {
 		/* rest of the rates are encoded in Extended supported
 		 * rates element */
@@ -124,6 +126,11 @@
 		*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY;
 	}
 
+	if (hapd->conf->sae_pwe == 1 && count < 8) {
+		count++;
+		*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_SAE_H2E_ONLY;
+	}
+
 	return pos;
 }
 
@@ -141,6 +148,8 @@
 		num++;
 	if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht)
 		num++;
+	if (hapd->conf->sae_pwe == 1)
+		num++;
 	if (num <= 8)
 		return eid;
 	num -= 8;
@@ -170,6 +179,12 @@
 			*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY;
 	}
 
+	if (hapd->conf->sae_pwe == 1) {
+		count++;
+		if (count > 8)
+			*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_SAE_H2E_ONLY;
+	}
+
 	return pos;
 }
 
@@ -388,15 +403,25 @@
 
 
 static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd,
-					     struct sta_info *sta, int update)
+					     struct sta_info *sta, int update,
+					     int status_code)
 {
 	struct wpabuf *buf;
 	const char *password = NULL;
 	struct sae_password_entry *pw;
 	const char *rx_id = NULL;
+	int use_pt = 0;
+	struct sae_pt *pt = NULL;
 
-	if (sta->sae->tmp)
+	if (sta->sae->tmp) {
 		rx_id = sta->sae->tmp->pw_id;
+		use_pt = sta->sae->tmp->h2e;
+	}
+
+	if (status_code == WLAN_STATUS_SUCCESS)
+		use_pt = 0;
+	else if (status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT)
+		use_pt = 1;
 
 	for (pw = hapd->conf->sae_passwords; pw; pw = pw->next) {
 		if (!is_broadcast_ether_addr(pw->peer_addr) &&
@@ -408,16 +433,24 @@
 		    os_strcmp(rx_id, pw->identifier) != 0)
 			continue;
 		password = pw->password;
+		pt = pw->pt;
 		break;
 	}
-	if (!password)
-		password = hapd->conf->ssid.wpa_passphrase;
 	if (!password) {
+		password = hapd->conf->ssid.wpa_passphrase;
+		pt = hapd->conf->ssid.pt;
+	}
+	if (!password || (use_pt && !pt)) {
 		wpa_printf(MSG_DEBUG, "SAE: No password available");
 		return NULL;
 	}
 
-	if (update &&
+	if (update && use_pt &&
+	    sae_prepare_commit_pt(sta->sae, pt, hapd->own_addr, sta->addr,
+				  NULL) < 0)
+		return NULL;
+
+	if (update && !use_pt &&
 	    sae_prepare_commit(hapd->own_addr, sta->addr,
 			       (u8 *) password, os_strlen(password), rx_id,
 			       sta->sae) < 0) {
@@ -462,19 +495,22 @@
 
 static int auth_sae_send_commit(struct hostapd_data *hapd,
 				struct sta_info *sta,
-				const u8 *bssid, int update)
+				const u8 *bssid, int update, int status_code)
 {
 	struct wpabuf *data;
 	int reply_res;
+	u16 status;
 
-	data = auth_build_sae_commit(hapd, sta, update);
+	data = auth_build_sae_commit(hapd, sta, update, status_code);
 	if (!data && sta->sae->tmp && sta->sae->tmp->pw_id)
 		return WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER;
 	if (data == NULL)
 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
 
+	status = (sta->sae->tmp && sta->sae->tmp->h2e) ?
+		WLAN_STATUS_SAE_HASH_TO_ELEMENT : WLAN_STATUS_SUCCESS;
 	reply_res = send_auth_reply(hapd, sta->addr, bssid, WLAN_AUTH_SAE, 1,
-				    WLAN_STATUS_SUCCESS, wpabuf_head(data),
+				    status, wpabuf_head(data),
 				    wpabuf_len(data), "sae-send-commit");
 
 	wpabuf_free(data);
@@ -663,7 +699,7 @@
 
 	switch (sta->sae->state) {
 	case SAE_COMMITTED:
-		ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0);
+		ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0, -1);
 		eloop_register_timeout(0,
 				       hapd->dot11RSNASAERetransPeriod * 1000,
 				       auth_sae_retransmit_timer, hapd, sta);
@@ -761,8 +797,8 @@
 
 
 static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
-		       const u8 *bssid, u8 auth_transaction, int allow_reuse,
-		       int *sta_removed)
+		       const u8 *bssid, u16 auth_transaction, u16 status_code,
+		       int allow_reuse, int *sta_removed)
 {
 	int ret;
 
@@ -777,8 +813,11 @@
 	switch (sta->sae->state) {
 	case SAE_NOTHING:
 		if (auth_transaction == 1) {
+			if (sta->sae->tmp)
+				sta->sae->tmp->h2e = status_code ==
+					WLAN_STATUS_SAE_HASH_TO_ELEMENT;
 			ret = auth_sae_send_commit(hapd, sta, bssid,
-						   !allow_reuse);
+						   !allow_reuse, status_code);
 			if (ret)
 				return ret;
 			sae_set_state(sta, SAE_COMMITTED, "Sent Commit");
@@ -787,14 +826,17 @@
 				return WLAN_STATUS_UNSPECIFIED_FAILURE;
 
 			/*
-			 * In mesh case, both Commit and Confirm can be sent
-			 * immediately. In infrastructure BSS, only a single
-			 * Authentication frame (Commit) is expected from the AP
-			 * here and the second one (Confirm) will be sent once
-			 * the STA has sent its second Authentication frame
-			 * (Confirm).
+			 * In mesh case, both Commit and Confirm are sent
+			 * immediately. In infrastructure BSS, by default, only
+			 * a single Authentication frame (Commit) is expected
+			 * from the AP here and the second one (Confirm) will
+			 * be sent once the STA has sent its second
+			 * Authentication frame (Confirm). This behavior can be
+			 * overridden with explicit configuration so that the
+			 * infrastructure BSS case sends both frames together.
 			 */
-			if (hapd->conf->mesh & MESH_ENABLED) {
+			if ((hapd->conf->mesh & MESH_ENABLED) ||
+			    hapd->conf->sae_confirm_immediate) {
 				/*
 				 * Send both Commit and Confirm immediately
 				 * based on SAE finite state machine
@@ -845,7 +887,8 @@
 				return WLAN_STATUS_SUCCESS;
 			sta->sae->sync++;
 
-			ret = auth_sae_send_commit(hapd, sta, bssid, 0);
+			ret = auth_sae_send_commit(hapd, sta, bssid, 0,
+						   status_code);
 			if (ret)
 				return ret;
 
@@ -868,7 +911,7 @@
 			 * additional events.
 			 */
 			return sae_sm_step(hapd, sta, bssid, auth_transaction,
-					   0, sta_removed);
+					   WLAN_STATUS_SUCCESS, 0, sta_removed);
 		}
 		break;
 	case SAE_CONFIRMED:
@@ -878,7 +921,8 @@
 				return WLAN_STATUS_SUCCESS;
 			sta->sae->sync++;
 
-			ret = auth_sae_send_commit(hapd, sta, bssid, 1);
+			ret = auth_sae_send_commit(hapd, sta, bssid, 1,
+						   status_code);
 			if (ret)
 				return ret;
 
@@ -906,7 +950,8 @@
 			*sta_removed = 1;
 		} else if (auth_transaction == 1) {
 			wpa_printf(MSG_DEBUG, "SAE: Start reauthentication");
-			ret = auth_sae_send_commit(hapd, sta, bssid, 1);
+			ret = auth_sae_send_commit(hapd, sta, bssid, 1,
+						   status_code);
 			if (ret)
 				return ret;
 			sae_set_state(sta, SAE_COMMITTED, "Sent Commit");
@@ -976,6 +1021,64 @@
 }
 
 
+static int sae_status_success(struct hostapd_data *hapd, u16 status_code)
+{
+	return (hapd->conf->sae_pwe == 0 &&
+		status_code == WLAN_STATUS_SUCCESS) ||
+		(hapd->conf->sae_pwe == 1 &&
+		 status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT) ||
+		(hapd->conf->sae_pwe == 2 &&
+		 (status_code == WLAN_STATUS_SUCCESS ||
+		  status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT));
+}
+
+
+static int sae_is_group_enabled(struct hostapd_data *hapd, int group)
+{
+	int *groups = hapd->conf->sae_groups;
+	int default_groups[] = { 19, 0 };
+	int i;
+
+	if (!groups)
+		groups = default_groups;
+
+	for (i = 0; groups[i] > 0; i++) {
+		if (groups[i] == group)
+			return 1;
+	}
+
+	return 0;
+}
+
+
+static int check_sae_rejected_groups(struct hostapd_data *hapd,
+				     const struct wpabuf *groups)
+{
+	size_t i, count;
+	const u8 *pos;
+
+	if (!groups)
+		return 0;
+
+	pos = wpabuf_head(groups);
+	count = wpabuf_len(groups) / 2;
+	for (i = 0; i < count; i++) {
+		int enabled;
+		u16 group;
+
+		group = WPA_GET_LE16(pos);
+		pos += 2;
+		enabled = sae_is_group_enabled(hapd, group);
+		wpa_printf(MSG_DEBUG, "SAE: Rejected group %u is %s",
+			   group, enabled ? "enabled" : "disabled");
+		if (enabled)
+			return 1;
+	}
+
+	return 0;
+}
+
+
 static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
 			    const struct ieee80211_mgmt *mgmt, size_t len,
 			    u16 auth_transaction, u16 status_code)
@@ -1013,7 +1116,7 @@
 #endif /* CONFIG_TESTING_OPTIONS */
 	if (!sta->sae) {
 		if (auth_transaction != 1 ||
-		    status_code != WLAN_STATUS_SUCCESS) {
+		    !sae_status_success(hapd, status_code)) {
 			resp = -1;
 			goto remove_sta;
 		}
@@ -1080,7 +1183,8 @@
 			 * Authentication frame, and the commit-scalar and
 			 * COMMIT-ELEMENT previously sent.
 			 */
-			resp = auth_sae_send_commit(hapd, sta, mgmt->bssid, 0);
+			resp = auth_sae_send_commit(hapd, sta, mgmt->bssid, 0,
+						    status_code);
 			if (resp != WLAN_STATUS_SUCCESS) {
 				wpa_printf(MSG_ERROR,
 					   "SAE: Failed to send commit message");
@@ -1103,7 +1207,7 @@
 			goto remove_sta;
 		}
 
-		if (status_code != WLAN_STATUS_SUCCESS)
+		if (!sae_status_success(hapd, status_code))
 			goto remove_sta;
 
 		if (!(hapd->conf->mesh & MESH_ENABLED) &&
@@ -1136,7 +1240,8 @@
 		resp = sae_parse_commit(sta->sae, mgmt->u.auth.variable,
 					((const u8 *) mgmt) + len -
 					mgmt->u.auth.variable, &token,
-					&token_len, groups);
+					&token_len, groups, status_code ==
+					WLAN_STATUS_SAE_HASH_TO_ELEMENT);
 		if (resp == SAE_SILENTLY_DISCARD) {
 			wpa_printf(MSG_DEBUG,
 				   "SAE: Drop commit message from " MACSTR " due to reflection attack",
@@ -1166,6 +1271,13 @@
 		if (resp != WLAN_STATUS_SUCCESS)
 			goto reply;
 
+		if (sta->sae->tmp &&
+		    check_sae_rejected_groups(
+			    hapd, sta->sae->tmp->peer_rejected_groups) < 0) {
+			resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+			goto remove_sta;
+		}
+
 		if (!token && use_sae_anti_clogging(hapd) && !allow_reuse) {
 			wpa_printf(MSG_DEBUG,
 				   "SAE: Request anti-clogging token from "
@@ -1180,7 +1292,7 @@
 		}
 
 		resp = sae_sm_step(hapd, sta, mgmt->bssid, auth_transaction,
-				   allow_reuse, &sta_removed);
+				   status_code, allow_reuse, &sta_removed);
 	} else if (auth_transaction == 2) {
 		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
 			       HOSTAPD_LEVEL_DEBUG,
@@ -1221,8 +1333,8 @@
 			}
 			sta->sae->rc = peer_send_confirm;
 		}
-		resp = sae_sm_step(hapd, sta, mgmt->bssid, auth_transaction, 0,
-			&sta_removed);
+		resp = sae_sm_step(hapd, sta, mgmt->bssid, auth_transaction,
+				   status_code, 0, &sta_removed);
 	} else {
 		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
 			       HOSTAPD_LEVEL_DEBUG,
@@ -1283,7 +1395,7 @@
 	if (sta->sae->state != SAE_NOTHING)
 		return -1;
 
-	ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0);
+	ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0, -1);
 	if (ret)
 		return -1;
 
@@ -1406,12 +1518,10 @@
 		return WLAN_STATUS_AKMP_NOT_VALID;
 	if (res == WPA_ALLOC_FAIL)
 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
-#ifdef CONFIG_IEEE80211W
 	if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION)
 		return WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION;
 	if (res == WPA_INVALID_MGMT_GROUP_CIPHER)
 		return WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
-#endif /* CONFIG_IEEE80211W */
 	if (res == WPA_INVALID_MDIE)
 		return WLAN_STATUS_INVALID_MDIE;
 	if (res == WPA_INVALID_PMKID)
@@ -1554,6 +1664,8 @@
 	res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
 				  hapd->iface->freq,
 				  elems.rsn_ie - 2, elems.rsn_ie_len + 2,
+				  elems.rsnxe ? elems.rsnxe - 2 : NULL,
+				  elems.rsnxe ? elems.rsnxe_len + 2 : 0,
 				  elems.mdie, elems.mdie_len, NULL, 0);
 	resp = wpa_res_to_status_code(res);
 	if (resp != WLAN_STATUS_SUCCESS)
@@ -2865,7 +2977,7 @@
 	rsn_ie_len += 2;
 	res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
 				  hapd->iface->freq, rsn_ie, rsn_ie_len,
-				  NULL, 0, owe_dh, owe_dh_len);
+				  NULL, 0, NULL, 0, owe_dh, owe_dh_len);
 	status = wpa_res_to_status_code(res);
 	if (status != WLAN_STATUS_SUCCESS)
 		goto end;
@@ -3073,12 +3185,13 @@
 		res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
 					  hapd->iface->freq,
 					  wpa_ie, wpa_ie_len,
+					  elems.rsnxe ? elems.rsnxe - 2 : NULL,
+					  elems.rsnxe ? elems.rsnxe_len + 2 : 0,
 					  elems.mdie, elems.mdie_len,
 					  elems.owe_dh, elems.owe_dh_len);
 		resp = wpa_res_to_status_code(res);
 		if (resp != WLAN_STATUS_SUCCESS)
 			return resp;
-#ifdef CONFIG_IEEE80211W
 		if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_MFP)) ==
 		    (WLAN_STA_ASSOC | WLAN_STA_MFP) &&
 		    !sta->sa_query_timed_out &&
@@ -3105,7 +3218,6 @@
 			sta->flags |= WLAN_STA_MFP;
 		else
 			sta->flags &= ~WLAN_STA_MFP;
-#endif /* CONFIG_IEEE80211W */
 
 #ifdef CONFIG_IEEE80211R_AP
 		if (sta->auth_alg == WLAN_AUTH_FT) {
@@ -3150,6 +3262,17 @@
 				   MAC2STR(sta->addr), sta->auth_alg);
 			return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
 		}
+
+		if (hapd->conf->sae_pwe == 2 &&
+		    sta->auth_alg == WLAN_AUTH_SAE &&
+		    sta->sae && sta->sae->tmp && !sta->sae->tmp->h2e &&
+		    elems.rsnxe && elems.rsnxe_len >= 1 &&
+		    (elems.rsnxe[0] & BIT(WLAN_RSNX_CAPAB_SAE_H2E))) {
+			wpa_printf(MSG_INFO, "SAE: " MACSTR
+				   " indicates support for SAE H2E, but did not use it",
+				   MAC2STR(sta->addr));
+			return WLAN_STATUS_UNSPECIFIED_FAILURE;
+		}
 #endif /* CONFIG_SAE */
 
 #ifdef CONFIG_OWE
@@ -3243,7 +3366,8 @@
 		sta->hs20_ie = wpabuf_alloc_copy(elems.hs20 + 4,
 						 elems.hs20_len - 4);
 		release = ((elems.hs20[4] >> 4) & 0x0f) + 1;
-		if (release >= 2 && !wpa_auth_uses_mfp(sta->wpa_sm)) {
+		if (release >= 2 && !wpa_auth_uses_mfp(sta->wpa_sm) &&
+		    hapd->conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
 			wpa_printf(MSG_DEBUG,
 				   "HS 2.0: PMF not negotiated by release %d station "
 				   MACSTR, release, MAC2STR(sta->addr));
@@ -3549,10 +3673,8 @@
 						  ies, ies_len);
 #endif /* CONFIG_OWE */
 
-#ifdef CONFIG_IEEE80211W
 	if (sta && status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY)
 		p = hostapd_eid_assoc_comeback_time(hapd, sta, p);
-#endif /* CONFIG_IEEE80211W */
 
 #ifdef CONFIG_IEEE80211N
 	p = hostapd_eid_ht_capabilities(hapd, p);
@@ -3560,7 +3682,8 @@
 #endif /* CONFIG_IEEE80211N */
 
 #ifdef CONFIG_IEEE80211AC
-	if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) {
+	if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac &&
+	    !is_6ghz_op_class(hapd->iconf->op_class)) {
 		u32 nsts = 0, sta_nsts;
 
 		if (sta && hapd->conf->use_sta_nsts && sta->vht_capabilities) {
@@ -3604,6 +3727,8 @@
 	}
 #endif /* CONFIG_FST */
 
+	p = hostapd_eid_rsnxe(hapd, p, buf + buflen - p);
+
 #ifdef CONFIG_OWE
 	if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) &&
 	    sta && sta->owe_ecdh && status_code == WLAN_STATUS_SUCCESS &&
@@ -4150,7 +4275,6 @@
 	 */
 	sta->flags |= WLAN_STA_ASSOC_REQ_OK;
 
-#ifdef CONFIG_IEEE80211W
 	if ((sta->flags & WLAN_STA_MFP) && sta->sa_query_timed_out) {
 		wpa_printf(MSG_DEBUG, "Allowing %sassociation after timed out "
 			   "SA Query procedure", reassoc ? "re" : "");
@@ -4161,7 +4285,6 @@
 		 * trying to associate.
 		 */
 	}
-#endif /* CONFIG_IEEE80211W */
 
 	/* Make sure that the previously registered inactivity timer will not
 	 * remove the STA immediately. */
@@ -4386,13 +4509,11 @@
 }
 
 
-#ifdef CONFIG_IEEE80211W
 static int robust_action_frame(u8 category)
 {
 	return category != WLAN_ACTION_PUBLIC &&
 		category != WLAN_ACTION_HT;
 }
-#endif /* CONFIG_IEEE80211W */
 
 
 static int handle_action(struct hostapd_data *hapd,
@@ -4426,7 +4547,6 @@
 		return 0;
 	}
 
-#ifdef CONFIG_IEEE80211W
 	if (sta && (sta->flags & WLAN_STA_MFP) &&
 	    !(mgmt->frame_control & host_to_le16(WLAN_FC_ISWEP)) &&
 	    robust_action_frame(mgmt->u.action.category)) {
@@ -4436,7 +4556,6 @@
 			       "an MFP STA");
 		return 0;
 	}
-#endif /* CONFIG_IEEE80211W */
 
 	if (sta) {
 		u16 fc = le_to_host16(mgmt->frame_control);
@@ -4470,11 +4589,9 @@
 	case WLAN_ACTION_WMM:
 		hostapd_wmm_action(hapd, mgmt, len);
 		return 1;
-#ifdef CONFIG_IEEE80211W
 	case WLAN_ACTION_SA_QUERY:
 		ieee802_11_sa_query_action(hapd, mgmt, len);
 		return 1;
-#endif /* CONFIG_IEEE80211W */
 #ifdef CONFIG_WNM_AP
 	case WLAN_ACTION_WNM:
 		ieee802_11_rx_wnm_action_ap(hapd, mgmt, len);
@@ -4626,6 +4743,18 @@
 	fc = le_to_host16(mgmt->frame_control);
 	stype = WLAN_FC_GET_STYPE(fc);
 
+	if (is_multicast_ether_addr(mgmt->sa) ||
+	    is_zero_ether_addr(mgmt->sa) ||
+	    os_memcmp(mgmt->sa, hapd->own_addr, ETH_ALEN) == 0) {
+		/* Do not process any frames with unexpected/invalid SA so that
+		 * we do not add any state for unexpected STA addresses or end
+		 * up sending out frames to unexpected destination. */
+		wpa_printf(MSG_DEBUG, "MGMT: Invalid SA=" MACSTR
+			   " in received frame - ignore this frame silently",
+			   MAC2STR(mgmt->sa));
+		return 0;
+	}
+
 	if (stype == WLAN_FC_STYPE_BEACON) {
 		handle_beacon(hapd, mgmt, len, fi);
 		return 1;
@@ -4862,9 +4991,7 @@
 	else
 		mlme_associate_indication(hapd, sta);
 
-#ifdef CONFIG_IEEE80211W
 	sta->sa_query_timed_out = 0;
-#endif /* CONFIG_IEEE80211W */
 
 	if (sta->eapol_sm == NULL) {
 		/*
@@ -5257,8 +5384,10 @@
 
 	wpa_printf(MSG_DEBUG, "Data/PS-poll frame from not associated STA "
 		   MACSTR, MAC2STR(src));
-	if (is_multicast_ether_addr(src)) {
-		/* Broadcast bit set in SA?! Ignore the frame silently. */
+	if (is_multicast_ether_addr(src) || is_zero_ether_addr(src) ||
+	    os_memcmp(src, hapd->own_addr, ETH_ALEN) == 0) {
+		/* Broadcast bit set in SA or unexpected SA?! Ignore the frame
+		 * silently. */
 		return;
 	}
 
diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
index b8453c9..f592da5 100644
--- a/src/ap/ieee802_11.h
+++ b/src/ap/ieee802_11.h
@@ -192,5 +192,6 @@
 		      int ap_seg1_idx, int *bandwidth, int *seg1_idx);
 
 void auth_sae_process_commit(void *eloop_ctx, void *user_ctx);
+u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len);
 
 #endif /* IEEE802_11_H */
diff --git a/src/ap/ieee802_11_he.c b/src/ap/ieee802_11_he.c
index a51f3fc..abd3940 100644
--- a/src/ap/ieee802_11_he.c
+++ b/src/ap/ieee802_11_he.c
@@ -11,6 +11,7 @@
 
 #include "utils/common.h"
 #include "common/ieee802_11_defs.h"
+#include "common/ieee802_11_common.h"
 #include "hostapd.h"
 #include "ap_config.h"
 #include "beacon.h"
@@ -44,6 +45,41 @@
 }
 
 
+static u8 ieee80211_he_mcs_set_size(const u8 *phy_cap_info)
+{
+	u8 sz = 4;
+
+	if (phy_cap_info[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
+	    HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G)
+		sz += 4;
+	if (phy_cap_info[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
+	    HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G)
+		sz += 4;
+
+	return sz;
+}
+
+
+static int ieee80211_invalid_he_cap_size(const u8 *buf, size_t len)
+{
+	struct ieee80211_he_capabilities *cap;
+	size_t cap_len;
+
+	cap = (struct ieee80211_he_capabilities *) buf;
+	cap_len = sizeof(*cap) - sizeof(cap->optional);
+	if (len < cap_len)
+		return 1;
+
+	cap_len += ieee80211_he_mcs_set_size(cap->he_phy_capab_info);
+	if (len < cap_len)
+		return 1;
+
+	cap_len += ieee80211_he_ppet_size(buf[cap_len], cap->he_phy_capab_info);
+
+	return len != cap_len;
+}
+
+
 u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid,
 			  enum ieee80211_op_mode opmode)
 {
@@ -51,12 +87,12 @@
 	struct hostapd_hw_modes *mode = hapd->iface->current_mode;
 	u8 he_oper_chwidth = ~HE_PHYCAP_CHANNEL_WIDTH_MASK;
 	u8 *pos = eid;
-	u8 ie_size = 0, mcs_nss_size = 0, ppet_size = 0;
+	u8 ie_size = 0, mcs_nss_size = 4, ppet_size = 0;
 
 	if (!mode)
 		return eid;
 
-	ie_size = sizeof(struct ieee80211_he_capabilities);
+	ie_size = sizeof(*cap) - sizeof(cap->optional);
 	ppet_size = ieee80211_he_ppet_size(mode->he_capab[opmode].ppet[0],
 					   mode->he_capab[opmode].phy_cap);
 
@@ -74,7 +110,6 @@
 	case CHANWIDTH_USE_HT:
 		he_oper_chwidth |= HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_IN_2G |
 			HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G;
-		mcs_nss_size += 4;
 		break;
 	}
 
@@ -136,6 +171,9 @@
 	if (!hapd->iface->current_mode)
 		return eid;
 
+	if (is_6ghz_op_class(hapd->iconf->op_class))
+		oper_size += 5;
+
 	*pos++ = WLAN_EID_EXTENSION;
 	*pos++ = 1 + oper_size;
 	*pos++ = WLAN_EID_EXT_HE_OPERATION;
@@ -164,9 +202,26 @@
 
 	/* TODO: conditional MaxBSSID Indicator subfield */
 
-	oper->he_oper_params = host_to_le32(params);
+	pos += 6; /* skip the fixed part */
 
-	pos += oper_size;
+	if (is_6ghz_op_class(hapd->iconf->op_class)) {
+		u8 seg0 = hostapd_get_oper_centr_freq_seg0_idx(hapd->iconf);
+
+		if (!seg0)
+			seg0 = hapd->iconf->channel;
+
+		params |= HE_OPERATION_6GHZ_OPER_INFO;
+		*pos++ = hapd->iconf->channel; /* Primary Channel */
+		*pos++ = center_idx_to_bw_6ghz(seg0); /* Control: Channel Width
+						       */
+		/* Channel Center Freq Seg0/Seg0 */
+		*pos++ = seg0;
+		*pos++ = hostapd_get_oper_centr_freq_seg1_idx(hapd->iconf);
+		/* Minimum Rate */
+		*pos++ = 6; /* TODO: what should be set here? */
+	}
+
+	oper->he_oper_params = host_to_le32(params);
 
 	return pos;
 }
@@ -325,6 +380,7 @@
 {
 	if (!he_capab || !hapd->iconf->ieee80211ax ||
 	    !check_valid_he_mcs(hapd, he_capab, opmode) ||
+	    ieee80211_invalid_he_cap_size(he_capab, he_capab_len) ||
 	    he_capab_len > sizeof(struct ieee80211_he_capabilities)) {
 		sta->flags &= ~WLAN_STA_HE;
 		os_free(sta->he_capab);
diff --git a/src/ap/ieee802_11_ht.c b/src/ap/ieee802_11_ht.c
index 214855d..6db9365 100644
--- a/src/ap/ieee802_11_ht.c
+++ b/src/ap/ieee802_11_ht.c
@@ -27,7 +27,7 @@
 	u8 *pos = eid;
 
 	if (!hapd->iconf->ieee80211n || !hapd->iface->current_mode ||
-	    hapd->conf->disable_11n)
+	    hapd->conf->disable_11n || is_6ghz_op_class(hapd->iconf->op_class))
 		return eid;
 
 	*pos++ = WLAN_EID_HT_CAP;
@@ -84,7 +84,8 @@
 	struct ieee80211_ht_operation *oper;
 	u8 *pos = eid;
 
-	if (!hapd->iconf->ieee80211n || hapd->conf->disable_11n)
+	if (!hapd->iconf->ieee80211n || hapd->conf->disable_11n ||
+	    is_6ghz_op_class(hapd->iconf->op_class))
 		return eid;
 
 	*pos++ = WLAN_EID_HT_OPERATION;
@@ -113,7 +114,8 @@
 	u8 sec_ch;
 
 	if (!hapd->cs_freq_params.channel ||
-	    !hapd->cs_freq_params.sec_channel_offset)
+	    !hapd->cs_freq_params.sec_channel_offset ||
+	    is_6ghz_op_class(hapd->iconf->op_class))
 		return eid;
 
 	if (hapd->cs_freq_params.sec_channel_offset == -1)
diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c
index 707381f..0b828e9 100644
--- a/src/ap/ieee802_11_shared.c
+++ b/src/ap/ieee802_11_shared.c
@@ -19,8 +19,6 @@
 #include "ieee802_11.h"
 
 
-#ifdef CONFIG_IEEE80211W
-
 u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd,
 				     struct sta_info *sta, u8 *eid)
 {
@@ -304,8 +302,6 @@
 	ap_sta_stop_sa_query(hapd, sta);
 }
 
-#endif /* CONFIG_IEEE80211W */
-
 
 static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
 {
@@ -404,14 +400,22 @@
 	u8 *pos = eid;
 	u8 len = 0, i;
 
-	if (hapd->conf->tdls & (TDLS_PROHIBIT | TDLS_PROHIBIT_CHAN_SWITCH))
+	if (hapd->conf->qos_map_set_len ||
+	    (hapd->conf->tdls & (TDLS_PROHIBIT | TDLS_PROHIBIT_CHAN_SWITCH)))
 		len = 5;
-	if (len < 4 && hapd->conf->interworking)
+	if (len < 4 &&
+	    (hapd->conf->time_advertisement == 2 || hapd->conf->interworking))
 		len = 4;
-	if (len < 3 && hapd->conf->wnm_sleep_mode)
+	if (len < 3 &&
+	    (hapd->conf->wnm_sleep_mode || hapd->conf->bss_transition))
 		len = 3;
-	if (len < 1 && hapd->iconf->obss_interval)
+	if (len < 1 &&
+	    (hapd->iconf->obss_interval ||
+	     (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA)))
 		len = 1;
+	if (len < 2 &&
+	    (hapd->conf->proxy_arp || hapd->conf->coloc_intf_reporting))
+		len = 2;
 	if (len < 7 && hapd->conf->ssid.utf8_ssid)
 		len = 7;
 	if (len < 9 &&
@@ -1000,3 +1004,22 @@
 	return 0;
 }
 #endif /* CONFIG_OCV */
+
+
+u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len)
+{
+	u8 *pos = eid;
+
+	if (!(hapd->conf->wpa & WPA_PROTO_RSN) ||
+	    (hapd->conf->sae_pwe != 1 && hapd->conf->sae_pwe != 2) ||
+	    len < 3)
+		return pos;
+
+	*pos++ = WLAN_EID_RSNX;
+	*pos++ = 1;
+	/* bits 0-3 = 0 since only one octet of Extended RSN Capabilities is
+	 * used for now */
+	*pos++ = BIT(WLAN_RSNX_CAPAB_SAE_H2E);
+
+	return pos;
+}
diff --git a/src/ap/ieee802_11_vht.c b/src/ap/ieee802_11_vht.c
index 269345f..f50f142 100644
--- a/src/ap/ieee802_11_vht.c
+++ b/src/ap/ieee802_11_vht.c
@@ -26,7 +26,7 @@
 	struct hostapd_hw_modes *mode = hapd->iface->current_mode;
 	u8 *pos = eid;
 
-	if (!mode)
+	if (!mode || is_6ghz_op_class(hapd->iconf->op_class))
 		return eid;
 
 	if (mode->mode == HOSTAPD_MODE_IEEE80211G && hapd->conf->vendor_vht &&
@@ -76,6 +76,9 @@
 	struct ieee80211_vht_operation *oper;
 	u8 *pos = eid;
 
+	if (is_6ghz_op_class(hapd->iconf->op_class))
+		return eid;
+
 	*pos++ = WLAN_EID_VHT_OPERATION;
 	*pos++ = sizeof(*oper);
 
diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c
index d628641..d081031 100644
--- a/src/ap/ieee802_1x.c
+++ b/src/ap/ieee802_1x.c
@@ -7,6 +7,9 @@
  */
 
 #include "utils/includes.h"
+#ifdef CONFIG_SQLITE
+#include <sqlite3.h>
+#endif /* CONFIG_SQLITE */
 
 #include "utils/common.h"
 #include "utils/eloop.h"
@@ -55,10 +58,9 @@
 
 	len = sizeof(*xhdr) + datalen;
 	buf = os_zalloc(len);
-	if (buf == NULL) {
-		wpa_printf(MSG_ERROR, "malloc() failed for "
-			   "ieee802_1x_send(len=%lu)",
-			   (unsigned long) len);
+	if (!buf) {
+		wpa_printf(MSG_ERROR, "malloc() failed for %s(len=%lu)",
+			   __func__, (unsigned long) len);
 		return;
 	}
 
@@ -149,12 +151,12 @@
 	size_t len, ekey_len;
 	struct eapol_state_machine *sm = sta->eapol_sm;
 
-	if (sm == NULL)
+	if (!sm)
 		return;
 
 	len = sizeof(*key) + key_len;
 	buf = os_zalloc(sizeof(*hdr) + len);
-	if (buf == NULL)
+	if (!buf)
 		return;
 
 	hdr = (struct ieee802_1x_hdr *) buf;
@@ -195,16 +197,16 @@
 
 	/* Key is encrypted using "Key-IV + MSK[0..31]" as the RC4-key and
 	 * MSK[32..63] is used to sign the message. */
-	if (sm->eap_if->eapKeyData == NULL || sm->eap_if->eapKeyDataLen < 64) {
-		wpa_printf(MSG_ERROR, "No eapKeyData available for encrypting "
-			   "and signing EAPOL-Key");
+	if (!sm->eap_if->eapKeyData || sm->eap_if->eapKeyDataLen < 64) {
+		wpa_printf(MSG_ERROR,
+			   "No eapKeyData available for encrypting and signing EAPOL-Key");
 		os_free(buf);
 		return;
 	}
 	os_memcpy((u8 *) (key + 1), key_data, key_len);
 	ekey_len = sizeof(key->key_iv) + 32;
 	ekey = os_malloc(ekey_len);
-	if (ekey == NULL) {
+	if (!ekey) {
 		wpa_printf(MSG_ERROR, "Could not encrypt key");
 		os_free(buf);
 		return;
@@ -241,7 +243,7 @@
 	struct eapol_authenticator *eapol = hapd->eapol_auth;
 	struct eapol_state_machine *sm = sta->eapol_sm;
 
-	if (sm == NULL || !sm->eap_if->eapKeyData)
+	if (!sm || !sm->eap_if->eapKeyData)
 		return;
 
 	wpa_printf(MSG_DEBUG, "IEEE 802.1X: Sending EAPOL-Key(s) to " MACSTR,
@@ -262,12 +264,13 @@
 
 	if (hapd->conf->individual_wep_key_len > 0) {
 		u8 *ikey;
+
 		ikey = os_malloc(hapd->conf->individual_wep_key_len);
-		if (ikey == NULL ||
+		if (!ikey ||
 		    random_get_bytes(ikey, hapd->conf->individual_wep_key_len))
 		{
-			wpa_printf(MSG_ERROR, "Could not generate random "
-				   "individual WEP key.");
+			wpa_printf(MSG_ERROR,
+				   "Could not generate random individual WEP key");
 			os_free(ikey);
 			return;
 		}
@@ -283,8 +286,8 @@
 		if (hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_WEP,
 					sta->addr, 0, 1, NULL, 0, ikey,
 					hapd->conf->individual_wep_key_len)) {
-			wpa_printf(MSG_ERROR, "Could not set individual WEP "
-				   "encryption.");
+			wpa_printf(MSG_ERROR,
+				   "Could not set individual WEP encryption");
 		}
 
 		os_free(ikey);
@@ -344,13 +347,13 @@
 
 	eap_erp_update_identity(sm->eap, eap, len);
 	identity = eap_get_identity(sm->eap, &identity_len);
-	if (identity == NULL)
+	if (!identity)
 		return;
 
 	/* Save station identity for future RADIUS packets */
 	os_free(sm->identity);
 	sm->identity = (u8 *) dup_binstr(identity, identity_len);
-	if (sm->identity == NULL) {
+	if (!sm->identity) {
 		sm->identity_len = 0;
 		return;
 	}
@@ -405,7 +408,6 @@
 		return -1;
 	}
 
-#ifdef CONFIG_IEEE80211W
 	if (hapd->conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
 		suite = wpa_cipher_to_suite(WPA_PROTO_RSN,
 					    hapd->conf->group_mgmt_cipher);
@@ -418,7 +420,6 @@
 			return -1;
 		}
 	}
-#endif /* CONFIG_IEEE80211W */
 
 	return 0;
 }
@@ -605,8 +606,7 @@
 		if (!radius_msg_add_attr(msg, attr->type,
 					 wpabuf_head(attr->val),
 					 wpabuf_len(attr->val))) {
-			wpa_printf(MSG_ERROR, "Could not add RADIUS "
-				   "attribute");
+			wpa_printf(MSG_ERROR, "Could not add RADIUS attribute");
 			return -1;
 		}
 	}
@@ -615,6 +615,63 @@
 }
 
 
+int add_sqlite_radius_attr(struct hostapd_data *hapd, struct sta_info *sta,
+			   struct radius_msg *msg, int acct)
+{
+#ifdef CONFIG_SQLITE
+	const char *attrtxt;
+	char addrtxt[3 * ETH_ALEN];
+	char *sql;
+	sqlite3_stmt *stmt = NULL;
+
+	if (!hapd->rad_attr_db)
+		return 0;
+
+	os_snprintf(addrtxt, sizeof(addrtxt), MACSTR, MAC2STR(sta->addr));
+
+	sql = "SELECT attr FROM radius_attributes WHERE sta=? AND (reqtype=? OR reqtype IS NULL);";
+	if (sqlite3_prepare_v2(hapd->rad_attr_db, sql, os_strlen(sql), &stmt,
+			       NULL) != SQLITE_OK) {
+		wpa_printf(MSG_ERROR, "DB: Failed to prepare SQL statement: %s",
+			   sqlite3_errmsg(hapd->rad_attr_db));
+		return -1;
+	}
+	sqlite3_bind_text(stmt, 1, addrtxt, os_strlen(addrtxt), SQLITE_STATIC);
+	sqlite3_bind_text(stmt, 2, acct ? "acct" : "auth", 4, SQLITE_STATIC);
+	while (sqlite3_step(stmt) == SQLITE_ROW) {
+		struct hostapd_radius_attr *attr;
+		struct radius_attr_hdr *hdr;
+
+		attrtxt = (const char *) sqlite3_column_text(stmt, 0);
+		attr = hostapd_parse_radius_attr(attrtxt);
+		if (!attr) {
+			wpa_printf(MSG_ERROR,
+				   "Skipping invalid attribute from SQL: %s",
+				   attrtxt);
+			continue;
+		}
+		wpa_printf(MSG_DEBUG, "Adding RADIUS attribute from SQL: %s",
+			   attrtxt);
+		hdr = radius_msg_add_attr(msg, attr->type,
+					  wpabuf_head(attr->val),
+					  wpabuf_len(attr->val));
+		hostapd_config_free_radius_attr(attr);
+		if (!hdr) {
+			wpa_printf(MSG_ERROR,
+				   "Could not add RADIUS attribute from SQL");
+			continue;
+		}
+	}
+
+	sqlite3_reset(stmt);
+	sqlite3_clear_bindings(stmt);
+	sqlite3_finalize(stmt);
+#endif /* CONFIG_SQLITE */
+
+	return 0;
+}
+
+
 void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd,
 				   struct sta_info *sta,
 				   const u8 *eap, size_t len)
@@ -622,18 +679,17 @@
 	struct radius_msg *msg;
 	struct eapol_state_machine *sm = sta->eapol_sm;
 
-	if (sm == NULL)
+	if (!sm)
 		return;
 
 	ieee802_1x_learn_identity(hapd, sm, eap, len);
 
-	wpa_printf(MSG_DEBUG, "Encapsulating EAP message into a RADIUS "
-		   "packet");
+	wpa_printf(MSG_DEBUG, "Encapsulating EAP message into a RADIUS packet");
 
 	sm->radius_identifier = radius_client_get_id(hapd->radius);
 	msg = radius_msg_new(RADIUS_CODE_ACCESS_REQUEST,
 			     sm->radius_identifier);
-	if (msg == NULL) {
+	if (!msg) {
 		wpa_printf(MSG_INFO, "Could not create new RADIUS packet");
 		return;
 	}
@@ -654,6 +710,9 @@
 				   msg) < 0)
 		goto fail;
 
+	if (sta && add_sqlite_radius_attr(hapd, sta, msg, 0) < 0)
+		goto fail;
+
 	/* TODO: should probably check MTU from driver config; 2304 is max for
 	 * IEEE 802.11, but use 1400 to avoid problems with too large packets
 	 */
@@ -677,12 +736,12 @@
 		int res = radius_msg_copy_attr(msg, sm->last_recv_radius,
 					       RADIUS_ATTR_STATE);
 		if (res < 0) {
-			wpa_printf(MSG_INFO, "Could not copy State attribute from previous Access-Challenge");
+			wpa_printf(MSG_INFO,
+				   "Could not copy State attribute from previous Access-Challenge");
 			goto fail;
 		}
-		if (res > 0) {
+		if (res > 0)
 			wpa_printf(MSG_DEBUG, "Copied RADIUS State Attribute");
-		}
 	}
 
 	if (hapd->conf->radius_request_cui) {
@@ -711,8 +770,8 @@
 		if (!radius_msg_add_wfa(
 			    msg, RADIUS_VENDOR_ATTR_WFA_HS20_AP_VERSION,
 			    &ver, 1)) {
-			wpa_printf(MSG_ERROR, "Could not add HS 2.0 AP "
-				   "version");
+			wpa_printf(MSG_ERROR,
+				   "Could not add HS 2.0 AP version");
 			goto fail;
 		}
 
@@ -720,6 +779,7 @@
 			const u8 *pos;
 			u8 buf[3];
 			u16 id;
+
 			pos = wpabuf_head_u8(sta->hs20_ie);
 			buf[0] = (*pos) >> 4;
 			if (((*pos) & HS20_PPS_MO_ID_PRESENT) &&
@@ -732,8 +792,8 @@
 				    msg,
 				    RADIUS_VENDOR_ATTR_WFA_HS20_STA_VERSION,
 				    buf, sizeof(buf))) {
-				wpa_printf(MSG_ERROR, "Could not add HS 2.0 "
-					   "STA version");
+				wpa_printf(MSG_ERROR,
+					   "Could not add HS 2.0 STA version");
 				goto fail;
 			}
 		}
@@ -792,13 +852,14 @@
 {
 	u8 type, *data;
 	struct eapol_state_machine *sm = sta->eapol_sm;
-	if (sm == NULL)
+
+	if (!sm)
 		return;
 
 	data = (u8 *) (eap + 1);
 
 	if (len < sizeof(*eap) + 1) {
-		wpa_printf(MSG_INFO, "handle_eap_response: too short response data");
+		wpa_printf(MSG_INFO, "%s: too short response data", __func__);
 		return;
 	}
 
@@ -826,12 +887,11 @@
 	u8 type, *data;
 	struct eapol_state_machine *sm = sta->eapol_sm;
 
-	if (sm == NULL)
+	if (!sm)
 		return;
 
 	if (len < sizeof(*eap) + 1) {
-		wpa_printf(MSG_INFO,
-			   "handle_eap_initiate: too short response data");
+		wpa_printf(MSG_INFO, "%s: too short response data", __func__);
 		return;
 	}
 
@@ -839,8 +899,8 @@
 	type = data[0];
 
 	hostapd_logger(hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X,
-		       HOSTAPD_LEVEL_DEBUG, "received EAP packet (code=%d "
-		       "id=%d len=%d) from STA: EAP Initiate type %u",
+		       HOSTAPD_LEVEL_DEBUG,
+		       "received EAP packet (code=%d id=%d len=%d) from STA: EAP Initiate type %u",
 		       eap->code, eap->identifier, be_to_host16(eap->length),
 		       type);
 
@@ -851,6 +911,29 @@
 }
 
 
+#ifndef CONFIG_NO_STDOUT_DEBUG
+static const char * eap_code_str(u8 code)
+{
+	switch (code) {
+	case EAP_CODE_REQUEST:
+		return "request";
+	case EAP_CODE_RESPONSE:
+		return "response";
+	case EAP_CODE_SUCCESS:
+		return "success";
+	case EAP_CODE_FAILURE:
+		return "failure";
+	case EAP_CODE_INITIATE:
+		return "initiate";
+	case EAP_CODE_FINISH:
+		return "finish";
+	default:
+		return "unknown";
+	}
+}
+#endif /* CONFIG_NO_STDOUT_DEBUG */
+
+
 /* Process incoming EAP packet from Supplicant */
 static void handle_eap(struct hostapd_data *hapd, struct sta_info *sta,
 		       u8 *buf, size_t len)
@@ -866,44 +949,29 @@
 	eap = (struct eap_hdr *) buf;
 
 	eap_len = be_to_host16(eap->length);
-	wpa_printf(MSG_DEBUG, "EAP: code=%d identifier=%d length=%d",
-		   eap->code, eap->identifier, eap_len);
+	wpa_printf(MSG_DEBUG, "EAP: code=%d (%s) identifier=%d length=%d",
+		   eap->code, eap_code_str(eap->code), eap->identifier,
+		   eap_len);
 	if (eap_len < sizeof(*eap)) {
 		wpa_printf(MSG_DEBUG, "   Invalid EAP length");
 		return;
 	} else if (eap_len > len) {
-		wpa_printf(MSG_DEBUG, "   Too short frame to contain this EAP "
-			   "packet");
+		wpa_printf(MSG_DEBUG,
+			   "   Too short frame to contain this EAP packet");
 		return;
 	} else if (eap_len < len) {
-		wpa_printf(MSG_DEBUG, "   Ignoring %lu extra bytes after EAP "
-			   "packet", (unsigned long) len - eap_len);
+		wpa_printf(MSG_DEBUG,
+			   "   Ignoring %lu extra bytes after EAP packet",
+			   (unsigned long) len - eap_len);
 	}
 
 	switch (eap->code) {
-	case EAP_CODE_REQUEST:
-		wpa_printf(MSG_DEBUG, " (request)");
-		return;
 	case EAP_CODE_RESPONSE:
-		wpa_printf(MSG_DEBUG, " (response)");
 		handle_eap_response(hapd, sta, eap, eap_len);
 		break;
-	case EAP_CODE_SUCCESS:
-		wpa_printf(MSG_DEBUG, " (success)");
-		return;
-	case EAP_CODE_FAILURE:
-		wpa_printf(MSG_DEBUG, " (failure)");
-		return;
 	case EAP_CODE_INITIATE:
-		wpa_printf(MSG_DEBUG, " (initiate)");
 		handle_eap_initiate(hapd, sta, eap, eap_len);
 		break;
-	case EAP_CODE_FINISH:
-		wpa_printf(MSG_DEBUG, " (finish)");
-		break;
-	default:
-		wpa_printf(MSG_DEBUG, " (unknown code)");
-		return;
 	}
 }
 
@@ -912,6 +980,7 @@
 ieee802_1x_alloc_eapol_sm(struct hostapd_data *hapd, struct sta_info *sta)
 {
 	int flags = 0;
+
 	if (sta->flags & WLAN_STA_PREAUTH)
 		flags |= EAPOL_SM_PREAUTH;
 	if (sta->wpa_sm) {
@@ -976,8 +1045,8 @@
 	sta = ap_get_sta(hapd, sa);
 	if (!sta || (!(sta->flags & (WLAN_STA_ASSOC | WLAN_STA_PREAUTH)) &&
 		     !(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_WIRED))) {
-		wpa_printf(MSG_DEBUG, "IEEE 802.1X data frame from not "
-			   "associated/Pre-authenticating STA");
+		wpa_printf(MSG_DEBUG,
+			   "IEEE 802.1X data frame from not associated/Pre-authenticating STA");
 
 		if (sta && (sta->flags & WLAN_STA_AUTH)) {
 			wpa_printf(MSG_DEBUG, "Saving EAPOL frame from " MACSTR
@@ -999,14 +1068,15 @@
 		   hdr->version, hdr->type, datalen);
 
 	if (len - sizeof(*hdr) < datalen) {
-		wpa_printf(MSG_INFO, "   frame too short for this IEEE 802.1X packet");
+		wpa_printf(MSG_INFO,
+			   "   frame too short for this IEEE 802.1X packet");
 		if (sta->eapol_sm)
 			sta->eapol_sm->dot1xAuthEapLengthErrorFramesRx++;
 		return;
 	}
 	if (len - sizeof(*hdr) > datalen) {
-		wpa_printf(MSG_DEBUG, "   ignoring %lu extra octets after "
-			   "IEEE 802.1X packet",
+		wpa_printf(MSG_DEBUG,
+			   "   ignoring %lu extra octets after IEEE 802.1X packet",
 			   (unsigned long) len - sizeof(*hdr) - datalen);
 	}
 
@@ -1027,8 +1097,8 @@
 
 	if (!hapd->conf->ieee802_1x && !hapd->conf->osen &&
 	    !(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) {
-		wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore EAPOL message - "
-			   "802.1X not enabled and WPS not used");
+		wpa_printf(MSG_DEBUG,
+			   "IEEE 802.1X: Ignore EAPOL message - 802.1X not enabled and WPS not used");
 		return;
 	}
 
@@ -1036,8 +1106,8 @@
 	if (key_mgmt != -1 &&
 	    (wpa_key_mgmt_wpa_psk(key_mgmt) || key_mgmt == WPA_KEY_MGMT_OWE ||
 	     key_mgmt == WPA_KEY_MGMT_DPP)) {
-		wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore EAPOL message - "
-			   "STA is using PSK");
+		wpa_printf(MSG_DEBUG,
+			   "IEEE 802.1X: Ignore EAPOL message - STA is using PSK");
 		return;
 	}
 
@@ -1060,9 +1130,8 @@
 				 * skipped if the STA is known to support WPS
 				 * 2.0.
 				 */
-				wpa_printf(MSG_DEBUG, "WPS: Do not start "
-					   "EAPOL until EAPOL-Start is "
-					   "received");
+				wpa_printf(MSG_DEBUG,
+					   "WPS: Do not start EAPOL until EAPOL-Start is received");
 				sta->eapol_sm->flags |= EAPOL_SM_WAIT_START;
 			}
 		}
@@ -1085,15 +1154,14 @@
 
 	case IEEE802_1X_TYPE_EAPOL_START:
 		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
-			       HOSTAPD_LEVEL_DEBUG, "received EAPOL-Start "
-			       "from STA");
+			       HOSTAPD_LEVEL_DEBUG,
+			       "received EAPOL-Start from STA");
 		sta->eapol_sm->flags &= ~EAPOL_SM_WAIT_START;
 		pmksa = wpa_auth_sta_get_pmksa(sta->wpa_sm);
 		if (pmksa) {
 			hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,
-				       HOSTAPD_LEVEL_DEBUG, "cached PMKSA "
-				       "available - ignore it since "
-				       "STA sent EAPOL-Start");
+				       HOSTAPD_LEVEL_DEBUG,
+				       "cached PMKSA available - ignore it since STA sent EAPOL-Start");
 			wpa_auth_sta_clear_pmksa(sta->wpa_sm, pmksa);
 		}
 		sta->eapol_sm->eapolStart = TRUE;
@@ -1104,8 +1172,8 @@
 
 	case IEEE802_1X_TYPE_EAPOL_LOGOFF:
 		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
-			       HOSTAPD_LEVEL_DEBUG, "received EAPOL-Logoff "
-			       "from STA");
+			       HOSTAPD_LEVEL_DEBUG,
+			       "received EAPOL-Logoff from STA");
 		sta->acct_terminate_cause =
 			RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
 		accounting_sta_stop(hapd, sta);
@@ -1117,8 +1185,8 @@
 	case IEEE802_1X_TYPE_EAPOL_KEY:
 		wpa_printf(MSG_DEBUG, "   EAPOL-Key");
 		if (!ap_sta_is_authorized(sta)) {
-			wpa_printf(MSG_DEBUG, "   Dropped key data from "
-				   "unauthorized Supplicant");
+			wpa_printf(MSG_DEBUG,
+				   "   Dropped key data from unauthorized Supplicant");
 			break;
 		}
 		break;
@@ -1174,8 +1242,8 @@
 #endif /* CONFIG_WPS */
 
 	if (!force_1x && !hapd->conf->ieee802_1x && !hapd->conf->osen) {
-		wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore STA - "
-			   "802.1X not enabled or forced for WPS");
+		wpa_printf(MSG_DEBUG,
+			   "IEEE 802.1X: Ignore STA - 802.1X not enabled or forced for WPS");
 		/*
 		 * Clear any possible EAPOL authenticator state to support
 		 * reassociation change from WPS to PSK.
@@ -1197,11 +1265,11 @@
 		return;
 	}
 
-	if (sta->eapol_sm == NULL) {
+	if (!sta->eapol_sm) {
 		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
 			       HOSTAPD_LEVEL_DEBUG, "start authentication");
 		sta->eapol_sm = ieee802_1x_alloc_eapol_sm(hapd, sta);
-		if (sta->eapol_sm == NULL) {
+		if (!sta->eapol_sm) {
 			hostapd_logger(hapd, sta->addr,
 				       HOSTAPD_MODULE_IEEE8021X,
 				       HOSTAPD_LEVEL_INFO,
@@ -1220,8 +1288,8 @@
 		 * initiates the handshake with EAPOL-Start. Only allow the
 		 * wait to be skipped if the STA is known to support WPS 2.0.
 		 */
-		wpa_printf(MSG_DEBUG, "WPS: Do not start EAPOL until "
-			   "EAPOL-Start is received");
+		wpa_printf(MSG_DEBUG,
+			   "WPS: Do not start EAPOL until EAPOL-Start is received");
 		sta->eapol_sm->flags |= EAPOL_SM_WAIT_START;
 	}
 #endif /* CONFIG_WPS */
@@ -1317,7 +1385,7 @@
 		sta->pending_eapol_rx = NULL;
 	}
 
-	if (sm == NULL)
+	if (!sm)
 		return;
 
 	sta->eapol_sm = NULL;
@@ -1342,7 +1410,7 @@
 	struct radius_msg *msg;
 	struct eapol_state_machine *sm = sta->eapol_sm;
 
-	if (sm == NULL || sm->last_recv_radius == NULL) {
+	if (!sm || !sm->last_recv_radius) {
 		if (sm)
 			sm->eap_if->aaaEapNoReq = TRUE;
 		return;
@@ -1351,21 +1419,21 @@
 	msg = sm->last_recv_radius;
 
 	eap = radius_msg_get_eap(msg);
-	if (eap == NULL) {
+	if (!eap) {
 		/* RFC 3579, Chap. 2.6.3:
 		 * RADIUS server SHOULD NOT send Access-Reject/no EAP-Message
 		 * attribute */
 		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
-			       HOSTAPD_LEVEL_WARNING, "could not extract "
-			       "EAP-Message from RADIUS message");
+			       HOSTAPD_LEVEL_WARNING,
+			       "could not extract EAP-Message from RADIUS message");
 		sm->eap_if->aaaEapNoReq = TRUE;
 		return;
 	}
 
 	if (wpabuf_len(eap) < sizeof(*hdr)) {
 		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
-			       HOSTAPD_LEVEL_WARNING, "too short EAP packet "
-			       "received from authentication server");
+			       HOSTAPD_LEVEL_WARNING,
+			       "too short EAP packet received from authentication server");
 		wpabuf_free(eap);
 		sm->eap_if->aaaEapNoReq = TRUE;
 		return;
@@ -1398,8 +1466,8 @@
 	}
 	buf[sizeof(buf) - 1] = '\0';
 	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
-		       HOSTAPD_LEVEL_DEBUG, "decapsulated EAP packet (code=%d "
-		       "id=%d len=%d) from RADIUS server: %s",
+		       HOSTAPD_LEVEL_DEBUG,
+		       "decapsulated EAP packet (code=%d id=%d len=%d) from RADIUS server: %s",
 		       hdr->code, hdr->identifier, be_to_host16(hdr->length),
 		       buf);
 	sm->eap_if->aaaEapReq = TRUE;
@@ -1419,7 +1487,8 @@
 	u8 *buf;
 	size_t len;
 	struct eapol_state_machine *sm = sta->eapol_sm;
-	if (sm == NULL)
+
+	if (!sm)
 		return;
 
 	keys = radius_msg_get_ms_keys(msg, req, shared_secret,
@@ -1482,8 +1551,7 @@
 	struct radius_attr_data *nclass;
 	size_t nclass_count;
 
-	if (!hapd->conf->radius->acct_server || hapd->radius == NULL ||
-	    sm == NULL)
+	if (!hapd->conf->radius->acct_server || !hapd->radius || !sm)
 		return;
 
 	radius_free_class(&sm->radius_class);
@@ -1492,7 +1560,7 @@
 		return;
 
 	nclass = os_calloc(count, sizeof(struct radius_attr_data));
-	if (nclass == NULL)
+	if (!nclass)
 		return;
 
 	nclass_count = 0;
@@ -1509,7 +1577,7 @@
 		} while (class_len < 1);
 
 		nclass[nclass_count].data = os_memdup(attr_class, class_len);
-		if (nclass[nclass_count].data == NULL)
+		if (!nclass[nclass_count].data)
 			break;
 
 		nclass[nclass_count].len = class_len;
@@ -1518,8 +1586,9 @@
 
 	sm->radius_class.attr = nclass;
 	sm->radius_class.count = nclass_count;
-	wpa_printf(MSG_DEBUG, "IEEE 802.1X: Stored %lu RADIUS Class "
-		   "attributes for " MACSTR,
+	wpa_printf(MSG_DEBUG,
+		   "IEEE 802.1X: Stored %lu RADIUS Class attributes for "
+		   MACSTR,
 		   (unsigned long) sm->radius_class.count,
 		   MAC2STR(sta->addr));
 }
@@ -1534,7 +1603,7 @@
 	size_t len;
 	struct eapol_state_machine *sm = sta->eapol_sm;
 
-	if (sm == NULL)
+	if (!sm)
 		return;
 
 	if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_USER_NAME, &buf, &len,
@@ -1542,12 +1611,12 @@
 		return;
 
 	identity = (u8 *) dup_binstr(buf, len);
-	if (identity == NULL)
+	if (!identity)
 		return;
 
 	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
-		       HOSTAPD_LEVEL_DEBUG, "old identity '%s' updated with "
-		       "User-Name from Access-Accept '%s'",
+		       HOSTAPD_LEVEL_DEBUG,
+		       "old identity '%s' updated with User-Name from Access-Accept '%s'",
 		       sm->identity ? (char *) sm->identity : "N/A",
 		       (char *) identity);
 
@@ -1567,7 +1636,7 @@
 	u8 *buf;
 	size_t len;
 
-	if (sm == NULL)
+	if (!sm)
 		return;
 
 	if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_CHARGEABLE_USER_IDENTITY,
@@ -1575,7 +1644,7 @@
 		return;
 
 	cui = wpabuf_alloc_copy(buf, len);
-	if (cui == NULL)
+	if (!cui)
 		return;
 
 	wpabuf_free(sm->radius_cui);
@@ -1596,14 +1665,16 @@
 		sta->remediation_method = pos[0];
 		os_memcpy(sta->remediation_url, pos + 1, len - 1);
 		sta->remediation_url[len - 1] = '\0';
-		wpa_printf(MSG_DEBUG, "HS 2.0: Subscription remediation needed "
-			   "for " MACSTR " - server method %u URL %s",
+		wpa_printf(MSG_DEBUG,
+			   "HS 2.0: Subscription remediation needed for "
+			   MACSTR " - server method %u URL %s",
 			   MAC2STR(sta->addr), sta->remediation_method,
 			   sta->remediation_url);
 	} else {
 		sta->remediation_url = NULL;
-		wpa_printf(MSG_DEBUG, "HS 2.0: Subscription remediation needed "
-			   "for " MACSTR, MAC2STR(sta->addr));
+		wpa_printf(MSG_DEBUG,
+			   "HS 2.0: Subscription remediation needed for "
+			   MACSTR, MAC2STR(sta->addr));
 	}
 	/* TODO: assign the STA into remediation VLAN or add filtering */
 }
@@ -1616,8 +1687,8 @@
 	if (len < 3)
 		return; /* Malformed information */
 	sta->hs20_deauth_requested = 1;
-	wpa_printf(MSG_DEBUG, "HS 2.0: Deauthentication request - Code %u  "
-		   "Re-auth Delay %u",
+	wpa_printf(MSG_DEBUG,
+		   "HS 2.0: Deauthentication request - Code %u  Re-auth Delay %u",
 		   *pos, WPA_GET_LE16(pos + 1));
 	wpabuf_free(sta->hs20_deauth_req);
 	sta->hs20_deauth_req = wpabuf_alloc(len + 1);
@@ -1641,16 +1712,17 @@
 		return; /* Malformed information */
 	os_free(sta->hs20_session_info_url);
 	sta->hs20_session_info_url = os_malloc(len);
-	if (sta->hs20_session_info_url == NULL)
+	if (!sta->hs20_session_info_url)
 		return;
 	swt = pos[0];
 	os_memcpy(sta->hs20_session_info_url, pos + 1, len - 1);
 	sta->hs20_session_info_url[len - 1] = '\0';
-	wpa_printf(MSG_DEBUG, "HS 2.0: Session Information URL='%s' SWT=%u "
-		   "(session_timeout=%d)",
+	wpa_printf(MSG_DEBUG,
+		   "HS 2.0: Session Information URL='%s' SWT=%u (session_timeout=%d)",
 		   sta->hs20_session_info_url, swt, session_timeout);
 	if (session_timeout < 0) {
-		wpa_printf(MSG_DEBUG, "HS 2.0: No Session-Timeout set - ignore session info URL");
+		wpa_printf(MSG_DEBUG,
+			   "HS 2.0: No Session-Timeout set - ignore session info URL");
 		return;
 	}
 	if (swt == 255)
@@ -1783,6 +1855,7 @@
 ieee802_1x_search_radius_identifier(struct hostapd_data *hapd, u8 identifier)
 {
 	struct sta_id_search id_search;
+
 	id_search.identifier = identifier;
 	id_search.sm = NULL;
 	ap_for_each_sta(hapd, ieee802_1x_select_radius_identifier, &id_search);
@@ -1853,9 +1926,9 @@
 	struct radius_hdr *hdr = radius_msg_get_hdr(msg);
 
 	sm = ieee802_1x_search_radius_identifier(hapd, hdr->identifier);
-	if (sm == NULL) {
-		wpa_printf(MSG_DEBUG, "IEEE 802.1X: Could not find matching "
-			   "station for this RADIUS message");
+	if (!sm) {
+		wpa_printf(MSG_DEBUG,
+			   "IEEE 802.1X: Could not find matching station for this RADIUS message");
 		return RADIUS_RX_UNKNOWN;
 	}
 	sta = sm->sta;
@@ -1866,12 +1939,12 @@
 	    radius_msg_get_attr(msg, RADIUS_ATTR_MESSAGE_AUTHENTICATOR, NULL,
 				0) < 0 &&
 	    radius_msg_get_attr(msg, RADIUS_ATTR_EAP_MESSAGE, NULL, 0) < 0) {
-		wpa_printf(MSG_DEBUG, "Allowing RADIUS Access-Reject without "
-			   "Message-Authenticator since it does not include "
-			   "EAP-Message");
+		wpa_printf(MSG_DEBUG,
+			   "Allowing RADIUS Access-Reject without Message-Authenticator since it does not include EAP-Message");
 	} else if (radius_msg_verify(msg, shared_secret, shared_secret_len,
 				     req, 1)) {
-		wpa_printf(MSG_INFO, "Incoming RADIUS packet did not have correct Message-Authenticator - dropped");
+		wpa_printf(MSG_INFO,
+			   "Incoming RADIUS packet did not have correct Message-Authenticator - dropped");
 		return RADIUS_RX_INVALID_AUTHENTICATOR;
 	}
 
@@ -1904,8 +1977,7 @@
 			hostapd_logger(hapd, sta->addr,
 				       HOSTAPD_MODULE_IEEE8021X,
 				       HOSTAPD_LEVEL_INFO,
-				       "ignored too small "
-				       "Acct-Interim-Interval %d",
+				       "ignored too small Acct-Interim-Interval %d",
 				       acct_interim_interval);
 		} else
 			sta->acct_interim_interval = acct_interim_interval;
@@ -1974,8 +2046,7 @@
 			hostapd_logger(hapd, sm->addr,
 				       HOSTAPD_MODULE_IEEE8021X,
 				       HOSTAPD_LEVEL_DEBUG,
-				       "using EAP timeout of %d seconds (from "
-				       "RADIUS)",
+				       "using EAP timeout of %d seconds (from RADIUS)",
 				       sm->eap_if->aaaMethodTimeout);
 		} else {
 			/*
@@ -2014,7 +2085,8 @@
 void ieee802_1x_abort_auth(struct hostapd_data *hapd, struct sta_info *sta)
 {
 	struct eapol_state_machine *sm = sta->eapol_sm;
-	if (sm == NULL)
+
+	if (!sm)
 		return;
 
 	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
@@ -2050,7 +2122,7 @@
 
 	os_free(eapol->default_wep_key);
 	eapol->default_wep_key = os_malloc(hapd->conf->default_wep_key_len);
-	if (eapol->default_wep_key == NULL ||
+	if (!eapol->default_wep_key ||
 	    random_get_bytes(eapol->default_wep_key,
 			     hapd->conf->default_wep_key_len)) {
 		wpa_printf(MSG_INFO, "Could not generate random WEP key");
@@ -2094,8 +2166,8 @@
 
 	if (ieee802_1x_rekey_broadcast(hapd)) {
 		hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE8021X,
-			       HOSTAPD_LEVEL_WARNING, "failed to generate a "
-			       "new broadcast key");
+			       HOSTAPD_LEVEL_WARNING,
+			       "failed to generate a new broadcast key");
 		os_free(eapol->default_wep_key);
 		eapol->default_wep_key = NULL;
 		return;
@@ -2109,8 +2181,8 @@
 				eapol->default_wep_key,
 				hapd->conf->default_wep_key_len)) {
 		hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE8021X,
-			       HOSTAPD_LEVEL_WARNING, "failed to configure a "
-			       "new broadcast key");
+			       HOSTAPD_LEVEL_WARNING,
+			       "failed to configure a new broadcast key");
 		os_free(eapol->default_wep_key);
 		eapol->default_wep_key = NULL;
 		return;
@@ -2145,8 +2217,8 @@
 		     (identity_len == WSC_ID_REGISTRAR_LEN &&
 		      os_memcmp(identity, WSC_ID_REGISTRAR,
 				WSC_ID_REGISTRAR_LEN) == 0))) {
-			wpa_printf(MSG_DEBUG, "WPS: WLAN_STA_MAYBE_WPS -> "
-				   "WLAN_STA_WPS");
+			wpa_printf(MSG_DEBUG,
+				   "WPS: WLAN_STA_MAYBE_WPS -> WLAN_STA_WPS");
 			sta->flags |= WLAN_STA_WPS;
 		}
 	}
@@ -2173,6 +2245,7 @@
 {
 	struct hostapd_data *hapd = ctx;
 	struct sta_info *sta = sta_ctx;
+
 	if (preauth)
 		rsn_preauth_finished(hapd, sta, success);
 	else
@@ -2190,7 +2263,7 @@
 	int rv = -1;
 
 	eap_user = hostapd_get_eap_user(hapd, identity, identity_len, phase2);
-	if (eap_user == NULL)
+	if (!eap_user)
 		goto out;
 
 	os_memset(user, 0, sizeof(*user));
@@ -2203,7 +2276,7 @@
 	if (eap_user->password) {
 		user->password = os_memdup(eap_user->password,
 					   eap_user->password_len);
-		if (user->password == NULL)
+		if (!user->password)
 			goto out;
 		user->password_len = eap_user->password_len;
 		user->password_hash = eap_user->password_hash;
@@ -2233,8 +2306,9 @@
 {
 	struct hostapd_data *hapd = ctx;
 	struct sta_info *sta;
+
 	sta = ap_get_sta(hapd, addr);
-	if (sta == NULL || sta->eapol_sm == NULL)
+	if (!sta || !sta->eapol_sm)
 		return 0;
 	return 1;
 }
@@ -2271,6 +2345,7 @@
 {
 	struct hostapd_data *hapd = ctx;
 	struct sta_info *sta = sta_ctx;
+
 	ieee802_1x_set_sta_authorized(hapd, sta, authorized);
 }
 
@@ -2279,6 +2354,7 @@
 {
 	struct hostapd_data *hapd = ctx;
 	struct sta_info *sta = sta_ctx;
+
 	ieee802_1x_abort_auth(hapd, sta);
 }
 
@@ -2289,6 +2365,7 @@
 #ifndef CONFIG_NO_RC4
 	struct hostapd_data *hapd = ctx;
 	struct sta_info *sta = sta_ctx;
+
 	ieee802_1x_tx_key(hapd, sta);
 #endif /* CONFIG_NO_RC4 */
 #endif /* CONFIG_FIPS */
@@ -2300,6 +2377,7 @@
 {
 	/* struct hostapd_data *hapd = ctx; */
 	struct sta_info *sta = sta_ctx;
+
 	switch (type) {
 	case EAPOL_AUTH_SM_CHANGE:
 		wpa_auth_sm_notify(sta->wpa_sm);
@@ -2349,43 +2427,15 @@
 	dl_list_init(&hapd->erp_keys);
 
 	os_memset(&conf, 0, sizeof(conf));
+	conf.eap_cfg = hapd->eap_cfg;
 	conf.ctx = hapd;
 	conf.eap_reauth_period = hapd->conf->eap_reauth_period;
 	conf.wpa = hapd->conf->wpa;
 	conf.individual_wep_key_len = hapd->conf->individual_wep_key_len;
-	conf.eap_server = hapd->conf->eap_server;
-	conf.ssl_ctx = hapd->ssl_ctx;
-	conf.msg_ctx = hapd->msg_ctx;
-	conf.eap_sim_db_priv = hapd->eap_sim_db_priv;
 	conf.eap_req_id_text = hapd->conf->eap_req_id_text;
 	conf.eap_req_id_text_len = hapd->conf->eap_req_id_text_len;
 	conf.erp_send_reauth_start = hapd->conf->erp_send_reauth_start;
 	conf.erp_domain = hapd->conf->erp_domain;
-	conf.erp = hapd->conf->eap_server_erp;
-	conf.tls_session_lifetime = hapd->conf->tls_session_lifetime;
-	conf.tls_flags = hapd->conf->tls_flags;
-	conf.pac_opaque_encr_key = hapd->conf->pac_opaque_encr_key;
-	conf.eap_fast_a_id = hapd->conf->eap_fast_a_id;
-	conf.eap_fast_a_id_len = hapd->conf->eap_fast_a_id_len;
-	conf.eap_fast_a_id_info = hapd->conf->eap_fast_a_id_info;
-	conf.eap_fast_prov = hapd->conf->eap_fast_prov;
-	conf.pac_key_lifetime = hapd->conf->pac_key_lifetime;
-	conf.pac_key_refresh_time = hapd->conf->pac_key_refresh_time;
-	conf.eap_teap_auth = hapd->conf->eap_teap_auth;
-	conf.eap_teap_pac_no_inner = hapd->conf->eap_teap_pac_no_inner;
-	conf.eap_sim_aka_result_ind = hapd->conf->eap_sim_aka_result_ind;
-	conf.tnc = hapd->conf->tnc;
-	conf.wps = hapd->wps;
-	conf.fragment_size = hapd->conf->fragment_size;
-	conf.pwd_group = hapd->conf->pwd_group;
-	conf.pbc_in_m1 = hapd->conf->pbc_in_m1;
-	if (hapd->conf->server_id) {
-		conf.server_id = (const u8 *) hapd->conf->server_id;
-		conf.server_id_len = os_strlen(hapd->conf->server_id);
-	} else {
-		conf.server_id = (const u8 *) "hostapd";
-		conf.server_id_len = 7;
-	}
 
 	os_memset(&cb, 0, sizeof(cb));
 	cb.eapol_send = ieee802_1x_eapol_send;
@@ -2404,7 +2454,7 @@
 #endif /* CONFIG_ERP */
 
 	hapd->eapol_auth = eapol_auth_init(&conf, &cb);
-	if (hapd->eapol_auth == NULL)
+	if (!hapd->eapol_auth)
 		return -1;
 
 	if ((hapd->conf->ieee802_1x || hapd->conf->wpa) &&
@@ -2425,7 +2475,7 @@
 
 		ieee802_1x_rekey(hapd, NULL);
 
-		if (hapd->eapol_auth->default_wep_key == NULL)
+		if (!hapd->eapol_auth->default_wep_key)
 			return -1;
 	}
 
@@ -2468,7 +2518,7 @@
 	const unsigned char rfc1042_hdr[ETH_ALEN] =
 		{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
 
-	if (sta == NULL)
+	if (!sta)
 		return -1;
 	if (len < sizeof(*hdr) + sizeof(rfc1042_hdr) + 2)
 		return 0;
@@ -2497,8 +2547,8 @@
 
 	if (len < (int) sizeof(*xhdr))
 		return 0;
-	wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR " TX status - version=%d "
-		   "type=%d length=%d - ack=%d",
+	wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR
+		   " TX status - version=%d type=%d length=%d - ack=%d",
 		   MAC2STR(sta->addr), xhdr->version, xhdr->type,
 		   be_to_host16(xhdr->length), ack);
 
@@ -2517,6 +2567,7 @@
 
 	if (pos + sizeof(struct wpa_eapol_key) <= buf + len) {
 		const struct wpa_eapol_key *wpa;
+
 		wpa = (const struct wpa_eapol_key *) pos;
 		if (wpa->type == EAPOL_KEY_TYPE_RSN ||
 		    wpa->type == EAPOL_KEY_TYPE_WPA)
@@ -2532,8 +2583,8 @@
 	if (!ack && pos + sizeof(*key) <= buf + len) {
 		key = (struct ieee802_1x_eapol_key *) pos;
 		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
-			       HOSTAPD_LEVEL_DEBUG, "did not Ack EAPOL-Key "
-			       "frame (%scast index=%d)",
+			       HOSTAPD_LEVEL_DEBUG,
+			       "did not Ack EAPOL-Key frame (%scast index=%d)",
 			       key->key_index & BIT(7) ? "uni" : "broad",
 			       key->key_index & ~BIT(7));
 		/* TODO: re-send EAPOL-Key couple of times (with short delay
@@ -2553,7 +2604,7 @@
 
 u8 * ieee802_1x_get_identity(struct eapol_state_machine *sm, size_t *len)
 {
-	if (sm == NULL || sm->identity == NULL)
+	if (!sm || !sm->identity)
 		return NULL;
 
 	*len = sm->identity_len;
@@ -2564,7 +2615,7 @@
 u8 * ieee802_1x_get_radius_class(struct eapol_state_machine *sm, size_t *len,
 				 int idx)
 {
-	if (sm == NULL || sm->radius_class.attr == NULL ||
+	if (!sm || !sm->radius_class.attr ||
 	    idx >= (int) sm->radius_class.count)
 		return NULL;
 
@@ -2575,7 +2626,7 @@
 
 struct wpabuf * ieee802_1x_get_radius_cui(struct eapol_state_machine *sm)
 {
-	if (sm == NULL)
+	if (!sm)
 		return NULL;
 	return sm->radius_cui;
 }
@@ -2584,7 +2635,7 @@
 const u8 * ieee802_1x_get_key(struct eapol_state_machine *sm, size_t *len)
 {
 	*len = 0;
-	if (sm == NULL)
+	if (!sm)
 		return NULL;
 
 	*len = sm->eap_if->eapKeyDataLen;
@@ -2609,7 +2660,7 @@
 void ieee802_1x_notify_port_enabled(struct eapol_state_machine *sm,
 				    int enabled)
 {
-	if (sm == NULL)
+	if (!sm)
 		return;
 	sm->eap_if->portEnabled = enabled ? TRUE : FALSE;
 	eapol_auth_step(sm);
@@ -2619,7 +2670,7 @@
 void ieee802_1x_notify_port_valid(struct eapol_state_machine *sm,
 				  int valid)
 {
-	if (sm == NULL)
+	if (!sm)
 		return;
 	sm->portValid = valid ? TRUE : FALSE;
 	eapol_auth_step(sm);
@@ -2628,7 +2679,7 @@
 
 void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, int pre_auth)
 {
-	if (sm == NULL)
+	if (!sm)
 		return;
 	if (pre_auth)
 		sm->flags |= EAPOL_SM_PREAUTH;
@@ -2660,7 +2711,7 @@
 	const char *name2;
 	char *identity_buf = NULL;
 
-	if (sm == NULL)
+	if (!sm)
 		return 0;
 
 	ret = os_snprintf(buf + len, buflen - len,
diff --git a/src/ap/ieee802_1x.h b/src/ap/ieee802_1x.h
index d771ba5..bb85b93 100644
--- a/src/ap/ieee802_1x.h
+++ b/src/ap/ieee802_1x.h
@@ -59,6 +59,8 @@
 			   struct hostapd_radius_attr *req_attr,
 			   struct sta_info *sta,
 			   struct radius_msg *msg);
+int add_sqlite_radius_attr(struct hostapd_data *hapd, struct sta_info *sta,
+			   struct radius_msg *msg, int acct);
 void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd,
 				   struct sta_info *sta,
 				   const u8 *eap, size_t len);
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index 51d7884..cbb8752 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -46,9 +46,7 @@
 static void ap_handle_session_warning_timer(void *eloop_ctx, void *timeout_ctx);
 static void ap_sta_deauth_cb_timeout(void *eloop_ctx, void *timeout_ctx);
 static void ap_sta_disassoc_cb_timeout(void *eloop_ctx, void *timeout_ctx);
-#ifdef CONFIG_IEEE80211W
 static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx);
-#endif /* CONFIG_IEEE80211W */
 static int ap_sta_remove(struct hostapd_data *hapd, struct sta_info *sta);
 static void ap_sta_delayed_1x_auth_fail_cb(void *eloop_ctx, void *timeout_ctx);
 
@@ -301,10 +299,8 @@
 
 	os_free(sta->challenge);
 
-#ifdef CONFIG_IEEE80211W
 	os_free(sta->sa_query_trans_id);
 	eloop_cancel_timeout(ap_sa_query_timer, hapd, sta);
-#endif /* CONFIG_IEEE80211W */
 
 #ifdef CONFIG_P2P
 	p2p_group_notif_disassoc(hapd->p2p_group, sta->addr);
@@ -1095,8 +1091,6 @@
 }
 
 
-#ifdef CONFIG_IEEE80211W
-
 int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta)
 {
 	u32 tu;
@@ -1186,8 +1180,6 @@
 	sta->sa_query_count = 0;
 }
 
-#endif /* CONFIG_IEEE80211W */
-
 
 const char * ap_sta_wpa_get_keyid(struct hostapd_data *hapd,
 				  struct sta_info *sta)
@@ -1414,7 +1406,7 @@
 	int res;
 
 	buf[0] = '\0';
-	res = os_snprintf(buf, buflen, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+	res = os_snprintf(buf, buflen, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
 			  (flags & WLAN_STA_AUTH ? "[AUTH]" : ""),
 			  (flags & WLAN_STA_ASSOC ? "[ASSOC]" : ""),
 			  (flags & WLAN_STA_AUTHORIZED ? "[AUTHORIZED]" : ""),
@@ -1433,6 +1425,7 @@
 			  (flags & WLAN_STA_GAS ? "[GAS]" : ""),
 			  (flags & WLAN_STA_HT ? "[HT]" : ""),
 			  (flags & WLAN_STA_VHT ? "[VHT]" : ""),
+			  (flags & WLAN_STA_HE ? "[HE]" : ""),
 			  (flags & WLAN_STA_VENDOR_VHT ? "[VENDOR_VHT]" : ""),
 			  (flags & WLAN_STA_WNM_SLEEP_MODE ?
 			   "[WNM_SLEEP_MODE]" : ""));
diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
index 5456a63..de806b4 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -171,7 +171,6 @@
 	struct ieee80211_he_capabilities *he_capab;
 	size_t he_capab_len;
 
-#ifdef CONFIG_IEEE80211W
 	int sa_query_count; /* number of pending SA Query requests;
 			     * 0 = no SA Query in progress */
 	int sa_query_timed_out;
@@ -179,7 +178,6 @@
 				* sa_query_count octets of pending SA Query
 				* transaction identifiers */
 	struct os_reltime sa_query_start;
-#endif /* CONFIG_IEEE80211W */
 
 #if defined(CONFIG_INTERWORKING) || defined(CONFIG_DPP)
 #define GAS_DIALOG_MAX 8 /* Max concurrent dialog number */
diff --git a/src/ap/wnm_ap.c b/src/ap/wnm_ap.c
index 27c69d3..e4dcfe9 100644
--- a/src/ap/wnm_ap.c
+++ b/src/ap/wnm_ap.c
@@ -150,7 +150,6 @@
 		pos += gtk_elem_len;
 		wpa_printf(MSG_DEBUG, "Pass 4, gtk_len = %d",
 			   (int) gtk_elem_len);
-#ifdef CONFIG_IEEE80211W
 		res = wpa_wnmsleep_igtk_subelem(sta->wpa_sm, pos);
 		if (res < 0)
 			goto fail;
@@ -158,7 +157,6 @@
 		pos += igtk_elem_len;
 		wpa_printf(MSG_DEBUG, "Pass 4 igtk_len = %d",
 			   (int) igtk_elem_len);
-#endif /* CONFIG_IEEE80211W */
 
 		WPA_PUT_LE16((u8 *)
 			     &mgmt->u.action.u.wnm_sleep_resp.keydata_len,
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index e1c0c2c..7b690d7 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -708,6 +708,7 @@
 #endif /* CONFIG_IEEE80211R_AP */
 	os_free(sm->last_rx_eapol_key);
 	os_free(sm->wpa_ie);
+	os_free(sm->rsnxe);
 	wpa_group_put(sm->wpa_auth, sm->group);
 #ifdef CONFIG_DPP2
 	wpabuf_clear_free(sm->dpp_z);
@@ -1818,10 +1819,8 @@
 	sm->ft_completed = 0;
 #endif /* CONFIG_IEEE80211R_AP */
 
-#ifdef CONFIG_IEEE80211W
 	if (sm->mgmt_frame_prot && event == WPA_AUTH)
 		remove_ptk = 0;
-#endif /* CONFIG_IEEE80211W */
 #ifdef CONFIG_FILS
 	if (wpa_key_mgmt_fils(sm->wpa_key_mgmt) &&
 	    (event == WPA_AUTH || event == WPA_ASSOC))
@@ -2938,6 +2937,22 @@
 				   WLAN_REASON_PREV_AUTH_NOT_VALID);
 		return;
 	}
+	if ((!sm->rsnxe && kde.rsnxe) ||
+	    (sm->rsnxe && !kde.rsnxe) ||
+	    (sm->rsnxe && kde.rsnxe &&
+	     (sm->rsnxe_len != kde.rsnxe_len ||
+	      os_memcmp(sm->rsnxe, kde.rsnxe, sm->rsnxe_len) != 0))) {
+		wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+				"RSNXE from (Re)AssocReq did not match the one in EAPOL-Key msg 2/4");
+		wpa_hexdump(MSG_DEBUG, "RSNXE in AssocReq",
+			    sm->rsnxe, sm->rsnxe_len);
+		wpa_hexdump(MSG_DEBUG, "RSNXE in EAPOL-Key msg 2/4",
+			    kde.rsnxe, kde.rsnxe_len);
+		/* MLME-DEAUTHENTICATE.request */
+		wpa_sta_disconnect(wpa_auth, sm->addr,
+				   WLAN_REASON_PREV_AUTH_NOT_VALID);
+		return;
+	}
 #ifdef CONFIG_OCV
 	if (wpa_auth_uses_ocv(sm)) {
 		struct wpa_channel_info ci;
@@ -3045,8 +3060,6 @@
 }
 
 
-#ifdef CONFIG_IEEE80211W
-
 static int ieee80211w_kde_len(struct wpa_state_machine *sm)
 {
 	if (sm->mgmt_frame_prot) {
@@ -3093,21 +3106,6 @@
 	return pos;
 }
 
-#else /* CONFIG_IEEE80211W */
-
-static int ieee80211w_kde_len(struct wpa_state_machine *sm)
-{
-	return 0;
-}
-
-
-static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos)
-{
-	return pos;
-}
-
-#endif /* CONFIG_IEEE80211W */
-
 
 static int ocv_oci_len(struct wpa_state_machine *sm)
 {
@@ -3145,7 +3143,7 @@
 	size_t gtk_len, kde_len;
 	struct wpa_group *gsm = sm->group;
 	u8 *wpa_ie;
-	int wpa_ie_len, secure, keyidx, encr = 0;
+	int wpa_ie_len, secure, gtkidx, encr = 0;
 
 	SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk);
 	sm->TimeoutEvt = FALSE;
@@ -3196,7 +3194,7 @@
 				return;
 			gtk = dummy_gtk;
 		}
-		keyidx = gsm->GN;
+		gtkidx = gsm->GN;
 		_rsc = rsc;
 		encr = 1;
 	} else {
@@ -3204,7 +3202,6 @@
 		secure = 0;
 		gtk = NULL;
 		gtk_len = 0;
-		keyidx = 0;
 		_rsc = NULL;
 		if (sm->rx_eapol_key_secure) {
 			/*
@@ -3261,7 +3258,7 @@
 #endif /* CONFIG_IEEE80211R_AP */
 	if (gtk) {
 		u8 hdr[2];
-		hdr[0] = keyidx & 0x03;
+		hdr[0] = gtkidx & 0x03;
 		hdr[1] = 0;
 		pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
 				  gtk, gtk_len);
@@ -3333,7 +3330,7 @@
 			WPA_KEY_INFO_MIC : 0) |
 		       WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL |
 		       WPA_KEY_INFO_KEY_TYPE,
-		       _rsc, sm->ANonce, kde, pos - kde, keyidx, encr);
+		       _rsc, sm->ANonce, kde, pos - kde, 0, encr);
 	os_free(kde);
 }
 
@@ -3746,7 +3743,6 @@
 	wpa_hexdump_key(MSG_DEBUG, "GTK",
 			group->GTK[group->GN - 1], group->GTK_len);
 
-#ifdef CONFIG_IEEE80211W
 	if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) {
 		size_t len;
 		len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
@@ -3759,7 +3755,6 @@
 		wpa_hexdump_key(MSG_DEBUG, "IGTK",
 				group->IGTK[group->GN_igtk - 4], len);
 	}
-#endif /* CONFIG_IEEE80211W */
 
 	return ret;
 }
@@ -3777,10 +3772,8 @@
 	os_memset(group->GTK, 0, sizeof(group->GTK));
 	group->GN = 1;
 	group->GM = 2;
-#ifdef CONFIG_IEEE80211W
 	group->GN_igtk = 4;
 	group->GM_igtk = 5;
-#endif /* CONFIG_IEEE80211W */
 	/* GTK[GN] = CalcGTK() */
 	wpa_gtk_update(wpa_auth, group);
 }
@@ -3869,7 +3862,6 @@
 }
 
 
-#ifdef CONFIG_IEEE80211W
 int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos)
 {
 	struct wpa_group *gsm = sm->group;
@@ -3898,7 +3890,7 @@
 
 	return pos - start;
 }
-#endif /* CONFIG_IEEE80211W */
+
 #endif /* CONFIG_WNM_AP */
 
 
@@ -3915,11 +3907,9 @@
 	tmp = group->GM;
 	group->GM = group->GN;
 	group->GN = tmp;
-#ifdef CONFIG_IEEE80211W
 	tmp = group->GM_igtk;
 	group->GM_igtk = group->GN_igtk;
 	group->GN_igtk = tmp;
-#endif /* CONFIG_IEEE80211W */
 	/* "GKeyDoneStations = GNoStations" is done in more robust way by
 	 * counting the STAs that are marked with GUpdateStationKeys instead of
 	 * including all STAs that could be in not-yet-completed state. */
@@ -3948,7 +3938,6 @@
 			     group->GTK[group->GN - 1], group->GTK_len) < 0)
 		ret = -1;
 
-#ifdef CONFIG_IEEE80211W
 	if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) {
 		enum wpa_alg alg;
 		size_t len;
@@ -3962,7 +3951,6 @@
 				     group->IGTK[group->GN_igtk - 4], len) < 0)
 			ret = -1;
 	}
-#endif /* CONFIG_IEEE80211W */
 
 	return ret;
 }
@@ -4100,11 +4088,9 @@
 		tmp = group->GM;
 		group->GM = group->GN;
 		group->GN = tmp;
-#ifdef CONFIG_IEEE80211W
 		tmp = group->GM_igtk;
 		group->GM_igtk = group->GN_igtk;
 		group->GN_igtk = tmp;
-#endif /* CONFIG_IEEE80211W */
 		wpa_gtk_update(wpa_auth, group);
 		wpa_group_config_group_keys(wpa_auth, group);
 	}
@@ -4250,8 +4236,12 @@
 
 	/* Private MIB */
 	ret = os_snprintf(buf + len, buflen - len,
+			  "wpa=%d\n"
+			  "AKMSuiteSelector=" RSN_SUITE "\n"
 			  "hostapdWPAPTKState=%d\n"
 			  "hostapdWPAPTKGroupState=%d\n",
+			  sm->wpa,
+			  RSN_SUITE_ARG(wpa_akm_to_suite(sm->wpa_key_mgmt)),
 			  sm->wpa_ptk_state,
 			  sm->wpa_ptk_group_state);
 	if (os_snprintf_error(buflen - len, ret))
@@ -4975,13 +4965,11 @@
 		       void *ctx1, void *ctx2)
 {
 	u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde, *pos;
-#ifdef CONFIG_IEEE80211W
 	u8 *opos;
-#endif /* CONFIG_IEEE80211W */
 	size_t gtk_len, kde_len;
 	struct wpa_group *gsm = sm->group;
 	u8 *wpa_ie;
-	int wpa_ie_len, secure, keyidx, encr = 0;
+	int wpa_ie_len, secure, gtkidx, encr = 0;
 
 	/* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE],
 	   GTK[GN], IGTK, [FTIE], [TIE * 2])
@@ -5008,7 +4996,7 @@
 		secure = 1;
 		gtk = gsm->GTK[gsm->GN - 1];
 		gtk_len = gsm->GTK_len;
-		keyidx = gsm->GN;
+		gtkidx = gsm->GN;
 		_rsc = rsc;
 		encr = 1;
 	} else {
@@ -5016,7 +5004,6 @@
 		secure = 0;
 		gtk = NULL;
 		gtk_len = 0;
-		keyidx = 0;
 		_rsc = NULL;
 		if (sm->rx_eapol_key_secure) {
 			/*
@@ -5069,12 +5056,11 @@
 #endif /* CONFIG_IEEE80211R_AP */
 	if (gtk) {
 		u8 hdr[2];
-		hdr[0] = keyidx & 0x03;
+		hdr[0] = gtkidx & 0x03;
 		hdr[1] = 0;
 		pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
 				  gtk, gtk_len);
 	}
-#ifdef CONFIG_IEEE80211W
 	opos = pos;
 	pos = ieee80211w_kde_add(sm, pos);
 	if (pos - opos >= 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN) {
@@ -5082,7 +5068,6 @@
 		opos += 2 + RSN_SELECTOR_LEN + 2;
 		os_memset(opos, 0, 6); /* clear PN */
 	}
-#endif /* CONFIG_IEEE80211W */
 	if (ocv_oci_add(sm, &pos) < 0) {
 		os_free(kde);
 		return -1;
@@ -5139,7 +5124,7 @@
 			WPA_KEY_INFO_MIC : 0) |
 		       WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL |
 		       WPA_KEY_INFO_KEY_TYPE,
-		       _rsc, sm->ANonce, kde, pos - kde, keyidx, encr);
+		       _rsc, sm->ANonce, kde, pos - kde, 0, encr);
 	os_free(kde);
 	return 0;
 }
@@ -5153,9 +5138,7 @@
 	struct wpa_group *gsm = sm->group;
 	const u8 *kde;
 	u8 *kde_buf = NULL, *pos, hdr[2];
-#ifdef CONFIG_IEEE80211W
 	u8 *opos;
-#endif /* CONFIG_IEEE80211W */
 	size_t kde_len;
 	u8 *gtk;
 
@@ -5178,7 +5161,6 @@
 		hdr[1] = 0;
 		pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
 				  gtk, gsm->GTK_len);
-#ifdef CONFIG_IEEE80211W
 		opos = pos;
 		pos = ieee80211w_kde_add(sm, pos);
 		if (pos - opos >=
@@ -5187,7 +5169,6 @@
 			opos += 2 + RSN_SELECTOR_LEN + 2;
 			os_memset(opos, 0, 6); /* clear PN */
 		}
-#endif /* CONFIG_IEEE80211W */
 		if (ocv_oci_add(sm, &pos) < 0) {
 			os_free(kde_buf);
 			return -1;
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index a348bc2..f627838 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -187,11 +187,9 @@
 	int disable_pmksa_caching;
 	int okc;
 	int tx_status;
-#ifdef CONFIG_IEEE80211W
 	enum mfp_options ieee80211w;
 	int group_mgmt_cipher;
 	int sae_require_mfp;
-#endif /* CONFIG_IEEE80211W */
 #ifdef CONFIG_OCV
 	int ocv; /* Operating Channel Validation */
 #endif /* CONFIG_OCV */
@@ -232,6 +230,7 @@
 	unsigned int fils_cache_id_set:1;
 	u8 fils_cache_id[FILS_CACHE_ID_LEN];
 #endif /* CONFIG_FILS */
+	int sae_pwe;
 };
 
 typedef enum {
@@ -320,6 +319,7 @@
 int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
 			struct wpa_state_machine *sm, int freq,
 			const u8 *wpa_ie, size_t wpa_ie_len,
+			const u8 *rsnxe, size_t rsnxe_len,
 			const u8 *mdie, size_t mdie_len,
 			const u8 *owe_dh, size_t owe_dh_len);
 int wpa_validate_osen(struct wpa_authenticator *wpa_auth,
diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c
index 696f8d5..a599be2 100644
--- a/src/ap/wpa_auth_ft.c
+++ b/src/ap/wpa_auth_ft.c
@@ -2232,7 +2232,6 @@
 }
 
 
-#ifdef CONFIG_IEEE80211W
 static u8 * wpa_ft_igtk_subelem(struct wpa_state_machine *sm, size_t *len)
 {
 	u8 *subelem, *pos;
@@ -2279,7 +2278,6 @@
 	*len = subelem_len;
 	return subelem;
 }
-#endif /* CONFIG_IEEE80211W */
 
 
 static u8 * wpa_ft_process_rdie(struct wpa_state_machine *sm,
@@ -2420,6 +2418,8 @@
 	u8 *end, *mdie, *ftie, *rsnie = NULL, *r0kh_id, *subelem = NULL;
 	u8 *fte_mic, *elem_count;
 	size_t mdie_len, ftie_len, rsnie_len = 0, r0kh_id_len, subelem_len = 0;
+	u8 rsnxe[10];
+	size_t rsnxe_len;
 	int res;
 	struct wpa_auth_config *conf;
 	struct wpa_ft_ies parse;
@@ -2487,7 +2487,6 @@
 		r0kh_id_len = sm->r0kh_id_len;
 		anonce = sm->ANonce;
 		snonce = sm->SNonce;
-#ifdef CONFIG_IEEE80211W
 		if (sm->mgmt_frame_prot) {
 			u8 *igtk;
 			size_t igtk_len;
@@ -2510,7 +2509,6 @@
 			subelem_len += igtk_len;
 			os_free(igtk);
 		}
-#endif /* CONFIG_IEEE80211W */
 #ifdef CONFIG_OCV
 		if (wpa_auth_uses_ocv(sm)) {
 			struct wpa_channel_info ci;
@@ -2584,6 +2582,13 @@
 	if (ric_start == pos)
 		ric_start = NULL;
 
+	res = wpa_write_rsnxe(&sm->wpa_auth->conf, rsnxe, sizeof(rsnxe));
+	if (res < 0)
+		return NULL;
+	rsnxe_len = res;
+	if (auth_alg == WLAN_AUTH_FT && rsnxe_len)
+		*elem_count += 1;
+
 	if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
 		kck = sm->PTK.kck2;
 		kck_len = sm->PTK.kck2_len;
@@ -2596,6 +2601,7 @@
 		       mdie, mdie_len, ftie, ftie_len,
 		       rsnie, rsnie_len,
 		       ric_start, ric_start ? pos - ric_start : 0,
+		       rsnxe_len ? rsnxe : NULL, rsnxe_len,
 		       fte_mic) < 0) {
 		wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC");
 		return NULL;
@@ -3253,6 +3259,8 @@
 	count = 3;
 	if (parse.ric)
 		count += ieee802_11_ie_count(parse.ric, parse.ric_len);
+	if (parse.rsnxe)
+		count++;
 	if (fte_elem_count != count) {
 		wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in MIC "
 			   "Control: received %u expected %u",
@@ -3272,6 +3280,8 @@
 		       parse.ftie - 2, parse.ftie_len + 2,
 		       parse.rsn - 2, parse.rsn_len + 2,
 		       parse.ric, parse.ric_len,
+		       parse.rsnxe ? parse.rsnxe - 2 : NULL,
+		       parse.rsnxe ? parse.rsnxe_len + 2 : 0,
 		       mic) < 0) {
 		wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC");
 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
@@ -3290,6 +3300,9 @@
 			    parse.ftie - 2, parse.ftie_len + 2);
 		wpa_hexdump(MSG_MSGDUMP, "FT: RSN",
 			    parse.rsn - 2, parse.rsn_len + 2);
+		wpa_hexdump(MSG_MSGDUMP, "FT: RSNXE",
+			    parse.rsnxe ? parse.rsnxe - 2 : NULL,
+			    parse.rsnxe ? parse.rsnxe_len + 2 : 0);
 		return WLAN_STATUS_INVALID_FTIE;
 	}
 
diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
index 0800a87..ddab950 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -64,11 +64,9 @@
 	wconf->ocv = conf->ocv;
 #endif /* CONFIG_OCV */
 	wconf->okc = conf->okc;
-#ifdef CONFIG_IEEE80211W
 	wconf->ieee80211w = conf->ieee80211w;
 	wconf->group_mgmt_cipher = conf->group_mgmt_cipher;
 	wconf->sae_require_mfp = conf->sae_require_mfp;
-#endif /* CONFIG_IEEE80211W */
 #ifdef CONFIG_IEEE80211R_AP
 	wconf->ssid_len = conf->ssid.ssid_len;
 	if (wconf->ssid_len > SSID_MAX_LEN)
@@ -107,9 +105,7 @@
 		wconf->rsn_pairwise = WPA_CIPHER_CCMP;
 		wconf->rsn_preauth = 0;
 		wconf->disable_pmksa_caching = 1;
-#ifdef CONFIG_IEEE80211W
 		wconf->ieee80211w = 1;
-#endif /* CONFIG_IEEE80211W */
 	}
 #endif /* CONFIG_HS20 */
 #ifdef CONFIG_TESTING_OPTIONS
@@ -134,6 +130,7 @@
 	os_memcpy(wconf->fils_cache_id, conf->fils_cache_id,
 		  FILS_CACHE_ID_LEN);
 #endif /* CONFIG_FILS */
+	wconf->sae_pwe = conf->sae_pwe;
 }
 
 
@@ -380,7 +377,6 @@
 				os_memcpy(sta->last_tk, key, key_len);
 			sta->last_tk_len = key_len;
 		}
-#ifdef CONFIG_IEEE80211W
 	} else if (alg == WPA_ALG_IGTK ||
 		   alg == WPA_ALG_BIP_GMAC_128 ||
 		   alg == WPA_ALG_BIP_GMAC_256 ||
@@ -390,7 +386,6 @@
 		if (key)
 			os_memcpy(hapd->last_igtk, key, key_len);
 		hapd->last_igtk_len = key_len;
-#endif /* CONFIG_IEEE80211W */
 	} else {
 		hapd->last_gtk_alg = alg;
 		hapd->last_gtk_key_idx = idx;
@@ -896,18 +891,28 @@
 {
 	struct hostapd_data *hapd = ctx;
 	struct sta_info *sta;
+	int ret;
 
 	wpa_printf(MSG_DEBUG, "Add station entry for " MACSTR
 		   " based on WPA authenticator callback",
 		   MAC2STR(sta_addr));
-	if (hostapd_add_sta_node(hapd, sta_addr, WLAN_AUTH_FT) < 0)
+	ret = hostapd_add_sta_node(hapd, sta_addr, WLAN_AUTH_FT);
+
+	/*
+	 * The expected return values from hostapd_add_sta_node() are
+	 * 0: successfully added STA entry
+	 * -EOPNOTSUPP: driver or driver wrapper does not support/need this
+	 *	operations
+	 * any other negative value: error in adding the STA entry */
+	if (ret < 0 && ret != -EOPNOTSUPP)
 		return NULL;
 
 	sta = ap_sta_add(hapd, sta_addr);
 	if (sta == NULL)
 		return NULL;
-	if (hapd->driver && hapd->driver->add_sta_node)
+	if (ret == 0)
 		sta->added_unassoc = 1;
+
 	sta->ft_over_ds = 1;
 	if (sta->wpa_sm) {
 		sta->auth_alg = WLAN_AUTH_FT;
diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h
index 4babd0c..a993f50 100644
--- a/src/ap/wpa_auth_i.h
+++ b/src/ap/wpa_auth_i.h
@@ -102,6 +102,8 @@
 
 	u8 *wpa_ie;
 	size_t wpa_ie_len;
+	u8 *rsnxe;
+	size_t rsnxe_len;
 
 	enum {
 		WPA_VERSION_NO_WPA = 0 /* WPA not used */,
@@ -190,10 +192,8 @@
 	Boolean changed;
 	Boolean first_sta_seen;
 	Boolean reject_4way_hs_for_entropy;
-#ifdef CONFIG_IEEE80211W
 	u8 IGTK[2][WPA_IGTK_MAX_LEN];
 	int GN_igtk, GM_igtk;
-#endif /* CONFIG_IEEE80211W */
 	/* Number of references except those in struct wpa_group->next */
 	unsigned int references;
 	unsigned int num_setup_iface;
@@ -269,6 +269,7 @@
 
 int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
 		     const u8 *pmkid);
+int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len);
 void wpa_auth_logger(struct wpa_authenticator *wpa_auth, const u8 *addr,
 		     logger_level level, const char *txt);
 void wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr,
diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c
index 2e5c916..2e6d059 100644
--- a/src/ap/wpa_auth_ie.c
+++ b/src/ap/wpa_auth_ie.c
@@ -183,7 +183,6 @@
 		num_suites++;
 	}
 #endif /* CONFIG_IEEE80211R_AP */
-#ifdef CONFIG_IEEE80211W
 	if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA256);
 		pos += RSN_SELECTOR_LEN;
@@ -194,7 +193,6 @@
 		pos += RSN_SELECTOR_LEN;
 		num_suites++;
 	}
-#endif /* CONFIG_IEEE80211W */
 #ifdef CONFIG_SAE
 	if (conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) {
 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE);
@@ -286,13 +284,11 @@
 		/* 4 PTKSA replay counters when using WMM */
 		capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2);
 	}
-#ifdef CONFIG_IEEE80211W
 	if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
 		capab |= WPA_CAPABILITY_MFPC;
 		if (conf->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED)
 			capab |= WPA_CAPABILITY_MFPR;
 	}
-#endif /* CONFIG_IEEE80211W */
 #ifdef CONFIG_OCV
 	if (conf->ocv)
 		capab |= WPA_CAPABILITY_OCVC;
@@ -314,7 +310,6 @@
 		pos += PMKID_LEN;
 	}
 
-#ifdef CONFIG_IEEE80211W
 	if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION &&
 	    conf->group_mgmt_cipher != WPA_CIPHER_AES_128_CMAC) {
 		if (2 + 4 > buf + len - pos)
@@ -347,7 +342,6 @@
 		}
 		pos += RSN_SELECTOR_LEN;
 	}
-#endif /* CONFIG_IEEE80211W */
 
 #ifdef CONFIG_RSN_TESTING
 	if (rsn_testing) {
@@ -378,6 +372,26 @@
 }
 
 
+int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len)
+{
+	u8 *pos = buf;
+
+	if (conf->sae_pwe != 1 && conf->sae_pwe != 2)
+		return 0; /* no supported extended RSN capabilities */
+
+	if (len < 3)
+		return -1;
+
+	*pos++ = WLAN_EID_RSNX;
+	*pos++ = 1;
+	/* bits 0-3 = 0 since only one octet of Extended RSN Capabilities is
+	 * used for now */
+	*pos++ = BIT(WLAN_RSNX_CAPAB_SAE_H2E);
+
+	return pos - buf;
+}
+
+
 static u8 * wpa_write_osen(struct wpa_auth_config *conf, u8 *eid)
 {
 	u8 *len;
@@ -411,13 +425,11 @@
 		/* 4 PTKSA replay counters when using WMM */
 		capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2);
 	}
-#ifdef CONFIG_IEEE80211W
 	if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
 		capab |= WPA_CAPABILITY_MFPC;
 		if (conf->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED)
 			capab |= WPA_CAPABILITY_MFPR;
 	}
-#endif /* CONFIG_IEEE80211W */
 #ifdef CONFIG_OCV
 	if (conf->ocv)
 		capab |= WPA_CAPABILITY_OCVC;
@@ -464,6 +476,11 @@
 		if (res < 0)
 			return res;
 		pos += res;
+		res = wpa_write_rsnxe(&wpa_auth->conf, pos,
+				      buf + sizeof(buf) - pos);
+		if (res < 0)
+			return res;
+		pos += res;
 	}
 #ifdef CONFIG_IEEE80211R_AP
 	if (wpa_key_mgmt_ft(wpa_auth->conf.wpa_key_mgmt)) {
@@ -532,6 +549,7 @@
 int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
 			struct wpa_state_machine *sm, int freq,
 			const u8 *wpa_ie, size_t wpa_ie_len,
+			const u8 *rsnxe, size_t rsnxe_len,
 			const u8 *mdie, size_t mdie_len,
 			const u8 *owe_dh, size_t owe_dh_len)
 {
@@ -607,12 +625,10 @@
 		else if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK)
 			selector = RSN_AUTH_KEY_MGMT_FT_PSK;
 #endif /* CONFIG_IEEE80211R_AP */
-#ifdef CONFIG_IEEE80211W
 		else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
 			selector = RSN_AUTH_KEY_MGMT_802_1X_SHA256;
 		else if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
 			selector = RSN_AUTH_KEY_MGMT_PSK_SHA256;
-#endif /* CONFIG_IEEE80211W */
 #ifdef CONFIG_SAE
 		else if (data.key_mgmt & WPA_KEY_MGMT_SAE)
 			selector = RSN_AUTH_KEY_MGMT_SAE;
@@ -717,12 +733,10 @@
 	else if (key_mgmt & WPA_KEY_MGMT_FT_PSK)
 		sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_PSK;
 #endif /* CONFIG_IEEE80211R_AP */
-#ifdef CONFIG_IEEE80211W
 	else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
 		sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
 	else if (key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
 		sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
-#endif /* CONFIG_IEEE80211W */
 #ifdef CONFIG_SAE
 	else if (key_mgmt & WPA_KEY_MGMT_SAE)
 		sm->wpa_key_mgmt = WPA_KEY_MGMT_SAE;
@@ -758,7 +772,6 @@
 		return WPA_INVALID_PAIRWISE;
 	}
 
-#ifdef CONFIG_IEEE80211W
 	if (wpa_auth->conf.ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED) {
 		if (!(data.capabilities & WPA_CAPABILITY_MFPC)) {
 			wpa_printf(MSG_DEBUG, "Management frame protection "
@@ -807,7 +820,6 @@
 			       "Management frame protection cannot use TKIP");
 		    return WPA_MGMT_FRAME_PROTECTION_VIOLATION;
 	}
-#endif /* CONFIG_IEEE80211W */
 
 #ifdef CONFIG_IEEE80211R_AP
 	if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
@@ -941,6 +953,21 @@
 	os_memcpy(sm->wpa_ie, wpa_ie, wpa_ie_len);
 	sm->wpa_ie_len = wpa_ie_len;
 
+	if (rsnxe && rsnxe_len) {
+		if (!sm->rsnxe || sm->rsnxe_len < rsnxe_len) {
+			os_free(sm->rsnxe);
+			sm->rsnxe = os_malloc(rsnxe_len);
+			if (!sm->rsnxe)
+				return WPA_ALLOC_FAIL;
+		}
+		os_memcpy(sm->rsnxe, rsnxe, rsnxe_len);
+		sm->rsnxe_len = rsnxe_len;
+	} else {
+		os_free(sm->rsnxe);
+		sm->rsnxe = NULL;
+		sm->rsnxe_len = 0;
+	}
+
 	return WPA_IE_OK;
 }
 
@@ -975,153 +1002,6 @@
 #endif /* CONFIG_HS20 */
 
 
-/**
- * wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs
- * @pos: Pointer to the IE header
- * @end: Pointer to the end of the Key Data buffer
- * @ie: Pointer to parsed IE data
- * Returns: 0 on success, 1 if end mark is found, -1 on failure
- */
-static int wpa_parse_generic(const u8 *pos, const u8 *end,
-			     struct wpa_eapol_ie_parse *ie)
-{
-	if (pos[1] == 0)
-		return 1;
-
-	if (pos[1] >= 6 &&
-	    RSN_SELECTOR_GET(pos + 2) == WPA_OUI_TYPE &&
-	    pos[2 + WPA_SELECTOR_LEN] == 1 &&
-	    pos[2 + WPA_SELECTOR_LEN + 1] == 0) {
-		ie->wpa_ie = pos;
-		ie->wpa_ie_len = pos[1] + 2;
-		return 0;
-	}
-
-	if (pos[1] >= 4 && WPA_GET_BE32(pos + 2) == OSEN_IE_VENDOR_TYPE) {
-		ie->osen = pos;
-		ie->osen_len = pos[1] + 2;
-		return 0;
-	}
-
-	if (1 + RSN_SELECTOR_LEN < end - pos &&
-	    pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN &&
-	    RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_PMKID) {
-		ie->pmkid = pos + 2 + RSN_SELECTOR_LEN;
-		return 0;
-	}
-
-	if (pos[1] > RSN_SELECTOR_LEN + 2 &&
-	    RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_GROUPKEY) {
-		ie->gtk = pos + 2 + RSN_SELECTOR_LEN;
-		ie->gtk_len = pos[1] - RSN_SELECTOR_LEN;
-		return 0;
-	}
-
-	if (pos[1] > RSN_SELECTOR_LEN + 2 &&
-	    RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_MAC_ADDR) {
-		ie->mac_addr = pos + 2 + RSN_SELECTOR_LEN;
-		ie->mac_addr_len = pos[1] - RSN_SELECTOR_LEN;
-		return 0;
-	}
-
-#ifdef CONFIG_IEEE80211W
-	if (pos[1] > RSN_SELECTOR_LEN + 2 &&
-	    RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_IGTK) {
-		ie->igtk = pos + 2 + RSN_SELECTOR_LEN;
-		ie->igtk_len = pos[1] - RSN_SELECTOR_LEN;
-		return 0;
-	}
-#endif /* CONFIG_IEEE80211W */
-
-#ifdef CONFIG_P2P
-	if (pos[1] >= RSN_SELECTOR_LEN + 1 &&
-	    RSN_SELECTOR_GET(pos + 2) == WFA_KEY_DATA_IP_ADDR_REQ) {
-		ie->ip_addr_req = pos + 2 + RSN_SELECTOR_LEN;
-		wpa_hexdump(MSG_DEBUG, "WPA: IP Address Request in EAPOL-Key",
-			    ie->ip_addr_req, pos[1] - RSN_SELECTOR_LEN);
-		return 0;
-	}
-
-	if (pos[1] >= RSN_SELECTOR_LEN + 3 * 4 &&
-	    RSN_SELECTOR_GET(pos + 2) == WFA_KEY_DATA_IP_ADDR_ALLOC) {
-		ie->ip_addr_alloc = pos + 2 + RSN_SELECTOR_LEN;
-		wpa_hexdump(MSG_DEBUG,
-			    "WPA: IP Address Allocation in EAPOL-Key",
-			    ie->ip_addr_alloc, pos[1] - RSN_SELECTOR_LEN);
-		return 0;
-	}
-#endif /* CONFIG_P2P */
-
-#ifdef CONFIG_OCV
-	if (pos[1] > RSN_SELECTOR_LEN + 2 &&
-	    RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_OCI) {
-		ie->oci = pos + 2 + RSN_SELECTOR_LEN;
-		ie->oci_len = pos[1] - RSN_SELECTOR_LEN;
-		return 0;
-	}
-#endif /* CONFIG_OCV */
-
-	return 0;
-}
-
-
-/**
- * wpa_parse_kde_ies - Parse EAPOL-Key Key Data IEs
- * @buf: Pointer to the Key Data buffer
- * @len: Key Data Length
- * @ie: Pointer to parsed IE data
- * Returns: 0 on success, -1 on failure
- */
-int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie)
-{
-	const u8 *pos, *end;
-	int ret = 0;
-
-	os_memset(ie, 0, sizeof(*ie));
-	for (pos = buf, end = pos + len; end - pos > 1; pos += 2 + pos[1]) {
-		if (pos[0] == 0xdd &&
-		    ((pos == buf + len - 1) || pos[1] == 0)) {
-			/* Ignore padding */
-			break;
-		}
-		if (2 + pos[1] > end - pos) {
-			wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key Key Data "
-				   "underflow (ie=%d len=%d pos=%d)",
-				   pos[0], pos[1], (int) (pos - buf));
-			wpa_hexdump_key(MSG_DEBUG, "WPA: Key Data",
-					buf, len);
-			ret = -1;
-			break;
-		}
-		if (*pos == WLAN_EID_RSN) {
-			ie->rsn_ie = pos;
-			ie->rsn_ie_len = pos[1] + 2;
-#ifdef CONFIG_IEEE80211R_AP
-		} else if (*pos == WLAN_EID_MOBILITY_DOMAIN) {
-			ie->mdie = pos;
-			ie->mdie_len = pos[1] + 2;
-		} else if (*pos == WLAN_EID_FAST_BSS_TRANSITION) {
-			ie->ftie = pos;
-			ie->ftie_len = pos[1] + 2;
-#endif /* CONFIG_IEEE80211R_AP */
-		} else if (*pos == WLAN_EID_VENDOR_SPECIFIC) {
-			ret = wpa_parse_generic(pos, end, ie);
-			if (ret < 0)
-				break;
-			if (ret > 0) {
-				ret = 0;
-				break;
-			}
-		} else {
-			wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized EAPOL-Key "
-				    "Key Data IE", pos, 2 + pos[1]);
-		}
-	}
-
-	return ret;
-}
-
-
 int wpa_auth_uses_mfp(struct wpa_state_machine *sm)
 {
 	return sm ? sm->mgmt_frame_prot : 0;
diff --git a/src/ap/wpa_auth_ie.h b/src/ap/wpa_auth_ie.h
index a38b206..dd44b9e 100644
--- a/src/ap/wpa_auth_ie.h
+++ b/src/ap/wpa_auth_ie.h
@@ -9,41 +9,6 @@
 #ifndef WPA_AUTH_IE_H
 #define WPA_AUTH_IE_H
 
-struct wpa_eapol_ie_parse {
-	const u8 *wpa_ie;
-	size_t wpa_ie_len;
-	const u8 *rsn_ie;
-	size_t rsn_ie_len;
-	const u8 *pmkid;
-	const u8 *gtk;
-	size_t gtk_len;
-	const u8 *mac_addr;
-	size_t mac_addr_len;
-#ifdef CONFIG_IEEE80211W
-	const u8 *igtk;
-	size_t igtk_len;
-#endif /* CONFIG_IEEE80211W */
-#ifdef CONFIG_IEEE80211R_AP
-	const u8 *mdie;
-	size_t mdie_len;
-	const u8 *ftie;
-	size_t ftie_len;
-#endif /* CONFIG_IEEE80211R_AP */
-#ifdef CONFIG_P2P
-	const u8 *ip_addr_req;
-	const u8 *ip_addr_alloc;
-#endif /* CONFIG_P2P */
-#ifdef CONFIG_OCV
-	const u8 *oci;
-	size_t oci_len;
-#endif /* CONFIG_OCV */
-
-	const u8 *osen;
-	size_t osen_len;
-};
-
-int wpa_parse_kde_ies(const u8 *buf, size_t len,
-		      struct wpa_eapol_ie_parse *ie);
 u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len,
 		 const u8 *data2, size_t data2_len);
 int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth);
diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c
index 6161cdb..33caeaf 100644
--- a/src/ap/wps_hostapd.c
+++ b/src/ap/wps_hostapd.c
@@ -358,12 +358,10 @@
 		    (cred->auth_type & WPS_AUTH_WPA2PSK) &&
 		    cred->key_len != 2 * PMK_LEN) {
 			bss->wpa_key_mgmt |= WPA_KEY_MGMT_SAE;
-#ifdef CONFIG_IEEE80211W
 			if (bss->ieee80211w == NO_MGMT_FRAME_PROTECTION)
 				bss->ieee80211w =
 					MGMT_FRAME_PROTECTION_OPTIONAL;
 			bss->sae_require_mfp = 1;
-#endif /* CONFIG_IEEE80211W */
 		}
 
 		if (cred->key_len >= 8 && cred->key_len < 64) {
@@ -533,9 +531,7 @@
 
 	if (wpa) {
 		char *prefix;
-#ifdef CONFIG_IEEE80211W
 		int sae = 0;
-#endif /* CONFIG_IEEE80211W */
 
 		fprintf(nconf, "wpa=%d\n", wpa);
 
@@ -553,13 +549,10 @@
 		    (cred->auth_type & WPS_AUTH_WPA2PSK) &&
 		    cred->key_len != 2 * PMK_LEN) {
 			fprintf(nconf, "%sSAE", prefix);
-#ifdef CONFIG_IEEE80211W
 			sae = 1;
-#endif /* CONFIG_IEEE80211W */
 		}
 		fprintf(nconf, "\n");
 
-#ifdef CONFIG_IEEE80211W
 		if (sae && hapd->conf->ieee80211w == NO_MGMT_FRAME_PROTECTION) {
 			fprintf(nconf, "ieee80211w=%d\n",
 				MGMT_FRAME_PROTECTION_OPTIONAL);
@@ -567,7 +560,6 @@
 		}
 		if (sae)
 			fprintf(nconf, "sae_require_mfp=1\n");
-#endif /* CONFIG_IEEE80211W */
 
 		fprintf(nconf, "wpa_pairwise=");
 		prefix = "";