[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/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
index 309127e..65c639b 100644
--- a/wpa_supplicant/Android.mk
+++ b/wpa_supplicant/Android.mk
@@ -124,6 +124,7 @@
 OBJS += src/utils/wpabuf.c
 OBJS += src/utils/bitfield.c
 OBJS += src/utils/ip_addr.c
+OBJS += src/utils/crc32.c
 OBJS += wmm_ac.c
 OBJS += op_classes.c
 OBJS += rrm.c
@@ -195,6 +196,10 @@
 L_CFLAGS += -DCONFIG_VHT_OVERRIDES
 endif
 
+ifdef CONFIG_HE_OVERRIDES
+L_CFLAGS += -DCONFIG_HE_OVERRIDES
+endif
+
 ifndef CONFIG_BACKEND
 CONFIG_BACKEND=file
 endif
@@ -282,6 +287,7 @@
 NEED_JSON=y
 NEED_GAS_SERVER=y
 NEED_BASE64=y
+NEED_ASN1=y
 ifdef CONFIG_DPP2
 L_CFLAGS += -DCONFIG_DPP2
 endif
@@ -410,6 +416,10 @@
 endif
 endif
 
+ifdef CONFIG_WEP
+L_CFLAGS += -DCONFIG_WEP
+endif
+
 
 include $(LOCAL_PATH)/src/drivers/drivers.mk
 
@@ -890,7 +900,6 @@
 OBJS += src/ap/eap_user_db.c
 OBJS += src/ap/neighbor_db.c
 OBJS += src/ap/rrm.c
-ifdef CONFIG_IEEE80211N
 OBJS += src/ap/ieee802_11_ht.c
 ifdef CONFIG_IEEE80211AC
 OBJS += src/ap/ieee802_11_vht.c
@@ -898,7 +907,6 @@
 ifdef CONFIG_IEEE80211AX
 OBJS += src/ap/ieee802_11_he.c
 endif
-endif
 ifdef CONFIG_WNM_AP
 L_CFLAGS += -DCONFIG_WNM_AP
 OBJS += src/ap/wnm_ap.c
@@ -918,15 +926,12 @@
 OBJS += src/eap_server/eap_server_identity.c
 OBJS += src/eap_server/eap_server_methods.c
 
-ifdef CONFIG_IEEE80211N
-L_CFLAGS += -DCONFIG_IEEE80211N
 ifdef CONFIG_IEEE80211AC
 L_CFLAGS += -DCONFIG_IEEE80211AC
 endif
 ifdef CONFIG_IEEE80211AX
 L_CFLAGS += -DCONFIG_IEEE80211AX
 endif
-endif
 
 ifdef NEED_AP_MLME
 OBJS += src/ap/wmm.c
@@ -1123,7 +1128,7 @@
 OBJS += src/tls/tlsv1_client_write.c
 OBJS += src/tls/tlsv1_client_read.c
 OBJS += src/tls/tlsv1_client_ocsp.c
-OBJS += src/tls/asn1.c
+NEED_ASN1=y
 OBJS += src/tls/rsa.c
 OBJS += src/tls/x509v3.c
 OBJS += src/tls/pkcs1.c
@@ -1413,6 +1418,10 @@
 OBJS += src/crypto/sha512-prf.c
 endif
 
+ifdef NEED_ASN1
+OBJS += src/tls/asn1.c
+endif
+
 ifdef NEED_DH_GROUPS
 OBJS += src/crypto/dh_groups.c
 endif
diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile
index 68ef5a2..45f673e 100644
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -104,6 +104,7 @@
 OBJS += ../src/utils/wpabuf.o
 OBJS += ../src/utils/bitfield.o
 OBJS += ../src/utils/ip_addr.o
+OBJS += ../src/utils/crc32.o
 OBJS += op_classes.o
 OBJS += rrm.o
 OBJS_p = wpa_passphrase.o
@@ -197,6 +198,10 @@
 CFLAGS += -DCONFIG_VHT_OVERRIDES
 endif
 
+ifdef CONFIG_HE_OVERRIDES
+CFLAGS += -DCONFIG_HE_OVERRIDES
+endif
+
 ifndef CONFIG_BACKEND
 CONFIG_BACKEND=file
 endif
@@ -284,6 +289,7 @@
 NEED_JSON=y
 NEED_GAS_SERVER=y
 NEED_BASE64=y
+NEED_ASN1=y
 ifdef CONFIG_DPP2
 CFLAGS += -DCONFIG_DPP2
 endif
@@ -906,7 +912,6 @@
 OBJS += ../src/ap/eap_user_db.o
 OBJS += ../src/ap/neighbor_db.o
 OBJS += ../src/ap/rrm.o
-ifdef CONFIG_IEEE80211N
 OBJS += ../src/ap/ieee802_11_ht.o
 ifdef CONFIG_IEEE80211AC
 OBJS += ../src/ap/ieee802_11_vht.o
@@ -914,7 +919,6 @@
 ifdef CONFIG_IEEE80211AX
 OBJS += ../src/ap/ieee802_11_he.o
 endif
-endif
 ifdef CONFIG_WNM_AP
 CFLAGS += -DCONFIG_WNM_AP
 OBJS += ../src/ap/wnm_ap.o
@@ -934,15 +938,12 @@
 OBJS += ../src/eap_server/eap_server_identity.o
 OBJS += ../src/eap_server/eap_server_methods.o
 
-ifdef CONFIG_IEEE80211N
-CFLAGS += -DCONFIG_IEEE80211N
 ifdef CONFIG_IEEE80211AC
 CFLAGS += -DCONFIG_IEEE80211AC
 endif
 ifdef CONFIG_IEEE80211AX
 CFLAGS += -DCONFIG_IEEE80211AX
 endif
-endif
 
 ifdef NEED_AP_MLME
 OBJS += ../src/ap/wmm.o
@@ -1156,12 +1157,12 @@
 OBJS += ../src/tls/tlsv1_client_write.o
 OBJS += ../src/tls/tlsv1_client_read.o
 OBJS += ../src/tls/tlsv1_client_ocsp.o
-OBJS += ../src/tls/asn1.o
 OBJS += ../src/tls/rsa.o
 OBJS += ../src/tls/x509v3.o
 OBJS += ../src/tls/pkcs1.o
 OBJS += ../src/tls/pkcs5.o
 OBJS += ../src/tls/pkcs8.o
+NEED_ASN1=y
 NEED_BASE64=y
 NEED_TLS_PRF=y
 ifdef CONFIG_TLSV12
@@ -1235,12 +1236,12 @@
 OBJS += ../src/tls/tlsv1_client_write.o
 OBJS += ../src/tls/tlsv1_client_read.o
 OBJS += ../src/tls/tlsv1_client_ocsp.o
-OBJS += ../src/tls/asn1.o
 OBJS += ../src/tls/rsa.o
 OBJS += ../src/tls/x509v3.o
 OBJS += ../src/tls/pkcs1.o
 OBJS += ../src/tls/pkcs5.o
 OBJS += ../src/tls/pkcs8.o
+NEED_ASN1=y
 NEED_BASE64=y
 NEED_TLS_PRF=y
 ifdef CONFIG_TLSV12
@@ -1523,6 +1524,10 @@
 OBJS += ../src/crypto/sha512-prf.o
 endif
 
+ifdef NEED_ASN1
+OBJS += ../src/tls/asn1.o
+endif
+
 ifdef NEED_DH_GROUPS
 OBJS += ../src/crypto/dh_groups.o
 endif
@@ -1846,6 +1851,10 @@
 OBJS_nfc += $(FST_OBJS)
 endif
 
+ifdef CONFIG_WEP
+CFLAGS += -DCONFIG_WEP
+endif
+
 ifndef LDO
 LDO=$(CC)
 endif
diff --git a/wpa_supplicant/README-DPP b/wpa_supplicant/README-DPP
index 457e32e..d378245 100644
--- a/wpa_supplicant/README-DPP
+++ b/wpa_supplicant/README-DPP
@@ -9,40 +9,44 @@
 Introduction to DPP
 -------------------
 
-Device provisioning Protocol allows enrolling of interface-less devices
-in a secure Wi-Fi network using many methods like QR code based
-authentication( detailed below ), PKEX based authentication etc. In DPP
-a Configurator is used to provide network credentials to the devices.
-The three phases of DPP connection are authentication, configuration and
+Device Provisioning Protocol (also known as Wi-Fi Easy Connect) allows
+enrolling of interface-less devices in a secure Wi-Fi network using many
+methods like QR code based authentication (detailed below), PKEX based
+authentication (password with in-band provisioning), etc. In DPP a
+Configurator is used to provide network credentials to the devices. The
+three phases of DPP connection are authentication, configuration and
 network introduction.
 
+More information about Wi-Fi Easy Connect is available from this Wi-Fi
+Alliance web page:
+https://www.wi-fi.org/discover-wi-fi/wi-fi-easy-connect
+
 Build config setup
 ------------------
 
-The following changes must go in the config file used to compile hostapd
-and wpa_supplicant.
+The following parameters must be included in the config file used to
+compile hostapd and wpa_supplicant.
 
 wpa_supplicant build config
 ---------------------------
 
-Enable DPP and protected management frame in wpa_supplicant build config
-file
+Enable DPP in wpa_supplicant build config file
 
 CONFIG_DPP=y
 
 hostapd build config
 --------------------
 
-Enable DPP and protected management frame in hostapd build config file
+Enable DPP in hostapd build config file
 
 CONFIG_DPP=y
 
 Configurator build config
 -------------------------
 
-Any STA or AP device can act as a Configurator. Enable DPP and protected
-managment frames in build config. For an AP to act as Configurator,
-Interworking needs to be enabled. For wpa_supplicant it is not required.
+Any STA or AP device can act as a Configurator. Enable DPP in build
+config. For an AP to act as a Configurator, Interworking needs to be
+enabled for GAS. For wpa_supplicant it is not required.
 
 CONFIG_INTERWORKING=y
 
@@ -90,41 +94,46 @@
 > dpp_configurator_get_key <id>
 
 
-How to configure an enrollee using Configurator
+How to configure an Enrollee using Configurator
 -----------------------------------------------
 
-On enrollee side:
+On Enrollee side:
 
-Generate QR code for the device. Store the qr code id returned by the
+Generate QR code for the device. Store the QR code id returned by the
 command.
 
-> dpp_bootstrap_gen type=qrcode mac=<mac-address-of-device> chan=<operating-class/operating-channel> key=<key of the device>
-(returns bootstrapping info id)
+> dpp_bootstrap_gen type=qrcode mac=<mac-address-of-device> chan=<operating-class/channel> key=<key of the device>
+(Returns bootstrapping info id. If the key parameter is not included, a new key
+is generated automatically. The MAC address is specified without octet
+separating colons. The channel list includes the possible channels on which the
+device is waiting. This uses global operating classes; e.g., 81/1 is the 2.4
+GHz channel 1 on 2412 MHz.)
 
-Get QR Code of device using the bootstrap info id.
+Get URI for the QR Code of device using the bootstrap info id.
 > dpp_bootstrap_get_uri <bootstrap-id>
 
-Make device listen to DPP request (The central frequency of channel 1 is
-2412) in case if enrollee is a client device.
+Make device listen to DPP request. The central frequency of the 2.4 GHz
+band channel 1 is 2412 MHz) in case the Enrollee is a client device. An
+AP as an Enrollee is listening on its operating channel.
 
 > dpp_listen <frequency>
 
 On Configurator side:
 
 Enter the QR Code in the Configurator.
-> dpp_qr_code "<QR-Code-read-from-enrollee>"
+> dpp_qr_code "<URI-from-QR-Code-read-from-enrollee>"
 
 On successfully adding QR Code, a bootstrapping info id is returned.
 
-Send provisioning request to enrollee. (conf is ap-dpp if enrollee is an
-AP. conf is sta-dpp if enrollee is a client)
+Send provisioning request to Enrollee. (conf is ap-dpp if Enrollee is an
+AP. conf is sta-dpp if Enrollee is a client)
 > dpp_auth_init peer=<qr-code-id> conf=<ap-dpp|sta-dpp> ssid=<SSID hexdump> configurator=<configurator-id>
 or for legacy (PSK/SAE) provisioning for a station Enrollee:
 > dpp_auth_init peer=<qr-code-id> conf=sta-psk ssid=<SSID hexdump> pass=<passphrase hexdump>
 
-The DPP values will be printed in the console. Save this values into the
-config file. If the enrollee is an AP, we need to manually write these
-values to the hostapd config file. If the enrollee is a client device,
+The DPP values will be printed in the console. Save these values into the
+config file. If the Enrollee is an AP, we need to manually write these
+values to the hostapd config file. If the Enrollee is a client device,
 these details can be automatically saved to config file using the
 following command.
 
@@ -156,7 +165,7 @@
 
 > dpp_configurator_add
 (returns configurator id)
-> dpp_configurator_sign conf=<ap-dpp|sta-dpp> configurator=<configurator-id>
+> dpp_configurator_sign conf=<ap-dpp|sta-dpp> configurator=<configurator-id> ssid=<SSID hexdump>
 
 
 Sample AP configuration files after provisioning
diff --git a/wpa_supplicant/android.config b/wpa_supplicant/android.config
index d05141f..1c3c937 100644
--- a/wpa_supplicant/android.config
+++ b/wpa_supplicant/android.config
@@ -435,11 +435,7 @@
 # either wpa_supplicant or hostapd are run.
 CONFIG_NO_RANDOM_POOL=y
 
-# IEEE 802.11n (High Throughput) support (mainly for AP mode)
-CONFIG_IEEE80211N=y
-
 # IEEE 802.11ac (Very High Throughput) support (mainly for AP mode)
-# (depends on CONFIG_IEEE80211N)
 #CONFIG_IEEE80211AC=y
 
 # Wireless Network Management (IEEE Std 802.11v-2011)
@@ -554,4 +550,12 @@
 # Note: does not configure WAPI implementation itself.
 #CONFIG_WAPI_INTERFACE=y
 
+# Wired equivalent privacy (WEP)
+# WEP is an obsolete cryptographic data confidentiality algorithm that is not
+# considered secure. It should not be used for anything anymore. The
+# functionality needed to use WEP is available in the current wpa_supplicant
+# release under this optional build parameter. This functionality is subject to
+# be completely removed in a future release.
+CONFIG_WEP=y
+
 include $(wildcard $(LOCAL_PATH)/android_config_*.inc)
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index e552306..6241682 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -44,7 +44,6 @@
 #endif /* CONFIG_WPS */
 
 
-#ifdef CONFIG_IEEE80211N
 static void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s,
 			     struct wpa_ssid *ssid,
 			     struct hostapd_config *conf,
@@ -130,7 +129,6 @@
 		conf->channel + conf->secondary_channel * 2;
 	conf->vht_oper_chwidth = CHANWIDTH_USE_HT;
 }
-#endif /* CONFIG_IEEE80211N */
 
 
 int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s,
@@ -149,7 +147,6 @@
 	/* TODO: enable HT40 if driver supports it;
 	 * drop to 11b if driver does not support 11g */
 
-#ifdef CONFIG_IEEE80211N
 	/*
 	 * Enable HT20 if the driver supports it, by setting conf->ieee80211n
 	 * and a mask of allowed capabilities within conf->ht_capab.
@@ -269,7 +266,6 @@
 			conf->no_pri_sec_switch = 1;
 		}
 	}
-#endif /* CONFIG_IEEE80211N */
 
 	return 0;
 }
@@ -348,7 +344,9 @@
 #endif /* CONFIG_IEEE80211AX */
 
 	bss->isolate = !wpa_s->conf->p2p_intra_bss;
+	bss->extended_key_id = wpa_s->conf->extended_key_id;
 	bss->force_per_enrollee_psk = wpa_s->global->p2p_per_sta_psk;
+	bss->wpa_deny_ptk0_rekey = ssid->wpa_deny_ptk0_rekey;
 
 	if (ssid->p2p_group) {
 		os_memcpy(bss->ip_addr_go, wpa_s->p2pdev->conf->ip_addr_go, 4);
@@ -393,6 +391,7 @@
 		bss->ssid.wpa_psk_set = 1;
 	} else if (ssid->passphrase) {
 		bss->ssid.wpa_passphrase = os_strdup(ssid->passphrase);
+#ifdef CONFIG_WEP
 	} else if (ssid->wep_key_len[0] || ssid->wep_key_len[1] ||
 		   ssid->wep_key_len[2] || ssid->wep_key_len[3]) {
 		struct hostapd_wep_keys *wep = &bss->ssid.wep;
@@ -408,6 +407,7 @@
 		}
 		wep->idx = ssid->wep_tx_keyidx;
 		wep->keys_set = 1;
+#endif /* CONFIG_WEP */
 	}
 #ifdef CONFIG_SAE
 	if (ssid->sae_password) {
@@ -489,11 +489,12 @@
 	bss->wpa_group = wpa_select_ap_group_cipher(bss->wpa, bss->wpa_pairwise,
 						    bss->rsn_pairwise);
 
-	if (bss->wpa && bss->ieee802_1x)
+	if (bss->wpa && bss->ieee802_1x) {
 		bss->ssid.security_policy = SECURITY_WPA;
-	else if (bss->wpa)
+	} else if (bss->wpa) {
 		bss->ssid.security_policy = SECURITY_WPA_PSK;
-	else if (bss->ieee802_1x) {
+#ifdef CONFIG_WEP
+	} else if (bss->ieee802_1x) {
 		int cipher = WPA_CIPHER_NONE;
 		bss->ssid.security_policy = SECURITY_IEEE_802_1X;
 		bss->ssid.wep.default_len = bss->default_wep_key_len;
@@ -511,6 +512,7 @@
 		bss->wpa_group = cipher;
 		bss->wpa_pairwise = cipher;
 		bss->rsn_pairwise = cipher;
+#endif /* CONFIG_WEP */
 	} else {
 		bss->ssid.security_policy = SECURITY_PLAINTEXT;
 		bss->wpa_group = WPA_CIPHER_NONE;
@@ -605,6 +607,8 @@
 	bss->ftm_responder = wpa_s->conf->ftm_responder;
 	bss->ftm_initiator = wpa_s->conf->ftm_initiator;
 
+	bss->transition_disable = ssid->transition_disable;
+
 	return 0;
 }
 
@@ -839,7 +843,6 @@
 		return -1;
 	hapd_iface->owner = wpa_s;
 	hapd_iface->drv_flags = wpa_s->drv_flags;
-	hapd_iface->smps_modes = wpa_s->drv_smps_modes;
 	hapd_iface->probe_resp_offloads = wpa_s->probe_resp_offloads;
 	hapd_iface->extended_capa = wpa_s->extended_capa;
 	hapd_iface->extended_capa_mask = wpa_s->extended_capa_mask;
diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c
index 943a340..127f43e 100644
--- a/wpa_supplicant/bss.c
+++ b/wpa_supplicant/bss.c
@@ -906,7 +906,7 @@
 		}
 	}
 
-	wpa_printf(MSG_DEBUG, "BSS: last_scan_res_used=%u/%u",
+	wpa_printf(MSG_DEBUG, "BSS: last_scan_res_used=%zu/%zu",
 		   wpa_s->last_scan_res_used, wpa_s->last_scan_res_size);
 }
 
diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h
index 3ce8cd3..0716761 100644
--- a/wpa_supplicant/bss.h
+++ b/wpa_supplicant/bss.h
@@ -18,6 +18,7 @@
 #define WPA_BSS_AUTHENTICATED		BIT(4)
 #define WPA_BSS_ASSOCIATED		BIT(5)
 #define WPA_BSS_ANQP_FETCH_TRIED	BIT(6)
+#define WPA_BSS_OWE_TRANSITION		BIT(7)
 
 struct wpa_bss_anqp_elem {
 	struct dl_list list;
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index 2d1c126..e1d9824 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -1856,6 +1856,8 @@
 #endif /* IEEE8021X_EAPOL */
 
 
+#ifdef CONFIG_WEP
+
 static int wpa_config_parse_wep_key(u8 *key, size_t *len, int line,
 				    const char *value, int idx)
 {
@@ -1966,6 +1968,8 @@
 }
 #endif /* NO_CONFIG_WRITE */
 
+#endif /* CONFIG_WEP */
+
 
 #ifdef CONFIG_P2P
 
@@ -2451,11 +2455,13 @@
 	{ STRe(openssl_ciphers, openssl_ciphers) },
 	{ INTe(erp, erp) },
 #endif /* IEEE8021X_EAPOL */
+#ifdef CONFIG_WEP
 	{ FUNC_KEY(wep_key0) },
 	{ FUNC_KEY(wep_key1) },
 	{ FUNC_KEY(wep_key2) },
 	{ FUNC_KEY(wep_key3) },
 	{ INT(wep_tx_keyidx) },
+#endif /* CONFIG_WEP */
 	{ INT(priority) },
 #ifdef IEEE8021X_EAPOL
 	{ INT(eap_workaround) },
@@ -2495,6 +2501,7 @@
 	{ INT(dot11MeshHoldingTimeout) },
 #endif /* CONFIG_MESH */
 	{ INT(wpa_ptk_rekey) },
+	{ INT_RANGE(wpa_deny_ptk0_rekey, 0, 2) },
 	{ INT(group_rekey) },
 	{ STR(bgscan) },
 	{ INT_RANGE(ignore_broadcast_ssid, 0, 2) },
@@ -2537,6 +2544,9 @@
 	{ INT_RANGE(vht_tx_mcs_nss_7, -1, 3) },
 	{ INT_RANGE(vht_tx_mcs_nss_8, -1, 3) },
 #endif /* CONFIG_VHT_OVERRIDES */
+#ifdef CONFIG_HE_OVERRIDES
+	{ INT_RANGE(disable_he, 0, 1)},
+#endif /* CONFIG_HE_OVERRIDES */
 	{ INT(ap_max_inactivity) },
 	{ INT(dtim_period) },
 	{ INT(beacon_int) },
@@ -2563,11 +2573,15 @@
 	{ STR_LEN(dpp_netaccesskey) },
 	{ INT(dpp_netaccesskey_expiry) },
 	{ STR_LEN(dpp_csign) },
+	{ INT_RANGE(dpp_pfs, 0, 2) },
 #endif /* CONFIG_DPP */
 	{ INT_RANGE(owe_group, 0, 65535) },
 	{ INT_RANGE(owe_only, 0, 1) },
+	{ INT_RANGE(owe_ptk_workaround, 0, 1) },
 	{ INT_RANGE(multi_ap_backhaul_sta, 0, 1) },
 	{ INT_RANGE(ft_eap_pmksa_caching, 0, 1) },
+	{ INT_RANGE(beacon_prot, 0, 1) },
+	{ INT_RANGE(transition_disable, 0, 255) },
 };
 
 #undef OFFSET
@@ -2603,7 +2617,7 @@
 int wpa_config_add_prio_network(struct wpa_config *config,
 				struct wpa_ssid *ssid)
 {
-	int prio;
+	size_t prio;
 	struct wpa_ssid *prev, **nlist;
 
 	/*
@@ -3018,6 +3032,7 @@
 	ssid->pairwise_cipher = DEFAULT_PAIRWISE;
 	ssid->group_cipher = DEFAULT_GROUP;
 	ssid->key_mgmt = DEFAULT_KEY_MGMT;
+	ssid->wpa_deny_ptk0_rekey = PTK0_REKEY_ALLOW_ALWAYS;
 	ssid->bg_scan_period = DEFAULT_BG_SCAN_PERIOD;
 	ssid->ht = 1;
 #ifdef IEEE8021X_EAPOL
@@ -4283,6 +4298,7 @@
 	config->key_mgmt_offload = DEFAULT_KEY_MGMT_OFFLOAD;
 	config->cert_in_cb = DEFAULT_CERT_IN_CB;
 	config->wpa_rsc_relaxation = DEFAULT_WPA_RSC_RELAXATION;
+	config->extended_key_id = DEFAULT_EXTENDED_KEY_ID;
 
 #ifdef CONFIG_MBO
 	config->mbo_cell_capa = DEFAULT_MBO_CELL_CAPA;
@@ -4308,7 +4324,7 @@
  */
 void wpa_config_debug_dump_networks(struct wpa_config *config)
 {
-	int prio;
+	size_t prio;
 	struct wpa_ssid *ssid;
 
 	for (prio = 0; prio < config->num_prio; prio++) {
@@ -4639,7 +4655,7 @@
 	struct wpa_config *config, int line, const char *pos)
 {
 	struct p2p_channel *pref = NULL, *n;
-	unsigned int num = 0;
+	size_t num = 0;
 	const char *pos2;
 	u8 op_class, chan;
 
@@ -4997,7 +5013,7 @@
 	{ INT(okc), 0 },
 	{ INT(pmf), 0 },
 	{ FUNC(sae_groups), 0 },
-	{ INT_RANGE(sae_pwe, 0, 2), 0 },
+	{ INT_RANGE(sae_pwe, 0, 3), 0 },
 	{ INT_RANGE(sae_pmkid_in_assoc, 0, 1), 0 },
 	{ INT(dtim_period), 0 },
 	{ INT(beacon_int), 0 },
@@ -5047,6 +5063,7 @@
 	{ INT_RANGE(bss_no_flush_when_down, 0, 1), 0 },
 #ifdef CONFIG_WNM
 	{ INT_RANGE(disable_btm, 0, 1), CFG_CHANGED_DISABLE_BTM },
+	{ INT_RANGE(extended_key_id, 0, 1), 0 },
 #endif /* CONFIG_WNM */
 };
 
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index d00c4ec..0ca27cb 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -44,6 +44,7 @@
 #define DEFAULT_MBO_CELL_CAPA MBO_CELL_CAPA_NOT_SUPPORTED
 #define DEFAULT_DISASSOC_IMMINENT_RSSI_THRESHOLD -75
 #define DEFAULT_OCE_SUPPORT OCE_STA
+#define DEFAULT_EXTENDED_KEY_ID 0
 
 #include "config_ssid.h"
 #include "wps/wps.h"
@@ -332,7 +333,7 @@
 	 */
 	unsigned int max_bss_load;
 
-	unsigned int num_req_conn_capab;
+	size_t num_req_conn_capab;
 	u8 *req_conn_capab_proto;
 	int **req_conn_capab_port;
 
@@ -403,7 +404,7 @@
 	 * This indicates how many per-priority network lists are included in
 	 * pssid.
 	 */
-	int num_prio;
+	size_t num_prio;
 
 	/**
 	 * cred - Head of the credential list
@@ -1578,6 +1579,17 @@
 	 * By default BSS transition management is enabled
 	 */
 	int disable_btm;
+
+	/**
+	 * extended_key_id - Extended Key ID support
+	 *
+	 * IEEE Std 802.11-2016 optionally allows to use Key ID 0 and 1 for PTK
+	 * keys with Extended Key ID.
+	 *
+	 * 0 = don't use Extended Key ID
+	 * 1 = use Extended Key ID when possible
+	 */
+	int extended_key_id;
 };
 
 
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index 305291e..52e1372 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -213,8 +213,22 @@
 			}
 		}
 
-		if (wpa_config_set(ssid, pos, pos2, *line) < 0)
+		if (wpa_config_set(ssid, pos, pos2, *line) < 0) {
+#ifndef CONFIG_WEP
+			if (os_strcmp(pos, "wep_key0") == 0 ||
+			    os_strcmp(pos, "wep_key1") == 0 ||
+			    os_strcmp(pos, "wep_key2") == 0 ||
+			    os_strcmp(pos, "wep_key3") == 0 ||
+			    os_strcmp(pos, "wep_tx_keyidx") == 0) {
+				wpa_printf(MSG_ERROR,
+					   "Line %d: unsupported WEP parameter",
+					   *line);
+				ssid->disabled = 1;
+				continue;
+			}
+#endif /* CONFIG_WEP */
 			errors++;
+		}
 	}
 
 	if (!end) {
@@ -653,6 +667,7 @@
 #endif /* IEEE8021X_EAPOL */
 
 
+#ifdef CONFIG_WEP
 static void write_wep_key(FILE *f, int idx, struct wpa_ssid *ssid)
 {
 	char field[20], *value;
@@ -667,6 +682,7 @@
 		os_free(value);
 	}
 }
+#endif /* CONFIG_WEP */
 
 
 #ifdef CONFIG_P2P
@@ -741,8 +757,6 @@
 
 static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
 {
-	int i;
-
 #define STR(t) write_str(f, #t, ssid)
 #define INT(t) write_int(f, #t, ssid->t, 0)
 #define INTe(t, m) write_int(f, #t, ssid->eap.m, 0)
@@ -831,9 +845,15 @@
 	STR(openssl_ciphers);
 	INTe(erp, erp);
 #endif /* IEEE8021X_EAPOL */
-	for (i = 0; i < 4; i++)
-		write_wep_key(f, i, ssid);
-	INT(wep_tx_keyidx);
+#ifdef CONFIG_WEP
+	{
+		int i;
+
+		for (i = 0; i < 4; i++)
+			write_wep_key(f, i, ssid);
+		INT(wep_tx_keyidx);
+	}
+#endif /* CONFIG_WEP */
 	INT(priority);
 #ifdef IEEE8021X_EAPOL
 	INT_DEF(eap_workaround, DEFAULT_EAP_WORKAROUND);
@@ -900,6 +920,7 @@
 	INT_DEF(mesh_rssi_threshold, DEFAULT_MESH_RSSI_THRESHOLD);
 #endif /* CONFIG_MESH */
 	INT(wpa_ptk_rekey);
+	INT(wpa_deny_ptk0_rekey);
 	INT(group_rekey);
 	INT(ignore_broadcast_ssid);
 #ifdef CONFIG_DPP
@@ -907,11 +928,15 @@
 	STR(dpp_netaccesskey);
 	INT(dpp_netaccesskey_expiry);
 	STR(dpp_csign);
+	INT(dpp_pfs);
 #endif /* CONFIG_DPP */
 	INT(owe_group);
 	INT(owe_only);
+	INT(owe_ptk_workaround);
 	INT(multi_ap_backhaul_sta);
 	INT(ft_eap_pmksa_caching);
+	INT(beacon_prot);
+	INT(transition_disable);
 #ifdef CONFIG_HT_OVERRIDES
 	INT_DEF(disable_ht, DEFAULT_DISABLE_HT);
 	INT_DEF(disable_ht40, DEFAULT_DISABLE_HT40);
@@ -946,6 +971,9 @@
 	INT_DEF(vht_tx_mcs_nss_7, -1);
 	INT_DEF(vht_tx_mcs_nss_8, -1);
 #endif /* CONFIG_VHT_OVERRIDES */
+#ifdef CONFIG_HE_OVERRIDES
+	INT(disable_he);
+#endif /* CONFIG_HE_OVERRIDES */
 
 #undef STR
 #undef INT
@@ -1576,6 +1604,9 @@
 			config->bss_no_flush_when_down);
 	if (config->disable_btm)
 		fprintf(f, "disable_btm=1\n");
+	if (config->extended_key_id != DEFAULT_EXTENDED_KEY_ID)
+		fprintf(f, "extended_key_id=%d\n",
+			config->extended_key_id);
 }
 
 #endif /* CONFIG_NO_CONFIG_WRITE */
@@ -1592,9 +1623,16 @@
 #endif /* CONFIG_NO_CONFIG_BLOBS */
 	int ret = 0;
 	const char *orig_name = name;
-	int tmp_len = os_strlen(name) + 5; /* allow space for .tmp suffix */
-	char *tmp_name = os_malloc(tmp_len);
+	int tmp_len;
+	char *tmp_name;
 
