[wpa_supplicant] Cumulative patch from commit e4eb009d9

Bug: 153102274
Test: Device boots up and connects to wifi networks, run traffic.
Test: Able to turn on/off softap, associate wifi STA, run traffic.
Test: Regression test passed (Bug: 153163800)

e4eb009d9 DPP2: Add Connector and C-sign-key in psk/sae credentials for reconfig
1dcfbab25 DPP2: Clear requirement for QR Code mutual authentication for chirping
a371164f8 Process received WNM Notification Request for beacon protection failures
0e794989e Beacon frame protection event for incorrect protection
7c8f540ee wpa_supplicant: Add HE override support
e149051ce hostapd: Validate the country_code parameter value
d4f5d1f0c DPP: Add some more details on how to use DPP
66e20bb1a Fix the dpp_configurator_sign example command
91498a122 hostapd: DFS for channel switch in repeater mode
c60717f83 hostapd: Add support for DFS channels in CHAN_SWITCH
683e7c755 DFS: Add new hostapd_is_dfs_overlap() helper
798876739 DFS: Rename and export hostapd_config_dfs_chan_available helper
30b6d4bb7 hostapd: Basic channel check for CHAN_SWITCH parameters
3f88d2ba0 AP: Drop not needed condition to delete PTK ID 1
80914e9eb DPP2: Fix build with OpenSSL 1.0.2 (EVP_PKEY_get0_EC_KEY() wrapper)
54e2961f8 Add a hostapd testing option for skipping association pruning
1a18f8df6 nl80211: Allow full AP client state capability to be disabled
7b156a3c5 wpa_auth: Use printf format %zu instead of type casts
f83d3491b wpa_auth: Do not split strings into multiple lines
9385f03fe wpa_auth: Coding style cleanup for pointer is NULL comparisons
62e12afcf wpa_auth: Clean up pointer dereferences
bbf94a095 nl80211: Configure PMKSA lifetime and reauth threshold timer to driver
1f4e9946b Sync with mac80211-next.git include/uapi/linux/nl80211.h
5058f771d DPP2: Allow station to require or not allow PFS
7c021dec3 DPP2: Allow AP to require or reject PFS
ca57d5f55 Return an enum from wpa_validate_wpa_ie()
2b4f9ce28 hostapd: Add HE bit in BSSID Information field of own Neighbor Report
80d0e50dc DPP2: Use a helper function for encapsulating TCP message
fa5143feb DPP2: Presence Announcement processing in Controller
db1ef8253 DPP2: Presence Announcement processing in AP/Relay
06dd32903 DPP2: Presence Announcement processing at Configurator
6f5bc15be DPP2: Configurator Connectivity indication
562f77144 DPP2: Chirping in wpa_supplicant Enrollee
1f0226770 DPP2: Add a helper function for building Presence Announcement frame
7cba35b0e DPP2: New identifier definitions
547dc7eaa DPP: Add DPP_BOOTSTRAP_SET command
804fc268a DPP: Allow per-peer configurator parameters to be set
514cc49ba DPP: Store global pointers in struct dpp_authentication
bc95d5833 Fix a typo in function documentation
b7275a814 Update STA flags to the driver immediately on disconnection
8ca6f924d STA: Fix wpa_clear_keys() PTK key deletion logic
ff5434090 AP: Fix Extended Key ID parameter check
96686e637 wpa_supplicant AP mode configuration for Transition Disable KDE
9d1857cf3 Process Transition Disable KDE in station mode
82cc0b0cc Allow hostapd AP to advertise Transition Disable KDE
3eb9ddc65 Transition Disable KDE definitions
a72ec4c22 Add addition CFR capture type to filter all NDPA NDP frames
a163bfe2b Change CFR attributes from required to optional
e520de8db Add ACS support for 60 GHz channel bonding
00f6a2762 nl80211: Fix offloaded ACS regression for the 60 GHz band
1e8ea0833 HE: Add HE support to hostapd_set_freq_params()
bb08be757 Extend vendor attributes to support enhanced CFR capture
30ac8ddaf Add QCA vendor attributes for ACS over EDMG (IEEE 802.11ay)
41c3f0cd5 Allow last configured Key ID for TK to be fetched from wpa_supplicant
8b63a5816 Use a shared helper function for RSN supplicant capabilities
b17b7a8e5 STA: Support Extended Key ID
862aac1fc AP: Support Extended Key ID
b967b5e85 Limit scan frequency list to 100 entries
9f9a148af Convert int_array to use size_t instead of int as the length
749add5c6 Limit freq_range_list_parse() result to UINT_MAX entries
2f0600856 loop: Use size_t for eloop.count
7858f493f eloop: Use size_t for socket table->count
3f45b8dae hs20-osu-client: Use size_t for certificate components
913220cbb eloop: Use size_t for signal_count
ae7193611 Limit maximum number of pending SA Queries
02b43c557 RADIUS: Use size_t instead of int for message attributes
a2c23195a D-Bus: Use size_t for values theoretically larger than 16-bit int
d2d16e310 Use size_t instead of int or unsigned int for configuration items
4391ddd63 Use size_t instead of unsigned_int for last_scan_res
22f0318db Interpolate rate calculation functions
3a25897ef Adjust max bitrate SNR floors
eb26a6997 Allow SA Query to be disabled for testing purposes
7546c489a nl80211: Fix RTM NEW/DELLINK IFLA_IFNAME copy for maximum ifname length
22547c314 More details to the vendor specific driver internal failure reporting
51e8f5d63 Ignore duplicated SSID element when parsing
5a296129f Set beacon protection config irrespective of macro CONFIG_FILS
cc79eb725 Check against integer overflow in int_array functions
a55ecfeab Allow RSNXE to be removed from Beacon frames for testing purposes
b7366a942 FT: Omit RSNXE from FT protocol Reassociation Response when needed
6140cca81 FT: Omit RSNXE from FT protocol Reassociation Request when needed
35936cd2c FT: Verify that RSNXE is used consistently in Reassociation Response
497ae9f00 FT: Verify that RSNXE is used consistently in Reassociation Request
51d1924bd FT: Set the new RSNXE Used subfield in FT reassociation
796253a65 nl80211: Debug print set_key() command names
ac2224153 nl80211: Extended Key ID support
a1afa2df8 Remove unnecessary and confusing length check from the PMKID KDE case
094c9cdc7 Add parsing of Key ID KDE for Extended Key ID
f5c0104f3 Add KEY_FLAG_MODIFY for Extended Key ID support
9e30180a3 nl80211: Allow scanning in wpa_supplicant AP mode
fab94f16e Indicate scan completion in active AP mode even when ignoring results
037e004c1 nl80211: Remove extraneous space from send_mlme debug print
81fa7730d nl80211: Add more TX status details in debug log in AP mode
f21fbfb97 Allow RSNE in EAPOL-Key msg 2/4 to be overridden for testing purposes
46e147fcd Allow RSNE/RSNXE to be replaced in FT protocol Reassocation Response frame
1a8e9334c FT: Check RSNE/RSNXE match in FT protocol Reassociation Response frame
839bab785 nl80211: Debug print driver capabilities
e861fa1f6 Move the "WPA: AP key_mgmt" debug print to be after final changes
1d9cff86b Multi-AP: Set 4-address mode after network selection
e0fb468a7 HS 2.0 server: Add a note on OCSP server hostname
440dac755 hs20-osu-client: Use more specific debug message on OSU connection
2b9713d61 Fill the current opclass in (Re)AssocRequest depending on HT/VHT IEs
d9a7b71a7 AP: Fix regression in frequency check for a usable EDMG channel
1f13c1393 mesh: Fix CONFIG_HT_OVERRIDES build without CONFIG_VHT_OVERRIDES
52efde2aa WPS: Do not set auth_alg=OPEN for PSK+SAE case
10223b501 SAE: Expose sae_write_commit() error cases to callers
7f1f69e89 SAE: Check hmac_sha256() result in sae_token_hash()
b0927e5d0 nl80211: Fix error print for hapd_send_eapol()
a17cbcd69 os_unix: Call srandom() only if os_get_random() succeeds
17ba51b14 nl80211: Fix tx_control_port error print
bb2ea8e5e DPP: Remove unreachable return statement
7dcc5f7fe SAE: Check sta pointer more consistently in testing code
15d63c604 Clean up hostapd_get_he_twt_responder() processing
7aa47fe5f DPP: Fix connectorTemplate addition
fe0429a58 Replace systemd install Alias with WantedBy
c7d293024 RSN: Stop 4-way handshake if scan results are not available
f4bf6a5d4 OWE: Allow BSS entry with different SSID to be used in transition mode
3c7381150 OWE: Mark BSS for transition mode based on active OWE network profiles
ecb5219d8 OWE: Avoid incorrect profile update in transition mode
785f99b68 FT: Silence debug prints when FT is not actually used
33a28170a Recognize OWE Transition Mode element in IE parser
fad044943 Report RSNXE mismatch in EAPOL-Key msg 3/4 more consistently with RSNE
4d64fd37b Allow RSNE in EAPOL-Key msg 3/4 to be replaced for testing purposes
9128b6726 Extend hostapd rsnxe_override_eapol to allow IE removal
43ededa9c Do not override WDS VLAN assignment for STA
87998f80e HS 2.0 server: Allow OCSP responder to continue running after errors
ca8a51c4b webkit2: Fix http://localhost:12345/ redirect handling
be15f33d0 Replace WPA_ALG_PMK with KEY_FLAG_PMK
11b1fcd6c nl80211: Drop outdated TDLS set_key() hack
2dd72315d wpa_cli: Add missing quote around interface name
f64b601c4 DFS: Add support for 80+80 MHz when going through channel switch
0a76a0b96 OWE: Fix PTK derivation workaround for interoperability
87775e32f Fix segmentation fault for NULL confname in SAVE_CONFIG
81621eab7 nl80211: Migrate from set_tx to key_flag API
9757f18db nl80211: Don't ignore when SET_KEY returns ENOENT
98b8275d9 nl80211: Remove not needed netlink key attribute
8563f6f56 nl80211: Fix wrong return code in set_key error path
adf550ee4 nl80211: Ignore seq number for key deletion
e9e69221c Validity checking function for key_flag API
5eb163256 nl80211: Add a missing key_flag for WEP shared key authentication
82eaa3e68 Remove the not yet needed KEY_FLAG_MODIFY
982b9cf02 Fix a wrong key_flag when deleting 802.1X WEP keys
d37c05e5b AP: Don't try to set NULL WEP default key
fa1a6aff2 Fix unicast argument for set_wep_key() from EAPOL supplicant
11dab0f37 WPS: Remove expired PINs on Selected Registrar timeout
8f89e57ab DFS: More debug prints on channel selection after radar detection
4b37d2428 hostapd: Fix to downgrade bandwidth in radar detection
7242087d1 DFS: Do not process radar event while disabling an interface
5fdacce46 Allow wildcard SSID to be enforced for a specific BSSID scan
43282f732 mesh: Fix HE enablement on 5 GHz with VHT
21f835e64 SAE: Allow SAE-only network profile with sae_password to be written
5bad30056 privsep: Mask out control port capability flag
c1a6b1e47 privsep: Add key_flag to set_key()
852d370f6 Silence a compiler warning in no-WEP and no-EAP builds
101da59aa common: Add support for element defragmentation
e636bc855 WPA: Rename FILS wrapped data
94773d40f crypto: Add a function to get the ECDH prime length
e8ae97aeb nl80211: Allow TX status for Authentication frames
c4988e73c driver: Extend send_mlme() with wait option
d046f2a9f nl80211: Register for SAE Authentication frames more strictly
7a9c36722 DBus: Add "sae" to interface key_mgmt capabilities
200c7693c Make WEP functionality an optional build parameter
bca44f4e4 WPS: Remove static-WEP-only workaround
b7f1d4f4d ACS: Allow hw_mode=any to be used with internal ACS algorithm
d07f1ade9 ACS: Determine mode when using hw_mode=any
c60362e6e ACS: Extend acs_find_ideal_chan() to support multiple modes
141a8815e ACS: Extend acs_request_scan() to support multiple modes
f3c44a196 ACS: Extend interference factor calculation for all modes
070522e5b ACS: Extend acs_find_chan() for all modes
4c1ffb45e ACS: Extend acs_surveys_are_sufficient() for all modes
3d09be41a ACS: Clear all modes in acs_cleanup()
499c37b72 ACS: Extend hostapd_get_mode_channel() to find from any mode
a62d76185 ACS: Fix spelling of "interference"
167205d45 os_unix: Seed random() for os_random()
74db49d74 SAE: Do not use PMKSA entry after its reauth threshold
bb93ea234 SAE: Do not clone PMKSA entry for OKC after its reauth threshold
114d12418 SAE: Fix PMKID derivation for OKC
3f10f716a common: Provide the BIT() macro locally
b8f6b0713 Add attribute for dwell time in QCA vendor scan
ec303e2cb Introduce QCA_WLAN_VENDOR_ATTR_CONFIG_ROAM_REASON
34640a88d Fix enum qca_wlan_vendor_attr_config value prefix
3fadb1dcc WPS: Ignore other APs if PBC is used with a specific BSSID
f1d385609 nl80211: Beacon protection capability flag and default key type
2e34f6a53 Sync with mac80211-next.git include/uapi/linux/nl80211.h
0f84a93f6 Fix a type in wpa_supplicant defconfig
0e05e8781 Simplify wpa_deny_ptk0_rekey documentation
a5944db04 Add wpa_deny_ptk0_rekey to AP get_config() output
8a1660b60 common: Add missing driver flag strings
4b04223f2 hostapd: Replace UDP ctrl_iface global cookies with per-instance ones
12fb9698a Use IFNAME= prefix for global UDP control interface events
293631f17 IBSS RSN: Coding style cleanup
1f90a49d0 STA: Allow PTK rekeying without Ext KeyID to be disabled as a workaround
1a7963e36 AP: Allow PTK rekeying without Ext KeyID to be disabled as a workaround
35da7c20a nl80211: Add driver capability flag for CAN_REPLACE_PTK0
7b26238d4 Do not skip MBO PMF check with the WPS special case WPA check exception
fae7e64aa Save RM enabled capability of station with AP SME
e9ac44fcb Make INTERWORKING_CONNECT more reliable in testing environment
1074d4241 Fix a typo in a comment
8fe7ec664 Remove Secondary Channel Offset element from Beacon/Probe Response frames
7f1529d2a Fix HE element order in Beacon and Probe Response frames
f3bcd6960 Remove CONFIG_IEEE80211N build option
640d59942 Fix location of MDE and RSNXE in Beacon and Probe Response frames
2d4c78aef Configure received BIGTK on station/supplicant side
ecbf59e69 wpa_supplicant configuration for Beacon protection
16889aff4 Add BIGTK KDE and subelement similarly to IGTK
555dcd75c Generate BIGTK and rekey it with IGTK
323d06187 Parsing of BIGTK KDE in EAPOL-Key frames
3937378ab Parsing of BIGTK subelement in FTE
d2e77310d driver: Document use of set_key() for BIGTK
c1df321b6 AP mode indication of Beacon protection being enabled
92d407dbd hostapd configuration for Beacon protection
cb86e8bac nl80211: Remove an extra closing parenthesis from a debug message
46cb04650 nl80211: Check nla_nest_start() result for NL80211_ATTR_HE_OBSS_PD
0b0ee0f15 HE: Propagate BSS color settings to nl80211
8155b36fa Fix VERSION_STR printf() calls in case the postfix strings include %
dd74ddd0d nl80211: Handle AKM suite selectors for AP configuration
139f6deaf Remove duplicated wpa_akm_to_suite() entry
10655d1bc nl80211: Add NLA_F_NESTED to nla_nest_start() with older libnl versions
5db5290ab webkit: Clean up USE_WEBKIT2 blocks
26ad26c8c webkit2: Split decide-policy into a separate function
02ed737ee webkit2: Split resource-load-started handler into a separate function
7de8bd508 webkit: Track gtk_main()/gtk_main_quit() calls
de0a8906f webkit2: Remove TODO not for download-started
ae07bc46c webkit2: Do not register notify::load-status handler
9ea9d18de webkit2: Replace notfy::progress with notify::estimated-load-progress
c0c4685d5 webkit2: Implement notify::title handler
ffeafc087 webkit2: Use mouse-target-changed to replace hovering-over-link
e33a0eece hs20-osu-client: Validate HTTPS server certificate by default (browser)
61bf9819c hs20_web_browser() to allow TLS server validation to be enabled
921ea4962 hs20-osu-client: Ignore TLS errors with webkit2
b4b1b122e hs20-osu-client: Enable webkit2 support
466e48dcd HT: Remove SMPS in AP mode
8de0ff0fa HE: Add TWT responder extended capabilities field
ab8c55358 HE: Dynamically turn on TWT responder support
0cb39f4fd HE: Extend BSS color support
458162a27 Sync with mac80211-next.git include/uapi/linux/nl80211.h
981b96caa WPS: Mark added PSK entry with wps=1 tag for per-Enrollee PSK case
b05627511 Fix exception checking in a wpa_supplicant P2P example script
2bab073df WPS: Add new PSK entries with wps=1 tag
fde8e7946 WPS: Make it possible to use PSKs loaded from the PSK file
b1977a652 WPS: Use PMK_LEN instead of hardcoded 32
b27ed050d Do not split strings into multiple lines
838180877 Use PMK_LEN macro instead of hardcoded value 64 (= 2 * 32)
f5da5810c Check pbkdf2_sha1() result when generating PSK from PSK file
e7d8842e6 OWE: Rename owe_assoc_req_process() parameter reason to status
877d9a02b Additional get_sta_info attrs for Beacon/Probe Response/disconnect reasons
8162d98f2 Introduce QCA_NL80211_VENDOR_SUBCMD_DRIVER_DISCONNECT_REASON
32551066b Introduce QCA_NL80211_VENDOR_SUBCMD_UPDATE_STA_INFO
dae85e655 P2P: Increase number of channels per operating class
75d0ec470 P2P: Fix a possible buffer overflow in struct p2p_reg_class
555131783 Introduce QCA_WLAN_VENDOR_ATTR_BEACON_REPORT_FAIL
c304bddcf DPP: Stop Action frame sequence on DPP_STOP_LISTEN and PKEX failure
de08fae66 DPP: Do not require dpp_configurator_params to start with a space
c7cc80fbc DPP: Reset DPP_AUTH_INIT netrole back to STA by default
adf3de44c Add check to consider band in enabling connection_vht flag
490d90db4 Define macro BIT() in qca_vendor.h
9a0edf170 wlantest: Add PTK derivation support with SAE, OWE, DPP
96a2a9a88 Send RM Enabled Capabilities element in (Re)Association Response frame
23dc196fd Check for FT support when selecting FT suites
85f3ab758 Replace deprecated readdir_r() with readdir()
641d79f16 SAE: Special test mode sae_pwe=3 for looping with password identifier
31d7fe917 Add GET_PMK for fetching the current PMK for a STA from hostapd
ca1cecc54 SAE: Verify that appropriate Status Code is used in SAE commit (SME)
c248ebaf4 DPP: Fix encryptedContent DER encoding
4dc3b70de DPP: Try to negotiate different parameters if NFC handover fails
61c049da3 DPP: Allow local channel list to be set
e2b1e7dce DPP: Require conf=configurator to allow Configurator provisioning
1ba4a10a0 DPP: Initialize conf_resp_status to non-OK
18714af2d DPP: Ignore unexpected duplicated Authentication Confirm
8f8473ceb SAE: Fix peer-commit-scalar reuse check
c4bab72d9 Use secondary channel provided by ACS for HT40 if valid
16b789eef Fix wmm compile on fedora-17 (gcc 4.7.2)
d240c74b6 nl80211: Fix regulatory limits for WMM cwmin/cwmax values
bc1289b07 nl80211: Fix WMM queue mapping for regulatory limit
fee28410d scan_est_throughput: Use ie_len instead of res->ie_len
b2b7f8dcf BSD: Fix the maximum size of a route(4) msg to 2048
25c247684 BSD: Remove an outdated comment
d807e289d BSD: Don't set or remove IFF_UP
4692e87b2 BSD: Share route(4) processing with hostapd and wpa_supplicant.
d20b34b43 BSD: Driver does not need to know about both wpa and hostap contexts
aad414e95 nl80211: Fix send_mlme for SAE external auth
1a9d270d4 Additional stats through QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO
c025c2eb5 DPP: DPPEnvelopedData generation for Configurator backup
7d9e32005 DPP: Received Configurator backup processing
ea91ddb08 DPP: DPPEnvelopedData parsing for Configurator backup/restore
312eac1d1 DPP: Add ASN.1 support into build
31b5950d0 ASN.1: Helper functions for building DER encoded data
ce1f47739 ASN.1: More OID definitions
8006742fa ASN.1: Add a helper for parsing AlgorithmIdentifier
f7f2843c4 ASN.1: Add a helper for parsing SEQUENCE
3393d94d0 ASN.1: Add a helper for parsing INTEGER
5e98998ec DPP2: Add Protocol Version attr to Auth Resp only if peer is R2 or newer
505797b45 Add a vendor attribute for RTPL instance primary frequency
76162b182 TLS: Fix bounds checking in certificate policy parser
703c2b645 DPP: Example script for NFC bootstrapping method
566972fd6 DPP: Show selected negotiation channel in DPP_BOOTSTRAP_INFO
5e287724e DPP: NFC negotiated connection handover
2bbe6ad3a DPP: Helper function for bootstrapping URI generation
12da39b38 crypto: Allow up to 10 fragments for hmac_sha*_vector()
d165b32f3 TLS: TOD-STRICT and TOD-TOFU certificate policies
cd66b8295 TLS: Fix a typo in a debug message
a62940904 Add vendor interface QCA_NL80211_VENDOR_SUBCMD_REQUEST_SAR_LIMITS_EVENT
0ecf73563 Add new QCA vendor attribute to set thermal level
8b138d282 OWE: PTK derivation workaround in STA mode
65a44e849 OWE: PTK derivation workaround in AP mode
bd50805e4 OWE: Select KDF hash algorithm based on the length of the prime
10bdce692 Fix a typo in an example configuration file comment
0d445cd39 Fix a typo in a comment
ce26f0086 Fix coloc_intf_reporting config param in hostapd in non-OWE builds
1011c7990 Do not enable HT/VHT for 6 GHz band 20 MHz width channels also
d0e116f61 Enhance get_mode() to return correct hw_mode with 6 GHz support
4658eb77d Remove deprecated text for ap_scan=0
5e32fb017 SAE: Use Anti-Clogging Token Container element with H2E
e36a5894d SAE: Use H2E whenever Password Identifier is used
c56b7a2fd SAE: Mark sae_derive_pt_ecc() static
29dd0b316 SAE H2E: Check H2E-only BSS membership selector only if SAE is enabled
4ee5a5035 trace: Handle binutils bfd.h breakage
fa308a649 hostapd: Fix a typo in sample configuration
d20365db1 EAP-SIM/AKA peer: Add support for EAP Method prefix
4bf78a79d ACS: Populate channel config from external ACS per documented behavior
fe1552d93 ACS: Update documentation of external ACS results event parameters
881177201 6 GHz: Fix Channel Width value for 80+80 in 6 GHZ Operation Info field
b4fe37c4f Silence compiler warning in no-NEED_AP_MLME builds
dd530b873 Silence compiler warning with CONFIG_NO_ROAMING=y
e1650a7b0 tests: Set key_flag when using SET_KEY
a919a2603 Introduce and add key_flag
3df4c05ae nl80211: Pass set_key() parameter struct to wpa_driver_nl80211_set_key()
99d8c4dca hostapd: Support VLAN offload to the driver
0f903f37d nl80211: VLAN offload support
4d3ae54fb Add vlan_id to driver set_key() operation
f82254645 driver: Move set_key() parameters into a struct
3912cbd88 SAE: A bit optimized sae_confirm_immediate=2 for testing purposes
33c8a1049 Do not select APs found on disabled channels for connection
aa663baf4 Fix QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL NULL check
f7b2fe99e tests: Fix undefined behavior in module tests
297d69161 OpenSSL: Fix memory leak in TOD policy validation
8296ee180 RSN IBSS: Fix EAPOL TX using control port
c52129bed nl80211: Allow control port to be disabled with a driver param
781c5a062 nl80211: Use control port TX for AP mode
d8252a981 nl80211: Report control port RX events
a79ed0687 Add no_encrypt flag for control port TX
144314eaa wpa_supplicant: Send EAPOL frames over nl80211 where available
8759e9116 nl80211: Control port over nl80211 helpers
ccaabeaa0 driver: Remove unused send_ether() driver op
3d41dd7c5 WPS: Add application extension data to WPS IE
b7bb2c020 P2P: Move p2p_long_listen into struct wpa_global
9ad3c12dd P2P: Always use global p2p_long_listen
9bedf9004 nl80211: Use monitor interface for sending no-encrypt test frames
8d84c75f7 Allow testing override for GTK/IGTK RSC from AP to STA
af670cb41 SME: Postpone current BSSID clearing until IEs are prepared
ff7743118 nl80211: Don't set offchan-OK flag if doing on-channel frame in AP mode
d5798e43f nl80211: Use current command for NL80211_CMD_REGISTER_ACTION
81ae8820a nl80211: Rename send_action_cookie to send_frame_cookie
5ad372cc3 nl80211: Clean up nl80211_send_frame_cmd() callers
0dae4354f nl80211: Get rid of separate wpa_driver_nl80211_send_frame()
e69592786 driver: Remove unused send_frame() driver op
ce0180487 Convert the only remaining send_frame() users to send_mlme()
27cc06d07 nl80211: Support no_encrypt=1 with send_mlme()
665a3007f driver: Add no_encrypt argument to send_mlme()
371002746 Make hostapd_drv_send_mlme() more generic
b3525dc17 P2P Manager: Use send_mlme() instead of send_frame() for Deauthentication
947465475 IBSS RSN: Use send_mlme() instead of send_frame() for Authentication frames
14cc3d10c nl80211: Simplify hapd_send_eapol() with monitor interface
16a266720 nl80211: Don't accept interrupted dump responses
6c5701937 Test functionality to override driver reported signal levels
c8eb7fe66 Fix signal_poll based roaming skip
a8b00423e BSD: Use struct ip rather than struct iphdr
3ea58a054 nl80211: Fix libnl error string fetching
139f7ab31 mac80211_linux: Fix libnl error string fetching
25ebd538a Drop support for libnl 1.1
1ace2f7c0 Drop debug print level for informative debug messages
ad2f09660 Maintain BSS entries for 5 seconds after interface is disabled
988f14448 Indicated if the selected BSS is the current BSS
a8ad9c31d Make min_diff determination from cur_level more readable
41f72d735 Use sel_est consistently with cur_sel in wpa_supplicant_need_to_roam()
a2c1bebd4 Improve roaming logic
9c8d550b7 Allow roam to lower signal level if throughput benefit is significant
9fafefb9e Skip roaming based on signal level difference if current SNR is good
f4f7600ad Use signal_poll noise information for roaming, if available
f97baef25 Clear SME auth_alg on FLUSH
568950c6e RSN: Do not add PMKSA candidates unnecessarily
0d1d1f0d2 Clear last Michael MIC error timer on FLUSH
69ccc557d wpa_supplicant: Fall back to avg_signal in roaming decision
7e7b23e22 Update throughput estimate for the current BSS based on signal poll
ad06ac0b0 Move throughput estimation into a helper function
ef1a45f28 Move scan/roaming related defines to a header file
98ea9d5d5 Use local variables for current BSS signal strength in roaming
22319c7fe RADIUS client: fix extra retry before failover
02c21c02d wpa_supplicant: Do not disconnect on deinit if WoWLAN is enabled
82ba4f2d1 nl80211: Add a driver ops function to check WoWLAN status
59536a33d wpa_cli: WPS-PIN-ACTIVE and WPS-CANCEL events for action scripts
b0621b083 Call hostapd_allowed_address() directly from handle_probe_req()
963681723 Fix possible memory leak of RADIUS data in handle_auth()
d4ceaafc2 Make hostapd_copy_psk_list() non-static
29024efd1 Move the RADIUS cached attributes into a struct
3cd4db231 FT: Do not deliver RRB messages locally without matching FT/SSID
c133c785d FT: Check mobility domain when sending RRB message to local managed BSS
a422d9b4c RRB: More debug prints for local delivery
7b1105afe RRB: Do not reorder locally delivered messages
4834c6869 FT: Fix hostapd_wpa_auth_oui_iter() iteration for multicast packets
18780c6d6 OpenSSL: Add support for TPM2-wrapped keys
974f84bb7 Fix ignore_broadcast_ssid behavior with SSID List and Short SSID List
1c7f652f9 AP: Support Short SSID List element in Probe Request frames
522450b7b AP: Determine Short SSID value for the BSS
41b06b065 mesh: Fix race condition in mesh mpm new peer handling
ef48f1bfb Ensure authenticator session timer is applied with wired driver
a383db064 defconfig: Enable MACsec
53661e3a9 Allow debug log to be written to both syslog and file
68f9f480e wpa_gui: Silence a compiler warning
eadfeb0e9 wpa_gui: Show entire list of networks
a3b59fa11 wpa_cli: Let LAST_ID argument to be used for LIST_NETWORKS
078217a2d STA OBSS: Update secondary channel info after CSA

Change-Id: I194039d27c1467a20aa4a28c0612ff9ba52ac7f9
diff --git a/src/ap/acs.c b/src/ap/acs.c
index 232afa8..5c01610 100644
--- a/src/ap/acs.c
+++ b/src/ap/acs.c
@@ -261,13 +261,13 @@
 }
 
 
-void acs_cleanup(struct hostapd_iface *iface)
+static void acs_cleanup_mode(struct hostapd_hw_modes *mode)
 {
 	int i;
 	struct hostapd_channel_data *chan;
 
-	for (i = 0; i < iface->current_mode->num_channels; i++) {
-		chan = &iface->current_mode->channels[i];
+	for (i = 0; i < mode->num_channels; i++) {
+		chan = &mode->channels[i];
 
 		if (chan->flag & HOSTAPD_CHAN_SURVEY_LIST_INITIALIZED)
 			acs_clean_chan_surveys(chan);
@@ -276,6 +276,15 @@
 		chan->flag |= HOSTAPD_CHAN_SURVEY_LIST_INITIALIZED;
 		chan->min_nf = 0;
 	}
+}
+
+
+void acs_cleanup(struct hostapd_iface *iface)
+{
+	int i;
+
+	for (i = 0; i < iface->num_hw_features; i++)
+		acs_cleanup_mode(&iface->hw_features[i]);
 
 	iface->chans_surveyed = 0;
 	iface->acs_num_completed_scans = 0;
@@ -453,21 +462,35 @@
 }
 
 
-static int acs_surveys_are_sufficient(struct hostapd_iface *iface)
+static int acs_surveys_are_sufficient_mode(struct hostapd_hw_modes *mode)
 {
 	int i;
 	struct hostapd_channel_data *chan;
-	int valid = 0;
 
-	for (i = 0; i < iface->current_mode->num_channels; i++) {
-		chan = &iface->current_mode->channels[i];
+	for (i = 0; i < mode->num_channels; i++) {
+		chan = &mode->channels[i];
 		if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
 		    acs_survey_list_is_sufficient(chan))
-			valid++;
+			return 1;
 	}
 
-	/* We need at least survey data for one channel */
-	return !!valid;
+	return 0;
+}
+
+
+static int acs_surveys_are_sufficient(struct hostapd_iface *iface)
+{
+	int i;
+	struct hostapd_hw_modes *mode;
+
+	for (i = 0; i < iface->num_hw_features; i++) {
+		mode = &iface->hw_features[i];
+		if (!hostapd_hw_skip_mode(iface, mode) &&
+		    acs_surveys_are_sufficient_mode(mode))
+			return 1;
+	}
+
+	return 0;
 }
 
 
@@ -489,14 +512,14 @@
 }
 
 
-static void acs_survey_all_chans_intereference_factor(
-	struct hostapd_iface *iface)
+static void acs_survey_mode_interference_factor(
+	struct hostapd_iface *iface, struct hostapd_hw_modes *mode)
 {
 	int i;
 	struct hostapd_channel_data *chan;
 
-	for (i = 0; i < iface->current_mode->num_channels; i++) {
-		chan = &iface->current_mode->channels[i];
+	for (i = 0; i < mode->num_channels; i++) {
+		chan = &mode->channels[i];
 
 		if (!acs_usable_chan(chan))
 			continue;
@@ -515,14 +538,28 @@
 }
 
 
-static struct hostapd_channel_data *acs_find_chan(struct hostapd_iface *iface,
-						  int freq)
+static void acs_survey_all_chans_interference_factor(
+	struct hostapd_iface *iface)
+{
+	int i;
+	struct hostapd_hw_modes *mode;
+
+	for (i = 0; i < iface->num_hw_features; i++) {
+		mode = &iface->hw_features[i];
+		if (!hostapd_hw_skip_mode(iface, mode))
+			acs_survey_mode_interference_factor(iface, mode);
+	}
+}
+
+
+static struct hostapd_channel_data *
+acs_find_chan_mode(struct hostapd_hw_modes *mode, int freq)
 {
 	struct hostapd_channel_data *chan;
 	int i;
 
-	for (i = 0; i < iface->current_mode->num_channels; i++) {
-		chan = &iface->current_mode->channels[i];
+	for (i = 0; i < mode->num_channels; i++) {
+		chan = &mode->channels[i];
 
 		if (chan->flag & HOSTAPD_CHAN_DISABLED)
 			continue;
@@ -535,6 +572,26 @@
 }
 
 
+static struct hostapd_channel_data *
+acs_find_chan(struct hostapd_iface *iface, int freq)
+{
+	int i;
+	struct hostapd_hw_modes *mode;
+	struct hostapd_channel_data *chan;
+
+	for (i = 0; i < iface->num_hw_features; i++) {
+		mode = &iface->hw_features[i];
+		if (!hostapd_hw_skip_mode(iface, mode)) {
+			chan = acs_find_chan_mode(mode, freq);
+			if (chan)
+				return chan;
+		}
+	}
+
+	return NULL;
+}
+
+
 static int is_24ghz_mode(enum hostapd_hw_mode mode)
 {
 	return mode == HOSTAPD_MODE_IEEE80211B ||
@@ -565,58 +622,24 @@
 #define ACS_24GHZ_PREFER_1_6_11 0.8
 #endif /* ACS_24GHZ_PREFER_1_6_11 */
 
-/*
- * At this point it's assumed chan->interface_factor has been computed.
- * This function should be reusable regardless of interference computation
- * option (survey, BSS, spectral, ...). chan->interference factor must be
- * summable (i.e., must be always greater than zero).
- */
-static struct hostapd_channel_data *
-acs_find_ideal_chan(struct hostapd_iface *iface)
+static void
+acs_find_ideal_chan_mode(struct hostapd_iface *iface,
+			 struct hostapd_hw_modes *mode,
+			 int n_chans, u32 bw,
+			 struct hostapd_channel_data **rand_chan,
+			 struct hostapd_channel_data **ideal_chan,
+			 long double *ideal_factor)
 {
-	struct hostapd_channel_data *chan, *adj_chan, *ideal_chan = NULL,
-		*rand_chan = NULL;
-	long double factor, ideal_factor = 0;
+	struct hostapd_channel_data *chan, *adj_chan = NULL;
+	long double factor;
 	int i, j;
-	int n_chans = 1;
-	u32 bw;
 	unsigned int k;
 
-	/* TODO: HT40- support */
-
-	if (iface->conf->ieee80211n &&
-	    iface->conf->secondary_channel == -1) {
-		wpa_printf(MSG_ERROR, "ACS: HT40- is not supported yet. Please try HT40+");
-		return NULL;
-	}
-
-	if (iface->conf->ieee80211n &&
-	    iface->conf->secondary_channel)
-		n_chans = 2;
-
-	if (iface->conf->ieee80211ac || iface->conf->ieee80211ax) {
-		switch (hostapd_get_oper_chwidth(iface->conf)) {
-		case CHANWIDTH_80MHZ:
-			n_chans = 4;
-			break;
-		case CHANWIDTH_160MHZ:
-			n_chans = 8;
-			break;
-		}
-	}
-
-	bw = num_chan_to_bw(n_chans);
-
-	/* TODO: VHT/HE80+80. Update acs_adjust_center_freq() too. */
-
-	wpa_printf(MSG_DEBUG,
-		   "ACS: Survey analysis for selected bandwidth %d MHz", bw);
-
-	for (i = 0; i < iface->current_mode->num_channels; i++) {
+	for (i = 0; i < mode->num_channels; i++) {
 		double total_weight;
 		struct acs_bias *bias, tmp_bias;
 
-		chan = &iface->current_mode->channels[i];
+		chan = &mode->channels[i];
 
 		/* Since in the current ACS implementation the first channel is
 		 * always a primary channel, skip channels not available as
@@ -637,7 +660,7 @@
 
 		/* HT40 on 5 GHz has a limited set of primary channels as per
 		 * 11n Annex J */
-		if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A &&
+		if (mode->mode == HOSTAPD_MODE_IEEE80211A &&
 		    iface->conf->ieee80211n &&
 		    iface->conf->secondary_channel &&
 		    !acs_usable_ht40_chan(chan)) {
@@ -646,7 +669,7 @@
 			continue;
 		}
 
-		if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A &&
+		if (mode->mode == HOSTAPD_MODE_IEEE80211A &&
 		    (iface->conf->ieee80211ac || iface->conf->ieee80211ax)) {
 			if (hostapd_get_oper_chwidth(iface->conf) ==
 			    CHANWIDTH_80MHZ &&
@@ -698,7 +721,7 @@
 
 		/* 2.4 GHz has overlapping 20 MHz channels. Include adjacent
 		 * channel interference factor. */
-		if (is_24ghz_mode(iface->current_mode->mode)) {
+		if (is_24ghz_mode(mode->mode)) {
 			for (j = 0; j < n_chans; j++) {
 				adj_chan = acs_find_chan(iface, chan->freq +
 							 (j * 20) - 5);
@@ -744,7 +767,7 @@
 					break;
 				bias = NULL;
 			}
-		} else if (is_24ghz_mode(iface->current_mode->mode) &&
+		} else if (is_24ghz_mode(mode->mode) &&
 			   is_common_24ghz_chan(chan->chan)) {
 			tmp_bias.channel = chan->chan;
 			tmp_bias.bias = ACS_24GHZ_PREFER_1_6_11;
@@ -763,14 +786,71 @@
 		}
 
 		if (acs_usable_chan(chan) &&
-		    (!ideal_chan || factor < ideal_factor)) {
-			ideal_factor = factor;
-			ideal_chan = chan;
+		    (!*ideal_chan || factor < *ideal_factor)) {
+			*ideal_factor = factor;
+			*ideal_chan = chan;
 		}
 
 		/* This channel would at least be usable */
-		if (!rand_chan)
-			rand_chan = chan;
+		if (!(*rand_chan))
+			*rand_chan = chan;
+	}
+}
+
+
+/*
+ * At this point it's assumed chan->interference_factor has been computed.
+ * This function should be reusable regardless of interference computation
+ * option (survey, BSS, spectral, ...). chan->interference factor must be
+ * summable (i.e., must be always greater than zero).
+ */
+static struct hostapd_channel_data *
+acs_find_ideal_chan(struct hostapd_iface *iface)
+{
+	struct hostapd_channel_data *ideal_chan = NULL,
+		*rand_chan = NULL;
+	long double ideal_factor = 0;
+	int i;
+	int n_chans = 1;
+	u32 bw;
+	struct hostapd_hw_modes *mode;
+
+	/* TODO: HT40- support */
+
+	if (iface->conf->ieee80211n &&
+	    iface->conf->secondary_channel == -1) {
+		wpa_printf(MSG_ERROR, "ACS: HT40- is not supported yet. Please try HT40+");
+		return NULL;
+	}
+
+	if (iface->conf->ieee80211n &&
+	    iface->conf->secondary_channel)
+		n_chans = 2;
+
+	if (iface->conf->ieee80211ac || iface->conf->ieee80211ax) {
+		switch (hostapd_get_oper_chwidth(iface->conf)) {
+		case CHANWIDTH_80MHZ:
+			n_chans = 4;
+			break;
+		case CHANWIDTH_160MHZ:
+			n_chans = 8;
+			break;
+		}
+	}
+
+	bw = num_chan_to_bw(n_chans);
+
+	/* TODO: VHT/HE80+80. Update acs_adjust_center_freq() too. */
+
+	wpa_printf(MSG_DEBUG,
+		   "ACS: Survey analysis for selected bandwidth %d MHz", bw);
+
+	for (i = 0; i < iface->num_hw_features; i++) {
+		mode = &iface->hw_features[i];
+		if (!hostapd_hw_skip_mode(iface, mode))
+			acs_find_ideal_chan_mode(iface, mode, n_chans, bw,
+						 &rand_chan, &ideal_chan,
+						 &ideal_factor);
 	}
 
 	if (ideal_chan) {
@@ -826,7 +906,7 @@
 		return -1;
 	}
 
-	acs_survey_all_chans_intereference_factor(iface);
+	acs_survey_all_chans_interference_factor(iface);
 	return 0;
 }
 
@@ -918,21 +998,15 @@
 }
 
 
-static int acs_request_scan(struct hostapd_iface *iface)
+static int * acs_request_scan_add_freqs(struct hostapd_iface *iface,
+					struct hostapd_hw_modes *mode,
+					int *freq)
 {
-	struct wpa_driver_scan_params params;
 	struct hostapd_channel_data *chan;
-	int i, *freq;
+	int i;
 
-	os_memset(&params, 0, sizeof(params));
-	params.freqs = os_calloc(iface->current_mode->num_channels + 1,
-				 sizeof(params.freqs[0]));
-	if (params.freqs == NULL)
-		return -1;
-
-	freq = params.freqs;
-	for (i = 0; i < iface->current_mode->num_channels; i++) {
-		chan = &iface->current_mode->channels[i];
+	for (i = 0; i < mode->num_channels; i++) {
+		chan = &mode->channels[i];
 		if (chan->flag & HOSTAPD_CHAN_DISABLED)
 			continue;
 
@@ -941,6 +1015,39 @@
 
 		*freq++ = chan->freq;
 	}
+
+	return freq;
+}
+
+
+static int acs_request_scan(struct hostapd_iface *iface)
+{
+	struct wpa_driver_scan_params params;
+	int i, *freq;
+	int num_channels;
+	struct hostapd_hw_modes *mode;
+
+	os_memset(&params, 0, sizeof(params));
+
+	num_channels = 0;
+	for (i = 0; i < iface->num_hw_features; i++) {
+		mode = &iface->hw_features[i];
+		if (!hostapd_hw_skip_mode(iface, mode))
+			num_channels += mode->num_channels;
+	}
+
+	params.freqs = os_calloc(num_channels + 1, sizeof(params.freqs[0]));
+	if (params.freqs == NULL)
+		return -1;
+
+	freq = params.freqs;
+
+	for (i = 0; i < iface->num_hw_features; i++) {
+		mode = &iface->hw_features[i];
+		if (!hostapd_hw_skip_mode(iface, mode))
+			freq = acs_request_scan_add_freqs(iface, mode, freq);
+	}
+
 	*freq = 0;
 
 	if (params.freqs == freq) {
@@ -978,7 +1085,8 @@
 		return HOSTAPD_CHAN_ACS;
 	}
 
-	if (!iface->current_mode)
+	if (!iface->current_mode &&
+	    iface->conf->hw_mode != HOSTAPD_MODE_IEEE80211ANY)
 		return HOSTAPD_CHAN_INVALID;
 
 	acs_cleanup(iface);
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index 68af3c1..5bf4502 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -54,16 +54,21 @@
 	bss->logger_syslog = (unsigned int) -1;
 	bss->logger_stdout = (unsigned int) -1;
 
+#ifdef CONFIG_WEP
 	bss->auth_algs = WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED;
 
 	bss->wep_rekeying_period = 300;
 	/* use key0 in individual key and key1 in broadcast key */
 	bss->broadcast_key_idx_min = 1;
 	bss->broadcast_key_idx_max = 2;
+#else /* CONFIG_WEP */
+	bss->auth_algs = WPA_AUTH_ALG_OPEN;
+#endif /* CONFIG_WEP */
 	bss->eap_reauth_period = 3600;
 
 	bss->wpa_group_rekey = 600;
 	bss->wpa_gmk_rekey = 86400;
+	bss->wpa_deny_ptk0_rekey = PTK0_REKEY_ALLOW_ALWAYS;
 	bss->wpa_group_update_count = 4;
 	bss->wpa_pairwise_update_count = 4;
 	bss->wpa_disable_eapol_key_retries =
@@ -251,6 +256,9 @@
 		HE_OPERATION_RTS_THRESHOLD_OFFSET;
 	/* Set default basic MCS/NSS set to single stream MCS 0-7 */
 	conf->he_op.he_basic_mcs_nss_set = 0xfffc;
+	conf->he_op.he_bss_color_disabled = 1;
+	conf->he_op.he_bss_color_partial = 0;
+	conf->he_op.he_bss_color = 1;
 #endif /* CONFIG_IEEE80211AX */
 
 	/* The third octet of the country string uses an ASCII space character
@@ -301,6 +309,7 @@
 
 	while (fgets(buf, sizeof(buf), f)) {
 		int vlan_id = 0;
+		int wps = 0;
 
 		line++;
 
@@ -331,6 +340,8 @@
 				value = "";
 			if (!os_strcmp(name, "keyid")) {
 				keyid = value;
+			} else if (!os_strcmp(name, "wps")) {
+				wps = atoi(value);
 			} else if (!os_strcmp(name, "vlanid")) {
 				vlan_id = atoi(value);
 			} else {
@@ -348,8 +359,9 @@
 		if (!token)
 			token = "";
 		if (hwaddr_aton(token, addr)) {
-			wpa_printf(MSG_ERROR, "Invalid MAC address '%s' on "
-				   "line %d in '%s'", token, line, fname);
+			wpa_printf(MSG_ERROR,
+				   "Invalid MAC address '%s' on line %d in '%s'",
+				   token, line, fname);
 			ret = -1;
 			break;
 		}
@@ -377,16 +389,17 @@
 
 		ok = 0;
 		len = os_strlen(pos);
-		if (len == 64 && hexstr2bin(pos, psk->psk, PMK_LEN) == 0)
+		if (len == 2 * PMK_LEN &&
+		    hexstr2bin(pos, psk->psk, PMK_LEN) == 0)
 			ok = 1;
-		else if (len >= 8 && len < 64) {
-			pbkdf2_sha1(pos, ssid->ssid, ssid->ssid_len,
-				    4096, psk->psk, PMK_LEN);
+		else if (len >= 8 && len < 64 &&
+			 pbkdf2_sha1(pos, ssid->ssid, ssid->ssid_len,
+				     4096, psk->psk, PMK_LEN) == 0)
 			ok = 1;
-		}
 		if (!ok) {
-			wpa_printf(MSG_ERROR, "Invalid PSK '%s' on line %d in "
-				   "'%s'", pos, line, fname);
+			wpa_printf(MSG_ERROR,
+				   "Invalid PSK '%s' on line %d in '%s'",
+				   pos, line, fname);
 			os_free(psk);
 			ret = -1;
 			break;
@@ -404,6 +417,8 @@
 			}
 		}
 
+		psk->wps = wps;
+
 		psk->next = ssid->wpa_psk;
 		ssid->wpa_psk = psk;
 	}
@@ -441,7 +456,9 @@
 	struct hostapd_ssid *ssid = &conf->ssid;
 	struct sae_password_entry *pw;
 
-	if (conf->sae_pwe == 0 || !wpa_key_mgmt_sae(conf->wpa_key_mgmt))
+	if ((conf->sae_pwe == 0 && !hostapd_sae_pw_id_in_use(conf)) ||
+	    conf->sae_pwe == 3 ||
+	    !wpa_key_mgmt_sae(conf->wpa_key_mgmt))
 		return 0; /* PT not needed */
 
 	sae_deinit_pt(ssid->pt);
@@ -623,6 +640,7 @@
 }
 
 
+#ifdef CONFIG_WEP
 static void hostapd_config_free_wep(struct hostapd_wep_keys *keys)
 {
 	int i;
@@ -631,6 +649,7 @@
 		keys->key[i] = NULL;
 	}
 }
+#endif /* CONFIG_WEP */
 
 
 void hostapd_config_clear_wpa_psk(struct hostapd_wpa_psk **l)
@@ -719,7 +738,9 @@
 
 	str_clear_free(conf->ssid.wpa_passphrase);
 	os_free(conf->ssid.wpa_psk_file);
+#ifdef CONFIG_WEP
 	hostapd_config_free_wep(&conf->ssid.wep);
+#endif /* CONFIG_WEP */
 #ifdef CONFIG_FULL_DYNAMIC_VLAN
 	os_free(conf->ssid.vlan_tagged_interface);
 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
@@ -813,6 +834,7 @@
 	os_free(conf->upc);
 	for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++)
 		wpabuf_free(conf->wps_vendor_ext[i]);
+	wpabuf_free(conf->wps_application_ext);
 	wpabuf_free(conf->wps_nfc_dh_pubkey);
 	wpabuf_free(conf->wps_nfc_dh_privkey);
 	wpabuf_free(conf->wps_nfc_dev_pw);
@@ -880,7 +902,12 @@
 #ifdef CONFIG_TESTING_OPTIONS
 	wpabuf_free(conf->own_ie_override);
 	wpabuf_free(conf->sae_commit_override);
+	wpabuf_free(conf->rsne_override_eapol);
 	wpabuf_free(conf->rsnxe_override_eapol);
+	wpabuf_free(conf->rsne_override_ft);
+	wpabuf_free(conf->rsnxe_override_ft);
+	wpabuf_free(conf->gtk_rsc_override);
+	wpabuf_free(conf->igtk_rsc_override);
 #endif /* CONFIG_TESTING_OPTIONS */
 
 	os_free(conf->no_probe_resp_if_seen_on);
@@ -1090,6 +1117,7 @@
 		return -1;
 	}
 
+#ifdef CONFIG_WEP
 	if (bss->wpa) {
 		int wep, i;
 
@@ -1107,6 +1135,7 @@
 			return -1;
 		}
 	}
+#endif /* CONFIG_WEP */
 
 	if (full_config && bss->wpa &&
 	    bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
@@ -1154,7 +1183,6 @@
 	}
 #endif /* CONFIG_IEEE80211R_AP */
 
-#ifdef CONFIG_IEEE80211N
 	if (full_config && conf->ieee80211n &&
 	    conf->hw_mode == HOSTAPD_MODE_IEEE80211B) {
 		bss->disable_11n = 1;
@@ -1162,12 +1190,14 @@
 			   "allowed, disabling HT capabilities");
 	}
 
+#ifdef CONFIG_WEP
 	if (full_config && conf->ieee80211n &&
 	    bss->ssid.security_policy == SECURITY_STATIC_WEP) {
 		bss->disable_11n = 1;
 		wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WEP is not "
 			   "allowed, disabling HT capabilities");
 	}
+#endif /* CONFIG_WEP */
 
 	if (full_config && conf->ieee80211n && bss->wpa &&
 	    !(bss->wpa_pairwise & WPA_CIPHER_CCMP) &&
@@ -1179,15 +1209,16 @@
 			   "requires CCMP/GCMP to be enabled, disabling HT "
 			   "capabilities");
 	}
-#endif /* CONFIG_IEEE80211N */
 
 #ifdef CONFIG_IEEE80211AC
+#ifdef CONFIG_WEP
 	if (full_config && conf->ieee80211ac &&
 	    bss->ssid.security_policy == SECURITY_STATIC_WEP) {
 		bss->disable_11ac = 1;
 		wpa_printf(MSG_ERROR,
 			   "VHT (IEEE 802.11ac) with WEP is not allowed, disabling VHT capabilities");
 	}
+#endif /* CONFIG_WEP */
 
 	if (full_config && conf->ieee80211ac && bss->wpa &&
 	    !(bss->wpa_pairwise & WPA_CIPHER_CCMP) &&
@@ -1207,12 +1238,14 @@
 		bss->wps_state = 0;
 	}
 
+#ifdef CONFIG_WEP
 	if (full_config && bss->wps_state &&
 	    bss->ssid.wep.keys_set && bss->wpa == 0) {
 		wpa_printf(MSG_INFO, "WPS: WEP configuration forced WPS to be "
 			   "disabled");
 		bss->wps_state = 0;
 	}
+#endif /* CONFIG_WEP */
 
 	if (full_config && bss->wps_state && bss->wpa &&
 	    (!(bss->wpa & 2) ||
@@ -1336,11 +1369,13 @@
 void hostapd_set_security_params(struct hostapd_bss_config *bss,
 				 int full_config)
 {
+#ifdef CONFIG_WEP
 	if (bss->individual_wep_key_len == 0) {
 		/* individual keys are not use; can use key idx0 for
 		 * broadcast keys */
 		bss->broadcast_key_idx_min = 0;
 	}
+#endif /* CONFIG_WEP */
 
 	if ((bss->wpa & 2) && bss->rsn_pairwise == 0)
 		bss->rsn_pairwise = bss->wpa_pairwise;
@@ -1366,6 +1401,7 @@
 	} else if (bss->ieee802_1x) {
 		int cipher = WPA_CIPHER_NONE;
 		bss->ssid.security_policy = SECURITY_IEEE_802_1X;
+#ifdef CONFIG_WEP
 		bss->ssid.wep.default_len = bss->default_wep_key_len;
 		if (full_config && bss->default_wep_key_len) {
 			cipher = bss->default_wep_key_len >= 13 ?
@@ -1376,11 +1412,13 @@
 			else
 				cipher = WPA_CIPHER_WEP40;
 		}
+#endif /* CONFIG_WEP */
 		bss->wpa_group = cipher;
 		bss->wpa_pairwise = cipher;
 		bss->rsn_pairwise = cipher;
 		if (full_config)
 			bss->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
+#ifdef CONFIG_WEP
 	} else if (bss->ssid.wep.keys_set) {
 		int cipher = WPA_CIPHER_WEP40;
 		if (bss->ssid.wep.len[0] >= 13)
@@ -1391,6 +1429,7 @@
 		bss->rsn_pairwise = cipher;
 		if (full_config)
 			bss->wpa_key_mgmt = WPA_KEY_MGMT_NONE;
+#endif /* CONFIG_WEP */
 	} else if (bss->osen) {
 		bss->ssid.security_policy = SECURITY_OSEN;
 		bss->wpa_group = WPA_CIPHER_CCMP;
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 83b8aee..2a0bf07 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -67,6 +67,7 @@
 struct ft_remote_r0kh;
 struct ft_remote_r1kh;
 
+#ifdef CONFIG_WEP
 #define NUM_WEP_KEYS 4
 struct hostapd_wep_keys {
 	u8 idx;
@@ -75,10 +76,13 @@
 	int keys_set;
 	size_t default_len; /* key length used for dynamic key generation */
 };
+#endif /* CONFIG_WEP */
 
 typedef enum hostap_security_policy {
 	SECURITY_PLAINTEXT = 0,
+#ifdef CONFIG_WEP
 	SECURITY_STATIC_WEP = 1,
+#endif /* CONFIG_WEP */
 	SECURITY_IEEE_802_1X = 2,
 	SECURITY_WPA_PSK = 3,
 	SECURITY_WPA = 4,
@@ -88,6 +92,7 @@
 struct hostapd_ssid {
 	u8 ssid[SSID_MAX_LEN];
 	size_t ssid_len;
+	u32 short_ssid;
 	unsigned int ssid_set:1;
 	unsigned int utf8_ssid:1;
 	unsigned int wpa_passphrase_set:1;
@@ -101,7 +106,9 @@
 	char *wpa_psk_file;
 	struct sae_pt *pt;
 
+#ifdef CONFIG_WEP
 	struct hostapd_wep_keys wep;
+#endif /* CONFIG_WEP */
 
 #define DYNAMIC_VLAN_DISABLED 0
 #define DYNAMIC_VLAN_OPTIONAL 1
@@ -151,6 +158,7 @@
 	struct hostapd_wpa_psk *next;
 	int group;
 	char keyid[KEYID_LEN];
+	int wps;
 	u8 psk[PMK_LEN];
 	u8 addr[ETH_ALEN];
 	u8 p2p_dev_addr[ETH_ALEN];
@@ -319,10 +327,12 @@
 	size_t eap_req_id_text_len;
 	int eapol_key_index_workaround;
 
+#ifdef CONFIG_WEP
 	size_t default_wep_key_len;
 	int individual_wep_key_len;
 	int wep_rekeying_period;
 	int broadcast_key_idx_min, broadcast_key_idx_max;
+#endif /* CONFIG_WEP */
 	int eap_reauth_period;
 	int erp_send_reauth_start;
 	char *erp_domain;
@@ -344,9 +354,11 @@
 			* algorithms, WPA_AUTH_ALG_{OPEN,SHARED,LEAP} */
 
 	int wpa; /* bitfield of WPA_PROTO_WPA, WPA_PROTO_RSN */
+	int extended_key_id;
 	int wpa_key_mgmt;
 	enum mfp_options ieee80211w;
 	int group_mgmt_cipher;
+	int beacon_prot;
 	/* dot11AssociationSAQueryMaximumTimeout (in TUs) */
 	unsigned int assoc_sa_query_max_timeout;
 	/* dot11AssociationSAQueryRetryTimeout (in TUs) */
@@ -367,6 +379,7 @@
 	int wpa_strict_rekey;
 	int wpa_gmk_rekey;
 	int wpa_ptk_rekey;
+	enum ptk0_rekey_handling wpa_deny_ptk0_rekey;
 	u32 wpa_group_update_count;
 	u32 wpa_pairwise_update_count;
 	int wpa_disable_eapol_key_retries;
@@ -497,6 +510,7 @@
 	char *model_url;
 	char *upc;
 	struct wpabuf *wps_vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
+	struct wpabuf *wps_application_ext;
 	int wps_nfc_pw_from_config;
 	int wps_nfc_dev_pw_id;
 	struct wpabuf *wps_nfc_dh_pubkey;
@@ -664,7 +678,14 @@
 	struct wpabuf *own_ie_override;
 	int sae_reflection_attack;
 	struct wpabuf *sae_commit_override;
+	struct wpabuf *rsne_override_eapol;
 	struct wpabuf *rsnxe_override_eapol;
+	struct wpabuf *rsne_override_ft;
+	struct wpabuf *rsnxe_override_ft;
+	struct wpabuf *gtk_rsc_override;
+	struct wpabuf *igtk_rsc_override;
+	int no_beacon_rsnxe;
+	int skip_prune_assoc;
 #endif /* CONFIG_TESTING_OPTIONS */
 
 #define MESH_ENABLED BIT(0)
@@ -720,6 +741,8 @@
 	struct wpabuf *dpp_csign;
 #ifdef CONFIG_DPP2
 	struct dpp_controller_conf *dpp_controller;
+	int dpp_configurator_connectivity;
+	int dpp_pfs;
 #endif /* CONFIG_DPP2 */
 #endif /* CONFIG_DPP */
 
@@ -729,12 +752,15 @@
 	size_t owe_transition_ssid_len;
 	char owe_transition_ifname[IFNAMSIZ + 1];
 	int *owe_groups;
+	int owe_ptk_workaround;
 #endif /* CONFIG_OWE */
 
 	int coloc_intf_reporting;
 
 	u8 send_probe_response;
 
+	u8 transition_disable;
+
 #define BACKHAUL_BSS 1
 #define FRONTHAUL_BSS 2
 	int multi_ap; /* bitmap of BACKHAUL_BSS, FRONTHAUL_BSS */
@@ -848,6 +874,8 @@
  */
 struct he_operation {
 	u8 he_bss_color;
+	u8 he_bss_color_disabled;
+	u8 he_bss_color_partial;
 	u8 he_default_pe_duration;
 	u8 he_twt_required;
 	u16 he_rts_threshold;
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index 7585866..1f284f0 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -588,7 +588,7 @@
 int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr,
 			  int total_flags, int flags_or, int flags_and)
 {
-	if (hapd->driver == NULL || hapd->driver->sta_set_flags == NULL)
+	if (!hapd->driver || !hapd->drv_priv || !hapd->driver->sta_set_flags)
 		return 0;
 	return hapd->driver->sta_set_flags(hapd->drv_priv, addr, total_flags,
 					   flags_or, flags_and);
@@ -680,36 +680,41 @@
 
 int hostapd_drv_set_key(const char *ifname, struct hostapd_data *hapd,
 			enum wpa_alg alg, const u8 *addr,
-			int key_idx, int set_tx,
+			int key_idx, int vlan_id, int set_tx,
 			const u8 *seq, size_t seq_len,
-			const u8 *key, size_t key_len)
+			const u8 *key, size_t key_len, enum key_flag key_flag)
 {
+	struct wpa_driver_set_key_params params;
+
 	if (hapd->driver == NULL || hapd->driver->set_key == NULL)
 		return 0;
-	return hapd->driver->set_key(ifname, hapd->drv_priv, alg, addr,
-				     key_idx, set_tx, seq, seq_len, key,
-				     key_len);
+
+	os_memset(&params, 0, sizeof(params));
+	params.ifname = ifname;
+	params.alg = alg;
+	params.addr = addr;
+	params.key_idx = key_idx;
+	params.set_tx = set_tx;
+	params.seq = seq;
+	params.seq_len = seq_len;
+	params.key = key;
+	params.key_len = key_len;
+	params.vlan_id = vlan_id;
+	params.key_flag = key_flag;
+
+	return hapd->driver->set_key(hapd->drv_priv, &params);
 }
 
 
 int hostapd_drv_send_mlme(struct hostapd_data *hapd,
-			  const void *msg, size_t len, int noack)
+			  const void *msg, size_t len, int noack,
+			  const u16 *csa_offs, size_t csa_offs_len,
+			  int no_encrypt)
 {
 	if (!hapd->driver || !hapd->driver->send_mlme || !hapd->drv_priv)
 		return 0;
 	return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0,
-				       NULL, 0);
-}
-
-
-int hostapd_drv_send_mlme_csa(struct hostapd_data *hapd,
-			      const void *msg, size_t len, int noack,
-			      const u16 *csa_offs, size_t csa_offs_len)
-{
-	if (hapd->driver == NULL || hapd->driver->send_mlme == NULL)
-		return 0;
-	return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0,
-				       csa_offs, csa_offs_len);
+				       csa_offs, csa_offs_len, no_encrypt, 0);
 }
 
 
@@ -933,6 +938,7 @@
 	}
 
 	params.freq_list = freq_list;
+	params.edmg_enabled = hapd->iface->conf->enable_edmg;
 
 	params.ht_enabled = !!(hapd->iface->conf->ieee80211n);
 	params.ht40_enabled = !!(hapd->iface->conf->ht_capab &
diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
index fa413df..56d1ad8 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -89,14 +89,13 @@
 int hostapd_drv_set_key(const char *ifname,
 			struct hostapd_data *hapd,
 			enum wpa_alg alg, const u8 *addr,
-			int key_idx, int set_tx,
+			int key_idx, int vlan_id, int set_tx,
 			const u8 *seq, size_t seq_len,
-			const u8 *key, size_t key_len);
+			const u8 *key, size_t key_len, enum key_flag key_flag);
 int hostapd_drv_send_mlme(struct hostapd_data *hapd,
-			  const void *msg, size_t len, int noack);
-int hostapd_drv_send_mlme_csa(struct hostapd_data *hapd,
-			      const void *msg, size_t len, int noack,
-			      const u16 *csa_offs, size_t csa_offs_len);
+			  const void *msg, size_t len, int noack,
+			  const u16 *csa_offs, size_t csa_offs_len,
+			  int no_encrypt);
 int hostapd_drv_sta_deauth(struct hostapd_data *hapd,
 			   const u8 *addr, int reason);
 int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
diff --git a/src/ap/ap_list.c b/src/ap/ap_list.c
index 8bf6dde..20be7f8 100644
--- a/src/ap/ap_list.c
+++ b/src/ap/ap_list.c
@@ -228,7 +228,6 @@
 		set_beacon++;
 	}
 
-#ifdef CONFIG_IEEE80211N
 	if (!iface->olbc_ht && !ap->ht_support &&
 	    (ap->channel == 0 ||
 	     ap->channel == iface->conf->channel ||
@@ -241,7 +240,6 @@
 			   MAC2STR(ap->addr), ap->channel);
 		set_beacon++;
 	}
-#endif /* CONFIG_IEEE80211N */
 
 	if (set_beacon)
 		ieee802_11_update_beacons(iface);
@@ -285,14 +283,12 @@
 			iface->olbc = 0;
 			set_beacon++;
 		}
-#ifdef CONFIG_IEEE80211N
 		if (!olbc_ht && iface->olbc_ht) {
 			wpa_printf(MSG_DEBUG, "OLBC HT not detected anymore");
 			iface->olbc_ht = 0;
 			hostapd_ht_operation_update(iface);
 			set_beacon++;
 		}
-#endif /* CONFIG_IEEE80211N */
 	}
 
 	if (set_beacon)
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index 331c09b..47ced9a 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -36,27 +36,6 @@
 
 #ifdef NEED_AP_MLME
 
-static u8 * hostapd_eid_rm_enabled_capab(struct hostapd_data *hapd, u8 *eid,
-					 size_t len)
-{
-	size_t i;
-
-	for (i = 0; i < RRM_CAPABILITIES_IE_LEN; i++) {
-		if (hapd->conf->radio_measurements[i])
-			break;
-	}
-
-	if (i == RRM_CAPABILITIES_IE_LEN || len < 2 + RRM_CAPABILITIES_IE_LEN)
-		return eid;
-
-	*eid++ = WLAN_EID_RRM_ENABLED_CAPABILITIES;
-	*eid++ = RRM_CAPABILITIES_IE_LEN;
-	os_memcpy(eid, hapd->conf->radio_measurements, RRM_CAPABILITIES_IE_LEN);
-
-	return eid + RRM_CAPABILITIES_IE_LEN;
-}
-
-
 static u8 * hostapd_eid_bss_load(struct hostapd_data *hapd, u8 *eid, size_t len)
 {
 	if (len < 2 + 5)
@@ -287,17 +266,101 @@
 }
 
 
-static u8 * hostapd_eid_wpa(struct hostapd_data *hapd, u8 *eid, size_t len)
+static const u8 * hostapd_wpa_ie(struct hostapd_data *hapd, u8 eid)
+{
+	const u8 *ies;
+	size_t ies_len;
+
+	ies = wpa_auth_get_wpa_ie(hapd->wpa_auth, &ies_len);
+	if (!ies)
+		return NULL;
+
+	return get_ie(ies, ies_len, eid);
+}
+
+
+static const u8 * hostapd_vendor_wpa_ie(struct hostapd_data *hapd,
+					u32 vendor_type)
+{
+	const u8 *ies;
+	size_t ies_len;
+
+	ies = wpa_auth_get_wpa_ie(hapd->wpa_auth, &ies_len);
+	if (!ies)
+		return NULL;
+
+	return get_vendor_ie(ies, ies_len, vendor_type);
+}
+
+
+static u8 * hostapd_get_rsne(struct hostapd_data *hapd, u8 *pos, size_t len)
 {
 	const u8 *ie;
-	size_t ielen;
 
-	ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &ielen);
-	if (ie == NULL || ielen > len)
-		return eid;
+	ie = hostapd_wpa_ie(hapd, WLAN_EID_RSN);
+	if (!ie || 2U + ie[1] > len)
+		return pos;
 
-	os_memcpy(eid, ie, ielen);
-	return eid + ielen;
+	os_memcpy(pos, ie, 2 + ie[1]);
+	return pos + 2 + ie[1];
+}
+
+
+static u8 * hostapd_get_mde(struct hostapd_data *hapd, u8 *pos, size_t len)
+{
+	const u8 *ie;
+
+	ie = hostapd_wpa_ie(hapd, WLAN_EID_MOBILITY_DOMAIN);
+	if (!ie || 2U + ie[1] > len)
+		return pos;
+
+	os_memcpy(pos, ie, 2 + ie[1]);
+	return pos + 2 + ie[1];
+}
+
+
+static u8 * hostapd_get_rsnxe(struct hostapd_data *hapd, u8 *pos, size_t len)
+{
+	const u8 *ie;
+
+#ifdef CONFIG_TESTING_OPTIONS
+	if (hapd->conf->no_beacon_rsnxe) {
+		wpa_printf(MSG_INFO, "TESTING: Do not add RSNXE into Beacon");
+		return pos;
+	}
+#endif /* CONFIG_TESTING_OPTIONS */
+	ie = hostapd_wpa_ie(hapd, WLAN_EID_RSNX);
+	if (!ie || 2U + ie[1] > len)
+		return pos;
+
+	os_memcpy(pos, ie, 2 + ie[1]);
+	return pos + 2 + ie[1];
+}
+
+
+static u8 * hostapd_get_wpa_ie(struct hostapd_data *hapd, u8 *pos, size_t len)
+{
+	const u8 *ie;
+
+	ie = hostapd_vendor_wpa_ie(hapd, WPA_IE_VENDOR_TYPE);
+	if (!ie || 2U + ie[1] > len)
+		return pos;
+
+	os_memcpy(pos, ie, 2 + ie[1]);
+	return pos + 2 + ie[1];
+}
+
+
+static u8 * hostapd_get_osen_ie(struct hostapd_data *hapd, u8 *pos, size_t len)
+{
+	const u8 *ie;
+
+	ie = hostapd_vendor_wpa_ie(hapd, OSEN_IE_VENDOR_TYPE);
+	if (!ie || 2U + ie[1] > len)
+		return pos;
+
+	os_memcpy(pos, ie, 2 + ie[1]);
+	return pos + 2 + ie[1];
 }
 
 
@@ -405,6 +468,7 @@
 
 	buflen += hostapd_mbo_ie_len(hapd);
 	buflen += hostapd_eid_owe_trans_len(hapd);
+	buflen += hostapd_eid_dpp_cc_len(hapd);
 
 	resp = os_zalloc(buflen);
 	if (resp == NULL)
@@ -455,14 +519,10 @@
 	/* Extended supported rates */
 	pos = hostapd_eid_ext_supp_rates(hapd, pos);
 
-	/* RSN, MDIE */
-	if (!(hapd->conf->wpa == WPA_PROTO_WPA ||
-	      (hapd->conf->osen && !hapd->conf->wpa)))
-		pos = hostapd_eid_wpa(hapd, pos, epos - pos);
-
+	pos = hostapd_get_rsne(hapd, pos, epos - pos);
 	pos = hostapd_eid_bss_load(hapd, pos, epos - pos);
-
 	pos = hostapd_eid_rm_enabled_capab(hapd, pos, epos - pos);
+	pos = hostapd_get_mde(hapd, pos, epos - pos);
 
 	/* eCSA IE */
 	csa_pos = hostapd_eid_ecsa(hapd, pos);
@@ -471,15 +531,8 @@
 	pos = csa_pos;
 
 	pos = hostapd_eid_supported_op_classes(hapd, pos);
-
-#ifdef CONFIG_IEEE80211N
-	/* Secondary Channel Offset element */
-	/* TODO: The standard doesn't specify a position for this element. */
-	pos = hostapd_eid_secondary_channel(hapd, pos);
-
 	pos = hostapd_eid_ht_capabilities(hapd, pos);
 	pos = hostapd_eid_ht_operation(hapd, pos);
-#endif /* CONFIG_IEEE80211N */
 
 	pos = hostapd_eid_ext_capab(hapd, pos);
 
@@ -509,13 +562,14 @@
 #endif /* CONFIG_IEEE80211AC */
 
 	pos = hostapd_eid_fils_indic(hapd, pos, 0);
+	pos = hostapd_get_rsnxe(hapd, pos, epos - pos);
 
 #ifdef CONFIG_IEEE80211AX
 	if (hapd->iconf->ieee80211ax) {
 		pos = hostapd_eid_he_capab(hapd, pos, IEEE80211_MODE_AP);
 		pos = hostapd_eid_he_operation(hapd, pos);
-		pos = hostapd_eid_he_mu_edca_parameter_set(hapd, pos);
 		pos = hostapd_eid_spatial_reuse(hapd, pos);
+		pos = hostapd_eid_he_mu_edca_parameter_set(hapd, pos);
 	}
 #endif /* CONFIG_IEEE80211AX */
 
@@ -524,10 +578,9 @@
 		pos = hostapd_eid_vendor_vht(hapd, pos);
 #endif /* CONFIG_IEEE80211AC */
 
-	/* WPA */
-	if (hapd->conf->wpa == WPA_PROTO_WPA ||
-	    (hapd->conf->osen && !hapd->conf->wpa))
-		pos = hostapd_eid_wpa(hapd, pos, epos - pos);
+	/* WPA / OSEN */
+	pos = hostapd_get_wpa_ie(hapd, pos, epos - pos);
+	pos = hostapd_get_osen_ie(hapd, pos, epos - pos);
 
 	/* Wi-Fi Alliance WMM */
 	pos = hostapd_eid_wmm(hapd, pos);
@@ -560,6 +613,7 @@
 
 	pos = hostapd_eid_mbo(hapd, pos, (u8 *) resp + buflen - pos);
 	pos = hostapd_eid_owe_trans(hapd, pos, (u8 *) resp + buflen - pos);
+	pos = hostapd_eid_dpp_cc(hapd, pos, (u8 *) resp + buflen - pos);
 
 	if (hapd->conf->vendor_elements) {
 		os_memcpy(pos, wpabuf_head(hapd->conf->vendor_elements),
@@ -581,7 +635,9 @@
 static enum ssid_match_result ssid_match(struct hostapd_data *hapd,
 					 const u8 *ssid, size_t ssid_len,
 					 const u8 *ssid_list,
-					 size_t ssid_list_len)
+					 size_t ssid_list_len,
+					 const u8 *short_ssid_list,
+					 size_t short_ssid_list_len)
 {
 	const u8 *pos, *end;
 	int wildcard = 0;
@@ -592,20 +648,30 @@
 	    os_memcmp(ssid, hapd->conf->ssid.ssid, ssid_len) == 0)
 		return EXACT_SSID_MATCH;
 
-	if (ssid_list == NULL)
-		return wildcard ? WILDCARD_SSID_MATCH : NO_SSID_MATCH;
+	if (ssid_list) {
+		pos = ssid_list;
+		end = ssid_list + ssid_list_len;
+		while (end - pos >= 2) {
+			if (2 + pos[1] > end - pos)
+				break;
+			if (pos[1] == 0)
+				wildcard = 1;
+			if (pos[1] == hapd->conf->ssid.ssid_len &&
+			    os_memcmp(pos + 2, hapd->conf->ssid.ssid,
+				      pos[1]) == 0)
+				return EXACT_SSID_MATCH;
+			pos += 2 + pos[1];
+		}
+	}
 
-	pos = ssid_list;
-	end = ssid_list + ssid_list_len;
-	while (end - pos >= 2) {
-		if (2 + pos[1] > end - pos)
-			break;
-		if (pos[1] == 0)
-			wildcard = 1;
-		if (pos[1] == hapd->conf->ssid.ssid_len &&
-		    os_memcmp(pos + 2, hapd->conf->ssid.ssid, pos[1]) == 0)
-			return EXACT_SSID_MATCH;
-		pos += 2 + pos[1];
+	if (short_ssid_list) {
+		pos = short_ssid_list;
+		end = short_ssid_list + short_ssid_list_len;
+		while (end - pos >= 4) {
+			if (hapd->conf->ssid.short_ssid == WPA_GET_LE32(pos))
+				return EXACT_SSID_MATCH;
+			pos += 4;
+		}
 	}
 
 	return wildcard ? WILDCARD_SSID_MATCH : NO_SSID_MATCH;
@@ -743,11 +809,7 @@
 	int ret;
 	u16 csa_offs[2];
 	size_t csa_offs_len;
-	u32 session_timeout, acct_interim_interval;
-	struct vlan_description vlan_id;
-	struct hostapd_sta_wpa_psk_short *psk = NULL;
-	char *identity = NULL;
-	char *radius_cui = NULL;
+	struct radius_sta rad_info;
 
 	if (len < IEEE80211_HDRLEN)
 		return;
@@ -756,10 +818,8 @@
 		sta_track_add(hapd->iface, mgmt->sa, ssi_signal);
 	ie_len = len - IEEE80211_HDRLEN;
 
-	ret = ieee802_11_allowed_address(hapd, mgmt->sa, (const u8 *) mgmt, len,
-					 &session_timeout,
-					 &acct_interim_interval, &vlan_id,
-					 &psk, &identity, &radius_cui, 1);
+	ret = hostapd_allowed_address(hapd, mgmt->sa, (const u8 *) mgmt, len,
+				      &rad_info, 1);
 	if (ret == HOSTAPD_ACL_REJECT) {
 		wpa_msg(hapd->msg_ctx, MSG_DEBUG,
 			"Ignore Probe Request frame from " MACSTR
@@ -838,7 +898,7 @@
 #endif /* CONFIG_P2P */
 
 	if (hapd->conf->ignore_broadcast_ssid && elems.ssid_len == 0 &&
-	    elems.ssid_list_len == 0) {
+	    elems.ssid_list_len == 0 && elems.short_ssid_list_len == 0) {
 		wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for "
 			   "broadcast SSID ignored", MAC2STR(mgmt->sa));
 		return;
@@ -870,7 +930,8 @@
 #endif /* CONFIG_TAXONOMY */
 
 	res = ssid_match(hapd, elems.ssid, elems.ssid_len,
-			 elems.ssid_list, elems.ssid_list_len);
+			 elems.ssid_list, elems.ssid_list_len,
+			 elems.short_ssid_list, elems.short_ssid_list_len);
 	if (res == NO_SSID_MATCH) {
 		if (!(mgmt->da[0] & 0x01)) {
 			wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
@@ -883,6 +944,12 @@
 		return;
 	}
 
+	if (hapd->conf->ignore_broadcast_ssid && res == WILDCARD_SSID_MATCH) {
+		wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for "
+			   "broadcast SSID ignored", MAC2STR(mgmt->sa));
+		return;
+	}
+
 #ifdef CONFIG_INTERWORKING
 	if (hapd->conf->interworking &&
 	    elems.interworking && elems.interworking_len >= 1) {
@@ -987,9 +1054,9 @@
 				hapd->cs_c_off_ecsa_proberesp;
 	}
 
-	ret = hostapd_drv_send_mlme_csa(hapd, resp, resp_len, noack,
-					csa_offs_len ? csa_offs : NULL,
-					csa_offs_len);
+	ret = hostapd_drv_send_mlme(hapd, resp, resp_len, noack,
+				    csa_offs_len ? csa_offs : NULL,
+				    csa_offs_len, 0);
 
 	if (ret < 0)
 		wpa_printf(MSG_INFO, "handle_probe_req: send failed");
@@ -1060,7 +1127,7 @@
 	size_t resp_len = 0;
 #ifdef NEED_AP_MLME
 	u16 capab_info;
-	u8 *pos, *tailpos, *csa_pos;
+	u8 *pos, *tailpos, *tailend, *csa_pos;
 
 #define BEACON_HEAD_BUF_SIZE 256
 #define BEACON_TAIL_BUF_SIZE 512
@@ -1099,6 +1166,7 @@
 
 	tail_len += hostapd_mbo_ie_len(hapd);
 	tail_len += hostapd_eid_owe_trans_len(hapd);
+	tail_len += hostapd_eid_dpp_cc_len(hapd);
 
 	tailpos = tail = os_malloc(tail_len);
 	if (head == NULL || tail == NULL) {
@@ -1107,6 +1175,7 @@
 		os_free(tail);
 		return -1;
 	}
+	tailend = tail + tail_len;
 
 	head->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
 					   WLAN_FC_STYPE_BEACON);
@@ -1147,8 +1216,7 @@
 
 	head_len = pos - (u8 *) head;
 
-	tailpos = hostapd_eid_country(hapd, tailpos,
-				      tail + BEACON_TAIL_BUF_SIZE - tailpos);
+	tailpos = hostapd_eid_country(hapd, tailpos, tailend - tailpos);
 
 	/* Power Constraint element */
 	tailpos = hostapd_eid_pwr_constraint(hapd, tailpos);
@@ -1165,19 +1233,11 @@
 	/* Extended supported rates */
 	tailpos = hostapd_eid_ext_supp_rates(hapd, tailpos);
 
-	/* RSN, MDIE */
-	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);
-
+	tailpos = hostapd_get_rsne(hapd, tailpos, tailend - tailpos);
+	tailpos = hostapd_eid_bss_load(hapd, tailpos, tailend - tailpos);
 	tailpos = hostapd_eid_rm_enabled_capab(hapd, tailpos,
-					       tail + BEACON_TAIL_BUF_SIZE -
-					       tailpos);
-
-	tailpos = hostapd_eid_bss_load(hapd, tailpos,
-				       tail + BEACON_TAIL_BUF_SIZE - tailpos);
+					       tailend - tailpos);
+	tailpos = hostapd_get_mde(hapd, tailpos, tailend - tailpos);
 
 	/* eCSA IE */
 	csa_pos = hostapd_eid_ecsa(hapd, tailpos);
@@ -1186,15 +1246,8 @@
 	tailpos = csa_pos;
 
 	tailpos = hostapd_eid_supported_op_classes(hapd, tailpos);
-
-#ifdef CONFIG_IEEE80211N
-	/* Secondary Channel Offset element */
-	/* TODO: The standard doesn't specify a position for this element. */
-	tailpos = hostapd_eid_secondary_channel(hapd, tailpos);
-
 	tailpos = hostapd_eid_ht_capabilities(hapd, tailpos);
 	tailpos = hostapd_eid_ht_operation(hapd, tailpos);
-#endif /* CONFIG_IEEE80211N */
 
 	tailpos = hostapd_eid_ext_capab(hapd, tailpos);
 
@@ -1226,14 +1279,15 @@
 #endif /* CONFIG_IEEE80211AC */
 
 	tailpos = hostapd_eid_fils_indic(hapd, tailpos, 0);
+	tailpos = hostapd_get_rsnxe(hapd, tailpos, tailend - tailpos);
 
 #ifdef CONFIG_IEEE80211AX
 	if (hapd->iconf->ieee80211ax) {
 		tailpos = hostapd_eid_he_capab(hapd, tailpos,
 					       IEEE80211_MODE_AP);
 		tailpos = hostapd_eid_he_operation(hapd, tailpos);
-		tailpos = hostapd_eid_he_mu_edca_parameter_set(hapd, tailpos);
 		tailpos = hostapd_eid_spatial_reuse(hapd, tailpos);
+		tailpos = hostapd_eid_he_mu_edca_parameter_set(hapd, tailpos);
 	}
 #endif /* CONFIG_IEEE80211AX */
 
@@ -1242,12 +1296,9 @@
 		tailpos = hostapd_eid_vendor_vht(hapd, tailpos);
 #endif /* CONFIG_IEEE80211AC */
 
-	/* 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);
+	/* WPA / OSEN */
+	tailpos = hostapd_get_wpa_ie(hapd, tailpos, tailend - tailpos);
+	tailpos = hostapd_get_osen_ie(hapd, tailpos, tailend - tailpos);
 
 	/* Wi-Fi Alliance WMM */
 	tailpos = hostapd_eid_wmm(hapd, tailpos);
@@ -1280,6 +1331,7 @@
 	tailpos = hostapd_eid_mbo(hapd, tailpos, tail + tail_len - tailpos);
 	tailpos = hostapd_eid_owe_trans(hapd, tailpos,
 					tail + tail_len - tailpos);
+	tailpos = hostapd_eid_dpp_cc(hapd, tailpos, tail + tail_len - tailpos);
 
 	if (hapd->conf->vendor_elements) {
 		os_memcpy(tailpos, wpabuf_head(hapd->conf->vendor_elements),
@@ -1318,10 +1370,13 @@
 	params->key_mgmt_suites = hapd->conf->wpa_key_mgmt;
 	params->auth_algs = hapd->conf->auth_algs;
 	params->wpa_version = hapd->conf->wpa;
-	params->privacy = hapd->conf->ssid.wep.keys_set || hapd->conf->wpa ||
+	params->privacy = hapd->conf->wpa;
+#ifdef CONFIG_WEP
+	params->privacy |= hapd->conf->ssid.wep.keys_set ||
 		(hapd->conf->ieee802_1x &&
 		 (hapd->conf->default_wep_key_len ||
 		  hapd->conf->individual_wep_key_len));
+#endif /* CONFIG_WEP */
 	switch (hapd->conf->ignore_broadcast_ssid) {
 	case 0:
 		params->hide_ssid = NO_SSID_HIDING;
@@ -1334,7 +1389,6 @@
 		break;
 	}
 	params->isolate = hapd->conf->isolate;
-	params->smps_mode = hapd->iconf->ht_capab & HT_CAP_INFO_SMPS_MASK;
 #ifdef NEED_AP_MLME
 	params->cts_protect = !!(ieee802_11_erp_info(hapd) &
 				ERP_INFO_USE_PROTECTION);
@@ -1430,6 +1484,13 @@
 		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;
+	params.he_bss_color_disabled =
+		hapd->iface->conf->he_op.he_bss_color_disabled;
+	params.he_bss_color_partial =
+		hapd->iface->conf->he_op.he_bss_color_partial;
+	params.he_bss_color = hapd->iface->conf->he_op.he_bss_color;
+	params.twt_responder = hostapd_get_he_twt_responder(hapd,
+							    IEEE80211_MODE_AP);
 #endif /* CONFIG_IEEE80211AX */
 	hapd->reenable_beacon = 0;
 
diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
index 9fd1b81..ef53a82 100644
--- a/src/ap/ctrl_iface_ap.c
+++ b/src/ap/ctrl_iface_ap.c
@@ -345,7 +345,6 @@
 	}
 #endif /* CONFIG_IEEE80211AC */
 
-#ifdef CONFIG_IEEE80211N
 	if ((sta->flags & WLAN_STA_HT) && sta->ht_capabilities) {
 		res = os_snprintf(buf + len, buflen - len,
 				  "ht_caps_info=0x%04x\n",
@@ -354,7 +353,6 @@
 		if (!os_snprintf_error(buflen - len, res))
 			len += res;
 	}
-#endif /* CONFIG_IEEE80211N */
 
 	if (sta->ext_capability &&
 	    buflen - len > (unsigned) (11 + 2 * sta->ext_capability[0])) {
@@ -462,9 +460,6 @@
 	int ret;
 	u8 *pos;
 
-	if (!hapd->drv_priv || !hapd->driver->send_frame)
-		return -1;
-
 	mgmt = os_zalloc(sizeof(*mgmt) + 100);
 	if (mgmt == NULL)
 		return -1;
@@ -498,8 +493,8 @@
 	pos += 2;
 	*pos++ = minor_reason_code;
 
-	ret = hapd->driver->send_frame(hapd->drv_priv, (u8 *) mgmt,
-				       pos - (u8 *) mgmt, 1);
+	ret = hostapd_drv_send_mlme(hapd, mgmt, pos - (u8 *) mgmt, 0, NULL, 0,
+				    0);
 	os_free(mgmt);
 
 	return ret < 0 ? -1 : 0;
@@ -529,8 +524,7 @@
 	if (pos) {
 		struct ieee80211_mgmt mgmt;
 		int encrypt;
-		if (!hapd->drv_priv || !hapd->driver->send_frame)
-			return -1;
+
 		pos += 6;
 		encrypt = atoi(pos);
 		os_memset(&mgmt, 0, sizeof(mgmt));
@@ -540,10 +534,10 @@
 		os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
 		os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
 		mgmt.u.deauth.reason_code = host_to_le16(reason);
-		if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt,
-					     IEEE80211_HDRLEN +
-					     sizeof(mgmt.u.deauth),
-					     encrypt) < 0)
+		if (hostapd_drv_send_mlme(hapd, (u8 *) &mgmt,
+					  IEEE80211_HDRLEN +
+					  sizeof(mgmt.u.deauth),
+					  0, NULL, 0, !encrypt) < 0)
 			return -1;
 		return 0;
 	}
@@ -592,8 +586,7 @@
 	if (pos) {
 		struct ieee80211_mgmt mgmt;
 		int encrypt;
-		if (!hapd->drv_priv || !hapd->driver->send_frame)
-			return -1;
+
 		pos += 6;
 		encrypt = atoi(pos);
 		os_memset(&mgmt, 0, sizeof(mgmt));
@@ -603,10 +596,10 @@
 		os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
 		os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
 		mgmt.u.disassoc.reason_code = host_to_le16(reason);
-		if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt,
-					     IEEE80211_HDRLEN +
-					     sizeof(mgmt.u.deauth),
-					     encrypt) < 0)
+		if (hostapd_drv_send_mlme(hapd, (u8 *) &mgmt,
+					  IEEE80211_HDRLEN +
+					  sizeof(mgmt.u.deauth),
+					  0, NULL, 0, !encrypt) < 0)
 			return -1;
 		return 0;
 	}
diff --git a/src/ap/dfs.c b/src/ap/dfs.c
index f70ecc9..3c078b9 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -144,30 +144,44 @@
 	int i;
 	u32 bw = num_chan_to_bw(num_chans);
 
-	if (first_chan_idx + num_chans > mode->num_channels)
+	if (first_chan_idx + num_chans > mode->num_channels) {
+		wpa_printf(MSG_DEBUG,
+			   "DFS: some channels in range not defined");
 		return 0;
+	}
 
 	first_chan = &mode->channels[first_chan_idx];
 
 	/* hostapd DFS implementation assumes the first channel as primary.
 	 * If it's not allowed to use the first channel as primary, decline the
 	 * whole channel range. */
-	if (!chan_pri_allowed(first_chan))
+	if (!chan_pri_allowed(first_chan)) {
+		wpa_printf(MSG_DEBUG, "DFS: primary chanenl not allowed");
 		return 0;
+	}
 
 	for (i = 0; i < num_chans; i++) {
 		chan = dfs_get_chan_data(mode, first_chan->freq + i * 20,
 					 first_chan_idx);
-		if (!chan)
+		if (!chan) {
+			wpa_printf(MSG_DEBUG, "DFS: no channel data for %d",
+				   first_chan->freq + i * 20);
 			return 0;
+		}
 
 		/* HT 40 MHz secondary channel availability checked only for
 		 * primary channel */
-		if (!chan_bw_allowed(chan, bw, 1, !i))
+		if (!chan_bw_allowed(chan, bw, 1, !i)) {
+			wpa_printf(MSG_DEBUG, "DFS: bw now allowed for %d",
+				   first_chan->freq + i * 20);
 			return 0;
+		}
 
-		if (!dfs_channel_available(chan, skip_radar))
+		if (!dfs_channel_available(chan, skip_radar)) {
+			wpa_printf(MSG_DEBUG, "DFS: channel not available %d",
+				   first_chan->freq + i * 20);
 			return 0;
+		}
 	}
 
 	return 1;
@@ -210,22 +224,36 @@
 		if (iface->conf->ieee80211n &&
 		    iface->conf->secondary_channel &&
 		    (!dfs_is_chan_allowed(chan, n_chans) ||
-		     !(chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40P)))
+		     !(chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40P))) {
+			wpa_printf(MSG_DEBUG,
+				   "DFS: channel %d (%d) is incompatible",
+				   chan->freq, chan->chan);
 			continue;
+		}
 
 		/* Skip incompatible chandefs */
-		if (!dfs_chan_range_available(mode, i, n_chans, skip_radar))
+		if (!dfs_chan_range_available(mode, i, n_chans, skip_radar)) {
+			wpa_printf(MSG_DEBUG,
+				   "DFS: range not available for %d (%d)",
+				   chan->freq, chan->chan);
 			continue;
+		}
 
-		if (!is_in_chanlist(iface, chan))
+		if (!is_in_chanlist(iface, chan)) {
+			wpa_printf(MSG_DEBUG,
+				   "DFS: channel %d (%d) not in chanlist",
+				   chan->freq, chan->chan);
 			continue;
+		}
 
 		if (ret_chan && idx == channel_idx) {
-			wpa_printf(MSG_DEBUG, "Selected ch. #%d", chan->chan);
+			wpa_printf(MSG_DEBUG, "Selected channel %d (%d)",
+				   chan->freq, chan->chan);
 			*ret_chan = chan;
 			return idx;
 		}
-		wpa_printf(MSG_DEBUG, "Adding channel: %d", chan->chan);
+		wpa_printf(MSG_DEBUG, "Adding channel %d (%d)",
+			   chan->freq, chan->chan);
 		channel_idx++;
 	}
 	return channel_idx;
@@ -235,6 +263,7 @@
 static void dfs_adjust_center_freq(struct hostapd_iface *iface,
 				   struct hostapd_channel_data *chan,
 				   int secondary_channel,
+				   int sec_chan_idx_80p80,
 				   u8 *oper_centr_freq_seg0_idx,
 				   u8 *oper_centr_freq_seg1_idx)
 {
@@ -261,8 +290,14 @@
 	case CHANWIDTH_160MHZ:
 		*oper_centr_freq_seg0_idx = chan->chan + 14;
 		break;
+	case CHANWIDTH_80P80MHZ:
+		*oper_centr_freq_seg0_idx = chan->chan + 6;
+		*oper_centr_freq_seg1_idx = sec_chan_idx_80p80 + 6;
+		break;
+
 	default:
-		wpa_printf(MSG_INFO, "DFS only VHT20/40/80/160 is supported now");
+		wpa_printf(MSG_INFO,
+			   "DFS: Unsupported channel width configuration");
 		*oper_centr_freq_seg0_idx = 0;
 		break;
 	}
@@ -441,8 +476,11 @@
 {
 	struct hostapd_hw_modes *mode;
 	struct hostapd_channel_data *chan = NULL;
+	struct hostapd_channel_data *chan2 = NULL;
 	int num_available_chandefs;
-	int chan_idx;
+	int chan_idx, chan_idx2;
+	int sec_chan_idx_80p80 = -1;
+	int i;
 	u32 _rand;
 
 	wpa_printf(MSG_DEBUG, "DFS: Selecting random channel");
@@ -459,6 +497,8 @@
 
 	/* Get the count first */
 	num_available_chandefs = dfs_find_channel(iface, NULL, 0, skip_radar);
+	wpa_printf(MSG_DEBUG, "DFS: num_available_chandefs=%d",
+		   num_available_chandefs);
 	if (num_available_chandefs == 0)
 		return NULL;
 
@@ -466,6 +506,12 @@
 		return NULL;
 	chan_idx = _rand % num_available_chandefs;
 	dfs_find_channel(iface, &chan, chan_idx, skip_radar);
+	if (!chan) {
+		wpa_printf(MSG_DEBUG, "DFS: no random channel found");
+		return NULL;
+	}
+	wpa_printf(MSG_DEBUG, "DFS: got random channel %d (%d)",
+		   chan->freq, chan->chan);
 
 	/* dfs_find_channel() calculations assume HT40+ */
 	if (iface->conf->secondary_channel)
@@ -473,8 +519,45 @@
 	else
 		*secondary_channel = 0;
 
+	/* Get secondary channel for HT80P80 */
+	if (hostapd_get_oper_chwidth(iface->conf) == CHANWIDTH_80P80MHZ) {
+		if (num_available_chandefs <= 1) {
+			wpa_printf(MSG_ERROR,
+				   "only 1 valid chan, can't support 80+80");
+			return NULL;
+		}
+
+		/*
+		 * Loop all channels except channel1 to find a valid channel2
+		 * that is not adjacent to channel1.
+		 */
+		for (i = 0; i < num_available_chandefs - 1; i++) {
+			/* start from chan_idx + 1, end when chan_idx - 1 */
+			chan_idx2 = (chan_idx + 1 + i) % num_available_chandefs;
+			dfs_find_channel(iface, &chan2, chan_idx2, skip_radar);
+			if (chan2 && abs(chan2->chan - chan->chan) > 12) {
+				/* two channels are not adjacent */
+				sec_chan_idx_80p80 = chan2->chan;
+				wpa_printf(MSG_DEBUG,
+					   "DFS: got second chan: %d (%d)",
+					   chan2->freq, chan2->chan);
+				break;
+			}
+		}
+
+		/* Check if we got a valid secondary channel which is not
+		 * adjacent to the first channel.
+		 */
+		if (sec_chan_idx_80p80 == -1) {
+			wpa_printf(MSG_INFO,
+				   "DFS: failed to get chan2 for 80+80");
+			return NULL;
+		}
+	}
+
 	dfs_adjust_center_freq(iface, chan,
 			       *secondary_channel,
+			       sec_chan_idx_80p80,
 			       oper_centr_freq_seg0_idx,
 			       oper_centr_freq_seg1_idx);
 
@@ -773,7 +856,7 @@
 }
 
 
-static int hostapd_config_dfs_chan_available(struct hostapd_iface *iface)
+int hostapd_is_dfs_chan_available(struct hostapd_iface *iface)
 {
 	int n_chans, n_chans1, start_chan_idx, start_chan_idx1;
 
@@ -821,7 +904,7 @@
 			 * another radio.
 			 */
 			if (iface->state != HAPD_IFACE_ENABLED &&
-			    hostapd_config_dfs_chan_available(iface)) {
+			    hostapd_is_dfs_chan_available(iface)) {
 				hostapd_setup_interface_complete(iface, 0);
 				iface->cac_started = 0;
 			}
@@ -851,6 +934,41 @@
 }
 
 
+static struct hostapd_channel_data *
+dfs_downgrade_bandwidth(struct hostapd_iface *iface, int *secondary_channel,
+			u8 *oper_centr_freq_seg0_idx,
+			u8 *oper_centr_freq_seg1_idx, int *skip_radar)
+{
+	struct hostapd_channel_data *channel;
+
+	for (;;) {
+		channel = dfs_get_valid_channel(iface, secondary_channel,
+						oper_centr_freq_seg0_idx,
+						oper_centr_freq_seg1_idx,
+						*skip_radar);
+		if (channel) {
+			wpa_printf(MSG_DEBUG, "DFS: Selected channel: %d",
+				   channel->chan);
+			return channel;
+		}
+
+		if (*skip_radar) {
+			*skip_radar = 0;
+		} else {
+			if (iface->conf->vht_oper_chwidth == CHANWIDTH_USE_HT)
+				break;
+			*skip_radar = 1;
+			iface->conf->vht_oper_chwidth--;
+		}
+	}
+
+	wpa_printf(MSG_INFO,
+		   "%s: no DFS channels left, waiting for NOP to finish",
+		   __func__);
+	return NULL;
+}
+
+
 static int hostapd_dfs_start_channel_switch_cac(struct hostapd_iface *iface)
 {
 	struct hostapd_channel_data *channel;
@@ -868,8 +986,14 @@
 					skip_radar);
 
 	if (!channel) {
-		wpa_printf(MSG_ERROR, "No valid channel available");
-		return err;
+		channel = dfs_downgrade_bandwidth(iface, &secondary_channel,
+						  &oper_centr_freq_seg0_idx,
+						  &oper_centr_freq_seg1_idx,
+						  &skip_radar);
+		if (!channel) {
+			wpa_printf(MSG_ERROR, "No valid channel available");
+			return err;
+		}
 	}
 
 	wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d",
@@ -898,11 +1022,13 @@
 	int secondary_channel;
 	u8 oper_centr_freq_seg0_idx;
 	u8 oper_centr_freq_seg1_idx;
+	u8 new_vht_oper_chwidth;
 	int skip_radar = 1;
 	struct csa_settings csa_settings;
 	unsigned int i;
 	int err = 1;
 	struct hostapd_hw_modes *cmode = iface->current_mode;
+	u8 current_vht_oper_chwidth = iface->conf->vht_oper_chwidth;
 
 	wpa_printf(MSG_DEBUG, "%s called (CAC active: %s, CSA active: %s)",
 		   __func__, iface->cac_started ? "yes" : "no",
@@ -936,28 +1062,25 @@
 		 * requires to perform a CAC first.
 		 */
 		skip_radar = 0;
-		channel = dfs_get_valid_channel(iface, &secondary_channel,
-						&oper_centr_freq_seg0_idx,
-						&oper_centr_freq_seg1_idx,
-						skip_radar);
-		if (!channel) {
-			wpa_printf(MSG_INFO,
-				   "%s: no DFS channels left, waiting for NOP to finish",
-				   __func__);
+		channel = dfs_downgrade_bandwidth(iface, &secondary_channel,
+						  &oper_centr_freq_seg0_idx,
+						  &oper_centr_freq_seg1_idx,
+						  &skip_radar);
+		if (!channel)
 			return err;
+		if (!skip_radar) {
+			iface->freq = channel->freq;
+			iface->conf->channel = channel->chan;
+			iface->conf->secondary_channel = secondary_channel;
+			hostapd_set_oper_centr_freq_seg0_idx(
+				iface->conf, oper_centr_freq_seg0_idx);
+			hostapd_set_oper_centr_freq_seg1_idx(
+				iface->conf, oper_centr_freq_seg1_idx);
+
+			hostapd_disable_iface(iface);
+			hostapd_enable_iface(iface);
+			return 0;
 		}
-
-		iface->freq = channel->freq;
-		iface->conf->channel = channel->chan;
-		iface->conf->secondary_channel = secondary_channel;
-		hostapd_set_oper_centr_freq_seg0_idx(iface->conf,
-						     oper_centr_freq_seg0_idx);
-		hostapd_set_oper_centr_freq_seg1_idx(iface->conf,
-						     oper_centr_freq_seg1_idx);
-
-		hostapd_disable_iface(iface);
-		hostapd_enable_iface(iface);
-		return 0;
 	}
 
 	wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d",
@@ -966,6 +1089,9 @@
 		"freq=%d chan=%d sec_chan=%d", channel->freq,
 		channel->chan, secondary_channel);
 
+	new_vht_oper_chwidth = iface->conf->vht_oper_chwidth;
+	iface->conf->vht_oper_chwidth = current_vht_oper_chwidth;
+
 	/* Setup CSA request */
 	os_memset(&csa_settings, 0, sizeof(csa_settings));
 	csa_settings.cs_count = 5;
@@ -980,7 +1106,7 @@
 				      iface->conf->ieee80211ac,
 				      iface->conf->ieee80211ax,
 				      secondary_channel,
-				      hostapd_get_oper_chwidth(iface->conf),
+				      new_vht_oper_chwidth,
 				      oper_centr_freq_seg0_idx,
 				      oper_centr_freq_seg1_idx,
 				      cmode->vht_capab,
@@ -1004,6 +1130,7 @@
 		iface->freq = channel->freq;
 		iface->conf->channel = channel->chan;
 		iface->conf->secondary_channel = secondary_channel;
+		iface->conf->vht_oper_chwidth = new_vht_oper_chwidth;
 		hostapd_set_oper_centr_freq_seg0_idx(iface->conf,
 						     oper_centr_freq_seg0_idx);
 		hostapd_set_oper_centr_freq_seg1_idx(iface->conf,
@@ -1040,8 +1167,10 @@
 		return 0;
 
 	/* mark radar frequency as invalid */
-	set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width,
-		      cf1, cf2, HOSTAPD_CHAN_DFS_UNAVAILABLE);
+	res = set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width,
+			    cf1, cf2, HOSTAPD_CHAN_DFS_UNAVAILABLE);
+	if (!res)
+		return 0;
 
 	/* Skip if reported radar event not overlapped our channels */
 	res = dfs_are_channels_overlapped(iface, freq, chan_width, cf1, cf2);
@@ -1161,3 +1290,56 @@
 		   __func__, iface->freq);
 	return 2;
 }
+
+
+int hostapd_is_dfs_overlap(struct hostapd_iface *iface, enum chan_width width,
+			   int center_freq)
+{
+	struct hostapd_channel_data *chan;
+	struct hostapd_hw_modes *mode = iface->current_mode;
+	int half_width;
+	int res = 0;
+	int i;
+
+	if (!iface->conf->ieee80211h || !mode ||
+	    mode->mode != HOSTAPD_MODE_IEEE80211A)
+		return 0;
+
+	switch (width) {
+	case CHAN_WIDTH_20_NOHT:
+	case CHAN_WIDTH_20:
+		half_width = 10;
+		break;
+	case CHAN_WIDTH_40:
+		half_width = 20;
+		break;
+	case CHAN_WIDTH_80:
+	case CHAN_WIDTH_80P80:
+		half_width = 40;
+		break;
+	case CHAN_WIDTH_160:
+		half_width = 80;
+		break;
+	default:
+		wpa_printf(MSG_WARNING, "DFS chanwidth %d not supported",
+			   width);
+		return 0;
+	}
+
+	for (i = 0; i < mode->num_channels; i++) {
+		chan = &mode->channels[i];
+
+		if (!(chan->flag & HOSTAPD_CHAN_RADAR))
+			continue;
+
+		if (center_freq - chan->freq < half_width &&
+		    chan->freq - center_freq < half_width)
+			res++;
+	}
+
+	wpa_printf(MSG_DEBUG, "DFS: (%d, %d): in range: %s",
+		   center_freq - half_width, center_freq + half_width,
+		   res ? "yes" : "no");
+
+	return res;
+}
diff --git a/src/ap/dfs.h b/src/ap/dfs.h
index f0fa6f6..606c1b3 100644
--- a/src/ap/dfs.h
+++ b/src/ap/dfs.h
@@ -25,9 +25,12 @@
 			     int ht_enabled,
 			     int chan_offset, int chan_width, int cf1, int cf2);
 int hostapd_is_dfs_required(struct hostapd_iface *iface);
+int hostapd_is_dfs_chan_available(struct hostapd_iface *iface);
 int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq,
 			  int ht_enabled, int chan_offset, int chan_width,
 			  int cf1, int cf2);
 int hostapd_handle_dfs_offload(struct hostapd_iface *iface);
+int hostapd_is_dfs_overlap(struct hostapd_iface *iface, enum chan_width width,
+			   int center_freq);
 
 #endif /* DFS_H */
diff --git a/src/ap/dhcp_snoop.c b/src/ap/dhcp_snoop.c
index ed37fc8..edc77da 100644
--- a/src/ap/dhcp_snoop.c
+++ b/src/ap/dhcp_snoop.c
@@ -39,22 +39,22 @@
 	const u8 *end, *pos;
 	int res, msgtype = 0, prefixlen = 32;
 	u32 subnet_mask = 0;
-	u16 tot_len;
+	u16 ip_len;
 
 	exten_len = len - ETH_HLEN - (sizeof(*b) - sizeof(b->exten));
 	if (exten_len < 4)
 		return;
 
 	b = (const struct bootp_pkt *) &buf[ETH_HLEN];
-	tot_len = ntohs(b->iph.tot_len);
-	if (tot_len > (unsigned int) (len - ETH_HLEN))
+	ip_len = ntohs(b->iph.ip_len);
+	if (ip_len > (unsigned int) (len - ETH_HLEN))
 		return;
 
 	if (WPA_GET_BE32(b->exten) != DHCP_MAGIC)
 		return;
 
 	/* Parse DHCP options */
-	end = (const u8 *) b + tot_len;
+	end = (const u8 *) b + ip_len;
 	pos = &b->exten[4];
 	while (pos < end && *pos != DHCP_OPT_END) {
 		const u8 *opt = pos++;
diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c
index 1a3a815..c86f01b 100644
--- a/src/ap/dpp_hostapd.c
+++ b/src/ap/dpp_hostapd.c
@@ -1,7 +1,7 @@
 /*
  * hostapd / DPP integration
  * Copyright (c) 2017, Qualcomm Atheros, Inc.
- * Copyright (c) 2018-2019, The Linux Foundation
+ * Copyright (c) 2018-2020, The Linux Foundation
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -81,6 +81,71 @@
 }
 
 
+int hostapd_dpp_nfc_handover_req(struct hostapd_data *hapd, const char *cmd)
+{
+	const char *pos;
+	struct dpp_bootstrap_info *peer_bi, *own_bi;
+
+	pos = os_strstr(cmd, " own=");
+	if (!pos)
+		return -1;
+	pos += 5;
+	own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
+	if (!own_bi)
+		return -1;
+
+	pos = os_strstr(cmd, " uri=");
+	if (!pos)
+		return -1;
+	pos += 5;
+	peer_bi = dpp_add_nfc_uri(hapd->iface->interfaces->dpp, pos);
+	if (!peer_bi) {
+		wpa_printf(MSG_INFO,
+			   "DPP: Failed to parse URI from NFC Handover Request");
+		return -1;
+	}
+
+	if (dpp_nfc_update_bi(own_bi, peer_bi) < 0)
+		return -1;
+
+	return peer_bi->id;
+}
+
+
+int hostapd_dpp_nfc_handover_sel(struct hostapd_data *hapd, const char *cmd)
+{
+	const char *pos;
+	struct dpp_bootstrap_info *peer_bi, *own_bi;
+
+	pos = os_strstr(cmd, " own=");
+	if (!pos)
+		return -1;
+	pos += 5;
+	own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
+	if (!own_bi)
+		return -1;
+
+	pos = os_strstr(cmd, " uri=");
+	if (!pos)
+		return -1;
+	pos += 5;
+	peer_bi = dpp_add_nfc_uri(hapd->iface->interfaces->dpp, pos);
+	if (!peer_bi) {
+		wpa_printf(MSG_INFO,
+			   "DPP: Failed to parse URI from NFC Handover Select");
+		return -1;
+	}
+
+	if (peer_bi->curve != own_bi->curve) {
+		wpa_printf(MSG_INFO,
+			   "DPP: Peer (NFC Handover Selector) used different curve");
+		return -1;
+	}
+
+	return peer_bi->id;
+}
+
+
 static void hostapd_dpp_auth_resp_retry_timeout(void *eloop_ctx,
 						void *timeout_ctx)
 {
@@ -478,15 +543,15 @@
 		dpp_auth_deinit(hapd->dpp_auth);
 	}
 
-	hapd->dpp_auth = dpp_auth_init(hapd->msg_ctx, peer_bi, own_bi,
+	hapd->dpp_auth = dpp_auth_init(hapd->iface->interfaces->dpp,
+				       hapd->msg_ctx, peer_bi, own_bi,
 				       allowed_roles, neg_freq,
 				       hapd->iface->hw_features,
 				       hapd->iface->num_hw_features);
 	if (!hapd->dpp_auth)
 		goto fail;
 	hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth);
-	if (dpp_set_configurator(hapd->iface->interfaces->dpp, hapd->msg_ctx,
-				 hapd->dpp_auth, cmd) < 0) {
+	if (dpp_set_configurator(hapd->dpp_auth, cmd) < 0) {
 		dpp_auth_deinit(hapd->dpp_auth);
 		hapd->dpp_auth = NULL;
 		goto fail;
@@ -598,7 +663,8 @@
 	}
 
 	hapd->dpp_auth_ok_on_ack = 0;
-	hapd->dpp_auth = dpp_auth_req_rx(hapd->msg_ctx, hapd->dpp_allowed_roles,
+	hapd->dpp_auth = dpp_auth_req_rx(hapd->iface->interfaces->dpp,
+					 hapd->msg_ctx, hapd->dpp_allowed_roles,
 					 hapd->dpp_qr_mutual,
 					 peer_bi, own_bi, freq, hdr, buf, len);
 	if (!hapd->dpp_auth) {
@@ -606,8 +672,7 @@
 		return;
 	}
 	hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth);
-	if (dpp_set_configurator(hapd->iface->interfaces->dpp, hapd->msg_ctx,
-				 hapd->dpp_auth,
+	if (dpp_set_configurator(hapd->dpp_auth,
 				 hapd->dpp_configurator_params) < 0) {
 		dpp_auth_deinit(hapd->dpp_auth);
 		hapd->dpp_auth = NULL;
@@ -643,7 +708,8 @@
 		 * message. */
 		wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
 			conf->connector);
-	} else if (conf->passphrase[0]) {
+	}
+	if (conf->passphrase[0]) {
 		char hex[64 * 2 + 1];
 
 		wpa_snprintf_hex(hex, sizeof(hex),
@@ -697,6 +763,33 @@
 }
 
 
+static int hostapd_dpp_handle_key_pkg(struct hostapd_data *hapd,
+				      struct dpp_asymmetric_key *key)
+{
+#ifdef CONFIG_DPP2
+	int res;
+
+	if (!key)
+		return 0;
+
+	wpa_printf(MSG_DEBUG, "DPP: Received Configurator backup");
+	wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
+
+	while (key) {
+		res = dpp_configurator_from_backup(
+			hapd->iface->interfaces->dpp, key);
+		if (res < 0)
+			return -1;
+		wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFIGURATOR_ID "%d",
+			res);
+		key = key->next;
+	}
+#endif /* CONFIG_DPP2 */
+
+	return 0;
+}
+
+
 static void hostapd_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
 				    enum gas_query_ap_result result,
 				    const struct wpabuf *adv_proto,
@@ -741,6 +834,9 @@
 	}
 
 	hostapd_dpp_handle_config_obj(hapd, auth, &auth->conf_obj[0]);
+	if (hostapd_dpp_handle_key_pkg(hapd, auth->conf_key_pkg) < 0)
+		goto fail;
+
 	status = DPP_STATUS_OK;
 #ifdef CONFIG_TESTING_OPTIONS
 	if (dpp_test == DPP_TEST_REJECT_CONFIG) {
@@ -1037,6 +1133,70 @@
 }
 
 
+static void
+hostapd_dpp_rx_presence_announcement(struct hostapd_data *hapd, const u8 *src,
+				     const u8 *hdr, const u8 *buf, size_t len,
+				     unsigned int freq)
+{
+	const u8 *r_bootstrap;
+	u16 r_bootstrap_len;
+	struct dpp_bootstrap_info *peer_bi;
+	struct dpp_authentication *auth;
+
+	wpa_printf(MSG_DEBUG, "DPP: Presence Announcement from " MACSTR,
+		   MAC2STR(src));
+
+	r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
+				   &r_bootstrap_len);
+	if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
+		wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
+			"Missing or invalid required Responder Bootstrapping Key Hash attribute");
+		return;
+	}
+	wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
+		    r_bootstrap, r_bootstrap_len);
+	peer_bi = dpp_bootstrap_find_chirp(hapd->iface->interfaces->dpp,
+					   r_bootstrap);
+	if (!peer_bi) {
+		if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
+					src, hdr, buf, len, freq, NULL,
+					r_bootstrap) == 0)
+			return;
+		wpa_printf(MSG_DEBUG,
+			   "DPP: No matching bootstrapping information found");
+		return;
+	}
+
+	if (hapd->dpp_auth) {
+		wpa_printf(MSG_DEBUG,
+			   "DPP: Ignore Presence Announcement during ongoing Authentication");
+		return;
+	}
+
+	auth = dpp_auth_init(hapd->iface->interfaces->dpp, hapd->msg_ctx,
+			     peer_bi, NULL, DPP_CAPAB_CONFIGURATOR, freq, NULL,
+			     0);
+	if (!auth)
+		return;
+	hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth);
+	if (dpp_set_configurator(hapd->dpp_auth,
+				 hapd->dpp_configurator_params) < 0) {
+		dpp_auth_deinit(auth);
+		return;
+	}
+
+	auth->neg_freq = freq;
+
+	if (!is_zero_ether_addr(peer_bi->mac_addr))
+		os_memcpy(auth->peer_mac_addr, peer_bi->mac_addr, ETH_ALEN);
+
+	hapd->dpp_auth = auth;
+	if (hostapd_dpp_auth_init_next(hapd) < 0) {
+		dpp_auth_deinit(hapd->dpp_auth);
+		hapd->dpp_auth = NULL;
+	}
+}
+
 #endif /* CONFIG_DPP2 */
 
 
@@ -1486,6 +1646,10 @@
 	case DPP_PA_CONNECTION_STATUS_RESULT:
 		hostapd_dpp_rx_conn_status_result(hapd, src, hdr, buf, len);
 		break;
+	case DPP_PA_PRESENCE_ANNOUNCEMENT:
+		hostapd_dpp_rx_presence_announcement(hapd, src, hdr, buf, len,
+						     freq);
+		break;
 #endif /* CONFIG_DPP2 */
 	default:
 		wpa_printf(MSG_DEBUG,
@@ -1580,14 +1744,13 @@
 	int ret = -1;
 	char *curve = NULL;
 
-	auth = os_zalloc(sizeof(*auth));
+	auth = dpp_alloc_auth(hapd->iface->interfaces->dpp, hapd->msg_ctx);
 	if (!auth)
 		return -1;
 
 	curve = get_param(cmd, " curve=");
 	hostapd_dpp_set_testing_options(hapd, auth);
-	if (dpp_set_configurator(hapd->iface->interfaces->dpp, hapd->msg_ctx,
-				 auth, cmd) == 0 &&
+	if (dpp_set_configurator(auth, cmd) == 0 &&
 	    dpp_configurator_own_config(auth, curve, 1) == 0) {
 		hostapd_dpp_handle_config_obj(hapd, auth, &auth->conf_obj[0]);
 		ret = 0;
diff --git a/src/ap/dpp_hostapd.h b/src/ap/dpp_hostapd.h
index e151c2f..b1fa99e 100644
--- a/src/ap/dpp_hostapd.h
+++ b/src/ap/dpp_hostapd.h
@@ -1,7 +1,7 @@
 /*
  * hostapd / DPP integration
  * Copyright (c) 2017, Qualcomm Atheros, Inc.
- * Copyright (c) 2018-2019, The Linux Foundation
+ * Copyright (c) 2018-2020, The Linux Foundation
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -12,6 +12,8 @@
 
 int hostapd_dpp_qr_code(struct hostapd_data *hapd, const char *cmd);
 int hostapd_dpp_nfc_uri(struct hostapd_data *hapd, const char *cmd);
+int hostapd_dpp_nfc_handover_req(struct hostapd_data *hapd, const char *cmd);
+int hostapd_dpp_nfc_handover_sel(struct hostapd_data *hapd, const char *cmd);
 int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd);
 int hostapd_dpp_listen(struct hostapd_data *hapd, const char *cmd);
 void hostapd_dpp_listen_stop(struct hostapd_data *hapd);
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index 8a4b0ef..559bb87 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -109,7 +109,8 @@
 			const u8 *req_ies, size_t req_ies_len, int reassoc)
 {
 	struct sta_info *sta;
-	int new_assoc, res;
+	int new_assoc;
+	enum wpa_validate_result res;
 	struct ieee802_11_elems elems;
 	const u8 *ie;
 	size_t ielen;
@@ -220,7 +221,6 @@
 	}
 #endif /* CONFIG_P2P */
 
-#ifdef CONFIG_IEEE80211N
 #ifdef NEED_AP_MLME
 	if (elems.ht_capabilities &&
 	    (hapd->iface->conf->ht_capab &
@@ -234,7 +234,6 @@
 			ht40_intolerant_add(hapd->iface, sta);
 	}
 #endif /* NEED_AP_MLME */
-#endif /* CONFIG_IEEE80211N */
 
 #ifdef CONFIG_INTERWORKING
 	if (elems.ext_capab && elems.ext_capab_len > 4) {
@@ -325,33 +324,67 @@
 					  elems.rsnxe ? elems.rsnxe_len + 2 : 0,
 					  elems.mdie, elems.mdie_len,
 					  elems.owe_dh, elems.owe_dh_len);
-		if (res != WPA_IE_OK) {
+		reason = WLAN_REASON_INVALID_IE;
+		status = WLAN_STATUS_INVALID_IE;
+		switch (res) {
+		case WPA_IE_OK:
+			reason = WLAN_REASON_UNSPECIFIED;
+			status = WLAN_STATUS_SUCCESS;
+			break;
+		case WPA_INVALID_IE:
+			reason = WLAN_REASON_INVALID_IE;
+			status = WLAN_STATUS_INVALID_IE;
+			break;
+		case WPA_INVALID_GROUP:
+			reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
+			status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
+			break;
+		case WPA_INVALID_PAIRWISE:
+			reason = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID;
+			status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
+			break;
+		case WPA_INVALID_AKMP:
+			reason = WLAN_REASON_AKMP_NOT_VALID;
+			status = WLAN_STATUS_AKMP_NOT_VALID;
+			break;
+		case WPA_NOT_ENABLED:
+			reason = WLAN_REASON_INVALID_IE;
+			status = WLAN_STATUS_INVALID_IE;
+			break;
+		case WPA_ALLOC_FAIL:
+			reason = WLAN_REASON_UNSPECIFIED;
+			status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+			break;
+		case WPA_MGMT_FRAME_PROTECTION_VIOLATION:
+			reason = WLAN_REASON_INVALID_IE;
+			status = WLAN_STATUS_INVALID_IE;
+			break;
+		case WPA_INVALID_MGMT_GROUP_CIPHER:
+			reason = WLAN_REASON_CIPHER_SUITE_REJECTED;
+			status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
+			break;
+		case WPA_INVALID_MDIE:
+			reason = WLAN_REASON_INVALID_MDE;
+			status = WLAN_STATUS_INVALID_MDIE;
+			break;
+		case WPA_INVALID_PROTO:
+			reason = WLAN_REASON_INVALID_IE;
+			status = WLAN_STATUS_INVALID_IE;
+			break;
+		case WPA_INVALID_PMKID:
+			reason = WLAN_REASON_INVALID_PMKID;
+			status = WLAN_STATUS_INVALID_PMKID;
+			break;
+		case WPA_DENIED_OTHER_REASON:
+			reason = WLAN_REASON_UNSPECIFIED;
+			status = WLAN_STATUS_ASSOC_DENIED_UNSPEC;
+			break;
+		}
+		if (status != WLAN_STATUS_SUCCESS) {
 			wpa_printf(MSG_DEBUG,
 				   "WPA/RSN information element rejected? (res %u)",
 				   res);
 			wpa_hexdump(MSG_DEBUG, "IE", ie, ielen);
-			if (res == WPA_INVALID_GROUP) {
-				reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
-				status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
-			} else if (res == WPA_INVALID_PAIRWISE) {
-				reason = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID;
-				status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
-			} else if (res == WPA_INVALID_AKMP) {
-				reason = WLAN_REASON_AKMP_NOT_VALID;
-				status = WLAN_STATUS_AKMP_NOT_VALID;
-			} 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;
-			} else if (res == WPA_INVALID_PMKID) {
-				reason = WLAN_REASON_INVALID_PMKID;
-				status = WLAN_STATUS_INVALID_PMKID;
-			} else {
-				reason = WLAN_REASON_INVALID_IE;
-				status = WLAN_STATUS_INVALID_IE;
-			}
 			goto fail;
 		}
 
@@ -469,6 +502,9 @@
 			return WLAN_STATUS_INVALID_IE;
 #endif /* CONFIG_HS20 */
 	}
+#ifdef CONFIG_WPS
+skip_wpa_check:
+#endif /* CONFIG_WPS */
 
 #ifdef CONFIG_MBO
 	if (hapd->conf->mbo_enabled && (hapd->conf->wpa & 2) &&
@@ -480,13 +516,10 @@
 	}
 #endif /* CONFIG_MBO */
 
-#ifdef CONFIG_WPS
-skip_wpa_check:
-#endif /* CONFIG_WPS */
-
 #ifdef CONFIG_IEEE80211R_AP
 	p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, buf, sizeof(buf),
-					sta->auth_alg, req_ies, req_ies_len);
+					sta->auth_alg, req_ies, req_ies_len,
+					!elems.rsnxe);
 	if (!p) {
 		wpa_printf(MSG_DEBUG, "FT: Failed to write AssocResp IEs");
 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
@@ -577,18 +610,18 @@
 		npos = owe_assoc_req_process(hapd, sta,
 					     elems.owe_dh, elems.owe_dh_len,
 					     p, sizeof(buf) - (p - buf),
-					     &reason);
+					     &status);
 		if (npos)
 			p = npos;
+
 		if (!npos &&
-		    reason == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
-			status = WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
+		    status == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
 			hostapd_sta_assoc(hapd, addr, reassoc, status, buf,
 					  p - buf);
 			return 0;
 		}
 
-		if (!npos || reason != WLAN_STATUS_SUCCESS)
+		if (!npos || status != WLAN_STATUS_SUCCESS)
 			goto fail;
 	}
 #endif /* CONFIG_OWE */
@@ -625,6 +658,11 @@
 	pfs_fail:
 #endif /* CONFIG_DPP2 */
 
+	if (elems.rrm_enabled &&
+	    elems.rrm_enabled_len >= sizeof(sta->rrm_enabled_capa))
+	    os_memcpy(sta->rrm_enabled_capa, elems.rrm_enabled,
+		      sizeof(sta->rrm_enabled_capa));
+
 #if defined(CONFIG_IEEE80211R_AP) || defined(CONFIG_FILS) || defined(CONFIG_OWE)
 	hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf);
 
@@ -709,6 +747,7 @@
 
 	ap_sta_set_authorized(hapd, sta, 0);
 	sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
+	hostapd_set_sta_flags(hapd, sta);
 	wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
 	sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
 	ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
@@ -906,6 +945,12 @@
 	} else if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) {
 		wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED
 			"freq=%d dfs=%d", freq, is_dfs);
+	} else if (is_dfs &&
+		   hostapd_is_dfs_required(hapd->iface) &&
+		   !hostapd_is_dfs_chan_available(hapd->iface) &&
+		   !hapd->iface->cac_started) {
+		hostapd_disable_iface(hapd->iface);
+		hostapd_enable_iface(hapd->iface);
 	}
 
 	for (i = 0; i < hapd->iface->num_bss; i++)
@@ -1005,32 +1050,35 @@
 		goto out;
 	}
 
+	hapd->iconf->edmg_channel = acs_res->edmg_channel;
+
 	if (hapd->iface->conf->ieee80211ac || hapd->iface->conf->ieee80211ax) {
 		/* set defaults for backwards compatibility */
 		hostapd_set_oper_centr_freq_seg1_idx(hapd->iconf, 0);
 		hostapd_set_oper_centr_freq_seg0_idx(hapd->iconf, 0);
 		hostapd_set_oper_chwidth(hapd->iconf, CHANWIDTH_USE_HT);
-		if (acs_res->ch_width == 80) {
+		if (acs_res->ch_width == 40) {
+			if (is_6ghz_freq(acs_res->pri_freq))
+				hostapd_set_oper_centr_freq_seg0_idx(
+					hapd->iconf,
+					acs_res->vht_seg0_center_ch);
+		} else if (acs_res->ch_width == 80) {
 			hostapd_set_oper_centr_freq_seg0_idx(
 				hapd->iconf, acs_res->vht_seg0_center_ch);
-			hostapd_set_oper_chwidth(hapd->iconf, CHANWIDTH_80MHZ);
-		} else if (acs_res->ch_width == 160) {
 			if (acs_res->vht_seg1_center_ch == 0) {
-				hostapd_set_oper_centr_freq_seg0_idx(
-					hapd->iconf,
-					acs_res->vht_seg0_center_ch);
 				hostapd_set_oper_chwidth(hapd->iconf,
-							 CHANWIDTH_160MHZ);
+							 CHANWIDTH_80MHZ);
 			} else {
-				hostapd_set_oper_centr_freq_seg0_idx(
-					hapd->iconf,
-					acs_res->vht_seg0_center_ch);
+				hostapd_set_oper_chwidth(hapd->iconf,
+							 CHANWIDTH_80P80MHZ);
 				hostapd_set_oper_centr_freq_seg1_idx(
 					hapd->iconf,
 					acs_res->vht_seg1_center_ch);
-				hostapd_set_oper_chwidth(hapd->iconf,
-							 CHANWIDTH_80P80MHZ);
 			}
+		} else if (acs_res->ch_width == 160) {
+			hostapd_set_oper_chwidth(hapd->iconf, CHANWIDTH_160MHZ);
+			hostapd_set_oper_centr_freq_seg0_idx(
+				hapd->iconf, acs_res->vht_seg1_center_ch);
 		}
 	}
 
@@ -1426,15 +1474,33 @@
 #endif /* HOSTAPD */
 
 
+static struct hostapd_channel_data *
+hostapd_get_mode_chan(struct hostapd_hw_modes *mode, unsigned int freq)
+{
+	int i;
+	struct hostapd_channel_data *chan;
+
+	for (i = 0; i < mode->num_channels; i++) {
+		chan = &mode->channels[i];
+		if ((unsigned int) chan->freq == freq)
+			return chan;
+	}
+
+	return NULL;
+}
+
+
 static struct hostapd_channel_data * hostapd_get_mode_channel(
 	struct hostapd_iface *iface, unsigned int freq)
 {
 	int i;
 	struct hostapd_channel_data *chan;
 
-	for (i = 0; i < iface->current_mode->num_channels; i++) {
-		chan = &iface->current_mode->channels[i];
-		if ((unsigned int) chan->freq == freq)
+	for (i = 0; i < iface->num_hw_features; i++) {
+		if (hostapd_hw_skip_mode(iface, &iface->hw_features[i]))
+			continue;
+		chan = hostapd_get_mode_chan(&iface->hw_features[i], freq);
+		if (chan)
 			return chan;
 	}
 
diff --git a/src/ap/fils_hlp.c b/src/ap/fils_hlp.c
index 6da514a..0310aab 100644
--- a/src/ap/fils_hlp.c
+++ b/src/ap/fils_hlp.c
@@ -158,7 +158,7 @@
 	ssize_t res;
 	u8 msgtype = 0;
 	int rapid_commit = 0;
-	struct iphdr *iph;
+	struct ip *iph;
 	struct udphdr *udph;
 	struct wpabuf *resp;
 	const u8 *rpos;
@@ -259,14 +259,14 @@
 	wpabuf_put_data(resp, "\xaa\xaa\x03\x00\x00\x00", 6);
 	wpabuf_put_be16(resp, ETH_P_IP);
 	iph = wpabuf_put(resp, sizeof(*iph));
-	iph->version = 4;
-	iph->ihl = sizeof(*iph) / 4;
-	iph->tot_len = htons(sizeof(*iph) + sizeof(*udph) + (end - pos));
-	iph->ttl = 1;
-	iph->protocol = 17; /* UDP */
-	iph->saddr = hapd->conf->dhcp_server.u.v4.s_addr;
-	iph->daddr = dhcp->client_ip;
-	iph->check = ip_checksum(iph, sizeof(*iph));
+	iph->ip_v = 4;
+	iph->ip_hl = sizeof(*iph) / 4;
+	iph->ip_len = htons(sizeof(*iph) + sizeof(*udph) + (end - pos));
+	iph->ip_ttl = 1;
+	iph->ip_p = 17; /* UDP */
+	iph->ip_src.s_addr = hapd->conf->dhcp_server.u.v4.s_addr;
+	iph->ip_dst.s_addr = dhcp->client_ip;
+	iph->ip_sum = ip_checksum(iph, sizeof(*iph));
 	udph = wpabuf_put(resp, sizeof(*udph));
 	udph->uh_sport = htons(DHCP_SERVER_PORT);
 	udph->uh_dport = htons(DHCP_CLIENT_PORT);
@@ -479,13 +479,13 @@
 				struct sta_info *sta, const u8 *dst,
 				const u8 *pos, size_t len)
 {
-	const struct iphdr *iph;
+	const struct ip *iph;
 	const struct udphdr *udph;
 	u16 sport, dport, ulen;
 
 	if (len < sizeof(*iph) + sizeof(*udph))
 		return 0;
-	iph = (const struct iphdr *) pos;
+	iph = (const struct ip *) pos;
 	udph = (const struct udphdr *) (iph + 1);
 	sport = ntohs(udph->uh_sport);
 	dport = ntohs(udph->uh_dport);
@@ -510,24 +510,24 @@
 			       struct sta_info *sta, const u8 *dst,
 			       const u8 *pos, size_t len)
 {
-	const struct iphdr *iph;
-	u16 tot_len;
+	const struct ip *iph;
+	uint16_t ip_len;
 
 	if (len < sizeof(*iph))
 		return 0;
-	iph = (const struct iphdr *) pos;
+	iph = (const struct ip *) pos;
 	if (ip_checksum(iph, sizeof(*iph)) != 0) {
 		wpa_printf(MSG_DEBUG,
 			   "FILS: HLP request IPv4 packet had invalid header checksum - dropped");
 		return 0;
 	}
-	tot_len = ntohs(iph->tot_len);
-	if (tot_len > len)
+	ip_len = ntohs(iph->ip_len);
+	if (ip_len > len)
 		return 0;
 	wpa_printf(MSG_DEBUG,
 		   "FILS: HLP request IPv4: saddr=%08x daddr=%08x protocol=%u",
-		   iph->saddr, iph->daddr, iph->protocol);
-	switch (iph->protocol) {
+		   iph->ip_src.s_addr, iph->ip_dst.s_addr, iph->ip_p);
+	switch (iph->ip_p) {
 	case 17:
 		return fils_process_hlp_udp(hapd, sta, dst, pos, len);
 	}
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index e4950e3..f2e964a 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -13,6 +13,7 @@
 
 #include "utils/common.h"
 #include "utils/eloop.h"
+#include "utils/crc32.h"
 #include "common/ieee802_11_defs.h"
 #include "common/wpa_ctrl.h"
 #include "common/hw_features_common.h"
@@ -57,8 +58,10 @@
 
 
 static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason);
+#ifdef CONFIG_WEP
 static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd);
 static int hostapd_broadcast_wep_clear(struct hostapd_data *hapd);
+#endif /* CONFIG_WEP */
 static int setup_interface2(struct hostapd_iface *iface);
 static void channel_list_update_timeout(void *eloop_ctx, void *timeout_ctx);
 static void hostapd_interface_setup_failure_handler(void *eloop_ctx,
@@ -88,7 +91,9 @@
 		return;
 
 	hostapd_set_privacy(hapd, 0);
+#ifdef CONFIG_WEP
 	hostapd_setup_encryption(hapd->conf->iface, hapd);
+#endif /* CONFIG_WEP */
 }
 
 
@@ -141,7 +146,9 @@
 		wpa_deinit(hapd->wpa_auth);
 		hapd->wpa_auth = NULL;
 		hostapd_set_privacy(hapd, 0);
+#ifdef CONFIG_WEP
 		hostapd_setup_encryption(hapd->conf->iface, hapd);
+#endif /* CONFIG_WEP */
 		hostapd_set_generic_elem(hapd, (u8 *) "", 0);
 	}
 
@@ -169,7 +176,9 @@
 	for (j = 0; j < iface->num_bss; j++) {
 		hostapd_flush_old_stations(iface->bss[j],
 					   WLAN_REASON_PREV_AUTH_NOT_VALID);
+#ifdef CONFIG_WEP
 		hostapd_broadcast_wep_clear(iface->bss[j]);
+#endif /* CONFIG_WEP */
 
 #ifndef CONFIG_NO_RADIUS
 		/* TODO: update dynamic data based on changed configuration
@@ -283,6 +292,8 @@
 }
 
 
+#ifdef CONFIG_WEP
+
 static void hostapd_broadcast_key_clear_iface(struct hostapd_data *hapd,
 					      const char *ifname)
 {
@@ -291,8 +302,8 @@
 	if (!ifname || !hapd->drv_priv)
 		return;
 	for (i = 0; i < NUM_WEP_KEYS; i++) {
-		if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_NONE, NULL, i,
-					0, NULL, 0, NULL, 0)) {
+		if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_NONE, NULL, i, 0,
+					0, NULL, 0, NULL, 0, KEY_FLAG_GROUP)) {
 			wpa_printf(MSG_DEBUG, "Failed to clear default "
 				   "encryption keys (ifname=%s keyidx=%d)",
 				   ifname, i);
@@ -301,8 +312,8 @@
 	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,
-						NULL, i, 0, NULL,
-						0, NULL, 0)) {
+						NULL, i, 0, 0, NULL,
+						0, NULL, 0, KEY_FLAG_GROUP)) {
 				wpa_printf(MSG_DEBUG, "Failed to clear "
 					   "default mgmt encryption keys "
 					   "(ifname=%s keyidx=%d)", ifname, i);
@@ -325,11 +336,12 @@
 	struct hostapd_ssid *ssid = &hapd->conf->ssid;
 
 	idx = ssid->wep.idx;
-	if (ssid->wep.default_len &&
+	if (ssid->wep.default_len && ssid->wep.key[idx] &&
 	    hostapd_drv_set_key(hapd->conf->iface,
-				hapd, WPA_ALG_WEP, broadcast_ether_addr, idx,
+				hapd, WPA_ALG_WEP, broadcast_ether_addr, idx, 0,
 				1, NULL, 0, ssid->wep.key[idx],
-				ssid->wep.len[idx])) {
+				ssid->wep.len[idx],
+				KEY_FLAG_GROUP_RX_TX_DEFAULT)) {
 		wpa_printf(MSG_WARNING, "Could not set WEP encryption.");
 		errors++;
 	}
@@ -337,6 +349,8 @@
 	return errors;
 }
 
+#endif /* CONFIG_WEP */
+
 
 static void hostapd_free_hapd_data(struct hostapd_data *hapd)
 {
@@ -479,11 +493,9 @@
 static void hostapd_cleanup_iface_partial(struct hostapd_iface *iface)
 {
 	wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
-#ifdef CONFIG_IEEE80211N
 #ifdef NEED_AP_MLME
 	hostapd_stop_setup_timers(iface);
 #endif /* NEED_AP_MLME */
-#endif /* CONFIG_IEEE80211N */
 	if (iface->current_mode)
 		acs_cleanup(iface);
 	hostapd_free_hw_features(iface->hw_features, iface->num_hw_features);
@@ -524,6 +536,8 @@
 }
 
 
+#ifdef CONFIG_WEP
+
 static void hostapd_clear_wep(struct hostapd_data *hapd)
 {
 	if (hapd->drv_priv && !hapd->iface->driver_ap_teardown && hapd->conf) {
@@ -552,10 +566,13 @@
 
 	for (i = 0; i < 4; i++) {
 		if (hapd->conf->ssid.wep.key[i] &&
-		    hostapd_drv_set_key(iface, hapd, WPA_ALG_WEP, NULL, i,
+		    hostapd_drv_set_key(iface, hapd, WPA_ALG_WEP, NULL, i, 0,
 					i == hapd->conf->ssid.wep.idx, NULL, 0,
 					hapd->conf->ssid.wep.key[i],
-					hapd->conf->ssid.wep.len[i])) {
+					hapd->conf->ssid.wep.len[i],
+					i == hapd->conf->ssid.wep.idx ?
+					KEY_FLAG_GROUP_RX_TX_DEFAULT :
+					KEY_FLAG_GROUP_RX_TX)) {
 			wpa_printf(MSG_WARNING, "Could not set WEP "
 				   "encryption.");
 			return -1;
@@ -568,6 +585,8 @@
 	return 0;
 }
 
+#endif /* CONFIG_WEP */
+
 
 static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason)
 {
@@ -603,7 +622,9 @@
 {
 	hostapd_free_stas(hapd);
 	hostapd_flush_old_stations(hapd, WLAN_REASON_DEAUTH_LEAVING);
+#ifdef CONFIG_WEP
 	hostapd_clear_wep(hapd);
+#endif /* CONFIG_WEP */
 }
 
 
@@ -1158,9 +1179,11 @@
 					   WLAN_REASON_PREV_AUTH_NOT_VALID);
 	hostapd_set_privacy(hapd, 0);
 
+#ifdef CONFIG_WEP
 	hostapd_broadcast_wep_clear(hapd);
 	if (hostapd_setup_encryption(conf->iface, hapd))
 		return -1;
+#endif /* CONFIG_WEP */
 
 	/*
 	 * Fetch the SSID from the system and use it or,
@@ -1190,8 +1213,14 @@
 		os_memcpy(conf->ssid.ssid, ssid, conf->ssid.ssid_len);
 	}
 
+	/*
+	 * Short SSID calculation is identical to FCS and it is defined in
+	 * IEEE P802.11-REVmd/D3.0, 9.4.2.170.3 (Calculating the Short-SSID).
+	 */
+	conf->ssid.short_ssid = crc32(conf->ssid.ssid, conf->ssid.ssid_len);
+
 	if (!hostapd_drv_none(hapd)) {
-		wpa_printf(MSG_ERROR, "Using interface %s with hwaddr " MACSTR
+		wpa_printf(MSG_DEBUG, "Using interface %s with hwaddr " MACSTR
 			   " and ssid \"%s\"",
 			   conf->iface, MAC2STR(hapd->own_addr),
 			   wpa_ssid_txt(conf->ssid.ssid, conf->ssid.ssid_len));
@@ -2338,12 +2367,10 @@
 		hostapd_bss_deinit(iface->bss[j]);
 	}
 
-#ifdef CONFIG_IEEE80211N
 #ifdef NEED_AP_MLME
 	hostapd_stop_setup_timers(iface);
 	eloop_cancel_timeout(ap_ht2040_timeout, iface, NULL);
 #endif /* NEED_AP_MLME */
-#endif /* CONFIG_IEEE80211N */
 }
 
 
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index 016fe3b..439e727 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -38,6 +38,10 @@
 struct mesh_conf;
 #endif /* CONFIG_MESH */
 
+#ifdef CONFIG_CTRL_IFACE_UDP
+#define CTRL_IFACE_COOKIE_LEN 8
+#endif /* CONFIG_CTRL_IFACE_UDP */
+
 struct hostapd_iface;
 
 struct hapd_interfaces {
@@ -72,6 +76,11 @@
 #ifdef CONFIG_DPP
 	struct dpp_global *dpp;
 #endif /* CONFIG_DPP */
+
+#ifdef CONFIG_CTRL_IFACE_UDP
+       unsigned char ctrl_iface_cookie[CTRL_IFACE_COOKIE_LEN];
+#endif /* CONFIG_CTRL_IFACE_UDP */
+
 };
 
 enum hostapd_chan_status {
@@ -395,6 +404,10 @@
 #ifdef CONFIG_SQLITE
 	sqlite3 *rad_attr_db;
 #endif /* CONFIG_SQLITE */
+
+#ifdef CONFIG_CTRL_IFACE_UDP
+       unsigned char ctrl_iface_cookie[CTRL_IFACE_COOKIE_LEN];
+#endif /* CONFIG_CTRL_IFACE_UDP */
 };
 
 
@@ -464,9 +477,6 @@
 
 	u64 drv_flags;
 
-	/* SMPS modes supported by the driver (WPA_DRIVER_SMPS_MODE_*) */
-	unsigned int smps_modes;
-
 	/*
 	 * A bitmap of supported protocols for probe response offload. See
 	 * struct wpa_driver_capa in driver.h
diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
index ba10752..f6e6903 100644
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -224,7 +224,6 @@
 }
 
 
-#ifdef CONFIG_IEEE80211N
 static int ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface *iface)
 {
 	int pri_freq, sec_freq;
@@ -561,26 +560,6 @@
 		return 0;
 	}
 
-	switch (conf & HT_CAP_INFO_SMPS_MASK) {
-	case HT_CAP_INFO_SMPS_STATIC:
-		if (!(iface->smps_modes & WPA_DRIVER_SMPS_MODE_STATIC)) {
-			wpa_printf(MSG_ERROR,
-				   "Driver does not support configured HT capability [SMPS-STATIC]");
-			return 0;
-		}
-		break;
-	case HT_CAP_INFO_SMPS_DYNAMIC:
-		if (!(iface->smps_modes & WPA_DRIVER_SMPS_MODE_DYNAMIC)) {
-			wpa_printf(MSG_ERROR,
-				   "Driver does not support configured HT capability [SMPS-DYNAMIC]");
-			return 0;
-		}
-		break;
-	case HT_CAP_INFO_SMPS_DISABLED:
-	default:
-		break;
-	}
-
 	if ((conf & HT_CAP_INFO_GREEN_FIELD) &&
 	    !(hw & HT_CAP_INFO_GREEN_FIELD)) {
 		wpa_printf(MSG_ERROR, "Driver does not support configured "
@@ -687,12 +666,9 @@
 }
 #endif /* CONFIG_IEEE80211AX */
 
-#endif /* CONFIG_IEEE80211N */
-
 
 int hostapd_check_ht_capab(struct hostapd_iface *iface)
 {
-#ifdef CONFIG_IEEE80211N
 	int ret;
 
 	if (is_6ghz_freq(iface->freq))
@@ -725,7 +701,6 @@
 		return ret;
 	if (!ieee80211n_allowed_ht40_channel_pair(iface))
 		return -1;
-#endif /* CONFIG_IEEE80211N */
 
 	return 0;
 }
@@ -810,7 +785,7 @@
 
 	/* 60 GHz channels 1..6 */
 	for (i = 0; i < 6; i++) {
-		int freq = 56160 + 2160 * i;
+		int freq = 56160 + 2160 * (i + 1);
 
 		if (edmg.channels & BIT(i)) {
 			contiguous++;
@@ -879,10 +854,11 @@
 	if (!iface->conf->secondary_channel)
 		return 1;
 
+	if (hostapd_is_usable_chan(iface, iface->freq +
+				   iface->conf->secondary_channel * 20, 0))
+		return 1;
 	if (!iface->conf->ht40_plus_minus_allowed)
-		return hostapd_is_usable_chan(
-			iface,
-			iface->freq + iface->conf->secondary_channel * 20, 0);
+		return 0;
 
 	/* Both HT40+ and HT40- are set, pick a valid secondary channel */
 	secondary_freq = iface->freq + 20;
@@ -903,10 +879,43 @@
 }
 
 
+static void hostapd_determine_mode(struct hostapd_iface *iface)
+{
+	int i;
+	enum hostapd_hw_mode target_mode;
+
+	if (iface->current_mode ||
+	    iface->conf->hw_mode != HOSTAPD_MODE_IEEE80211ANY)
+		return;
+
+	if (iface->freq < 4000)
+		target_mode = HOSTAPD_MODE_IEEE80211G;
+	else if (iface->freq > 50000)
+		target_mode = HOSTAPD_MODE_IEEE80211AD;
+	else
+		target_mode = HOSTAPD_MODE_IEEE80211A;
+
+	for (i = 0; i < iface->num_hw_features; i++) {
+		struct hostapd_hw_modes *mode;
+
+		mode = &iface->hw_features[i];
+		if (mode->mode == target_mode) {
+			iface->current_mode = mode;
+			iface->conf->hw_mode = mode->mode;
+			break;
+		}
+	}
+
+	if (!iface->current_mode)
+		wpa_printf(MSG_ERROR, "ACS: Cannot decide mode");
+}
+
+
 static enum hostapd_chan_status
 hostapd_check_chans(struct hostapd_iface *iface)
 {
 	if (iface->freq) {
+		hostapd_determine_mode(iface);
 		if (hostapd_is_usable_chans(iface))
 			return HOSTAPD_CHAN_VALID;
 		else
@@ -1032,9 +1041,15 @@
 	}
 
 	if (iface->current_mode == NULL) {
-		if (!(iface->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) ||
-		    !(iface->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_HW_MODE_ANY))
-		{
+		if ((iface->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) &&
+		    (iface->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_HW_MODE_ANY)) {
+			wpa_printf(MSG_DEBUG,
+				   "Using offloaded hw_mode=any ACS");
+		} else if (!(iface->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) &&
+			   iface->conf->hw_mode == HOSTAPD_MODE_IEEE80211ANY) {
+			wpa_printf(MSG_DEBUG,
+				   "Using internal ACS for hw_mode=any");
+		} else {
 			wpa_printf(MSG_ERROR,
 				   "Hardware does not support configured mode");
 			hostapd_logger(iface->bss[0], NULL,
@@ -1109,3 +1124,20 @@
 	}
 	return 0;
 }
+
+
+int hostapd_hw_skip_mode(struct hostapd_iface *iface,
+			 struct hostapd_hw_modes *mode)
+{
+	int i;
+
+	if (iface->current_mode)
+		return mode != iface->current_mode;
+	if (mode->mode != HOSTAPD_MODE_IEEE80211B)
+		return 0;
+	for (i = 0; i < iface->num_hw_features; i++) {
+		if (iface->hw_features[i].mode == HOSTAPD_MODE_IEEE80211G)
+			return 1;
+	}
+	return 0;
+}
diff --git a/src/ap/hw_features.h b/src/ap/hw_features.h
index 902a19f..dd24f95 100644
--- a/src/ap/hw_features.h
+++ b/src/ap/hw_features.h
@@ -25,6 +25,8 @@
 int hostapd_prepare_rates(struct hostapd_iface *iface,
 			  struct hostapd_hw_modes *mode);
 void hostapd_stop_setup_timers(struct hostapd_iface *iface);
+int hostapd_hw_skip_mode(struct hostapd_iface *iface,
+			 struct hostapd_hw_modes *mode);
 #else /* NEED_AP_MLME */
 static inline void
 hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
@@ -49,7 +51,7 @@
 
 static inline const char * hostapd_hw_mode_txt(int mode)
 {
-	return NULL;
+	return "UNKNOWN";
 }
 
 static inline int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan)
@@ -77,6 +79,12 @@
 {
 }
 
+static inline int hostapd_hw_skip_mode(struct hostapd_iface *iface,
+				       struct hostapd_hw_modes *mode)
+{
+	return 0;
+}
+
 #endif /* NEED_AP_MLME */
 
 #endif /* HW_FEATURES_H */
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 5b70425..e54217c 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -88,6 +88,7 @@
 {
 	u8 *pos = eid;
 	int i, num, count;
+	int h2e_required;
 
 	if (hapd->iface->current_rates == NULL)
 		return eid;
@@ -98,8 +99,11 @@
 		num++;
 	if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht)
 		num++;
-	if (hapd->conf->sae_pwe == 1 &&
-	    wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt))
+	h2e_required = (hapd->conf->sae_pwe == 1 ||
+			hostapd_sae_pw_id_in_use(hapd->conf) == 2) &&
+		hapd->conf->sae_pwe != 3 &&
+		wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt);
+	if (h2e_required)
 		num++;
 	if (num > 8) {
 		/* rest of the rates are encoded in Extended supported
@@ -127,9 +131,7 @@
 		*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY;
 	}
 
-	if (hapd->conf->sae_pwe == 1 &&
-	    wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
-	    count < 8) {
+	if (h2e_required && count < 8) {
 		count++;
 		*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_SAE_H2E_ONLY;
 	}
@@ -142,6 +144,7 @@
 {
 	u8 *pos = eid;
 	int i, num, count;
+	int h2e_required;
 
 	if (hapd->iface->current_rates == NULL)
 		return eid;
@@ -151,8 +154,11 @@
 		num++;
 	if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht)
 		num++;
-	if (hapd->conf->sae_pwe == 1 &&
-	    wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt))
+	h2e_required = (hapd->conf->sae_pwe == 1 ||
+			hostapd_sae_pw_id_in_use(hapd->conf) == 2) &&
+		hapd->conf->sae_pwe != 3 &&
+		wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt);
+	if (h2e_required)
 		num++;
 	if (num <= 8)
 		return eid;
@@ -183,8 +189,7 @@
 			*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY;
 	}
 
-	if (hapd->conf->sae_pwe == 1 &&
-	    wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt)) {
+	if (h2e_required) {
 		count++;
 		if (count > 8)
 			*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_SAE_H2E_ONLY;
@@ -194,10 +199,31 @@
 }
 
 
+u8 * hostapd_eid_rm_enabled_capab(struct hostapd_data *hapd, u8 *eid,
+				  size_t len)
+{
+	size_t i;
+
+	for (i = 0; i < RRM_CAPABILITIES_IE_LEN; i++) {
+		if (hapd->conf->radio_measurements[i])
+			break;
+	}
+
+	if (i == RRM_CAPABILITIES_IE_LEN || len < 2 + RRM_CAPABILITIES_IE_LEN)
+		return eid;
+
+	*eid++ = WLAN_EID_RRM_ENABLED_CAPABILITIES;
+	*eid++ = RRM_CAPABILITIES_IE_LEN;
+	os_memcpy(eid, hapd->conf->radio_measurements, RRM_CAPABILITIES_IE_LEN);
+
+	return eid + RRM_CAPABILITIES_IE_LEN;
+}
+
+
 u16 hostapd_own_capab_info(struct hostapd_data *hapd)
 {
 	int capab = WLAN_CAPABILITY_ESS;
-	int privacy;
+	int privacy = 0;
 	int dfs;
 	int i;
 
@@ -213,12 +239,14 @@
 	    hapd->iconf->preamble == SHORT_PREAMBLE)
 		capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
 
+#ifdef CONFIG_WEP
 	privacy = hapd->conf->ssid.wep.keys_set;
 
 	if (hapd->conf->ieee802_1x &&
 	    (hapd->conf->default_wep_key_len ||
 	     hapd->conf->individual_wep_key_len))
 		privacy = 1;
+#endif /* CONFIG_WEP */
 
 	if (hapd->conf->wpa)
 		privacy = 1;
@@ -258,6 +286,7 @@
 }
 
 
+#ifdef CONFIG_WEP
 #ifndef CONFIG_NO_RC4
 static u16 auth_shared_key(struct hostapd_data *hapd, struct sta_info *sta,
 			   u16 auth_transaction, const u8 *challenge,
@@ -314,9 +343,10 @@
 	return 0;
 }
 #endif /* CONFIG_NO_RC4 */
+#endif /* CONFIG_WEP */
 
 
-static int send_auth_reply(struct hostapd_data *hapd,
+static int send_auth_reply(struct hostapd_data *hapd, struct sta_info *sta,
 			   const u8 *dst, const u8 *bssid,
 			   u16 auth_alg, u16 auth_transaction, u16 resp,
 			   const u8 *ies, size_t ies_len, const char *dbg)
@@ -349,7 +379,37 @@
 		   " auth_alg=%d auth_transaction=%d resp=%d (IE len=%lu) (dbg=%s)",
 		   MAC2STR(dst), auth_alg, auth_transaction,
 		   resp, (unsigned long) ies_len, dbg);
-	if (hostapd_drv_send_mlme(hapd, reply, rlen, 0) < 0)
+#ifdef CONFIG_TESTING_OPTIONS
+#ifdef CONFIG_SAE
+	if (hapd->conf->sae_confirm_immediate == 2 &&
+	    auth_alg == WLAN_AUTH_SAE) {
+		if (auth_transaction == 1 && sta &&
+		    (resp == WLAN_STATUS_SUCCESS ||
+		     resp == WLAN_STATUS_SAE_HASH_TO_ELEMENT)) {
+			wpa_printf(MSG_DEBUG,
+				   "TESTING: Postpone SAE Commit transmission until Confirm is ready");
+			os_free(sta->sae_postponed_commit);
+			sta->sae_postponed_commit = buf;
+			sta->sae_postponed_commit_len = rlen;
+			return WLAN_STATUS_SUCCESS;
+		}
+
+		if (auth_transaction == 2 && sta && sta->sae_postponed_commit) {
+			wpa_printf(MSG_DEBUG,
+				   "TESTING: Send postponed SAE Commit first, immediately followed by SAE Confirm");
+			if (hostapd_drv_send_mlme(hapd,
+						  sta->sae_postponed_commit,
+						  sta->sae_postponed_commit_len,
+						  0, NULL, 0, 0) < 0)
+				wpa_printf(MSG_INFO, "send_auth_reply: send failed");
+			os_free(sta->sae_postponed_commit);
+			sta->sae_postponed_commit = NULL;
+			sta->sae_postponed_commit_len = 0;
+		}
+	}
+#endif /* CONFIG_SAE */
+#endif /* CONFIG_TESTING_OPTIONS */
+	if (hostapd_drv_send_mlme(hapd, reply, rlen, 0, NULL, 0, 0) < 0)
 		wpa_printf(MSG_INFO, "send_auth_reply: send failed");
 	else
 		reply_res = WLAN_STATUS_SUCCESS;
@@ -369,7 +429,7 @@
 	struct sta_info *sta;
 	int reply_res;
 
-	reply_res = send_auth_reply(hapd, dst, bssid, WLAN_AUTH_FT,
+	reply_res = send_auth_reply(hapd, NULL, dst, bssid, WLAN_AUTH_FT,
 				    auth_transaction, status, ies, ies_len,
 				    "auth-ft-finish");
 
@@ -423,7 +483,9 @@
 		use_pt = sta->sae->tmp->h2e;
 	}
 
-	if (status_code == WLAN_STATUS_SUCCESS)
+	if (rx_id && hapd->conf->sae_pwe != 3)
+		use_pt = 1;
+	else if (status_code == WLAN_STATUS_SUCCESS)
 		use_pt = 0;
 	else if (status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT)
 		use_pt = 1;
@@ -474,10 +536,13 @@
 
 	buf = wpabuf_alloc(SAE_COMMIT_MAX_LEN +
 			   (rx_id ? 3 + os_strlen(rx_id) : 0));
-	if (buf == NULL)
-		return NULL;
-	sae_write_commit(sta->sae, buf, sta->sae->tmp ?
-			 sta->sae->tmp->anti_clogging_token : NULL, rx_id);
+	if (buf &&
+	    sae_write_commit(sta->sae, buf, sta->sae->tmp ?
+			     sta->sae->tmp->anti_clogging_token : NULL,
+			     rx_id) < 0) {
+		wpabuf_free(buf);
+		buf = NULL;
+	}
 
 	return buf;
 }
@@ -514,7 +579,8 @@
 
 	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,
+	reply_res = send_auth_reply(hapd, sta, sta->addr, bssid,
+				    WLAN_AUTH_SAE, 1,
 				    status, wpabuf_head(data),
 				    wpabuf_len(data), "sae-send-commit");
 
@@ -535,7 +601,8 @@
 	if (data == NULL)
 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
 
-	reply_res = send_auth_reply(hapd, sta->addr, bssid, WLAN_AUTH_SAE, 2,
+	reply_res = send_auth_reply(hapd, sta, sta->addr, bssid,
+				    WLAN_AUTH_SAE, 2,
 				    WLAN_STATUS_SUCCESS, wpabuf_head(data),
 				    wpabuf_len(data), "sae-send-confirm");
 
@@ -575,13 +642,15 @@
 }
 
 
-static u8 sae_token_hash(struct hostapd_data *hapd, const u8 *addr)
+static int sae_token_hash(struct hostapd_data *hapd, const u8 *addr, u8 *idx)
 {
 	u8 hash[SHA256_MAC_LEN];
 
-	hmac_sha256(hapd->sae_token_key, sizeof(hapd->sae_token_key),
-		    addr, ETH_ALEN, hash);
-	return hash[0];
+	if (hmac_sha256(hapd->sae_token_key, sizeof(hapd->sae_token_key),
+			addr, ETH_ALEN, hash) < 0)
+		return -1;
+	*idx = hash[0];
+	return 0;
 }
 
 
@@ -594,9 +663,8 @@
 	u16 token_idx;
 	u8 idx;
 
-	if (token_len != SHA256_MAC_LEN)
+	if (token_len != SHA256_MAC_LEN || sae_token_hash(hapd, addr, &idx) < 0)
 		return -1;
-	idx = sae_token_hash(hapd, addr);
 	token_idx = hapd->sae_pending_token_idx[idx];
 	if (token_idx == 0 || token_idx != WPA_GET_BE16(token)) {
 		wpa_printf(MSG_DEBUG, "SAE: Invalid anti-clogging token from "
@@ -621,7 +689,7 @@
 
 
 static struct wpabuf * auth_build_token_req(struct hostapd_data *hapd,
-					    int group, const u8 *addr)
+					    int group, const u8 *addr, int h2e)
 {
 	struct wpabuf *buf;
 	u8 *token;
@@ -647,13 +715,23 @@
 			  sizeof(hapd->sae_pending_token_idx));
 	}
 
-	buf = wpabuf_alloc(sizeof(le16) + SHA256_MAC_LEN);
+	buf = wpabuf_alloc(sizeof(le16) + 3 + SHA256_MAC_LEN);
 	if (buf == NULL)
 		return NULL;
 
 	wpabuf_put_le16(buf, group); /* Finite Cyclic Group */
 
-	p_idx = sae_token_hash(hapd, addr);
+	if (h2e) {
+		/* Encapsulate Anti-clogging Token field in a container IE */
+		wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
+		wpabuf_put_u8(buf, 1 + SHA256_MAC_LEN);
+		wpabuf_put_u8(buf, WLAN_EID_EXT_ANTI_CLOGGING_TOKEN);
+	}
+
+	if (sae_token_hash(hapd, addr, &p_idx) < 0) {
+		wpabuf_free(buf);
+		return NULL;
+	}
 	token_idx = hapd->sae_pending_token_idx[p_idx];
 	if (!token_idx) {
 		hapd->sae_token_idx++;
@@ -795,6 +873,9 @@
 	mlme_authenticate_indication(hapd, sta);
 	wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
 	sae_set_state(sta, SAE_ACCEPTED, "Accept Confirm");
+	crypto_bignum_deinit(sta->sae->peer_commit_scalar_accepted, 0);
+	sta->sae->peer_commit_scalar_accepted = sta->sae->peer_commit_scalar;
+	sta->sae->peer_commit_scalar = NULL;
 	wpa_auth_pmksa_add_sae(hapd->wpa_auth, sta->addr,
 			       sta->sae->pmk, sta->sae->pmkid);
 	sae_sme_send_external_auth_status(hapd, sta, WLAN_STATUS_SUCCESS);
@@ -1028,11 +1109,20 @@
 
 static int sae_status_success(struct hostapd_data *hapd, u16 status_code)
 {
-	return (hapd->conf->sae_pwe == 0 &&
+	int sae_pwe = hapd->conf->sae_pwe;
+	int id_in_use;
+
+	id_in_use = hostapd_sae_pw_id_in_use(hapd->conf);
+	if (id_in_use == 2 && sae_pwe != 3)
+		sae_pwe = 1;
+	else if (id_in_use == 1 && sae_pwe == 0)
+		sae_pwe = 2;
+
+	return ((sae_pwe == 0 || sae_pwe == 3) &&
 		status_code == WLAN_STATUS_SUCCESS) ||
-		(hapd->conf->sae_pwe == 1 &&
+		(sae_pwe == 1 &&
 		 status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT) ||
-		(hapd->conf->sae_pwe == 2 &&
+		(sae_pwe == 2 &&
 		 (status_code == WLAN_STATUS_SUCCESS ||
 		  status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT));
 }
@@ -1103,7 +1193,7 @@
 		wpa_printf(MSG_DEBUG, "SAE: TESTING - reflection attack");
 		pos = mgmt->u.auth.variable;
 		end = ((const u8 *) mgmt) + len;
-		send_auth_reply(hapd, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
+		send_auth_reply(hapd, sta, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
 				auth_transaction, resp, pos, end - pos,
 				"auth-sae-reflection-attack");
 		goto remove_sta;
@@ -1111,7 +1201,7 @@
 
 	if (hapd->conf->sae_commit_override && auth_transaction == 1) {
 		wpa_printf(MSG_DEBUG, "SAE: TESTING - commit override");
-		send_auth_reply(hapd, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
+		send_auth_reply(hapd, sta, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
 				auth_transaction, resp,
 				wpabuf_head(hapd->conf->sae_commit_override),
 				wpabuf_len(hapd->conf->sae_commit_override),
@@ -1286,11 +1376,17 @@
 		}
 
 		if (!token && use_sae_anti_clogging(hapd) && !allow_reuse) {
+			int h2e = 0;
+
 			wpa_printf(MSG_DEBUG,
 				   "SAE: Request anti-clogging token from "
 				   MACSTR, MAC2STR(sta->addr));
+			if (sta->sae->tmp)
+				h2e = sta->sae->tmp->h2e;
+			if (status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT)
+				h2e = 1;
 			data = auth_build_token_req(hapd, sta->sae->group,
-						    sta->addr);
+						    sta->addr, h2e);
 			resp = WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ;
 			if (hapd->conf->mesh & MESH_ENABLED)
 				sae_set_state(sta, SAE_NOTHING,
@@ -1365,7 +1461,7 @@
 			data = wpabuf_alloc_copy(pos, 2);
 
 		sae_sme_send_external_auth_status(hapd, sta, resp);
-		send_auth_reply(hapd, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
+		send_auth_reply(hapd, sta, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
 				auth_transaction, resp,
 				data ? wpabuf_head(data) : (u8 *) "",
 				data ? wpabuf_len(data) : 0, "auth-sae");
@@ -1515,27 +1611,37 @@
 #endif /* CONFIG_SAE */
 
 
-static u16 wpa_res_to_status_code(int res)
+static u16 wpa_res_to_status_code(enum wpa_validate_result res)
 {
-	if (res == WPA_INVALID_GROUP)
-		return WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
-	if (res == WPA_INVALID_PAIRWISE)
-		return WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
-	if (res == WPA_INVALID_AKMP)
-		return WLAN_STATUS_AKMP_NOT_VALID;
-	if (res == WPA_ALLOC_FAIL)
-		return WLAN_STATUS_UNSPECIFIED_FAILURE;
-	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;
-	if (res == WPA_INVALID_MDIE)
-		return WLAN_STATUS_INVALID_MDIE;
-	if (res == WPA_INVALID_PMKID)
-		return WLAN_STATUS_INVALID_PMKID;
-	if (res != WPA_IE_OK)
+	switch (res) {
+	case WPA_IE_OK:
+		return WLAN_STATUS_SUCCESS;
+	case WPA_INVALID_IE:
 		return WLAN_STATUS_INVALID_IE;
-	return WLAN_STATUS_SUCCESS;
+	case WPA_INVALID_GROUP:
+		return WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
+	case WPA_INVALID_PAIRWISE:
+		return WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
+	case WPA_INVALID_AKMP:
+		return WLAN_STATUS_AKMP_NOT_VALID;
+	case WPA_NOT_ENABLED:
+		return WLAN_STATUS_INVALID_IE;
+	case WPA_ALLOC_FAIL:
+		return WLAN_STATUS_UNSPECIFIED_FAILURE;
+	case WPA_MGMT_FRAME_PROTECTION_VIOLATION:
+		return WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION;
+	case WPA_INVALID_MGMT_GROUP_CIPHER:
+		return WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
+	case WPA_INVALID_MDIE:
+		return WLAN_STATUS_INVALID_MDIE;
+	case WPA_INVALID_PROTO:
+		return WLAN_STATUS_INVALID_IE;
+	case WPA_INVALID_PMKID:
+		return WLAN_STATUS_INVALID_PMKID;
+	case WPA_DENIED_OTHER_REASON:
+		return WLAN_STATUS_ASSOC_DENIED_UNSPEC;
+	}
+	return WLAN_STATUS_INVALID_IE;
 }
 
 
@@ -1555,7 +1661,7 @@
 	u16 resp = WLAN_STATUS_SUCCESS;
 	const u8 *end;
 	struct ieee802_11_elems elems;
-	int res;
+	enum wpa_validate_result res;
 	struct wpa_ie_data rsn;
 	struct rsn_pmksa_cache_entry *pmksa = NULL;
 
@@ -1731,11 +1837,11 @@
 		    FILS_SESSION_LEN);
 	os_memcpy(sta->fils_session, elems.fils_session, FILS_SESSION_LEN);
 
-	/* FILS Wrapped Data */
-	if (elems.fils_wrapped_data) {
+	/* Wrapped Data */
+	if (elems.wrapped_data) {
 		wpa_hexdump(MSG_DEBUG, "FILS: Wrapped Data",
-			    elems.fils_wrapped_data,
-			    elems.fils_wrapped_data_len);
+			    elems.wrapped_data,
+			    elems.wrapped_data_len);
 		if (!pmksa) {
 #ifndef CONFIG_NO_RADIUS
 			if (!sta->eapol_sm) {
@@ -1745,8 +1851,8 @@
 			wpa_printf(MSG_DEBUG,
 				   "FILS: Forward EAP-Initiate/Re-auth to authentication server");
 			ieee802_1x_encapsulate_radius(
-				hapd, sta, elems.fils_wrapped_data,
-				elems.fils_wrapped_data_len);
+				hapd, sta, elems.wrapped_data,
+				elems.wrapped_data_len);
 			sta->fils_pending_cb = cb;
 			wpa_printf(MSG_DEBUG,
 				   "FILS: Will send Authentication frame once the response from authentication server is available");
@@ -1755,8 +1861,8 @@
 			 * to maintain a copy of the EAP-Initiate/Reauth
 			 * message. */
 			if (fils_pmkid_erp(wpa_auth_sta_key_mgmt(sta->wpa_sm),
-					   elems.fils_wrapped_data,
-					   elems.fils_wrapped_data_len,
+					   elems.wrapped_data,
+					   elems.wrapped_data_len,
 					   sta->fils_erp_pmkid) == 0)
 				sta->fils_erp_pmkid_set = 1;
 			return;
@@ -1899,12 +2005,12 @@
 	wpabuf_put_u8(data, WLAN_EID_EXT_FILS_SESSION);
 	wpabuf_put_data(data, sta->fils_session, FILS_SESSION_LEN);
 
-	/* FILS Wrapped Data */
+	/* Wrapped Data */
 	if (!pmksa && erp_resp) {
 		wpabuf_put_u8(data, WLAN_EID_EXTENSION); /* Element ID */
 		wpabuf_put_u8(data, 1 + wpabuf_len(erp_resp)); /* Length */
 		/* Element ID Extension */
-		wpabuf_put_u8(data, WLAN_EID_EXT_FILS_WRAPPED_DATA);
+		wpabuf_put_u8(data, WLAN_EID_EXT_WRAPPED_DATA);
 		wpabuf_put_buf(data, erp_resp);
 
 		if (fils_rmsk_to_pmk(wpa_auth_sta_key_mgmt(sta->wpa_sm),
@@ -2006,7 +2112,7 @@
 	auth_alg = (pub ||
 		    resp == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) ?
 		WLAN_AUTH_FILS_SK_PFS : WLAN_AUTH_FILS_SK;
-	send_auth_reply(hapd, sta->addr, hapd->own_addr, auth_alg, 2, resp,
+	send_auth_reply(hapd, sta, sta->addr, hapd->own_addr, auth_alg, 2, resp,
 			data ? wpabuf_head(data) : (u8 *) "",
 			data ? wpabuf_len(data) : 0, "auth-fils-finish");
 	wpabuf_free(data);
@@ -2050,28 +2156,18 @@
 #endif /* CONFIG_FILS */
 
 
-int
-ieee802_11_allowed_address(struct hostapd_data *hapd, const u8 *addr,
-			   const u8 *msg, size_t len, u32 *session_timeout,
-			   u32 *acct_interim_interval,
-			   struct vlan_description *vlan_id,
-			   struct hostapd_sta_wpa_psk_short **psk,
-			   char **identity, char **radius_cui, int is_probe_req)
+static int ieee802_11_allowed_address(struct hostapd_data *hapd, const u8 *addr,
+				      const u8 *msg, size_t len,
+				      struct radius_sta *info)
 {
 	int res;
 
-	os_memset(vlan_id, 0, sizeof(*vlan_id));
-	res = hostapd_allowed_address(hapd, addr, msg, len,
-				      session_timeout, acct_interim_interval,
-				      vlan_id, psk, identity, radius_cui,
-				      is_probe_req);
+	res = hostapd_allowed_address(hapd, addr, msg, len, info, 0);
 
 	if (res == HOSTAPD_ACL_REJECT) {
-		if (!is_probe_req)
-			wpa_printf(MSG_DEBUG,
-				   "Station " MACSTR
-				   " not allowed to authenticate",
-				   MAC2STR(addr));
+		wpa_printf(MSG_DEBUG, "Station " MACSTR
+			   " not allowed to authenticate",
+			   MAC2STR(addr));
 		return HOSTAPD_ACL_REJECT;
 	}
 
@@ -2091,12 +2187,15 @@
 
 static int
 ieee802_11_set_radius_info(struct hostapd_data *hapd, struct sta_info *sta,
-			   int res, u32 session_timeout,
-			   u32 acct_interim_interval,
-			   struct vlan_description *vlan_id,
-			   struct hostapd_sta_wpa_psk_short **psk,
-			   char **identity, char **radius_cui)
+			   int res, struct radius_sta *info)
 {
+	u32 session_timeout = info->session_timeout;
+	u32 acct_interim_interval = info->acct_interim_interval;
+	struct vlan_description *vlan_id = &info->vlan_id;
+	struct hostapd_sta_wpa_psk_short *psk = info->psk;
+	char *identity = info->identity;
+	char *radius_cui = info->radius_cui;
+
 	if (vlan_id->notempty &&
 	    !hostapd_vlan_valid(hapd->conf->vlan, vlan_id)) {
 		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
@@ -2113,20 +2212,22 @@
 			       HOSTAPD_LEVEL_INFO, "VLAN ID %d", sta->vlan_id);
 
 	hostapd_free_psk_list(sta->psk);
-	if (hapd->conf->wpa_psk_radius != PSK_RADIUS_IGNORED) {
-		sta->psk = *psk;
-		*psk = NULL;
-	} else {
+	if (hapd->conf->wpa_psk_radius != PSK_RADIUS_IGNORED)
+		hostapd_copy_psk_list(&sta->psk, psk);
+	else
 		sta->psk = NULL;
-	}
 
 	os_free(sta->identity);
-	sta->identity = *identity;
-	*identity = NULL;
+	if (identity)
+		sta->identity = os_strdup(identity);
+	else
+		sta->identity = NULL;
 
 	os_free(sta->radius_cui);
-	sta->radius_cui = *radius_cui;
-	*radius_cui = NULL;
+	if (radius_cui)
+		sta->radius_cui = os_strdup(radius_cui);
+	else
+		sta->radius_cui = NULL;
 
 	if (hapd->conf->acct_interim_interval == 0 && acct_interim_interval)
 		sta->acct_interim_interval = acct_interim_interval;
@@ -2154,14 +2255,10 @@
 	int res, reply_res;
 	u16 fc;
 	const u8 *challenge = NULL;
-	u32 session_timeout, acct_interim_interval;
-	struct vlan_description vlan_id;
-	struct hostapd_sta_wpa_psk_short *psk = NULL;
 	u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN];
 	size_t resp_ies_len = 0;
-	char *identity = NULL;
-	char *radius_cui = NULL;
 	u16 seq_ctrl;
+	struct radius_sta rad_info;
 
 	if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
 		wpa_printf(MSG_INFO, "handle_auth - too short payload (len=%lu)",
@@ -2312,10 +2409,8 @@
 		}
 	}
 
-	res = ieee802_11_allowed_address(
-		hapd, mgmt->sa, (const u8 *) mgmt, len, &session_timeout,
-		&acct_interim_interval, &vlan_id, &psk, &identity, &radius_cui,
-		0);
+	res = ieee802_11_allowed_address(hapd, mgmt->sa, (const u8 *) mgmt, len,
+					 &rad_info);
 	if (res == HOSTAPD_ACL_REJECT) {
 		wpa_msg(hapd->msg_ctx, MSG_DEBUG,
 			"Ignore Authentication frame from " MACSTR
@@ -2398,9 +2493,7 @@
 	sta->auth_rssi = rssi;
 #endif /* CONFIG_MBO */
 
-	res = ieee802_11_set_radius_info(
-		hapd, sta, res, session_timeout, acct_interim_interval,
-		&vlan_id, &psk, &identity, &radius_cui);
+	res = ieee802_11_set_radius_info(hapd, sta, res, &rad_info);
 	if (res) {
 		wpa_printf(MSG_DEBUG, "ieee802_11_set_radius_info() failed");
 		resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
@@ -2471,6 +2564,7 @@
 		sta->auth_alg = WLAN_AUTH_OPEN;
 		mlme_authenticate_indication(hapd, sta);
 		break;
+#ifdef CONFIG_WEP
 #ifndef CONFIG_NO_RC4
 	case WLAN_AUTH_SHARED_KEY:
 		resp = auth_shared_key(hapd, sta, auth_transaction, challenge,
@@ -2489,6 +2583,7 @@
 		}
 		break;
 #endif /* CONFIG_NO_RC4 */
+#endif /* CONFIG_WEP */
 #ifdef CONFIG_IEEE80211R_AP
 	case WLAN_AUTH_FT:
 		sta->auth_alg = WLAN_AUTH_FT;
@@ -2542,11 +2637,7 @@
 	}
 
  fail:
-	os_free(identity);
-	os_free(radius_cui);
-	hostapd_free_psk_list(psk);
-
-	reply_res = send_auth_reply(hapd, mgmt->sa, mgmt->bssid, auth_alg,
+	reply_res = send_auth_reply(hapd, sta, mgmt->sa, mgmt->bssid, auth_alg,
 				    auth_transaction + 1, resp, resp_ies,
 				    resp_ies_len, "handle-auth");
 
@@ -2963,7 +3054,7 @@
 	u16 status;
 	u8 *owe_buf, ie[256 * 2];
 	size_t ie_len = 0;
-	int res;
+	enum wpa_validate_result res;
 
 	if (!rsn_ie || rsn_ie_len < 2) {
 		wpa_printf(MSG_DEBUG, "OWE: No RSNE in (Re)AssocReq");
@@ -3068,7 +3159,6 @@
 	if (resp != WLAN_STATUS_SUCCESS)
 		return resp;
 
-#ifdef CONFIG_IEEE80211N
 	resp = copy_sta_ht_capab(hapd, sta, elems.ht_capabilities);
 	if (resp != WLAN_STATUS_SUCCESS)
 		return resp;
@@ -3079,7 +3169,6 @@
 			       "mandatory HT PHY - reject association");
 		return WLAN_STATUS_ASSOC_DENIED_NO_HT;
 	}
-#endif /* CONFIG_IEEE80211N */
 
 #ifdef CONFIG_IEEE80211AC
 	if (hapd->iconf->ieee80211ac) {
@@ -3176,7 +3265,8 @@
 	}
 
 	if (hapd->conf->wpa && wpa_ie) {
-		int res;
+		enum wpa_validate_result res;
+
 		wpa_ie -= 2;
 		wpa_ie_len += 2;
 		if (sta->wpa_sm == NULL)
@@ -3324,7 +3414,6 @@
 	pfs_fail:
 #endif /* CONFIG_DPP2 */
 
-#ifdef CONFIG_IEEE80211N
 		if ((sta->flags & (WLAN_STA_HT | WLAN_STA_VHT)) &&
 		    wpa_auth_get_pairwise(sta->wpa_sm) == WPA_CIPHER_TKIP) {
 			hostapd_logger(hapd, sta->addr,
@@ -3334,7 +3423,6 @@
 				       "association");
 			return WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
 		}
-#endif /* CONFIG_IEEE80211N */
 #ifdef CONFIG_HS20
 	} else if (hapd->conf->osen) {
 		if (elems.osen == NULL) {
@@ -3479,7 +3567,7 @@
 	send_len = IEEE80211_HDRLEN + sizeof(reply.u.deauth);
 	reply.u.deauth.reason_code = host_to_le16(reason_code);
 
-	if (hostapd_drv_send_mlme(hapd, &reply, send_len, 0) < 0)
+	if (hostapd_drv_send_mlme(hapd, &reply, send_len, 0, NULL, 0, 0) < 0)
 		wpa_printf(MSG_INFO, "Failed to send deauth: %s",
 			   strerror(errno));
 }
@@ -3535,10 +3623,8 @@
 		sta->ft_over_ds = 0;
 	}
 
-#ifdef CONFIG_IEEE80211N
 	if (sta->flags & WLAN_STA_HT)
 		hostapd_get_ht_capab(hapd, sta->ht_capabilities, &ht_cap);
-#endif /* CONFIG_IEEE80211N */
 #ifdef CONFIG_IEEE80211AC
 	if (sta->flags & WLAN_STA_VHT)
 		hostapd_get_vht_capab(hapd, sta->vht_capabilities, &vht_cap);
@@ -3586,7 +3672,8 @@
 
 static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
 			   const u8 *addr, u16 status_code, int reassoc,
-			   const u8 *ies, size_t ies_len, int rssi)
+			   const u8 *ies, size_t ies_len, int rssi,
+			   int omit_rsnxe)
 {
 	int send_len;
 	u8 *buf;
@@ -3637,6 +3724,9 @@
 	/* Extended supported rates */
 	p = hostapd_eid_ext_supp_rates(hapd, p);
 
+	/* Radio measurement capabilities */
+	p = hostapd_eid_rm_enabled_capab(hapd, p, buf + buflen - p);
+
 #ifdef CONFIG_MBO
 	if (status_code == WLAN_STATUS_DENIED_POOR_CHANNEL_CONDITIONS &&
 	    rssi != 0) {
@@ -3653,7 +3743,8 @@
 		 * Transition Information, RSN, [RIC Response] */
 		p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, p,
 						buf + buflen - p,
-						sta->auth_alg, ies, ies_len);
+						sta->auth_alg, ies, ies_len,
+						omit_rsnxe);
 		if (!p) {
 			wpa_printf(MSG_DEBUG,
 				   "FT: Failed to write AssocResp IEs");
@@ -3683,10 +3774,8 @@
 	if (sta && status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY)
 		p = hostapd_eid_assoc_comeback_time(hapd, sta, p);
 
-#ifdef CONFIG_IEEE80211N
 	p = hostapd_eid_ht_capabilities(hapd, p);
 	p = hostapd_eid_ht_operation(hapd, p);
-#endif /* CONFIG_IEEE80211N */
 
 #ifdef CONFIG_IEEE80211AC
 	if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac &&
@@ -3734,7 +3823,23 @@
 	}
 #endif /* CONFIG_FST */
 
-	p = hostapd_eid_rsnxe(hapd, p, buf + buflen - p);
+#ifdef CONFIG_TESTING_OPTIONS
+	if (hapd->conf->rsnxe_override_ft &&
+	    buf + buflen - p >=
+	    (long int) wpabuf_len(hapd->conf->rsnxe_override_ft) &&
+	    sta && sta->auth_alg == WLAN_AUTH_FT) {
+		wpa_printf(MSG_DEBUG, "TESTING: RSNXE FT override");
+		os_memcpy(p, wpabuf_head(hapd->conf->rsnxe_override_ft),
+			  wpabuf_len(hapd->conf->rsnxe_override_ft));
+		p += wpabuf_len(hapd->conf->rsnxe_override_ft);
+		goto rsnxe_done;
+	}
+#endif /* CONFIG_TESTING_OPTIONS */
+	if (!omit_rsnxe)
+		p = hostapd_eid_rsnxe(hapd, p, buf + buflen - p);
+#ifdef CONFIG_TESTING_OPTIONS
+rsnxe_done:
+#endif /* CONFIG_TESTING_OPTIONS */
 
 #ifdef CONFIG_OWE
 	if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) &&
@@ -3865,7 +3970,7 @@
 	}
 #endif /* CONFIG_FILS */
 
-	if (hostapd_drv_send_mlme(hapd, reply, send_len, 0) < 0) {
+	if (hostapd_drv_send_mlme(hapd, reply, send_len, 0, NULL, 0, 0) < 0) {
 		wpa_printf(MSG_INFO, "Failed to send assoc resp: %s",
 			   strerror(errno));
 		res = WLAN_STATUS_UNSPECIFIED_FAILURE;
@@ -3880,12 +3985,12 @@
 #ifdef CONFIG_OWE
 u8 * owe_assoc_req_process(struct hostapd_data *hapd, struct sta_info *sta,
 			   const u8 *owe_dh, u8 owe_dh_len,
-			   u8 *owe_buf, size_t owe_buf_len, u16 *reason)
+			   u8 *owe_buf, size_t owe_buf_len, u16 *status)
 {
 #ifdef CONFIG_TESTING_OPTIONS
 	if (hapd->conf->own_ie_override) {
 		wpa_printf(MSG_DEBUG, "OWE: Using IE override");
-		*reason = WLAN_STATUS_SUCCESS;
+		*status = WLAN_STATUS_SUCCESS;
 		return wpa_auth_write_assoc_resp_owe(sta->wpa_sm, owe_buf,
 						     owe_buf_len, NULL, 0);
 	}
@@ -3895,18 +4000,18 @@
 		wpa_printf(MSG_DEBUG, "OWE: Using PMKSA caching");
 		owe_buf = wpa_auth_write_assoc_resp_owe(sta->wpa_sm, owe_buf,
 							owe_buf_len, NULL, 0);
-		*reason = WLAN_STATUS_SUCCESS;
+		*status = WLAN_STATUS_SUCCESS;
 		return owe_buf;
 	}
 
 	if (sta->owe_pmk && sta->external_dh_updated) {
 		wpa_printf(MSG_DEBUG, "OWE: Using previously derived PMK");
-		*reason = WLAN_STATUS_SUCCESS;
+		*status = WLAN_STATUS_SUCCESS;
 		return owe_buf;
 	}
 
-	*reason = owe_process_assoc_req(hapd, sta, owe_dh, owe_dh_len);
-	if (*reason != WLAN_STATUS_SUCCESS)
+	*status = owe_process_assoc_req(hapd, sta, owe_dh, owe_dh_len);
+	if (*status != WLAN_STATUS_SUCCESS)
 		return NULL;
 
 	owe_buf = wpa_auth_write_assoc_resp_owe(sta->wpa_sm, owe_buf,
@@ -3917,7 +4022,7 @@
 
 		pub = crypto_ecdh_get_pubkey(sta->owe_ecdh, 0);
 		if (!pub) {
-			*reason = WLAN_STATUS_UNSPECIFIED_FAILURE;
+			*status = WLAN_STATUS_UNSPECIFIED_FAILURE;
 			return owe_buf;
 		}
 
@@ -3952,7 +4057,7 @@
 	reply_res = send_assoc_resp(hapd, sta, sta->addr, WLAN_STATUS_SUCCESS,
 				    sta->fils_pending_assoc_is_reassoc,
 				    sta->fils_pending_assoc_req,
-				    sta->fils_pending_assoc_req_len, 0);
+				    sta->fils_pending_assoc_req_len, 0, 0);
 	os_free(sta->fils_pending_assoc_req);
 	sta->fils_pending_assoc_req = NULL;
 	sta->fils_pending_assoc_req_len = 0;
@@ -3997,12 +4102,10 @@
 	int left, i;
 	struct sta_info *sta;
 	u8 *tmp = NULL;
-	struct hostapd_sta_wpa_psk_short *psk = NULL;
-	char *identity = NULL;
-	char *radius_cui = NULL;
 #ifdef CONFIG_FILS
 	int delay_assoc = 0;
 #endif /* CONFIG_FILS */
+	int omit_rsnxe = 0;
 
 	if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_req) :
 				      sizeof(mgmt->u.assoc_req))) {
@@ -4079,13 +4182,11 @@
 		    hapd->iface->current_mode->mode ==
 			HOSTAPD_MODE_IEEE80211AD) {
 			int acl_res;
-			u32 session_timeout, acct_interim_interval;
-			struct vlan_description vlan_id;
+			struct radius_sta info;
 
-			acl_res = ieee802_11_allowed_address(
-				hapd, mgmt->sa, (const u8 *) mgmt, len,
-				&session_timeout, &acct_interim_interval,
-				&vlan_id, &psk, &identity, &radius_cui, 0);
+			acl_res = ieee802_11_allowed_address(hapd, mgmt->sa,
+							     (const u8 *) mgmt,
+							     len, &info);
 			if (acl_res == HOSTAPD_ACL_REJECT) {
 				wpa_msg(hapd->msg_ctx, MSG_DEBUG,
 					"Ignore Association Request frame from "
@@ -4110,9 +4211,7 @@
 			}
 
 			acl_res = ieee802_11_set_radius_info(
-				hapd, sta, acl_res, session_timeout,
-				acct_interim_interval, &vlan_id, &psk,
-				&identity, &radius_cui);
+				hapd, sta, acl_res, &info);
 			if (acl_res) {
 				resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
 				goto fail;
@@ -4219,6 +4318,7 @@
 	resp = check_assoc_ies(hapd, sta, pos, left, reassoc);
 	if (resp != WLAN_STATUS_SUCCESS)
 		goto fail;
+	omit_rsnxe = !get_ie(pos, left, WLAN_EID_RSNX);
 
 	if (hostapd_get_aid(hapd, sta) < 0) {
 		hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
@@ -4271,9 +4371,7 @@
 			ieee802_11_set_beacons(hapd->iface);
 	}
 
-#ifdef CONFIG_IEEE80211N
 	update_ht_state(hapd, sta);
-#endif /* CONFIG_IEEE80211N */
 
 	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
 		       HOSTAPD_LEVEL_DEBUG,
@@ -4313,9 +4411,6 @@
 #endif /* CONFIG_FILS */
 
  fail:
-	os_free(identity);
-	os_free(radius_cui);
-	hostapd_free_psk_list(psk);
 
 	/*
 	 * In case of a successful response, add the station to the driver.
@@ -4377,7 +4472,7 @@
 #endif /* CONFIG_FILS */
 
 	reply_res = send_assoc_resp(hapd, sta, mgmt->sa, resp, reassoc, pos,
-				    left, rssi);
+				    left, rssi, omit_rsnxe);
 	os_free(tmp);
 
 	/*
@@ -4418,6 +4513,7 @@
 	ap_sta_set_authorized(hapd, sta, 0);
 	sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
 	sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK);
+	hostapd_set_sta_flags(hapd, sta);
 	wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
 	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
 		       HOSTAPD_LEVEL_INFO, "disassociated");
@@ -4484,6 +4580,7 @@
 	sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
 	sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC |
 			WLAN_STA_ASSOC_REQ_OK);
+	hostapd_set_sta_flags(hapd, sta);
 	wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
 	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
 		       HOSTAPD_LEVEL_DEBUG, "deauthenticated");
@@ -4615,14 +4712,12 @@
 #endif /* CONFIG_FST */
 	case WLAN_ACTION_PUBLIC:
 	case WLAN_ACTION_PROTECTED_DUAL:
-#ifdef CONFIG_IEEE80211N
 		if (len >= IEEE80211_HDRLEN + 2 &&
 		    mgmt->u.action.u.public_action.action ==
 		    WLAN_PA_20_40_BSS_COEX) {
 			hostapd_2040_coex_action(hapd, mgmt, len);
 			return 1;
 		}
-#endif /* CONFIG_IEEE80211N */
 #ifdef CONFIG_DPP
 		if (len >= IEEE80211_HDRLEN + 6 &&
 		    mgmt->u.action.u.vs_public_action.action ==
@@ -4705,7 +4800,7 @@
 		os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
 		resp->u.action.category |= 0x80;
 
-		if (hostapd_drv_send_mlme(hapd, resp, len, 0) < 0) {
+		if (hostapd_drv_send_mlme(hapd, resp, len, 0, NULL, 0, 0) < 0) {
 			wpa_printf(MSG_ERROR, "IEEE 802.11: Failed to send "
 				   "Action frame");
 		}
@@ -4903,6 +4998,7 @@
 				       struct sta_info *sta,
 				       char *ifname_wds)
 {
+#ifdef CONFIG_WEP
 	int i;
 	struct hostapd_ssid *ssid = &hapd->conf->ssid;
 
@@ -4912,14 +5008,18 @@
 	for (i = 0; i < 4; i++) {
 		if (ssid->wep.key[i] &&
 		    hostapd_drv_set_key(ifname_wds, hapd, WPA_ALG_WEP, NULL, i,
-					i == ssid->wep.idx, NULL, 0,
-					ssid->wep.key[i], ssid->wep.len[i])) {
+					0, i == ssid->wep.idx, NULL, 0,
+					ssid->wep.key[i], ssid->wep.len[i],
+					i == ssid->wep.idx ?
+					KEY_FLAG_GROUP_RX_TX_DEFAULT :
+					KEY_FLAG_GROUP_RX_TX)) {
 			wpa_printf(MSG_WARNING,
 				   "Could not set WEP keys for WDS interface; %s",
 				   ifname_wds);
 			break;
 		}
 	}
+#endif /* CONFIG_WEP */
 }
 
 
diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
index f592da5..c7bdb4b 100644
--- a/src/ap/ieee802_11.h
+++ b/src/ap/ieee802_11.h
@@ -16,8 +16,7 @@
 struct ieee80211_ht_capabilities;
 struct ieee80211_vht_capabilities;
 struct ieee80211_mgmt;
-struct vlan_description;
-struct hostapd_sta_wpa_psk_short;
+struct radius_sta;
 enum ieee80211_op_mode;
 
 int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
@@ -50,9 +49,10 @@
 u8 * hostapd_eid_qos_map_set(struct hostapd_data *hapd, u8 *eid);
 u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid);
 u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid);
+u8 * hostapd_eid_rm_enabled_capab(struct hostapd_data *hapd, u8 *eid,
+				  size_t len);
 u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid);
 u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid);
-u8 * hostapd_eid_secondary_channel(struct hostapd_data *hapd, u8 *eid);
 u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid, u32 nsts);
 u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid);
 u8 * hostapd_eid_vendor_vht(struct hostapd_data *hapd, u8 *eid);
@@ -95,6 +95,8 @@
 u16 copy_sta_he_capab(struct hostapd_data *hapd, struct sta_info *sta,
 		      enum ieee80211_op_mode opmode, const u8 *he_capab,
 		      size_t he_capab_len);
+int hostapd_get_he_twt_responder(struct hostapd_data *hapd,
+				 enum ieee80211_op_mode mode);
 void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
 		       const u8 *buf, size_t len, int ack);
 void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst,
@@ -162,7 +164,7 @@
 				 const u8 *msk, size_t msk_len);
 u8 * owe_assoc_req_process(struct hostapd_data *hapd, struct sta_info *sta,
 			   const u8 *owe_dh, u8 owe_dh_len,
-			   u8 *owe_buf, size_t owe_buf_len, u16 *reason);
+			   u8 *owe_buf, size_t owe_buf_len, u16 *status);
 u16 owe_process_rsn_ie(struct hostapd_data *hapd, struct sta_info *sta,
 		       const u8 *rsn_ie, size_t rsn_ie_len,
 		       const u8 *owe_dh, size_t owe_dh_len);
@@ -180,13 +182,9 @@
 
 size_t hostapd_eid_owe_trans_len(struct hostapd_data *hapd);
 u8 * hostapd_eid_owe_trans(struct hostapd_data *hapd, u8 *eid, size_t len);
-int ieee802_11_allowed_address(struct hostapd_data *hapd, const u8 *addr,
-			       const u8 *msg, size_t len, u32 *session_timeout,
-			       u32 *acct_interim_interval,
-			       struct vlan_description *vlan_id,
-			       struct hostapd_sta_wpa_psk_short **psk,
-			       char **identity, char **radius_cui,
-			       int is_probe_req);
+
+size_t hostapd_eid_dpp_cc_len(struct hostapd_data *hapd);
+u8 * hostapd_eid_dpp_cc(struct hostapd_data *hapd, u8 *eid, size_t len);
 
 int get_tx_parameters(struct sta_info *sta, int ap_max_chanwidth,
 		      int ap_seg1_idx, int *bandwidth, int *seg1_idx);
diff --git a/src/ap/ieee802_11_auth.c b/src/ap/ieee802_11_auth.c
index 931d4d0..783ee6d 100644
--- a/src/ap/ieee802_11_auth.c
+++ b/src/ap/ieee802_11_auth.c
@@ -32,12 +32,7 @@
 	macaddr addr;
 	int accepted; /* HOSTAPD_ACL_* */
 	struct hostapd_cached_radius_acl *next;
-	u32 session_timeout;
-	u32 acct_interim_interval;
-	struct vlan_description vlan_id;
-	struct hostapd_sta_wpa_psk_short *psk;
-	char *identity;
-	char *radius_cui;
+	struct radius_sta info;
 };
 
 
@@ -54,9 +49,9 @@
 #ifndef CONFIG_NO_RADIUS
 static void hostapd_acl_cache_free_entry(struct hostapd_cached_radius_acl *e)
 {
-	os_free(e->identity);
-	os_free(e->radius_cui);
-	hostapd_free_psk_list(e->psk);
+	os_free(e->info.identity);
+	os_free(e->info.radius_cui);
+	hostapd_free_psk_list(e->info.psk);
 	os_free(e);
 }
 
@@ -73,25 +68,8 @@
 }
 
 
-static void copy_psk_list(struct hostapd_sta_wpa_psk_short **psk,
-			  struct hostapd_sta_wpa_psk_short *src)
-{
-	if (!psk)
-		return;
-
-	if (src)
-		src->ref++;
-
-	*psk = src;
-}
-
-
 static int hostapd_acl_cache_get(struct hostapd_data *hapd, const u8 *addr,
-				 u32 *session_timeout,
-				 u32 *acct_interim_interval,
-				 struct vlan_description *vlan_id,
-				 struct hostapd_sta_wpa_psk_short **psk,
-				 char **identity, char **radius_cui)
+				 struct radius_sta *out)
 {
 	struct hostapd_cached_radius_acl *entry;
 	struct os_reltime now;
@@ -105,27 +83,8 @@
 		if (os_reltime_expired(&now, &entry->timestamp,
 				       RADIUS_ACL_TIMEOUT))
 			return -1; /* entry has expired */
-		if (entry->accepted == HOSTAPD_ACL_ACCEPT_TIMEOUT)
-			if (session_timeout)
-				*session_timeout = entry->session_timeout;
-		if (acct_interim_interval)
-			*acct_interim_interval =
-				entry->acct_interim_interval;
-		if (vlan_id)
-			*vlan_id = entry->vlan_id;
-		copy_psk_list(psk, entry->psk);
-		if (identity) {
-			if (entry->identity)
-				*identity = os_strdup(entry->identity);
-			else
-				*identity = NULL;
-		}
-		if (radius_cui) {
-			if (entry->radius_cui)
-				*radius_cui = os_strdup(entry->radius_cui);
-			else
-				*radius_cui = NULL;
-		}
+		*out = entry->info;
+
 		return entry->accepted;
 	}
 
@@ -238,42 +197,28 @@
  * @addr: MAC address of the STA
  * @msg: Authentication message
  * @len: Length of msg in octets
- * @session_timeout: Buffer for returning session timeout (from RADIUS)
- * @acct_interim_interval: Buffer for returning account interval (from RADIUS)
- * @vlan_id: Buffer for returning VLAN ID
- * @psk: Linked list buffer for returning WPA PSK
- * @identity: Buffer for returning identity (from RADIUS)
- * @radius_cui: Buffer for returning CUI (from RADIUS)
+ * @out.session_timeout: Buffer for returning session timeout (from RADIUS)
+ * @out.acct_interim_interval: Buffer for returning account interval (from
+ *	RADIUS)
+ * @out.vlan_id: Buffer for returning VLAN ID
+ * @out.psk: Linked list buffer for returning WPA PSK
+ * @out.identity: Buffer for returning identity (from RADIUS)
+ * @out.radius_cui: Buffer for returning CUI (from RADIUS)
  * @is_probe_req: Whether this query for a Probe Request frame
  * Returns: HOSTAPD_ACL_ACCEPT, HOSTAPD_ACL_REJECT, or HOSTAPD_ACL_PENDING
  *
- * The caller is responsible for freeing the returned *identity and *radius_cui
- * values with os_free().
+ * The caller is responsible for properly cloning the returned out->identity and
+ * out->radius_cui and out->psk values.
  */
 int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
-			    const u8 *msg, size_t len, u32 *session_timeout,
-			    u32 *acct_interim_interval,
-			    struct vlan_description *vlan_id,
-			    struct hostapd_sta_wpa_psk_short **psk,
-			    char **identity, char **radius_cui,
+			    const u8 *msg, size_t len, struct radius_sta *out,
 			    int is_probe_req)
 {
 	int res;
 
-	if (session_timeout)
-		*session_timeout = 0;
-	if (acct_interim_interval)
-		*acct_interim_interval = 0;
-	if (vlan_id)
-		os_memset(vlan_id, 0, sizeof(*vlan_id));
-	if (psk)
-		*psk = NULL;
-	if (identity)
-		*identity = NULL;
-	if (radius_cui)
-		*radius_cui = NULL;
+	os_memset(out, 0, sizeof(*out));
 
-	res = hostapd_check_acl(hapd, addr, vlan_id);
+	res = hostapd_check_acl(hapd, addr, &out->vlan_id);
 	if (res != HOSTAPD_ACL_PENDING)
 		return res;
 
@@ -290,12 +235,10 @@
 		};
 
 		if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_DISABLED)
-			vlan_id = NULL;
+			os_memset(&out->vlan_id, 0, sizeof(out->vlan_id));
 
 		/* Check whether ACL cache has an entry for this station */
-		res = hostapd_acl_cache_get(hapd, addr, session_timeout,
-					    acct_interim_interval, vlan_id, psk,
-					    identity, radius_cui);
+		res = hostapd_acl_cache_get(hapd, addr, out);
 		if (res == HOSTAPD_ACL_ACCEPT ||
 		    res == HOSTAPD_ACL_ACCEPT_TIMEOUT)
 			return res;
@@ -307,14 +250,6 @@
 			if (os_memcmp(query->addr, addr, ETH_ALEN) == 0) {
 				/* pending query in RADIUS retransmit queue;
 				 * do not generate a new one */
-				if (identity) {
-					os_free(*identity);
-					*identity = NULL;
-				}
-				if (radius_cui) {
-					os_free(*radius_cui);
-					*radius_cui = NULL;
-				}
 				return HOSTAPD_ACL_PENDING;
 			}
 			query = query->next;
@@ -488,8 +423,8 @@
 					  passphraselen);
 				psk->is_passphrase = 1;
 			}
-			psk->next = cache->psk;
-			cache->psk = psk;
+			psk->next = cache->info.psk;
+			cache->info.psk = psk;
 			psk = NULL;
 		}
 skip:
@@ -518,6 +453,7 @@
 	struct hostapd_data *hapd = data;
 	struct hostapd_acl_query_data *query, *prev;
 	struct hostapd_cached_radius_acl *cache;
+	struct radius_sta *info;
 	struct radius_hdr *hdr = radius_msg_get_hdr(msg);
 
 	query = hapd->acl_queries;
@@ -555,65 +491,66 @@
 	}
 	os_get_reltime(&cache->timestamp);
 	os_memcpy(cache->addr, query->addr, sizeof(cache->addr));
+	info = &cache->info;
 	if (hdr->code == RADIUS_CODE_ACCESS_ACCEPT) {
 		u8 *buf;
 		size_t len;
 
 		if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_SESSION_TIMEOUT,
-					      &cache->session_timeout) == 0)
+					      &info->session_timeout) == 0)
 			cache->accepted = HOSTAPD_ACL_ACCEPT_TIMEOUT;
 		else
 			cache->accepted = HOSTAPD_ACL_ACCEPT;
 
 		if (radius_msg_get_attr_int32(
 			    msg, RADIUS_ATTR_ACCT_INTERIM_INTERVAL,
-			    &cache->acct_interim_interval) == 0 &&
-		    cache->acct_interim_interval < 60) {
+			    &info->acct_interim_interval) == 0 &&
+		    info->acct_interim_interval < 60) {
 			wpa_printf(MSG_DEBUG, "Ignored too small "
 				   "Acct-Interim-Interval %d for STA " MACSTR,
-				   cache->acct_interim_interval,
+				   info->acct_interim_interval,
 				   MAC2STR(query->addr));
-			cache->acct_interim_interval = 0;
+			info->acct_interim_interval = 0;
 		}
 
 		if (hapd->conf->ssid.dynamic_vlan != DYNAMIC_VLAN_DISABLED)
-			cache->vlan_id.notempty = !!radius_msg_get_vlanid(
-				msg, &cache->vlan_id.untagged,
-				MAX_NUM_TAGGED_VLAN, cache->vlan_id.tagged);
+			info->vlan_id.notempty = !!radius_msg_get_vlanid(
+				msg, &info->vlan_id.untagged,
+				MAX_NUM_TAGGED_VLAN, info->vlan_id.tagged);
 
 		decode_tunnel_passwords(hapd, shared_secret, shared_secret_len,
 					msg, req, cache);
 
 		if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_USER_NAME,
 					    &buf, &len, NULL) == 0) {
-			cache->identity = os_zalloc(len + 1);
-			if (cache->identity)
-				os_memcpy(cache->identity, buf, len);
+			info->identity = os_zalloc(len + 1);
+			if (info->identity)
+				os_memcpy(info->identity, buf, len);
 		}
 		if (radius_msg_get_attr_ptr(
 			    msg, RADIUS_ATTR_CHARGEABLE_USER_IDENTITY,
 			    &buf, &len, NULL) == 0) {
-			cache->radius_cui = os_zalloc(len + 1);
-			if (cache->radius_cui)
-				os_memcpy(cache->radius_cui, buf, len);
+			info->radius_cui = os_zalloc(len + 1);
+			if (info->radius_cui)
+				os_memcpy(info->radius_cui, buf, len);
 		}
 
 		if (hapd->conf->wpa_psk_radius == PSK_RADIUS_REQUIRED &&
-		    !cache->psk)
+		    !info->psk)
 			cache->accepted = HOSTAPD_ACL_REJECT;
 
-		if (cache->vlan_id.notempty &&
-		    !hostapd_vlan_valid(hapd->conf->vlan, &cache->vlan_id)) {
+		if (info->vlan_id.notempty &&
+		    !hostapd_vlan_valid(hapd->conf->vlan, &info->vlan_id)) {
 			hostapd_logger(hapd, query->addr,
 				       HOSTAPD_MODULE_RADIUS,
 				       HOSTAPD_LEVEL_INFO,
 				       "Invalid VLAN %d%s received from RADIUS server",
-				       cache->vlan_id.untagged,
-				       cache->vlan_id.tagged[0] ? "+" : "");
-			os_memset(&cache->vlan_id, 0, sizeof(cache->vlan_id));
+				       info->vlan_id.untagged,
+				       info->vlan_id.tagged[0] ? "+" : "");
+			os_memset(&info->vlan_id, 0, sizeof(info->vlan_id));
 		}
 		if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_REQUIRED &&
-		    !cache->vlan_id.notempty)
+		    !info->vlan_id.notempty)
 			cache->accepted = HOSTAPD_ACL_REJECT;
 	} else
 		cache->accepted = HOSTAPD_ACL_REJECT;
@@ -622,7 +559,7 @@
 
 #ifdef CONFIG_DRIVER_RADIUS_ACL
 	hostapd_drv_set_radius_acl_auth(hapd, query->addr, cache->accepted,
-					cache->session_timeout);
+					info->session_timeout);
 #else /* CONFIG_DRIVER_RADIUS_ACL */
 #ifdef NEED_AP_MLME
 	/* Re-send original authentication frame for 802.11 processing */
@@ -685,6 +622,19 @@
 }
 
 
+void hostapd_copy_psk_list(struct hostapd_sta_wpa_psk_short **psk,
+			   struct hostapd_sta_wpa_psk_short *src)
+{
+	if (!psk)
+		return;
+
+	if (src)
+		src->ref++;
+
+	*psk = src;
+}
+
+
 void hostapd_free_psk_list(struct hostapd_sta_wpa_psk_short *psk)
 {
 	if (psk && psk->ref) {
diff --git a/src/ap/ieee802_11_auth.h b/src/ap/ieee802_11_auth.h
index 5aece51..9410f55 100644
--- a/src/ap/ieee802_11_auth.h
+++ b/src/ap/ieee802_11_auth.h
@@ -16,18 +16,25 @@
 	HOSTAPD_ACL_ACCEPT_TIMEOUT = 3
 };
 
+struct radius_sta {
+	u32 session_timeout;
+	u32 acct_interim_interval;
+	struct vlan_description vlan_id;
+	struct hostapd_sta_wpa_psk_short *psk;
+	char *identity;
+	char *radius_cui;
+};
+
 int hostapd_check_acl(struct hostapd_data *hapd, const u8 *addr,
 		      struct vlan_description *vlan_id);
 int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
-			    const u8 *msg, size_t len, u32 *session_timeout,
-			    u32 *acct_interim_interval,
-			    struct vlan_description *vlan_id,
-			    struct hostapd_sta_wpa_psk_short **psk,
-			    char **identity, char **radius_cui,
+			    const u8 *msg, size_t len, struct radius_sta *out,
 			    int is_probe_req);
 int hostapd_acl_init(struct hostapd_data *hapd);
 void hostapd_acl_deinit(struct hostapd_data *hapd);
 void hostapd_free_psk_list(struct hostapd_sta_wpa_psk_short *psk);
 void hostapd_acl_expire(struct hostapd_data *hapd);
+void hostapd_copy_psk_list(struct hostapd_sta_wpa_psk_short **psk,
+			   struct hostapd_sta_wpa_psk_short *src);
 
 #endif /* IEEE802_11_AUTH_H */
diff --git a/src/ap/ieee802_11_he.c b/src/ap/ieee802_11_he.c
index abd3940..57c6b18 100644
--- a/src/ap/ieee802_11_he.c
+++ b/src/ap/ieee802_11_he.c
@@ -192,9 +192,12 @@
 		params |= (hapd->iface->conf->he_op.he_rts_threshold <<
 			   HE_OPERATION_RTS_THRESHOLD_OFFSET);
 
-	if (hapd->iface->conf->he_op.he_bss_color)
-		params |= (hapd->iface->conf->he_op.he_bss_color <<
-			   HE_OPERATION_BSS_COLOR_OFFSET);
+	if (hapd->iface->conf->he_op.he_bss_color_disabled)
+		params |= HE_OPERATION_BSS_COLOR_DISABLED;
+	if (hapd->iface->conf->he_op.he_bss_color_partial)
+		params |= HE_OPERATION_BSS_COLOR_PARTIAL;
+	params |= hapd->iface->conf->he_op.he_bss_color <<
+		HE_OPERATION_BSS_COLOR_OFFSET;
 
 	/* HE minimum required basic MCS and NSS for STAs */
 	oper->he_mcs_nss_set =
@@ -206,17 +209,25 @@
 
 	if (is_6ghz_op_class(hapd->iconf->op_class)) {
 		u8 seg0 = hostapd_get_oper_centr_freq_seg0_idx(hapd->iconf);
+		u8 seg1 = hostapd_get_oper_centr_freq_seg1_idx(hapd->iconf);
 
 		if (!seg0)
 			seg0 = hapd->iconf->channel;
 
 		params |= HE_OPERATION_6GHZ_OPER_INFO;
+
+		/* 6 GHz Operation Information field */
 		*pos++ = hapd->iconf->channel; /* Primary Channel */
-		*pos++ = center_idx_to_bw_6ghz(seg0); /* Control: Channel Width
-						       */
-		/* Channel Center Freq Seg0/Seg0 */
+
+		/* Control: Channel Width */
+		if (seg1)
+			*pos++ = 3;
+		else
+			*pos++ = center_idx_to_bw_6ghz(seg0);
+
+		/* Channel Center Freq Seg0/Seg1 */
 		*pos++ = seg0;
-		*pos++ = hostapd_get_oper_centr_freq_seg1_idx(hapd->iconf);
+		*pos++ = seg1;
 		/* Minimum Rate */
 		*pos++ = 6; /* TODO: what should be set here? */
 	}
@@ -402,3 +413,18 @@
 
 	return WLAN_STATUS_SUCCESS;
 }
+
+
+int hostapd_get_he_twt_responder(struct hostapd_data *hapd,
+				 enum ieee80211_op_mode mode)
+{
+	u8 *mac_cap;
+
+	if (!hapd->iface->current_mode ||
+	    !hapd->iface->current_mode->he_capab[mode].he_supported)
+		return 0;
+
+	mac_cap = hapd->iface->current_mode->he_capab[mode].mac_cap;
+
+	return !!(mac_cap[HE_MAC_CAPAB_0] & HE_MACCAP_TWT_RESPONDER);
+}
diff --git a/src/ap/ieee802_11_ht.c b/src/ap/ieee802_11_ht.c
index 6db9365..59ecbdc 100644
--- a/src/ap/ieee802_11_ht.c
+++ b/src/ap/ieee802_11_ht.c
@@ -109,33 +109,9 @@
 }
 
 
-u8 * hostapd_eid_secondary_channel(struct hostapd_data *hapd, u8 *eid)
-{
-	u8 sec_ch;
-
-	if (!hapd->cs_freq_params.channel ||
-	    !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)
-		sec_ch = HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW;
-	else if (hapd->cs_freq_params.sec_channel_offset == 1)
-		sec_ch = HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE;
-	else
-		return eid;
-
-	*eid++ = WLAN_EID_SECONDARY_CHANNEL_OFFSET;
-	*eid++ = 1;
-	*eid++ = sec_ch;
-
-	return eid;
-}
-
-
 /*
 op_mode
-Set to 0 (HT pure) under the followign conditions
+Set to 0 (HT pure) under the following conditions
 	- all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or
 	- all STAs in the BSS are 20 MHz HT in 20 MHz BSS
 Set to 1 (HT non-member protection) if there may be non-HT STAs
diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c
index 1e1cc38..113b4ef 100644
--- a/src/ap/ieee802_11_shared.c
+++ b/src/ap/ieee802_11_shared.c
@@ -112,7 +112,8 @@
 		end += oci_ie_len;
 	}
 #endif /* CONFIG_OCV */
-	if (hostapd_drv_send_mlme(hapd, mgmt, end - (u8 *) mgmt, 0) < 0)
+	if (hostapd_drv_send_mlme(hapd, mgmt, end - (u8 *) mgmt, 0, NULL, 0, 0)
+	    < 0)
 		wpa_printf(MSG_INFO, "ieee802_11_send_sa_query_req: send failed");
 
 	os_free(mgmt);
@@ -193,7 +194,8 @@
 		end += oci_ie_len;
 	}
 #endif /* CONFIG_OCV */
-	if (hostapd_drv_send_mlme(hapd, resp, end - (u8 *) resp, 0) < 0)
+	if (hostapd_drv_send_mlme(hapd, resp, end - (u8 *) resp, 0, NULL, 0, 0)
+	    < 0)
 		wpa_printf(MSG_INFO, "ieee80211_mgmt_sa_query_request: send failed");
 
 	os_free(resp);
@@ -375,6 +377,11 @@
 		    wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt))
 			*pos |= 0x01;
 #endif /* CONFIG_FILS */
+#ifdef CONFIG_IEEE80211AX
+		if (hapd->iconf->ieee80211ax &&
+		    hostapd_get_he_twt_responder(hapd, IEEE80211_MODE_AP))
+			*pos |= 0x40; /* Bit 78 - TWT responder */
+#endif /* CONFIG_IEEE80211AX */
 		break;
 	case 10: /* Bits 80-87 */
 #ifdef CONFIG_SAE
@@ -390,6 +397,8 @@
 					       * Identifiers Used Exclusively */
 		}
 #endif /* CONFIG_SAE */
+		if (hapd->conf->beacon_prot)
+			*pos |= 0x10; /* Bit 84 - Beacon Protection Enabled */
 		break;
 	}
 }
@@ -438,12 +447,19 @@
 	     !wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt)) && len < 10)
 		len = 10;
 #endif /* CONFIG_FILS */
+#ifdef CONFIG_IEEE80211AX
+	if (len < 10 && hapd->iconf->ieee80211ax &&
+	    hostapd_get_he_twt_responder(hapd, IEEE80211_MODE_AP))
+		len = 10;
+#endif /* CONFIG_IEEE80211AX */
 #ifdef CONFIG_SAE
 	if (len < 11 && hapd->conf->wpa &&
 	    wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
 	    hostapd_sae_pw_id_in_use(hapd->conf))
 		len = 11;
 #endif /* CONFIG_SAE */
+	if (len < 11 && hapd->conf->beacon_prot)
+		len = 11;
 	if (len < hapd->iface->extended_capa_len)
 		len = hapd->iface->extended_capa_len;
 	if (len == 0)
@@ -858,6 +874,36 @@
 }
 
 
+size_t hostapd_eid_dpp_cc_len(struct hostapd_data *hapd)
+{
+#ifdef CONFIG_DPP2
+	if (hapd->conf->dpp_configurator_connectivity)
+		return 6;
+#endif /* CONFIG_DPP2 */
+	return 0;
+}
+
+
+u8 * hostapd_eid_dpp_cc(struct hostapd_data *hapd, u8 *eid, size_t len)
+{
+#ifdef CONFIG_DPP2
+	u8 *pos = eid;
+
+	if (!hapd->conf->dpp_configurator_connectivity || len < 6)
+		return pos;
+
+	*pos++ = WLAN_EID_VENDOR_SPECIFIC;
+	*pos++ = 4;
+	WPA_PUT_BE24(pos, OUI_WFA);
+	pos += 3;
+	*pos++ = DPP_CC_OUI_TYPE;
+
+	return pos;
+#endif /* CONFIG_DPP2 */
+	return eid;
+}
+
+
 void ap_copy_sta_supp_op_classes(struct sta_info *sta,
 				 const u8 *supp_op_classes,
 				 size_t supp_op_classes_len)
@@ -1012,7 +1058,9 @@
 
 	if (!(hapd->conf->wpa & WPA_PROTO_RSN) ||
 	    !wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) ||
-	    (hapd->conf->sae_pwe != 1 && hapd->conf->sae_pwe != 2) ||
+	    (hapd->conf->sae_pwe != 1 && hapd->conf->sae_pwe != 2 &&
+	     !hostapd_sae_pw_id_in_use(hapd->conf)) ||
+	    hapd->conf->sae_pwe == 3 ||
 	    len < 3)
 		return pos;
 
diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c
index d081031..6d4d435 100644
--- a/src/ap/ieee802_1x.c
+++ b/src/ap/ieee802_1x.c
@@ -137,6 +137,7 @@
 }
 
 
+#ifdef CONFIG_WEP
 #ifndef CONFIG_FIPS
 #ifndef CONFIG_NO_RC4
 
@@ -284,8 +285,9 @@
 		/* TODO: set encryption in TX callback, i.e., only after STA
 		 * has ACKed EAPOL-Key frame */
 		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)) {
+					sta->addr, 0, 0, 1, NULL, 0, ikey,
+					hapd->conf->individual_wep_key_len,
+					KEY_FLAG_PAIRWISE_RX_TX)) {
 			wpa_printf(MSG_ERROR,
 				   "Could not set individual WEP encryption");
 		}
@@ -296,6 +298,7 @@
 
 #endif /* CONFIG_NO_RC4 */
 #endif /* CONFIG_FIPS */
+#endif /* CONFIG_WEP */
 
 
 const char *radius_mode_txt(struct hostapd_data *hapd)
@@ -2113,6 +2116,8 @@
 }
 
 
+#ifdef CONFIG_WEP
+
 static int ieee802_1x_rekey_broadcast(struct hostapd_data *hapd)
 {
 	struct eapol_authenticator *eapol = hapd->eapol_auth;
@@ -2177,9 +2182,10 @@
 	 * after new broadcast key has been sent to all stations. */
 	if (hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_WEP,
 				broadcast_ether_addr,
-				eapol->default_wep_key_idx, 1, NULL, 0,
+				eapol->default_wep_key_idx, 0, 1, NULL, 0,
 				eapol->default_wep_key,
-				hapd->conf->default_wep_key_len)) {
+				hapd->conf->default_wep_key_len,
+				KEY_FLAG_GROUP_RX_TX_DEFAULT)) {
 		hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE8021X,
 			       HOSTAPD_LEVEL_WARNING,
 			       "failed to configure a new broadcast key");
@@ -2196,6 +2202,8 @@
 	}
 }
 
+#endif /* CONFIG_WEP */
+
 
 static void ieee802_1x_eapol_send(void *ctx, void *sta_ctx, u8 type,
 				  const u8 *data, size_t datalen)
@@ -2359,6 +2367,7 @@
 }
 
 
+#ifdef CONFIG_WEP
 static void _ieee802_1x_tx_key(void *ctx, void *sta_ctx)
 {
 #ifndef CONFIG_FIPS
@@ -2370,6 +2379,7 @@
 #endif /* CONFIG_NO_RC4 */
 #endif /* CONFIG_FIPS */
 }
+#endif /* CONFIG_WEP */
 
 
 static void ieee802_1x_eapol_event(void *ctx, void *sta_ctx,
@@ -2420,7 +2430,6 @@
 
 int ieee802_1x_init(struct hostapd_data *hapd)
 {
-	int i;
 	struct eapol_auth_config conf;
 	struct eapol_auth_cb cb;
 
@@ -2431,7 +2440,9 @@
 	conf.ctx = hapd;
 	conf.eap_reauth_period = hapd->conf->eap_reauth_period;
 	conf.wpa = hapd->conf->wpa;
+#ifdef CONFIG_WEP
 	conf.individual_wep_key_len = hapd->conf->individual_wep_key_len;
+#endif /* CONFIG_WEP */
 	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;
@@ -2446,7 +2457,9 @@
 	cb.logger = ieee802_1x_logger;
 	cb.set_port_authorized = ieee802_1x_set_port_authorized;
 	cb.abort_auth = _ieee802_1x_abort_auth;
+#ifdef CONFIG_WEP
 	cb.tx_key = _ieee802_1x_tx_key;
+#endif /* CONFIG_WEP */
 	cb.eapol_event = ieee802_1x_eapol_event;
 #ifdef CONFIG_ERP
 	cb.erp_get_key = ieee802_1x_erp_get_key;
@@ -2467,17 +2480,21 @@
 		return -1;
 #endif /* CONFIG_NO_RADIUS */
 
+#ifdef CONFIG_WEP
 	if (hapd->conf->default_wep_key_len) {
+		int i;
+
 		for (i = 0; i < 4; i++)
 			hostapd_drv_set_key(hapd->conf->iface, hapd,
-					    WPA_ALG_NONE, NULL, i, 0, NULL, 0,
-					    NULL, 0);
+					    WPA_ALG_NONE, NULL, i, 0, 0, NULL,
+					    0, NULL, 0, KEY_FLAG_GROUP);
 
 		ieee802_1x_rekey(hapd, NULL);
 
 		if (!hapd->eapol_auth->default_wep_key)
 			return -1;
 	}
+#endif /* CONFIG_WEP */
 
 	return 0;
 }
@@ -2497,7 +2514,9 @@
 
 void ieee802_1x_deinit(struct hostapd_data *hapd)
 {
+#ifdef CONFIG_WEP
 	eloop_cancel_timeout(ieee802_1x_rekey, hapd, NULL);
+#endif /* CONFIG_WEP */
 
 	if (hapd->driver && hapd->drv_priv &&
 	    (hapd->conf->ieee802_1x || hapd->conf->wpa))
diff --git a/src/ap/neighbor_db.c b/src/ap/neighbor_db.c
index 4012ae4..01bf886 100644
--- a/src/ap/neighbor_db.c
+++ b/src/ap/neighbor_db.c
@@ -256,6 +256,8 @@
 		/* VHT bit added in IEEE P802.11-REVmc/D4.3 */
 		if (vht)
 			bssid_info |= NEI_REP_BSSID_INFO_VHT;
+		if (he)
+			bssid_info |= NEI_REP_BSSID_INFO_HE;
 	}
 
 	/* TODO: Set NEI_REP_BSSID_INFO_MOBILITY_DOMAIN if MDE is set */
diff --git a/src/ap/pmksa_cache_auth.c b/src/ap/pmksa_cache_auth.c
index 15e2c49..fe5f817 100644
--- a/src/ap/pmksa_cache_auth.c
+++ b/src/ap/pmksa_cache_auth.c
@@ -516,6 +516,11 @@
 	for (entry = pmksa->pmksa; entry; entry = entry->next) {
 		if (os_memcmp(entry->spa, spa, ETH_ALEN) != 0)
 			continue;
+		if (wpa_key_mgmt_sae(entry->akmp)) {
+			if (os_memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0)
+				return entry;
+			continue;
+		}
 		rsn_pmkid(entry->pmk, entry->pmk_len, aa, spa, new_pmkid,
 			  entry->akmp);
 		if (os_memcmp(new_pmkid, pmkid, PMKID_LEN) == 0)
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index cbb8752..903be28 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -164,6 +164,7 @@
 
 	/* just in case */
 	ap_sta_set_authorized(hapd, sta, 0);
+	hostapd_set_sta_flags(hapd, sta);
 
 	if (sta->flags & (WLAN_STA_WDS | WLAN_STA_MULTI_AP))
 		hostapd_set_wds_sta(hapd, NULL, sta->addr, sta->aid, 0);
@@ -233,9 +234,7 @@
 	sta->assoc_ie_taxonomy = NULL;
 #endif /* CONFIG_TAXONOMY */
 
-#ifdef CONFIG_IEEE80211N
 	ht40_intolerant_remove(hapd->iface, sta);
-#endif /* CONFIG_IEEE80211N */
 
 #ifdef CONFIG_P2P
 	if (sta->no_p2p_set) {
@@ -246,10 +245,10 @@
 	}
 #endif /* CONFIG_P2P */
 
-#if defined(NEED_AP_MLME) && defined(CONFIG_IEEE80211N)
+#ifdef NEED_AP_MLME
 	if (hostapd_ht_operation_update(hapd->iface) > 0)
 		set_beacon++;
-#endif /* NEED_AP_MLME && CONFIG_IEEE80211N */
+#endif /* NEED_AP_MLME */
 
 #ifdef CONFIG_MESH
 	if (hapd->mesh_sta_free_cb)
@@ -373,6 +372,10 @@
 
 	os_free(sta->ifname_wds);
 
+#ifdef CONFIG_TESTING_OPTIONS
+	os_free(sta->sae_postponed_commit);
+#endif /* CONFIG_TESTING_OPTIONS */
+
 	os_free(sta);
 }
 
@@ -542,6 +545,7 @@
 	case STA_DISASSOC_FROM_CLI:
 		ap_sta_set_authorized(hapd, sta, 0);
 		sta->flags &= ~WLAN_STA_ASSOC;
+		hostapd_set_sta_flags(hapd, sta);
 		ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
 		if (!sta->acct_terminate_cause)
 			sta->acct_terminate_cause =
@@ -586,7 +590,8 @@
 
 	wpa_printf(MSG_DEBUG, "%s: Session timer for STA " MACSTR,
 		   hapd->conf->iface, MAC2STR(sta->addr));
-	if (!(sta->flags & WLAN_STA_AUTH)) {
+	if (!(sta->flags & (WLAN_STA_AUTH | WLAN_STA_ASSOC |
+			    WLAN_STA_AUTHORIZED))) {
 		if (sta->flags & WLAN_STA_GAS) {
 			wpa_printf(MSG_DEBUG, "GAS: Remove temporary STA "
 				   "entry " MACSTR, MAC2STR(sta->addr));
@@ -809,6 +814,7 @@
 		sta->timeout_next = STA_DEAUTH;
 	}
 	ap_sta_set_authorized(hapd, sta, 0);
+	hostapd_set_sta_flags(hapd, sta);
 	wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout "
 		   "for " MACSTR " (%d seconds - "
 		   "AP_MAX_INACTIVITY_AFTER_DISASSOC)",
@@ -859,6 +865,7 @@
 	sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
 	sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK);
 	ap_sta_set_authorized(hapd, sta, 0);
+	hostapd_set_sta_flags(hapd, sta);
 	sta->timeout_next = STA_REMOVE;
 	wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout "
 		   "for " MACSTR " (%d seconds - "
@@ -1024,6 +1031,13 @@
 	int ret;
 	int old_vlanid = sta->vlan_id_bound;
 
+	if ((sta->flags & WLAN_STA_WDS) && sta->vlan_id == 0) {
+		wpa_printf(MSG_DEBUG,
+			   "Do not override WDS VLAN assignment for STA "
+			   MACSTR, MAC2STR(sta->addr));
+		return 0;
+	}
+
 	iface = hapd->conf->iface;
 	if (hapd->conf->ssid.vlan[0])
 		iface = hapd->conf->ssid.vlan;
@@ -1045,7 +1059,8 @@
 	if (sta->vlan_id == old_vlanid)
 		goto skip_counting;
 
-	if (sta->vlan_id > 0 && vlan == NULL) {
+	if (sta->vlan_id > 0 && !vlan &&
+	    !(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_VLAN_OFFLOAD)) {
 		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
 			       HOSTAPD_LEVEL_DEBUG, "could not find VLAN for "
 			       "binding station to (vlan_id=%d)",
@@ -1129,6 +1144,8 @@
 	if (sta->sa_query_count > 0 &&
 	    ap_check_sa_query_timeout(hapd, sta))
 		return;
+	if (sta->sa_query_count >= 1000)
+		return;
 
 	nbuf = os_realloc_array(sta->sa_query_trans_id,
 				sta->sa_query_count + 1,
@@ -1316,9 +1333,10 @@
 	if (sta == NULL)
 		return;
 	ap_sta_set_authorized(hapd, sta, 0);
+	sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
+	hostapd_set_sta_flags(hapd, sta);
 	wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
 	ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
-	sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
 	wpa_printf(MSG_DEBUG, "%s: %s: reschedule ap_handle_timer timeout "
 		   "for " MACSTR " (%d seconds - "
 		   "AP_MAX_INACTIVITY_AFTER_DEAUTH)",
diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
index de806b4..8ff6ac6 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -276,6 +276,8 @@
 	int last_tk_key_idx;
 	u8 last_tk[WPA_TK_MAX_LEN];
 	size_t last_tk_len;
+	u8 *sae_postponed_commit;
+	size_t sae_postponed_commit_len;
 #endif /* CONFIG_TESTING_OPTIONS */
 #ifdef CONFIG_AIRTIME_POLICY
 	unsigned int airtime_weight;
diff --git a/src/ap/utils.c b/src/ap/utils.c
index fcb371b..bedad6e 100644
--- a/src/ap/utils.c
+++ b/src/ap/utils.c
@@ -56,6 +56,10 @@
 		ohapd = iface->bss[j];
 		if (ohapd == data->hapd)
 			continue;
+#ifdef CONFIG_TESTING_OPTIONS
+		if (ohapd->conf->skip_prune_assoc)
+			continue;
+#endif /* CONFIG_TESTING_OPTIONS */
 #ifdef CONFIG_FST
 		/* Don't prune STAs belong to same FST */
 		if (ohapd->iface->fst &&
diff --git a/src/ap/vlan_init.c b/src/ap/vlan_init.c
index e293a00..53eacfb 100644
--- a/src/ap/vlan_init.c
+++ b/src/ap/vlan_init.c
@@ -22,7 +22,9 @@
 static int vlan_if_add(struct hostapd_data *hapd, struct hostapd_vlan *vlan,
 		       int existsok)
 {
-	int ret, i;
+	int ret;
+#ifdef CONFIG_WEP
+	int i;
 
 	for (i = 0; i < NUM_WEP_KEYS; i++) {
 		if (!hapd->conf->ssid.wep.key[i])
@@ -32,6 +34,7 @@
 			   vlan->ifname);
 		return -1;
 	}
+#endif /* CONFIG_WEP */
 
 	if (!iface_exists(vlan->ifname))
 		ret = hostapd_vlan_if_add(hapd, vlan->ifname);
diff --git a/src/ap/wmm.c b/src/ap/wmm.c
index 9f52dee..9ebb01e 100644
--- a/src/ap/wmm.c
+++ b/src/ap/wmm.c
@@ -111,9 +111,11 @@
 	u8 *pos = eid;
 	struct wmm_parameter_element *wmm =
 		(struct wmm_parameter_element *) (pos + 2);
-	struct hostapd_wmm_ac_params wmmp[WMM_AC_NUM] = { 0 };
+	struct hostapd_wmm_ac_params wmmp[WMM_AC_NUM];
 	int e;
 
+	os_memset(wmmp, 0, sizeof(wmmp));
+
 	if (!hapd->conf->wmm_enabled)
 		return eid;
 	wmm_calc_regulatory_limit(hapd, wmmp);
@@ -209,7 +211,7 @@
 	os_memcpy(t, tspec, sizeof(struct wmm_tspec_element));
 	len = ((u8 *) (t + 1)) - buf;
 
-	if (hostapd_drv_send_mlme(hapd, m, len, 0) < 0)
+	if (hostapd_drv_send_mlme(hapd, m, len, 0, NULL, 0, 0) < 0)
 		wpa_printf(MSG_INFO, "wmm_send_action: send failed");
 }
 
diff --git a/src/ap/wnm_ap.c b/src/ap/wnm_ap.c
index e4dcfe9..67281b3 100644
--- a/src/ap/wnm_ap.c
+++ b/src/ap/wnm_ap.c
@@ -54,6 +54,7 @@
 	size_t len;
 	size_t gtk_elem_len = 0;
 	size_t igtk_elem_len = 0;
+	size_t bigtk_elem_len = 0;
 	struct wnm_sleep_element wnmsleep_ie;
 	u8 *wnmtfs_ie, *oci_ie;
 	u8 wnmsleep_ie_len, oci_ie_len;
@@ -122,8 +123,10 @@
 
 #define MAX_GTK_SUBELEM_LEN 45
 #define MAX_IGTK_SUBELEM_LEN 26
+#define MAX_BIGTK_SUBELEM_LEN 26
 	mgmt = os_zalloc(sizeof(*mgmt) + wnmsleep_ie_len +
 			 MAX_GTK_SUBELEM_LEN + MAX_IGTK_SUBELEM_LEN +
+			 MAX_BIGTK_SUBELEM_LEN +
 			 oci_ie_len);
 	if (mgmt == NULL) {
 		wpa_printf(MSG_DEBUG, "MLME: Failed to allocate buffer for "
@@ -157,10 +160,19 @@
 		pos += igtk_elem_len;
 		wpa_printf(MSG_DEBUG, "Pass 4 igtk_len = %d",
 			   (int) igtk_elem_len);
+		if (hapd->conf->beacon_prot) {
+			res = wpa_wnmsleep_bigtk_subelem(sta->wpa_sm, pos);
+			if (res < 0)
+				goto fail;
+			bigtk_elem_len = res;
+			pos += bigtk_elem_len;
+			wpa_printf(MSG_DEBUG, "Pass 4 bigtk_len = %d",
+				   (int) bigtk_elem_len);
+		}
 
 		WPA_PUT_LE16((u8 *)
 			     &mgmt->u.action.u.wnm_sleep_resp.keydata_len,
-			     gtk_elem_len + igtk_elem_len);
+			     gtk_elem_len + igtk_elem_len + bigtk_elem_len);
 	}
 	os_memcpy(pos, &wnmsleep_ie, wnmsleep_ie_len);
 	/* copy TFS IE here */
@@ -176,7 +188,8 @@
 #endif /* CONFIG_OCV */
 
 	len = 1 + sizeof(mgmt->u.action.u.wnm_sleep_resp) + gtk_elem_len +
-		igtk_elem_len + wnmsleep_ie_len + wnmtfs_ie_len + oci_ie_len;
+		igtk_elem_len + bigtk_elem_len +
+		wnmsleep_ie_len + wnmtfs_ie_len + oci_ie_len;
 
 	/* In driver, response frame should be forced to sent when STA is in
 	 * PS mode */
@@ -189,8 +202,8 @@
 
 		/* when entering wnmsleep
 		 * 1. pause the node in driver
-		 * 2. mark the node so that AP won't update GTK/IGTK during
-		 * WNM Sleep
+		 * 2. mark the node so that AP won't update GTK/IGTK/BIGTK
+		 * during WNM Sleep
 		 */
 		if (wnmsleep_ie.status == WNM_STATUS_SLEEP_ACCEPT &&
 		    wnmsleep_ie.action_type == WNM_SLEEP_MODE_ENTER) {
@@ -201,7 +214,7 @@
 		}
 		/* when exiting wnmsleep
 		 * 1. unmark the node
-		 * 2. start GTK/IGTK update if MFP is not used
+		 * 2. start GTK/IGTK/BIGTK update if MFP is not used
 		 * 3. unpause the node in driver
 		 */
 		if ((wnmsleep_ie.status == WNM_STATUS_SLEEP_ACCEPT ||
@@ -221,6 +234,7 @@
 
 #undef MAX_GTK_SUBELEM_LEN
 #undef MAX_IGTK_SUBELEM_LEN
+#undef MAX_BIGTK_SUBELEM_LEN
 fail:
 	os_free(wnmtfs_ie);
 	os_free(oci_ie);
@@ -508,6 +522,30 @@
 }
 
 
+static void wnm_beacon_protection_failure(struct hostapd_data *hapd,
+					  const u8 *addr)
+{
+	struct sta_info *sta;
+
+	if (!hapd->conf->beacon_prot)
+		return;
+
+	sta = ap_get_sta(hapd, addr);
+	if (!sta || !(sta->flags & WLAN_STA_AUTHORIZED)) {
+		wpa_printf(MSG_DEBUG, "Station " MACSTR
+			   " not found for received WNM-Notification Request",
+			   MAC2STR(addr));
+		return;
+	}
+
+	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
+		       HOSTAPD_LEVEL_INFO,
+		       "Beacon protection failure reported");
+	wpa_msg(hapd->msg_ctx, MSG_INFO, WPA_EVENT_UNPROT_BEACON "reporter="
+		MACSTR, MAC2STR(addr));
+}
+
+
 static void ieee802_11_rx_wnm_notification_req(struct hostapd_data *hapd,
 					       const u8 *addr, const u8 *buf,
 					       size_t len)
@@ -526,8 +564,14 @@
 		   MAC2STR(addr), dialog_token, type);
 	wpa_hexdump(MSG_MSGDUMP, "WNM: Notification Request subelements",
 		    buf, len);
-	if (type == WLAN_EID_VENDOR_SPECIFIC)
+	switch (type) {
+	case WNM_NOTIF_TYPE_BEACON_PROTECTION_FAILURE:
+		wnm_beacon_protection_failure(hapd, addr);
+		break;
+	case WNM_NOTIF_TYPE_VENDOR_SPECIFIC:
 		mbo_ap_wnm_notification_req(hapd, addr, buf, len);
+		break;
+	}
 }
 
 
@@ -641,7 +685,7 @@
 
 	wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Request frame to indicate imminent disassociation (disassoc_timer=%d) to "
 		   MACSTR, disassoc_timer, MAC2STR(sta->addr));
-	if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
+	if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0, NULL, 0, 0) < 0) {
 		wpa_printf(MSG_DEBUG, "Failed to send BSS Transition "
 			   "Management Request frame");
 		return -1;
@@ -714,7 +758,7 @@
 	os_memcpy(pos, url, url_len);
 	pos += url_len;
 
-	if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
+	if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0, NULL, 0, 0) < 0) {
 		wpa_printf(MSG_DEBUG, "Failed to send BSS Transition "
 			   "Management Request frame");
 		return -1;
@@ -790,7 +834,7 @@
 				  mbo_len);
 	}
 
-	if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
+	if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0, NULL, 0, 0) < 0) {
 		wpa_printf(MSG_DEBUG,
 			   "Failed to send BSS Transition Management Request frame");
 		os_free(buf);
@@ -834,7 +878,7 @@
 	wpa_printf(MSG_DEBUG, "WNM: Sending Collocated Interference Request to "
 		   MACSTR " (dialog_token=%u auto_report=%u timeout=%u)",
 		   MAC2STR(sta->addr), dialog_token, auto_report, timeout);
-	if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
+	if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0, NULL, 0, 0) < 0) {
 		wpa_printf(MSG_DEBUG,
 			   "WNM: Failed to send Collocated Interference Request frame");
 		return -1;
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index 6611b0e..e0ffb27 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -56,13 +56,14 @@
 				       struct wpa_group *group);
 static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
 			  const u8 *pmk, unsigned int pmk_len,
-			  struct wpa_ptk *ptk);
+			  struct wpa_ptk *ptk, int force_sha256);
 static void wpa_group_free(struct wpa_authenticator *wpa_auth,
 			   struct wpa_group *group);
 static void wpa_group_get(struct wpa_authenticator *wpa_auth,
 			  struct wpa_group *group);
 static void wpa_group_put(struct wpa_authenticator *wpa_auth,
 			  struct wpa_group *group);
+static int ieee80211w_kde_len(struct wpa_state_machine *sm);
 static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos);
 
 static const u32 eapol_key_timeout_first = 100; /* ms */
@@ -105,7 +106,7 @@
 static inline int wpa_auth_get_eapol(struct wpa_authenticator *wpa_auth,
 				     const u8 *addr, wpa_eapol_variable var)
 {
-	if (wpa_auth->cb->get_eapol == NULL)
+	if (!wpa_auth->cb->get_eapol)
 		return -1;
 	return wpa_auth->cb->get_eapol(wpa_auth->cb_ctx, addr, var);
 }
@@ -117,7 +118,7 @@
 					  const u8 *prev_psk, size_t *psk_len,
 					  int *vlan_id)
 {
-	if (wpa_auth->cb->get_psk == NULL)
+	if (!wpa_auth->cb->get_psk)
 		return NULL;
 	return wpa_auth->cb->get_psk(wpa_auth->cb_ctx, addr, p2p_dev_addr,
 				     prev_psk, psk_len, vlan_id);
@@ -127,7 +128,7 @@
 static inline int wpa_auth_get_msk(struct wpa_authenticator *wpa_auth,
 				   const u8 *addr, u8 *msk, size_t *len)
 {
-	if (wpa_auth->cb->get_msk == NULL)
+	if (!wpa_auth->cb->get_msk)
 		return -1;
 	return wpa_auth->cb->get_msk(wpa_auth->cb_ctx, addr, msk, len);
 }
@@ -136,21 +137,46 @@
 static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth,
 				   int vlan_id,
 				   enum wpa_alg alg, const u8 *addr, int idx,
-				   u8 *key, size_t key_len)
+				   u8 *key, size_t key_len,
+				   enum key_flag key_flag)
 {
-	if (wpa_auth->cb->set_key == NULL)
+	if (!wpa_auth->cb->set_key)
 		return -1;
 	return wpa_auth->cb->set_key(wpa_auth->cb_ctx, vlan_id, alg, addr, idx,
-				     key, key_len);
+				     key, key_len, key_flag);
 }
 
 
 static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth,
 				      const u8 *addr, int idx, u8 *seq)
 {
-	if (wpa_auth->cb->get_seqnum == NULL)
+	int res;
+
+	if (!wpa_auth->cb->get_seqnum)
 		return -1;
-	return wpa_auth->cb->get_seqnum(wpa_auth->cb_ctx, addr, idx, seq);
+	res = wpa_auth->cb->get_seqnum(wpa_auth->cb_ctx, addr, idx, seq);
+#ifdef CONFIG_TESTING_OPTIONS
+	if (!addr && idx < 4 && wpa_auth->conf.gtk_rsc_override_set) {
+		wpa_printf(MSG_DEBUG,
+			   "TESTING: Override GTK RSC %016llx --> %016llx",
+			   (long long unsigned) WPA_GET_LE64(seq),
+			   (long long unsigned)
+			   WPA_GET_LE64(wpa_auth->conf.gtk_rsc_override));
+		os_memcpy(seq, wpa_auth->conf.gtk_rsc_override,
+			  WPA_KEY_RSC_LEN);
+	}
+	if (!addr && idx >= 4 && idx <= 5 &&
+	    wpa_auth->conf.igtk_rsc_override_set) {
+		wpa_printf(MSG_DEBUG,
+			   "TESTING: Override IGTK RSC %016llx --> %016llx",
+			   (long long unsigned) WPA_GET_LE64(seq),
+			   (long long unsigned)
+			   WPA_GET_LE64(wpa_auth->conf.igtk_rsc_override));
+		os_memcpy(seq, wpa_auth->conf.igtk_rsc_override,
+			  WPA_KEY_RSC_LEN);
+	}
+#endif /* CONFIG_TESTING_OPTIONS */
+	return res;
 }
 
 
@@ -158,7 +184,7 @@
 wpa_auth_send_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr,
 		    const u8 *data, size_t data_len, int encrypt)
 {
-	if (wpa_auth->cb->send_eapol == NULL)
+	if (!wpa_auth->cb->send_eapol)
 		return -1;
 	return wpa_auth->cb->send_eapol(wpa_auth->cb_ctx, addr, data, data_len,
 					encrypt);
@@ -169,7 +195,7 @@
 static inline int wpa_auth_start_ampe(struct wpa_authenticator *wpa_auth,
 				      const u8 *addr)
 {
-	if (wpa_auth->cb->start_ampe == NULL)
+	if (!wpa_auth->cb->start_ampe)
 		return -1;
 	return wpa_auth->cb->start_ampe(wpa_auth->cb_ctx, addr);
 }
@@ -180,7 +206,7 @@
 			  int (*cb)(struct wpa_state_machine *sm, void *ctx),
 			  void *cb_ctx)
 {
-	if (wpa_auth->cb->for_each_sta == NULL)
+	if (!wpa_auth->cb->for_each_sta)
 		return 0;
 	return wpa_auth->cb->for_each_sta(wpa_auth->cb_ctx, cb, cb_ctx);
 }
@@ -190,7 +216,7 @@
 			   int (*cb)(struct wpa_authenticator *a, void *ctx),
 			   void *cb_ctx)
 {
-	if (wpa_auth->cb->for_each_auth == NULL)
+	if (!wpa_auth->cb->for_each_auth)
 		return 0;
 	return wpa_auth->cb->for_each_auth(wpa_auth->cb_ctx, cb, cb_ctx);
 }
@@ -199,7 +225,7 @@
 void wpa_auth_logger(struct wpa_authenticator *wpa_auth, const u8 *addr,
 		     logger_level level, const char *txt)
 {
-	if (wpa_auth->cb->logger == NULL)
+	if (!wpa_auth->cb->logger)
 		return;
 	wpa_auth->cb->logger(wpa_auth->cb_ctx, addr, level, txt);
 }
@@ -212,7 +238,7 @@
 	int maxlen;
 	va_list ap;
 
-	if (wpa_auth->cb->logger == NULL)
+	if (!wpa_auth->cb->logger)
 		return;
 
 	maxlen = os_strlen(fmt) + 100;
@@ -233,7 +259,7 @@
 static void wpa_sta_disconnect(struct wpa_authenticator *wpa_auth,
 			       const u8 *addr, u16 reason)
 {
-	if (wpa_auth->cb->disconnect == NULL)
+	if (!wpa_auth->cb->disconnect)
 		return;
 	wpa_printf(MSG_DEBUG, "wpa_sta_disconnect STA " MACSTR " (reason %u)",
 		   MAC2STR(addr), reason);
@@ -266,8 +292,8 @@
 	struct wpa_authenticator *wpa_auth = eloop_ctx;
 
 	if (random_get_bytes(wpa_auth->group->GMK, WPA_GMK_LEN)) {
-		wpa_printf(MSG_ERROR, "Failed to get random data for WPA "
-			   "initialization.");
+		wpa_printf(MSG_ERROR,
+			   "Failed to get random data for WPA initialization.");
 	} else {
 		wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "GMK rekeyd");
 		wpa_hexdump_key(MSG_DEBUG, "GMK",
@@ -391,7 +417,7 @@
 	struct wpa_group *group;
 
 	group = os_zalloc(sizeof(struct wpa_group));
-	if (group == NULL)
+	if (!group)
 		return NULL;
 
 	group->GTKAuthenticator = TRUE;
@@ -399,9 +425,8 @@
 	group->GTK_len = wpa_cipher_key_len(wpa_auth->conf.wpa_group);
 
 	if (random_pool_ready() != 1) {
-		wpa_printf(MSG_INFO, "WPA: Not enough entropy in random pool "
-			   "for secure operations - update keys later when "
-			   "the first station connects");
+		wpa_printf(MSG_INFO,
+			   "WPA: Not enough entropy in random pool for secure operations - update keys later when the first station connects");
 	}
 
 	/*
@@ -411,16 +436,16 @@
 	 * on embedded devices.
 	 */
 	if (wpa_group_init_gmk_and_counter(wpa_auth, group) < 0) {
-		wpa_printf(MSG_ERROR, "Failed to get random data for WPA "
-			   "initialization.");
+		wpa_printf(MSG_ERROR,
+			   "Failed to get random data for WPA initialization.");
 		os_free(group);
 		return NULL;
 	}
 
 	group->GInit = TRUE;
 	if (delay_init) {
-		wpa_printf(MSG_DEBUG, "WPA: Delay group state machine start "
-			   "until Beacon frames have been configured");
+		wpa_printf(MSG_DEBUG,
+			   "WPA: Delay group state machine start until Beacon frames have been configured");
 		/* Initialization is completed in wpa_init_keys(). */
 	} else {
 		wpa_group_sm_step(wpa_auth, group);
@@ -447,7 +472,7 @@
 	struct wpa_authenticator *wpa_auth;
 
 	wpa_auth = os_zalloc(sizeof(struct wpa_authenticator));
-	if (wpa_auth == NULL)
+	if (!wpa_auth)
 		return NULL;
 	os_memcpy(wpa_auth->addr, addr, ETH_ALEN);
 	os_memcpy(&wpa_auth->conf, conf, sizeof(*conf));
@@ -461,7 +486,7 @@
 	}
 
 	wpa_auth->group = wpa_group_init(wpa_auth, 0, 1);
-	if (wpa_auth->group == NULL) {
+	if (!wpa_auth->group) {
 		os_free(wpa_auth->wpa_ie);
 		os_free(wpa_auth);
 		return NULL;
@@ -469,7 +494,7 @@
 
 	wpa_auth->pmksa = pmksa_cache_auth_init(wpa_auth_pmksa_free_cb,
 						wpa_auth);
-	if (wpa_auth->pmksa == NULL) {
+	if (!wpa_auth->pmksa) {
 		wpa_printf(MSG_ERROR, "PMKSA cache initialization failed.");
 		os_free(wpa_auth->group);
 		os_free(wpa_auth->wpa_ie);
@@ -479,7 +504,7 @@
 
 #ifdef CONFIG_IEEE80211R_AP
 	wpa_auth->ft_pmk_cache = wpa_ft_pmk_cache_init();
-	if (wpa_auth->ft_pmk_cache == NULL) {
+	if (!wpa_auth->ft_pmk_cache) {
 		wpa_printf(MSG_ERROR, "FT PMK cache initialization failed.");
 		os_free(wpa_auth->group);
 		os_free(wpa_auth->wpa_ie);
@@ -518,8 +543,8 @@
 {
 	struct wpa_group *group = wpa_auth->group;
 
-	wpa_printf(MSG_DEBUG, "WPA: Start group state machine to set initial "
-		   "keys");
+	wpa_printf(MSG_DEBUG,
+		   "WPA: Start group state machine to set initial keys");
 	wpa_group_sm_step(wpa_auth, group);
 	group->GInit = FALSE;
 	wpa_group_sm_step(wpa_auth, group);
@@ -575,7 +600,8 @@
 		 struct wpa_auth_config *conf)
 {
 	struct wpa_group *group;
-	if (wpa_auth == NULL)
+
+	if (!wpa_auth)
 		return 0;
 
 	os_memcpy(&wpa_auth->conf, conf, sizeof(*conf));
@@ -609,7 +635,7 @@
 		return NULL;
 
 	sm = os_zalloc(sizeof(struct wpa_state_machine));
-	if (sm == NULL)
+	if (!sm)
 		return NULL;
 	os_memcpy(sm->addr, addr, ETH_ALEN);
 	if (p2p_dev_addr)
@@ -626,14 +652,13 @@
 int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth,
 			    struct wpa_state_machine *sm)
 {
-	if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL)
+	if (!wpa_auth || !wpa_auth->conf.wpa || !sm)
 		return -1;
 
 #ifdef CONFIG_IEEE80211R_AP
 	if (sm->ft_completed) {
 		wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
-				"FT authentication already completed - do not "
-				"start 4-way handshake");
+				"FT authentication already completed - do not start 4-way handshake");
 		/* Go to PTKINITDONE state to allow GTK rekeying */
 		sm->wpa_ptk_state = WPA_PTK_PTKINITDONE;
 		sm->Pair = TRUE;
@@ -676,7 +701,7 @@
 	/* WPA/RSN was not used - clear WPA state. This is needed if the STA
 	 * reassociates back to the same AP while the previous entry for the
 	 * STA has not yet been removed. */
-	if (sm == NULL)
+	if (!sm)
 		return;
 
 	sm->wpa_key_mgmt = 0;
@@ -688,8 +713,9 @@
 #ifdef CONFIG_P2P
 	if (WPA_GET_BE32(sm->ip_addr)) {
 		u32 start;
-		wpa_printf(MSG_DEBUG, "P2P: Free assigned IP "
-			   "address %u.%u.%u.%u from " MACSTR,
+		wpa_printf(MSG_DEBUG,
+			   "P2P: Free assigned IP address %u.%u.%u.%u from "
+			   MACSTR,
 			   sm->ip_addr[0], sm->ip_addr[1],
 			   sm->ip_addr[2], sm->ip_addr[3],
 			   MAC2STR(sm->addr));
@@ -719,31 +745,34 @@
 
 void wpa_auth_sta_deinit(struct wpa_state_machine *sm)
 {
-	if (sm == NULL)
+	struct wpa_authenticator *wpa_auth;
+
+	if (!sm)
 		return;
 
-	if (sm->wpa_auth->conf.wpa_strict_rekey && sm->has_GTK) {
-		wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
-				"strict rekeying - force GTK rekey since STA "
-				"is leaving");
+	wpa_auth = sm->wpa_auth;
+	if (wpa_auth->conf.wpa_strict_rekey && sm->has_GTK) {
+		wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
+				"strict rekeying - force GTK rekey since STA is leaving");
 		if (eloop_deplete_timeout(0, 500000, wpa_rekey_gtk,
-					  sm->wpa_auth, NULL) == -1)
-			eloop_register_timeout(0, 500000, wpa_rekey_gtk, sm->wpa_auth,
-					       NULL);
+					  wpa_auth, NULL) == -1)
+			eloop_register_timeout(0, 500000, wpa_rekey_gtk,
+					       wpa_auth, NULL);
 	}
 
-	eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm);
+	eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm);
 	sm->pending_1_of_4_timeout = 0;
 	eloop_cancel_timeout(wpa_sm_call_step, sm, NULL);
-	eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);
+	eloop_cancel_timeout(wpa_rekey_ptk, wpa_auth, sm);
 #ifdef CONFIG_IEEE80211R_AP
 	wpa_ft_sta_deinit(sm);
 #endif /* CONFIG_IEEE80211R_AP */
 	if (sm->in_step_loop) {
 		/* Must not free state machine while wpa_sm_step() is running.
 		 * Freeing will be completed in the end of wpa_sm_step(). */
-		wpa_printf(MSG_DEBUG, "WPA: Registering pending STA state "
-			   "machine deinit for " MACSTR, MAC2STR(sm->addr));
+		wpa_printf(MSG_DEBUG,
+			   "WPA: Registering pending STA state machine deinit for "
+			   MACSTR, MAC2STR(sm->addr));
 		sm->pending_deinit = 1;
 	} else
 		wpa_free_sta_sm(sm);
@@ -752,11 +781,23 @@
 
 static void wpa_request_new_ptk(struct wpa_state_machine *sm)
 {
-	if (sm == NULL)
+	if (!sm)
 		return;
 
-	sm->PTKRequest = TRUE;
-	sm->PTK_valid = 0;
+	if (!sm->use_ext_key_id && sm->wpa_auth->conf.wpa_deny_ptk0_rekey) {
+		wpa_printf(MSG_INFO,
+			   "WPA: PTK0 rekey not allowed, disconnect " MACSTR,
+			   MAC2STR(sm->addr));
+		sm->Disconnect = TRUE;
+		/* Try to encourage the STA to reconnect */
+		sm->disconnect_reason =
+			WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA;
+	} else {
+		if (sm->use_ext_key_id)
+			sm->keyidx_active ^= 1; /* flip Key ID */
+		sm->PTKRequest = TRUE;
+		sm->PTK_valid = 0;
+	}
 }
 
 
@@ -781,7 +822,7 @@
 	int i;
 	for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) {
 		if (ctr[i].valid &&
-		    (replay_counter == NULL ||
+		    (!replay_counter ||
 		     os_memcmp(replay_counter, ctr[i].counter,
 			       WPA_REPLAY_COUNTER_LEN) == 0))
 			ctr[i].valid = FALSE;
@@ -798,9 +839,9 @@
 	struct rsn_mdie *mdie;
 
 	if (wpa_parse_wpa_ie_rsn(kde->rsn_ie, kde->rsn_ie_len, &ie) < 0 ||
-	    ie.num_pmkid != 1 || ie.pmkid == NULL) {
-		wpa_printf(MSG_DEBUG, "FT: No PMKR1Name in "
-			   "FT 4-way handshake message 2/4");
+	    ie.num_pmkid != 1 || !ie.pmkid) {
+		wpa_printf(MSG_DEBUG,
+			   "FT: No PMKR1Name in FT 4-way handshake message 2/4");
 		return -1;
 	}
 
@@ -809,8 +850,9 @@
 		    sm->sup_pmk_r1_name, PMKID_LEN);
 
 	if (!kde->mdie || !kde->ftie) {
-		wpa_printf(MSG_DEBUG, "FT: No %s in FT 4-way handshake "
-			   "message 2/4", kde->mdie ? "FTIE" : "MDIE");
+		wpa_printf(MSG_DEBUG,
+			   "FT: No %s in FT 4-way handshake message 2/4",
+			   kde->mdie ? "FTIE" : "MDIE");
 		return -1;
 	}
 
@@ -844,18 +886,15 @@
 {
 	/* Supplicant reported a Michael MIC error */
 	wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
-			 "received EAPOL-Key Error Request "
-			 "(STA detected Michael MIC failure (group=%d))",
+			 "received EAPOL-Key Error Request (STA detected Michael MIC failure (group=%d))",
 			 group);
 
 	if (group && wpa_auth->conf.wpa_group != WPA_CIPHER_TKIP) {
 		wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
-				"ignore Michael MIC failure report since "
-				"group cipher is not TKIP");
+				"ignore Michael MIC failure report since group cipher is not TKIP");
 	} else if (!group && sm->pairwise != WPA_CIPHER_TKIP) {
 		wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
-				"ignore Michael MIC failure report since "
-				"pairwise cipher is not TKIP");
+				"ignore Michael MIC failure report since pairwise cipher is not TKIP");
 	} else {
 		if (wpa_auth_mic_failure_report(wpa_auth, sm->addr) > 0)
 			return 1; /* STA entry was removed */
@@ -888,7 +927,7 @@
 			pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr,
 					       sm->p2p_dev_addr, pmk, &pmk_len,
 					       &vlan_id);
-			if (pmk == NULL)
+			if (!pmk)
 				break;
 #ifdef CONFIG_IEEE80211R_AP
 			if (wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) {
@@ -901,7 +940,8 @@
 			pmk_len = sm->pmk_len;
 		}
 
-		if (wpa_derive_ptk(sm, sm->alt_SNonce, pmk, pmk_len, &PTK) < 0)
+		if (wpa_derive_ptk(sm, sm->alt_SNonce, pmk, pmk_len, &PTK, 0) <
+		    0)
 			break;
 
 		if (wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK,
@@ -956,7 +996,7 @@
 	size_t keyhdrlen, mic_len;
 	u8 *mic;
 
-	if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL)
+	if (!wpa_auth || !wpa_auth->conf.wpa || !sm)
 		return;
 	wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL data", data, data_len);
 
@@ -975,20 +1015,19 @@
 	key_data = mic + mic_len + 2;
 	key_data_length = WPA_GET_BE16(mic + mic_len);
 	wpa_printf(MSG_DEBUG, "WPA: Received EAPOL-Key from " MACSTR
-		   " key_info=0x%x type=%u mic_len=%u key_data_length=%u",
+		   " key_info=0x%x type=%u mic_len=%zu key_data_length=%u",
 		   MAC2STR(sm->addr), key_info, key->type,
-		   (unsigned int) mic_len, key_data_length);
+		   mic_len, key_data_length);
 	wpa_hexdump(MSG_MSGDUMP,
 		    "WPA: EAPOL-Key header (ending before Key MIC)",
 		    key, sizeof(*key));
 	wpa_hexdump(MSG_MSGDUMP, "WPA: EAPOL-Key Key MIC",
 		    mic, mic_len);
 	if (key_data_length > data_len - sizeof(*hdr) - keyhdrlen) {
-		wpa_printf(MSG_INFO, "WPA: Invalid EAPOL-Key frame - "
-			   "key_data overflow (%d > %lu)",
+		wpa_printf(MSG_INFO,
+			   "WPA: Invalid EAPOL-Key frame - key_data overflow (%d > %zu)",
 			   key_data_length,
-			   (unsigned long) (data_len - sizeof(*hdr) -
-					    keyhdrlen));
+			   data_len - sizeof(*hdr) - keyhdrlen);
 		return;
 	}
 
@@ -998,18 +1037,18 @@
 			 * Some deployed station implementations seem to send
 			 * msg 4/4 with incorrect type value in WPA2 mode.
 			 */
-			wpa_printf(MSG_DEBUG, "Workaround: Allow EAPOL-Key "
-				   "with unexpected WPA type in RSN mode");
+			wpa_printf(MSG_DEBUG,
+				   "Workaround: Allow EAPOL-Key with unexpected WPA type in RSN mode");
 		} else if (key->type != EAPOL_KEY_TYPE_RSN) {
-			wpa_printf(MSG_DEBUG, "Ignore EAPOL-Key with "
-				   "unexpected type %d in RSN mode",
+			wpa_printf(MSG_DEBUG,
+				   "Ignore EAPOL-Key with unexpected type %d in RSN mode",
 				   key->type);
 			return;
 		}
 	} else {
 		if (key->type != EAPOL_KEY_TYPE_WPA) {
-			wpa_printf(MSG_DEBUG, "Ignore EAPOL-Key with "
-				   "unexpected type %d in WPA mode",
+			wpa_printf(MSG_DEBUG,
+				   "Ignore EAPOL-Key with unexpected type %d in WPA mode",
 				   key->type);
 			return;
 		}
@@ -1054,9 +1093,7 @@
 			    ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
 				wpa_auth_logger(wpa_auth, sm->addr,
 						LOGGER_WARNING,
-						"advertised support for "
-						"AES-128-CMAC, but did not "
-						"use it");
+						"advertised support for AES-128-CMAC, but did not use it");
 				return;
 			}
 
@@ -1065,8 +1102,7 @@
 			    ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
 				wpa_auth_logger(wpa_auth, sm->addr,
 						LOGGER_WARNING,
-						"did not use HMAC-SHA1-AES "
-						"with CCMP/GCMP");
+						"did not use HMAC-SHA1-AES with CCMP/GCMP");
 				return;
 			}
 		}
@@ -1084,8 +1120,7 @@
 		    os_memcmp(key->replay_counter, sm->req_replay_counter,
 			      WPA_REPLAY_COUNTER_LEN) <= 0) {
 			wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING,
-					"received EAPOL-Key request with "
-					"replayed counter");
+					"received EAPOL-Key request with replayed counter");
 			return;
 		}
 	}
@@ -1108,9 +1143,7 @@
 			 * even if we have already sent out EAPOL-Key 3/4.
 			 */
 			wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
-					 "Process SNonce update from STA "
-					 "based on retransmitted EAPOL-Key "
-					 "1/4");
+					 "Process SNonce update from STA based on retransmitted EAPOL-Key 1/4");
 			sm->update_snonce = 1;
 			os_memcpy(sm->alt_SNonce, sm->SNonce, WPA_NONCE_LEN);
 			sm->alt_snonce_valid = TRUE;
@@ -1139,12 +1172,12 @@
 					     key->replay_counter) &&
 		    sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING) {
 			wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
-					 "ignore retransmitted EAPOL-Key %s - "
-					 "SNonce did not change", msgtxt);
+					 "ignore retransmitted EAPOL-Key %s - SNonce did not change",
+					 msgtxt);
 		} else {
 			wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
-					 "received EAPOL-Key %s with "
-					 "unexpected replay counter", msgtxt);
+					 "received EAPOL-Key %s with unexpected replay counter",
+					 msgtxt);
 		}
 		for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) {
 			if (!sm->key_replay[i].valid)
@@ -1175,8 +1208,7 @@
 		    (!sm->update_snonce ||
 		     sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING)) {
 			wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
-					 "received EAPOL-Key msg 2/4 in "
-					 "invalid state (%d) - dropped",
+					 "received EAPOL-Key msg 2/4 in invalid state (%d) - dropped",
 					 sm->wpa_ptk_state);
 			return;
 		}
@@ -1191,9 +1223,8 @@
 			 * Counter update and the station will be allowed to
 			 * continue.
 			 */
-			wpa_printf(MSG_DEBUG, "WPA: Reject 4-way handshake to "
-				   "collect more entropy for random number "
-				   "generation");
+			wpa_printf(MSG_DEBUG,
+				   "WPA: Reject 4-way handshake to collect more entropy for random number generation");
 			random_mark_pool_ready();
 			wpa_sta_disconnect(wpa_auth, sm->addr,
 					   WLAN_REASON_PREV_AUTH_NOT_VALID);
@@ -1204,8 +1235,7 @@
 		if (sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING ||
 		    !sm->PTK_valid) {
 			wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
-					 "received EAPOL-Key msg 4/4 in "
-					 "invalid state (%d) - dropped",
+					 "received EAPOL-Key msg 4/4 in invalid state (%d) - dropped",
 					 sm->wpa_ptk_state);
 			return;
 		}
@@ -1214,8 +1244,7 @@
 		if (sm->wpa_ptk_group_state != WPA_PTK_GROUP_REKEYNEGOTIATING
 		    || !sm->PTK_valid) {
 			wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
-					 "received EAPOL-Key msg 2/2 in "
-					 "invalid state (%d) - dropped",
+					 "received EAPOL-Key msg 2/2 in invalid state (%d) - dropped",
 					 sm->wpa_ptk_group_state);
 			return;
 		}
@@ -1294,8 +1323,7 @@
 				  WPA_REPLAY_COUNTER_LEN);
 		} else {
 			wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
-					"received EAPOL-Key request with "
-					"invalid MIC");
+					"received EAPOL-Key request with invalid MIC");
 			return;
 		}
 
@@ -1311,8 +1339,7 @@
 				return; /* STA entry was removed */
 		} else if (key_info & WPA_KEY_INFO_KEY_TYPE) {
 			wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
-					"received EAPOL-Key Request for new "
-					"4-Way Handshake");
+					"received EAPOL-Key Request for new 4-Way Handshake");
 			wpa_request_new_ptk(sm);
 		} else if (key_data_length > 0 &&
 			   wpa_parse_kde_ies(key_data, key_data_length,
@@ -1320,8 +1347,7 @@
 			   kde.mac_addr) {
 		} else {
 			wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
-					"received EAPOL-Key Request for GTK "
-					"rekeying");
+					"received EAPOL-Key Request for GTK rekeying");
 			eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL);
 			wpa_rekey_gtk(wpa_auth, NULL);
 		}
@@ -1354,7 +1380,7 @@
 
 	os_free(sm->last_rx_eapol_key);
 	sm->last_rx_eapol_key = os_memdup(data, data_len);
-	if (sm->last_rx_eapol_key == NULL)
+	if (!sm->last_rx_eapol_key)
 		return;
 	sm->last_rx_eapol_key_len = data_len;
 
@@ -1433,6 +1459,7 @@
 		      const u8 *kde, size_t kde_len,
 		      int keyidx, int encr, int force_version)
 {
+	struct wpa_auth_config *conf = &wpa_auth->conf;
 	struct ieee802_1x_hdr *hdr;
 	struct wpa_eapol_key *key;
 	size_t len, mic_len, keyhdrlen;
@@ -1461,15 +1488,14 @@
 
 	pairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE);
 
-	wpa_printf(MSG_DEBUG, "WPA: Send EAPOL(version=%d secure=%d mic=%d "
-		   "ack=%d install=%d pairwise=%d kde_len=%lu keyidx=%d "
-		   "encr=%d)",
+	wpa_printf(MSG_DEBUG,
+		   "WPA: Send EAPOL(version=%d secure=%d mic=%d ack=%d install=%d pairwise=%d kde_len=%zu keyidx=%d encr=%d)",
 		   version,
 		   (key_info & WPA_KEY_INFO_SECURE) ? 1 : 0,
 		   (key_info & WPA_KEY_INFO_MIC) ? 1 : 0,
 		   (key_info & WPA_KEY_INFO_ACK) ? 1 : 0,
 		   (key_info & WPA_KEY_INFO_INSTALL) ? 1 : 0,
-		   pairwise, (unsigned long) kde_len, keyidx, encr);
+		   pairwise, kde_len, keyidx, encr);
 
 	key_data_len = kde_len;
 
@@ -1487,9 +1513,9 @@
 		len += AES_BLOCK_SIZE;
 
 	hdr = os_zalloc(len);
-	if (hdr == NULL)
+	if (!hdr)
 		return;
-	hdr->version = wpa_auth->conf.eapol_version;
+	hdr->version = conf->eapol_version;
 	hdr->type = IEEE802_1X_TYPE_EAPOL_KEY;
 	hdr->length = host_to_be16(len  - sizeof(*hdr));
 	key = (struct wpa_eapol_key *) (hdr + 1);
@@ -1505,7 +1531,7 @@
 		key_info |= keyidx << WPA_KEY_INFO_KEY_INDEX_SHIFT;
 	WPA_PUT_BE16(key->key_info, key_info);
 
-	alg = pairwise ? sm->pairwise : wpa_auth->conf.wpa_group;
+	alg = pairwise ? sm->pairwise : conf->wpa_group;
 	if (sm->wpa == WPA_VERSION_WPA2 && !pairwise)
 		WPA_PUT_BE16(key->key_length, 0);
 	else
@@ -1559,7 +1585,7 @@
 #endif /* CONFIG_FILS */
 	} else if (encr && kde) {
 		buf = os_zalloc(key_data_len);
-		if (buf == NULL) {
+		if (!buf) {
 			os_free(hdr);
 			return;
 		}
@@ -1576,8 +1602,8 @@
 		    wpa_use_aes_key_wrap(sm->wpa_key_mgmt) ||
 		    version == WPA_KEY_INFO_TYPE_AES_128_CMAC) {
 			wpa_printf(MSG_DEBUG,
-				   "WPA: Encrypt Key Data using AES-WRAP (KEK length %u)",
-				   (unsigned int) sm->PTK.kek_len);
+				   "WPA: Encrypt Key Data using AES-WRAP (KEK length %zu)",
+				   sm->PTK.kek_len);
 			if (aes_wrap(sm->PTK.kek, sm->PTK.kek_len,
 				     (key_data_len - 8) / 8, buf, key_data)) {
 				os_free(hdr);
@@ -1611,8 +1637,7 @@
 	if (key_info & WPA_KEY_INFO_MIC) {
 		if (!sm->PTK_valid || !mic_len) {
 			wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
-					"PTK not valid when sending EAPOL-Key "
-					"frame");
+					"PTK not valid when sending EAPOL-Key frame");
 			os_free(hdr);
 			return;
 		}
@@ -1625,9 +1650,8 @@
 		}
 #ifdef CONFIG_TESTING_OPTIONS
 		if (!pairwise &&
-		    wpa_auth->conf.corrupt_gtk_rekey_mic_probability > 0.0 &&
-		    drand48() <
-		    wpa_auth->conf.corrupt_gtk_rekey_mic_probability) {
+		    conf->corrupt_gtk_rekey_mic_probability > 0.0 &&
+		    drand48() < conf->corrupt_gtk_rekey_mic_probability) {
 			wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
 					"Corrupting group EAPOL-Key Key MIC");
 			key_mic[0]++;
@@ -1635,8 +1659,7 @@
 #endif /* CONFIG_TESTING_OPTIONS */
 	}
 
-	wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_inc_EapolFramesTx,
-			   1);
+	wpa_auth_set_eapol(wpa_auth, sm->addr, WPA_EAPOL_inc_EapolFramesTx, 1);
 	wpa_auth_send_eapol(wpa_auth, sm->addr, (u8 *) hdr, len,
 			    sm->pairwise_set);
 	os_free(hdr);
@@ -1653,7 +1676,7 @@
 	int pairwise = key_info & WPA_KEY_INFO_KEY_TYPE;
 	u32 ctr;
 
-	if (sm == NULL)
+	if (!sm)
 		return;
 
 	__wpa_send_eapol(wpa_auth, sm, key_info, key_rsc, nonce, kde, kde_len,
@@ -1673,8 +1696,9 @@
 #ifdef TEST_FUZZ
 	timeout_ms = 1;
 #endif /* TEST_FUZZ */
-	wpa_printf(MSG_DEBUG, "WPA: Use EAPOL-Key timeout of %u ms (retry "
-		   "counter %u)", timeout_ms, ctr);
+	wpa_printf(MSG_DEBUG,
+		   "WPA: Use EAPOL-Key timeout of %u ms (retry counter %u)",
+		   timeout_ms, ctr);
 	eloop_register_timeout(timeout_ms / 1000, (timeout_ms % 1000) * 1000,
 			       wpa_send_eapol_timeout, wpa_auth, sm);
 }
@@ -1714,9 +1738,14 @@
 	sm->PTK_valid = FALSE;
 	os_memset(&sm->PTK, 0, sizeof(sm->PTK));
 	if (wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 0, NULL,
-			     0))
+			     0, KEY_FLAG_PAIRWISE))
 		wpa_printf(MSG_DEBUG,
 			   "RSN: PTK removal from the driver failed");
+	if (sm->use_ext_key_id &&
+	    wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 1, NULL,
+			     0, KEY_FLAG_PAIRWISE))
+		wpa_printf(MSG_DEBUG,
+			   "RSN: PTK Key ID 1 removal from the driver failed");
 	sm->pairwise_set = FALSE;
 	eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);
 }
@@ -1726,7 +1755,7 @@
 {
 	int remove_ptk = 1;
 
-	if (sm == NULL)
+	if (!sm)
 		return -1;
 
 	wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
@@ -1766,8 +1795,8 @@
 			 * sure that the WPA state machines gets initialized
 			 * properly at this point.
 			 */
-			wpa_printf(MSG_DEBUG, "WPA state machine had not been "
-				   "started - initialize now");
+			wpa_printf(MSG_DEBUG,
+				   "WPA state machine had not been started - initialize now");
 			sm->started = 1;
 			sm->Init = TRUE;
 			if (wpa_sm_step(sm) == 1)
@@ -1776,6 +1805,22 @@
 			sm->AuthenticationRequest = TRUE;
 			break;
 		}
+
+		if (!sm->use_ext_key_id &&
+		    sm->wpa_auth->conf.wpa_deny_ptk0_rekey) {
+			wpa_printf(MSG_INFO,
+				   "WPA: PTK0 rekey not allowed, disconnect "
+				   MACSTR, MAC2STR(sm->addr));
+			sm->Disconnect = TRUE;
+			/* Try to encourage the STA to reconnect */
+			sm->disconnect_reason =
+				WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA;
+			break;
+		}
+
+		if (sm->use_ext_key_id)
+			sm->keyidx_active ^= 1; /* flip Key ID */
+
 		if (sm->GUpdateStationKeys) {
 			/*
 			 * Reauthentication cancels the pending group key
@@ -1789,8 +1834,8 @@
 		break;
 	case WPA_ASSOC_FT:
 #ifdef CONFIG_IEEE80211R_AP
-		wpa_printf(MSG_DEBUG, "FT: Retry PTK configuration "
-			   "after association");
+		wpa_printf(MSG_DEBUG,
+			   "FT: Retry PTK configuration after association");
 		wpa_ft_install_ptk(sm);
 
 		/* Using FT protocol, not WPA auth state machine */
@@ -1923,11 +1968,11 @@
 	 * GMK and Counter here to improve their strength if there was not
 	 * enough entropy available immediately after system startup.
 	 */
-	wpa_printf(MSG_DEBUG, "WPA: Re-initialize GMK/Counter on first "
-		   "station");
+	wpa_printf(MSG_DEBUG,
+		   "WPA: Re-initialize GMK/Counter on first station");
 	if (random_pool_ready() != 1) {
-		wpa_printf(MSG_INFO, "WPA: Not enough entropy in random pool "
-			   "to proceed - reject first 4-way handshake");
+		wpa_printf(MSG_INFO,
+			   "WPA: Not enough entropy in random pool to proceed - reject first 4-way handshake");
 		group->reject_4way_hs_for_entropy = TRUE;
 	} else {
 		group->first_sta_seen = TRUE;
@@ -1961,8 +2006,8 @@
 	 * stronger protection against potential precomputation attacks.
 	 */
 	if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) {
-		wpa_printf(MSG_ERROR, "WPA: Failed to get random data for "
-			   "ANonce.");
+		wpa_printf(MSG_ERROR,
+			   "WPA: Failed to get random data for ANonce.");
 		sm->Disconnect = TRUE;
 		return;
 	}
@@ -2019,13 +2064,13 @@
 			pmk_len = PMK_LEN_SUITE_B_192;
 		else
 			pmk_len = PMK_LEN;
-		wpa_printf(MSG_DEBUG, "WPA: PMK from EAPOL state machine "
-			   "(MSK len=%lu PMK len=%u)", (unsigned long) len,
-			   pmk_len);
+		wpa_printf(MSG_DEBUG,
+			   "WPA: PMK from EAPOL state machine (MSK len=%zu PMK len=%u)",
+			   len, pmk_len);
 		if (len < pmk_len) {
 			wpa_printf(MSG_DEBUG,
-				   "WPA: MSK not long enough (%u) to create PMK (%u)",
-				   (unsigned int) len, (unsigned int) pmk_len);
+				   "WPA: MSK not long enough (%zu) to create PMK (%u)",
+				   len, pmk_len);
 			sm->Disconnect = TRUE;
 			return;
 		}
@@ -2208,10 +2253,11 @@
 
 static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
 			  const u8 *pmk, unsigned int pmk_len,
-			  struct wpa_ptk *ptk)
+			  struct wpa_ptk *ptk, int force_sha256)
 {
 	const u8 *z = NULL;
 	size_t z_len = 0;
+	int akmp;
 
 #ifdef CONFIG_IEEE80211R_AP
 	if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
@@ -2237,9 +2283,12 @@
 	}
 #endif /* CONFIG_DPP2 */
 
+	akmp = sm->wpa_key_mgmt;
+	if (force_sha256)
+		akmp |= WPA_KEY_MGMT_PSK_SHA256;
 	return wpa_pmk_to_ptk(pmk, pmk_len, "Pairwise key expansion",
 			      sm->wpa_auth->addr, sm->addr, sm->ANonce, snonce,
-			      ptk, sm->wpa_key_mgmt, sm->pairwise, z, z_len);
+			      ptk, akmp, sm->pairwise, z, z_len);
 }
 
 
@@ -2453,9 +2502,9 @@
 
 	if (elems.fils_key_confirm_len != sm->fils_key_auth_len) {
 		wpa_printf(MSG_DEBUG,
-			   "FILS: Unexpected Key-Auth length %d (expected %d)",
+			   "FILS: Unexpected Key-Auth length %d (expected %zu)",
 			   elems.fils_key_confirm_len,
-			   (int) sm->fils_key_auth_len);
+			   sm->fils_key_auth_len);
 		return -1;
 	}
 
@@ -2648,8 +2697,13 @@
 	u8 *gtk, dummy_gtk[32];
 	size_t gtk_len;
 	struct wpa_group *gsm;
+	size_t plain_len;
+	struct wpa_auth_config *conf = &sm->wpa_auth->conf;
 
-	plain = wpabuf_alloc(1000);
+	plain_len = 1000 + ieee80211w_kde_len(sm);
+	if (conf->transition_disable)
+		plain_len += 2 + RSN_SELECTOR_LEN + 1;
+	plain = wpabuf_alloc(plain_len);
 	if (!plain)
 		return NULL;
 
@@ -2678,8 +2732,7 @@
 	/* GTK KDE */
 	gtk = gsm->GTK[gsm->GN - 1];
 	gtk_len = gsm->GTK_len;
-	if (sm->wpa_auth->conf.disable_gtk ||
-	    sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
+	if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
 		/*
 		 * Provide unique random GTK to each STA to prevent use
 		 * of GTK in the BSS.
@@ -2697,11 +2750,18 @@
 			   gtk, gtk_len);
 	wpabuf_put(plain, tmp2 - tmp);
 
-	/* IGTK KDE */
+	/* IGTK KDE and BIGTK KDE */
 	tmp = wpabuf_put(plain, 0);
 	tmp2 = ieee80211w_kde_add(sm, tmp);
 	wpabuf_put(plain, tmp2 - tmp);
 
+	if (conf->transition_disable) {
+		tmp = wpabuf_put(plain, 0);
+		tmp2 = wpa_add_kde(tmp, WFA_KEY_DATA_TRANSITION_DISABLE,
+				   &conf->transition_disable, 1, NULL, 0);
+		wpabuf_put(plain, tmp2 - tmp);
+	}
+
 	*len = (u8 *) wpabuf_put(plain, 0) - len - 1;
 
 #ifdef CONFIG_OCV
@@ -2747,7 +2807,7 @@
 
 	wpa_printf(MSG_DEBUG, "FILS: Configure TK to the driver");
 	if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0,
-			     sm->PTK.tk, klen)) {
+			     sm->PTK.tk, klen, KEY_FLAG_PAIRWISE_RX_TX)) {
 		wpa_printf(MSG_DEBUG, "FILS: Failed to set TK to the driver");
 		return -1;
 	}
@@ -2779,8 +2839,8 @@
 	os_memcpy(pos, wpabuf_head(plain), wpabuf_len(plain));
 	pos += wpabuf_len(plain);
 
-	wpa_printf(MSG_DEBUG, "%s: plain buf_len: %u", __func__,
-		   (unsigned int) wpabuf_len(plain));
+	wpa_printf(MSG_DEBUG, "%s: plain buf_len: %zu", __func__,
+		   wpabuf_len(plain));
 	wpabuf_clear_free(plain);
 	sm->fils_completed = 1;
 	return pos;
@@ -2819,6 +2879,7 @@
 	struct wpa_eapol_key *key;
 	struct wpa_eapol_ie_parse kde;
 	int vlan_id = 0;
+	int owe_ptk_workaround = !!wpa_auth->conf.owe_ptk_workaround;
 
 	SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk);
 	sm->EAPOLKeyReceived = FALSE;
@@ -2836,7 +2897,7 @@
 			pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr,
 					       sm->p2p_dev_addr, pmk, &pmk_len,
 					       &vlan_id);
-			if (pmk == NULL)
+			if (!pmk)
 				break;
 			psk_found = 1;
 #ifdef CONFIG_IEEE80211R_AP
@@ -2856,7 +2917,8 @@
 			pmk_len = sm->pmksa->pmk_len;
 		}
 
-		if (wpa_derive_ptk(sm, sm->SNonce, pmk, pmk_len, &PTK) < 0)
+		if (wpa_derive_ptk(sm, sm->SNonce, pmk, pmk_len, &PTK,
+				   owe_ptk_workaround == 2) < 0)
 			break;
 
 		if (mic_len &&
@@ -2880,6 +2942,16 @@
 		}
 #endif /* CONFIG_FILS */
 
+#ifdef CONFIG_OWE
+		if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE && pmk_len > 32 &&
+		    owe_ptk_workaround == 1) {
+			wpa_printf(MSG_DEBUG,
+				   "OWE: Try PTK derivation workaround with SHA256");
+			owe_ptk_workaround = 2;
+			continue;
+		}
+#endif /* CONFIG_OWE */
+
 		if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
 		    wpa_key_mgmt_sae(sm->wpa_key_mgmt))
 			break;
@@ -2922,7 +2994,7 @@
 		eapol_key_ie_len = kde.wpa_ie_len;
 	}
 	ft = sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt);
-	if (sm->wpa_ie == NULL ||
+	if (!sm->wpa_ie ||
 	    wpa_compare_rsn_ie(ft, sm->wpa_ie, sm->wpa_ie_len,
 			       eapol_key_ie, eapol_key_ie_len)) {
 		wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
@@ -3016,10 +3088,9 @@
 		if (os_memcmp_const(sm->sup_pmk_r1_name, sm->pmk_r1_name,
 				    WPA_PMK_NAME_LEN) != 0) {
 			wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
-					"PMKR1Name mismatch in FT 4-way "
-					"handshake");
-			wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from "
-				    "Supplicant",
+					"PMKR1Name mismatch in FT 4-way handshake");
+			wpa_hexdump(MSG_DEBUG,
+				    "FT: PMKR1Name from Supplicant",
 				    sm->sup_pmk_r1_name, WPA_PMK_NAME_LEN);
 			wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name",
 				    sm->pmk_r1_name, WPA_PMK_NAME_LEN);
@@ -3063,22 +3134,29 @@
 
 static int ieee80211w_kde_len(struct wpa_state_machine *sm)
 {
+	size_t len = 0;
+
 	if (sm->mgmt_frame_prot) {
-		size_t len;
-		len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
-		return 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN + len;
+		len += 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN;
+		len += wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
+	}
+	if (sm->mgmt_frame_prot && sm->wpa_auth->conf.beacon_prot) {
+		len += 2 + RSN_SELECTOR_LEN + WPA_BIGTK_KDE_PREFIX_LEN;
+		len += wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
 	}
 
-	return 0;
+	return len;
 }
 
 
 static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos)
 {
 	struct wpa_igtk_kde igtk;
+	struct wpa_bigtk_kde bigtk;
 	struct wpa_group *gsm = sm->group;
 	u8 rsc[WPA_KEY_RSC_LEN];
-	size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
+	struct wpa_auth_config *conf = &sm->wpa_auth->conf;
+	size_t len = wpa_cipher_key_len(conf->group_mgmt_cipher);
 
 	if (!sm->mgmt_frame_prot)
 		return pos;
@@ -3091,8 +3169,7 @@
 	else
 		os_memcpy(igtk.pn, rsc, sizeof(igtk.pn));
 	os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], len);
-	if (sm->wpa_auth->conf.disable_gtk ||
-	    sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
+	if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
 		/*
 		 * Provide unique random IGTK to each STA to prevent use of
 		 * IGTK in the BSS.
@@ -3104,6 +3181,21 @@
 			  (const u8 *) &igtk, WPA_IGTK_KDE_PREFIX_LEN + len,
 			  NULL, 0);
 
+	if (!conf->beacon_prot)
+		return pos;
+
+	bigtk.keyid[0] = gsm->GN_bigtk;
+	bigtk.keyid[1] = 0;
+	if (gsm->wpa_group_state != WPA_GROUP_SETKEYSDONE ||
+	    wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_bigtk, rsc) < 0)
+		os_memset(bigtk.pn, 0, sizeof(bigtk.pn));
+	else
+		os_memcpy(bigtk.pn, rsc, sizeof(bigtk.pn));
+	os_memcpy(bigtk.bigtk, gsm->BIGTK[gsm->GN_bigtk - 6], len);
+	pos = wpa_add_kde(pos, RSN_KEY_DATA_BIGTK,
+			  (const u8 *) &bigtk, WPA_BIGTK_KDE_PREFIX_LEN + len,
+			  NULL, 0);
+
 	return pos;
 }
 
@@ -3138,41 +3230,73 @@
 }
 
 
+#ifdef CONFIG_TESTING_OPTIONS
+static u8 * replace_ie(const char *name, const u8 *old_buf, size_t *len, u8 eid,
+		       const u8 *ie, size_t ie_len)
+{
+	const u8 *elem;
+	u8 *buf;
+
+	wpa_printf(MSG_DEBUG, "TESTING: %s EAPOL override", name);
+	wpa_hexdump(MSG_DEBUG, "TESTING: wpa_ie before override",
+		    old_buf, *len);
+	buf = os_malloc(*len + ie_len);
+	if (!buf)
+		return NULL;
+	os_memcpy(buf, old_buf, *len);
+	elem = get_ie(buf, *len, eid);
+	if (elem) {
+		u8 elem_len = 2 + elem[1];
+
+		os_memmove((void *) elem, elem + elem_len,
+			   *len - (elem - buf) - elem_len);
+		*len -= elem_len;
+	}
+	os_memcpy(buf + *len, ie, ie_len);
+	*len += ie_len;
+	wpa_hexdump(MSG_DEBUG, "TESTING: wpa_ie after EAPOL override",
+		    buf, *len);
+
+	return buf;
+}
+#endif /* CONFIG_TESTING_OPTIONS */
+
+
 SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
 {
 	u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde = NULL, *pos, dummy_gtk[32];
-	size_t gtk_len, kde_len;
+	size_t gtk_len, kde_len, wpa_ie_len;
 	struct wpa_group *gsm = sm->group;
 	u8 *wpa_ie;
-	int wpa_ie_len, secure, gtkidx, encr = 0;
-	u8 *wpa_ie_buf = NULL;
+	int secure, gtkidx, encr = 0;
+	u8 *wpa_ie_buf = NULL, *wpa_ie_buf2 = NULL;
+	u8 hdr[2];
+	struct wpa_auth_config *conf = &sm->wpa_auth->conf;
 
 	SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk);
 	sm->TimeoutEvt = FALSE;
 
 	sm->TimeoutCtr++;
-	if (sm->wpa_auth->conf.wpa_disable_eapol_key_retries &&
-	    sm->TimeoutCtr > 1) {
+	if (conf->wpa_disable_eapol_key_retries && sm->TimeoutCtr > 1) {
 		/* Do not allow retransmission of EAPOL-Key msg 3/4 */
 		return;
 	}
-	if (sm->TimeoutCtr > sm->wpa_auth->conf.wpa_pairwise_update_count) {
+	if (sm->TimeoutCtr > conf->wpa_pairwise_update_count) {
 		/* No point in sending the EAPOL-Key - we will disconnect
 		 * immediately following this. */
 		return;
 	}
 
 	/* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE],
-	   GTK[GN], IGTK, [FTIE], [TIE * 2])
+	   GTK[GN], IGTK, [BIGTK], [FTIE], [TIE * 2])
 	 */
 	os_memset(rsc, 0, WPA_KEY_RSC_LEN);
 	wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc);
 	/* If FT is used, wpa_auth->wpa_ie includes both RSNIE and MDIE */
 	wpa_ie = sm->wpa_auth->wpa_ie;
 	wpa_ie_len = sm->wpa_auth->wpa_ie_len;
-	if (sm->wpa == WPA_VERSION_WPA &&
-	    (sm->wpa_auth->conf.wpa & WPA_PROTO_RSN) &&
-	    wpa_ie_len > wpa_ie[1] + 2 && wpa_ie[0] == WLAN_EID_RSN) {
+	if (sm->wpa == WPA_VERSION_WPA && (conf->wpa & WPA_PROTO_RSN) &&
+	    wpa_ie_len > wpa_ie[1] + 2U && wpa_ie[0] == WLAN_EID_RSN) {
 		/* WPA-only STA, remove RSN IE and possible MDIE */
 		wpa_ie = wpa_ie + wpa_ie[1] + 2;
 		if (wpa_ie[0] == WLAN_EID_MOBILITY_DOMAIN)
@@ -3180,42 +3304,45 @@
 		wpa_ie_len = wpa_ie[1] + 2;
 	}
 #ifdef CONFIG_TESTING_OPTIONS
-	if (sm->wpa_auth->conf.rsnxe_override_eapol_len) {
-		u8 *obuf = sm->wpa_auth->conf.rsnxe_override_eapol;
-		size_t olen = sm->wpa_auth->conf.rsnxe_override_eapol_len;
-		const u8 *rsnxe;
-
-		wpa_hexdump(MSG_DEBUG,
-			    "TESTING: wpa_ie before RSNXE EAPOL override",
-			    wpa_ie, wpa_ie_len);
-		wpa_ie_buf = os_malloc(wpa_ie_len + olen);
+	if (conf->rsne_override_eapol_set) {
+		wpa_ie_buf2 = replace_ie(
+			"RSNE", wpa_ie, &wpa_ie_len, WLAN_EID_RSN,
+			conf->rsne_override_eapol,
+			conf->rsne_override_eapol_len);
+		if (!wpa_ie_buf2)
+			goto done;
+		wpa_ie = wpa_ie_buf2;
+	}
+	if (conf->rsnxe_override_eapol_set) {
+		wpa_ie_buf = replace_ie(
+			"RSNXE", wpa_ie, &wpa_ie_len, WLAN_EID_RSNX,
+			conf->rsnxe_override_eapol,
+			conf->rsnxe_override_eapol_len);
 		if (!wpa_ie_buf)
-			return;
-		os_memcpy(wpa_ie_buf, wpa_ie, wpa_ie_len);
+			goto done;
 		wpa_ie = wpa_ie_buf;
-		rsnxe = get_ie(wpa_ie, wpa_ie_len, WLAN_EID_RSNX);
-		if (rsnxe) {
-			u8 rsnxe_len = 2 + rsnxe[1];
-
-			os_memmove((void *) rsnxe, rsnxe + rsnxe_len,
-				   wpa_ie_len - (rsnxe - wpa_ie) - rsnxe_len);
-			wpa_ie_len -= rsnxe_len;
-		}
-		os_memcpy(wpa_ie + wpa_ie_len, obuf, olen);
-		wpa_ie_len += olen;
-		wpa_hexdump(MSG_DEBUG,
-			    "TESTING: wpa_ie after RSNXE EAPOL override",
-			    wpa_ie, wpa_ie_len);
 	}
 #endif /* CONFIG_TESTING_OPTIONS */
 	wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
 			"sending 3/4 msg of 4-Way Handshake");
 	if (sm->wpa == WPA_VERSION_WPA2) {
+		if (sm->use_ext_key_id && sm->TimeoutCtr == 1 &&
+		    wpa_auth_set_key(sm->wpa_auth, 0,
+				     wpa_cipher_to_alg(sm->pairwise),
+				     sm->addr,
+				     sm->keyidx_active, sm->PTK.tk,
+				     wpa_cipher_key_len(sm->pairwise),
+				     KEY_FLAG_PAIRWISE_RX)) {
+			wpa_sta_disconnect(sm->wpa_auth, sm->addr,
+					   WLAN_REASON_PREV_AUTH_NOT_VALID);
+			return;
+		}
+
 		/* WPA2 send GTK in the 4-way handshake */
 		secure = 1;
 		gtk = gsm->GTK[gsm->GN - 1];
 		gtk_len = gsm->GTK_len;
-		if (sm->wpa_auth->conf.disable_gtk ||
+		if (conf->disable_gtk ||
 		    sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
 			/*
 			 * Provide unique random GTK to each STA to prevent use
@@ -3244,13 +3371,16 @@
 			 * WPA if the supplicant used it first.
 			 */
 			wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
-					"STA used Secure bit in WPA msg 2/4 - "
-					"set Secure for 3/4 as workaround");
+					"STA used Secure bit in WPA msg 2/4 - set Secure for 3/4 as workaround");
 			secure = 1;
 		}
 	}
 
 	kde_len = wpa_ie_len + ieee80211w_kde_len(sm) + ocv_oci_len(sm);
+
+	if (sm->use_ext_key_id)
+		kde_len += 2 + RSN_SELECTOR_LEN + 2;
+
 	if (gtk)
 		kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len;
 #ifdef CONFIG_IEEE80211R_AP
@@ -3263,8 +3393,12 @@
 	if (WPA_GET_BE32(sm->ip_addr) > 0)
 		kde_len += 2 + RSN_SELECTOR_LEN + 3 * 4;
 #endif /* CONFIG_P2P */
+
+	if (conf->transition_disable)
+		kde_len += 2 + RSN_SELECTOR_LEN + 1;
+
 	kde = os_malloc(kde_len);
-	if (kde == NULL)
+	if (!kde)
 		goto done;
 
 	pos = kde;
@@ -3278,18 +3412,23 @@
 		elen = pos - kde;
 		res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name);
 		if (res < 0) {
-			wpa_printf(MSG_ERROR, "FT: Failed to insert "
-				   "PMKR1Name into RSN IE in EAPOL-Key data");
+			wpa_printf(MSG_ERROR,
+				   "FT: Failed to insert PMKR1Name into RSN IE in EAPOL-Key data");
 			goto done;
 		}
 		pos -= wpa_ie_len;
 		pos += elen;
 	}
 #endif /* CONFIG_IEEE80211R_AP */
+	hdr[1] = 0;
+
+	if (sm->use_ext_key_id) {
+		hdr[0] = sm->keyidx_active & 0x01;
+		pos = wpa_add_kde(pos, RSN_KEY_DATA_KEYID, hdr, 2, NULL, 0);
+	}
+
 	if (gtk) {
-		u8 hdr[2];
 		hdr[0] = gtkidx & 0x03;
-		hdr[1] = 0;
 		pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
 				  gtk, gtk_len);
 	}
@@ -3300,9 +3439,7 @@
 #ifdef CONFIG_IEEE80211R_AP
 	if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
 		int res;
-		struct wpa_auth_config *conf;
 
-		conf = &sm->wpa_auth->conf;
 		if (sm->assoc_resp_ftie &&
 		    kde + kde_len - pos >= 2 + sm->assoc_resp_ftie[1]) {
 			os_memcpy(pos, sm->assoc_resp_ftie,
@@ -3316,11 +3453,11 @@
 					     conf->r0_key_holder_len,
 					     NULL, NULL, pos,
 					     kde + kde_len - pos,
-					     NULL, 0);
+					     NULL, 0, 0);
 		}
 		if (res < 0) {
-			wpa_printf(MSG_ERROR, "FT: Failed to insert FTIE "
-				   "into EAPOL-Key Key Data");
+			wpa_printf(MSG_ERROR,
+				   "FT: Failed to insert FTIE into EAPOL-Key Key Data");
 			goto done;
 		}
 		pos += res;
@@ -3344,13 +3481,17 @@
 	if (WPA_GET_BE32(sm->ip_addr) > 0) {
 		u8 addr[3 * 4];
 		os_memcpy(addr, sm->ip_addr, 4);
-		os_memcpy(addr + 4, sm->wpa_auth->conf.ip_addr_mask, 4);
-		os_memcpy(addr + 8, sm->wpa_auth->conf.ip_addr_go, 4);
+		os_memcpy(addr + 4, conf->ip_addr_mask, 4);
+		os_memcpy(addr + 8, conf->ip_addr_go, 4);
 		pos = wpa_add_kde(pos, WFA_KEY_DATA_IP_ADDR_ALLOC,
 				  addr, sizeof(addr), NULL, 0);
 	}
 #endif /* CONFIG_P2P */
 
+	if (conf->transition_disable)
+		pos = wpa_add_kde(pos, WFA_KEY_DATA_TRANSITION_DISABLE,
+				  &conf->transition_disable, 1, NULL, 0);
+
 	wpa_send_eapol(sm->wpa_auth, sm,
 		       (secure ? WPA_KEY_INFO_SECURE : 0) |
 		       (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
@@ -3361,6 +3502,7 @@
 done:
 	os_free(kde);
 	os_free(wpa_ie_buf);
+	os_free(wpa_ie_buf2);
 }
 
 
@@ -3371,8 +3513,17 @@
 	if (sm->Pair) {
 		enum wpa_alg alg = wpa_cipher_to_alg(sm->pairwise);
 		int klen = wpa_cipher_key_len(sm->pairwise);
-		if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0,
-				     sm->PTK.tk, klen)) {
+		int res;
+
+		if (sm->use_ext_key_id)
+			res = wpa_auth_set_key(sm->wpa_auth, 0, 0, sm->addr,
+					       sm->keyidx_active, NULL, 0,
+					       KEY_FLAG_PAIRWISE_RX_TX_MODIFY);
+		else
+			res = wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr,
+					       0, sm->PTK.tk, klen,
+					       KEY_FLAG_PAIRWISE_RX_TX);
+		if (res) {
 			wpa_sta_disconnect(sm->wpa_auth, sm->addr,
 					   WLAN_REASON_PREV_AUTH_NOT_VALID);
 			return;
@@ -3419,6 +3570,7 @@
 SM_STEP(WPA_PTK)
 {
 	struct wpa_authenticator *wpa_auth = sm->wpa_auth;
+	struct wpa_auth_config *conf = &wpa_auth->conf;
 
 	if (sm->Init)
 		SM_ENTER(WPA_PTK, INITIALIZE);
@@ -3453,7 +3605,7 @@
 		break;
 	case WPA_PTK_AUTHENTICATION2:
 		if (wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) &&
-		    wpa_auth_get_eapol(sm->wpa_auth, sm->addr,
+		    wpa_auth_get_eapol(wpa_auth, sm->addr,
 				       WPA_EAPOL_keyRun) > 0)
 			SM_ENTER(WPA_PTK, INITPMK);
 		else if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
@@ -3464,7 +3616,7 @@
 			SM_ENTER(WPA_PTK, INITPMK);
 		break;
 	case WPA_PTK_INITPMK:
-		if (wpa_auth_get_eapol(sm->wpa_auth, sm->addr,
+		if (wpa_auth_get_eapol(wpa_auth, sm->addr,
 				       WPA_EAPOL_keyAvailable) > 0) {
 			SM_ENTER(WPA_PTK, PTKSTART);
 #ifdef CONFIG_DPP
@@ -3473,13 +3625,13 @@
 #endif /* CONFIG_DPP */
 		} else {
 			wpa_auth->dot11RSNA4WayHandshakeFailures++;
-			wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO,
+			wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
 					"INITPMK - keyAvailable = false");
 			SM_ENTER(WPA_PTK, DISCONNECT);
 		}
 		break;
 	case WPA_PTK_INITPSK:
-		if (wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr,
+		if (wpa_auth_get_psk(wpa_auth, sm->addr, sm->p2p_dev_addr,
 				     NULL, NULL, NULL)) {
 			SM_ENTER(WPA_PTK, PTKSTART);
 #ifdef CONFIG_SAE
@@ -3487,7 +3639,7 @@
 			SM_ENTER(WPA_PTK, PTKSTART);
 #endif /* CONFIG_SAE */
 		} else {
-			wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO,
+			wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
 					"no PSK configured for the STA");
 			wpa_auth->dot11RSNA4WayHandshakeFailures++;
 			SM_ENTER(WPA_PTK, DISCONNECT);
@@ -3497,13 +3649,11 @@
 		if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest &&
 		    sm->EAPOLKeyPairwise)
 			SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING);
-		else if (sm->TimeoutCtr >
-			 sm->wpa_auth->conf.wpa_pairwise_update_count) {
+		else if (sm->TimeoutCtr > conf->wpa_pairwise_update_count) {
 			wpa_auth->dot11RSNA4WayHandshakeFailures++;
-			wpa_auth_vlogger(
-				sm->wpa_auth, sm->addr, LOGGER_DEBUG,
-				"PTKSTART: Retry limit %u reached",
-				sm->wpa_auth->conf.wpa_pairwise_update_count);
+			wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
+					 "PTKSTART: Retry limit %u reached",
+					 conf->wpa_pairwise_update_count);
 			SM_ENTER(WPA_PTK, DISCONNECT);
 		} else if (sm->TimeoutEvt)
 			SM_ENTER(WPA_PTK, PTKSTART);
@@ -3527,14 +3677,13 @@
 			 sm->EAPOLKeyPairwise && sm->MICVerified)
 			SM_ENTER(WPA_PTK, PTKINITDONE);
 		else if (sm->TimeoutCtr >
-			 sm->wpa_auth->conf.wpa_pairwise_update_count ||
-			 (sm->wpa_auth->conf.wpa_disable_eapol_key_retries &&
+			 conf->wpa_pairwise_update_count ||
+			 (conf->wpa_disable_eapol_key_retries &&
 			  sm->TimeoutCtr > 1)) {
 			wpa_auth->dot11RSNA4WayHandshakeFailures++;
-			wpa_auth_vlogger(
-				sm->wpa_auth, sm->addr, LOGGER_DEBUG,
-				"PTKINITNEGOTIATING: Retry limit %u reached",
-				sm->wpa_auth->conf.wpa_pairwise_update_count);
+			wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
+					 "PTKINITNEGOTIATING: Retry limit %u reached",
+					 conf->wpa_pairwise_update_count);
 			SM_ENTER(WPA_PTK, DISCONNECT);
 		} else if (sm->TimeoutEvt)
 			SM_ENTER(WPA_PTK, PTKINITNEGOTIATING);
@@ -3565,16 +3714,16 @@
 	u8 *kde_buf = NULL, *pos, hdr[2];
 	size_t kde_len;
 	u8 *gtk, dummy_gtk[32];
+	struct wpa_auth_config *conf = &sm->wpa_auth->conf;
 
 	SM_ENTRY_MA(WPA_PTK_GROUP, REKEYNEGOTIATING, wpa_ptk_group);
 
 	sm->GTimeoutCtr++;
-	if (sm->wpa_auth->conf.wpa_disable_eapol_key_retries &&
-	    sm->GTimeoutCtr > 1) {
+	if (conf->wpa_disable_eapol_key_retries && sm->GTimeoutCtr > 1) {
 		/* Do not allow retransmission of EAPOL-Key group msg 1/2 */
 		return;
 	}
-	if (sm->GTimeoutCtr > sm->wpa_auth->conf.wpa_group_update_count) {
+	if (sm->GTimeoutCtr > conf->wpa_group_update_count) {
 		/* No point in sending the EAPOL-Key - we will disconnect
 		 * immediately following this. */
 		return;
@@ -3591,8 +3740,7 @@
 			"sending 1/2 msg of Group Key Handshake");
 
 	gtk = gsm->GTK[gsm->GN - 1];
-	if (sm->wpa_auth->conf.disable_gtk ||
-	    sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
+	if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
 		/*
 		 * Provide unique random GTK to each STA to prevent use
 		 * of GTK in the BSS.
@@ -3605,7 +3753,7 @@
 		kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len +
 			ieee80211w_kde_len(sm) + ocv_oci_len(sm);
 		kde_buf = os_malloc(kde_len);
-		if (kde_buf == NULL)
+		if (!kde_buf)
 			return;
 
 		kde = pos = kde_buf;
@@ -3638,8 +3786,8 @@
 
 SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED)
 {
-#ifdef CONFIG_OCV
 	struct wpa_authenticator *wpa_auth = sm->wpa_auth;
+#ifdef CONFIG_OCV
 	const u8 *key_data, *mic;
 	struct ieee802_1x_hdr *hdr;
 	struct wpa_eapol_key *key;
@@ -3704,7 +3852,7 @@
 	sm->GUpdateStationKeys = FALSE;
 	sm->GTimeoutCtr = 0;
 	/* FIX: MLME.SetProtection.Request(TA, Tx_Rx) */
-	wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO,
+	wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
 			 "group key handshake completed (%s)",
 			 sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN");
 	sm->has_GTK = TRUE;
@@ -3761,7 +3909,9 @@
 static int wpa_gtk_update(struct wpa_authenticator *wpa_auth,
 			  struct wpa_group *group)
 {
+	struct wpa_auth_config *conf = &wpa_auth->conf;
 	int ret = 0;
+	size_t len;
 
 	os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
 	inc_byte_array(group->Counter, WPA_NONCE_LEN);
@@ -3772,9 +3922,8 @@
 	wpa_hexdump_key(MSG_DEBUG, "GTK",
 			group->GTK[group->GN - 1], group->GTK_len);
 
-	if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) {
-		size_t len;
-		len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
+	if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
+		len = wpa_cipher_key_len(conf->group_mgmt_cipher);
 		os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
 		inc_byte_array(group->Counter, WPA_NONCE_LEN);
 		if (wpa_gmk_to_gtk(group->GMK, "IGTK key expansion",
@@ -3785,6 +3934,19 @@
 				group->IGTK[group->GN_igtk - 4], len);
 	}
 
+	if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION &&
+	    conf->beacon_prot) {
+		len = wpa_cipher_key_len(conf->group_mgmt_cipher);
+		os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
+		inc_byte_array(group->Counter, WPA_NONCE_LEN);
+		if (wpa_gmk_to_gtk(group->GMK, "BIGTK key expansion",
+				   wpa_auth->addr, group->GNonce,
+				   group->BIGTK[group->GN_bigtk - 6], len) < 0)
+			ret = -1;
+		wpa_hexdump_key(MSG_DEBUG, "BIGTK",
+				group->BIGTK[group->GN_bigtk - 6], len);
+	}
+
 	return ret;
 }
 
@@ -3792,8 +3954,9 @@
 static void wpa_group_gtk_init(struct wpa_authenticator *wpa_auth,
 			       struct wpa_group *group)
 {
-	wpa_printf(MSG_DEBUG, "WPA: group state machine entering state "
-		   "GTK_INIT (VLAN-ID %d)", group->vlan_id);
+	wpa_printf(MSG_DEBUG,
+		   "WPA: group state machine entering state GTK_INIT (VLAN-ID %d)",
+		   group->vlan_id);
 	group->changed = FALSE; /* GInit is not cleared here; avoid loop */
 	group->wpa_group_state = WPA_GROUP_GTK_INIT;
 
@@ -3803,6 +3966,8 @@
 	group->GM = 2;
 	group->GN_igtk = 4;
 	group->GM_igtk = 5;
+	group->GN_bigtk = 6;
+	group->GM_bigtk = 7;
 	/* GTK[GN] = CalcGTK() */
 	wpa_gtk_update(wpa_auth, group);
 }
@@ -3826,8 +3991,7 @@
 		 * station needs to be counted here anyway.
 		 */
 		wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
-				"GUpdateStationKeys was already set when "
-				"marking station for GTK rekeying");
+				"GUpdateStationKeys was already set when marking station for GTK rekeying");
 	}
 
 	/* Do not rekey GTK/IGTK when STA is in WNM-Sleep Mode */
@@ -3846,7 +4010,7 @@
 /* update GTK when exiting WNM-Sleep Mode */
 void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm)
 {
-	if (sm == NULL || sm->is_wnmsleep)
+	if (!sm || sm->is_wnmsleep)
 		return;
 
 	wpa_group_update_sta(sm, NULL);
@@ -3920,6 +4084,36 @@
 	return pos - start;
 }
 
+
+int wpa_wnmsleep_bigtk_subelem(struct wpa_state_machine *sm, u8 *pos)
+{
+	struct wpa_group *gsm = sm->group;
+	u8 *start = pos;
+	size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
+
+	/*
+	 * BIGTK subelement:
+	 * Sub-elem ID[1] | Length[1] | KeyID[2] | PN[6] | Key[16]
+	 */
+	*pos++ = WNM_SLEEP_SUBELEM_BIGTK;
+	*pos++ = 2 + 6 + len;
+	WPA_PUT_LE16(pos, gsm->GN_bigtk);
+	pos += 2;
+	if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_bigtk, pos) != 0)
+		return 0;
+	pos += 6;
+
+	os_memcpy(pos, gsm->BIGTK[gsm->GN_bigtk - 6], len);
+	pos += len;
+
+	wpa_printf(MSG_DEBUG, "WNM: BIGTK Key ID %u in WNM-Sleep Mode exit",
+		   gsm->GN_bigtk);
+	wpa_hexdump_key(MSG_DEBUG, "WNM: BIGTK in WNM-Sleep Mode exit",
+			gsm->IGTK[gsm->GN_bigtk - 6], len);
+
+	return pos - start;
+}
+
 #endif /* CONFIG_WNM_AP */
 
 
@@ -3928,8 +4122,9 @@
 {
 	int tmp;
 
-	wpa_printf(MSG_DEBUG, "WPA: group state machine entering state "
-		   "SETKEYS (VLAN-ID %d)", group->vlan_id);
+	wpa_printf(MSG_DEBUG,
+		   "WPA: group state machine entering state SETKEYS (VLAN-ID %d)",
+		   group->vlan_id);
 	group->changed = TRUE;
 	group->wpa_group_state = WPA_GROUP_SETKEYS;
 	group->GTKReKey = FALSE;
@@ -3939,14 +4134,17 @@
 	tmp = group->GM_igtk;
 	group->GM_igtk = group->GN_igtk;
 	group->GN_igtk = tmp;
+	tmp = group->GM_bigtk;
+	group->GM_bigtk = group->GN_bigtk;
+	group->GN_bigtk = tmp;
 	/* "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. */
 	wpa_gtk_update(wpa_auth, group);
 
 	if (group->GKeyDoneStations) {
-		wpa_printf(MSG_DEBUG, "wpa_group_setkeys: Unexpected "
-			   "GKeyDoneStations=%d when starting new GTK rekey",
+		wpa_printf(MSG_DEBUG,
+			   "wpa_group_setkeys: Unexpected GKeyDoneStations=%d when starting new GTK rekey",
 			   group->GKeyDoneStations);
 		group->GKeyDoneStations = 0;
 	}
@@ -3959,25 +4157,35 @@
 static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth,
 				       struct wpa_group *group)
 {
+	struct wpa_auth_config *conf = &wpa_auth->conf;
 	int ret = 0;
 
 	if (wpa_auth_set_key(wpa_auth, group->vlan_id,
-			     wpa_cipher_to_alg(wpa_auth->conf.wpa_group),
+			     wpa_cipher_to_alg(conf->wpa_group),
 			     broadcast_ether_addr, group->GN,
-			     group->GTK[group->GN - 1], group->GTK_len) < 0)
+			     group->GTK[group->GN - 1], group->GTK_len,
+			     KEY_FLAG_GROUP_TX_DEFAULT) < 0)
 		ret = -1;
 
-	if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) {
+	if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
 		enum wpa_alg alg;
 		size_t len;
 
-		alg = wpa_cipher_to_alg(wpa_auth->conf.group_mgmt_cipher);
-		len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
+		alg = wpa_cipher_to_alg(conf->group_mgmt_cipher);
+		len = wpa_cipher_key_len(conf->group_mgmt_cipher);
 
 		if (ret == 0 &&
 		    wpa_auth_set_key(wpa_auth, group->vlan_id, alg,
 				     broadcast_ether_addr, group->GN_igtk,
-				     group->IGTK[group->GN_igtk - 4], len) < 0)
+				     group->IGTK[group->GN_igtk - 4], len,
+				     KEY_FLAG_GROUP_TX_DEFAULT) < 0)
+			ret = -1;
+
+		if (ret == 0 && conf->beacon_prot &&
+		    wpa_auth_set_key(wpa_auth, group->vlan_id, alg,
+				     broadcast_ether_addr, group->GN_bigtk,
+				     group->BIGTK[group->GN_bigtk - 6], len,
+				     KEY_FLAG_GROUP_TX_DEFAULT) < 0)
 			ret = -1;
 	}
 
@@ -3989,7 +4197,7 @@
 {
 	if (sm->group == ctx) {
 		wpa_printf(MSG_DEBUG, "WPA: Mark STA " MACSTR
-			   " for discconnection due to fatal failure",
+			   " for disconnection due to fatal failure",
 			   MAC2STR(sm->addr));
 		sm->Disconnect = TRUE;
 	}
@@ -4001,7 +4209,8 @@
 static void wpa_group_fatal_failure(struct wpa_authenticator *wpa_auth,
 				    struct wpa_group *group)
 {
-	wpa_printf(MSG_DEBUG, "WPA: group state machine entering state FATAL_FAILURE");
+	wpa_printf(MSG_DEBUG,
+		   "WPA: group state machine entering state FATAL_FAILURE");
 	group->changed = TRUE;
 	group->wpa_group_state = WPA_GROUP_FATAL_FAILURE;
 	wpa_auth_for_each_sta(wpa_auth, wpa_group_disconnect_cb, group);
@@ -4011,8 +4220,9 @@
 static int wpa_group_setkeysdone(struct wpa_authenticator *wpa_auth,
 				 struct wpa_group *group)
 {
-	wpa_printf(MSG_DEBUG, "WPA: group state machine entering state "
-		   "SETKEYSDONE (VLAN-ID %d)", group->vlan_id);
+	wpa_printf(MSG_DEBUG,
+		   "WPA: group state machine entering state SETKEYSDONE (VLAN-ID %d)",
+		   group->vlan_id);
 	group->changed = TRUE;
 	group->wpa_group_state = WPA_GROUP_SETKEYSDONE;
 
@@ -4049,7 +4259,7 @@
 
 static int wpa_sm_step(struct wpa_state_machine *sm)
 {
-	if (sm == NULL)
+	if (!sm)
 		return 0;
 
 	if (sm->in_step_loop) {
@@ -4079,8 +4289,9 @@
 	sm->in_step_loop = 0;
 
 	if (sm->pending_deinit) {
-		wpa_printf(MSG_DEBUG, "WPA: Completing pending STA state "
-			   "machine deinit for " MACSTR, MAC2STR(sm->addr));
+		wpa_printf(MSG_DEBUG,
+			   "WPA: Completing pending STA state machine deinit for "
+			   MACSTR, MAC2STR(sm->addr));
 		wpa_free_sta_sm(sm);
 		return 1;
 	}
@@ -4097,7 +4308,7 @@
 
 void wpa_auth_sm_notify(struct wpa_state_machine *sm)
 {
-	if (sm == NULL)
+	if (!sm)
 		return;
 	eloop_register_timeout(0, 0, wpa_sm_call_step, sm, NULL);
 }
@@ -4108,7 +4319,7 @@
 	int tmp, i;
 	struct wpa_group *group;
 
-	if (wpa_auth == NULL)
+	if (!wpa_auth)
 		return;
 
 	group = wpa_auth->group;
@@ -4120,6 +4331,9 @@
 		tmp = group->GM_igtk;
 		group->GM_igtk = group->GN_igtk;
 		group->GN_igtk = tmp;
+		tmp = group->GM_bigtk;
+		group->GM_bigtk = group->GN_bigtk;
+		group->GN_bigtk = tmp;
 		wpa_gtk_update(wpa_auth, group);
 		wpa_group_config_group_keys(wpa_auth, group);
 	}
@@ -4138,6 +4352,7 @@
 
 int wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen)
 {
+	struct wpa_auth_config *conf;
 	int len = 0, ret;
 	char pmkid_txt[PMKID_LEN * 2 + 1];
 #ifdef CONFIG_RSN_PREAUTH
@@ -4146,8 +4361,9 @@
 	const int preauth = 0;
 #endif /* CONFIG_RSN_PREAUTH */
 
-	if (wpa_auth == NULL)
+	if (!wpa_auth)
 		return len;
+	conf = &wpa_auth->conf;
 
 	ret = os_snprintf(buf + len, buflen - len,
 			  "dot11RSNAOptionImplemented=TRUE\n"
@@ -4155,8 +4371,8 @@
 			  "dot11RSNAEnabled=%s\n"
 			  "dot11RSNAPreauthenticationEnabled=%s\n",
 			  wpa_bool_txt(preauth),
-			  wpa_bool_txt(wpa_auth->conf.wpa & WPA_PROTO_RSN),
-			  wpa_bool_txt(wpa_auth->conf.rsn_preauth));
+			  wpa_bool_txt(conf->wpa & WPA_PROTO_RSN),
+			  wpa_bool_txt(conf->rsn_preauth));
 	if (os_snprintf_error(buflen - len, ret))
 		return len;
 	len += ret;
@@ -4191,10 +4407,10 @@
 		"dot11RSNA4WayHandshakeFailures=%u\n"
 		"dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n",
 		RSN_VERSION,
-		!!wpa_auth->conf.wpa_strict_rekey,
-		wpa_auth->conf.wpa_group_update_count,
-		wpa_auth->conf.wpa_pairwise_update_count,
-		wpa_cipher_key_len(wpa_auth->conf.wpa_group) * 8,
+		!!conf->wpa_strict_rekey,
+		conf->wpa_group_update_count,
+		conf->wpa_pairwise_update_count,
+		wpa_cipher_key_len(conf->wpa_group) * 8,
 		dot11RSNAConfigPMKLifetime,
 		dot11RSNAConfigPMKReauthThreshold,
 		dot11RSNAConfigSATimeout,
@@ -4230,7 +4446,7 @@
 	int len = 0, ret;
 	u32 pairwise = 0;
 
-	if (sm == NULL)
+	if (!sm)
 		return 0;
 
 	/* TODO: FF-FF-FF-FF-FF-FF entry for broadcast/multicast stats */
@@ -4311,7 +4527,7 @@
 
 int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm)
 {
-	if (sm == NULL)
+	if (!sm)
 		return -1;
 	return sm->wpa_key_mgmt;
 }
@@ -4319,7 +4535,7 @@
 
 int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm)
 {
-	if (sm == NULL)
+	if (!sm)
 		return 0;
 	return sm->wpa;
 }
@@ -4344,7 +4560,7 @@
 int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm,
 			     struct rsn_pmksa_cache_entry *entry)
 {
-	if (sm == NULL || sm->pmksa != entry)
+	if (!sm || sm->pmksa != entry)
 		return -1;
 	sm->pmksa = NULL;
 	return 0;
@@ -4367,7 +4583,7 @@
 
 const u8 * wpa_auth_get_wpa_ie(struct wpa_authenticator *wpa_auth, size_t *len)
 {
-	if (wpa_auth == NULL)
+	if (!wpa_auth)
 		return NULL;
 	*len = wpa_auth->wpa_ie_len;
 	return wpa_auth->wpa_ie;
@@ -4378,7 +4594,7 @@
 		       unsigned int pmk_len,
 		       int session_timeout, struct eapol_state_machine *eapol)
 {
-	if (sm == NULL || sm->wpa != WPA_VERSION_WPA2 ||
+	if (!sm || sm->wpa != WPA_VERSION_WPA2 ||
 	    sm->wpa_auth->conf.disable_pmksa_caching)
 		return -1;
 
@@ -4414,7 +4630,7 @@
 			       int session_timeout,
 			       struct eapol_state_machine *eapol)
 {
-	if (wpa_auth == NULL)
+	if (!wpa_auth)
 		return -1;
 
 	wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK from preauth", pmk, len);
@@ -4475,7 +4691,7 @@
 {
 	struct rsn_pmksa_cache_entry *pmksa;
 
-	if (wpa_auth == NULL || wpa_auth->pmksa == NULL)
+	if (!wpa_auth || !wpa_auth->pmksa)
 		return;
 	pmksa = pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, NULL);
 	if (pmksa) {
@@ -4641,13 +4857,13 @@
 {
 	struct wpa_group *group;
 
-	if (wpa_auth == NULL || wpa_auth->group == NULL)
+	if (!wpa_auth || !wpa_auth->group)
 		return NULL;
 
 	wpa_printf(MSG_DEBUG, "WPA: Add group state machine for VLAN-ID %d",
 		   vlan_id);
 	group = wpa_group_init(wpa_auth, vlan_id, 0);
-	if (group == NULL)
+	if (!group)
 		return NULL;
 
 	group->next = wpa_auth->group->next;
@@ -4667,7 +4883,7 @@
 {
 	struct wpa_group *group;
 
-	if (wpa_auth == NULL)
+	if (!wpa_auth)
 		return 0;
 
 	group = wpa_auth->group;
@@ -4677,9 +4893,9 @@
 		group = group->next;
 	}
 
-	if (group == NULL) {
+	if (!group) {
 		group = wpa_auth_add_group(wpa_auth, vlan_id);
-		if (group == NULL)
+		if (!group)
 			return -1;
 	}
 
@@ -4708,7 +4924,7 @@
 	struct wpa_group *group;
 	int ret = 0;
 
-	if (wpa_auth == NULL)
+	if (!wpa_auth)
 		return 0;
 
 	group = wpa_auth->group;
@@ -4718,7 +4934,7 @@
 		group = group->next;
 	}
 
-	if (group == NULL)
+	if (!group)
 		return -1;
 
 	wpa_printf(MSG_DEBUG,
@@ -4753,7 +4969,7 @@
 {
 	struct wpa_group *group;
 
-	if (sm == NULL || sm->wpa_auth == NULL)
+	if (!sm || !sm->wpa_auth)
 		return 0;
 
 	group = sm->wpa_auth->group;
@@ -4763,9 +4979,9 @@
 		group = group->next;
 	}
 
-	if (group == NULL) {
+	if (!group) {
 		group = wpa_auth_add_group(sm->wpa_auth, vlan_id);
-		if (group == NULL)
+		if (!group)
 			return -1;
 	}
 
@@ -4775,8 +4991,9 @@
 	if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
 		return -1;
 
-	wpa_printf(MSG_DEBUG, "WPA: Moving STA " MACSTR " to use group state "
-		   "machine for VLAN ID %d", MAC2STR(sm->addr), vlan_id);
+	wpa_printf(MSG_DEBUG, "WPA: Moving STA " MACSTR
+		   " to use group state machine for VLAN ID %d",
+		   MAC2STR(sm->addr), vlan_id);
 
 	wpa_group_get(sm->wpa_auth, group);
 	wpa_group_put(sm->wpa_auth, sm->group);
@@ -4789,7 +5006,7 @@
 void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth,
 				  struct wpa_state_machine *sm, int ack)
 {
-	if (wpa_auth == NULL || sm == NULL)
+	if (!wpa_auth || !sm)
 		return;
 	wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key TX status for STA " MACSTR
 		   " ack=%d", MAC2STR(sm->addr), ack);
@@ -4805,8 +5022,8 @@
 		 * the station has received the frame.
 		 */
 		int timeout_ms = eapol_key_timeout_subseq;
-		wpa_printf(MSG_DEBUG, "WPA: Increase initial EAPOL-Key 1/4 "
-			   "timeout by %u ms because of acknowledged frame",
+		wpa_printf(MSG_DEBUG,
+			   "WPA: Increase initial EAPOL-Key 1/4 timeout by %u ms because of acknowledged frame",
 			   timeout_ms);
 		eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm);
 		eloop_register_timeout(timeout_ms / 1000,
@@ -4826,7 +5043,7 @@
 
 int wpa_auth_uses_sae(struct wpa_state_machine *sm)
 {
-	if (sm == NULL)
+	if (!sm)
 		return 0;
 	return wpa_key_mgmt_sae(sm->wpa_key_mgmt);
 }
@@ -4834,7 +5051,7 @@
 
 int wpa_auth_uses_ft_sae(struct wpa_state_machine *sm)
 {
-	if (sm == NULL)
+	if (!sm)
 		return 0;
 	return sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_SAE;
 }
@@ -4843,7 +5060,7 @@
 #ifdef CONFIG_P2P
 int wpa_auth_get_ip_addr(struct wpa_state_machine *sm, u8 *addr)
 {
-	if (sm == NULL || WPA_GET_BE32(sm->ip_addr) == 0)
+	if (!sm || WPA_GET_BE32(sm->ip_addr) == 0)
 		return -1;
 	os_memcpy(addr, sm->ip_addr, 4);
 	return 0;
@@ -4919,7 +5136,7 @@
 
 	return wpa_write_ftie(conf, use_sha384, conf->r0_key_holder,
 			      conf->r0_key_holder_len,
-			      NULL, NULL, buf, len, NULL, 0);
+			      NULL, NULL, buf, len, NULL, 0, 0);
 }
 #endif /* CONFIG_IEEE80211R_AP */
 
@@ -4999,9 +5216,10 @@
 	struct wpa_group *gsm = sm->group;
 	u8 *wpa_ie;
 	int wpa_ie_len, secure, gtkidx, encr = 0;
+	u8 hdr[2];
 
 	/* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE],
-	   GTK[GN], IGTK, [FTIE], [TIE * 2])
+	   GTK[GN], IGTK, [BIGTK], [FTIE], [TIE * 2])
 	 */
 
 	/* Use 0 RSC */
@@ -5044,13 +5262,16 @@
 			 * WPA if the supplicant used it first.
 			 */
 			wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
-					"STA used Secure bit in WPA msg 2/4 - "
-					"set Secure for 3/4 as workaround");
+					"STA used Secure bit in WPA msg 2/4 - set Secure for 3/4 as workaround");
 			secure = 1;
 		}
 	}
 
 	kde_len = wpa_ie_len + ieee80211w_kde_len(sm) + ocv_oci_len(sm);
+
+	if (sm->use_ext_key_id)
+		kde_len += 2 + RSN_SELECTOR_LEN + 2;
+
 	if (gtk)
 		kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len;
 #ifdef CONFIG_IEEE80211R_AP
@@ -5060,7 +5281,7 @@
 	}
 #endif /* CONFIG_IEEE80211R_AP */
 	kde = os_malloc(kde_len);
-	if (kde == NULL)
+	if (!kde)
 		return -1;
 
 	pos = kde;
@@ -5074,8 +5295,8 @@
 		elen = pos - kde;
 		res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name);
 		if (res < 0) {
-			wpa_printf(MSG_ERROR, "FT: Failed to insert "
-				   "PMKR1Name into RSN IE in EAPOL-Key data");
+			wpa_printf(MSG_ERROR,
+				   "FT: Failed to insert PMKR1Name into RSN IE in EAPOL-Key data");
 			os_free(kde);
 			return -1;
 		}
@@ -5083,10 +5304,15 @@
 		pos += elen;
 	}
 #endif /* CONFIG_IEEE80211R_AP */
+	hdr[1] = 0;
+
+	if (sm->use_ext_key_id) {
+		hdr[0] = sm->keyidx_active & 0x01;
+		pos = wpa_add_kde(pos, RSN_KEY_DATA_KEYID, hdr, 2, NULL, 0);
+	}
+
 	if (gtk) {
-		u8 hdr[2];
 		hdr[0] = gtkidx & 0x03;
-		hdr[1] = 0;
 		pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
 				  gtk, gtk_len);
 	}
@@ -5121,11 +5347,11 @@
 					     conf->r0_key_holder_len,
 					     NULL, NULL, pos,
 					     kde + kde_len - pos,
-					     NULL, 0);
+					     NULL, 0, 0);
 		}
 		if (res < 0) {
-			wpa_printf(MSG_ERROR, "FT: Failed to insert FTIE "
-				   "into EAPOL-Key Key Data");
+			wpa_printf(MSG_ERROR,
+				   "FT: Failed to insert FTIE into EAPOL-Key Key Data");
 			os_free(kde);
 			return -1;
 		}
@@ -5182,7 +5408,7 @@
 		kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len +
 			ieee80211w_kde_len(sm) + ocv_oci_len(sm);
 		kde_buf = os_malloc(kde_len);
-		if (kde_buf == NULL)
+		if (!kde_buf)
 			return -1;
 
 		kde = pos = kde_buf;
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index 933a4b8..868aaa1 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -169,6 +169,7 @@
 
 struct wpa_auth_config {
 	int wpa;
+	int extended_key_id;
 	int wpa_key_mgmt;
 	int wpa_pairwise;
 	int wpa_group;
@@ -176,6 +177,7 @@
 	int wpa_strict_rekey;
 	int wpa_gmk_rekey;
 	int wpa_ptk_rekey;
+	int wpa_deny_ptk0_rekey;
 	u32 wpa_group_update_count;
 	u32 wpa_pairwise_update_count;
 	int wpa_disable_eapol_key_retries;
@@ -188,6 +190,7 @@
 	int okc;
 	int tx_status;
 	enum mfp_options ieee80211w;
+	int beacon_prot;
 	int group_mgmt_cipher;
 	int sae_require_mfp;
 #ifdef CONFIG_OCV
@@ -219,8 +222,22 @@
 	double corrupt_gtk_rekey_mic_probability;
 	u8 own_ie_override[MAX_OWN_IE_OVERRIDE];
 	size_t own_ie_override_len;
+	u8 rsne_override_eapol[MAX_OWN_IE_OVERRIDE];
+	size_t rsne_override_eapol_len;
 	u8 rsnxe_override_eapol[MAX_OWN_IE_OVERRIDE];
 	size_t rsnxe_override_eapol_len;
+	u8 rsne_override_ft[MAX_OWN_IE_OVERRIDE];
+	size_t rsne_override_ft_len;
+	u8 rsnxe_override_ft[MAX_OWN_IE_OVERRIDE];
+	size_t rsnxe_override_ft_len;
+	u8 gtk_rsc_override[WPA_KEY_RSC_LEN];
+	u8 igtk_rsc_override[WPA_KEY_RSC_LEN];
+	unsigned int rsne_override_eapol_set:1;
+	unsigned int rsnxe_override_eapol_set:1;
+	unsigned int rsne_override_ft_set:1;
+	unsigned int rsnxe_override_ft_set:1;
+	unsigned int gtk_rsc_override_set:1;
+	unsigned int igtk_rsc_override_set:1;
 #endif /* CONFIG_TESTING_OPTIONS */
 #ifdef CONFIG_P2P
 	u8 ip_addr_go[4];
@@ -233,6 +250,11 @@
 	u8 fils_cache_id[FILS_CACHE_ID_LEN];
 #endif /* CONFIG_FILS */
 	int sae_pwe;
+	int owe_ptk_workaround;
+	u8 transition_disable;
+#ifdef CONFIG_DPP2
+	int dpp_pfs;
+#endif /* CONFIG_DPP2 */
 };
 
 typedef enum {
@@ -259,7 +281,8 @@
 			      int *vlan_id);
 	int (*get_msk)(void *ctx, const u8 *addr, u8 *msk, size_t *len);
 	int (*set_key)(void *ctx, int vlan_id, enum wpa_alg alg,
-		       const u8 *addr, int idx, u8 *key, size_t key_len);
+		       const u8 *addr, int idx, u8 *key, size_t key_len,
+		       enum key_flag key_flag);
 	int (*get_seqnum)(void *ctx, const u8 *addr, int idx, u8 *seq);
 	int (*send_eapol)(void *ctx, const u8 *addr, const u8 *data,
 			  size_t data_len, int encrypt);
@@ -311,19 +334,21 @@
 int wpa_reconfig(struct wpa_authenticator *wpa_auth,
 		 struct wpa_auth_config *conf);
 
-enum {
+enum wpa_validate_result {
 	WPA_IE_OK, WPA_INVALID_IE, WPA_INVALID_GROUP, WPA_INVALID_PAIRWISE,
 	WPA_INVALID_AKMP, WPA_NOT_ENABLED, WPA_ALLOC_FAIL,
 	WPA_MGMT_FRAME_PROTECTION_VIOLATION, WPA_INVALID_MGMT_GROUP_CIPHER,
-	WPA_INVALID_MDIE, WPA_INVALID_PROTO, WPA_INVALID_PMKID
+	WPA_INVALID_MDIE, WPA_INVALID_PROTO, WPA_INVALID_PMKID,
+	WPA_DENIED_OTHER_REASON
 };
 
-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);
+enum wpa_validate_result
+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,
 		      struct wpa_state_machine *sm,
 		      const u8 *osen_ie, size_t osen_ie_len);
@@ -407,7 +432,8 @@
 #ifdef CONFIG_IEEE80211R_AP
 u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
 				 size_t max_len, int auth_alg,
-				 const u8 *req_ies, size_t req_ies_len);
+				 const u8 *req_ies, size_t req_ies_len,
+				 int omit_rsnxe);
 void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid,
 			 u16 auth_transaction, const u8 *ies, size_t ies_len,
 			 void (*cb)(void *ctx, const u8 *dst, const u8 *bssid,
@@ -431,6 +457,7 @@
 void wpa_set_wnmsleep(struct wpa_state_machine *sm, int flag);
 int wpa_wnmsleep_gtk_subelem(struct wpa_state_machine *sm, u8 *pos);
 int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos);
+int wpa_wnmsleep_bigtk_subelem(struct wpa_state_machine *sm, u8 *pos);
 
 int wpa_auth_uses_sae(struct wpa_state_machine *sm);
 int wpa_auth_uses_ft_sae(struct wpa_state_machine *sm);
diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c
index a599be2..476a2be 100644
--- a/src/ap/wpa_auth_ft.c
+++ b/src/ap/wpa_auth_ft.c
@@ -808,7 +808,7 @@
 		   const u8 *r0kh_id, size_t r0kh_id_len,
 		   const u8 *anonce, const u8 *snonce,
 		   u8 *buf, size_t len, const u8 *subelem,
-		   size_t subelem_len)
+		   size_t subelem_len, int rsnxe_used)
 {
 	u8 *pos = buf, *ielen;
 	size_t hdrlen = use_sha384 ? sizeof(struct rsn_ftie_sha384) :
@@ -826,7 +826,7 @@
 
 		os_memset(hdr, 0, sizeof(*hdr));
 		pos += sizeof(*hdr);
-		WPA_PUT_LE16(hdr->mic_control, 0);
+		WPA_PUT_LE16(hdr->mic_control, !!rsnxe_used);
 		if (anonce)
 			os_memcpy(hdr->anonce, anonce, WPA_NONCE_LEN);
 		if (snonce)
@@ -836,7 +836,7 @@
 
 		os_memset(hdr, 0, sizeof(*hdr));
 		pos += sizeof(*hdr);
-		WPA_PUT_LE16(hdr->mic_control, 0);
+		WPA_PUT_LE16(hdr->mic_control, !!rsnxe_used);
 		if (anonce)
 			os_memcpy(hdr->anonce, anonce, WPA_NONCE_LEN);
 		if (snonce)
@@ -951,8 +951,9 @@
 		goto err;
 	}
 
-	wpa_printf(MSG_DEBUG, "FT: Send out sequence number request to " MACSTR,
-		   MAC2STR(src_addr));
+	wpa_printf(MSG_DEBUG, "FT: Send sequence number request from " MACSTR
+		   " to " MACSTR,
+		   MAC2STR(wpa_auth->addr), MAC2STR(src_addr));
 	item = os_zalloc(sizeof(*item));
 	if (!item)
 		goto err;
@@ -1997,9 +1998,6 @@
 	key = r0kh->key;
 	key_len = sizeof(r0kh->key);
 
-	wpa_printf(MSG_DEBUG, "FT: Send PMK-R1 pull request to remote R0KH "
-		   "address " MACSTR, MAC2STR(r0kh->addr));
-
 	if (r0kh->seq->rx.num_last == 0) {
 		/* A sequence request will be sent out anyway when pull
 		 * response is received. Send it out now to avoid one RTT. */
@@ -2008,6 +2006,10 @@
 				   key_len, NULL, 0, NULL, 0, NULL);
 	}
 
+	wpa_printf(MSG_DEBUG, "FT: Send PMK-R1 pull request from " MACSTR
+		   " to remote R0KH address " MACSTR,
+		   MAC2STR(sm->wpa_auth->addr), MAC2STR(r0kh->addr));
+
 	if (first &&
 	    random_get_bytes(sm->ft_pending_pull_nonce, FT_RRB_NONCE_LEN) < 0) {
 		wpa_printf(MSG_DEBUG, "FT: Failed to get random data for "
@@ -2280,6 +2282,54 @@
 }
 
 
+static u8 * wpa_ft_bigtk_subelem(struct wpa_state_machine *sm, size_t *len)
+{
+	u8 *subelem, *pos;
+	struct wpa_group *gsm = sm->group;
+	size_t subelem_len;
+	const u8 *kek;
+	size_t kek_len;
+	size_t bigtk_len;
+
+	if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
+		kek = sm->PTK.kek2;
+		kek_len = sm->PTK.kek2_len;
+	} else {
+		kek = sm->PTK.kek;
+		kek_len = sm->PTK.kek_len;
+	}
+
+	bigtk_len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
+
+	/* Sub-elem ID[1] | Length[1] | KeyID[2] | BIPN[6] | Key Length[1] |
+	 * Key[16+8] */
+	subelem_len = 1 + 1 + 2 + 6 + 1 + bigtk_len + 8;
+	subelem = os_zalloc(subelem_len);
+	if (subelem == NULL)
+		return NULL;
+
+	pos = subelem;
+	*pos++ = FTIE_SUBELEM_BIGTK;
+	*pos++ = subelem_len - 2;
+	WPA_PUT_LE16(pos, gsm->GN_bigtk);
+	pos += 2;
+	wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_bigtk, pos);
+	pos += 6;
+	*pos++ = bigtk_len;
+	if (aes_wrap(kek, kek_len, bigtk_len / 8,
+		     gsm->IGTK[gsm->GN_bigtk - 6], pos)) {
+		wpa_printf(MSG_DEBUG,
+			   "FT: BIGTK subelem encryption failed: kek_len=%d",
+			   (int) kek_len);
+		os_free(subelem);
+		return NULL;
+	}
+
+	*len = subelem_len;
+	return subelem;
+}
+
+
 static u8 * wpa_ft_process_rdie(struct wpa_state_machine *sm,
 				u8 *pos, u8 *end, u8 id, u8 descr_count,
 				const u8 *ies, size_t ies_len)
@@ -2413,13 +2463,15 @@
 
 u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
 				 size_t max_len, int auth_alg,
-				 const u8 *req_ies, size_t req_ies_len)
+				 const u8 *req_ies, size_t req_ies_len,
+				 int omit_rsnxe)
 {
 	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];
+	u8 rsnxe_buf[10], *rsnxe = rsnxe_buf;
 	size_t rsnxe_len;
+	int rsnxe_used;
 	int res;
 	struct wpa_auth_config *conf;
 	struct wpa_ft_ies parse;
@@ -2440,6 +2492,32 @@
 
 	end = pos + max_len;
 
+#ifdef CONFIG_TESTING_OPTIONS
+	if (auth_alg == WLAN_AUTH_FT &&
+	    sm->wpa_auth->conf.rsne_override_ft_set) {
+		wpa_printf(MSG_DEBUG,
+			   "TESTING: RSNE FT override for MIC calculation");
+		rsnie = sm->wpa_auth->conf.rsne_override_ft;
+		rsnie_len = sm->wpa_auth->conf.rsne_override_ft_len;
+		if (end - pos < (long int) rsnie_len)
+			return pos;
+		os_memcpy(pos, rsnie, rsnie_len);
+		rsnie = pos;
+		pos += rsnie_len;
+		if (rsnie_len > PMKID_LEN && sm->pmk_r1_name_valid) {
+			int idx;
+
+			/* Replace all 0xff PMKID with the valid PMKR1Name */
+			for (idx = 0; idx < PMKID_LEN; idx++) {
+				if (rsnie[rsnie_len - 1 - idx] != 0xff)
+					break;
+			}
+			if (idx == PMKID_LEN)
+				os_memcpy(&rsnie[rsnie_len - PMKID_LEN],
+					  sm->pmk_r1_name, WPA_PMK_NAME_LEN);
+		}
+	} else
+#endif /* CONFIG_TESTING_OPTIONS */
 	if (auth_alg == WLAN_AUTH_FT ||
 	    ((auth_alg == WLAN_AUTH_FILS_SK ||
 	      auth_alg == WLAN_AUTH_FILS_SK_PFS ||
@@ -2509,6 +2587,29 @@
 			subelem_len += igtk_len;
 			os_free(igtk);
 		}
+		if (sm->mgmt_frame_prot && conf->beacon_prot) {
+			u8 *bigtk;
+			size_t bigtk_len;
+			u8 *nbuf;
+
+			bigtk = wpa_ft_bigtk_subelem(sm, &bigtk_len);
+			if (!bigtk) {
+				wpa_printf(MSG_DEBUG,
+					   "FT: Failed to add BIGTK subelement");
+				os_free(subelem);
+				return NULL;
+			}
+			nbuf = os_realloc(subelem, subelem_len + bigtk_len);
+			if (!nbuf) {
+				os_free(subelem);
+				os_free(bigtk);
+				return NULL;
+			}
+			subelem = nbuf;
+			os_memcpy(subelem + subelem_len, bigtk, bigtk_len);
+			subelem_len += bigtk_len;
+			os_free(bigtk);
+		}
 #ifdef CONFIG_OCV
 		if (wpa_auth_uses_ocv(sm)) {
 			struct wpa_channel_info ci;
@@ -2544,9 +2645,11 @@
 		anonce = NULL;
 		snonce = NULL;
 	}
+	rsnxe_used = (auth_alg == WLAN_AUTH_FT) &&
+		(conf->sae_pwe == 1 || conf->sae_pwe == 2);
 	res = wpa_write_ftie(conf, use_sha384, r0kh_id, r0kh_id_len,
 			     anonce, snonce, pos, end - pos,
-			     subelem, subelem_len);
+			     subelem, subelem_len, rsnxe_used);
 	os_free(subelem);
 	if (res < 0)
 		return NULL;
@@ -2582,10 +2685,24 @@
 	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 (omit_rsnxe) {
+		rsnxe_len = 0;
+	} else {
+		res = wpa_write_rsnxe(&sm->wpa_auth->conf, rsnxe,
+				      sizeof(rsnxe_buf));
+		if (res < 0)
+			return NULL;
+		rsnxe_len = res;
+	}
+#ifdef CONFIG_TESTING_OPTIONS
+	if (auth_alg == WLAN_AUTH_FT &&
+	    sm->wpa_auth->conf.rsnxe_override_ft_set) {
+		wpa_printf(MSG_DEBUG,
+			   "TESTING: RSNXE FT override for MIC calculation");
+		rsnxe = sm->wpa_auth->conf.rsnxe_override_ft;
+		rsnxe_len = sm->wpa_auth->conf.rsnxe_override_ft_len;
+	}
+#endif /* CONFIG_TESTING_OPTIONS */
 	if (auth_alg == WLAN_AUTH_FT && rsnxe_len)
 		*elem_count += 1;
 
@@ -2620,12 +2737,13 @@
 static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth,
 				   int vlan_id,
 				   enum wpa_alg alg, const u8 *addr, int idx,
-				   u8 *key, size_t key_len)
+				   u8 *key, size_t key_len,
+				   enum key_flag key_flag)
 {
 	if (wpa_auth->cb->set_key == NULL)
 		return -1;
 	return wpa_auth->cb->set_key(wpa_auth->cb_ctx, vlan_id, alg, addr, idx,
-				     key, key_len);
+				     key, key_len, key_flag);
 }
 
 
@@ -2657,8 +2775,8 @@
 	 * again after association to get the PTK configured, but that could be
 	 * optimized by adding the STA entry earlier.
 	 */
-	if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0,
-			     sm->PTK.tk, klen))
+	if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, sm->keyidx_active,
+			     sm->PTK.tk, klen, KEY_FLAG_PAIRWISE_RX_TX))
 		return;
 
 	/* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */
@@ -3057,7 +3175,8 @@
 	pos += ret;
 
 	ret = wpa_write_ftie(conf, use_sha384, parse.r0kh_id, parse.r0kh_id_len,
-			     sm->ANonce, sm->SNonce, pos, end - pos, NULL, 0);
+			     sm->ANonce, sm->SNonce, pos, end - pos, NULL, 0,
+			     0);
 	if (ret < 0)
 		goto fail;
 	pos += ret;
@@ -3129,10 +3248,13 @@
 	int use_sha384;
 	const u8 *anonce, *snonce, *fte_mic;
 	u8 fte_elem_count;
+	int rsnxe_used;
+	struct wpa_auth_config *conf;
 
 	if (sm == NULL)
 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
 
+	conf = &sm->wpa_auth->conf;
 	use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt);
 
 	wpa_hexdump(MSG_DEBUG, "FT: Reassoc Req IEs", ies, ies_len);
@@ -3161,8 +3283,7 @@
 
 	mdie = (struct rsn_mdie *) parse.mdie;
 	if (mdie == NULL || parse.mdie_len < sizeof(*mdie) ||
-	    os_memcmp(mdie->mobility_domain,
-		      sm->wpa_auth->conf.mobility_domain,
+	    os_memcmp(mdie->mobility_domain, conf->mobility_domain,
 		      MOBILITY_DOMAIN_ID_LEN) != 0) {
 		wpa_printf(MSG_DEBUG, "FT: Invalid MDIE");
 		return WLAN_STATUS_INVALID_MDIE;
@@ -3179,6 +3300,7 @@
 
 		anonce = ftie->anonce;
 		snonce = ftie->snonce;
+		rsnxe_used = ftie->mic_control[0] & 0x01;
 		fte_elem_count = ftie->mic_control[1];
 		fte_mic = ftie->mic;
 	} else {
@@ -3192,6 +3314,7 @@
 
 		anonce = ftie->anonce;
 		snonce = ftie->snonce;
+		rsnxe_used = ftie->mic_control[0] & 0x01;
 		fte_elem_count = ftie->mic_control[1];
 		fte_mic = ftie->mic;
 	}
@@ -3237,14 +3360,14 @@
 		return WLAN_STATUS_INVALID_FTIE;
 	}
 
-	if (os_memcmp_const(parse.r1kh_id, sm->wpa_auth->conf.r1_key_holder,
+	if (os_memcmp_const(parse.r1kh_id, conf->r1_key_holder,
 			    FT_R1KH_ID_LEN) != 0) {
 		wpa_printf(MSG_DEBUG, "FT: Unknown R1KH-ID used in "
 			   "ReassocReq");
 		wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID in FTIE",
 			    parse.r1kh_id, FT_R1KH_ID_LEN);
 		wpa_hexdump(MSG_DEBUG, "FT: Expected R1KH-ID",
-			    sm->wpa_auth->conf.r1_key_holder, FT_R1KH_ID_LEN);
+			    conf->r1_key_holder, FT_R1KH_ID_LEN);
 		return WLAN_STATUS_INVALID_FTIE;
 	}
 
@@ -3306,6 +3429,13 @@
 		return WLAN_STATUS_INVALID_FTIE;
 	}
 
+	if (rsnxe_used && (conf->sae_pwe == 1 || conf->sae_pwe == 2) &&
+	    !parse.rsnxe) {
+		wpa_printf(MSG_INFO,
+			   "FT: FTE indicated that STA uses RSNXE, but RSNXE was not included");
+		return WLAN_STATUS_UNSPECIFIED_FAILURE;
+	}
+
 #ifdef CONFIG_OCV
 	if (wpa_auth_uses_ocv(sm)) {
 		struct wpa_channel_info ci;
@@ -3687,6 +3817,10 @@
 		goto out;
 	}
 
+	wpa_printf(MSG_DEBUG, "FT: Send PMK-R1 pull response from " MACSTR
+		   " to " MACSTR,
+		   MAC2STR(wpa_auth->addr), MAC2STR(src_addr));
+
 	resp[0].type = FT_RRB_S1KH_ID;
 	resp[0].len = f_s1kh_id_len;
 	resp[0].data = f_s1kh_id;
@@ -4193,6 +4327,10 @@
 		goto out;
 	}
 
+	wpa_printf(MSG_DEBUG, "FT: Send sequence number response from " MACSTR
+		   " to " MACSTR,
+		   MAC2STR(wpa_auth->addr), MAC2STR(src_addr));
+
 	seq_resp_auth[0].type = FT_RRB_NONCE;
 	seq_resp_auth[0].len = f_nonce_len;
 	seq_resp_auth[0].data = f_nonce;
@@ -4452,9 +4590,11 @@
 	size_t alen, elen;
 	int no_defer = 0;
 
-	wpa_printf(MSG_DEBUG, "FT: RRB-OUI received frame from remote AP "
-		   MACSTR, MAC2STR(src_addr));
-	wpa_printf(MSG_DEBUG, "FT: RRB-OUI frame - oui_suffix=%d", oui_suffix);
+	wpa_printf(MSG_DEBUG, "FT: RRB-OUI(" MACSTR
+		   ") received frame from remote AP "
+		   MACSTR " oui_suffix=%u dst=" MACSTR,
+		   MAC2STR(wpa_auth->addr), MAC2STR(src_addr), oui_suffix,
+		   MAC2STR(dst_addr));
 	wpa_hexdump(MSG_MSGDUMP, "FT: RRB frame payload", data, data_len);
 
 	if (is_multicast_ether_addr(src_addr)) {
@@ -4464,13 +4604,8 @@
 		return;
 	}
 
-	if (is_multicast_ether_addr(dst_addr)) {
-		wpa_printf(MSG_DEBUG,
-			   "FT: RRB-OUI received frame from remote AP " MACSTR
-			   " to multicast address " MACSTR,
-			   MAC2STR(src_addr), MAC2STR(dst_addr));
+	if (is_multicast_ether_addr(dst_addr))
 		no_defer = 1;
-	}
 
 	if (data_len < sizeof(u16)) {
 		wpa_printf(MSG_DEBUG, "FT: RRB-OUI frame too short");
@@ -4545,6 +4680,10 @@
 		return -1;
 	}
 
+	wpa_printf(MSG_DEBUG, "FT: Send PMK-R1 push from " MACSTR
+		   " to remote R0KH address " MACSTR,
+		   MAC2STR(wpa_auth->addr), MAC2STR(r1kh->addr));
+
 	if (wpa_ft_rrb_build_r0(r1kh->key, sizeof(r1kh->key), push, pmk_r0,
 				r1kh->id, s1kh_id, push_auth, wpa_auth->addr,
 				FT_PACKET_R0KH_R1KH_PUSH,
diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
index 7fb0923..7a1ed24 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -37,8 +37,11 @@
 				  struct hostapd_config *iconf,
 				  struct wpa_auth_config *wconf)
 {
+	int sae_pw_id;
+
 	os_memset(wconf, 0, sizeof(*wconf));
 	wconf->wpa = conf->wpa;
+	wconf->extended_key_id = conf->extended_key_id;
 	wconf->wpa_key_mgmt = conf->wpa_key_mgmt;
 	wconf->wpa_pairwise = conf->wpa_pairwise;
 	wconf->wpa_group = conf->wpa_group;
@@ -65,6 +68,7 @@
 #endif /* CONFIG_OCV */
 	wconf->okc = conf->okc;
 	wconf->ieee80211w = conf->ieee80211w;
+	wconf->beacon_prot = conf->beacon_prot;
 	wconf->group_mgmt_cipher = conf->group_mgmt_cipher;
 	wconf->sae_require_mfp = conf->sae_require_mfp;
 #ifdef CONFIG_IEEE80211R_AP
@@ -118,14 +122,58 @@
 			  wpabuf_head(conf->own_ie_override),
 			  wconf->own_ie_override_len);
 	}
+	if (conf->rsne_override_eapol &&
+	    wpabuf_len(conf->rsne_override_eapol) <= MAX_OWN_IE_OVERRIDE) {
+		wconf->rsne_override_eapol_set = 1;
+		wconf->rsne_override_eapol_len =
+			wpabuf_len(conf->rsne_override_eapol);
+		os_memcpy(wconf->rsne_override_eapol,
+			  wpabuf_head(conf->rsne_override_eapol),
+			  wconf->rsne_override_eapol_len);
+	}
 	if (conf->rsnxe_override_eapol &&
 	    wpabuf_len(conf->rsnxe_override_eapol) <= MAX_OWN_IE_OVERRIDE) {
+		wconf->rsnxe_override_eapol_set = 1;
 		wconf->rsnxe_override_eapol_len =
 			wpabuf_len(conf->rsnxe_override_eapol);
 		os_memcpy(wconf->rsnxe_override_eapol,
 			  wpabuf_head(conf->rsnxe_override_eapol),
 			  wconf->rsnxe_override_eapol_len);
 	}
+	if (conf->rsne_override_ft &&
+	    wpabuf_len(conf->rsne_override_ft) <= MAX_OWN_IE_OVERRIDE) {
+		wconf->rsne_override_ft_set = 1;
+		wconf->rsne_override_ft_len =
+			wpabuf_len(conf->rsne_override_ft);
+		os_memcpy(wconf->rsne_override_ft,
+			  wpabuf_head(conf->rsne_override_ft),
+			  wconf->rsne_override_ft_len);
+	}
+	if (conf->rsnxe_override_ft &&
+	    wpabuf_len(conf->rsnxe_override_ft) <= MAX_OWN_IE_OVERRIDE) {
+		wconf->rsnxe_override_ft_set = 1;
+		wconf->rsnxe_override_ft_len =
+			wpabuf_len(conf->rsnxe_override_ft);
+		os_memcpy(wconf->rsnxe_override_ft,
+			  wpabuf_head(conf->rsnxe_override_ft),
+			  wconf->rsnxe_override_ft_len);
+	}
+	if (conf->gtk_rsc_override &&
+	    wpabuf_len(conf->gtk_rsc_override) > 0 &&
+	    wpabuf_len(conf->gtk_rsc_override) <= WPA_KEY_RSC_LEN) {
+		os_memcpy(wconf->gtk_rsc_override,
+			  wpabuf_head(conf->gtk_rsc_override),
+			  wpabuf_len(conf->gtk_rsc_override));
+		wconf->gtk_rsc_override_set = 1;
+	}
+	if (conf->igtk_rsc_override &&
+	    wpabuf_len(conf->igtk_rsc_override) > 0 &&
+	    wpabuf_len(conf->igtk_rsc_override) <= WPA_KEY_RSC_LEN) {
+		os_memcpy(wconf->igtk_rsc_override,
+			  wpabuf_head(conf->igtk_rsc_override),
+			  wpabuf_len(conf->igtk_rsc_override));
+		wconf->igtk_rsc_override_set = 1;
+	}
 #endif /* CONFIG_TESTING_OPTIONS */
 #ifdef CONFIG_P2P
 	os_memcpy(wconf->ip_addr_go, conf->ip_addr_go, 4);
@@ -139,6 +187,18 @@
 		  FILS_CACHE_ID_LEN);
 #endif /* CONFIG_FILS */
 	wconf->sae_pwe = conf->sae_pwe;
+	sae_pw_id = hostapd_sae_pw_id_in_use(conf);
+	if (sae_pw_id == 2 && wconf->sae_pwe != 3)
+		wconf->sae_pwe = 1;
+	else if (sae_pw_id == 1 && wconf->sae_pwe == 0)
+		wconf->sae_pwe = 2;
+#ifdef CONFIG_OWE
+	wconf->owe_ptk_workaround = conf->owe_ptk_workaround;
+#endif /* CONFIG_OWE */
+	wconf->transition_disable = conf->transition_disable;
+#ifdef CONFIG_DPP2
+	wconf->dpp_pfs = conf->dpp_pfs;
+#endif /* CONFIG_DPP2 */
 }
 
 
@@ -362,19 +422,27 @@
 
 static int hostapd_wpa_auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg,
 				    const u8 *addr, int idx, u8 *key,
-				    size_t key_len)
+				    size_t key_len, enum key_flag key_flag)
 {
 	struct hostapd_data *hapd = ctx;
 	const char *ifname = hapd->conf->iface;
 
 	if (vlan_id > 0) {
 		ifname = hostapd_get_vlan_id_ifname(hapd->conf->vlan, vlan_id);
-		if (ifname == NULL)
-			return -1;
+		if (!ifname) {
+			if (!(hapd->iface->drv_flags &
+			      WPA_DRIVER_FLAGS_VLAN_OFFLOAD))
+				return -1;
+			ifname = hapd->conf->iface;
+		}
 	}
 
 #ifdef CONFIG_TESTING_OPTIONS
-	if (addr && !is_broadcast_ether_addr(addr)) {
+	if (key_flag & KEY_FLAG_MODIFY) {
+		/* We are updating an already installed key. Don't overwrite
+		 * the already stored key information with zeros.
+		 */
+	} else if (addr && !is_broadcast_ether_addr(addr)) {
 		struct sta_info *sta;
 
 		sta = ap_get_sta(hapd, addr);
@@ -402,8 +470,8 @@
 		hapd->last_gtk_len = key_len;
 	}
 #endif /* CONFIG_TESTING_OPTIONS */
-	return hostapd_drv_set_key(ifname, hapd, alg, addr, idx, 1, NULL, 0,
-				   key, key_len);
+	return hostapd_drv_set_key(ifname, hapd, alg, addr, idx, vlan_id, 1,
+				   NULL, 0, key, key_len, key_flag);
 }
 
 
@@ -623,10 +691,6 @@
 	}
 #endif /* CONFIG_IEEE80211R_AP */
 
-	if (hapd->driver && hapd->driver->send_ether)
-		return hapd->driver->send_ether(hapd->drv_priv, dst,
-						hapd->own_addr, proto,
-						data, data_len);
 	if (hapd->l2 == NULL)
 		return -1;
 
@@ -688,6 +752,12 @@
 	dl_list_for_each_safe(data, n, &hapd->l2_oui_queue,
 			      struct oui_deliver_later_data, list) {
 		oui_ctx = hostapd_wpa_get_oui(hapd, data->oui_suffix);
+		wpa_printf(MSG_DEBUG, "RRB(%s): %s src=" MACSTR " dst=" MACSTR
+			   " oui_suffix=%u data_len=%u data=%p",
+			   hapd->conf->iface, __func__,
+			   MAC2STR(data->src_addr), MAC2STR(data->dst_addr),
+			   data->oui_suffix, (unsigned int) data->data_len,
+			   data);
 		if (hapd->wpa_auth && oui_ctx) {
 			eth_p_oui_deliver(oui_ctx, data->src_addr,
 					  data->dst_addr,
@@ -712,16 +782,26 @@
 {
 	struct wpa_auth_oui_iface_iter_data *idata = ctx;
 	struct oui_deliver_later_data *data;
-	struct hostapd_data *hapd;
+	struct hostapd_data *hapd, *src_hapd = idata->src_hapd;
 	size_t j;
 
 	for (j = 0; j < iface->num_bss; j++) {
 		hapd = iface->bss[j];
-		if (hapd == idata->src_hapd)
-			continue;
+		if (hapd == src_hapd)
+			continue; /* don't deliver back to same interface */
+		if (!wpa_key_mgmt_ft(hapd->conf->wpa_key_mgmt) ||
+		    hapd->conf->ssid.ssid_len !=
+		    src_hapd->conf->ssid.ssid_len ||
+		    os_memcmp(hapd->conf->ssid.ssid,
+			      src_hapd->conf->ssid.ssid,
+			      hapd->conf->ssid.ssid_len) != 0 ||
+		    os_memcmp(hapd->conf->mobility_domain,
+			      src_hapd->conf->mobility_domain,
+			      MOBILITY_DOMAIN_ID_LEN) != 0)
+			continue; /* no matching FT SSID/mobility domain */
 		if (!is_multicast_ether_addr(idata->dst_addr) &&
 		    os_memcmp(hapd->own_addr, idata->dst_addr, ETH_ALEN) != 0)
-			continue;
+			continue; /* destination address does not match */
 
 		/* defer eth_p_oui_deliver until next eloop step as this is
 		 * when it would be triggerd from reading from sock
@@ -733,14 +813,20 @@
 		data = os_zalloc(sizeof(*data) + idata->data_len);
 		if (!data)
 			return 1;
+		wpa_printf(MSG_DEBUG,
+			   "RRB(%s): local delivery to %s dst=" MACSTR
+			   " oui_suffix=%u data_len=%u data=%p",
+			   src_hapd->conf->iface, hapd->conf->iface,
+			   MAC2STR(idata->dst_addr), idata->oui_suffix,
+			   (unsigned int) idata->data_len, data);
 
-		os_memcpy(data->src_addr, idata->src_hapd->own_addr, ETH_ALEN);
+		os_memcpy(data->src_addr, src_hapd->own_addr, ETH_ALEN);
 		os_memcpy(data->dst_addr, idata->dst_addr, ETH_ALEN);
 		os_memcpy(data + 1, idata->data, idata->data_len);
 		data->data_len = idata->data_len;
 		data->oui_suffix = idata->oui_suffix;
 
-		dl_list_add(&hapd->l2_oui_queue, &data->list);
+		dl_list_add_tail(&hapd->l2_oui_queue, &data->list);
 
 		if (!eloop_is_timeout_registered(hostapd_oui_deliver_later,
 						 hapd, NULL))
@@ -748,7 +834,11 @@
 					       hostapd_oui_deliver_later,
 					       hapd, NULL);
 
-		return 1;
+		/* If dst_addr is a multicast address, do not return any
+		 * non-zero value here. Otherwise, the iteration of
+		 * for_each_interface() will be stopped. */
+		if (!is_multicast_ether_addr(idata->dst_addr))
+			return 1;
 	}
 
 	return 0;
@@ -764,6 +854,10 @@
 	struct hostapd_data *hapd = ctx;
 	struct eth_p_oui_ctx *oui_ctx;
 
+	wpa_printf(MSG_DEBUG, "RRB(%s): send to dst=" MACSTR
+		   " oui_suffix=%u data_len=%u",
+		   hapd->conf->iface, MAC2STR(dst), oui_suffix,
+		   (unsigned int) data_len);
 #ifdef CONFIG_IEEE80211R_AP
 	if (hapd->iface->interfaces &&
 	    hapd->iface->interfaces->for_each_interface) {
@@ -807,26 +901,32 @@
 #ifndef CONFIG_NO_VLAN
 	struct hostapd_data *hapd = ctx;
 	struct sta_info *sta;
-	struct vlan_description vlan_desc;
 
 	sta = ap_get_sta(hapd, addr);
 	if (!sta)
 		return -1;
 
-	os_memset(&vlan_desc, 0, sizeof(vlan_desc));
-	vlan_desc.notempty = 1;
-	vlan_desc.untagged = vlan_id;
-	if (!hostapd_vlan_valid(hapd->conf->vlan, &vlan_desc)) {
-		wpa_printf(MSG_INFO, "Invalid VLAN ID %d in wpa_psk_file",
-			   vlan_id);
-		return -1;
-	}
+	if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_VLAN_OFFLOAD)) {
+		struct vlan_description vlan_desc;
 
-	if (ap_sta_set_vlan(hapd, sta, &vlan_desc) < 0) {
-		wpa_printf(MSG_INFO,
-			   "Failed to assign VLAN ID %d from wpa_psk_file to "
-			   MACSTR, vlan_id, MAC2STR(sta->addr));
-		return -1;
+		os_memset(&vlan_desc, 0, sizeof(vlan_desc));
+		vlan_desc.notempty = 1;
+		vlan_desc.untagged = vlan_id;
+		if (!hostapd_vlan_valid(hapd->conf->vlan, &vlan_desc)) {
+			wpa_printf(MSG_INFO,
+				   "Invalid VLAN ID %d in wpa_psk_file",
+				   vlan_id);
+			return -1;
+		}
+
+		if (ap_sta_set_vlan(hapd, sta, &vlan_desc) < 0) {
+			wpa_printf(MSG_INFO,
+				   "Failed to assign VLAN ID %d from wpa_psk_file to "
+				   MACSTR, vlan_id, MAC2STR(sta->addr));
+			return -1;
+		}
+	} else {
+		sta->vlan_id = vlan_id;
 	}
 
 	wpa_printf(MSG_INFO,
@@ -888,7 +988,7 @@
 	os_memcpy(m->bssid, hapd->own_addr, ETH_ALEN);
 	os_memcpy(&m->u, data, data_len);
 
-	res = hostapd_drv_send_mlme(hapd, (u8 *) m, mlen, 0);
+	res = hostapd_drv_send_mlme(hapd, (u8 *) m, mlen, 0, NULL, 0, 0);
 	os_free(m);
 	return res;
 }
@@ -1318,6 +1418,22 @@
 		_conf.tx_status = 1;
 	if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_MLME)
 		_conf.ap_mlme = 1;
+
+	if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_WIRED) &&
+	    (hapd->conf->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_NEVER ||
+	     (hapd->conf->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_LOCAL_OK &&
+	      !(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS)))) {
+		wpa_msg(hapd->msg_ctx, MSG_INFO,
+			"Disable PTK0 rekey support - replaced with disconnect");
+		_conf.wpa_deny_ptk0_rekey = 1;
+	}
+
+	if (_conf.extended_key_id &&
+	    (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID))
+		wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Extended Key ID supported");
+	else
+		_conf.extended_key_id = 0;
+
 	hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb, hapd);
 	if (hapd->wpa_auth == NULL) {
 		wpa_printf(MSG_ERROR, "WPA initialization failed.");
@@ -1352,9 +1468,7 @@
 			   hapd->conf->iface;
 		hapd->l2 = l2_packet_init(ft_iface, NULL, ETH_P_RRB,
 					  hostapd_rrb_receive, hapd, 1);
-		if (hapd->l2 == NULL &&
-		    (hapd->driver == NULL ||
-		     hapd->driver->send_ether == NULL)) {
+		if (!hapd->l2) {
 			wpa_printf(MSG_ERROR, "Failed to open l2_packet "
 				   "interface");
 			return -1;
diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h
index a993f50..bc59d6a 100644
--- a/src/ap/wpa_auth_i.h
+++ b/src/ap/wpa_auth_i.h
@@ -61,6 +61,8 @@
 	unsigned int pmk_len;
 	u8 pmkid[PMKID_LEN]; /* valid if pmkid_set == 1 */
 	struct wpa_ptk PTK;
+	u8 keyidx_active;
+	Boolean use_ext_key_id;
 	Boolean PTK_valid;
 	Boolean pairwise_set;
 	Boolean tk_already_set;
@@ -193,7 +195,9 @@
 	Boolean first_sta_seen;
 	Boolean reject_4way_hs_for_entropy;
 	u8 IGTK[2][WPA_IGTK_MAX_LEN];
+	u8 BIGTK[2][WPA_IGTK_MAX_LEN];
 	int GN_igtk, GM_igtk;
+	int GN_bigtk, GM_bigtk;
 	/* Number of references except those in struct wpa_group->next */
 	unsigned int references;
 	unsigned int num_setup_iface;
@@ -292,7 +296,7 @@
 		   const u8 *r0kh_id, size_t r0kh_id_len,
 		   const u8 *anonce, const u8 *snonce,
 		   u8 *buf, size_t len, const u8 *subelem,
-		   size_t subelem_len);
+		   size_t subelem_len, int rsnxe_used);
 int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, struct wpa_ptk *ptk);
 struct wpa_ft_pmk_cache * wpa_ft_pmk_cache_init(void);
 void wpa_ft_pmk_cache_deinit(struct wpa_ft_pmk_cache *cache);
diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c
index 2e6d059..2ac1df4 100644
--- a/src/ap/wpa_auth_ie.c
+++ b/src/ap/wpa_auth_ie.c
@@ -297,6 +297,8 @@
 	if (rsn_testing)
 		capab |= BIT(8) | BIT(15);
 #endif /* CONFIG_RSN_TESTING */
+	if (conf->extended_key_id)
+		capab |= WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST;
 	WPA_PUT_LE16(pos, capab);
 	pos += 2;
 
@@ -546,13 +548,15 @@
 }
 
 
-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)
+enum wpa_validate_result
+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)
 {
+	struct wpa_auth_config *conf = &wpa_auth->conf;
 	struct wpa_ie_data data;
 	int ciphers, key_mgmt, res, version;
 	u32 selector;
@@ -860,6 +864,16 @@
 	}
 #endif /* CONFIG_OWE */
 
+#ifdef CONFIG_DPP2
+	if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP &&
+	    ((conf->dpp_pfs == 1 && !owe_dh) ||
+	     (conf->dpp_pfs == 2 && owe_dh))) {
+		wpa_printf(MSG_DEBUG, "DPP: PFS %s",
+			   conf->dpp_pfs == 1 ? "required" : "not allowed");
+		return WPA_DENIED_OTHER_REASON;
+	}
+#endif /* CONFIG_DPP2 */
+
 	sm->pairwise = wpa_pick_pairwise_cipher(ciphers, 0);
 	if (sm->pairwise < 0)
 		return WPA_INVALID_PAIRWISE;
@@ -944,6 +958,23 @@
 	}
 #endif /* CONFIG_DPP */
 
+	if (conf->extended_key_id && sm->wpa == WPA_VERSION_WPA2 &&
+	    sm->pairwise != WPA_CIPHER_TKIP &&
+	    (data.capabilities & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST)) {
+		sm->use_ext_key_id = TRUE;
+		if (conf->extended_key_id == 2 &&
+		    !wpa_key_mgmt_ft(sm->wpa_key_mgmt) &&
+		    !wpa_key_mgmt_fils(sm->wpa_key_mgmt))
+			sm->keyidx_active = 1;
+		else
+			sm->keyidx_active = 0;
+		wpa_printf(MSG_DEBUG,
+			   "RSN: Extended Key ID supported (start with %d)",
+			   sm->keyidx_active);
+	} else {
+		sm->use_ext_key_id = FALSE;
+	}
+
 	if (sm->wpa_ie == NULL || sm->wpa_ie_len < wpa_ie_len) {
 		os_free(sm->wpa_ie);
 		sm->wpa_ie = os_malloc(wpa_ie_len);
diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c
index 175b9fc..1d77b94 100644
--- a/src/ap/wps_hostapd.c
+++ b/src/ap/wps_hostapd.c
@@ -125,6 +125,7 @@
 	os_memcpy(p->addr, mac_addr, ETH_ALEN);
 	os_memcpy(p->p2p_dev_addr, p2p_dev_addr, ETH_ALEN);
 	os_memcpy(p->psk, psk, PMK_LEN);
+	p->wps = 1;
 
 	if (hapd->new_psk_cb) {
 		hapd->new_psk_cb(hapd->new_psk_cb_ctx, mac_addr, p2p_dev_addr,
@@ -137,16 +138,17 @@
 	if (ssid->wpa_psk_file) {
 		FILE *f;
 		char hex[PMK_LEN * 2 + 1];
+
 		/* Add the new PSK to PSK list file */
 		f = fopen(ssid->wpa_psk_file, "a");
-		if (f == NULL) {
-			wpa_printf(MSG_DEBUG, "Failed to add the PSK to "
-				   "'%s'", ssid->wpa_psk_file);
+		if (!f) {
+			wpa_printf(MSG_DEBUG, "Failed to add the PSK to '%s'",
+				   ssid->wpa_psk_file);
 			return -1;
 		}
 
 		wpa_snprintf_hex(hex, sizeof(hex), psk, psk_len);
-		fprintf(f, MACSTR " %s\n", MAC2STR(mac_addr), hex);
+		fprintf(f, "wps=1 " MACSTR " %s\n", MAC2STR(mac_addr), hex);
 		fclose(f);
 	}
 
@@ -269,6 +271,44 @@
 }
 
 
+static int hostapd_wps_lookup_pskfile_cb(void *ctx, const u8 *mac_addr,
+					 const u8 **psk)
+{
+	const struct hostapd_data *hapd = ctx;
+	const struct hostapd_wpa_psk *wpa_psk;
+	const u8 *any_psk = NULL;
+	const u8 *dev_psk = NULL;
+
+	for (wpa_psk = hapd->conf->ssid.wpa_psk; wpa_psk;
+	     wpa_psk = wpa_psk->next) {
+		if (!wpa_psk->wps)
+			continue;
+
+		if (!any_psk && is_zero_ether_addr(wpa_psk->addr))
+			any_psk = wpa_psk->psk;
+
+		if (mac_addr && !dev_psk &&
+		    os_memcmp(mac_addr, wpa_psk->addr, ETH_ALEN) == 0) {
+			dev_psk = wpa_psk->psk;
+			break;
+		}
+	}
+
+	if (dev_psk) {
+		*psk = dev_psk;
+	} else if (any_psk) {
+		*psk = any_psk;
+	} else {
+		*psk = NULL;
+		wpa_printf(MSG_DEBUG,
+			   "WPS: No appropriate PSK in wpa_psk_file");
+		return 0;
+	}
+
+	return 1;
+}
+
+
 static void wps_reload_config(void *eloop_data, void *user_ctx)
 {
 	struct hostapd_iface *iface = eloop_data;
@@ -611,8 +651,10 @@
 		    (str_starts(buf, "ssid=") ||
 		     str_starts(buf, "ssid2=") ||
 		     str_starts(buf, "auth_algs=") ||
+#ifdef CONFIG_WEP
 		     str_starts(buf, "wep_default_key=") ||
 		     str_starts(buf, "wep_key") ||
+#endif /* CONFIG_WEP */
 		     str_starts(buf, "wps_state=") ||
 		     (pmf_changed && str_starts(buf, "ieee80211w=")) ||
 		     str_starts(buf, "wpa=") ||
@@ -985,6 +1027,21 @@
 }
 
 
+static int hostapd_wps_set_application_ext(struct hostapd_data *hapd,
+					   struct wps_context *wps)
+{
+	wpabuf_free(wps->dev.application_ext);
+
+	if (!hapd->conf->wps_application_ext) {
+		wps->dev.application_ext = NULL;
+		return 0;
+	}
+
+	wps->dev.application_ext = wpabuf_dup(hapd->conf->wps_application_ext);
+	return wps->dev.application_ext ? 0 : -1;
+}
+
+
 static void hostapd_free_wps(struct wps_context *wps)
 {
 	int i;
@@ -1074,7 +1131,8 @@
 	os_memcpy(wps->dev.pri_dev_type, hapd->conf->device_type,
 		  WPS_DEV_TYPE_LEN);
 
-	if (hostapd_wps_set_vendor_ext(hapd, wps) < 0)
+	if (hostapd_wps_set_vendor_ext(hapd, wps) < 0 ||
+	    hostapd_wps_set_application_ext(hapd, wps) < 0)
 		goto fail;
 
 	wps->dev.os_version = WPA_GET_BE32(hapd->conf->os_version);
@@ -1140,6 +1198,7 @@
 		wpa_snprintf_hex((char *) wps->network_key, 2 * PMK_LEN + 1,
 				 conf->ssid.wpa_psk->psk, PMK_LEN);
 		wps->network_key_len = 2 * PMK_LEN;
+#ifdef CONFIG_WEP
 	} else if (conf->ssid.wep.keys_set && conf->ssid.wep.key[0]) {
 		wps->network_key = os_malloc(conf->ssid.wep.len[0]);
 		if (wps->network_key == NULL)
@@ -1147,6 +1206,7 @@
 		os_memcpy(wps->network_key, conf->ssid.wep.key[0],
 			  conf->ssid.wep.len[0]);
 		wps->network_key_len = conf->ssid.wep.len[0];
+#endif /* CONFIG_WEP */
 	}
 
 	if (conf->ssid.wpa_psk) {
@@ -1197,14 +1257,13 @@
 	cfg.pin_needed_cb = hostapd_wps_pin_needed_cb;
 	cfg.reg_success_cb = hostapd_wps_reg_success_cb;
 	cfg.enrollee_seen_cb = hostapd_wps_enrollee_seen_cb;
+	cfg.lookup_pskfile_cb = hostapd_wps_lookup_pskfile_cb;
 	cfg.cb_ctx = hapd;
 	cfg.skip_cred_build = conf->skip_cred_build;
 	cfg.extra_cred = conf->extra_cred;
 	cfg.extra_cred_len = conf->extra_cred_len;
 	cfg.disable_auto_conf = (hapd->conf->wps_cred_processing == 1) &&
 		conf->skip_cred_build;
-	if (conf->ssid.security_policy == SECURITY_STATIC_WEP)
-		cfg.static_wep_only = 1;
 	cfg.dualband = interface_count(hapd->iface) > 1;
 	if ((wps->dev.rf_bands & (WPS_RF_50GHZ | WPS_RF_24GHZ)) ==
 	    (WPS_RF_50GHZ | WPS_RF_24GHZ))
@@ -1311,6 +1370,7 @@
 #endif /* CONFIG_WPS_UPNP */
 
 	hostapd_wps_set_vendor_ext(hapd, hapd->wps);
+	hostapd_wps_set_application_ext(hapd, hapd->wps);
 
 	if (hapd->conf->wps_state)
 		wps_registrar_update_ie(hapd->wps->registrar);