+	if (!name) {
+		wpa_printf(MSG_ERROR, "No configuration file for writing");
+		return -1;
+	}
+
+	tmp_len = os_strlen(name) + 5; /* allow space for .tmp suffix */
+	tmp_name = os_malloc(tmp_len);
 	if (tmp_name) {
 		os_snprintf(tmp_name, tmp_len, "%s.tmp", name);
 		name = tmp_name;
@@ -1622,8 +1660,11 @@
 	for (ssid = config->ssid; ssid; ssid = ssid->next) {
 		if (ssid->key_mgmt == WPA_KEY_MGMT_WPS || ssid->temporary)
 			continue; /* do not save temporary networks */
-		if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
-		    !ssid->passphrase)
+		if (wpa_key_mgmt_wpa_psk_no_sae(ssid->key_mgmt) &&
+		    !ssid->psk_set && !ssid->passphrase)
+			continue; /* do not save invalid network */
+		if (wpa_key_mgmt_sae(ssid->key_mgmt) &&
+		    !ssid->passphrase && !ssid->sae_password)
 			continue; /* do not save invalid network */
 		fprintf(f, "\nnetwork={\n");
 		wpa_config_write_network(f, ssid);
diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h
index af8317b..a186ab9 100644
--- a/wpa_supplicant/config_ssid.h
+++ b/wpa_supplicant/config_ssid.h
@@ -299,6 +299,7 @@
 	struct eap_peer_config eap;
 #endif /* IEEE8021X_EAPOL */
 
+#ifdef CONFIG_WEP
 #define NUM_WEP_KEYS 4
 #define MAX_WEP_KEY_LEN 16
 	/**
@@ -315,6 +316,7 @@
 	 * wep_tx_keyidx - Default key index for TX frames using WEP
 	 */
 	int wep_tx_keyidx;
+#endif /* CONFIG_WEP */
 
 	/**
 	 * proactive_key_caching - Enable proactive key caching
@@ -552,6 +554,19 @@
 	 */
 	int wpa_ptk_rekey;
 
+	/** wpa_deny_ptk0_rekey - Control PTK0 rekeying
+	 *
+	 * Rekeying a pairwise key using only keyid 0 (PTK0 rekey) has many
+	 * broken implementations and should be avoided when using or
+	 * interacting with one.
+	 *
+	 * 0 = always rekey when configured/instructed
+	 * 1 = only rekey when the local driver is explicitly indicating it can
+	 *	perform this operation without issues
+	 * 2 = never allow PTK0 rekeys
+	 */
+	enum ptk0_rekey_handling wpa_deny_ptk0_rekey;
+
 	/**
 	 * group_rekey - Group rekeying time in seconds
 	 *
@@ -763,6 +778,16 @@
 	    vht_tx_mcs_nss_7, vht_tx_mcs_nss_8;
 #endif /* CONFIG_VHT_OVERRIDES */
 
+#ifdef CONFIG_HE_OVERRIDES
+	/**
+	 * disable_he - Disable HE (IEEE 802.11ax) for this network
+	 *
+	 * By default, use it if it is available, but this can be configured
+	 * to 1 to have it disabled.
+	 */
+	int disable_he;
+#endif /* CONFIG_HE_OVERRIDES */
+
 	/**
 	 * ap_max_inactivity - Timeout in seconds to detect STA's inactivity
 	 *
@@ -987,6 +1012,22 @@
 	size_t dpp_csign_len;
 
 	/**
+	 * dpp_pfs - DPP PFS
+	 * 0: allow PFS to be used or not used
+	 * 1: require PFS to be used (note: not compatible with DPP R1)
+	 * 2: do not allow PFS to be used
+	 */
+	int dpp_pfs;
+
+	/**
+	 * dpp_pfs_fallback - DPP PFS fallback selection
+	 *
+	 * This is an internally used variable (i.e., not used in external
+	 * configuration) to track state of the DPP PFS fallback mechanism.
+	 */
+	int dpp_pfs_fallback;
+
+	/**
 	 * owe_group - OWE DH Group
 	 *
 	 * 0 = use default (19) first and then try all supported groups one by
@@ -1008,6 +1049,19 @@
 	int owe_only;
 
 	/**
+	 * owe_ptk_workaround - OWE PTK derivation workaround
+	 *
+	 * Initial OWE implementation used SHA256 when deriving the PTK for all
+	 * OWE groups. This was supposed to change to SHA384 for group 20 and
+	 * SHA512 for group 21. This parameter can be used to enable older
+	 * behavior mainly for testing purposes. There is no impact to group 19
+	 * behavior, but if enabled, this will make group 20 and 21 cases use
+	 * SHA256-based PTK derivation which will not work with the updated
+	 * OWE implementation on the AP side.
+	 */
+	int owe_ptk_workaround;
+
+	/**
 	 * owe_transition_bss_select_count - OWE transition BSS select count
 	 *
 	 * This is an internally used variable (i.e., not used in external
@@ -1033,6 +1087,34 @@
 	 * FT initial mobility domain association.
 	 */
 	int ft_eap_pmksa_caching;
+
+	/**
+	 * beacon_prot - Whether Beacon protection is enabled
+	 *
+	 * This depends on management frame protection (ieee80211w) being
+	 * enabled.
+	 */
+	int beacon_prot;
+
+	/**
+	 * transition_disable - Transition Disable indication
+	 * The AP can notify authenticated stations to disable transition mode
+	 * in their network profiles when the network has completed transition
+	 * steps, i.e., once sufficiently large number of APs in the ESS have
+	 * been updated to support the more secure alternative. When this
+	 * indication is used, the stations are expected to automatically
+	 * disable transition mode and less secure security options. This
+	 * includes use of WEP, TKIP (including use of TKIP as the group
+	 * cipher), and connections without PMF.
+	 * Bitmap bits:
+	 * bit 0 (0x01): WPA3-Personal (i.e., disable WPA2-Personal = WPA-PSK
+	 *	and only allow SAE to be used)
+	 * bit 1 (0x02): SAE-PK (disable SAE without use of SAE-PK)
+	 * bit 2 (0x04): WPA3-Enterprise (move to requiring PMF)
+	 * bit 3 (0x08): Enhanced Open (disable use of open network; require
+	 *	OWE)
+	 */
+	u8 transition_disable;
 };
 
 #endif /* CONFIG_SSID_H */
diff --git a/wpa_supplicant/config_winreg.c b/wpa_supplicant/config_winreg.c
index 0f2a30a..1b7f96e 100644
--- a/wpa_supplicant/config_winreg.c
+++ b/wpa_supplicant/config_winreg.c
@@ -277,6 +277,15 @@
 	wpa_config_read_reg_dword(hk, TEXT("okc"), &config->okc);
 	wpa_config_read_reg_dword(hk, TEXT("pmf"), &val);
 	config->pmf = val;
+	if (wpa_config_read_reg_dword(hk, TEXT("extended_key_id"),
+				      &val) == 0) {
+		if (val < 0 || val > 1) {
+			wpa_printf(MSG_ERROR,
+				   "Invalid Extended Key ID setting (%d)", val);
+			errors++;
+		}
+		config->extended_key_id = val;
+	}
 
 	return errors ? -1 : 0;
 }
@@ -823,6 +832,7 @@
 #endif /* IEEE8021X_EAPOL */
 
 
+#ifdef CONFIG_WEP
 static void write_wep_key(HKEY hk, int idx, struct wpa_ssid *ssid)
 {
 	char field[20], *value;
@@ -834,11 +844,12 @@
 		os_free(value);
 	}
 }
+#endif /* CONFIG_WEP */
 
 
 static int wpa_config_write_network(HKEY hk, struct wpa_ssid *ssid, int id)
 {
-	int i, errors = 0;
+	int errors = 0;
 	HKEY nhk, netw;
 	LONG ret;
 	TCHAR name[5];
@@ -924,9 +935,15 @@
 	INTe(engine2, phase2_cert.engine);
 	INT_DEF(eapol_flags, DEFAULT_EAPOL_FLAGS);
 #endif /* IEEE8021X_EAPOL */
-	for (i = 0; i < 4; i++)
-		write_wep_key(netw, i, ssid);
-	INT(wep_tx_keyidx);
+#ifdef CONFIG_WEP
+	{
+		int i;
+
+		for (i = 0; i < 4; i++)
+			write_wep_key(netw, i, ssid);
+		INT(wep_tx_keyidx);
+	}
+#endif /* CONFIG_WEP */
 	INT(priority);
 #ifdef IEEE8021X_EAPOL
 	INT_DEF(eap_workaround, DEFAULT_EAP_WORKAROUND);
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index be5ea17..7301d50 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -419,6 +419,64 @@
 }
 
 
+#ifdef CONFIG_TESTING_OPTIONS
+static int wpas_ctrl_iface_set_dso(struct wpa_supplicant *wpa_s,
+				   const char *val)
+{
+	u8 bssid[ETH_ALEN];
+	const char *pos = val;
+	struct driver_signal_override *dso = NULL, *tmp, parsed;
+
+	if (hwaddr_aton(pos, bssid))
+		return -1;
+	pos = os_strchr(pos, ' ');
+
+	dl_list_for_each(tmp, &wpa_s->drv_signal_override,
+			 struct driver_signal_override, list) {
+		if (os_memcmp(bssid, tmp->bssid, ETH_ALEN) == 0) {
+			dso = tmp;
+			break;
+		}
+	}
+
+	if (!pos) {
+		/* Remove existing entry */
+		if (dso) {
+			dl_list_del(&dso->list);
+			os_free(dso);
+		}
+		return 0;
+	}
+	pos++;
+
+	/* Update an existing entry or add a new one */
+	os_memset(&parsed, 0, sizeof(parsed));
+	if (sscanf(pos, "%d %d %d %d %d",
+		   &parsed.si_current_signal,
+		   &parsed.si_avg_signal,
+		   &parsed.si_avg_beacon_signal,
+		   &parsed.si_current_noise,
+		   &parsed.scan_level) != 5)
+		return -1;
+
+	if (!dso) {
+		dso = os_zalloc(sizeof(*dso));
+		if (!dso)
+			return -1;
+		os_memcpy(dso->bssid, bssid, ETH_ALEN);
+		dl_list_add(&wpa_s->drv_signal_override, &dso->list);
+	}
+	dso->si_current_signal = parsed.si_current_signal;
+	dso->si_avg_signal = parsed.si_avg_signal;
+	dso->si_avg_beacon_signal = parsed.si_avg_beacon_signal;
+	dso->si_current_noise = parsed.si_current_noise;
+	dso->scan_level = parsed.scan_level;
+
+	return 0;
+}
+#endif /* CONFIG_TESTING_OPTIONS */
+
+
 static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
 					 char *cmd)
 {
@@ -663,6 +721,8 @@
 		wpa_s->ignore_assoc_disallow = !!atoi(value);
 		wpa_drv_ignore_assoc_disallow(wpa_s,
 					      wpa_s->ignore_assoc_disallow);
+	} else if (os_strcasecmp(cmd, "disable_sa_query") == 0) {
+		wpa_s->disable_sa_query = !!atoi(value);
 	} else if (os_strcasecmp(cmd, "ignore_sae_h2e_only") == 0) {
 		wpa_s->ignore_sae_h2e_only = !!atoi(value);
 	} else if (os_strcasecmp(cmd, "extra_sae_rejected_groups") == 0) {
@@ -687,6 +747,12 @@
 				break;
 			pos++;
 		}
+	} else if (os_strcasecmp(cmd, "rsne_override_eapol") == 0) {
+		wpabuf_free(wpa_s->rsne_override_eapol);
+		if (os_strcmp(value, "NULL") == 0)
+			wpa_s->rsne_override_eapol = NULL;
+		else
+			wpa_s->rsne_override_eapol = wpabuf_parse_bin(value);
 	} else if (os_strcasecmp(cmd, "rsnxe_override_assoc") == 0) {
 		wpabuf_free(wpa_s->rsnxe_override_assoc);
 		if (os_strcmp(value, "NULL") == 0)
@@ -713,6 +779,8 @@
 			wpa_s->sae_commit_override = NULL;
 		else
 			wpa_s->sae_commit_override = wpabuf_parse_bin(value);
+	} else if (os_strcasecmp(cmd, "driver_signal_override") == 0) {
+		ret = wpas_ctrl_iface_set_dso(wpa_s, value);
 #ifdef CONFIG_DPP
 	} else if (os_strcasecmp(cmd, "dpp_config_obj_override") == 0) {
 		os_free(wpa_s->dpp_config_obj_override);
@@ -851,6 +919,8 @@
 		return wpa_snprintf_hex(buf, buflen,
 					wpa_sm_get_anonce(wpa_s->wpa),
 					WPA_NONCE_LEN);
+	} else if (os_strcasecmp(cmd, "last_tk_key_idx") == 0) {
+		res = os_snprintf(buf, buflen, "%d", wpa_s->last_tk_key_idx);
 #endif /* CONFIG_TESTING_OPTIONS */
 	} else {
 		res = wpa_config_get_value(cmd, wpa_s->conf, buf, buflen);
@@ -3889,8 +3959,10 @@
 	{ WPA_DRIVER_CAPA_ENC_GCMP, "GCMP", 0 },
 	{ WPA_DRIVER_CAPA_ENC_TKIP, "TKIP", 0 },
 	{ WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE, "NONE", 0 },
+#ifdef CONFIG_WEP
 	{ WPA_DRIVER_CAPA_ENC_WEP104, "WEP104", 1 },
 	{ WPA_DRIVER_CAPA_ENC_WEP40, "WEP40", 1 }
+#endif /* CONFIG_WEP */
 };
 
 static const struct cipher_info ciphers_group_mgmt[] = {
@@ -3952,7 +4024,11 @@
 	if (res < 0) {
 		if (strict)
 			return 0;
+#ifdef CONFIG_WEP
 		len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen);
+#else /* CONFIG_WEP */
+		len = os_strlcpy(buf, "CCMP TKIP", buflen);
+#endif /* CONFIG_WEP */
 		if (len >= buflen)
 			return -1;
 		return len;
@@ -5285,15 +5361,24 @@
 {
 	wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication");
 	/* MLME-DELETEKEYS.request */
-	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 0);
-	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 0);
-	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 0);
-	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 0);
-	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 0);
-	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 0);
+	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL,
+			0, KEY_FLAG_GROUP);
+	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL,
+			0, KEY_FLAG_GROUP);
+	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL,
+			0, KEY_FLAG_GROUP);
+	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL,
+			0, KEY_FLAG_GROUP);
+	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL,
+			0, KEY_FLAG_GROUP);
+	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL,
+			0, KEY_FLAG_GROUP);
 
 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL,
-			0);
+			0, KEY_FLAG_PAIRWISE);
+	if (wpa_sm_ext_key_id(wpa_s->wpa))
+		wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 1, 0,
+				NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE);
 	/* MLME-SETPROTECTION.request(None) */
 	wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid,
 				   MLME_SETPROTECTION_PROTECT_TYPE_NONE,
@@ -7130,7 +7215,7 @@
 		return -1;
 	}
 
-	bss = wpa_bss_get_bssid(wpa_s, bssid);
+	bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
 	if (bss == NULL) {
 		wpa_printf(MSG_DEBUG, "Could not find BSS " MACSTR,
 			   MAC2STR(bssid));
@@ -8019,6 +8104,10 @@
 	wpa_s->dpp_resp_wait_time = 0;
 	wpa_s->dpp_resp_max_tries = 0;
 	wpa_s->dpp_resp_retry_time = 0;
+#ifdef CONFIG_DPP2
+	wpas_dpp_chirp_stop(wpa_s);
+	wpa_s->dpp_pfs_fallback = 0;
+#endif /* CONFIG_DPP2 */
 #ifdef CONFIG_TESTING_OPTIONS
 	os_memset(dpp_pkex_own_mac_override, 0, ETH_ALEN);
 	os_memset(dpp_pkex_peer_mac_override, 0, ETH_ALEN);
@@ -8038,9 +8127,12 @@
 
 	eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
 	wpa_supplicant_stop_countermeasures(wpa_s, NULL);
+	wpa_s->last_michael_mic_error.sec = 0;
 
 	wpa_s->no_keep_alive = 0;
 	wpa_s->own_disconnect_req = 0;
+	wpa_s->own_reconnect_req = 0;
+	wpa_s->deny_ptk0_rekey = 0;
 
 	os_free(wpa_s->disallow_aps_bssid);
 	wpa_s->disallow_aps_bssid = NULL;
@@ -8089,6 +8181,7 @@
 	wpa_s->p2p_go_csa_on_inv = 0;
 	wpa_s->ignore_auth_resp = 0;
 	wpa_s->ignore_assoc_disallow = 0;
+	wpa_s->disable_sa_query = 0;
 	wpa_s->testing_resend_assoc = 0;
 	wpa_s->ignore_sae_h2e_only = 0;
 	wpa_s->reject_btm_req_reason = 0;
@@ -8099,10 +8192,13 @@
 	wpa_s->sae_commit_override = NULL;
 	os_free(wpa_s->extra_sae_rejected_groups);
 	wpa_s->extra_sae_rejected_groups = NULL;
+	wpabuf_free(wpa_s->rsne_override_eapol);
+	wpa_s->rsne_override_eapol = NULL;
 	wpabuf_free(wpa_s->rsnxe_override_assoc);
 	wpa_s->rsnxe_override_assoc = NULL;
 	wpabuf_free(wpa_s->rsnxe_override_eapol);
 	wpa_s->rsnxe_override_eapol = NULL;
+	wpas_clear_driver_signal_override(wpa_s);
 #ifdef CONFIG_DPP
 	os_free(wpa_s->dpp_config_obj_override);
 	wpa_s->dpp_config_obj_override = NULL;
@@ -8117,6 +8213,8 @@
 	wpa_s->disconnected = 0;
 	os_free(wpa_s->next_scan_freqs);
 	wpa_s->next_scan_freqs = NULL;
+	os_memset(wpa_s->next_scan_bssid, 0, ETH_ALEN);
+	wpa_s->next_scan_bssid_wildcard_ssid = 0;
 	os_free(wpa_s->select_network_scan_freqs);
 	wpa_s->select_network_scan_freqs = NULL;
 
@@ -8135,6 +8233,7 @@
 
 #ifdef CONFIG_SME
 	wpa_s->sme.last_unprot_disconnect.sec = 0;
+	wpa_s->sme.auth_alg = 0;
 #endif /* CONFIG_SME */
 
 	wpabuf_free(wpa_s->ric_ies);
@@ -8451,6 +8550,9 @@
 				goto done;
 			}
 			os_memcpy(wpa_s->next_scan_bssid, bssid, ETH_ALEN);
+
+			wpa_s->next_scan_bssid_wildcard_ssid =
+				os_strstr(params, "wildcard_ssid=1") != NULL;
 		}
 
 		pos = params;
@@ -8962,7 +9064,7 @@
 {
 	struct wpa_supplicant *wpa_s = ctx;
 	const struct ether_header *eth;
-	struct iphdr ip;
+	struct ip ip;
 	const u8 *pos;
 	unsigned int i;
 	char extra[30];
@@ -8978,14 +9080,13 @@
 	os_memcpy(&ip, eth + 1, sizeof(ip));
 	pos = &buf[sizeof(*eth) + sizeof(ip)];
 
-	if (ip.ihl != 5 || ip.version != 4 ||
-	    ntohs(ip.tot_len) > HWSIM_IP_LEN) {
+	if (ip.ip_hl != 5 || ip.ip_v != 4 || ntohs(ip.ip_len) > HWSIM_IP_LEN) {
 		wpa_printf(MSG_DEBUG,
 			   "test data: RX - ignore unexpect IP header");
 		return;
 	}
 
-	for (i = 0; i < ntohs(ip.tot_len) - sizeof(ip); i++) {
+	for (i = 0; i < ntohs(ip.ip_len) - sizeof(ip); i++) {
 		if (*pos != (u8) i) {
 			wpa_printf(MSG_DEBUG,
 				   "test data: RX - ignore mismatching payload");
@@ -8994,8 +9095,8 @@
 		pos++;
 	}
 	extra[0] = '\0';
-	if (ntohs(ip.tot_len) != HWSIM_IP_LEN)
-		os_snprintf(extra, sizeof(extra), " len=%d", ntohs(ip.tot_len));
+	if (ntohs(ip.ip_len) != HWSIM_IP_LEN)
+		os_snprintf(extra, sizeof(extra), " len=%d", ntohs(ip.ip_len));
 	wpa_msg(wpa_s, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR "%s",
 		MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost), extra);
 }
@@ -9047,7 +9148,7 @@
 	u8 tos;
 	u8 buf[2 + HWSIM_PACKETLEN];
 	struct ether_header *eth;
-	struct iphdr *ip;
+	struct ip *ip;
 	u8 *dpos;
 	unsigned int i;
 	size_t send_len = HWSIM_IP_LEN;
@@ -9086,17 +9187,17 @@
 	os_memcpy(eth->ether_dhost, dst, ETH_ALEN);
 	os_memcpy(eth->ether_shost, src, ETH_ALEN);
 	eth->ether_type = htons(ETHERTYPE_IP);
-	ip = (struct iphdr *) (eth + 1);
+	ip = (struct ip *) (eth + 1);
 	os_memset(ip, 0, sizeof(*ip));
-	ip->ihl = 5;
-	ip->version = 4;
-	ip->ttl = 64;
-	ip->tos = tos;
-	ip->tot_len = htons(send_len);
-	ip->protocol = 1;
-	ip->saddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1);
-	ip->daddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2);
-	ip->check = ipv4_hdr_checksum(ip, sizeof(*ip));
+	ip->ip_hl = 5;
+	ip->ip_v = 4;
+	ip->ip_ttl = 64;
+	ip->ip_tos = tos;
+	ip->ip_len = htons(send_len);
+	ip->ip_p = 1;
+	ip->ip_src.s_addr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1);
+	ip->ip_dst.s_addr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2);
+	ip->ip_sum = ipv4_hdr_checksum(ip, sizeof(*ip));
 	dpos = (u8 *) (ip + 1);
 	for (i = 0; i < send_len - sizeof(*ip); i++)
 		*dpos++ = i;
@@ -9289,13 +9390,15 @@
 	 * in the driver. */
 	if (wpa_drv_set_key(wpa_s, wpa_s->last_tk_alg, wpa_s->last_tk_addr,
 			    wpa_s->last_tk_key_idx, 1, zero, 6,
-			    zero, wpa_s->last_tk_len) < 0)
+			    zero, wpa_s->last_tk_len,
+			    KEY_FLAG_PAIRWISE_RX_TX) < 0)
 		return -1;
 
 	/* Set the previously configured key to reset its TSC/RSC */
 	return wpa_drv_set_key(wpa_s, wpa_s->last_tk_alg, wpa_s->last_tk_addr,
 			       wpa_s->last_tk_key_idx, 1, zero, 6,
-			       wpa_s->last_tk, wpa_s->last_tk_len);
+			       wpa_s->last_tk, wpa_s->last_tk_len,
+			       KEY_FLAG_PAIRWISE_RX_TX);
 }
 
 
@@ -10741,6 +10844,28 @@
 			if (os_snprintf_error(reply_size, reply_len))
 				reply_len = -1;
 		}
+	} else if (os_strncmp(buf, "DPP_NFC_HANDOVER_REQ ", 21) == 0) {
+		int res;
+
+		res = wpas_dpp_nfc_handover_req(wpa_s, buf + 20);
+		if (res < 0) {
+			reply_len = -1;
+		} else {
+			reply_len = os_snprintf(reply, reply_size, "%d", res);
+			if (os_snprintf_error(reply_size, reply_len))
+				reply_len = -1;
+		}
+	} else if (os_strncmp(buf, "DPP_NFC_HANDOVER_SEL ", 21) == 0) {
+		int res;
+
+		res = wpas_dpp_nfc_handover_sel(wpa_s, buf + 20);
+		if (res < 0) {
+			reply_len = -1;
+		} else {
+			reply_len = os_snprintf(reply, reply_size, "%d", res);
+			if (os_snprintf_error(reply_size, reply_len))
+				reply_len = -1;
+		}
 	} else if (os_strncmp(buf, "DPP_BOOTSTRAP_GEN ", 18) == 0) {
 		int res;
 
@@ -10769,6 +10894,10 @@
 	} else if (os_strncmp(buf, "DPP_BOOTSTRAP_INFO ", 19) == 0) {
 		reply_len = dpp_bootstrap_info(wpa_s->dpp, atoi(buf + 19),
 					       reply, reply_size);
+	} else if (os_strncmp(buf, "DPP_BOOTSTRAP_SET ", 18) == 0) {
+		if (dpp_bootstrap_set(wpa_s->dpp, atoi(buf + 18),
+				      os_strchr(buf + 18, ' ')) < 0)
+			reply_len = -1;
 	} else if (os_strncmp(buf, "DPP_AUTH_INIT ", 14) == 0) {
 		if (wpas_dpp_auth_init(wpa_s, buf + 13) < 0)
 			reply_len = -1;
@@ -10822,6 +10951,11 @@
 			reply_len = -1;
 	} else if (os_strcmp(buf, "DPP_CONTROLLER_STOP") == 0) {
 		dpp_controller_stop(wpa_s->dpp);
+	} else if (os_strncmp(buf, "DPP_CHIRP ", 10) == 0) {
+		if (wpas_dpp_chirp(wpa_s, buf + 9) < 0)
+			reply_len = -1;
+	} else if (os_strcmp(buf, "DPP_STOP_CHIRP") == 0) {
+		wpas_dpp_chirp_stop(wpa_s);
 #endif /* CONFIG_DPP2 */
 #endif /* CONFIG_DPP */
 	} else {
diff --git a/wpa_supplicant/ctrl_iface_udp.c b/wpa_supplicant/ctrl_iface_udp.c
index 8a6057a..1e92b97 100644
--- a/wpa_supplicant/ctrl_iface_udp.c
+++ b/wpa_supplicant/ctrl_iface_udp.c
@@ -516,7 +516,7 @@
 		return;
 
 	if (ifname)
-		os_snprintf(levelstr, sizeof(levelstr), "IFACE=%s <%d>",
+		os_snprintf(levelstr, sizeof(levelstr), "IFNAME=%s <%d>",
 			    ifname, level);
 	else
 		os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c
index 4b6dabc..4e17e31 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers.c
@@ -991,20 +991,25 @@
 	const struct wpa_dbus_property_desc *property_desc,
 	DBusMessageIter *iter, DBusError *error, void *user_data)
 {
-	const char *capabilities[11];
+	const char *capabilities[12];
 	size_t num_items = 0;
-#ifdef CONFIG_FILS
 	struct wpa_global *global = user_data;
 	struct wpa_supplicant *wpa_s;
+#ifdef CONFIG_FILS
 	int fils_supported = 0, fils_sk_pfs_supported = 0;
+#endif /* CONFIG_FILS */
+	int ext_key_id_supported = 0;
 
 	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
+#ifdef CONFIG_FILS
 		if (wpa_is_fils_supported(wpa_s))
 			fils_supported = 1;
 		if (wpa_is_fils_sk_pfs_supported(wpa_s))
 			fils_sk_pfs_supported = 1;
-	}
 #endif /* CONFIG_FILS */
+		if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID)
+			ext_key_id_supported = 1;
+	}
 
 #ifdef CONFIG_AP
 	capabilities[num_items++] = "ap";
@@ -1037,6 +1042,8 @@
 #ifdef CONFIG_OWE
 	capabilities[num_items++] = "owe";
 #endif /* CONFIG_OWE */
+	if (ext_key_id_supported)
+		capabilities[num_items++] = "extended_key_id";
 
 	return wpas_dbus_simple_array_property_getter(iter,
 						      DBUS_TYPE_STRING,
@@ -1146,7 +1153,7 @@
 				  DBusMessage **reply)
 {
 	u8 *ies = NULL, *nies;
-	int ies_len = 0;
+	size_t ies_len = 0;
 	DBusMessageIter array_iter, sub_array_iter;
 	char *val;
 	int len;
@@ -1177,7 +1184,7 @@
 		dbus_message_iter_recurse(&array_iter, &sub_array_iter);
 
 		dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
-		if (len == 0) {
+		if (len <= 0) {
 			dbus_message_iter_next(&array_iter);
 			continue;
 		}
@@ -1208,7 +1215,7 @@
 {
 	DBusMessageIter array_iter, sub_array_iter;
 	int *freqs = NULL, *nfreqs;
-	int freqs_num = 0;
+	size_t freqs_num = 0;
 
 	if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
 		wpa_printf(MSG_DEBUG,
@@ -2664,7 +2671,10 @@
 	/***** group cipher */
 	if (res < 0) {
 		const char *args[] = {
-			"ccmp", "tkip", "wep104", "wep40"
+			"ccmp", "tkip",
+#ifdef CONFIG_WEP
+			"wep104", "wep40"
+#endif /* CONFIG_WEP */
 		};
 
 		if (!wpa_dbus_dict_append_string_array(
@@ -2691,12 +2701,14 @@
 		    ((capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) &&
 		     !wpa_dbus_dict_string_array_add_element(
 			     &iter_array, "tkip")) ||
+#ifdef CONFIG_WEP
 		    ((capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) &&
 		     !wpa_dbus_dict_string_array_add_element(
 			     &iter_array, "wep104")) ||
 		    ((capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) &&
 		     !wpa_dbus_dict_string_array_add_element(
 			     &iter_array, "wep40")) ||
+#endif /* CONFIG_WEP */
 		    !wpa_dbus_dict_end_string_array(&iter_dict,
 						    &iter_dict_entry,
 						    &iter_dict_val,
@@ -2793,6 +2805,12 @@
 			goto nomem;
 #endif /* CONFIG_WPS */
 
+#ifdef CONFIG_SAE
+		if ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE) &&
+		    !wpa_dbus_dict_string_array_add_element(&iter_array, "sae"))
+			goto nomem;
+#endif /* CONFIG_SAE */
+
 		if (!wpa_dbus_dict_end_string_array(&iter_dict,
 						    &iter_dict_entry,
 						    &iter_dict_val,
@@ -4733,9 +4751,14 @@
 
 	/* Group */
 	switch (ie_data->group_cipher) {
+#ifdef CONFIG_WEP
 	case WPA_CIPHER_WEP40:
 		group = "wep40";
 		break;
+	case WPA_CIPHER_WEP104:
+		group = "wep104";
+		break;
+#endif /* CONFIG_WEP */
 	case WPA_CIPHER_TKIP:
 		group = "tkip";
 		break;
@@ -4745,9 +4768,6 @@
 	case WPA_CIPHER_GCMP:
 		group = "gcmp";
 		break;
-	case WPA_CIPHER_WEP104:
-		group = "wep104";
-		break;
 	case WPA_CIPHER_CCMP_256:
 		group = "ccmp-256";
 		break;
diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig
index db76c6a..ef2339f 100644
--- a/wpa_supplicant/defconfig
+++ b/wpa_supplicant/defconfig
@@ -77,7 +77,7 @@
 #CONFIG_DRIVER_MACSEC_QCA=y
 
 # Driver interface for Linux MACsec drivers
-#CONFIG_DRIVER_MACSEC_LINUX=y
+CONFIG_DRIVER_MACSEC_LINUX=y
 
 # Driver interface for the Broadcom RoboSwitch family
 #CONFIG_DRIVER_ROBOSWITCH=y
@@ -183,7 +183,7 @@
 #CONFIG_EAP_EKE=y
 
 # MACsec
-#CONFIG_MACSEC=y
+CONFIG_MACSEC=y
 
 # PKCS#12 (PFX) support (used to read private key and certificate file from
 # a file that usually has extension .p12 or .pfx)
@@ -248,7 +248,7 @@
 # Simultaneous Authentication of Equals (SAE), WPA3-Personal
 CONFIG_SAE=y
 
-# Disable scan result processing (ap_mode=1) to save code size by about 1 kB.
+# Disable scan result processing (ap_scan=1) to save code size by about 1 kB.
 # This can be used if ap_scan=1 mode is never enabled.
 #CONFIG_NO_SCAN_PROCESSING=y
 
@@ -471,11 +471,7 @@
 # Requires glibc 2.25 to build, falls back to /dev/random if unavailable.
 #CONFIG_GETRANDOM=y
 
-# IEEE 802.11n (High Throughput) support (mainly for AP mode)
-CONFIG_IEEE80211N=y
-
 # IEEE 802.11ac (Very High Throughput) support (mainly for AP mode)
-# (depends on CONFIG_IEEE80211N)
 CONFIG_IEEE80211AC=y
 
 # Wireless Network Management (IEEE Std 802.11v-2011)
@@ -612,3 +608,12 @@
 # Configure the building of the interface which allows WAPI configuration.
 # Note: does not configure WAPI implementation itself.
 #CONFIG_WAPI_INTERFACE=y
+
+# Wired equivalent privacy (WEP)
+# WEP is an obsolete cryptographic data confidentiality algorithm that is not
+# considered secure. It should not be used for anything anymore. The
+# functionality needed to use WEP is available in the current wpa_supplicant
+# release under this optional build parameter. This functionality is subject to
+# be completely removed in a future release.
+#CONFIG_WEP=y
+
diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c
index 73649c2..c75ab47 100644
--- a/wpa_supplicant/dpp_supplicant.c
+++ b/wpa_supplicant/dpp_supplicant.c
@@ -1,7 +1,7 @@
 /*
  * wpa_supplicant - DPP
  * 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.
@@ -107,6 +107,71 @@
 }
 
 
+int wpas_dpp_nfc_handover_req(struct wpa_supplicant *wpa_s, 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(wpa_s->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(wpa_s->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 wpas_dpp_nfc_handover_sel(struct wpa_supplicant *wpa_s, 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(wpa_s->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(wpa_s->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 wpas_dpp_auth_resp_retry_timeout(void *eloop_ctx, void *timeout_ctx)
 {
 	struct wpa_supplicant *wpa_s = eloop_ctx;
@@ -689,6 +754,8 @@
 			wpa_s->dpp_netrole = DPP_NETROLE_CONFIGURATOR;
 		else
 			wpa_s->dpp_netrole = DPP_NETROLE_STA;
+	} else {
+		wpa_s->dpp_netrole = DPP_NETROLE_STA;
 	}
 
 	pos = os_strstr(cmd, " neg_freq=");
@@ -705,12 +772,12 @@
 		wpa_s->dpp_auth = NULL;
 	}
 
-	auth = dpp_auth_init(wpa_s, peer_bi, own_bi, allowed_roles, neg_freq,
-			     wpa_s->hw.modes, wpa_s->hw.num_modes);
+	auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, own_bi, allowed_roles,
+			     neg_freq, wpa_s->hw.modes, wpa_s->hw.num_modes);
 	if (!auth)
 		goto fail;
 	wpas_dpp_set_testing_options(wpa_s, auth);
-	if (dpp_set_configurator(wpa_s->dpp, wpa_s, auth, cmd) < 0) {
+	if (dpp_set_configurator(auth, cmd) < 0) {
 		dpp_auth_deinit(auth);
 		goto fail;
 	}
@@ -911,6 +978,10 @@
 	wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR,
 		   MAC2STR(src));
 
+#ifdef CONFIG_DPP2
+	wpas_dpp_chirp_stop(wpa_s);
+#endif /* CONFIG_DPP2 */
+
 	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) {
@@ -949,7 +1020,8 @@
 
 	wpa_s->dpp_gas_client = 0;
 	wpa_s->dpp_auth_ok_on_ack = 0;
-	wpa_s->dpp_auth = dpp_auth_req_rx(wpa_s, wpa_s->dpp_allowed_roles,
+	wpa_s->dpp_auth = dpp_auth_req_rx(wpa_s->dpp, wpa_s,
+					  wpa_s->dpp_allowed_roles,
 					  wpa_s->dpp_qr_mutual,
 					  peer_bi, own_bi, freq, hdr, buf, len);
 	if (!wpa_s->dpp_auth) {
@@ -957,7 +1029,7 @@
 		return;
 	}
 	wpas_dpp_set_testing_options(wpa_s, wpa_s->dpp_auth);
-	if (dpp_set_configurator(wpa_s->dpp, wpa_s, wpa_s->dpp_auth,
+	if (dpp_set_configurator(wpa_s->dpp_auth,
 				 wpa_s->dpp_configurator_params) < 0) {
 		dpp_auth_deinit(wpa_s->dpp_auth);
 		wpa_s->dpp_auth = NULL;
@@ -1031,8 +1103,10 @@
 	ssid->ssid_len = conf->ssid_len;
 
 	if (conf->connector) {
-		ssid->key_mgmt = WPA_KEY_MGMT_DPP;
-		ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
+		if (dpp_akm_dpp(conf->akm)) {
+			ssid->key_mgmt = WPA_KEY_MGMT_DPP;
+			ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
+		}
 		ssid->dpp_connector = os_strdup(conf->connector);
 		if (!ssid->dpp_connector)
 			goto fail;
@@ -1061,7 +1135,7 @@
 
 	if (!conf->connector || dpp_akm_psk(conf->akm) ||
 	    dpp_akm_sae(conf->akm)) {
-		if (!conf->connector)
+		if (!conf->connector || !dpp_akm_dpp(conf->akm))
 			ssid->key_mgmt = 0;
 		if (dpp_akm_psk(conf->akm))
 			ssid->key_mgmt |= WPA_KEY_MGMT_PSK |
@@ -1203,6 +1277,32 @@
 }
 
 
+static int wpas_dpp_handle_key_pkg(struct wpa_supplicant *wpa_s,
+				   struct dpp_asymmetric_key *key)
+{
+#ifdef CONFIG_DPP2
+	int res;
+
+	if (!key)
+		return 0;
+
+	wpa_printf(MSG_DEBUG, "DPP: Received Configurator backup");
+	wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
+
+	while (key) {
+		res = dpp_configurator_from_backup(wpa_s->dpp, key);
+		if (res < 0)
+			return -1;
+		wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFIGURATOR_ID "%d",
+			res);
+		key = key->next;
+	}
+#endif /* CONFIG_DPP2 */
+
+	return 0;
+}
+
+
 static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
 				 enum gas_query_result result,
 				 const struct wpabuf *adv_proto,
@@ -1259,6 +1359,8 @@
 	}
 	if (auth->num_conf_obj)
 		wpas_dpp_post_process_config(wpa_s, auth);
+	if (wpas_dpp_handle_key_pkg(wpa_s, auth->conf_key_pkg) < 0)
+		goto fail;
 
 	status = DPP_STATUS_OK;
 #ifdef CONFIG_TESTING_OPTIONS
@@ -1605,6 +1707,76 @@
 	return res;
 }
 
+
+static void wpas_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi)
+{
+	struct wpa_supplicant *wpa_s = ctx;
+
+	if (bi == wpa_s->dpp_chirp_bi)
+		wpas_dpp_chirp_stop(wpa_s);
+}
+
+
+static void
+wpas_dpp_rx_presence_announcement(struct wpa_supplicant *wpa_s, 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;
+
+	if (!wpa_s->dpp)
+		return;
+
+	if (wpa_s->dpp_auth) {
+		wpa_printf(MSG_DEBUG,
+			   "DPP: Ignore Presence Announcement during ongoing Authentication");
+		return;
+	}
+
+	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(wpa_s, 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(wpa_s->dpp, r_bootstrap);
+	if (!peer_bi) {
+		wpa_printf(MSG_DEBUG,
+			   "DPP: No matching bootstrapping information found");
+		return;
+	}
+
+	auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, NULL,
+			     DPP_CAPAB_CONFIGURATOR, freq, NULL, 0);
+	if (!auth)
+		return;
+	wpas_dpp_set_testing_options(wpa_s, auth);
+	if (dpp_set_configurator(auth, wpa_s->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);
+
+	wpa_s->dpp_auth = auth;
+	if (wpas_dpp_auth_init_next(wpa_s) < 0) {
+		dpp_auth_deinit(wpa_s->dpp_auth);
+		wpa_s->dpp_auth = NULL;
+	}
+}
+
 #endif /* CONFIG_DPP2 */
 
 
@@ -2069,6 +2241,7 @@
 	if (wpas_dpp_auth_init(wpa_s, cmd) < 0) {
 		wpa_printf(MSG_DEBUG,
 			   "DPP: Authentication initialization failed");
+		offchannel_send_action_done(wpa_s);
 		return;
 	}
 }
@@ -2149,6 +2322,10 @@
 	case DPP_PA_CONNECTION_STATUS_RESULT:
 		wpas_dpp_rx_conn_status_result(wpa_s, src, hdr, buf, len);
 		break;
+	case DPP_PA_PRESENCE_ANNOUNCEMENT:
+		wpas_dpp_rx_presence_announcement(wpa_s, src, hdr, buf, len,
+						  freq);
+		break;
 #endif /* CONFIG_DPP2 */
 	default:
 		wpa_printf(MSG_DEBUG,
@@ -2271,13 +2448,13 @@
 	int ret = -1;
 	char *curve = NULL;
 
-	auth = os_zalloc(sizeof(*auth));
+	auth = dpp_alloc_auth(wpa_s->dpp, wpa_s);
 	if (!auth)
 		return -1;
 
 	curve = get_param(cmd, " curve=");
 	wpas_dpp_set_testing_options(wpa_s, auth);
-	if (dpp_set_configurator(wpa_s->dpp, wpa_s, auth, cmd) == 0 &&
+	if (dpp_set_configurator(auth, cmd) == 0 &&
 	    dpp_configurator_own_config(auth, curve, 0) == 0)
 		ret = wpas_dpp_handle_config_obj(wpa_s, auth,
 						 &auth->conf_obj[0]);
@@ -2549,6 +2726,8 @@
 
 void wpas_dpp_stop(struct wpa_supplicant *wpa_s)
 {
+	if (wpa_s->dpp_auth || wpa_s->dpp_pkex)
+		offchannel_send_action_done(wpa_s);
 	dpp_auth_deinit(wpa_s->dpp_auth);
 	wpa_s->dpp_auth = NULL;
 	dpp_pkex_free(wpa_s->dpp_pkex);
@@ -2579,6 +2758,7 @@
 	config.cb_ctx = wpa_s;
 #ifdef CONFIG_DPP2
 	config.process_conf_obj = wpas_dpp_process_conf_obj;
+	config.remove_bi = wpas_dpp_remove_bi;
 #endif /* CONFIG_DPP2 */
 	wpa_s->dpp = dpp_global_init(&config);
 	return wpa_s->dpp ? 0 : -1;
@@ -2610,6 +2790,7 @@
 	eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL);
 	dpp_pfs_free(wpa_s->dpp_pfs);
 	wpa_s->dpp_pfs = NULL;
+	wpas_dpp_chirp_stop(wpa_s);
 #endif /* CONFIG_DPP2 */
 	offchannel_send_action_done(wpa_s);
 	wpas_dpp_listen_stop(wpa_s);
@@ -2622,6 +2803,7 @@
 
 
 #ifdef CONFIG_DPP2
+
 int wpas_dpp_controller_start(struct wpa_supplicant *wpa_s, const char *cmd)
 {
 	struct dpp_controller_config config;
@@ -2638,4 +2820,270 @@
 	config.configurator_params = wpa_s->dpp_configurator_params;
 	return dpp_controller_start(wpa_s->dpp, &config);
 }
+
+
+static void wpas_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx);
+
+static void wpas_dpp_chirp_timeout(void *eloop_ctx, void *timeout_ctx)
+{
+	struct wpa_supplicant *wpa_s = eloop_ctx;
+
+	wpa_printf(MSG_DEBUG, "DPP: No chirp response received");
+	offchannel_send_action_done(wpa_s);
+	wpas_dpp_chirp_next(wpa_s, NULL);
+}
+
+
+static void wpas_dpp_chirp_tx_status(struct wpa_supplicant *wpa_s,
+				     unsigned int freq, const u8 *dst,
+				     const u8 *src, const u8 *bssid,
+				     const u8 *data, size_t data_len,
+				     enum offchannel_send_action_result result)
+{
+	if (result == OFFCHANNEL_SEND_ACTION_FAILED) {
+		wpa_printf(MSG_DEBUG, "DPP: Failed to send chirp on %d MHz",
+			   wpa_s->dpp_chirp_freq);
+		if (eloop_register_timeout(0, 0, wpas_dpp_chirp_next,
+					   wpa_s, NULL) < 0)
+			wpas_dpp_chirp_stop(wpa_s);
+		return;
+	}
+
+	wpa_printf(MSG_DEBUG, "DPP: Chirp send completed - wait for response");
+	if (eloop_register_timeout(2, 0, wpas_dpp_chirp_timeout,
+				   wpa_s, NULL) < 0)
+		wpas_dpp_chirp_stop(wpa_s);
+}
+
+
+static void wpas_dpp_chirp_start(struct wpa_supplicant *wpa_s)
+{
+	wpa_printf(MSG_DEBUG, "DPP: Chirp on %d MHz", wpa_s->dpp_chirp_freq);
+	wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
+		MAC2STR(broadcast), wpa_s->dpp_chirp_freq,
+		DPP_PA_PRESENCE_ANNOUNCEMENT);
+	if (offchannel_send_action(
+		    wpa_s, wpa_s->dpp_chirp_freq, broadcast,
+		    wpa_s->own_addr, broadcast,
+		    wpabuf_head(wpa_s->dpp_presence_announcement),
+		    wpabuf_len(wpa_s->dpp_presence_announcement),
+		    2000, wpas_dpp_chirp_tx_status, 0) < 0)
+		wpas_dpp_chirp_stop(wpa_s);
+}
+
+
+static void wpas_dpp_chirp_scan_res_handler(struct wpa_supplicant *wpa_s,
+					    struct wpa_scan_results *scan_res)
+{
+	struct dpp_bootstrap_info *bi = wpa_s->dpp_chirp_bi;
+	unsigned int i;
+	struct hostapd_hw_modes *mode;
+	int c;
+	struct wpa_bss *bss;
+
+	if (!bi)
+		return;
+
+	wpa_s->dpp_chirp_scan_done = 1;
+
+	os_free(wpa_s->dpp_chirp_freqs);
+	wpa_s->dpp_chirp_freqs = NULL;
+
+	/* Channels from own bootstrapping info */
+	for (i = 0; i < bi->num_freq; i++)
+		int_array_add_unique(&wpa_s->dpp_chirp_freqs, bi->freq[i]);
+
+	/* Preferred chirping channels */
+	int_array_add_unique(&wpa_s->dpp_chirp_freqs, 2437);
+
+	mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
+			HOSTAPD_MODE_IEEE80211A, 0);
+	if (mode) {
+		int chan44 = 0, chan149 = 0;
+
+		for (c = 0; c < mode->num_channels; c++) {
+			struct hostapd_channel_data *chan = &mode->channels[c];
+
+			if (chan->flag & (HOSTAPD_CHAN_DISABLED |
+					  HOSTAPD_CHAN_RADAR))
+				continue;
+			if (chan->freq == 5220)
+				chan44 = 1;
+			if (chan->freq == 5745)
+				chan149 = 1;
+		}
+		if (chan149)
+			int_array_add_unique(&wpa_s->dpp_chirp_freqs, 5745);
+		else if (chan44)
+			int_array_add_unique(&wpa_s->dpp_chirp_freqs, 5220);
+	}
+
+	mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
+			HOSTAPD_MODE_IEEE80211AD, 0);
+	if (mode) {
+		for (c = 0; c < mode->num_channels; c++) {
+			struct hostapd_channel_data *chan = &mode->channels[c];
+
+			if ((chan->flag & (HOSTAPD_CHAN_DISABLED |
+					   HOSTAPD_CHAN_RADAR)) ||
+			    chan->freq != 60480)
+				continue;
+			int_array_add_unique(&wpa_s->dpp_chirp_freqs, 60480);
+			break;
+		}
+	}
+
+	/* Add channels from scan results for APs that advertise Configurator
+	 * Connectivity element */
+	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
+		if (wpa_bss_get_vendor_ie(bss, DPP_CC_IE_VENDOR_TYPE))
+			int_array_add_unique(&wpa_s->dpp_chirp_freqs,
+					     bss->freq);
+	}
+
+	if (!wpa_s->dpp_chirp_freqs ||
+	    eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL) < 0)
+		wpas_dpp_chirp_stop(wpa_s);
+}
+
+
+static void wpas_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx)
+{
+	struct wpa_supplicant *wpa_s = eloop_ctx;
+	int i;
+
+	if (wpa_s->dpp_chirp_listen)
+		wpas_dpp_listen_stop(wpa_s);
+
+	if (wpa_s->dpp_chirp_freq == 0) {
+		if (wpa_s->dpp_chirp_round % 4 == 0 &&
+		    !wpa_s->dpp_chirp_scan_done) {
+			wpa_printf(MSG_DEBUG,
+				   "DPP: Update channel list for chirping");
+			wpa_s->scan_req = MANUAL_SCAN_REQ;
+			wpa_s->scan_res_handler =
+				wpas_dpp_chirp_scan_res_handler;
+			wpa_supplicant_req_scan(wpa_s, 0, 0);
+			return;
+		}
+		wpa_s->dpp_chirp_freq = wpa_s->dpp_chirp_freqs[0];
+		wpa_s->dpp_chirp_round++;
+		wpa_printf(MSG_DEBUG, "DPP: Start chirping round %d",
+			   wpa_s->dpp_chirp_round);
+	} else {
+		for (i = 0; wpa_s->dpp_chirp_freqs[i]; i++)
+			if (wpa_s->dpp_chirp_freqs[i] == wpa_s->dpp_chirp_freq)
+				break;
+		if (!wpa_s->dpp_chirp_freqs[i]) {
+			wpa_printf(MSG_DEBUG,
+				   "DPP: Previous chirp freq %d not found",
+				   wpa_s->dpp_chirp_freq);
+			return;
+		}
+		i++;
+		if (wpa_s->dpp_chirp_freqs[i]) {
+			wpa_s->dpp_chirp_freq = wpa_s->dpp_chirp_freqs[i];
+		} else {
+			wpa_s->dpp_chirp_iter--;
+			if (wpa_s->dpp_chirp_iter <= 0) {
+				wpa_printf(MSG_DEBUG,
+					   "DPP: Chirping iterations completed");
+				wpas_dpp_chirp_stop(wpa_s);
+				return;
+			}
+			wpa_s->dpp_chirp_freq = 0;
+			wpa_s->dpp_chirp_scan_done = 0;
+			if (eloop_register_timeout(30, 0, wpas_dpp_chirp_next,
+						   wpa_s, NULL) < 0) {
+				wpas_dpp_chirp_stop(wpa_s);
+				return;
+			}
+			if (wpa_s->dpp_chirp_listen) {
+				wpa_printf(MSG_DEBUG,
+					   "DPP: Listen on %d MHz during chirp 30 second wait",
+					wpa_s->dpp_chirp_listen);
+				wpas_dpp_listen_start(wpa_s,
+						      wpa_s->dpp_chirp_listen);
+			} else {
+				wpa_printf(MSG_DEBUG,
+					   "DPP: Wait 30 seconds before starting the next chirping round");
+			}
+			return;
+		}
+	}
+
+	wpas_dpp_chirp_start(wpa_s);
+}
+
+
+int wpas_dpp_chirp(struct wpa_supplicant *wpa_s, const char *cmd)
+{
+	const char *pos;
+	int iter = 1, listen_freq = 0;
+	struct dpp_bootstrap_info *bi;
+
+	pos = os_strstr(cmd, " own=");
+	if (!pos)
+		return -1;
+	pos += 5;
+	bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
+	if (!bi) {
+		wpa_printf(MSG_DEBUG,
+			   "DPP: Identified bootstrap info not found");
+		return -1;
+	}
+
+	pos = os_strstr(cmd, " iter=");
+	if (pos) {
+		iter = atoi(pos + 6);
+		if (iter <= 0)
+			return -1;
+	}
+
+	pos = os_strstr(cmd, " listen=");
+	if (pos) {
+		listen_freq = atoi(pos + 8);
+		if (iter <= 0)
+			return -1;
+	}
+
+	wpas_dpp_chirp_stop(wpa_s);
+	wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
+	wpa_s->dpp_qr_mutual = 0;
+	wpa_s->dpp_chirp_bi = bi;
+	wpa_s->dpp_presence_announcement = dpp_build_presence_announcement(bi);
+	if (!wpa_s->dpp_presence_announcement)
+		return -1;
+	wpa_s->dpp_chirp_iter = iter;
+	wpa_s->dpp_chirp_round = 0;
+	wpa_s->dpp_chirp_scan_done = 0;
+	wpa_s->dpp_chirp_listen = listen_freq;
+
+	return eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL);
+}
+
+
+void wpas_dpp_chirp_stop(struct wpa_supplicant *wpa_s)
+{
+	if (wpa_s->dpp_presence_announcement) {
+		offchannel_send_action_done(wpa_s);
+		wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CHIRP_STOPPED);
+	}
+	wpa_s->dpp_chirp_bi = NULL;
+	wpabuf_free(wpa_s->dpp_presence_announcement);
+	wpa_s->dpp_presence_announcement = NULL;
+	if (wpa_s->dpp_chirp_listen)
+		wpas_dpp_listen_stop(wpa_s);
+	wpa_s->dpp_chirp_listen = 0;
+	wpa_s->dpp_chirp_freq = 0;
+	os_free(wpa_s->dpp_chirp_freqs);
+	wpa_s->dpp_chirp_freqs = NULL;
+	eloop_cancel_timeout(wpas_dpp_chirp_next, wpa_s, NULL);
+	eloop_cancel_timeout(wpas_dpp_chirp_timeout, wpa_s, NULL);
+	if (wpa_s->scan_res_handler == wpas_dpp_chirp_scan_res_handler) {
+		wpas_abort_ongoing_scan(wpa_s);
+		wpa_s->scan_res_handler = NULL;
+	}
+}
+
 #endif /* CONFIG_DPP2 */
diff --git a/wpa_supplicant/dpp_supplicant.h b/wpa_supplicant/dpp_supplicant.h
index 607036a..2ce378d 100644
--- a/wpa_supplicant/dpp_supplicant.h
+++ b/wpa_supplicant/dpp_supplicant.h
@@ -1,7 +1,7 @@
 /*
  * wpa_supplicant - DPP
  * 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.
@@ -14,6 +14,8 @@
 
 int wpas_dpp_qr_code(struct wpa_supplicant *wpa_s, const char *cmd);
 int wpas_dpp_nfc_uri(struct wpa_supplicant *wpa_s, const char *cmd);
+int wpas_dpp_nfc_handover_req(struct wpa_supplicant *wpa_s, const char *cmd);
+int wpas_dpp_nfc_handover_sel(struct wpa_supplicant *wpa_s, const char *cmd);
 int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd);
 int wpas_dpp_listen(struct wpa_supplicant *wpa_s, const char *cmd);
 void wpas_dpp_listen_stop(struct wpa_supplicant *wpa_s);
@@ -33,5 +35,7 @@
 void wpas_dpp_connected(struct wpa_supplicant *wpa_s);
 void wpas_dpp_send_conn_status_result(struct wpa_supplicant *wpa_s,
 				      enum dpp_status_error result);
+int wpas_dpp_chirp(struct wpa_supplicant *wpa_s, const char *cmd);
+void wpas_dpp_chirp_stop(struct wpa_supplicant *wpa_s);
 
 #endif /* DPP_SUPPLICANT_H */
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index cf9972a..6a03d8e 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -124,13 +124,8 @@
 	return -1;
 }
 
-static inline struct wpa_scan_results * wpa_drv_get_scan_results2(
-	struct wpa_supplicant *wpa_s)
-{
-	if (wpa_s->driver->get_scan_results2)
-		return wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
-	return NULL;
-}
+struct wpa_scan_results *
+wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s);
 
 static inline int wpa_drv_get_bssid(struct wpa_supplicant *wpa_s, u8 *bssid)
 {
@@ -152,18 +147,38 @@
 				  enum wpa_alg alg, const u8 *addr,
 				  int key_idx, 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;
+
+	os_memset(&params, 0, sizeof(params));
+	params.ifname = wpa_s->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.key_flag = key_flag;
+
 	if (alg != WPA_ALG_NONE) {
-		if (key_idx >= 0 && key_idx <= 6)
+		/* keyidx = 1 can be either a broadcast or--with
+		 * Extended Key ID--a unicast key. Use bit 15 for
+		 * the pairwise keyidx 1 which is hopefully high enough
+		 * to not clash with future extensions.
+		 */
+		if (key_idx == 1 && (key_flag & KEY_FLAG_PAIRWISE))
+			wpa_s->keys_cleared &= ~BIT(15);
+		else if (key_idx >= 0 && key_idx <= 5)
 			wpa_s->keys_cleared &= ~BIT(key_idx);
 		else
 			wpa_s->keys_cleared = 0;
 	}
 	if (wpa_s->driver->set_key) {
-		return wpa_s->driver->set_key(wpa_s->ifname, wpa_s->drv_priv,
-					      alg, addr, key_idx, set_tx,
-					      seq, seq_len, key, key_len);
+		return wpa_s->driver->set_key(wpa_s->drv_priv, &params);
 	}
 	return -1;
 }
@@ -304,12 +319,12 @@
 
 static inline int wpa_drv_send_mlme(struct wpa_supplicant *wpa_s,
 				    const u8 *data, size_t data_len, int noack,
-				    unsigned int freq)
+				    unsigned int freq, unsigned int wait)
 {
 	if (wpa_s->driver->send_mlme)
 		return wpa_s->driver->send_mlme(wpa_s->drv_priv,
 						data, data_len, noack,
-						freq, NULL, 0);
+						freq, NULL, 0, 0, wait);
 	return -1;
 }
 
@@ -347,6 +362,17 @@
 	return -1;
 }
 
+static inline int wpa_drv_tx_control_port(struct wpa_supplicant *wpa_s,
+					  const u8 *dest, u16 proto,
+					  const u8 *buf, size_t len,
+					  int no_encrypt)
+{
+	if (!wpa_s->driver->tx_control_port)
+		return -1;
+	return wpa_s->driver->tx_control_port(wpa_s->drv_priv, dest, proto,
+					      buf, len, no_encrypt);
+}
+
 static inline int wpa_drv_hapd_send_eapol(struct wpa_supplicant *wpa_s,
 					  const u8 *addr, const u8 *data,
 					  size_t data_len, int encrypt,
@@ -494,13 +520,8 @@
 	return -1;
 }
 
-static inline int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
-				      struct wpa_signal_info *si)
-{
-	if (wpa_s->driver->signal_poll)
-		return wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
-	return -1;
-}
+int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
+			struct wpa_signal_info *si);
 
 static inline int wpa_drv_channel_info(struct wpa_supplicant *wpa_s,
 				       struct wpa_channel_info *ci)
@@ -681,6 +702,13 @@
 					  qos_map_set_len);
 }
 
+static inline int wpa_drv_get_wowlan(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s->driver->get_wowlan)
+		return 0;
+	return wpa_s->driver->get_wowlan(wpa_s->drv_priv);
+}
+
 static inline int wpa_drv_wowlan(struct wpa_supplicant *wpa_s,
 				 const struct wowlan_triggers *triggers)
 {
diff --git a/wpa_supplicant/eapol_test.c b/wpa_supplicant/eapol_test.c
index 53d7585..2fa4968 100644
--- a/wpa_supplicant/eapol_test.c
+++ b/wpa_supplicant/eapol_test.c
@@ -1390,7 +1390,7 @@
 			eapol_test.ctrl_iface = 1;
 			break;
 		case 'v':
-			printf("eapol_test v" VERSION_STR "\n");
+			printf("eapol_test v%s\n", VERSION_STR);
 			return 0;
 		case 'W':
 			wait_for_monitor++;
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 4c459cf..cf56108 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -188,6 +188,16 @@
 			      drv_ssid_len) == 0)
 			return 0; /* current profile still in use */
 
+#ifdef CONFIG_OWE
+		if ((wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
+		    wpa_s->current_bss &&
+		    (wpa_s->current_bss->flags & WPA_BSS_OWE_TRANSITION) &&
+		    drv_ssid_len == wpa_s->current_bss->ssid_len &&
+		    os_memcmp(drv_ssid, wpa_s->current_bss->ssid,
+			      drv_ssid_len) == 0)
+			return 0; /* current profile still in use */
+#endif /* CONFIG_OWE */
+
 		wpa_msg(wpa_s, MSG_DEBUG,
 			"Driver-initiated BSS selection changed the SSID to %s",
 			wpa_ssid_txt(drv_ssid, drv_ssid_len));
@@ -479,6 +489,7 @@
 
 #ifndef CONFIG_NO_SCAN_PROCESSING
 
+#ifdef CONFIG_WEP
 static int has_wep_key(struct wpa_ssid *ssid)
 {
 	int i;
@@ -490,6 +501,7 @@
 
 	return 0;
 }
+#endif /* CONFIG_WEP */
 
 
 static int wpa_supplicant_match_privacy(struct wpa_bss *bss,
@@ -510,8 +522,10 @@
 		return 1;
 #endif /* CONFIG_OWE */
 
+#ifdef CONFIG_WEP
 	if (has_wep_key(ssid))
 		privacy = 1;
+#endif /* CONFIG_WEP */
 
 #ifdef IEEE8021X_EAPOL
 	if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) &&
@@ -540,17 +554,21 @@
 	int proto_match = 0;
 	const u8 *rsn_ie, *wpa_ie;
 	int ret;
+#ifdef CONFIG_WEP
 	int wep_ok;
+#endif /* CONFIG_WEP */
 
 	ret = wpas_wps_ssid_bss_match(wpa_s, ssid, bss);
 	if (ret >= 0)
 		return ret;
 
+#ifdef CONFIG_WEP
 	/* Allow TSN if local configuration accepts WEP use without WPA/WPA2 */
 	wep_ok = !wpa_key_mgmt_wpa(ssid->key_mgmt) &&
 		(((ssid->key_mgmt & WPA_KEY_MGMT_NONE) &&
 		  ssid->wep_key_len[ssid->wep_tx_keyidx] > 0) ||
 		 (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA));
+#endif /* CONFIG_WEP */
 
 	rsn_ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
 	while ((ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)) && rsn_ie) {
@@ -567,6 +585,7 @@
 		if (!ie.has_group)
 			ie.group_cipher = wpa_default_rsn_cipher(bss->freq);
 
+#ifdef CONFIG_WEP
 		if (wep_ok &&
 		    (ie.group_cipher & (WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)))
 		{
@@ -575,6 +594,7 @@
 					"   selected based on TSN in RSN IE");
 			return 1;
 		}
+#endif /* CONFIG_WEP */
 
 		if (!(ie.proto & ssid->proto) &&
 		    !(ssid->proto & WPA_PROTO_OSEN)) {
@@ -655,6 +675,7 @@
 			break;
 		}
 
+#ifdef CONFIG_WEP
 		if (wep_ok &&
 		    (ie.group_cipher & (WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)))
 		{
@@ -663,6 +684,7 @@
 					"   selected based on TSN in WPA IE");
 			return 1;
 		}
+#endif /* CONFIG_WEP */
 
 		if (!(ie.proto & ssid->proto)) {
 			if (debug_print)
@@ -772,8 +794,8 @@
 }
 
 
-static int rate_match(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
-		      int debug_print)
+static int rate_match(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
+		      struct wpa_bss *bss, int debug_print)
 {
 	const struct hostapd_hw_modes *mode = NULL, *modes;
 	const u8 scan_ie[2] = { WLAN_EID_SUPP_RATES, WLAN_EID_EXT_SUPP_RATES };
@@ -853,7 +875,9 @@
 #ifdef CONFIG_SAE
 			if (flagged && ((rate_ie[j] & 0x7f) ==
 					BSS_MEMBERSHIP_SELECTOR_SAE_H2E_ONLY)) {
-				if (wpa_s->conf->sae_pwe == 0) {
+				if (wpa_s->conf->sae_pwe == 0 &&
+				    !ssid->sae_password_id &&
+				    wpa_key_mgmt_sae(ssid->key_mgmt)) {
 					if (debug_print)
 						wpa_dbg(wpa_s, MSG_DEBUG,
 							"   SAE H2E disabled");
@@ -971,6 +995,24 @@
 	*ret_ssid = pos;
 	*ret_ssid_len = ssid_len;
 
+	if (!(bss->flags & WPA_BSS_OWE_TRANSITION)) {
+		struct wpa_ssid *ssid;
+
+		for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
+			if (wpas_network_disabled(wpa_s, ssid))
+				continue;
+			if (ssid->ssid_len == ssid_len &&
+			    os_memcmp(ssid->ssid, pos, ssid_len) == 0) {
+				/* OWE BSS in transition mode for a currently
+				 * enabled OWE network. */
+				wpa_dbg(wpa_s, MSG_DEBUG,
+					"OWE: transition mode OWE SSID for active OWE profile");
+				bss->flags |= WPA_BSS_OWE_TRANSITION;
+				break;
+			}
+		}
+	}
+
 	if (bss->ssid_len > 0)
 		return;
 
@@ -1011,10 +1053,33 @@
 		wpa_ssid_txt(pos, ssid_len));
 	os_memcpy(bss->ssid, pos, ssid_len);
 	bss->ssid_len = ssid_len;
+	bss->flags |= WPA_BSS_OWE_TRANSITION;
 #endif /* CONFIG_OWE */
 }
 
 
+static int disabled_freq(struct wpa_supplicant *wpa_s, int freq)
+{
+	int i, j;
+
+	if (!wpa_s->hw.modes || !wpa_s->hw.num_modes)
+		return 0;
+
+	for (j = 0; j < wpa_s->hw.num_modes; j++) {
+		struct hostapd_hw_modes *mode = &wpa_s->hw.modes[j];
+
+		for (i = 0; i < mode->num_channels; i++) {
+			struct hostapd_channel_data *chan = &mode->channels[i];
+
+			if (chan->freq == freq)
+				return !!(chan->flag & HOSTAPD_CHAN_DISABLED);
+		}
+	}
+
+	return 1;
+}
+
+
 struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
 				     int i, struct wpa_bss *bss,
 				     struct wpa_ssid *group,
@@ -1106,6 +1171,12 @@
 		return NULL;
 	}
 
+	if (disabled_freq(wpa_s, bss->freq)) {
+		if (debug_print)
+			wpa_dbg(wpa_s, MSG_DEBUG, "   skip - channel disabled");
+		return NULL;
+	}
+
 	wpa = wpa_ie_len > 0 || rsn_ie_len > 0;
 
 	for (ssid = group; ssid; ssid = only_first_ssid ? NULL : ssid->pnext) {
@@ -1206,6 +1277,7 @@
 			continue;
 		}
 
+#ifdef CONFIG_WEP
 		if (wpa && !wpa_key_mgmt_wpa(ssid->key_mgmt) &&
 		    has_wep_key(ssid)) {
 			if (debug_print)
@@ -1213,6 +1285,7 @@
 					"   skip - ignore WPA/WPA2 AP for WEP network block");
 			continue;
 		}
+#endif /* CONFIG_WEP */
 
 		if ((ssid->key_mgmt & WPA_KEY_MGMT_OSEN) && !osen &&
 		    !rsn_osen) {
@@ -1262,7 +1335,7 @@
 		}
 #endif /* CONFIG_MESH */
 
-		if (!rate_match(wpa_s, bss, debug_print)) {
+		if (!rate_match(wpa_s, ssid, bss, debug_print)) {
 			if (debug_print)
 				wpa_dbg(wpa_s, MSG_DEBUG,
 					"   skip - rate sets do not match");
@@ -1270,7 +1343,8 @@
 		}
 
 #ifdef CONFIG_SAE
-		if (wpa_s->conf->sae_pwe == 1 &&
+		if ((wpa_s->conf->sae_pwe == 1 || ssid->sae_password_id) &&
+		    wpa_s->conf->sae_pwe != 3 &&
 		    wpa_key_mgmt_sae(ssid->key_mgmt) &&
 		    (!(ie = wpa_bss_get_ie(bss, WLAN_EID_RSNX)) ||
 		     ie[1] < 1 ||
@@ -1446,8 +1520,9 @@
 		wpa_s->owe_transition_select = 0;
 		if (!*selected_ssid)
 			continue;
-		wpa_dbg(wpa_s, MSG_DEBUG, "   selected BSS " MACSTR
+		wpa_dbg(wpa_s, MSG_DEBUG, "   selected %sBSS " MACSTR
 			" ssid='%s'",
+			bss == wpa_s->current_bss ? "current ": "",
 			MAC2STR(bss->bssid),
 			wpa_ssid_txt(bss->ssid, bss->ssid_len));
 		return bss;
@@ -1461,7 +1536,7 @@
 					     struct wpa_ssid **selected_ssid)
 {
 	struct wpa_bss *selected = NULL;
-	int prio;
+	size_t prio;
 	struct wpa_ssid *next_ssid = NULL;
 	struct wpa_ssid *ssid;
 
@@ -1616,7 +1691,7 @@
 static struct wpa_ssid *
 wpa_supplicant_pick_new_network(struct wpa_supplicant *wpa_s)
 {
-	int prio;
+	size_t prio;
 	struct wpa_ssid *ssid;
 
 	for (prio = 0; prio < wpa_s->conf->num_prio; prio++) {
@@ -1672,6 +1747,31 @@
 }
 
 
+#ifndef CONFIG_NO_ROAMING
+
+static int wpas_get_snr_signal_info(u32 frequency, int avg_signal, int noise)
+{
+	if (noise == WPA_INVALID_NOISE)
+		noise = IS_5GHZ(frequency) ? DEFAULT_NOISE_FLOOR_5GHZ :
+			DEFAULT_NOISE_FLOOR_2GHZ;
+	return avg_signal - noise;
+}
+
+
+static unsigned int
+wpas_get_est_throughput_from_bss_snr(const struct wpa_supplicant *wpa_s,
+				     const struct wpa_bss *bss, int snr)
+{
+	int rate = wpa_bss_get_max_rate(bss);
+	const u8 *ies = (const void *) (bss + 1);
+	size_t ie_len = bss->ie_len ? bss->ie_len : bss->beacon_ie_len;
+
+	return wpas_get_est_tpt(wpa_s, ies, ie_len, rate, snr);
+}
+
+#endif /* CONFIG_NO_ROAMING */
+
+
 static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s,
 				       struct wpa_bss *selected,
 				       struct wpa_ssid *ssid)
@@ -1680,7 +1780,10 @@
 #ifndef CONFIG_NO_ROAMING
 	int min_diff, diff;
 	int to_5ghz;
-	int cur_est, sel_est;
+	int cur_level;
+	unsigned int cur_est, sel_est;
+	struct wpa_signal_info si;
+	int cur_snr = 0;
 #endif /* CONFIG_NO_ROAMING */
 
 	if (wpa_s->reassociate)
@@ -1731,7 +1834,41 @@
 		return 1;
 	}
 
-	if (selected->est_throughput > current_bss->est_throughput + 5000) {
+	cur_level = current_bss->level;
+	cur_est = current_bss->est_throughput;
+	sel_est = selected->est_throughput;
+
+	/*
+	 * Try to poll the signal from the driver since this will allow to get
+	 * more accurate values. In some cases, there can be big differences
+	 * between the RSSI of the Probe Response frames of the AP we are
+	 * associated with and the Beacon frames we hear from the same AP after
+	 * association. This can happen, e.g., when there are two antennas that
+	 * hear the AP very differently. If the driver chooses to hear the
+	 * Probe Response frames during the scan on the "bad" antenna because
+	 * it wants to save power, but knows to choose the other antenna after
+	 * association, we will hear our AP with a low RSSI as part of the
+	 * scan even when we can hear it decently on the other antenna. To cope
+	 * with this, ask the driver to teach us how it hears the AP. Also, the
+	 * scan results may be a bit old, since we can very quickly get fresh
+	 * information about our currently associated AP.
+	 */
+	if (wpa_drv_signal_poll(wpa_s, &si) == 0 &&
+	    (si.avg_beacon_signal || si.avg_signal)) {
+		cur_level = si.avg_beacon_signal ? si.avg_beacon_signal :
+			si.avg_signal;
+		cur_snr = wpas_get_snr_signal_info(si.frequency, cur_level,
+						   si.current_noise);
+
+		cur_est = wpas_get_est_throughput_from_bss_snr(wpa_s,
+							       current_bss,
+							       cur_snr);
+		wpa_dbg(wpa_s, MSG_DEBUG,
+			"Using signal poll values for the current BSS: level=%d snr=%d est_throughput=%u",
+			cur_level, cur_snr, cur_est);
+	}
+
+	if (sel_est > cur_est + 5000) {
 		wpa_dbg(wpa_s, MSG_DEBUG,
 			"Allow reassociation - selected BSS has better estimated throughput");
 		return 1;
@@ -1739,59 +1876,59 @@
 
 	to_5ghz = selected->freq > 4000 && current_bss->freq < 4000;
 
-	if (current_bss->level < 0 &&
-	    current_bss->level > selected->level + to_5ghz * 2) {
+	if (cur_level < 0 && cur_level > selected->level + to_5ghz * 2 &&
+	    sel_est < cur_est * 1.2) {
 		wpa_dbg(wpa_s, MSG_DEBUG, "Skip roam - Current BSS has better "
 			"signal level");
 		return 0;
 	}
 
-	if (current_bss->est_throughput > selected->est_throughput + 5000) {
+	if (cur_est > sel_est + 5000) {
 		wpa_dbg(wpa_s, MSG_DEBUG,
 			"Skip roam - Current BSS has better estimated throughput");
 		return 0;
 	}
 
-	cur_est = current_bss->est_throughput;
-	sel_est = selected->est_throughput;
-	min_diff = 2;
-	if (current_bss->level < 0) {
-		if (current_bss->level < -85)
-			min_diff = 1;
-		else if (current_bss->level < -80)
-			min_diff = 2;
-		else if (current_bss->level < -75)
-			min_diff = 3;
-		else if (current_bss->level < -70)
-			min_diff = 4;
-		else
-			min_diff = 5;
-		if (cur_est > sel_est * 1.5)
-			min_diff += 10;
-		else if (cur_est > sel_est * 1.2)
-			min_diff += 5;
-		else if (cur_est > sel_est * 1.1)
-			min_diff += 2;
-		else if (cur_est > sel_est)
-			min_diff++;
+	if (cur_snr > GREAT_SNR) {
+		wpa_dbg(wpa_s, MSG_DEBUG,
+			"Skip roam - Current BSS has good SNR (%u > %u)",
+			cur_snr, GREAT_SNR);
+		return 0;
 	}
-	if (to_5ghz) {
-		int reduce = 2;
 
-		/* Make it easier to move to 5 GHz band */
-		if (sel_est > cur_est * 1.5)
-			reduce = 5;
-		else if (sel_est > cur_est * 1.2)
-			reduce = 4;
-		else if (sel_est > cur_est * 1.1)
-			reduce = 3;
+	if (cur_level < -85) /* ..-86 dBm */
+		min_diff = 1;
+	else if (cur_level < -80) /* -85..-81 dBm */
+		min_diff = 2;
+	else if (cur_level < -75) /* -80..-76 dBm */
+		min_diff = 3;
+	else if (cur_level < -70) /* -75..-71 dBm */
+		min_diff = 4;
+	else if (cur_level < 0) /* -70..-1 dBm */
+		min_diff = 5;
+	else /* unspecified units (not in dBm) */
+		min_diff = 2;
 
-		if (min_diff > reduce)
-			min_diff -= reduce;
-		else
-			min_diff = 0;
-	}
-	diff = abs(current_bss->level - selected->level);
+	if (cur_est > sel_est * 1.5)
+		min_diff += 10;
+	else if (cur_est > sel_est * 1.2)
+		min_diff += 5;
+	else if (cur_est > sel_est * 1.1)
+		min_diff += 2;
+	else if (cur_est > sel_est)
+		min_diff++;
+	else if (sel_est > cur_est * 1.5)
+		min_diff -= 10;
+	else if (sel_est > cur_est * 1.2)
+		min_diff -= 5;
+	else if (sel_est > cur_est * 1.1)
+		min_diff -= 2;
+	else if (sel_est > cur_est)
+		min_diff--;
+
+	if (to_5ghz)
+		min_diff -= 2;
+	diff = selected->level - cur_level;
 	if (diff < min_diff) {
 		wpa_dbg(wpa_s, MSG_DEBUG,
 			"Skip roam - too small difference in signal level (%d < %d)",
@@ -1887,15 +2024,6 @@
 		goto scan_work_done;
 	}
 
-	if (ap) {
-		wpa_dbg(wpa_s, MSG_DEBUG, "Ignore scan results in AP mode");
-#ifdef CONFIG_AP
-		if (wpa_s->ap_iface->scan_cb)
-			wpa_s->ap_iface->scan_cb(wpa_s->ap_iface);
-#endif /* CONFIG_AP */
-		goto scan_work_done;
-	}
-
 	wpa_dbg(wpa_s, MSG_DEBUG, "New scan results available (own=%u ext=%u)",
 		wpa_s->own_scan_running,
 		data ? data->scan_info.external_scan : 0);
@@ -1912,6 +2040,15 @@
 
 	wpas_notify_scan_done(wpa_s, 1);
 
+	if (ap) {
+		wpa_dbg(wpa_s, MSG_DEBUG, "Ignore scan results in AP mode");
+#ifdef CONFIG_AP
+		if (wpa_s->ap_iface->scan_cb)
+			wpa_s->ap_iface->scan_cb(wpa_s->ap_iface);
+#endif /* CONFIG_AP */
+		goto scan_work_done;
+	}
+
 	if (data && data->scan_info.external_scan) {
 		wpa_dbg(wpa_s, MSG_DEBUG, "Do not use results from externally requested scan operation for network selection");
 		wpa_scan_results_free(scan_res);
@@ -2194,7 +2331,8 @@
 		return -1;
 
 	os_get_reltime(&now);
-	if (os_reltime_expired(&now, &wpa_s->last_scan, 5)) {
+	if (os_reltime_expired(&now, &wpa_s->last_scan,
+			       SCAN_RES_VALID_FOR_CONNECT)) {
 		wpa_printf(MSG_DEBUG, "Fast associate: Old scan results");
 		return -1;
 	}
@@ -2327,28 +2465,41 @@
 	const u8 *map_sub_elem, *pos;
 	size_t len;
 
-	if (!wpa_s->current_ssid ||
-	    !wpa_s->current_ssid->multi_ap_backhaul_sta ||
-	    !ies ||
-	    ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed)
-		return;
+	wpa_s->multi_ap_ie = 0;
 
-	if (!elems.multi_ap || elems.multi_ap_len < 7) {
-		wpa_printf(MSG_INFO, "AP doesn't support Multi-AP protocol");
-		goto fail;
-	}
+	if (!ies ||
+	    ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed ||
+	    !elems.multi_ap || elems.multi_ap_len < 7)
+		return;
 
 	pos = elems.multi_ap + 4;
 	len = elems.multi_ap_len - 4;
 
 	map_sub_elem = get_ie(pos, len, MULTI_AP_SUB_ELEM_TYPE);
-	if (!map_sub_elem || map_sub_elem[1] < 1) {
-		wpa_printf(MSG_INFO, "invalid Multi-AP sub elem type");
+	if (!map_sub_elem || map_sub_elem[1] < 1)
+		return;
+
+	wpa_s->multi_ap_backhaul = !!(map_sub_elem[2] & MULTI_AP_BACKHAUL_BSS);
+	wpa_s->multi_ap_fronthaul = !!(map_sub_elem[2] &
+				       MULTI_AP_FRONTHAUL_BSS);
+	wpa_s->multi_ap_ie = 1;
+}
+
+
+static void multi_ap_set_4addr_mode(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s->current_ssid ||
+	    !wpa_s->current_ssid->multi_ap_backhaul_sta)
+		return;
+
+	if (!wpa_s->multi_ap_ie) {
+		wpa_printf(MSG_INFO,
+			   "AP does not include valid Multi-AP element");
 		goto fail;
 	}
 
-	if (!(map_sub_elem[2] & MULTI_AP_BACKHAUL_BSS)) {
-		if ((map_sub_elem[2] & MULTI_AP_FRONTHAUL_BSS) &&
+	if (!wpa_s->multi_ap_backhaul) {
+		if (wpa_s->multi_ap_fronthaul &&
 		    wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
 			wpa_printf(MSG_INFO,
 				   "WPS active, accepting fronthaul-only BSS");
@@ -2472,8 +2623,14 @@
 			wpa_s->connection_set = 1;
 			wpa_s->connection_ht = req_elems.ht_capabilities &&
 				resp_elems.ht_capabilities;
+			/* Do not include subset of VHT on 2.4 GHz vendor
+			 * extension in consideration for reporting VHT
+			 * association. */
 			wpa_s->connection_vht = req_elems.vht_capabilities &&
-				resp_elems.vht_capabilities;
+				resp_elems.vht_capabilities &&
+				(!data->assoc_info.freq ||
+				 wpas_freq_to_band(data->assoc_info.freq) !=
+				 BAND_2_4_GHZ);
 			wpa_s->connection_he = req_elems.he_capabilities &&
 				resp_elems.he_capabilities;
 
@@ -2818,6 +2975,7 @@
 #endif /* CONFIG_AP */
 
 	eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
+	wpa_s->own_reconnect_req = 0;
 
 	ft_completed = wpa_ft_is_completed(wpa_s->wpa);
 	if (data && wpa_supplicant_event_associnfo(wpa_s, data) < 0)
@@ -2867,6 +3025,8 @@
 		}
 	}
 
+	multi_ap_set_4addr_mode(wpa_s);
+
 	if (wpa_s->conf->ap_scan == 1 &&
 	    wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION) {
 		if (wpa_supplicant_assoc_update_ie(wpa_s) < 0 && new_bss)
@@ -2971,6 +3131,13 @@
 	wpa_s->last_eapol_matches_bssid = 0;
 
 #ifdef CONFIG_TESTING_OPTIONS
+	if (wpa_s->rsne_override_eapol) {
+		wpa_printf(MSG_DEBUG,
+			   "TESTING: RSNE EAPOL-Key msg 2/4 override");
+		wpa_sm_set_assoc_wpa_ie(wpa_s->wpa,
+					wpabuf_head(wpa_s->rsne_override_eapol),
+					wpabuf_len(wpa_s->rsne_override_eapol));
+	}
 	if (wpa_s->rsnxe_override_eapol) {
 		wpa_printf(MSG_DEBUG,
 			   "TESTING: RSNXE EAPOL-Key msg 2/4 override");
@@ -2999,6 +3166,7 @@
 		wpa_s->pending_eapol_rx = NULL;
 	}
 
+#ifdef CONFIG_WEP
 	if ((wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
 	     wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) &&
 	    wpa_s->current_ssid &&
@@ -3006,6 +3174,7 @@
 		/* Set static WEP keys again */
 		wpa_set_wep_keys(wpa_s, wpa_s->current_ssid);
 	}
+#endif /* CONFIG_WEP */
 
 #ifdef CONFIG_IBSS_RSN
 	if (wpa_s->current_ssid &&
@@ -3051,6 +3220,10 @@
 #ifdef CONFIG_MBO
 	wpas_mbo_check_pmf(wpa_s, bss, wpa_s->current_ssid);
 #endif /* CONFIG_MBO */
+
+#ifdef CONFIG_DPP2
+	wpa_s->dpp_pfs_fallback = 0;
+#endif /* CONFIG_DPP2 */
 }
 
 
@@ -3178,21 +3351,25 @@
 		if (wpa_s->wpa_state == WPA_COMPLETED &&
 		    wpa_s->current_ssid &&
 		    wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
-		    !locally_generated &&
-		    disconnect_reason_recoverable(reason_code)) {
+		    (wpa_s->own_reconnect_req ||
+		     (!locally_generated &&
+		      disconnect_reason_recoverable(reason_code)))) {
 			/*
 			 * It looks like the AP has dropped association with
-			 * us, but could allow us to get back in. Try to
-			 * reconnect to the same BSS without full scan to save
-			 * time for some common cases.
+			 * us, but could allow us to get back in. This is also
+			 * triggered for cases where local reconnection request
+			 * is used to force reassociation with the same BSS.
+			 * Try to reconnect to the same BSS without a full scan
+			 * to save time for some common cases.
 			 */
 			fast_reconnect = wpa_s->current_bss;
 			fast_reconnect_ssid = wpa_s->current_ssid;
-		} else if (wpa_s->wpa_state >= WPA_ASSOCIATING)
+		} else if (wpa_s->wpa_state >= WPA_ASSOCIATING) {
 			wpa_supplicant_req_scan(wpa_s, 0, 100000);
-		else
+		} else {
 			wpa_dbg(wpa_s, MSG_DEBUG, "Do not request new "
 				"immediate scan");
+		}
 	} else {
 		wpa_dbg(wpa_s, MSG_DEBUG, "Auto connect disabled: do not "
 			"try to re-connect");
@@ -4216,6 +4393,39 @@
 	}
 #endif /* CONFIG_OWE */
 
+#ifdef CONFIG_DPP2
+	/* Try to follow AP's PFS policy. WLAN_STATUS_ASSOC_DENIED_UNSPEC is
+	 * the status code defined in the DPP R2 tech spec.
+	 * WLAN_STATUS_AKMP_NOT_VALID is addressed in the same manner as an
+	 * interoperability workaround with older hostapd implementation. */
+	if (wpa_s->current_ssid &&
+	    wpa_s->current_ssid->key_mgmt == WPA_KEY_MGMT_DPP &&
+	    wpa_s->current_ssid->dpp_pfs == 0 &&
+	    (data->assoc_reject.status_code ==
+	     WLAN_STATUS_ASSOC_DENIED_UNSPEC ||
+	     data->assoc_reject.status_code == WLAN_STATUS_AKMP_NOT_VALID)) {
+		struct wpa_ssid *ssid = wpa_s->current_ssid;
+		struct wpa_bss *bss = wpa_s->current_bss;
+
+		wpa_s->current_ssid->dpp_pfs_fallback ^= 1;
+		if (!bss)
+			bss = wpa_supplicant_get_new_bss(wpa_s, bssid);
+		if (!bss || wpa_s->dpp_pfs_fallback) {
+			wpa_printf(MSG_DEBUG,
+				   "DPP: Updated PFS policy for next try");
+			wpas_connection_failed(wpa_s, bssid);
+			wpa_supplicant_mark_disassoc(wpa_s);
+			return;
+		}
+		wpa_printf(MSG_DEBUG, "DPP: Try again with updated PFS policy");
+		wpa_s->dpp_pfs_fallback = 1;
+		wpas_connect_work_done(wpa_s);
+		wpa_supplicant_mark_disassoc(wpa_s);
+		wpa_supplicant_connect(wpa_s, bss, ssid);
+		return;
+	}
+#endif /* CONFIG_DPP2 */
+
 #ifdef CONFIG_MBO
 	if (data->assoc_reject.status_code ==
 	    WLAN_STATUS_DENIED_POOR_CHANNEL_CONDITIONS &&
@@ -4282,11 +4492,44 @@
 }
 
 
+static void wpas_event_unprot_beacon(struct wpa_supplicant *wpa_s,
+				     struct unprot_beacon *data)
+{
+	struct wpabuf *buf;
+	int res;
+
+	if (!data || wpa_s->wpa_state != WPA_COMPLETED ||
+	    os_memcmp(data->sa, wpa_s->bssid, ETH_ALEN) != 0)
+		return;
+	wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_UNPROT_BEACON MACSTR,
+		MAC2STR(data->sa));
+
+	buf = wpabuf_alloc(4);
+	if (!buf)
+		return;
+
+	wpabuf_put_u8(buf, WLAN_ACTION_WNM);
+	wpabuf_put_u8(buf, WNM_NOTIFICATION_REQ);
+	wpabuf_put_u8(buf, 1); /* Dialog Token */
+	wpabuf_put_u8(buf, WNM_NOTIF_TYPE_BEACON_PROTECTION_FAILURE);
+
+	res = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
+				  wpa_s->own_addr, wpa_s->bssid,
+				  wpabuf_head(buf), wpabuf_len(buf), 0);
+	if (res < 0)
+		wpa_printf(MSG_DEBUG,
+			   "Failed to send WNM-Notification Request frame");
+
+	wpabuf_free(buf);
+}
+
+
 void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
 			  union wpa_event_data *data)
 {
 	struct wpa_supplicant *wpa_s = ctx;
 	int resched;
+	struct os_reltime age, clear_at;
 #ifndef CONFIG_NO_STDOUT_DEBUG
 	int level = MSG_DEBUG;
 #endif /* CONFIG_NO_STDOUT_DEBUG */
@@ -4589,6 +4832,20 @@
 		wpa_s->assoc_freq = data->ch_switch.freq;
 		wpa_s->current_ssid->frequency = data->ch_switch.freq;
 
+#ifdef CONFIG_SME
+		switch (data->ch_switch.ch_offset) {
+		case 1:
+			wpa_s->sme.ht_sec_chan = HT_SEC_CHAN_ABOVE;
+			break;
+		case -1:
+			wpa_s->sme.ht_sec_chan = HT_SEC_CHAN_BELOW;
+			break;
+		default:
+			wpa_s->sme.ht_sec_chan = HT_SEC_CHAN_UNKNOWN;
+			break;
+		}
+#endif /* CONFIG_SME */
+
 #ifdef CONFIG_AP
 		if (wpa_s->current_ssid->mode == WPAS_MODE_AP ||
 		    wpa_s->current_ssid->mode == WPAS_MODE_P2P_GO ||
@@ -4811,6 +5068,8 @@
 	case EVENT_INTERFACE_ENABLED:
 		wpa_dbg(wpa_s, MSG_DEBUG, "Interface was enabled");
 		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
+			eloop_cancel_timeout(wpas_clear_disabled_interface,
+					     wpa_s, NULL);
 			wpa_supplicant_update_mac_addr(wpa_s);
 			wpa_supplicant_set_default_scan_ies(wpa_s);
 			if (wpa_s->p2p_mgmt) {
@@ -4879,8 +5138,20 @@
 				wpa_s, WLAN_REASON_DEAUTH_LEAVING, 1);
 		}
 		wpa_supplicant_mark_disassoc(wpa_s);
-		if (!wpa_s->conf->bss_no_flush_when_down)
-			wpa_bss_flush(wpa_s);
+		os_reltime_age(&wpa_s->last_scan, &age);
+		if (age.sec >= SCAN_RES_VALID_FOR_CONNECT) {
+			clear_at.sec = SCAN_RES_VALID_FOR_CONNECT;
+			clear_at.usec = 0;
+		} else {
+			struct os_reltime tmp;
+
+			tmp.sec = SCAN_RES_VALID_FOR_CONNECT;
+			tmp.usec = 0;
+			os_reltime_sub(&tmp, &age, &clear_at);
+		}
+		eloop_register_timeout(clear_at.sec, clear_at.usec,
+				       wpas_clear_disabled_interface,
+				       wpa_s, NULL);
 		radio_remove_works(wpa_s, NULL, 0);
 
 		wpa_supplicant_set_state(wpa_s, WPA_INTERFACE_DISABLED);
@@ -5057,6 +5328,9 @@
 						 data->sta_opmode.rx_nss);
 #endif /* CONFIG_AP */
 		break;
+	case EVENT_UNPROT_BEACON:
+		wpas_event_unprot_beacon(wpa_s, &data->unprot_beacon);
+		break;
 	default:
 		wpa_msg(wpa_s, MSG_INFO, "Unknown event %d", event);
 		break;
diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py
new file mode 100755
index 0000000..f49da34
--- /dev/null
+++ b/wpa_supplicant/examples/dpp-nfc.py
@@ -0,0 +1,692 @@
+#!/usr/bin/python3
+#
+# Example nfcpy to wpa_supplicant wrapper for DPP NFC operations
+# Copyright (c) 2012-2013, Jouni Malinen <j@w1.fi>
+# Copyright (c) 2019-2020, The Linux Foundation
+#
+# This software may be distributed under the terms of the BSD license.
+# See README for more details.
+
+import os
+import sys
+import time
+import threading
+import argparse
+
+import nfc
+import ndef
+
+import logging
+
+scriptsdir = os.path.dirname(os.path.realpath("dpp-nfc.py"))
+sys.path.append(os.path.join(scriptsdir, '..', '..', 'wpaspy'))
+import wpaspy
+
+wpas_ctrl = '/var/run/wpa_supplicant'
+ifname = None
+init_on_touch = False
+in_raw_mode = False
+prev_tcgetattr = 0
+no_input = False
+srv = None
+continue_loop = True
+terminate_now = False
+summary_file = None
+success_file = None
+
+def summary(txt):
+    print(txt)
+    if summary_file:
+        with open(summary_file, 'a') as f:
+            f.write(txt + "\n")
+
+def success_report(txt):
+    summary(txt)
+    if success_file:
+        with open(success_file, 'a') as f:
+            f.write(txt + "\n")
+
+def wpas_connect():
+    ifaces = []
+    if os.path.isdir(wpas_ctrl):
+        try:
+            ifaces = [os.path.join(wpas_ctrl, i) for i in os.listdir(wpas_ctrl)]
+        except OSError as error:
+            print("Could not find wpa_supplicant: ", error)
+            return None
+
+    if len(ifaces) < 1:
+        print("No wpa_supplicant control interface found")
+        return None
+
+    for ctrl in ifaces:
+        if ifname:
+            if ifname not in ctrl:
+                continue
+        try:
+            print("Trying to use control interface " + ctrl)
+            wpas = wpaspy.Ctrl(ctrl)
+            return wpas
+        except Exception as e:
+            pass
+    return None
+
+def dpp_nfc_uri_process(uri):
+    wpas = wpas_connect()
+    if wpas is None:
+        return False
+    peer_id = wpas.request("DPP_NFC_URI " + uri)
+    if "FAIL" in peer_id:
+        print("Could not parse DPP URI from NFC URI record")
+        return False
+    peer_id = int(peer_id)
+    print("peer_id=%d" % peer_id)
+    cmd = "DPP_AUTH_INIT peer=%d" % peer_id
+    res = wpas.request(cmd)
+    if "OK" not in res:
+        print("Failed to initiate DPP Authentication")
+        return False
+    print("DPP Authentication initiated")
+    return True
+
+def dpp_hs_tag_read(record):
+    wpas = wpas_connect()
+    if wpas is None:
+        return False
+    print(record)
+    if len(record.data) < 5:
+        print("Too short DPP HS")
+        return False
+    if record.data[0] != 0:
+        print("Unexpected URI Identifier Code")
+        return False
+    uribuf = record.data[1:]
+    try:
+        uri = uribuf.decode()
+    except:
+        print("Invalid URI payload")
+        return False
+    print("URI: " + uri)
+    if not uri.startswith("DPP:"):
+        print("Not a DPP URI")
+        return False
+    return dpp_nfc_uri_process(uri)
+
+def get_status(wpas, extra=None):
+    if extra:
+        extra = "-" + extra
+    else:
+        extra = ""
+    res = wpas.request("STATUS" + extra)
+    lines = res.splitlines()
+    vals = dict()
+    for l in lines:
+        try:
+            [name, value] = l.split('=', 1)
+        except ValueError:
+            logger.info("Ignore unexpected status line: " + l)
+            continue
+        vals[name] = value
+    return vals
+
+def get_status_field(wpas, field, extra=None):
+    vals = get_status(wpas, extra)
+    if field in vals:
+        return vals[field]
+    return None
+
+def own_addr(wpas):
+    return get_status_field(wpas, "address")
+
+def dpp_bootstrap_gen(wpas, type="qrcode", chan=None, mac=None, info=None,
+                      curve=None, key=None):
+    cmd = "DPP_BOOTSTRAP_GEN type=" + type
+    if chan:
+        cmd += " chan=" + chan
+    if mac:
+        if mac is True:
+            mac = own_addr(wpas)
+        cmd += " mac=" + mac.replace(':', '')
+    if info:
+        cmd += " info=" + info
+    if curve:
+        cmd += " curve=" + curve
+    if key:
+        cmd += " key=" + key
+    res = wpas.request(cmd)
+    if "FAIL" in res:
+        raise Exception("Failed to generate bootstrapping info")
+    return int(res)
+
+def wpas_get_nfc_uri(start_listen=True):
+    wpas = wpas_connect()
+    if wpas is None:
+        return None
+    global own_id, chanlist
+    own_id = dpp_bootstrap_gen(wpas, type="nfc-uri", chan=chanlist, mac=True)
+    res = wpas.request("DPP_BOOTSTRAP_GET_URI %d" % own_id).rstrip()
+    if "FAIL" in res:
+        return None
+    if start_listen:
+        wpas.request("DPP_LISTEN 2412 netrole=configurator")
+    return res
+
+def wpas_report_handover_req(uri):
+    wpas = wpas_connect()
+    if wpas is None:
+        return None
+    global own_id
+    cmd = "DPP_NFC_HANDOVER_REQ own=%d uri=%s" % (own_id, uri)
+    return wpas.request(cmd)
+
+def wpas_report_handover_sel(uri):
+    wpas = wpas_connect()
+    if wpas is None:
+        return None
+    global own_id
+    cmd = "DPP_NFC_HANDOVER_SEL own=%d uri=%s" % (own_id, uri)
+    return wpas.request(cmd)
+
+def dpp_handover_client(llc):
+    uri = wpas_get_nfc_uri(start_listen=False)
+    uri = ndef.UriRecord(uri)
+    print("NFC URI record for DPP: " + str(uri))
+    carrier = ndef.Record('application/vnd.wfa.dpp', 'A', uri.data)
+    hr = ndef.HandoverRequestRecord(version="1.4", crn=os.urandom(2))
+    hr.add_alternative_carrier('active', carrier.name)
+    message = [hr, carrier]
+    print("NFC Handover Request message for DPP: " + str(message))
+
+    client = nfc.handover.HandoverClient(llc)
+    try:
+        summary("Trying to initiate NFC connection handover")
+        client.connect()
+        summary("Connected for handover")
+    except nfc.llcp.ConnectRefused:
+        summary("Handover connection refused")
+        client.close()
+        return
+    except Exception as e:
+        summary("Other exception: " + str(e))
+        client.close()
+        return
+
+    summary("Sending handover request")
+
+    if not client.send_records(message):
+        summary("Failed to send handover request")
+        client.close()
+        return
+
+    summary("Receiving handover response")
+    message = client.recv_records(timeout=3.0)
+    if message is None:
+        summary("No response received")
+        client.close()
+        return
+    print("Received message: " + str(message))
+    if len(message) < 1 or \
+       not isinstance(message[0], ndef.HandoverSelectRecord):
+        summary("Response was not Hs - received: " + message.type)
+        client.close()
+        return
+
+    print("Received message")
+    print("alternative carriers: " + str(message[0].alternative_carriers))
+
+    dpp_found = False
+    for carrier in message:
+        if isinstance(carrier, ndef.HandoverSelectRecord):
+            continue
+        print("Remote carrier type: " + carrier.type)
+        if carrier.type == "application/vnd.wfa.dpp":
+            if len(carrier.data) == 0 or carrier.data[0] != 0:
+                print("URI Identifier Code 'None' not seen")
+                continue
+            print("DPP carrier type match - send to wpa_supplicant")
+            dpp_found = True
+            uri = carrier.data[1:].decode("utf-8")
+            print("DPP URI: " + uri)
+            res = wpas_report_handover_sel(uri)
+            if res is None or "FAIL" in res:
+                summary("DPP handover report rejected")
+                break
+
+            success_report("DPP handover reported successfully (initiator)")
+            print("peer_id=" + res)
+            peer_id = int(res)
+            # TODO: Single Configurator instance
+            wpas = wpas_connect()
+            if wpas is None:
+                break
+            res = wpas.request("DPP_CONFIGURATOR_ADD")
+            if "FAIL" in res:
+                print("Failed to initiate Configurator")
+                break
+            conf_id = int(res)
+            global own_id
+            print("Initiate DPP authentication")
+            cmd = "DPP_AUTH_INIT peer=%d own=%d conf=sta-dpp configurator=%d" % (peer_id, own_id, conf_id)
+            res = wpas.request(cmd)
+            if "FAIL" in res:
+                print("Failed to initiate DPP authentication")
+            break
+
+    if not dpp_found:
+        print("DPP carrier not seen in response - allow peer to initiate a new handover with different parameters")
+        client.close()
+        print("Returning from dpp_handover_client")
+        return
+
+    print("Remove peer")
+    client.close()
+    print("Done with handover")
+    global only_one
+    if only_one:
+        print("only_one -> stop loop")
+        global continue_loop
+        continue_loop = False
+
+    global no_wait
+    if no_wait:
+        print("Trying to exit..")
+        global terminate_now
+        terminate_now = True
+
+    print("Returning from dpp_handover_client")
+
+class HandoverServer(nfc.handover.HandoverServer):
+    def __init__(self, llc):
+        super(HandoverServer, self).__init__(llc)
+        self.sent_carrier = None
+        self.ho_server_processing = False
+        self.success = False
+        self.try_own = False
+
+    def process_handover_request_message(self, records):
+        self.ho_server_processing = True
+        clear_raw_mode()
+        print("\nHandoverServer - request received: " + str(records))
+
+        carrier = None
+        hs = ndef.HandoverSelectRecord('1.4')
+        sel = [hs]
+
+        found = False
+
+        for carrier in records:
+            if isinstance(carrier, ndef.HandoverRequestRecord):
+                continue
+            print("Remote carrier type: " + carrier.type)
+            if carrier.type == "application/vnd.wfa.dpp":
+                print("DPP carrier type match - add DPP carrier record")
+                if len(carrier.data) == 0 or carrier.data[0] != 0:
+                    print("URI Identifier Code 'None' not seen")
+                    continue
+                uri = carrier.data[1:].decode("utf-8")
+                print("Received DPP URI: " + uri)
+
+                data = wpas_get_nfc_uri(start_listen=False)
+                print("Own URI (pre-processing): %s" % data)
+
+                res = wpas_report_handover_req(uri)
+                if res is None or "FAIL" in res:
+                    print("DPP handover request processing failed")
+                    continue
+
+                found = True
+                self.received_carrier = carrier
+
+                wpas = wpas_connect()
+                if wpas is None:
+                    continue
+                global own_id
+                data = wpas.request("DPP_BOOTSTRAP_GET_URI %d" % own_id).rstrip()
+                if "FAIL" in data:
+                    continue
+                print("Own URI (post-processing): %s" % data)
+                uri = ndef.UriRecord(data)
+                print("Own bootstrapping NFC URI record: " + str(uri))
+
+                info = wpas.request("DPP_BOOTSTRAP_INFO %d" % own_id)
+                freq = None
+                for line in info.splitlines():
+                    if line.startswith("use_freq="):
+                        freq = int(line.split('=')[1])
+                if freq is None:
+                    print("No channel negotiated over NFC - use channel 1")
+                    freq = 2412
+                res = wpas.request("DPP_LISTEN %d" % freq)
+                if "OK" not in res:
+                    print("Failed to start DPP listen")
+                    break
+
+                carrier = ndef.Record('application/vnd.wfa.dpp', 'A', uri.data)
+                print("Own DPP carrier record: " + str(carrier))
+                hs.add_alternative_carrier('active', carrier.name)
+                sel = [hs, carrier]
+                break
+
+        summary("Sending handover select: " + str(sel))
+        if found:
+            self.success = True
+        else:
+            self.try_own = True
+        return sel
+
+def clear_raw_mode():
+    import sys, tty, termios
+    global prev_tcgetattr, in_raw_mode
+    if not in_raw_mode:
+        return
+    fd = sys.stdin.fileno()
+    termios.tcsetattr(fd, termios.TCSADRAIN, prev_tcgetattr)
+    in_raw_mode = False
+
+def getch():
+    import sys, tty, termios, select
+    global prev_tcgetattr, in_raw_mode
+    fd = sys.stdin.fileno()
+    prev_tcgetattr = termios.tcgetattr(fd)
+    ch = None
+    try:
+        tty.setraw(fd)
+        in_raw_mode = True
+        [i, o, e] = select.select([fd], [], [], 0.05)
+        if i:
+            ch = sys.stdin.read(1)
+    finally:
+        termios.tcsetattr(fd, termios.TCSADRAIN, prev_tcgetattr)
+        in_raw_mode = False
+    return ch
+
+def dpp_tag_read(tag):
+    success = False
+    for record in tag.ndef.records:
+        print(record)
+        print("record type " + record.type)
+        if record.type == "application/vnd.wfa.dpp":
+            summary("DPP HS tag - send to wpa_supplicant")
+            success = dpp_hs_tag_read(record)
+            break
+        if isinstance(record, ndef.UriRecord):
+            print("URI record: uri=" + record.uri)
+            print("URI record: iri=" + record.iri)
+            if record.iri.startswith("DPP:"):
+                print("DPP URI")
+                if not dpp_nfc_uri_process(record.iri):
+                    break
+                success = True
+            else:
+                print("Ignore unknown URI")
+            break
+
+    if success:
+        success_report("Tag read succeeded")
+
+    return success
+
+def rdwr_connected_write_tag(tag):
+    summary("Tag found - writing - " + str(tag))
+    if not tag.ndef.is_writeable:
+        print("Not a writable tag")
+        return
+    global dpp_tag_data
+    if tag.ndef.capacity < len(dpp_tag_data):
+        print("Not enough room for the message")
+        return
+    tag.ndef.records = dpp_tag_data
+    success_report("Tag write succeeded")
+    print("Done - remove tag")
+    global only_one
+    if only_one:
+        global continue_loop
+        continue_loop = False
+    global dpp_sel_wait_remove
+    return dpp_sel_wait_remove
+
+def write_nfc_uri(clf, wait_remove=True):
+    print("Write NFC URI record")
+    data = wpas_get_nfc_uri()
+    if data is None:
+        summary("Could not get NFC URI from wpa_supplicant")
+        return
+
+    global dpp_sel_wait_remove
+    dpp_sel_wait_remove = wait_remove
+    print("URI: %s" % data)
+    uri = ndef.UriRecord(data)
+    print(uri)
+
+    print("Touch an NFC tag")
+    global dpp_tag_data
+    dpp_tag_data = [uri]
+    clf.connect(rdwr={'on-connect': rdwr_connected_write_tag})
+
+def write_nfc_hs(clf, wait_remove=True):
+    print("Write NFC Handover Select record on a tag")
+    data = wpas_get_nfc_uri()
+    if data is None:
+        summary("Could not get NFC URI from wpa_supplicant")
+        return
+
+    global dpp_sel_wait_remove
+    dpp_sel_wait_remove = wait_remove
+    print("URI: %s" % data)
+    uri = ndef.UriRecord(data)
+    print(uri)
+    carrier = ndef.Record('application/vnd.wfa.dpp', 'A', uri.data)
+    hs = ndef.HandoverSelectRecord('1.4')
+    hs.add_alternative_carrier('active', carrier.name)
+    print(hs)
+    print(carrier)
+
+    print("Touch an NFC tag")
+    global dpp_tag_data
+    dpp_tag_data = [hs, carrier]
+    print(dpp_tag_data)
+    clf.connect(rdwr={'on-connect': rdwr_connected_write_tag})
+
+def rdwr_connected(tag):
+    global only_one, no_wait
+    summary("Tag connected: " + str(tag))
+
+    if tag.ndef:
+        print("NDEF tag: " + tag.type)
+        print(tag.ndef.records)
+        success = dpp_tag_read(tag)
+        if only_one and success:
+            global continue_loop
+            continue_loop = False
+    else:
+        summary("Not an NDEF tag - remove tag")
+        return True
+
+    return not no_wait
+
+def llcp_worker(llc):
+    global init_on_touch
+    if init_on_touch:
+        print("Starting handover client")
+        dpp_handover_client(llc)
+        print("Exiting llcp_worker thread (init_in_touch)")
+        return
+
+    global no_input
+    if no_input:
+        print("Wait for handover to complete")
+    else:
+        print("Wait for handover to complete - press 'i' to initiate")
+    global srv
+    global wait_connection
+    while not wait_connection and srv.sent_carrier is None:
+        if srv.try_own:
+            srv.try_own = False
+            print("Try to initiate another handover with own parameters")
+            dpp_handover_client(llc)
+            print("Exiting llcp_worker thread (retry with own parameters)")
+            return
+        if srv.ho_server_processing:
+            time.sleep(0.025)
+        elif no_input:
+            time.sleep(0.5)
+        else:
+            res = getch()
+            if res != 'i':
+                continue
+            clear_raw_mode()
+            print("Starting handover client")
+            dpp_handover_client(llc)
+            print("Exiting llcp_worker thread (manual init)")
+            return
+
+    clear_raw_mode()
+    print("\rExiting llcp_worker thread")
+
+def llcp_startup(llc):
+    print("Start LLCP server")
+    global srv
+    srv = HandoverServer(llc)
+    return llc
+
+def llcp_connected(llc):
+    print("P2P LLCP connected")
+    global wait_connection
+    wait_connection = False
+    global init_on_touch
+    if not init_on_touch:
+        global srv
+        srv.start()
+    if init_on_touch or not no_input:
+        threading.Thread(target=llcp_worker, args=(llc,)).start()
+    return True
+
+def llcp_release(llc):
+    print("LLCP release")
+    return True
+
+def terminate_loop():
+    global terminate_now
+    return terminate_now
+
+def main():
+    clf = nfc.ContactlessFrontend()
+
+    parser = argparse.ArgumentParser(description='nfcpy to wpa_supplicant integration for DPP NFC operations')
+    parser.add_argument('-d', const=logging.DEBUG, default=logging.INFO,
+                        action='store_const', dest='loglevel',
+                        help='verbose debug output')
+    parser.add_argument('-q', const=logging.WARNING, action='store_const',
+                        dest='loglevel', help='be quiet')
+    parser.add_argument('--only-one', '-1', action='store_true',
+                        help='run only one operation and exit')
+    parser.add_argument('--init-on-touch', '-I', action='store_true',
+                        help='initiate handover on touch')
+    parser.add_argument('--no-wait', action='store_true',
+                        help='do not wait for tag to be removed before exiting')
+    parser.add_argument('--ifname', '-i',
+                        help='network interface name')
+    parser.add_argument('--no-input', '-a', action='store_true',
+                        help='do not use stdout input to initiate handover')
+    parser.add_argument('--tag-read-only', '-t', action='store_true',
+                        help='tag read only (do not allow connection handover)')
+    parser.add_argument('--handover-only', action='store_true',
+                        help='connection handover only (do not allow tag read)')
+    parser.add_argument('--summary',
+                        help='summary file for writing status updates')
+    parser.add_argument('--success',
+                        help='success file for writing success update')
+    parser.add_argument('--device', default='usb', help='NFC device to open')
+    parser.add_argument('--chan', default='81/1', help='channel list')
+    parser.add_argument('command', choices=['write-nfc-uri',
+                                            'write-nfc-hs'],
+                        nargs='?')
+    args = parser.parse_args()
+    print(args)
+
+    global only_one
+    only_one = args.only_one
+
+    global no_wait
+    no_wait = args.no_wait
+
+    global chanlist
+    chanlist = args.chan
+
+    logging.basicConfig(level=args.loglevel)
+
+    global init_on_touch
+    init_on_touch = args.init_on_touch
+
+    if args.ifname:
+        global ifname
+        ifname = args.ifname
+        print("Selected ifname " + ifname)
+
+    if args.summary:
+        global summary_file
+        summary_file = args.summary
+
+    if args.success:
+        global success_file
+        success_file = args.success
+
+    if args.no_input:
+        global no_input
+        no_input = True
+
+    clf = nfc.ContactlessFrontend()
+    global wait_connection
+
+    try:
+        if not clf.open(args.device):
+            print("Could not open connection with an NFC device")
+            raise SystemExit
+
+        if args.command == "write-nfc-uri":
+            write_nfc_uri(clf, wait_remove=not args.no_wait)
+            raise SystemExit
+
+        if args.command == "write-nfc-hs":
+            write_nfc_hs(clf, wait_remove=not args.no_wait)
+            raise SystemExit
+
+        global continue_loop
+        while continue_loop:
+            clear_raw_mode()
+            print("\rWaiting for a tag or peer to be touched")
+            wait_connection = True
+            try:
+                if args.tag_read_only:
+                    if not clf.connect(rdwr={'on-connect': rdwr_connected}):
+                        break
+                elif args.handover_only:
+                    if not clf.connect(llcp={'on-startup': llcp_startup,
+                                             'on-connect': llcp_connected,
+                                             'on-release': llcp_release},
+                                       terminate=terminate_loop):
+                        break
+                else:
+                    if not clf.connect(rdwr={'on-connect': rdwr_connected},
+                                       llcp={'on-startup': llcp_startup,
+                                             'on-connect': llcp_connected,
+                                             'on-release': llcp_release},
+                                       terminate=terminate_loop):
+                        break
+            except Exception as e:
+                print("clf.connect failed: " + str(e))
+                break
+
+            global srv
+            if only_one and srv and srv.success:
+                raise SystemExit
+
+    except KeyboardInterrupt:
+        raise SystemExit
+    finally:
+        clf.close()
+
+    raise SystemExit
+
+if __name__ == '__main__':
+    main()
diff --git a/wpa_supplicant/examples/p2p/p2p_connect.py b/wpa_supplicant/examples/p2p/p2p_connect.py
index 6e3d94e..2f62e9c 100644
--- a/wpa_supplicant/examples/p2p/p2p_connect.py
+++ b/wpa_supplicant/examples/p2p/p2p_connect.py
@@ -108,7 +108,7 @@
 		self.path = None
 		try:
 			self.path = self.wpas.GetInterface(ifname)
-		except:
+		except dbus.DBusException as exc:
 			if not str(exc).startswith(
 				self.wpas_dbus_interface + \
 				".InterfaceUnknown:"):
diff --git a/wpa_supplicant/hidl/1.3/p2p_iface.cpp b/wpa_supplicant/hidl/1.3/p2p_iface.cpp
index bd893a3..ffa9b6a 100644
--- a/wpa_supplicant/hidl/1.3/p2p_iface.cpp
+++ b/wpa_supplicant/hidl/1.3/p2p_iface.cpp
@@ -100,7 +100,7 @@
 	struct hostapd_hw_modes *mode;
 	int count, i;
 
-	mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, band);
+	mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, band, 0);
 	if (mode == NULL) {
 		/* No channels supported in this band. */
 		return;
diff --git a/wpa_supplicant/ibss_rsn.c b/wpa_supplicant/ibss_rsn.c
index 36c0aff..02e6390 100644
--- a/wpa_supplicant/ibss_rsn.c
+++ b/wpa_supplicant/ibss_rsn.c
@@ -64,10 +64,16 @@
 {
 	struct ibss_rsn_peer *peer = ctx;
 	struct wpa_supplicant *wpa_s = peer->ibss_rsn->wpa_s;
+	int encrypt = peer->authentication_status & IBSS_RSN_REPORTED_PTK;
 
-	wpa_printf(MSG_DEBUG, "SUPP: %s(dest=" MACSTR " proto=0x%04x "
-		   "len=%lu)",
-		   __func__, MAC2STR(dest), proto, (unsigned long) len);
+	wpa_printf(MSG_DEBUG, "SUPP: %s(dest=" MACSTR
+		   " proto=0x%04x len=%lu no_encrypt=%d)",
+		   __func__, MAC2STR(dest), proto, (unsigned long) len,
+		   !encrypt);
+
+	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT)
+		return wpa_drv_tx_control_port(wpa_s, dest, proto, buf, len,
+					       !encrypt);
 
 	if (wpa_s->l2)
 		return l2_packet_send(wpa_s->l2, dest, proto, buf, len);
@@ -140,7 +146,7 @@
 static int supp_set_key(void *ctx, enum wpa_alg alg,
 			const u8 *addr, int key_idx, 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 ibss_rsn_peer *peer = ctx;
 
@@ -167,7 +173,7 @@
 	if (is_broadcast_ether_addr(addr))
 		addr = peer->addr;
 	return wpa_drv_set_key(peer->ibss_rsn->wpa_s, alg, addr, key_idx,
-			       set_tx, seq, seq_len, key, key_len);
+			       set_tx, seq, seq_len, key, key_len, key_flag);
 }
 
 
@@ -194,7 +200,13 @@
 }
 
 
-static void supp_deauthenticate(void * ctx, u16 reason_code)
+static void supp_deauthenticate(void *ctx, u16 reason_code)
+{
+	wpa_printf(MSG_DEBUG, "SUPP: %s (TODO)", __func__);
+}
+
+
+static void supp_reconnect(void *ctx)
 {
 	wpa_printf(MSG_DEBUG, "SUPP: %s (TODO)", __func__);
 }
@@ -219,6 +231,7 @@
 	ctx->mlme_setprotection = supp_mlme_setprotection;
 	ctx->cancel_auth_timeout = supp_cancel_auth_timeout;
 	ctx->deauthenticate = supp_deauthenticate;
+	ctx->reconnect = supp_reconnect;
 	peer->supp = wpa_sm_init(ctx);
 	if (peer->supp == NULL) {
 		wpa_printf(MSG_DEBUG, "SUPP: wpa_sm_init() failed");
@@ -287,6 +300,10 @@
 		   "encrypt=%d)",
 		   __func__, MAC2STR(addr), (unsigned long) data_len, encrypt);
 
+	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT)
+		return wpa_drv_tx_control_port(wpa_s, addr, ETH_P_EAPOL,
+					       data, data_len, !encrypt);
+
 	if (wpa_s->l2)
 		return l2_packet_send(wpa_s->l2, addr, ETH_P_EAPOL, data,
 				      data_len);
@@ -296,7 +313,8 @@
 
 
 static int auth_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)
 {
 	struct ibss_rsn *ibss_rsn = ctx;
 	u8 seq[6];
@@ -335,7 +353,7 @@
 	}
 
 	return wpa_drv_set_key(ibss_rsn->wpa_s, alg, addr, idx,
-			       1, seq, 6, key, key_len);
+			       1, seq, 6, key, key_len, key_flag);
 }
 
 
@@ -487,9 +505,6 @@
 	const size_t auth_length = IEEE80211_HDRLEN + sizeof(auth.u.auth);
 	struct wpa_supplicant *wpa_s = ibss_rsn->wpa_s;
 
-	if (wpa_s->driver->send_frame == NULL)
-		return -1;
-
 	os_memset(&auth, 0, sizeof(auth));
 
 	auth.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
@@ -505,8 +520,7 @@
 	wpa_printf(MSG_DEBUG, "RSN: IBSS TX Auth frame (SEQ %d) to " MACSTR,
 		   seq, MAC2STR(da));
 
-	return wpa_s->driver->send_frame(wpa_s->drv_priv, (u8 *) &auth,
-					 auth_length, 0);
+	return wpa_drv_send_mlme(wpa_s, (u8 *) &auth, auth_length, 0, 0, 0);
 }
 
 
@@ -852,7 +866,7 @@
 		wpa_printf(MSG_DEBUG, "RSN: Clear pairwise key for peer "
 			   MACSTR, MAC2STR(addr));
 		wpa_drv_set_key(ibss_rsn->wpa_s, WPA_ALG_NONE, addr, 0, 0,
-				NULL, 0, NULL, 0);
+				NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE);
 	}
 
 	if (peer &&
diff --git a/wpa_supplicant/mesh_mpm.c b/wpa_supplicant/mesh_mpm.c
index 308366f..4925b5c 100644
--- a/wpa_supplicant/mesh_mpm.c
+++ b/wpa_supplicant/mesh_mpm.c
@@ -233,12 +233,10 @@
 		  2 + 24 + /* peering management */
 		  2 + 96 + 32 + 32 + /* AMPE (96 + max GTKlen + max IGTKlen) */
 		  2 + 16;  /* MIC */
-#ifdef CONFIG_IEEE80211N
 	if (type != PLINK_CLOSE && wpa_s->mesh_ht_enabled) {
 		buf_len += 2 + 26 + /* HT capabilities */
 			   2 + 22;  /* HT operation */
 	}
-#endif /* CONFIG_IEEE80211N */
 #ifdef CONFIG_IEEE80211AC
 	if (type != PLINK_CLOSE && wpa_s->mesh_vht_enabled) {
 		buf_len += 2 + 12 + /* VHT Capabilities */
@@ -354,7 +352,6 @@
 				   wpabuf_put(buf, PMKID_LEN));
 	}
 
-#ifdef CONFIG_IEEE80211N
 	if (type != PLINK_CLOSE && wpa_s->mesh_ht_enabled) {
 		u8 ht_capa_oper[2 + 26 + 2 + 22];
 
@@ -362,7 +359,6 @@
 		pos = hostapd_eid_ht_operation(bss, pos);
 		wpabuf_put_data(buf, ht_capa_oper, pos - ht_capa_oper);
 	}
-#endif /* CONFIG_IEEE80211N */
 #ifdef CONFIG_IEEE80211AC
 	if (type != PLINK_CLOSE && wpa_s->mesh_vht_enabled) {
 		u8 vht_capa_oper[2 + 12 + 2 + 5];
@@ -696,9 +692,7 @@
 	struct mesh_conf *conf = wpa_s->ifmsh->mconf;
 	struct hostapd_data *data = wpa_s->ifmsh->bss[0];
 	struct sta_info *sta;
-#ifdef CONFIG_IEEE80211N
 	struct ieee80211_ht_operation *oper;
-#endif /* CONFIG_IEEE80211N */
 	int ret;
 
 	if (elems->mesh_config_len >= 7 &&
@@ -710,11 +704,12 @@
 	}
 
 	sta = ap_get_sta(data, addr);
-	if (!sta) {
-		sta = ap_sta_add(data, addr);
-		if (!sta)
-			return NULL;
-	}
+	if (sta)
+		return NULL;
+
+	sta = ap_sta_add(data, addr);
+	if (!sta)
+		return NULL;
 
 	/* Set WMM by default since Mesh STAs are QoS STAs */
 	sta->flags |= WLAN_STA_WMM;
@@ -728,7 +723,6 @@
 	if (!sta->my_lid)
 		mesh_mpm_init_link(wpa_s, sta);
 
-#ifdef CONFIG_IEEE80211N
 	copy_sta_ht_capab(data, sta, elems->ht_capabilities);
 
 	oper = (struct ieee80211_ht_operation *) elems->ht_operation;
@@ -742,7 +736,6 @@
 	}
 
 	update_ht_state(data, sta);
-#endif /* CONFIG_IEEE80211N */
 
 #ifdef CONFIG_IEEE80211AC
 	copy_sta_vht_capab(data, sta, elems->vht_capabilities);
@@ -876,7 +869,8 @@
 		wpa_hexdump_key(MSG_DEBUG, "mesh: MTK", sta->mtk, sta->mtk_len);
 		wpa_drv_set_key(wpa_s, wpa_cipher_to_alg(conf->pairwise_cipher),
 				sta->addr, 0, 0, seq, sizeof(seq),
-				sta->mtk, sta->mtk_len);
+				sta->mtk, sta->mtk_len,
+				KEY_FLAG_PAIRWISE_RX_TX);
 
 		wpa_hexdump_key(MSG_DEBUG, "mesh: RX MGTK Key RSC",
 				sta->mgtk_rsc, sizeof(sta->mgtk_rsc));
@@ -885,7 +879,8 @@
 		wpa_drv_set_key(wpa_s, wpa_cipher_to_alg(conf->group_cipher),
 				sta->addr, sta->mgtk_key_id, 0,
 				sta->mgtk_rsc, sizeof(sta->mgtk_rsc),
-				sta->mgtk, sta->mgtk_len);
+				sta->mgtk, sta->mgtk_len,
+				KEY_FLAG_GROUP_RX);
 
 		if (sta->igtk_len) {
 			wpa_hexdump_key(MSG_DEBUG, "mesh: RX IGTK Key RSC",
@@ -897,7 +892,8 @@
 				wpa_cipher_to_alg(conf->mgmt_group_cipher),
 				sta->addr, sta->igtk_key_id, 0,
 				sta->igtk_rsc, sizeof(sta->igtk_rsc),
-				sta->igtk, sta->igtk_len);
+				sta->igtk, sta->igtk_len,
+				KEY_FLAG_GROUP_RX);
 		}
 	}
 
diff --git a/wpa_supplicant/mesh_rsn.c b/wpa_supplicant/mesh_rsn.c
index e730b63..f19bfbf 100644
--- a/wpa_supplicant/mesh_rsn.c
+++ b/wpa_supplicant/mesh_rsn.c
@@ -100,7 +100,8 @@
 
 
 static int auth_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)
 {
 	struct mesh_rsn *mesh_rsn = ctx;
 	u8 seq[6];
@@ -118,7 +119,7 @@
 	wpa_hexdump_key(MSG_DEBUG, "AUTH: set_key - key", key, key_len);
 
 	return wpa_drv_set_key(mesh_rsn->wpa_s, alg, addr, idx,
-			       1, seq, 6, key, key_len);
+			       1, seq, 6, key, key_len, key_flag);
 }
 
 
@@ -196,7 +197,8 @@
 		wpa_drv_set_key(rsn->wpa_s,
 				wpa_cipher_to_alg(rsn->mgmt_group_cipher), NULL,
 				rsn->igtk_key_id, 1,
-				seq, sizeof(seq), rsn->igtk, rsn->igtk_len);
+				seq, sizeof(seq), rsn->igtk, rsn->igtk_len,
+				KEY_FLAG_GROUP_TX_DEFAULT);
 	}
 
 	/* group privacy / data frames */
@@ -204,7 +206,7 @@
 			rsn->mgtk, rsn->mgtk_len);
 	wpa_drv_set_key(rsn->wpa_s, wpa_cipher_to_alg(rsn->group_cipher), NULL,
 			rsn->mgtk_key_id, 1, seq, sizeof(seq),
-			rsn->mgtk, rsn->mgtk_len);
+			rsn->mgtk, rsn->mgtk_len, KEY_FLAG_GROUP_TX_DEFAULT);
 
 	return 0;
 }
diff --git a/wpa_supplicant/offchannel.c b/wpa_supplicant/offchannel.c
index b74be7d..e40cf5b 100644
--- a/wpa_supplicant/offchannel.c
+++ b/wpa_supplicant/offchannel.c
@@ -226,10 +226,10 @@
 	}
 
 #ifdef CONFIG_P2P
-	if (wpa_s->p2p_long_listen > 0) {
+	if (wpa_s->global->p2p_long_listen > 0) {
 		/* Continue the listen */
 		wpa_printf(MSG_DEBUG, "P2P: Continuing long Listen state");
-		wpas_p2p_listen_start(wpa_s, wpa_s->p2p_long_listen);
+		wpas_p2p_listen_start(wpa_s, wpa_s->global->p2p_long_listen);
 	}
 #endif /* CONFIG_P2P */
 }
@@ -246,7 +246,7 @@
  * @buf: Frame to transmit starting from the Category field
  * @len: Length of @buf in bytes
  * @wait_time: Wait time for response in milliseconds
- * @tx_cb: Callback function for indicating TX status or %NULL for now callback
+ * @tx_cb: Callback function for indicating TX status or %NULL for no callback
  * @no_cck: Whether CCK rates are to be disallowed for TX rate selection
  * Returns: 0 on success or -1 on failure
  *
diff --git a/wpa_supplicant/op_classes.c b/wpa_supplicant/op_classes.c
index b15ac9e..983801f 100644
--- a/wpa_supplicant/op_classes.c
+++ b/wpa_supplicant/op_classes.c
@@ -14,6 +14,7 @@
 #include "utils/common.h"
 #include "common/ieee802_11_common.h"
 #include "wpa_supplicant_i.h"
+#include "bss.h"
 
 
 static enum chan_allowed allow_channel(struct hostapd_hw_modes *mode,
@@ -228,7 +229,8 @@
 	int freq2 = 0;
 	int freq5 = 0;
 
-	mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, op_class->mode);
+	mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, op_class->mode,
+			is_6ghz_op_class(op_class->op_class));
 	if (!mode)
 		return 0;
 
@@ -355,9 +357,25 @@
 }
 
 
+static int wpas_sta_secondary_channel_offset(struct wpa_bss *bss, u8 *current,
+					     u8 *channel)
+{
+
+	u8 *ies, phy_type;
+	size_t ies_len;
+
+	if (!bss)
+		return -1;
+	ies = (u8 *) (bss + 1);
+	ies_len = bss->ie_len ? bss->ie_len : bss->beacon_ie_len;
+	return wpas_get_op_chan_phy(bss->freq, ies, ies_len, current,
+				    channel, &phy_type);
+}
+
+
 size_t wpas_supp_op_class_ie(struct wpa_supplicant *wpa_s,
 			     struct wpa_ssid *ssid,
-			     int freq, u8 *pos, size_t len)
+			     struct wpa_bss *bss, u8 *pos, size_t len)
 {
 	struct wpabuf *buf;
 	u8 op, current, chan;
@@ -365,11 +383,13 @@
 	size_t res;
 
 	/*
-	 * Assume 20 MHz channel for now.
-	 * TODO: Use the secondary channel and VHT channel width that will be
-	 * used after association.
+	 * Determine the current operating class correct mode based on
+	 * advertised BSS capabilities, if available. Fall back to a less
+	 * accurate guess based on frequency if the needed IEs are not available
+	 * or used.
 	 */
-	if (ieee80211_freq_to_channel_ext(freq, 0, CHANWIDTH_USE_HT,
+	if (wpas_sta_secondary_channel_offset(bss, &current, &chan) < 0 &&
+	    ieee80211_freq_to_channel_ext(bss->freq, 0, CHANWIDTH_USE_HT,
 					  &current, &chan) == NUM_HOSTAPD_MODES)
 		return 0;
 
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index a3c4574..2c8754b 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -1912,7 +1912,7 @@
 		return -1;
 
 	hwmode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
-			  HOSTAPD_MODE_IEEE80211AD);
+			  HOSTAPD_MODE_IEEE80211AD, 0);
 	if (!hwmode) {
 		wpa_printf(MSG_ERROR,
 			   "Unsupported AP mode: HOSTAPD_MODE_IEEE80211AD");
@@ -2422,7 +2422,7 @@
 		wpas_start_wps_enrollee(group_wpa_s, res);
 	}
 
-	wpa_s->p2p_long_listen = 0;
+	wpa_s->global->p2p_long_listen = 0;
 	eloop_cancel_timeout(wpas_p2p_long_listen_timeout, wpa_s, NULL);
 
 	eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s, NULL);
@@ -2701,7 +2701,7 @@
 {
 	struct wpa_supplicant *wpa_s = ctx;
 	return wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1,
-				 freq);
+				 freq, 0);
 }
 
 
@@ -3735,7 +3735,8 @@
 		if (o->p2p == NO_P2P_SUPP)
 			continue;
 
-		mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, o->mode);
+		mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, o->mode,
+				is_6ghz_op_class(o->op_class));
 		if (mode == NULL)
 			continue;
 		if (mode->mode == HOSTAPD_MODE_IEEE80211G)
@@ -3745,23 +3746,32 @@
 			res = wpas_p2p_verify_channel(wpa_s, mode, ch, o->bw);
 			if (res == ALLOWED) {
 				if (reg == NULL) {
+					if (cla == P2P_MAX_REG_CLASSES)
+						continue;
 					wpa_printf(MSG_DEBUG, "P2P: Add operating class %u",
 						   o->op_class);
 					reg = &chan->reg_class[cla];
 					cla++;
 					reg->reg_class = o->op_class;
 				}
+				if (reg->channels == P2P_MAX_REG_CLASS_CHANNELS)
+					continue;
 				reg->channel[reg->channels] = ch;
 				reg->channels++;
 			} else if (res == NO_IR &&
 				   wpa_s->conf->p2p_add_cli_chan) {
 				if (cli_reg == NULL) {
+					if (cli_cla == P2P_MAX_REG_CLASSES)
+						continue;
 					wpa_printf(MSG_DEBUG, "P2P: Add operating class %u (client only)",
 						   o->op_class);
 					cli_reg = &cli_chan->reg_class[cli_cla];
 					cli_cla++;
 					cli_reg->reg_class = o->op_class;
 				}
+				if (cli_reg->channels ==
+				    P2P_MAX_REG_CLASS_CHANNELS)
+					continue;
 				cli_reg->channel[cli_reg->channels] = ch;
 				cli_reg->channels++;
 			}
@@ -4758,7 +4768,7 @@
 	eloop_cancel_timeout(wpas_p2p_psk_failure_removal, wpa_s, NULL);
 	eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s, NULL);
 	eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL);
-	wpa_s->p2p_long_listen = 0;
+	wpa_s->global->p2p_long_listen = 0;
 	eloop_cancel_timeout(wpas_p2p_long_listen_timeout, wpa_s, NULL);
 	eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL);
 	wpas_p2p_remove_pending_group_interface(wpa_s);
@@ -5643,7 +5653,7 @@
 		go_intent = wpa_s->conf->p2p_go_intent;
 
 	if (!auth)
-		wpa_s->p2p_long_listen = 0;
+		wpa_s->global->p2p_long_listen = 0;
 
 	wpa_s->p2p_wps_method = wps_method;
 	wpa_s->p2p_persistent_group = !!persistent_group;
@@ -5813,19 +5823,20 @@
 {
 	wpa_printf(MSG_DEBUG, "P2P: Cancel remain-on-channel callback "
 		   "(p2p_long_listen=%d ms pending_action_tx=%p)",
-		   wpa_s->p2p_long_listen, offchannel_pending_action_tx(wpa_s));
+		   wpa_s->global->p2p_long_listen,
+		   offchannel_pending_action_tx(wpa_s));
 	wpas_p2p_listen_work_done(wpa_s);
 	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
 		return;
-	if (wpa_s->p2p_long_listen > 0)
-		wpa_s->p2p_long_listen -= wpa_s->max_remain_on_chan;
+	if (wpa_s->global->p2p_long_listen > 0)
+		wpa_s->global->p2p_long_listen -= wpa_s->max_remain_on_chan;
 	if (p2p_listen_end(wpa_s->global->p2p, freq) > 0)
 		return; /* P2P module started a new operation */
 	if (offchannel_pending_action_tx(wpa_s))
 		return;
-	if (wpa_s->p2p_long_listen > 0) {
+	if (wpa_s->global->p2p_long_listen > 0) {
 		wpa_printf(MSG_DEBUG, "P2P: Continuing long Listen state");
-		wpas_p2p_listen_start(wpa_s, wpa_s->p2p_long_listen);
+		wpas_p2p_listen_start(wpa_s, wpa_s->global->p2p_long_listen);
 	} else {
 		/*
 		 * When listen duration is over, stop listen & update p2p_state
@@ -6298,7 +6309,7 @@
 			cand = wpa_s->p2p_group_common_freqs[i];
 			mode = ieee80211_freq_to_chan(cand, &chan);
 			hwmode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
-					  mode);
+					  mode, is_6ghz_freq(cand));
 			if (!hwmode ||
 			    wpas_p2p_verify_channel(wpa_s, hwmode, chan,
 						    BW80) != ALLOWED)
@@ -6325,7 +6336,7 @@
 			cand = wpa_s->p2p_group_common_freqs[i];
 			mode = ieee80211_freq_to_chan(cand, &chan);
 			hwmode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
-					  mode);
+					  mode, is_6ghz_freq(cand));
 			if (!wpas_same_band(wpa_s->current_ssid->frequency,
 					    cand) ||
 			    !hwmode ||
@@ -6960,7 +6971,7 @@
 		  u8 seek_cnt, const char **seek_string, int freq)
 {
 	wpas_p2p_clear_pending_action_tx(wpa_s);
-	wpa_s->p2p_long_listen = 0;
+	wpa_s->global->p2p_long_listen = 0;
 
 	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL ||
 	    wpa_s->p2p_in_provisioning) {
@@ -7005,7 +7016,7 @@
 static void wpas_p2p_stop_find_oper(struct wpa_supplicant *wpa_s)
 {
 	wpas_p2p_clear_pending_action_tx(wpa_s);
-	wpa_s->p2p_long_listen = 0;
+	wpa_s->global->p2p_long_listen = 0;
 	eloop_cancel_timeout(wpas_p2p_long_listen_timeout, wpa_s, NULL);
 	eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL);
 
@@ -7031,7 +7042,7 @@
 static void wpas_p2p_long_listen_timeout(void *eloop_ctx, void *timeout_ctx)
 {
 	struct wpa_supplicant *wpa_s = eloop_ctx;
-	wpa_s->p2p_long_listen = 0;
+	wpa_s->global->p2p_long_listen = 0;
 }
 
 
@@ -7060,7 +7071,7 @@
 		timeout = 3600;
 	}
 	eloop_cancel_timeout(wpas_p2p_long_listen_timeout, wpa_s, NULL);
-	wpa_s->p2p_long_listen = 0;
+	wpa_s->global->p2p_long_listen = 0;
 
 	/*
 	 * Stop previous find/listen operation to avoid trying to request a new
@@ -7072,7 +7083,7 @@
 
 	res = wpas_p2p_listen_start(wpa_s, timeout * 1000);
 	if (res == 0 && timeout * 1000 > wpa_s->max_remain_on_chan) {
-		wpa_s->p2p_long_listen = timeout * 1000;
+		wpa_s->global->p2p_long_listen = timeout * 1000;
 		eloop_register_timeout(timeout, 0,
 				       wpas_p2p_long_listen_timeout,
 				       wpa_s, NULL);
@@ -7179,7 +7190,7 @@
 
 int wpas_p2p_reject(struct wpa_supplicant *wpa_s, const u8 *addr)
 {
-	wpa_s->p2p_long_listen = 0;
+	wpa_s->global->p2p_long_listen = 0;
 
 	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
 		return -1;
diff --git a/wpa_supplicant/preauth_test.c b/wpa_supplicant/preauth_test.c
index 3f2da34..4a8f4ff 100644
--- a/wpa_supplicant/preauth_test.c
+++ b/wpa_supplicant/preauth_test.c
@@ -41,6 +41,12 @@
 }
 
 
+static void _wpa_supplicant_reconnect(void *wpa_s)
+{
+	wpa_supplicant_reconnect(wpa_s);
+}
+
+
 static u8 * wpa_alloc_eapol(const struct wpa_supplicant *wpa_s, u8 type,
 			    const void *data, u16 data_len,
 			    size_t *msg_len, void **data_pos)
@@ -127,7 +133,8 @@
 static int wpa_supplicant_set_key(void *wpa_s, enum wpa_alg alg,
 				  const u8 *addr, int key_idx, 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)
 {
 	printf("%s - not implemented\n", __func__);
 	return -1;
@@ -146,7 +153,8 @@
 static int wpa_supplicant_add_pmkid(void *wpa_s, void *network_ctx,
 				    const u8 *bssid, const u8 *pmkid,
 				    const u8 *fils_cache_id,
-				    const u8 *pmk, size_t pmk_len)
+				    const u8 *pmk, size_t pmk_len,
+				    u32 pmk_lifetime, u8 pmk_reauth_threshold)
 {
 	printf("%s - not implemented\n", __func__);
 	return -1;
@@ -244,6 +252,7 @@
 	ctx->set_config_blob = wpa_supplicant_set_config_blob;
 	ctx->get_config_blob = wpa_supplicant_get_config_blob;
 	ctx->mlme_setprotection = wpa_supplicant_mlme_setprotection;
+	ctx->reconnect = _wpa_supplicant_reconnect;
 
 	wpa_s->wpa = wpa_sm_init(ctx);
 	assert(wpa_s->wpa != NULL);
diff --git a/wpa_supplicant/rrm.c b/wpa_supplicant/rrm.c
index 7930e01..afc1172 100644
--- a/wpa_supplicant/rrm.c
+++ b/wpa_supplicant/rrm.c
@@ -609,7 +609,8 @@
 		pos++;
 		left--;
 
-		mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, op->mode);
+		mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, op->mode,
+				is_6ghz_op_class(op->op_class));
 		if (!mode)
 			continue;
 
@@ -661,7 +662,8 @@
 		return NULL;
 	}
 
-	mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, op->mode);
+	mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, op->mode,
+			is_6ghz_op_class(op->op_class));
 	if (!mode)
 		return NULL;
 
@@ -693,8 +695,8 @@
 }
 
 
-static int wpas_get_op_chan_phy(int freq, const u8 *ies, size_t ies_len,
-				u8 *op_class, u8 *chan, u8 *phy_type)
+int wpas_get_op_chan_phy(int freq, const u8 *ies, size_t ies_len,
+			 u8 *op_class, u8 *chan, u8 *phy_type)
 {
 	const u8 *ie;
 	int sec_chan = 0, vht = 0;
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index 4d158a9..b475730 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -668,13 +668,14 @@
 
 static void wpa_setband_scan_freqs_list(struct wpa_supplicant *wpa_s,
 					enum hostapd_hw_mode band,
-					struct wpa_driver_scan_params *params)
+					struct wpa_driver_scan_params *params,
+					int is_6ghz)
 {
 	/* Include only supported channels for the specified band */
 	struct hostapd_hw_modes *mode;
 	int count, i;
 
-	mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, band);
+	mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, band, is_6ghz);
 	if (mode == NULL) {
 		/* No channels supported in this band - use empty list */
 		params->freqs = os_zalloc(sizeof(int));
@@ -701,10 +702,10 @@
 		return; /* already using a limited channel set */
 	if (wpa_s->setband == WPA_SETBAND_5G)
 		wpa_setband_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A,
-					    params);
+					    params, 0);
 	else if (wpa_s->setband == WPA_SETBAND_2G)
 		wpa_setband_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G,
-					    params);
+					    params, 0);
 }
 
 
@@ -1108,7 +1109,9 @@
 		     tssid = tssid->next) {
 			if (wpas_network_disabled(wpa_s, tssid))
 				continue;
-			if ((params.freqs || !freqs_set) && tssid->scan_freq) {
+			if (((params.freqs || !freqs_set) &&
+			     tssid->scan_freq) &&
+			    int_array_len(params.freqs) < 100) {
 				int_array_concat(&params.freqs,
 						 tssid->scan_freq);
 			} else {
@@ -1250,7 +1253,8 @@
 
 		params.bssid = wpa_s->next_scan_bssid;
 		bss = wpa_bss_get_bssid_latest(wpa_s, params.bssid);
-		if (bss && bss->ssid_len && params.num_ssids == 1 &&
+		if (!wpa_s->next_scan_bssid_wildcard_ssid &&
+		    bss && bss->ssid_len && params.num_ssids == 1 &&
 		    params.ssids[0].ssid_len == 0) {
 			params.ssids[0].ssid = bss->ssid;
 			params.ssids[0].ssid_len = bss->ssid_len;
@@ -1327,6 +1331,7 @@
 #ifdef CONFIG_INTERWORKING
 		wpa_s->interworking_fast_assoc_tried = 0;
 #endif /* CONFIG_INTERWORKING */
+		wpa_s->next_scan_bssid_wildcard_ssid = 0;
 		if (params.bssid)
 			os_memset(wpa_s->next_scan_bssid, 0, ETH_ALEN);
 	}
@@ -1956,20 +1961,6 @@
 }
 
 
-/*
- * Channels with a great SNR can operate at full rate. What is a great SNR?
- * This doc https://supportforums.cisco.com/docs/DOC-12954 says, "the general
- * rule of thumb is that any SNR above 20 is good." This one
- * http://www.cisco.com/en/US/tech/tk722/tk809/technologies_q_and_a_item09186a00805e9a96.shtml#qa23
- * recommends 25 as a minimum SNR for 54 Mbps data rate. The estimates used in
- * scan_est_throughput() allow even smaller SNR values for the maximum rates
- * (21 for 54 Mbps, 22 for VHT80 MCS9, 24 for HT40 and HT20 MCS7). Use 25 as a
- * somewhat conservative value here.
- */
-#define GREAT_SNR 25
-
-#define IS_5GHZ(n) (n > 4000)
-
 /* Compare function for sorting scan results. Return >0 if @b is considered
  * better. */
 static int wpa_scan_result_compar(const void *a, const void *b)
@@ -2178,14 +2169,6 @@
 }
 
 
-/*
- * Noise floor values to use when we have signal strength
- * measurements, but no noise floor measurements. These values were
- * measured in an office environment with many APs.
- */
-#define DEFAULT_NOISE_FLOOR_2GHZ (-89)
-#define DEFAULT_NOISE_FLOOR_5GHZ (-92)
-
 void scan_snr(struct wpa_scan_res *res)
 {
 	if (res->flags & WPA_SCAN_NOISE_INVALID) {
@@ -2204,86 +2187,83 @@
 }
 
 
-static unsigned int max_ht20_rate(int snr)
+static unsigned int interpolate_rate(int snr, int snr0, int snr1,
+				     int rate0, int rate1)
 {
-	if (snr < 6)
-		return 6500; /* HT20 MCS0 */
-	if (snr < 8)
-		return 13000; /* HT20 MCS1 */
-	if (snr < 13)
-		return 19500; /* HT20 MCS2 */
-	if (snr < 17)
-		return 26000; /* HT20 MCS3 */
-	if (snr < 20)
-		return 39000; /* HT20 MCS4 */
-	if (snr < 23)
-		return 52000; /* HT20 MCS5 */
-	if (snr < 24)
-		return 58500; /* HT20 MCS6 */
-	return 65000; /* HT20 MCS7 */
+	return rate0 + (snr - snr0) * (rate1 - rate0) / (snr1 - snr0);
 }
 
 
-static unsigned int max_ht40_rate(int snr)
+#define INTERPOLATE_RATE(snr0, snr1, rate0, rate1) \
+	if (snr < (snr1)) \
+		return interpolate_rate(snr, (snr0), (snr1), (rate0), (rate1))
+
+static unsigned int max_ht20_rate(int snr, int vht)
 {
-	if (snr < 3)
-		return 13500; /* HT40 MCS0 */
-	if (snr < 6)
-		return 27000; /* HT40 MCS1 */
-	if (snr < 10)
-		return 40500; /* HT40 MCS2 */
-	if (snr < 15)
-		return 54000; /* HT40 MCS3 */
-	if (snr < 17)
-		return 81000; /* HT40 MCS4 */
-	if (snr < 22)
-		return 108000; /* HT40 MCS5 */
-	if (snr < 24)
-		return 121500; /* HT40 MCS6 */
-	return 135000; /* HT40 MCS7 */
+	if (snr < 0)
+		return 0;
+	INTERPOLATE_RATE(0, 2, 0, 6500); /* HT20 MCS0 */
+	INTERPOLATE_RATE(2, 5, 6500, 13000); /* HT20 MCS1 */
+	INTERPOLATE_RATE(5, 9, 13000, 19500); /* HT20 MCS2 */
+	INTERPOLATE_RATE(9, 11, 19500, 26000); /* HT20 MCS3 */
+	INTERPOLATE_RATE(11, 15, 26000, 39000); /* HT20 MCS4 */
+	INTERPOLATE_RATE(15, 18, 39000, 52000); /* HT20 MCS5 */
+	INTERPOLATE_RATE(18, 20, 52000, 58500); /* HT20 MCS6 */
+	INTERPOLATE_RATE(20, 25, 58500, 65000); /* HT20 MCS7 */
+	if (!vht)
+		return 65000;
+	INTERPOLATE_RATE(25, 29, 65000, 78000); /* VHT20 MCS8 */
+	return 78000;
+}
+
+
+static unsigned int max_ht40_rate(int snr, int vht)
+{
+	if (snr < 0)
+		return 0;
+	INTERPOLATE_RATE(0, 5, 0, 13500); /* HT40 MCS0 */
+	INTERPOLATE_RATE(5, 8, 13500, 27000); /* HT40 MCS1 */
+	INTERPOLATE_RATE(8, 12, 27000, 40500); /* HT40 MCS2 */
+	INTERPOLATE_RATE(12, 14, 40500, 54000); /* HT40 MCS3 */
+	INTERPOLATE_RATE(14, 18, 54000, 81000); /* HT40 MCS4 */
+	INTERPOLATE_RATE(18, 21, 81000, 108000); /* HT40 MCS5 */
+	INTERPOLATE_RATE(21, 23, 108000, 121500); /* HT40 MCS6 */
+	INTERPOLATE_RATE(23, 28, 121500, 135000); /* HT40 MCS7 */
+	if (!vht)
+		return 135000;
+	INTERPOLATE_RATE(28, 32, 135000, 162000); /* VHT40 MCS8 */
+	INTERPOLATE_RATE(32, 34, 162000, 180000); /* VHT40 MCS9 */
+	return 180000;
 }
 
 
 static unsigned int max_vht80_rate(int snr)
 {
-	if (snr < 1)
+	if (snr < 0)
 		return 0;
-	if (snr < 2)
-		return 29300; /* VHT80 MCS0 */
-	if (snr < 5)
-		return 58500; /* VHT80 MCS1 */
-	if (snr < 9)
-		return 87800; /* VHT80 MCS2 */
-	if (snr < 11)
-		return 117000; /* VHT80 MCS3 */
-	if (snr < 15)
-		return 175500; /* VHT80 MCS4 */
-	if (snr < 16)
-		return 234000; /* VHT80 MCS5 */
-	if (snr < 18)
-		return 263300; /* VHT80 MCS6 */
-	if (snr < 20)
-		return 292500; /* VHT80 MCS7 */
-	if (snr < 22)
-		return 351000; /* VHT80 MCS8 */
-	return 390000; /* VHT80 MCS9 */
+	INTERPOLATE_RATE(0, 8, 0, 29300); /* VHT80 MCS0 */
+	INTERPOLATE_RATE(8, 11, 29300, 58500); /* VHT80 MCS1 */
+	INTERPOLATE_RATE(11, 15, 58500, 87800); /* VHT80 MCS2 */
+	INTERPOLATE_RATE(15, 17, 87800, 117000); /* VHT80 MCS3 */
+	INTERPOLATE_RATE(17, 21, 117000, 175500); /* VHT80 MCS4 */
+	INTERPOLATE_RATE(21, 24, 175500, 234000); /* VHT80 MCS5 */
+	INTERPOLATE_RATE(24, 26, 234000, 263300); /* VHT80 MCS6 */
+	INTERPOLATE_RATE(26, 31, 263300, 292500); /* VHT80 MCS7 */
+	INTERPOLATE_RATE(31, 35, 292500, 351000); /* VHT80 MCS8 */
+	INTERPOLATE_RATE(35, 37, 351000, 390000); /* VHT80 MCS9 */
+	return 390000;
 }
 
+#undef INTERPOLATE_RATE
 
-void scan_est_throughput(struct wpa_supplicant *wpa_s,
-			 struct wpa_scan_res *res)
+
+unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s,
+			      const u8 *ies, size_t ies_len, int rate,
+			      int snr)
 {
 	enum local_hw_capab capab = wpa_s->hw_capab;
-	int rate; /* max legacy rate in 500 kb/s units */
-	const u8 *ie;
 	unsigned int est, tmp;
-	int snr = res->snr;
-
-	if (res->est_throughput)
-		return;
-
-	/* Get maximum legacy rate */
-	rate = wpa_scan_get_max_rate(res);
+	const u8 *ie;
 
 	/* Limit based on estimated SNR */
 	if (rate > 1 * 2 && snr < 1)
@@ -2296,32 +2276,50 @@
 		rate = 9 * 2;
 	else if (rate > 12 * 2 && snr < 7)
 		rate = 12 * 2;
+	else if (rate > 12 * 2 && snr < 8)
+		rate = 14 * 2;
+	else if (rate > 12 * 2 && snr < 9)
+		rate = 16 * 2;
 	else if (rate > 18 * 2 && snr < 10)
 		rate = 18 * 2;
 	else if (rate > 24 * 2 && snr < 11)
 		rate = 24 * 2;
+	else if (rate > 24 * 2 && snr < 12)
+		rate = 27 * 2;
+	else if (rate > 24 * 2 && snr < 13)
+		rate = 30 * 2;
+	else if (rate > 24 * 2 && snr < 14)
+		rate = 33 * 2;
 	else if (rate > 36 * 2 && snr < 15)
 		rate = 36 * 2;
+	else if (rate > 36 * 2 && snr < 16)
+		rate = 39 * 2;
+	else if (rate > 36 * 2 && snr < 17)
+		rate = 42 * 2;
+	else if (rate > 36 * 2 && snr < 18)
+		rate = 45 * 2;
 	else if (rate > 48 * 2 && snr < 19)
 		rate = 48 * 2;
+	else if (rate > 48 * 2 && snr < 20)
+		rate = 51 * 2;
 	else if (rate > 54 * 2 && snr < 21)
 		rate = 54 * 2;
 	est = rate * 500;
 
 	if (capab == CAPAB_HT || capab == CAPAB_HT40 || capab == CAPAB_VHT) {
-		ie = wpa_scan_get_ie(res, WLAN_EID_HT_CAP);
+		ie = get_ie(ies, ies_len, WLAN_EID_HT_CAP);
 		if (ie) {
-			tmp = max_ht20_rate(snr);
+			tmp = max_ht20_rate(snr, 0);
 			if (tmp > est)
 				est = tmp;
 		}
 	}
 
 	if (capab == CAPAB_HT40 || capab == CAPAB_VHT) {
-		ie = wpa_scan_get_ie(res, WLAN_EID_HT_OPERATION);
+		ie = get_ie(ies, ies_len, WLAN_EID_HT_OPERATION);
 		if (ie && ie[1] >= 2 &&
 		    (ie[3] & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK)) {
-			tmp = max_ht40_rate(snr);
+			tmp = max_ht40_rate(snr, 0);
 			if (tmp > est)
 				est = tmp;
 		}
@@ -2329,22 +2327,22 @@
 
 	if (capab == CAPAB_VHT) {
 		/* Use +1 to assume VHT is always faster than HT */
-		ie = wpa_scan_get_ie(res, WLAN_EID_VHT_CAP);
+		ie = get_ie(ies, ies_len, WLAN_EID_VHT_CAP);
 		if (ie) {
-			tmp = max_ht20_rate(snr) + 1;
+			tmp = max_ht20_rate(snr, 1) + 1;
 			if (tmp > est)
 				est = tmp;
 
-			ie = wpa_scan_get_ie(res, WLAN_EID_HT_OPERATION);
+			ie = get_ie(ies, ies_len, WLAN_EID_HT_OPERATION);
 			if (ie && ie[1] >= 2 &&
 			    (ie[3] &
 			     HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK)) {
-				tmp = max_ht40_rate(snr) + 1;
+				tmp = max_ht40_rate(snr, 1) + 1;
 				if (tmp > est)
 					est = tmp;
 			}
 
-			ie = wpa_scan_get_ie(res, WLAN_EID_VHT_OPERATION);
+			ie = get_ie(ies, ies_len, WLAN_EID_VHT_OPERATION);
 			if (ie && ie[1] >= 1 &&
 			    (ie[2] & VHT_OPMODE_CHANNEL_WIDTH_MASK)) {
 				tmp = max_vht80_rate(snr) + 1;
@@ -2354,9 +2352,30 @@
 		}
 	}
 
-	/* TODO: channel utilization and AP load (e.g., from AP Beacon) */
+	return est;
+}
 
-	res->est_throughput = est;
+
+void scan_est_throughput(struct wpa_supplicant *wpa_s,
+			 struct wpa_scan_res *res)
+{
+	int rate; /* max legacy rate in 500 kb/s units */
+	int snr = res->snr;
+	const u8 *ies = (const void *) (res + 1);
+	size_t ie_len = res->ie_len;
+
+	if (res->est_throughput)
+		return;
+
+	/* Get maximum legacy rate */
+	rate = wpa_scan_get_max_rate(res);
+
+	if (!ie_len)
+		ie_len = res->beacon_ie_len;
+	res->est_throughput =
+		wpas_get_est_tpt(wpa_s, ies, ie_len, rate, snr);
+
+	/* TODO: channel utilization and AP load (e.g., from AP Beacon) */
 }
 
 
@@ -2611,8 +2630,8 @@
 
 int wpas_start_pno(struct wpa_supplicant *wpa_s)
 {
-	int ret, prio;
-	size_t i, num_ssid, num_match_ssid;
+	int ret;
+	size_t prio, i, num_ssid, num_match_ssid;
 	struct wpa_ssid *ssid;
 	struct wpa_driver_scan_params params;
 	struct sched_scan_plan scan_plan;
diff --git a/wpa_supplicant/scan.h b/wpa_supplicant/scan.h
index 58caa78..c9ce2ce 100644
--- a/wpa_supplicant/scan.h
+++ b/wpa_supplicant/scan.h
@@ -9,6 +9,28 @@
 #ifndef SCAN_H
 #define SCAN_H
 
+/*
+ * Noise floor values to use when we have signal strength
+ * measurements, but no noise floor measurements. These values were
+ * measured in an office environment with many APs.
+ */
+#define DEFAULT_NOISE_FLOOR_2GHZ (-89)
+#define DEFAULT_NOISE_FLOOR_5GHZ (-92)
+
+/*
+ * Channels with a great SNR can operate at full rate. What is a great SNR?
+ * This doc https://supportforums.cisco.com/docs/DOC-12954 says, "the general
+ * rule of thumb is that any SNR above 20 is good." This one
+ * http://www.cisco.com/en/US/tech/tk722/tk809/technologies_q_and_a_item09186a00805e9a96.shtml#qa23
+ * recommends 25 as a minimum SNR for 54 Mbps data rate. The estimates used in
+ * scan_est_throughput() allow even smaller SNR values for the maximum rates
+ * (21 for 54 Mbps, 22 for VHT80 MCS9, 24 for HT40 and HT20 MCS7). Use 25 as a
+ * somewhat conservative value here.
+ */
+#define GREAT_SNR 25
+
+#define IS_5GHZ(n) (n > 4000)
+
 int wpa_supplicant_enabled_networks(struct wpa_supplicant *wpa_s);
 void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec);
 int wpa_supplicant_delayed_sched_scan(struct wpa_supplicant *wpa_s,
@@ -60,6 +82,9 @@
 void scan_snr(struct wpa_scan_res *res);
 void scan_est_throughput(struct wpa_supplicant *wpa_s,
 			 struct wpa_scan_res *res);
+unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s,
+			      const u8 *ies, size_t ies_len, int rate,
+			      int snr);
 void wpa_supplicant_set_default_scan_ies(struct wpa_supplicant *wpa_s);
 
 #endif /* SCAN_H */
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index 08d7e3e..0cc81bf 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -131,7 +131,10 @@
 		return NULL;
 	}
 
-	if (wpa_s->conf->sae_pwe == 1 || wpa_s->conf->sae_pwe == 2) {
+	if (ssid->sae_password_id && wpa_s->conf->sae_pwe != 3)
+		use_pt = 1;
+
+	if (use_pt || wpa_s->conf->sae_pwe == 1 || wpa_s->conf->sae_pwe == 2) {
 		bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
 		if (bss) {
 			const u8 *rsnxe;
@@ -142,7 +145,9 @@
 					    BIT(WLAN_RSNX_CAPAB_SAE_H2E));
 		}
 
-		if (wpa_s->conf->sae_pwe == 1 && !use_pt) {
+		if ((wpa_s->conf->sae_pwe == 1 || ssid->sae_password_id) &&
+		    wpa_s->conf->sae_pwe != 3 &&
+		    !use_pt) {
 			wpa_printf(MSG_DEBUG,
 				   "SAE: Cannot use H2E with the selected AP");
 			return NULL;
@@ -166,7 +171,7 @@
 		os_memcpy(wpa_s->sme.sae.tmp->bssid, bssid, ETH_ALEN);
 
 reuse_data:
-	len = wpa_s->sme.sae_token ? wpabuf_len(wpa_s->sme.sae_token) : 0;
+	len = wpa_s->sme.sae_token ? 3 + wpabuf_len(wpa_s->sme.sae_token) : 0;
 	if (ssid->sae_password_id)
 		len += 4 + os_strlen(ssid->sae_password_id);
 	buf = wpabuf_alloc(4 + SAE_COMMIT_MAX_LEN + len);
@@ -177,8 +182,11 @@
 		wpabuf_put_le16(buf, use_pt ? WLAN_STATUS_SAE_HASH_TO_ELEMENT :
 				WLAN_STATUS_SUCCESS);
 	}
-	sae_write_commit(&wpa_s->sme.sae, buf, wpa_s->sme.sae_token,
-			 ssid->sae_password_id);
+	if (sae_write_commit(&wpa_s->sme.sae, buf, wpa_s->sme.sae_token,
+			     ssid->sae_password_id) < 0) {
+		wpabuf_free(buf);
+		return NULL;
+	}
 	if (ret_use_pt)
 		*ret_use_pt = use_pt;
 
@@ -281,7 +289,7 @@
 #if defined(CONFIG_IEEE80211R) || defined(CONFIG_FILS)
 	const u8 *md = NULL;
 #endif /* CONFIG_IEEE80211R || CONFIG_FILS */
-	int i, bssid_changed;
+	int bssid_changed;
 	struct wpabuf *resp = NULL;
 	u8 ext_capab[18];
 	int ext_capab_len;
@@ -291,6 +299,7 @@
 #ifdef CONFIG_MBO
 	const u8 *mbo_ie;
 #endif /* CONFIG_MBO */
+	int omit_rsnxe = 0;
 
 	if (bss == NULL) {
 		wpa_msg(wpa_s, MSG_ERROR, "SME: No scan result available for "
@@ -365,18 +374,18 @@
 	}
 #endif /* CONFIG_SAE */
 
-	for (i = 0; i < NUM_WEP_KEYS; i++) {
-		if (ssid->wep_key_len[i])
-			params.wep_key[i] = ssid->wep_key[i];
-		params.wep_key_len[i] = ssid->wep_key_len[i];
-	}
-	params.wep_tx_keyidx = ssid->wep_tx_keyidx;
+#ifdef CONFIG_WEP
+	{
+		int i;
 
-	bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
-	os_memset(wpa_s->bssid, 0, ETH_ALEN);
-	os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
-	if (bssid_changed)
-		wpas_notify_bssid_changed(wpa_s);
+		for (i = 0; i < NUM_WEP_KEYS; i++) {
+			if (ssid->wep_key_len[i])
+				params.wep_key[i] = ssid->wep_key[i];
+			params.wep_key_len[i] = ssid->wep_key_len[i];
+		}
+		params.wep_tx_keyidx = ssid->wep_tx_keyidx;
+	}
+#endif /* CONFIG_WEP */
 
 	if ((wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
 	     wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
@@ -498,6 +507,7 @@
 		wpa_dbg(wpa_s, MSG_DEBUG, "SME: FT mobility domain %02x%02x",
 			md[0], md[1]);
 
+		omit_rsnxe = !wpa_bss_get_ie(bss, WLAN_EID_RSNX);
 		if (wpa_s->sme.assoc_req_ie_len + 5 <
 		    sizeof(wpa_s->sme.assoc_req_ie)) {
 			struct rsn_mdie *mdie;
@@ -570,7 +580,7 @@
 	sme_auth_handle_rrm(wpa_s, bss);
 
 	wpa_s->sme.assoc_req_ie_len += wpas_supp_op_class_ie(
-		wpa_s, ssid, bss->freq,
+		wpa_s, ssid, bss,
 		wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
 		sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len);
 
@@ -606,7 +616,8 @@
 #endif /* CONFIG_TESTING_OPTIONS */
 	if (wpa_s->rsnxe_len > 0 &&
 	    wpa_s->rsnxe_len <=
-	    sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len) {
+	    sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len &&
+	    !omit_rsnxe) {
 		os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
 			  wpa_s->rsnxe, wpa_s->rsnxe_len);
 		wpa_s->sme.assoc_req_ie_len += wpa_s->rsnxe_len;
@@ -718,6 +729,12 @@
 	}
 #endif /* CONFIG_SAE */
 
+	bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
+	os_memset(wpa_s->bssid, 0, ETH_ALEN);
+	os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
+	if (bssid_changed)
+		wpas_notify_bssid_changed(wpa_s);
+
 	old_ssid = wpa_s->current_ssid;
 	wpa_s->current_ssid = ssid;
 	wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
@@ -1010,7 +1027,7 @@
 				    bssid, 1, wpa_s->sme.seq_num,
 				    use_pt ? WLAN_STATUS_SAE_HASH_TO_ELEMENT :
 				    WLAN_STATUS_SUCCESS);
-	wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, 0);
+	wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, 0, 0);
 	wpabuf_free(resp);
 	wpabuf_free(buf);
 
@@ -1080,7 +1097,7 @@
 	sme_external_auth_build_buf(buf, resp, wpa_s->own_addr,
 				    da, 2, wpa_s->sme.seq_num,
 				    WLAN_STATUS_SUCCESS);
-	wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, 0);
+	wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, 0, 0);
 	wpabuf_free(resp);
 	wpabuf_free(buf);
 }
@@ -1177,11 +1194,16 @@
 	    (external || wpa_s->current_bss) && wpa_s->current_ssid) {
 		int default_groups[] = { 19, 20, 21, 0 };
 		u16 group;
+		const u8 *token_pos;
+		size_t token_len;
+		int h2e = 0;
 
 		groups = wpa_s->conf->sae_groups;
 		if (!groups || groups[0] <= 0)
 			groups = default_groups;
 
+		wpa_hexdump(MSG_DEBUG, "SME: SAE anti-clogging token request",
+			    data, len);
 		if (len < sizeof(le16)) {
 			wpa_dbg(wpa_s, MSG_DEBUG,
 				"SME: Too short SAE anti-clogging token request");
@@ -1199,8 +1221,30 @@
 			return -1;
 		}
 		wpabuf_free(wpa_s->sme.sae_token);
-		wpa_s->sme.sae_token = wpabuf_alloc_copy(data + sizeof(le16),
-							 len - sizeof(le16));
+		token_pos = data + sizeof(le16);
+		token_len = len - sizeof(le16);
+		if (wpa_s->sme.sae.tmp)
+			h2e = wpa_s->sme.sae.tmp->h2e;
+		if (h2e) {
+			if (token_len < 3) {
+				wpa_dbg(wpa_s, MSG_DEBUG,
+					"SME: Too short SAE anti-clogging token container");
+				return -1;
+			}
+			if (token_pos[0] != WLAN_EID_EXTENSION ||
+			    token_pos[1] == 0 ||
+			    token_pos[1] > token_len - 2 ||
+			    token_pos[2] != WLAN_EID_EXT_ANTI_CLOGGING_TOKEN) {
+				wpa_dbg(wpa_s, MSG_DEBUG,
+					"SME: Invalid SAE anti-clogging token container header");
+				return -1;
+			}
+			token_len = token_pos[1] - 1;
+			token_pos += 3;
+		}
+		wpa_s->sme.sae_token = wpabuf_alloc_copy(token_pos, token_len);
+		wpa_hexdump_buf(MSG_DEBUG, "SME: Requested anti-clogging token",
+				wpa_s->sme.sae_token);
 		if (!external)
 			sme_send_authentication(wpa_s, wpa_s->current_bss,
 						wpa_s->current_ssid, 2);
@@ -1260,6 +1304,19 @@
 				   "SAE: Ignore commit message while waiting for confirm");
 			return 0;
 		}
+		if (wpa_s->sme.sae.tmp && wpa_s->sme.sae.tmp->h2e &&
+		    status_code == WLAN_STATUS_SUCCESS) {
+			wpa_printf(MSG_DEBUG,
+				   "SAE: Unexpected use of status code 0 in SAE commit when H2E was expected");
+			return -1;
+		}
+		if (wpa_s->sme.sae.tmp && !wpa_s->sme.sae.tmp->h2e &&
+		    status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT) {
+			wpa_printf(MSG_DEBUG,
+				   "SAE: Unexpected use of status code for H2E in SAE commit when H2E was not expected");
+			return -1;
+		}
+
 		if (groups && groups[0] <= 0)
 			groups = NULL;
 		res = sae_parse_commit(&wpa_s->sme.sae, data, len, NULL, NULL,
@@ -1736,7 +1793,9 @@
 
 #ifdef CONFIG_DPP2
 	if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP && wpa_s->current_ssid &&
-	    wpa_s->current_ssid->dpp_netaccesskey) {
+	    wpa_s->current_ssid->dpp_netaccesskey &&
+	    wpa_s->current_ssid->dpp_pfs != 2 &&
+	    !wpa_s->current_ssid->dpp_pfs_fallback) {
 		struct wpa_ssid *ssid = wpa_s->current_ssid;
 
 		dpp_pfs_free(wpa_s->dpp_pfs);
@@ -1810,6 +1869,9 @@
 	params.vhtcaps_mask = &vhtcaps_mask;
 	wpa_supplicant_apply_vht_overrides(wpa_s, wpa_s->current_ssid, &params);
 #endif /* CONFIG_VHT_OVERRIDES */
+#ifdef CONFIG_HE_OVERRIDES
+	wpa_supplicant_apply_he_overrides(wpa_s, wpa_s->current_ssid, &params);
+#endif /* CONFIG_HE_OVERRIDES */
 #ifdef CONFIG_IEEE80211R
 	if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies &&
 	    get_ie(wpa_s->sme.ft_ies, wpa_s->sme.ft_ies_len,
@@ -2308,7 +2370,7 @@
 	int start, end;
 
 	mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
-			HOSTAPD_MODE_IEEE80211G);
+			HOSTAPD_MODE_IEEE80211G, 0);
 	if (mode == NULL) {
 		/* No channels supported in this band - use empty list */
 		params->freqs = os_zalloc(sizeof(int));
@@ -2601,6 +2663,10 @@
 		return;
 	if (wpa_s->sme.sa_query_count > 0)
 		return;
+#ifdef CONFIG_TESTING_OPTIONS
+	if (wpa_s->disable_sa_query)
+		return;
+#endif /* CONFIG_TESTING_OPTIONS */
 
 	os_get_reltime(&now);
 	if (wpa_s->sme.last_unprot_disconnect.sec &&
diff --git a/wpa_supplicant/systemd/wpa_supplicant-nl80211.service.arg.in b/wpa_supplicant/systemd/wpa_supplicant-nl80211.service.arg.in
index 03ac507..da69a87 100644
--- a/wpa_supplicant/systemd/wpa_supplicant-nl80211.service.arg.in
+++ b/wpa_supplicant/systemd/wpa_supplicant-nl80211.service.arg.in
@@ -12,4 +12,4 @@
 ExecStart=@BINDIR@/wpa_supplicant -c/etc/wpa_supplicant/wpa_supplicant-nl80211-%I.conf -Dnl80211 -i%I
 
 [Install]
-Alias=multi-user.target.wants/wpa_supplicant-nl80211@%i.service
+WantedBy=multi-user.target
diff --git a/wpa_supplicant/systemd/wpa_supplicant-wired.service.arg.in b/wpa_supplicant/systemd/wpa_supplicant-wired.service.arg.in
index c8a744d..ca3054b 100644
--- a/wpa_supplicant/systemd/wpa_supplicant-wired.service.arg.in
+++ b/wpa_supplicant/systemd/wpa_supplicant-wired.service.arg.in
@@ -12,4 +12,4 @@
 ExecStart=@BINDIR@/wpa_supplicant -c/etc/wpa_supplicant/wpa_supplicant-wired-%I.conf -Dwired -i%I
 
 [Install]
-Alias=multi-user.target.wants/wpa_supplicant-wired@%i.service
+WantedBy=multi-user.target
diff --git a/wpa_supplicant/systemd/wpa_supplicant.service.arg.in b/wpa_supplicant/systemd/wpa_supplicant.service.arg.in
index 7788b38..55d2b9c 100644
--- a/wpa_supplicant/systemd/wpa_supplicant.service.arg.in
+++ b/wpa_supplicant/systemd/wpa_supplicant.service.arg.in
@@ -12,4 +12,4 @@
 ExecStart=@BINDIR@/wpa_supplicant -c/etc/wpa_supplicant/wpa_supplicant-%I.conf -i%I
 
 [Install]
-Alias=multi-user.target.wants/wpa_supplicant@%i.service
+WantedBy=multi-user.target
diff --git a/wpa_supplicant/wnm_sta.c b/wpa_supplicant/wnm_sta.c
index 1c0399f..2e09102 100644
--- a/wpa_supplicant/wnm_sta.c
+++ b/wpa_supplicant/wnm_sta.c
@@ -280,6 +280,15 @@
 			wpa_wnmsleep_install_key(wpa_s->wpa,
 						 WNM_SLEEP_SUBELEM_IGTK, ptr);
 			ptr += 10 + WPA_IGTK_LEN;
+		} else if (*ptr == WNM_SLEEP_SUBELEM_BIGTK) {
+			if (ptr[1] < 2 + 6 + WPA_BIGTK_LEN) {
+				wpa_printf(MSG_DEBUG,
+					   "WNM: Too short BIGTK subelem");
+				break;
+			}
+			wpa_wnmsleep_install_key(wpa_s->wpa,
+						 WNM_SLEEP_SUBELEM_BIGTK, ptr);
+			ptr += 10 + WPA_BIGTK_LEN;
 		} else
 			break; /* skip the loop */
 	}
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index a1b0615..07d5f31 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -502,6 +502,7 @@
 		"ignore_auth_resp",
 #endif /* CONFIG_TESTING_OPTIONS */
 		"relative_rssi", "relative_band_adjust",
+		"extended_key_id",
 	};
 	int i, num_fields = ARRAY_SIZE(fields);
 
@@ -593,7 +594,7 @@
 		"tdls_external_control", "osu_dir", "wowlan_triggers",
 		"p2p_search_delay", "mac_addr", "rand_addr_lifetime",
 		"preassoc_mac_addr", "key_mgmt_offload", "passive_scan",
-		"reassoc_same_bss_optim"
+		"reassoc_same_bss_optim", "extended_key_id"
 	};
 	int i, num_fields = ARRAY_SIZE(fields);
 
@@ -1302,7 +1303,7 @@
 static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
 				     char *argv[])
 {
-	return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
+	return wpa_cli_cmd(ctrl, "LIST_NETWORKS", 0, argc, argv);
 }
 
 
@@ -1441,6 +1442,7 @@
 	"dot11MeshHoldingTimeout",
 #endif /* CONFIG_MESH */
 	"wpa_ptk_rekey", "bgscan", "ignore_broadcast_ssid",
+	"wpa_deny_ptk0_rekey",
 	"enable_edmg", "edmg_channel",
 #ifdef CONFIG_P2P
 	"go_p2p_dev_addr", "p2p_client_list", "psk_list",
@@ -1458,6 +1460,9 @@
 	"vht_tx_mcs_nss_3", "vht_tx_mcs_nss_4", "vht_tx_mcs_nss_5",
 	"vht_tx_mcs_nss_6", "vht_tx_mcs_nss_7", "vht_tx_mcs_nss_8",
 #endif /* CONFIG_VHT_OVERRIDES */
+#ifdef CONFIG_HE_OVERRIDES
+	"disable_he",
+#endif /* CONFIG_HE_OVERRIDES */
 	"ap_max_inactivity", "dtim_period", "beacon_int",
 #ifdef CONFIG_MACSEC
 	"macsec_policy",
@@ -1782,7 +1787,7 @@
 	}
 
 	if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
-		printf("Connected to interface '%s.\n", ctrl_ifname);
+		printf("Connected to interface '%s'.\n", ctrl_ifname);
 	} else {
 		printf("Could not connect to interface '%s' - re-trying\n",
 		       ctrl_ifname);
@@ -4004,6 +4009,10 @@
 		wpa_cli_exec(action_file, ifname, pos);
 	} else if (str_starts(pos, WPS_EVENT_ACTIVE)) {
 		wpa_cli_exec(action_file, ifname, pos);
+	} else if (str_starts(pos, WPS_EVENT_PIN_ACTIVE)) {
+		wpa_cli_exec(action_file, ifname, pos);
+	} else if (str_starts(pos, WPS_EVENT_CANCEL)) {
+		wpa_cli_exec(action_file, ifname, pos);
 	} else if (str_starts(pos, WPS_EVENT_TIMEOUT)) {
 		wpa_cli_exec(action_file, ifname, pos);
 	} else if (str_starts(pos, WPS_EVENT_FAIL)) {
diff --git a/wpa_supplicant/wpa_gui-qt4/peers.cpp b/wpa_supplicant/wpa_gui-qt4/peers.cpp
index 3bcf2f5..0a0b3ff 100644
--- a/wpa_supplicant/wpa_gui-qt4/peers.cpp
+++ b/wpa_supplicant/wpa_gui-qt4/peers.cpp
@@ -476,7 +476,9 @@
 		add_station(info);
 
 		reply_len = sizeof(reply) - 1;
-		snprintf(cmd, sizeof(cmd), "STA-NEXT %s", reply);
+		res = snprintf(cmd, sizeof(cmd), "STA-NEXT %s", reply);
+		if (res < 0 || (size_t) res >= sizeof(cmd))
+			break;
 		res = wpagui->ctrlRequest(cmd, reply, &reply_len);
 	} while (res >= 0);
 }
diff --git a/wpa_supplicant/wpa_gui-qt4/wpagui.cpp b/wpa_supplicant/wpa_gui-qt4/wpagui.cpp
index a0aa05e..9404ab4 100644
--- a/wpa_supplicant/wpa_gui-qt4/wpagui.cpp
+++ b/wpa_supplicant/wpa_gui-qt4/wpagui.cpp
@@ -12,6 +12,8 @@
 
 #include <cstdio>
 #include <unistd.h>
+#include <chrono>
+#include <thread>
 #include <QMessageBox>
 #include <QCloseEvent>
 #include <QImageReader>
@@ -713,9 +715,22 @@
 			   strstr(flags, "[DISABLED]") == NULL)
 			first_active = networkSelect->count() - 1;
 
-		if (last)
-			break;
 		start = end + 1;
+		if (*start && strchr(start, '\n'))
+			continue;
+
+		/* avoid race conditions */
+		std::this_thread::sleep_for(std::chrono::milliseconds(200));
+		QString cmd("LIST_NETWORKS LAST_ID=");
+		cmd.append(id);
+		if (ctrlRequest(cmd.toLocal8Bit().constData(), buf, &len) < 0)
+			break;
+
+		buf[len] = '\0';
+		start = strchr(buf, '\n');
+		if (!start)
+			break;
+		start++;
 	}
 
 	if (networkSelect->count() > 1)
diff --git a/wpa_supplicant/wpa_priv.c b/wpa_supplicant/wpa_priv.c
index f197352..c5d7168 100644
--- a/wpa_supplicant/wpa_priv.c
+++ b/wpa_supplicant/wpa_priv.c
@@ -391,6 +391,7 @@
 {
 	struct privsep_cmd_set_key *params;
 	int res;
+	struct wpa_driver_set_key_params p;
 
 	if (iface->drv_priv == NULL || iface->driver->set_key == NULL)
 		return;
@@ -402,14 +403,19 @@
 
 	params = buf;
 
-	res = iface->driver->set_key(iface->ifname, iface->drv_priv,
-				     params->alg,
-				     params->addr, params->key_idx,
-				     params->set_tx,
-				     params->seq_len ? params->seq : NULL,
-				     params->seq_len,
-				     params->key_len ? params->key : NULL,
-				     params->key_len);
+	os_memset(&p, 0, sizeof(p));
+	p.ifname = iface->ifname;
+	p.alg = params->alg;
+	p.addr = params->addr;
+	p.key_idx = params->key_idx;
+	p.set_tx = params->set_tx;
+	p.seq = params->seq_len ? params->seq : NULL;
+	p.seq_len = params->seq_len;
+	p.key = params->key_len ? params->key : NULL;
+	p.key_len = params->key_len;
+	p.key_flag = params->key_flag;
+
+	res = iface->driver->set_key(iface->drv_priv, &p);
 	wpa_printf(MSG_DEBUG, "drv->set_key: res=%d", res);
 }
 
@@ -1184,14 +1190,15 @@
 
 static void usage(void)
 {
-	printf("wpa_priv v" VERSION_STR "\n"
+	printf("wpa_priv v%s\n"
 	       "Copyright (c) 2007-2017, Jouni Malinen <j@w1.fi> and "
 	       "contributors\n"
 	       "\n"
 	       "usage:\n"
 	       "  wpa_priv [-Bdd] [-c<ctrl dir>] [-P<pid file>] "
 	       "<driver:ifname> \\\n"
-	       "           [driver:ifname ...]\n");
+	       "           [driver:ifname ...]\n",
+	       VERSION_STR);
 }
 
 
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 73e63ab..d429496 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -130,6 +130,7 @@
 #endif /* CONFIG_OWE */
 
 
+#ifdef CONFIG_WEP
 /* Configure default/group WEP keys for static WEP */
 int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
 {
@@ -142,11 +143,15 @@
 		set = 1;
 		wpa_drv_set_key(wpa_s, WPA_ALG_WEP, NULL,
 				i, i == ssid->wep_tx_keyidx, NULL, 0,
-				ssid->wep_key[i], ssid->wep_key_len[i]);
+				ssid->wep_key[i], ssid->wep_key_len[i],
+				i == ssid->wep_tx_keyidx ?
+				KEY_FLAG_GROUP_RX_TX_DEFAULT :
+				KEY_FLAG_GROUP_RX_TX);
 	}
 
 	return set;
 }
+#endif /* CONFIG_WEP */
 
 
 int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
@@ -200,7 +205,8 @@
 	/* TODO: should actually remember the previously used seq#, both for TX
 	 * and RX from each STA.. */
 
-	ret = wpa_drv_set_key(wpa_s, alg, NULL, 0, 1, seq, 6, key, keylen);
+	ret = wpa_drv_set_key(wpa_s, alg, NULL, 0, 1, seq, 6, key, keylen,
+			      KEY_FLAG_GROUP_RX_TX_DEFAULT);
 	os_memset(key, 0, sizeof(key));
 	return ret;
 }
@@ -393,7 +399,9 @@
 void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
 				       struct wpa_ssid *ssid)
 {
+#ifdef CONFIG_WEP
 	int i;
+#endif /* CONFIG_WEP */
 
 	if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
 		wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
@@ -411,6 +419,7 @@
 	wpa_s->group_cipher = WPA_CIPHER_NONE;
 	wpa_s->mgmt_group_cipher = 0;
 
+#ifdef CONFIG_WEP
 	for (i = 0; i < NUM_WEP_KEYS; i++) {
 		if (ssid->wep_key_len[i] > 5) {
 			wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
@@ -422,6 +431,7 @@
 			break;
 		}
 	}
+#endif /* CONFIG_WEP */
 
 	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
 	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
@@ -477,6 +487,31 @@
 }
 
 
+void wpas_clear_disabled_interface(void *eloop_ctx, void *timeout_ctx)
+{
+	struct wpa_supplicant *wpa_s = eloop_ctx;
+
+	if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
+		return;
+	wpa_dbg(wpa_s, MSG_DEBUG, "Clear cached state on disabled interface");
+	wpa_bss_flush(wpa_s);
+}
+
+
+#ifdef CONFIG_TESTING_OPTIONS
+void wpas_clear_driver_signal_override(struct wpa_supplicant *wpa_s)
+{
+	struct driver_signal_override *dso;
+
+	while ((dso = dl_list_first(&wpa_s->drv_signal_override,
+				    struct driver_signal_override, list))) {
+		dl_list_del(&dso->list);
+		os_free(dso);
+	}
+}
+#endif /* CONFIG_TESTING_OPTIONS */
+
+
 static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
 {
 	int i;
@@ -502,10 +537,13 @@
 	wpa_s->last_assoc_req_wpa_ie = NULL;
 	os_free(wpa_s->extra_sae_rejected_groups);
 	wpa_s->extra_sae_rejected_groups = NULL;
+	wpabuf_free(wpa_s->rsne_override_eapol);
+	wpa_s->rsne_override_eapol = NULL;
 	wpabuf_free(wpa_s->rsnxe_override_assoc);
 	wpa_s->rsnxe_override_assoc = NULL;
 	wpabuf_free(wpa_s->rsnxe_override_eapol);
 	wpa_s->rsnxe_override_eapol = NULL;
+	wpas_clear_driver_signal_override(wpa_s);
 #endif /* CONFIG_TESTING_OPTIONS */
 
 	if (wpa_s->conf != NULL) {
@@ -552,6 +590,7 @@
 #endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
 
 	eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
+	eloop_cancel_timeout(wpas_clear_disabled_interface, wpa_s, NULL);
 
 	wpas_wps_deinit(wpa_s);
 
@@ -708,12 +747,17 @@
 		if (wpa_s->keys_cleared & BIT(i))
 			continue;
 		wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
-				NULL, 0);
+				NULL, 0, KEY_FLAG_GROUP);
 	}
-	if (!(wpa_s->keys_cleared & BIT(0)) && addr &&
+	/* Pairwise Key ID 1 for Extended Key ID is tracked in bit 15 */
+	if (~wpa_s->keys_cleared & (BIT(0) | BIT(15)) && addr &&
 	    !is_zero_ether_addr(addr)) {
-		wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
-				0);
+		if (!(wpa_s->keys_cleared & BIT(0)))
+			wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL,
+					0, NULL, 0, KEY_FLAG_PAIRWISE);
+		if (!(wpa_s->keys_cleared & BIT(15)))
+			wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 1, 0, NULL,
+					0, NULL, 0, KEY_FLAG_PAIRWISE);
 		/* MLME-SETPROTECTION.request(None) */
 		wpa_drv_mlme_setprotection(
 			wpa_s, addr,
@@ -1242,7 +1286,7 @@
 			      u8 *wpa_ie, size_t *wpa_ie_len)
 {
 	struct wpa_ie_data ie;
-	int sel, proto;
+	int sel, proto, sae_pwe;
 	const u8 *bss_wpa, *bss_rsn, *bss_rsnx, *bss_osen;
 
 	if (bss) {
@@ -1421,13 +1465,18 @@
 #endif /* CONFIG_NO_WPA */
 
 	sel = ie.key_mgmt & ssid->key_mgmt;
-	wpa_dbg(wpa_s, MSG_DEBUG,
-		"WPA: AP key_mgmt 0x%x network profile key_mgmt 0x%x; available key_mgmt 0x%x",
-		ie.key_mgmt, ssid->key_mgmt, sel);
 #ifdef CONFIG_SAE
 	if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
 		sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
 #endif /* CONFIG_SAE */
+#ifdef CONFIG_IEEE80211R
+	if (!(wpa_s->drv_flags & (WPA_DRIVER_FLAGS_SME |
+				  WPA_DRIVER_FLAGS_UPDATE_FT_IES)))
+		sel &= ~WPA_KEY_MGMT_FT;
+#endif /* CONFIG_IEEE80211R */
+	wpa_dbg(wpa_s, MSG_DEBUG,
+		"WPA: AP key_mgmt 0x%x network profile key_mgmt 0x%x; available key_mgmt 0x%x",
+		ie.key_mgmt, ssid->key_mgmt, sel);
 	if (0) {
 #ifdef CONFIG_IEEE80211R
 #ifdef CONFIG_SHA384
@@ -1587,7 +1636,34 @@
 #ifdef CONFIG_OCV
 	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv);
 #endif /* CONFIG_OCV */
-	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PWE, wpa_s->conf->sae_pwe);
+	sae_pwe = wpa_s->conf->sae_pwe;
+	if (ssid->sae_password_id && sae_pwe != 3)
+		sae_pwe = 1;
+	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PWE, sae_pwe);
+
+	/* Extended Key ID is only supported in infrastructure BSS so far */
+	if (ssid->mode == WPAS_MODE_INFRA && wpa_s->conf->extended_key_id &&
+	    (ssid->proto & WPA_PROTO_RSN) &&
+	    ssid->pairwise_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_CCMP_256 |
+				     WPA_CIPHER_GCMP | WPA_CIPHER_GCMP_256) &&
+	    (wpa_s->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID)) {
+		int use_ext_key_id = 0;
+
+		wpa_msg(wpa_s, MSG_DEBUG,
+			"WPA: Enable Extended Key ID support");
+		wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID,
+				 wpa_s->conf->extended_key_id);
+		if (bss_rsn &&
+		    wpa_s->conf->extended_key_id &&
+		    wpa_s->pairwise_cipher != WPA_CIPHER_TKIP &&
+		    (ie.capabilities & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST))
+			use_ext_key_id = 1;
+		wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID,
+				 use_ext_key_id);
+	} else {
+		wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID, 0);
+		wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID, 0);
+	}
 
 	if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
 		wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
@@ -1722,6 +1798,20 @@
 	} else
 		wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
 
+	if (ssid->mode != WPAS_MODE_IBSS &&
+	    !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED) &&
+	    (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_NEVER ||
+	     (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_LOCAL_OK &&
+	      !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS)))) {
+		wpa_msg(wpa_s, MSG_INFO,
+			"Disable PTK0 rekey support - replaced with reconnect");
+		wpa_s->deny_ptk0_rekey = 1;
+		wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 1);
+	} else {
+		wpa_s->deny_ptk0_rekey = 0;
+		wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 0);
+	}
+
 	return 0;
 }
 
@@ -1963,7 +2053,8 @@
 	if (!password)
 		password = ssid->passphrase;
 
-	if (conf->sae_pwe == 0 || !password) {
+	if ((conf->sae_pwe == 0 && !ssid->sae_password_id) || !password ||
+	    conf->sae_pwe == 3) {
 		/* PT derivation not needed */
 		sae_deinit_pt(ssid->pt);
 		ssid->pt = NULL;
@@ -2018,6 +2109,7 @@
 	int rand_style;
 
 	wpa_s->own_disconnect_req = 0;
+	wpa_s->own_reconnect_req = 0;
 
 	/*
 	 * If we are starting a new connection, any previously pending EAPOL
@@ -2031,6 +2123,7 @@
 	else
 		rand_style = ssid->mac_addr;
 
+	wpa_s->multi_ap_ie = 0;
 	wmm_ac_clear_saved_tspecs(wpa_s);
 	wpa_s->reassoc_same_bss = 0;
 	wpa_s->reassoc_same_ess = 0;
@@ -2314,6 +2407,10 @@
 	/* Allow HE on 2.4 GHz without VHT: see nl80211_put_freq_params() */
 	if (is_24ghz)
 		freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
+#ifdef CONFIG_HE_OVERRIDES
+	if (is_24ghz && ssid->disable_he)
+		freq->he_enabled = 0;
+#endif /* CONFIG_HE_OVERRIDES */
 
 	/* Setup higher BW only for 5 GHz */
 	if (mode->mode != HOSTAPD_MODE_IEEE80211A)
@@ -2336,8 +2433,10 @@
 
 #ifdef CONFIG_HT_OVERRIDES
 	if (ssid->disable_ht40) {
+#ifdef CONFIG_VHT_OVERRIDES
 		if (ssid->disable_vht)
 			return;
+#endif /* CONFIG_VHT_OVERRIDES */
 		goto skip_ht40;
 	}
 #endif /* CONFIG_HT_OVERRIDES */
@@ -2434,8 +2533,8 @@
 	if (!vht_freq.vht_enabled)
 		return;
 
-	/* Enable HE for VHT */
-	vht_freq.he_enabled = mode->he_capab[ieee80211_mode].he_supported;
+	/* Enable HE with VHT for 5 GHz */
+	freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
 
 	/* setup center_freq1, bandwidth */
 	for (j = 0; j < ARRAY_SIZE(vht80); j++) {
@@ -2510,6 +2609,12 @@
 #endif /* CONFIG_HT_OVERRIDES */
 	}
 
+#ifdef CONFIG_HE_OVERRIDES
+	if (ssid->disable_he) {
+		vht_freq.he_enabled = 0;
+		freq->he_enabled = 0;
+	}
+#endif /* CONFIG_HE_OVERRIDES */
 	if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
 				    freq->channel, ssid->enable_edmg,
 				    ssid->edmg_channel, freq->ht_enabled,
@@ -2828,7 +2933,7 @@
 #endif /* CONFIG_P2P */
 
 	if (bss) {
-		wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss->freq,
+		wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss,
 						    wpa_ie + wpa_ie_len,
 						    max_wpa_ie_len -
 						    wpa_ie_len);
@@ -2977,7 +3082,8 @@
 
 #ifdef CONFIG_DPP2
 	if (wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
-	    ssid->dpp_netaccesskey) {
+	    ssid->dpp_netaccesskey &&
+	    ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) {
 		dpp_pfs_free(wpa_s->dpp_pfs);
 		wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
 					      ssid->dpp_netaccesskey_len);
@@ -3216,7 +3322,7 @@
 	if (hw_mode == NUM_HOSTAPD_MODES)
 		goto fail;
 
-	mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode);
+	mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, 0);
 	if (!mode)
 		goto fail;
 
@@ -3265,10 +3371,12 @@
 	struct wpa_supplicant *wpa_s = work->wpa_s;
 	u8 *wpa_ie;
 	const u8 *edmg_ie_oper;
-	int use_crypt, ret, i, bssid_changed;
+	int use_crypt, ret, bssid_changed;
 	unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
 	struct wpa_driver_associate_params params;
+#if defined(CONFIG_WEP) || defined(IEEE8021X_EAPOL)
 	int wep_keys_set = 0;
+#endif /* CONFIG_WEP || IEEE8021X_EAPOL */
 	int assoc_failed = 0;
 	struct wpa_ssid *old_ssid;
 	u8 prev_bssid[ETH_ALEN];
@@ -3375,10 +3483,12 @@
 	    wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
 		if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
 			use_crypt = 0;
+#ifdef CONFIG_WEP
 		if (wpa_set_wep_keys(wpa_s, ssid)) {
 			use_crypt = 1;
 			wep_keys_set = 1;
 		}
+#endif /* CONFIG_WEP */
 	}
 	if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
 		use_crypt = 0;
@@ -3523,12 +3633,18 @@
 	wpa_s->auth_alg = params.auth_alg;
 	params.mode = ssid->mode;
 	params.bg_scan_period = ssid->bg_scan_period;
-	for (i = 0; i < NUM_WEP_KEYS; i++) {
-		if (ssid->wep_key_len[i])
-			params.wep_key[i] = ssid->wep_key[i];
-		params.wep_key_len[i] = ssid->wep_key_len[i];
+#ifdef CONFIG_WEP
+	{
+		int i;
+
+		for (i = 0; i < NUM_WEP_KEYS; i++) {
+			if (ssid->wep_key_len[i])
+				params.wep_key[i] = ssid->wep_key[i];
+			params.wep_key_len[i] = ssid->wep_key_len[i];
+		}
+		params.wep_tx_keyidx = ssid->wep_tx_keyidx;
 	}
-	params.wep_tx_keyidx = ssid->wep_tx_keyidx;
+#endif /* CONFIG_WEP */
 
 	if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
 	    (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
@@ -3605,6 +3721,9 @@
 	params.vhtcaps_mask = &vhtcaps_mask;
 	wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
 #endif /* CONFIG_VHT_OVERRIDES */
+#ifdef CONFIG_HE_OVERRIDES
+	wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
+#endif /* CONFIG_HE_OVERRIDES */
 
 #ifdef CONFIG_P2P
 	/*
@@ -3686,11 +3805,13 @@
 		wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
 	}
 
+#ifdef CONFIG_WEP
 	if (wep_keys_set &&
 	    (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
 		/* Set static WEP keys again */
 		wpa_set_wep_keys(wpa_s, ssid);
 	}
+#endif /* CONFIG_WEP */
 
 	if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
 		/*
@@ -3804,6 +3925,15 @@
 	wpa_supplicant_clear_connection(wpa_s, addr);
 }
 
+
+void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s)
+{
+	wpa_s->own_reconnect_req = 1;
+	wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
+
+}
+
+
 static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
 					      struct wpa_ssid *ssid)
 {
@@ -4791,6 +4921,9 @@
 
 	dl_list_init(&wpa_s->bss_tmp_disallowed);
 	dl_list_init(&wpa_s->fils_hlp_req);
+#ifdef CONFIG_TESTING_OPTIONS
+	dl_list_init(&wpa_s->drv_signal_override);
+#endif /* CONFIG_TESTING_OPTIONS */
 
 	return wpa_s;
 }
@@ -5153,6 +5286,19 @@
 #endif /* CONFIG_VHT_OVERRIDES */
 
 
+#ifdef CONFIG_HE_OVERRIDES
+void wpa_supplicant_apply_he_overrides(
+	struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
+	struct wpa_driver_associate_params *params)
+{
+	if (!ssid)
+		return;
+
+	params->disable_he = ssid->disable_he;
+}
+#endif /* CONFIG_HE_OVERRIDES */
+
+
 static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
 {
 #ifdef PCSC_FUNCS
@@ -6095,7 +6241,6 @@
 		wpa_s->drv_capa_known = 1;
 		wpa_s->drv_flags = capa.flags;
 		wpa_s->drv_enc = capa.enc;
-		wpa_s->drv_smps_modes = capa.smps_modes;
 		wpa_s->drv_rrm_flags = capa.rrm_flags;
 		wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
 		wpa_s->max_scan_ssids = capa.max_scan_ssids;
@@ -6319,11 +6464,17 @@
 
 	wpa_s->disconnected = 1;
 	if (wpa_s->drv_priv) {
-		wpa_supplicant_deauthenticate(wpa_s,
-					      WLAN_REASON_DEAUTH_LEAVING);
+		/* Don't deauthenticate if WoWLAN is enabled */
+		if (!wpa_drv_get_wowlan(wpa_s)) {
+			wpa_supplicant_deauthenticate(
+				wpa_s, WLAN_REASON_DEAUTH_LEAVING);
 
-		wpa_drv_set_countermeasures(wpa_s, 0);
-		wpa_clear_keys(wpa_s, NULL);
+			wpa_drv_set_countermeasures(wpa_s, 0);
+			wpa_clear_keys(wpa_s, NULL);
+		} else {
+			wpa_msg(wpa_s, MSG_INFO,
+				"Do not deauthenticate as part of interface deinit since WoWLAN is enabled");
+		}
 	}
 
 	wpa_supplicant_cleanup(wpa_s);
@@ -6704,7 +6855,7 @@
 
 	if (params->wpa_debug_file_path)
 		wpa_debug_open_file(params->wpa_debug_file_path);
-	else
+	if (!params->wpa_debug_file_path && !params->wpa_debug_syslog)
 		wpa_debug_setup_stdout();
 	if (params->wpa_debug_syslog)
 		wpa_debug_open_syslog();
@@ -6772,7 +6923,7 @@
 	wpa_debug_timestamp = global->params.wpa_debug_timestamp =
 		params->wpa_debug_timestamp;
 
-	wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
+	wpa_printf(MSG_DEBUG, "wpa_supplicant v%s", VERSION_STR);
 
 	if (eloop_init()) {
 		wpa_printf(MSG_ERROR, "Failed to initialize event loop");
@@ -7036,7 +7187,7 @@
 	 * There is no point in blacklisting the AP if this event is
 	 * generated based on local request to disconnect.
 	 */
-	if (wpa_s->own_disconnect_req) {
+	if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) {
 		wpa_s->own_disconnect_req = 0;
 		wpa_dbg(wpa_s, MSG_DEBUG,
 			"Ignore connection failure due to local request to disconnect");
@@ -7301,8 +7452,10 @@
 
 int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
 {
+#ifdef CONFIG_WEP
 	int i;
 	unsigned int drv_enc;
+#endif /* CONFIG_WEP */
 
 	if (wpa_s->p2p_mgmt)
 		return 1; /* no normal network profiles on p2p_mgmt interface */
@@ -7313,6 +7466,7 @@
 	if (ssid->disabled)
 		return 1;
 
+#ifdef CONFIG_WEP
 	if (wpa_s->drv_capa_known)
 		drv_enc = wpa_s->drv_enc;
 	else
@@ -7330,6 +7484,7 @@
 			continue;
 		return 1; /* invalid WEP key */
 	}
+#endif /* CONFIG_WEP */
 
 	if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
 	    (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
@@ -7727,12 +7882,17 @@
 
 
 struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
-				   u16 num_modes, enum hostapd_hw_mode mode)
+				   u16 num_modes, enum hostapd_hw_mode mode,
+				   int is_6ghz)
 {
 	u16 i;
 
 	for (i = 0; i < num_modes; i++) {
-		if (modes[i].mode == mode)
+		if (modes[i].mode != mode ||
+		    !modes[i].num_channels || !modes[i].channels)
+			continue;
+		if ((!is_6ghz && !is_6ghz_freq(modes[i].channels[0].freq)) ||
+		    (is_6ghz && is_6ghz_freq(modes[i].channels[0].freq)))
 			return &modes[i];
 	}
 
@@ -7909,3 +8069,87 @@
 
 	return 0;
 }
+
+
+int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
+			struct wpa_signal_info *si)
+{
+	int res;
+
+	if (!wpa_s->driver->signal_poll)
+		return -1;
+
+	res = wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
+
+#ifdef CONFIG_TESTING_OPTIONS
+	if (res == 0) {
+		struct driver_signal_override *dso;
+
+		dl_list_for_each(dso, &wpa_s->drv_signal_override,
+				 struct driver_signal_override, list) {
+			if (os_memcmp(wpa_s->bssid, dso->bssid,
+				      ETH_ALEN) != 0)
+				continue;
+			wpa_printf(MSG_DEBUG,
+				   "Override driver signal_poll information: current_signal: %d->%d avg_signal: %d->%d avg_beacon_signal: %d->%d current_noise: %d->%d",
+				   si->current_signal,
+				   dso->si_current_signal,
+				   si->avg_signal,
+				   dso->si_avg_signal,
+				   si->avg_beacon_signal,
+				   dso->si_avg_beacon_signal,
+				   si->current_noise,
+				   dso->si_current_noise);
+			si->current_signal = dso->si_current_signal;
+			si->avg_signal = dso->si_avg_signal;
+			si->avg_beacon_signal = dso->si_avg_beacon_signal;
+			si->current_noise = dso->si_current_noise;
+			break;
+		}
+	}
+#endif /* CONFIG_TESTING_OPTIONS */
+
+	return res;
+}
+
+
+struct wpa_scan_results *
+wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s)
+{
+	struct wpa_scan_results *scan_res;
+#ifdef CONFIG_TESTING_OPTIONS
+	size_t idx;
+#endif /* CONFIG_TESTING_OPTIONS */
+
+	if (!wpa_s->driver->get_scan_results2)
+		return NULL;
+
+	scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
+
+#ifdef CONFIG_TESTING_OPTIONS
+	for (idx = 0; scan_res && idx < scan_res->num; idx++) {
+		struct driver_signal_override *dso;
+		struct wpa_scan_res *res = scan_res->res[idx];
+
+		dl_list_for_each(dso, &wpa_s->drv_signal_override,
+				 struct driver_signal_override, list) {
+			if (os_memcmp(res->bssid, dso->bssid, ETH_ALEN) != 0)
+				continue;
+			wpa_printf(MSG_DEBUG,
+				   "Override driver scan signal level %d->%d for "
+				   MACSTR,
+				   res->level, dso->scan_level,
+				   MAC2STR(res->bssid));
+			res->flags |= WPA_SCAN_QUAL_INVALID;
+			if (dso->scan_level < 0)
+				res->flags |= WPA_SCAN_LEVEL_DBM;
+			else
+				res->flags &= ~WPA_SCAN_LEVEL_DBM;
+			res->level = dso->scan_level;
+			break;
+		}
+	}
+#endif /* CONFIG_TESTING_OPTIONS */
+
+	return scan_res;
+}
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index 328f91a..f242c3a 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -94,11 +94,8 @@
 # 1: wpa_supplicant initiates scanning and AP selection; if no APs matching to
 #    the currently enabled networks are found, a new network (IBSS or AP mode
 #    operation) may be initialized (if configured) (default)
-# 0: driver takes care of scanning, AP selection, and IEEE 802.11 association
-#    parameters (e.g., WPA IE generation); this mode can also be used with
-#    non-WPA drivers when using IEEE 802.1X mode; do not try to associate with
-#    APs (i.e., external program needs to control association). This mode must
-#    also be used when using wired Ethernet drivers (including MACsec).
+# 0: This mode must only be used when using wired Ethernet drivers
+#    (including MACsec).
 # 2: like 0, but associate with APs using security policy and SSID (but not
 #    BSSID); this can be used, e.g., with ndiswrapper and NDIS drivers to
 #    enable operation with hidden SSIDs and optimized roaming; in this mode,
@@ -106,8 +103,8 @@
 #    the driver reports successful association; each network block should have
 #    explicit security policy (i.e., only one option in the lists) for
 #    key_mgmt, pairwise, group, proto variables
-# Note: ap_scan=2 should not be used with the nl80211 driver interface (the
-# current Linux interface). ap_scan=1 is optimized work working with nl80211.
+# Note: ap_scan=0/2 should not be used with the nl80211 driver interface (the
+# current Linux interface). ap_scan=1 is the only option working with nl80211.
 # For finding networks using hidden SSID, scan_ssid=1 in the network block can
 # be used with nl80211.
 # When using IBSS or AP mode, ap_scan=2 mode can force the new network to be
@@ -426,11 +423,13 @@
 #sae_groups=19 20 21
 
 # SAE mechanism for PWE derivation
-# 0 = hunting-and-pecking loop only (default)
-# 1 = hash-to-element only
+# 0 = hunting-and-pecking loop only (default without password identifier)
+# 1 = hash-to-element only (default with password identifier)
 # 2 = both hunting-and-pecking loop and hash-to-element enabled
 # Note: The default value is likely to change from 0 to 2 once the new
 # hash-to-element mechanism has received more interoperability testing.
+# When using SAE password identifier, the hash-to-element mechanism is used
+# regardless of the sae_pwe parameter value.
 #sae_pwe=0
 
 # Default value for DTIM period (if not overridden in network block)
@@ -803,6 +802,11 @@
 # Set BIT(1) to Enable OCE in STA-CFON mode
 #oce=1
 
+# Extended Key ID support for Individually Addressed frames
+# 0 = force off: Do not use Extended Key ID (default)
+# 1 = auto: Activate Extended Key ID support if the driver supports it
+#extended_key_id=0
+
 # network block
 #
 # Each network (usually AP's sharing the same SSID) is configured as a separate
@@ -1102,6 +1106,18 @@
 # wpa_ptk_rekey: Maximum lifetime for PTK in seconds. This can be used to
 # enforce rekeying of PTK to mitigate some attacks against TKIP deficiencies.
 #
+# wpa_deny_ptk0_rekey: Workaround for PTK rekey issues
+# PTK0 rekeys (using only one Key ID value for pairwise keys) can degrade the
+# security and stability with some cards.
+# To avoid the issues wpa_supplicant can replace those PTK rekeys (including
+# EAP reauthentications) with fast reconnects.
+#
+# Available options:
+# 0 = always rekey when configured/instructed (default)
+# 1 = only rekey when the local driver is explicitly indicating it can perform
+#	this operation without issues
+# 2 = never allow problematic PTK0 rekeys
+#
 # group_rekey: Group rekeying time in seconds. This value, if non-zero, is used
 # as the dot11RSNAConfigGroupRekeyTime parameter when operating in
 # Authenticator role in IBSS, or in AP and mesh modes.
@@ -1445,6 +1461,12 @@
 # 1-65535 = DH Group to use for FILS PFS
 #fils_dh_group=0
 
+# DPP PFS
+# 0: allow PFS to be used or not used (default)
+# 1: require PFS to be used (note: not compatible with DPP R1)
+# 2: do not allow PFS to be used
+#dpp_pfs=0
+
 # MAC address policy
 # 0 = use permanent MAC address
 # 1 = use random MAC address for each ESS connection
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 967298b..8b1d0d0 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -47,6 +47,9 @@
 struct wpas_dbus_priv;
 struct wpas_hidl_priv;
 
+/* How many seconds to consider old scan results valid for association. */
+#define SCAN_RES_VALID_FOR_CONNECT 5
+
 /**
  * struct wpa_interface - Parameters for wpa_supplicant_add_iface()
  */
@@ -280,6 +283,7 @@
 	struct dl_list p2p_srv_upnp; /* struct p2p_srv_upnp */
 	int p2p_disabled;
 	int cross_connection;
+	int p2p_long_listen; /* remaining time in long Listen state in ms */
 	struct wpa_freq_range_list p2p_disallow_freq;
 	struct wpa_freq_range_list p2p_go_avoid_freq;
 	enum wpa_conc_pref {
@@ -477,6 +481,16 @@
 	struct wpabuf *pkt;
 };
 
+struct driver_signal_override {
+	struct dl_list list;
+	u8 bssid[ETH_ALEN];
+	int si_current_signal;
+	int si_avg_signal;
+	int si_avg_beacon_signal;
+	int si_current_noise;
+	int scan_level;
+};
+
 /**
  * struct wpa_supplicant - Internal data for wpa_supplicant interface
  *
@@ -540,6 +554,7 @@
 
 	/* Selected configuration (based on Beacon/ProbeResp WPA IE) */
 	int pairwise_cipher;
+	int deny_ptk0_rekey;
 	int group_cipher;
 	int key_mgmt;
 	int wpa_proto;
@@ -592,8 +607,8 @@
 	  * results.
 	  */
 	struct wpa_bss **last_scan_res;
-	unsigned int last_scan_res_used;
-	unsigned int last_scan_res_size;
+	size_t last_scan_res_used;
+	size_t last_scan_res_size;
 	struct os_reltime last_scan;
 
 	const struct wpa_driver_ops *driver;
@@ -700,6 +715,7 @@
 	int scan_id[MAX_SCAN_ID];
 	unsigned int scan_id_count;
 	u8 next_scan_bssid[ETH_ALEN];
+	unsigned int next_scan_bssid_wildcard_ssid:1;
 
 	struct wpa_ssid_value *ssids_from_scan_req;
 	unsigned int num_ssids_from_scan_req;
@@ -710,7 +726,6 @@
 
 	u64 drv_flags;
 	unsigned int drv_enc;
-	unsigned int drv_smps_modes;
 	unsigned int drv_rrm_flags;
 
 	/*
@@ -880,7 +895,6 @@
 		P2P_GROUP_INTERFACE_CLIENT
 	} p2p_group_interface;
 	struct p2p_group *p2p_group;
-	int p2p_long_listen; /* remaining time in long Listen state in ms */
 	char p2p_pin[10];
 	int p2p_wps_method;
 	u8 p2p_auth_invite[ETH_ALEN];
@@ -1064,6 +1078,7 @@
 	unsigned int wmm_ac_supported:1;
 	unsigned int ext_work_in_progress:1;
 	unsigned int own_disconnect_req:1;
+	unsigned int own_reconnect_req:1;
 	unsigned int ignore_post_flush_scan_res:1;
 
 #define MAC_ADDR_RAND_SCAN       BIT(0)
@@ -1126,6 +1141,7 @@
 	unsigned int p2p_go_csa_on_inv:1;
 	unsigned int ignore_auth_resp:1;
 	unsigned int ignore_assoc_disallow:1;
+	unsigned int disable_sa_query:1;
 	unsigned int testing_resend_assoc:1;
 	unsigned int ignore_sae_h2e_only:1;
 	struct wpabuf *sae_commit_override;
@@ -1136,8 +1152,10 @@
 	size_t last_tk_len;
 	struct wpabuf *last_assoc_req_wpa_ie;
 	int *extra_sae_rejected_groups;
+	struct wpabuf *rsne_override_eapol;
 	struct wpabuf *rsnxe_override_assoc;
 	struct wpabuf *rsnxe_override_eapol;
+	struct dl_list drv_signal_override;
 #endif /* CONFIG_TESTING_OPTIONS */
 
 	struct wmm_ac_assoc_data *wmm_ac_assoc_info;
@@ -1264,6 +1282,15 @@
 	size_t dpp_last_ssid_len;
 #ifdef CONFIG_DPP2
 	struct dpp_pfs *dpp_pfs;
+	int dpp_pfs_fallback;
+	struct wpabuf *dpp_presence_announcement;
+	struct dpp_bootstrap_info *dpp_chirp_bi;
+	int dpp_chirp_freq;
+	int *dpp_chirp_freqs;
+	int dpp_chirp_iter;
+	int dpp_chirp_round;
+	int dpp_chirp_scan_done;
+	int dpp_chirp_listen;
 #endif /* CONFIG_DPP2 */
 #ifdef CONFIG_TESTING_OPTIONS
 	char *dpp_config_obj_override;
@@ -1280,6 +1307,9 @@
 	unsigned int enabled_4addr_mode:1;
 	unsigned int multi_bss_support:1;
 	unsigned int drv_authorized_port:1;
+	unsigned int multi_ap_ie:1;
+	unsigned int multi_ap_backhaul:1;
+	unsigned int multi_ap_fronthaul:1;
 };
 
 
@@ -1290,6 +1320,9 @@
 void wpa_supplicant_apply_vht_overrides(
 	struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
 	struct wpa_driver_associate_params *params);
+void wpa_supplicant_apply_he_overrides(
+	struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
+	struct wpa_driver_associate_params *params);
 
 int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
 int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
@@ -1321,6 +1354,7 @@
 void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s);
 void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
 				   u16 reason_code);
+void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s);
 
 struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s);
 int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id);
@@ -1386,6 +1420,8 @@
 int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s);
 void add_freq(int *freqs, int *num_freqs, int freq);
 
+int wpas_get_op_chan_phy(int freq, const u8 *ies, size_t ies_len,
+			 u8 *op_class, u8 *chan, u8 *phy_type);
 void wpas_rrm_reset(struct wpa_supplicant *wpa_s);
 void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s,
 				   const u8 *report, size_t report_len);
@@ -1408,6 +1444,7 @@
 				 struct scan_info *info);
 void wpas_clear_beacon_rep_data(struct wpa_supplicant *wpa_s);
 void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s);
+void wpas_clear_disabled_interface(void *eloop_ctx, void *timeout_ctx);
 
 
 /* MBO functions */
@@ -1444,7 +1481,7 @@
 				 u8 channel, u8 bw);
 size_t wpas_supp_op_class_ie(struct wpa_supplicant *wpa_s,
 			     struct wpa_ssid *ssid,
-			     int freq, u8 *pos, size_t len);
+			     struct wpa_bss *bss, u8 *pos, size_t len);
 int * wpas_supp_op_classes(struct wpa_supplicant *wpa_s);
 
 int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
@@ -1567,7 +1604,8 @@
 int wpas_sched_scan_plans_set(struct wpa_supplicant *wpa_s, const char *cmd);
 
 struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
-				   u16 num_modes, enum hostapd_hw_mode mode);
+				   u16 num_modes, enum hostapd_hw_mode mode,
+				   int is_6ghz);
 
 void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
 			  unsigned int sec, int rssi_threshold);
@@ -1588,4 +1626,6 @@
 int wpa_is_fils_supported(struct wpa_supplicant *wpa_s);
 int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s);
 
+void wpas_clear_driver_signal_override(struct wpa_supplicant *wpa_s);
+
 #endif /* WPA_SUPPLICANT_I_H */
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index d80b8f2..6bd271e 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -112,6 +112,14 @@
 	}
 #endif /* CONFIG_TESTING_OPTIONS */
 
+	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) {
+		int encrypt = wpa_s->wpa &&
+			wpa_sm_has_ptk_installed(wpa_s->wpa);
+
+		return wpa_drv_tx_control_port(wpa_s, dest, proto, buf, len,
+					       !encrypt);
+	}
+
 	if (wpa_s->l2) {
 		return l2_packet_send(wpa_s->l2, dest, proto, buf, len);
 	}
@@ -219,6 +227,7 @@
 }
 
 
+#ifdef CONFIG_WEP
 /**
  * wpa_eapol_set_wep_key - set WEP key for the driver
  * @ctx: Pointer to wpa_supplicant data (wpa_s)
@@ -242,8 +251,11 @@
 	}
 	return wpa_drv_set_key(wpa_s, WPA_ALG_WEP,
 			       unicast ? wpa_s->bssid : NULL,
-			       keyidx, unicast, NULL, 0, key, keylen);
+			       keyidx, unicast, NULL, 0, key, keylen,
+			       unicast ? KEY_FLAG_PAIRWISE_RX_TX :
+			       KEY_FLAG_GROUP_RX_TX_DEFAULT);
 }
+#endif /* CONFIG_WEP */
 
 
 static void wpa_supplicant_aborted_cached(void *ctx)
@@ -340,8 +352,8 @@
 	wpa_hexdump_key(MSG_DEBUG, "RSN: Configure PMK for driver-based 4-way "
 			"handshake", pmk, pmk_len);
 
-	if (wpa_drv_set_key(wpa_s, WPA_ALG_PMK, NULL, 0, 0, NULL, 0, pmk,
-			    pmk_len)) {
+	if (wpa_drv_set_key(wpa_s, 0, NULL, 0, 0, NULL, 0, pmk,
+			    pmk_len, KEY_FLAG_PMK)) {
 		wpa_printf(MSG_DEBUG, "Failed to set PMK to the driver");
 	}
 
@@ -386,6 +398,13 @@
 			curr = bss;
 			break;
 		}
+#ifdef CONFIG_OWE
+		if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
+		    (bss->flags & WPA_BSS_OWE_TRANSITION)) {
+			curr = bss;
+			break;
+		}
+#endif /* CONFIG_OWE */
 	}
 
 	if (curr) {
@@ -476,6 +495,12 @@
 }
 
 
+static void _wpa_supplicant_reconnect(void *wpa_s)
+{
+	wpa_supplicant_reconnect(wpa_s);
+}
+
+
 static void * wpa_supplicant_get_network_ctx(void *wpa_s)
 {
 	return wpa_supplicant_get_ssid(wpa_s);
@@ -492,7 +517,8 @@
 static int wpa_supplicant_set_key(void *_wpa_s, enum wpa_alg alg,
 				  const u8 *addr, int key_idx, 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_supplicant *wpa_s = _wpa_s;
 	if (alg == WPA_ALG_TKIP && key_idx == 0 && key_len == 32) {
@@ -507,7 +533,8 @@
 	}
 #endif /* CONFIG_TESTING_GET_GTK */
 #ifdef CONFIG_TESTING_OPTIONS
-	if (addr && !is_broadcast_ether_addr(addr)) {
+	if (addr && !is_broadcast_ether_addr(addr) &&
+	    !(key_flag & KEY_FLAG_MODIFY)) {
 		wpa_s->last_tk_alg = alg;
 		os_memcpy(wpa_s->last_tk_addr, addr, ETH_ALEN);
 		wpa_s->last_tk_key_idx = key_idx;
@@ -517,7 +544,7 @@
 	}
 #endif /* CONFIG_TESTING_OPTIONS */
 	return wpa_drv_set_key(wpa_s, alg, addr, key_idx, set_tx, seq, seq_len,
-			       key, key_len);
+			       key, key_len, key_flag);
 }
 
 
@@ -547,7 +574,8 @@
 static int wpa_supplicant_add_pmkid(void *_wpa_s, void *network_ctx,
 				    const u8 *bssid, const u8 *pmkid,
 				    const u8 *fils_cache_id,
-				    const u8 *pmk, size_t pmk_len)
+				    const u8 *pmk, size_t pmk_len,
+				    u32 pmk_lifetime, u8 pmk_reauth_threshold)
 {
 	struct wpa_supplicant *wpa_s = _wpa_s;
 	struct wpa_ssid *ssid;
@@ -569,6 +597,8 @@
 	params.pmkid = pmkid;
 	params.pmk = pmk;
 	params.pmk_len = pmk_len;
+	params.pmk_lifetime = pmk_lifetime;
+	params.pmk_reauth_threshold = pmk_reauth_threshold;
 
 	return wpa_drv_add_pmkid(wpa_s, &params);
 }
@@ -1047,6 +1077,21 @@
 }
 
 
+static int wpa_supplicant_eap_auth_start_cb(void *ctx)
+{
+	struct wpa_supplicant *wpa_s = ctx;
+
+	if (!wpa_s->new_connection && wpa_s->deny_ptk0_rekey &&
+	    !wpa_sm_ext_key_id_active(wpa_s->wpa)) {
+		wpa_msg(wpa_s, MSG_INFO,
+			"WPA: PTK0 rekey not allowed, reconnecting");
+		wpa_supplicant_reconnect(wpa_s);
+		return -1;
+	}
+	return 0;
+}
+
+
 static void wpa_supplicant_set_anon_id(void *ctx, const u8 *id, size_t len)
 {
 	struct wpa_supplicant *wpa_s = ctx;
@@ -1102,7 +1147,9 @@
 	ctx->preauth = 0;
 	ctx->eapol_done_cb = wpa_supplicant_notify_eapol_done;
 	ctx->eapol_send = wpa_supplicant_eapol_send;
+#ifdef CONFIG_WEP
 	ctx->set_wep_key = wpa_eapol_set_wep_key;
+#endif /* CONFIG_WEP */
 #ifndef CONFIG_NO_CONFIG_BLOBS
 	ctx->set_config_blob = wpa_supplicant_set_config_blob;
 	ctx->get_config_blob = wpa_supplicant_get_config_blob;
@@ -1125,6 +1172,7 @@
 	ctx->cert_in_cb = wpa_s->conf->cert_in_cb;
 	ctx->status_cb = wpa_supplicant_status_cb;
 	ctx->eap_error_cb = wpa_supplicant_eap_error_cb;
+	ctx->confirm_auth_cb = wpa_supplicant_eap_auth_start_cb;
 	ctx->set_anon_id = wpa_supplicant_set_anon_id;
 	ctx->cb_ctx = wpa_s;
 	wpa_s->eapol = eapol_sm_init(ctx);
@@ -1160,8 +1208,8 @@
 
 	if (wpa_s->conf->key_mgmt_offload &&
 	    (wpa_s->drv_flags & WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD))
-		return wpa_drv_set_key(wpa_s, WPA_ALG_PMK, NULL, 0, 0,
-				       NULL, 0, pmk, pmk_len);
+		return wpa_drv_set_key(wpa_s, 0, NULL, 0, 0,
+				       NULL, 0, pmk, pmk_len, KEY_FLAG_PMK);
 	else
 		return 0;
 }
@@ -1193,6 +1241,73 @@
 	return wpa_drv_channel_info(wpa_s, ci);
 }
 
+
+static void disable_wpa_wpa2(struct wpa_ssid *ssid)
+{
+	ssid->proto &= ~WPA_PROTO_WPA;
+	ssid->proto |= WPA_PROTO_RSN;
+	ssid->key_mgmt &= ~(WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK |
+			    WPA_KEY_MGMT_PSK_SHA256);
+	ssid->group_cipher &= ~WPA_CIPHER_TKIP;
+	if (!(ssid->group_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP |
+				    WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP_256)))
+		ssid->group_cipher |= WPA_CIPHER_CCMP;
+	ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
+}
+
+
+static void wpa_supplicant_transition_disable(void *_wpa_s, u8 bitmap)
+{
+	struct wpa_supplicant *wpa_s = _wpa_s;
+	struct wpa_ssid *ssid;
+	int changed = 0;
+
+	wpa_msg(wpa_s, MSG_INFO, TRANSITION_DISABLE "%02x", bitmap);
+
+	ssid = wpa_s->current_ssid;
+	if (!ssid)
+		return;
+
+	if ((bitmap & TRANSITION_DISABLE_WPA3_PERSONAL) &&
+	    wpa_key_mgmt_sae(wpa_s->key_mgmt) &&
+	    (ssid->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE)) &&
+	    (ssid->ieee80211w != MGMT_FRAME_PROTECTION_REQUIRED ||
+	     (ssid->group_cipher & WPA_CIPHER_TKIP))) {
+		wpa_printf(MSG_DEBUG,
+			   "WPA3-Personal transition mode disabled based on AP notification");
+		disable_wpa_wpa2(ssid);
+		changed = 1;
+	}
+
+	if ((bitmap & TRANSITION_DISABLE_WPA3_ENTERPRISE) &&
+	    wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
+	    (ssid->key_mgmt & (WPA_KEY_MGMT_IEEE8021X |
+			       WPA_KEY_MGMT_FT_IEEE8021X |
+			       WPA_KEY_MGMT_IEEE8021X_SHA256)) &&
+	    (ssid->ieee80211w != MGMT_FRAME_PROTECTION_REQUIRED ||
+	     (ssid->group_cipher & WPA_CIPHER_TKIP))) {
+		disable_wpa_wpa2(ssid);
+		changed = 1;
+	}
+
+	if ((bitmap & TRANSITION_DISABLE_ENHANCED_OPEN) &&
+	    wpa_s->key_mgmt == WPA_KEY_MGMT_OWE &&
+	    (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
+	    !ssid->owe_only) {
+		ssid->owe_only = 1;
+		changed = 1;
+	}
+
+	if (!changed)
+		return;
+
+#ifndef CONFIG_NO_CONFIG_WRITE
+	if (wpa_s->conf->update_config &&
+	    wpa_config_write(wpa_s->confname, wpa_s->conf))
+		wpa_printf(MSG_DEBUG, "Failed to update configuration");
+#endif /* CONFIG_NO_CONFIG_WRITE */
+}
+
 #endif /* CONFIG_NO_WPA */
 
 
@@ -1211,6 +1326,7 @@
 	ctx->set_state = _wpa_supplicant_set_state;
 	ctx->get_state = _wpa_supplicant_get_state;
 	ctx->deauthenticate = _wpa_supplicant_deauthenticate;
+	ctx->reconnect = _wpa_supplicant_reconnect;
 	ctx->set_key = wpa_supplicant_set_key;
 	ctx->get_network_ctx = wpa_supplicant_get_network_ctx;
 	ctx->get_bssid = wpa_supplicant_get_bssid;
@@ -1244,6 +1360,7 @@
 	ctx->key_mgmt_set_pmk = wpa_supplicant_key_mgmt_set_pmk;
 	ctx->fils_hlp_rx = wpa_supplicant_fils_hlp_rx;
 	ctx->channel_info = wpa_supplicant_channel_info;
+	ctx->transition_disable = wpa_supplicant_transition_disable;
 
 	wpa_s->wpa = wpa_sm_init(ctx);
 	if (wpa_s->wpa == NULL) {
@@ -1275,6 +1392,8 @@
 		conf.ssid = ssid->ssid;
 		conf.ssid_len = ssid->ssid_len;
 		conf.wpa_ptk_rekey = ssid->wpa_ptk_rekey;
+		conf.wpa_deny_ptk0_rekey = ssid->wpa_deny_ptk0_rekey;
+		conf.owe_ptk_workaround = ssid->owe_ptk_workaround;
 #ifdef CONFIG_P2P
 		if (ssid->p2p_group && wpa_s->current_bss &&
 		    !wpa_s->p2p_disable_ip_addr_req) {
@@ -1297,6 +1416,7 @@
 			conf.fils_cache_id =
 				wpa_bss_get_fils_cache_id(wpa_s->current_bss);
 #endif /* CONFIG_FILS */
+		conf.beacon_prot = ssid->beacon_prot;
 	}
 	wpa_sm_set_config(wpa_s->wpa, ssid ? &conf : NULL);
 }
diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c
index 8387fc3..e617158 100644
--- a/wpa_supplicant/wps_supplicant.c
+++ b/wpa_supplicant/wps_supplicant.c
@@ -532,6 +532,7 @@
 		ssid->key_mgmt = WPA_KEY_MGMT_PSK;
 		if (wpa_s->conf->wps_cred_add_sae &&
 		    cred->key_len != 2 * PMK_LEN) {
+			ssid->auth_alg = 0;
 			ssid->key_mgmt |= WPA_KEY_MGMT_SAE;
 			ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
 		}
@@ -1829,6 +1830,10 @@
 	wpa_printf(MSG_DEBUG, "WPS: Check whether PBC session overlap is "
 		   "present in scan results; selected BSSID " MACSTR,
 		   MAC2STR(selected->bssid));
+	if (!is_zero_ether_addr(ssid->bssid))
+		wpa_printf(MSG_DEBUG,
+			   "WPS: Network profile limited to accept only a single BSSID " MACSTR,
+			   MAC2STR(ssid->bssid));
 
 	/* Make sure that only one AP is in active PBC mode */
 	wps_ie = wpa_bss_get_vendor_ie_multi(selected, WPS_IE_VENDOR_TYPE);
@@ -1849,6 +1854,14 @@
 		    os_memcmp(selected->bssid, ap->bssid, ETH_ALEN) == 0)
 			continue;
 
+		if (!is_zero_ether_addr(ssid->bssid) &&
+		    os_memcmp(ap->bssid, ssid->bssid, ETH_ALEN) != 0) {
+			wpa_printf(MSG_DEBUG, "WPS: Ignore another BSS " MACSTR
+				   " in active PBC mode due to local BSSID limitation",
+				   MAC2STR(ap->bssid));
+			continue;
+		}
+
 		wpa_printf(MSG_DEBUG, "WPS: Another BSS in active PBC mode: "
 			   MACSTR, MAC2STR(ap->bssid));
 		wpa_hexdump(MSG_DEBUG, "WPS: UUID of the other BSS",