[wpa_supplicant] Cumulative patch from commit 59e9794c7

Bug: 180762886
Test: Verify Passpoint ANQP functionality and Passpoint association
Test: Connect to Passpoint, Open, WPA2, WPA3 networks and run traffic
Test: Regression test passed (Bug: 180943193)

BYPASS_INCLUSIVE_LANGUAGE_REASON=Merged from Open source

59e9794c7 QCA vendor attribute to configure Punctured Preamble Rx in HE cap
875d7be38 QCA vendor attribute to disable data and management frame Tx
ecb7590f3 QCA vendor attribute to configure RU 242 tone for data Tx
8d2329712 QCA vendor attribute to configure BSS max idle period
dc72854fe Fix handle_auth_cb() message length check regression
f03580e31 Restore permanent MAC address on the FLUSH command
976c3c161 DPP2: Accept Config Result before GAS response TX status
6518c72b0 Multi-AP: Fix backhaul SSID printing condition
1ba8a315c Avoid use of C++ keyword in a header file
10502ad59 radiotap: Fix compiler issues with packed structures
0dee287c8 EAP server: Extend EAP-TLS Commitment Message use to PEAP and EAP-TTLS
fae4eafe4 EAP-TTLS peer: Handle Commitment Message for TLS 1.3
155125b02 EAP-TLS peer: Handle Commitment Message for TLS 1.3
3a457509d EAP: Extend Session-Id derivation with TLS 1.3 to PEAP and EAP-TTLS
647db6a6b EAP-TTLS: Key derivation per draft-ietf-emu-tls-eap-types-00
c74f23020 EAP-PEAP: Key derivation per draft-ietf-emu-tls-eap-types-00
872609c15 EAP-TTLS/PEAP peer: Fix failure when using session tickets under TLS 1.3
8265f8453 nl80211: Unconditionally clear nl_msg
6c7b0a965 PASN: Correctly set RSNXE bits from AP
85eb47e3a PASN: Correctly set RSNXE bits from STA
be5f7f374 wpa_supplicant: Fix potential memleak on an error path
8f248d1ac Check for message truncation in RADIUS client
5cb25307e Set RADIUS message length to reflect RFC 2865
7df089b56 Create RADIUS_MAX_MSG_LEN param in the shared radius.h
98a52b09c Add new attributes in get_sta_info QCA vendor command
8f204f69a Show OCV and beacon protection capabilities in control interface
6f92f81da AP: Check driver's capability to enable OCV when driver SME is used
73ebd58fc STA: Check driver capability to enable OCV when driver SME is used
f3dfe42c7 Clean up RSN parameter setting for PASN
d36d4209f Enable beacon protection only when driver indicates support
9d99814e2 Update sgml to generate reproducible manpages
e680a51e9 ext_password: Implement new file-based backend
e9f449ba5 wpa_supplicant: Move wpa_config_get_line() into utils
b1c23d3f2 HE: Fall back to 20 MHz on 2.4 GHz if 40 MHz is not supported
f1c6c9d3e ACS: Allow downgrading to 20 MHz based on OBSS results
9bb2f7529 Sync with mac80211-next.git include/uapi/linux/nl80211.h
cfc45a98d nl80211: Unsolicited broadcast Probe Response configuration
024b4b2a2 AP: Unsolicited broadcast Probe Response configuration
6fb626412 P2P: Clear unexpected HT40 configuration on 2.4 GHz band
6b59e63f0 Include secondary channel config in no-hw-channel-found message
d76ba2b31 nl80211: Add FILS Discovery frame configuration
9c02a0f5a FILS: Add generation of FILS Discovery frame template
c4c529e9c Add a helper function for determining RSN capabilities field value
272466518 Define FILS Discovery frame subfields
3eb5f7128 Do not include VHT elements in Beacon frames on the 6 GHz band
2c2b6d265 Add Transmit Power Envelope also for 6 GHz HE AP
6c2b729de Use hostapd_get_oper_chwidth() when build Transmit Power Envelope element
5d3c4496f Make VHT Transmit Power Envelope element helper more generic
58bbbb598 nl80211: Ignore 4addr mode enabling error if it was already enabled
1b45b8d3f wpa_supplicant: Don't exit scanning state on config reload
581df2d52 DPP2: Defer chirp scan if other scan is queued up
35756c02e mesh: Assign channel in frequency params in all bands
b1c3e4d07 nl80211: Send HE 6 GHz capability parameters to the driver
8d10831dc wolfSSL: wolfSSL_use_PrivateKey_* correct return codes
7e823d4df DPP: Expose config object PSK/passphrase in wpa_supplicant
1029f16a9 DPP: Expose config object AKM in wpa_supplicant control interface
ad59639ed DPP2: Fix Authentication Request destination in the chirping case
598f67132 SAE: Avoid driver STA entry removal unnecessarily when using H2E/PK
99cd45372 hw_feature: Correctly select mode in case of the 6 GHz band
f728c867e AP: Extend Spatial Reuse Parameter Set
9f9d3d362 Allow HE MCS rate selection for Beacon frames
7f2f262e6 nl80211: Support the 6 GHz band for beacon rate configuration
c3d557b4d hostapd: Add HE 6 GHz band capability configuration
bd8b17030 EAP-AKA: Check that ID message storing succeeds
e781f7c86 Fix compiler warning on CONFIG_AP without CONFIG_P2P builds
4c9b16602 Update Visual Studio projects to match file renaming
48cfb52b7 Rename blacklist.[ch] to bssid_ignore.[ch]
626fc0dcd Rename wpa_blacklist to wpa_bssid_ignore
b58ac90c3 Rename INTERWORKING_BLACKLISTED define
72cd4293f Rename the control interface BLACKLIST command to BSSID_IGNORE
752b1c608 Rename network profiles parameters for ignoring/accepted BSSIDs
e6ac26943 radiotap: Update radiotap parser
136bbf15c wlantest: Add more details about protected FTM frames
f56eec7c1 wlantest: Process Action No Ack frames like Action frames
ef26fc19f DFS: Allow switch to an available channel
f98fe2fd0 hostapd: Report errors ACCEPT_ACL/DENY_ACL control interface commands
15251c658 hostapd: Fix dynamic ACCEPT_ACL management over control interface
871d6648f hostapd: Add multi_ap settings to get_config() output
f95ccc102 WPS: Reconfigure credentials on hostapd config reload
2fd90eb09 WPS: Use helper variables to clean up code
f7bbad576 wpa_supplicant: Configurable fast-associate timer threshold
b829b7003 wpa_supplicant: Notify freq change on CH_SWITCH
3a00a86bb hostapd: Fix dpp_listen in DPP responder scenario
4a7e0ac26 hostapd: Add an option to notify management frames on ctrl_iface
e79febb3f P2P: Adding option to manage device drivers creating random MAC addresses
a579642bc BSD: If route socket overflows, sync drivers to system interfaces
fa859ebb1 RSN+WPA: Fix RSNE removing in EAPOL-Key msg 3/4 when RSNXE is included
dc1977959 RSN: Validate RSNXE match in EAPOL-Key msg 3/4 only when RSN is used
0b7895750 DPP: Silence compiler warning about signed/unsigned comparison
8f557d204 Make wpa_bss_ext_capab() handle NULL bss argument
2cadb60ab robust_av: Use wpa_bss_ext_capab() helper
a287c2078 Disable HE capabilities when using unacceptable security config
56c192c5e nl80211: Skip frame filter config for P2P-Device
2b916c9fd dbus: Fix IEs getter to use wpa_bss_ie_ptr()
9416b5f32 Add HE in ieee80211_freq_to_channel_ext() documentation
2acfd15a2 hostapd: Generalize channel switch methods to incorperated HE mode
2908dc91c hostapd: Enable HE for channel switch commmand
1c3e71d14 P2P: Add a maximum length limit for peer vendor IEs
947272feb P2P: Fix copying of secondary device types for P2P group client
25df656a8 Remove pointless defines for ext capab bits
11355a122 Reset external_scan_running on interface deletion
630b1fdba AP: Add 6 GHz security constraints
df0bfe475 mesh: Fix for leaving mesh
24f0507af WPA: Support deriving KDK based on capabilities (Authenticator)
dccb6cde0 WPA: Support deriving KDK based on capabilities
9e7b980d6 PASN: Include RSNXE in the PASN negotiation
d8cd20e37 RSN: Add RSNXE new definitions
2eb2fb8bd AP: Support PASN with FT key derivation
5c65ad6c0 PASN: Support PASN with FT key derivation
62edb79a0 AP: Support PASN with FILS key derivation
8c6d2e252 PASN: Support PASN with FILS key derivation
da35e1214 AP: Support PASN with SAE key derivation
a93ec28d1 PASN: Support PASN with SAE key derivation
3040c8a2d AP: Add support for PASN processing to the SME
f2f8e4f45 Add PTKSA cache to hostapd
2c963a117 AP: Add support for configuring PASN
ad338cfe5 ctrl_iface: Add support for PASN authentication
363768c8a PASN: Add support for PASN processing to wpa_supplicant
d70060f96 WPA: Add PTKSA cache to wpa_supplicant for PASN
a4e369161 WPA: Add PTKSA cache implementation
a84ba92fa WPA: Add a function to get PMKSA cache entry
6709b4ceb common: Add PASN parsing to ieee802_11_parse_extension()
46bfc3a84 tests: Add module tests for PASN PTK derivation
9ce123cdb PASN: Add common Authentication frame build/validation functions
c6d1a33bb PASN: Add functions to compute PTK, MIC and hash
d87f4aea1 FILS: Extend the fils_pmk_to_ptk() function to also derive KDK
6e834db74 FT: Extend the wpa_pmk_r1_to_ptk() function to also derive KDK
46c232eb7 WPA: Extend the wpa_pmk_to_ptk() function to also derive KDK
019507e10 common: Allow WPA_CIPHER_GTK_NOT_USED as a valid group management cipher
244721221 nl80211: Always register for RX authentication frames with PASN
a728449a0 nl80211: Allow off-channel of PASN authentication frames in send_mlme()
367e79231 PASN: Add some specification definitions
833cdbe97 Add support for new 5 GHz channels 173 and 177
21fdb454d P2P: Fix channel selection for operating class 129
959af4f57 DPP: Abort authentication if no Auth Confirm is received within a second
62657365f Add a configuration to disconnect on deinit if WoWLAN is enabled
8f5897294 dbus: Export new 'suiteb192' capability
9cdcc8823 DBus: Add 'owe' to interface Capabilities
8e8406469 wpa_cli: Add WPS_EVENT_OVERLAP to action scripts
41fae6e0b nl80211: Add missing WPA3-SAE auth_data in auth retry case
71718b628 FT: Update key mgmt properly in RSNE during roaming
ea77568d8 Add user configured vendor IEs to default scan IEs
b6947f01a Android: Pass the vendor events to $(BOARD_WPA_SUPPLICANT_PRIVATE_LIB)
7b121af26 P2P: Delay P2P scan when an external scan is in progress
f39d6aacb P2P: Recover p2p_find operation in case of failure to fetch scan results
74818ca63 Process QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH after NL80211_CMD_ROAM
b4a41abad nl80211: Do not ignore disconnection event after a connection event
084b3d2f8 Drop unexpected connection event while disconnected
73c7c2da9 Vendor feature capability to notify TWT asynchronous response support
a337c1d7c New TWT operations and attributes to TWT Setup and Nudge
b709bb40f DPP2: Add DPP_CONTROLLER commands to hostapd_cli and wpa_cli
6ead8b897 Use bool for is_6ghz variables and functions
7131fede3 Extend the setband support for 6 GHz and band combinations
2a37cda74 scan: Add a helper function to append supported freqs from a given band
bba926350 Fix gcc-10 build with -Werror=array-bounds and dl_list_for_each()
0225301fd wolfSSL: Client cert loading API fix
297050b46 nl80211: Report invalid signal and noise when info is unavailable
be96f4e8d wlantest: Allow missing RSNE in S1G beacon
d83eaa351 Add option to ignore Probe Request frames when RSSI is too low
f2a010140 wpa_supplicant: Initial connection speedup
4683b7218 DFS: Enter DFS state if no available channel is found
eee0d242b hostapd: Add ability to disable HT/VHT/HE per BSS
89ad24379 mesh: Move mesh frequency setting to its own function
7c2cad969 mesh: Fix DFS deinit/init
0896c442d mesh: Fix for mesh init/deinit
06161d4f1 mesh: Fix mesh_oom test
12ae3e3db mesh: Inform kernel driver about DFS handler in userspace
a27faf2c9 mesh: Fix channel switch error during CAC
872590978 nl80211: Do not set offchanok on DFS channels in non-ETSI for mesh
e3608040c mesh: Update ssid->frequency as pri/sec channels switch
f1df4fbfc mesh: Use setup completion callback to complete mesh join
3c9abc785 QCA vendor attributes to configure TX and RX NSS
ed24bad1d AP: Check driver support while auto-selecting bandwidth for AP/P2P GO
5b782ff62 Add bus failure reason code to vendor indication
1c77f3d3f Indicate whether additional ANQP elements were protected
90ca804e4 Add vendor attributes for TWT nudge request
454ebb504 BSS: Use variable length array for IEs at the end of struct wpa_bss
be7ee264f BSS: Use wrapper function for getting a pointer to the IE buffer
95edd8144 BSS: Add wpa_bss_get_ie_ext() wrapper
dba4f7a54 Mark wpa_bss_get_fils_cache_id() argument const
2a7023ba6 Change list arguments to const where possible
fdf114641 nl80211: Send the sae_pwe value to the driver
2576f27e0 P2P: Disable P2P in the 6 GHz band for now
2ffd3bb4b P2P: Include p2p_6ghz_disable in global configuration
60c902f40 Add connect fail reason code from the driver to assoc reject event
7423fa6e8 Vendor feature capability to support concurrent sessions on Wi-Fi bands
1934ad9b2 Add extra parameters to vendor command GPIO attribute
d0e0d2283 Sync with mac80211-next.git include/uapi/linux/nl80211.h
c2c468622 Set NLA_F_NESTED flag with NL80211_ATTR_VENDOR_DATA conditionally
cd3aa54a3 Add test configuration attr to enable/disable full bandwidth UL MU-MIMO
f4de21a77 BSS/scan: More conversions to for_each_element_id()
aa06444f2 dbus: Check eloop registration failure in add_watch handler
56a1df71e BSS: Convert wpa_bss_get_vendor_ie() to use for_each_element_id()
ec1f4f3c8 Make GTK length validation for RSN Group 1/2 easier to analyze
c42d41bf3 EAP-IKEv2: Try to make transform parser simpler to understand
ec0d99c00 HS 2.0: Clarify OSU Friendly Name length validation
05962099c TDLS: Fix error path for TPK M1 send failure in testing functionality
a9fed5f5b Avoid undefined behavior with memcpy PMK/PSK update
c643c3928 nl80211: Fix filtering of unsupported bands/modes
a86078c87 TDLS: Fix error path handling for TPK M1 send failures
3d490296b DPP2: Fix error path handling in enterprise provisioning
f724dd1bf Remove unused variable update
589bf1f7a DPP2: Fix ppkey parsing
79e3f08d3 6 GHz: Add support for missing 6 GHz operating classes
66bed14b2 6 GHz: Fix opclasses mapping in ieee80211_freq_to_channel_ext()
5e779873e EAP-SIM peer: Send AT_IDENTITY first
0577e8e67 nl80211: Check for proper nlmsg allocation in send_and_recv_msgs_owner()
02289ab53 DPP2: Explicitly check EC_KEY before dereferencing it
c57590476 P2P: Consider BSS entry pending for P2P joining as a known BSS
106d67a93 nl80211: Filter out unsupported bands
9c39c1a6d P2P: Include p2p_add_cli_chan parameter while cloning the configuration
8f0ed71ff Vendor specific feature capability for Adaptive 11r
45ae6ae8e Add additional vendor specific hang reason codes
d2190cdc6 DPP2: Update the default port number for DPP-over-TCP
5d988b4a5 Fix couple more typos
b439b21a2 wpa_supplicant: Fix typos
183e72ae1 SAE-PK: Do not accept SAE-PK status code when no PK is configured
80662accb SAE: Don't use potentially uninitialized keys
b4c7114cf wpa_supplicant: Remove unfeasible conditions in config parsing
ff7e0c1cf wpa_cli: Don't access uninitialized variables
e364a34c6 OpenSSL: Make openssl_debug_dump_certificate() more robust

Change-Id: Ia7e3838712a621fe0341464dd04671f708d8cde4
diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
index 2a171f6..553302c 100644
--- a/wpa_supplicant/Android.mk
+++ b/wpa_supplicant/Android.mk
@@ -60,6 +60,10 @@
 L_CFLAGS += -DANDROID_LIB_STUB
 endif
 
+ifneq ($(BOARD_WPA_SUPPLICANT_PRIVATE_LIB_EVENT),)
+L_CFLAGS += -DANDROID_LIB_EVENT
+endif
+
 # Disable roaming in wpa_supplicant
 ifdef CONFIG_NO_ROAMING
 L_CFLAGS += -DCONFIG_NO_ROAMING
@@ -121,6 +125,7 @@
 OBJS += bss.c
 OBJS += eap_register.c
 OBJS += src/utils/common.c
+OBJS += src/utils/config.c
 OBJS += src/utils/wpa_debug.c
 OBJS += src/utils/wpabuf.c
 OBJS += src/utils/bitfield.c
@@ -402,6 +407,17 @@
 OBJS += wifi_display.c
 endif
 
+ifdef CONFIG_PASN
+L_CFLAGS += -DCONFIG_PASN
+L_CFLAGS += -DCONFIG_PTKSA_CACHE
+NEED_HMAC_SHA256_KDF=y
+NEED_HMAC_SHA384_KDF=y
+NEED_SHA256=y
+NEED_SHA384=y
+OBJS += src/common/ptksa_cache.c
+OBJS += pasn_supplicant.c
+endif
+
 ifdef CONFIG_HS20
 OBJS += hs20_supplicant.c
 L_CFLAGS += -DCONFIG_HS20
@@ -1638,6 +1654,12 @@
 NEED_EXT_PASSWORD=y
 endif
 
+ifdef CONFIG_EXT_PASSWORD_FILE
+OBJS += src/utils/ext_password_file.c
+L_CFLAGS += -DCONFIG_EXT_PASSWORD_FILE
+NEED_EXT_PASSWORD=y
+endif
+
 ifdef NEED_EXT_PASSWORD
 OBJS += src/utils/ext_password.c
 L_CFLAGS += -DCONFIG_EXT_PASSWORD
@@ -1668,7 +1690,7 @@
 
 OBJS += src/drivers/driver_common.c
 
-OBJS += wpa_supplicant.c events.c blacklist.c wpas_glue.c scan.c
+OBJS += wpa_supplicant.c events.c bssid_ignore.c wpas_glue.c scan.c
 OBJS_t := $(OBJS) $(OBJS_l2) eapol_test.c
 OBJS_t += src/radius/radius_client.c
 OBJS_t += src/radius/radius.c
diff --git a/wpa_supplicant/ChangeLog b/wpa_supplicant/ChangeLog
index f82e5e0..a06a93b 100644
--- a/wpa_supplicant/ChangeLog
+++ b/wpa_supplicant/ChangeLog
@@ -533,7 +533,7 @@
 	* fixed MSCHAP UTF-8 to UCS-2 conversion for three-byte encoding;
 	  this fixes password with include UTF-8 characters that use
 	  three-byte encoding EAP methods that use NtPasswordHash
-	* fixed couple of sequencies where radio work items could get stuck,
+	* fixed couple of sequences where radio work items could get stuck,
 	  e.g., when rfkill blocking happens during scanning or when
 	  scan-for-auth workaround is used
 	* P2P enhancements/fixes
@@ -627,7 +627,7 @@
 	* added 'dup_network <id_s> <id_d> <name>' command; this can be used to
 	  clone the psk field without having toextract it from wpa_supplicant
 	* fixed GSM authentication on USIM
-	* added support for usin epoll in eloop (CONFIG_ELOOP_EPOLL=y)
+	* added support for using epoll in eloop (CONFIG_ELOOP_EPOLL=y)
 	* fixed some concurrent virtual interface cases with dedicated P2P
 	  management interface to not catch events from removed interface (this
 	  could result in the management interface getting disabled)
@@ -1113,7 +1113,7 @@
 	    workarounds.
 	  - Add support for AuthorizedMACs attribute.
 	* TDLS:
-	  - Propogate TDLS related nl80211 capability flags from kernel and
+	  - Propagate TDLS related nl80211 capability flags from kernel and
 	    add them as driver capability flags. If the driver doesn't support
 	    capabilities, assume TDLS is supported internally. When TDLS is
 	    explicitly not supported, disable all user facing TDLS operations.
@@ -2221,7 +2221,7 @@
 	* added support for EAP-SIM pseudonyms and fast re-authentication
 	* added support for EAP-TLS/PEAP/TTLS fast re-authentication (TLS
 	  session resumption)
-	* added support for EAP-SIM with two challanges
+	* added support for EAP-SIM with two challenges
 	  (phase1="sim_min_num_chal=3" can be used to require three challenges)
 	* added support for configuring DH/DSA parameters for an ephemeral DH
 	  key exchange (EAP-TLS/PEAP/TTLS) using new configuration parameters
@@ -2332,7 +2332,7 @@
 	  ctrl_interface_group can be used to select which group gets access to
 	  the control interface;
 	  wpa_cli: by default, try to connect to the first interface available
-	  in /var/run/wpa_supplicant; this path can be overriden with -p option
+	  in /var/run/wpa_supplicant; this path can be overridden with -p option
 	  and an interface can be selected with -i option (i.e., in most common
 	  cases, wpa_cli does not need to get any arguments)
 	* added support for LEAP
diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile
index 08522de..87db2cd 100644
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -83,6 +83,7 @@
 OBJS += bss.o
 OBJS += eap_register.o
 OBJS += ../src/utils/common.o
+OBJS += ../src/utils/config.o
 OBJS += ../src/utils/wpa_debug.o
 OBJS += ../src/utils/wpabuf.o
 OBJS += ../src/utils/bitfield.o
@@ -394,6 +395,17 @@
 OBJS += wifi_display.o
 endif
 
+ifdef CONFIG_PASN
+CFLAGS += -DCONFIG_PASN
+CFLAGS += -DCONFIG_PTKSA_CACHE
+NEED_HMAC_SHA256_KDF=y
+NEED_HMAC_SHA384_KDF=y
+NEED_SHA256=y
+NEED_SHA384=y
+OBJS += ../src/common/ptksa_cache.o
+OBJS += pasn_supplicant.o
+endif
+
 ifdef CONFIG_HS20
 OBJS += hs20_supplicant.o
 CFLAGS += -DCONFIG_HS20
@@ -1743,6 +1755,12 @@
 NEED_EXT_PASSWORD=y
 endif
 
+ifdef CONFIG_EXT_PASSWORD_FILE
+OBJS += ../src/utils/ext_password_file.o
+CFLAGS += -DCONFIG_EXT_PASSWORD_FILE
+NEED_EXT_PASSWORD=y
+endif
+
 ifdef NEED_EXT_PASSWORD
 OBJS += ../src/utils/ext_password.o
 CFLAGS += -DCONFIG_EXT_PASSWORD
@@ -1785,7 +1803,7 @@
 OBJS += ../src/drivers/driver_common.o
 OBJS_priv += ../src/drivers/driver_common.o
 
-OBJS += wpa_supplicant.o events.o blacklist.o wpas_glue.o scan.o
+OBJS += wpa_supplicant.o events.o bssid_ignore.o wpas_glue.o scan.o
 OBJS_t := $(OBJS) $(OBJS_l2) eapol_test.o
 OBJS_t += ../src/radius/radius_client.o
 OBJS_t += ../src/radius/radius.o
diff --git a/wpa_supplicant/README b/wpa_supplicant/README
index bbc86b1..391912e 100644
--- a/wpa_supplicant/README
+++ b/wpa_supplicant/README
@@ -383,7 +383,7 @@
 You will need to make a configuration file, e.g.,
 /etc/wpa_supplicant.conf, with network configuration for the networks
 you are going to use. Configuration file section below includes
-explanation fo the configuration file format and includes various
+explanation of the configuration file format and includes various
 examples. Once the configuration is ready, you can test whether the
 configuration work by first running wpa_supplicant with following
 command to start it on foreground with debugging enabled:
@@ -778,7 +778,7 @@
   disconnect = disconnect and wait for reassociate command before connecting
   scan = request new BSS scan
   scan_results = get latest scan results
-  get_capability <eap/pairwise/group/key_mgmt/proto/auth_alg> = get capabilies
+  get_capability <eap/pairwise/group/key_mgmt/proto/auth_alg> = get capabilities
   terminate = terminate wpa_supplicant
   quit = exit wpa_cli
 
diff --git a/wpa_supplicant/README-HS20 b/wpa_supplicant/README-HS20
index 3342871..484e4cb 100644
--- a/wpa_supplicant/README-HS20
+++ b/wpa_supplicant/README-HS20
@@ -78,7 +78,7 @@
 
 # Parameters for controlling scanning
 
-# Homogenous ESS identifier
+# Homogeneous ESS identifier
 # If this is set, scans will be used to request response only from BSSes
 # belonging to the specified Homogeneous ESS. This is used only if interworking
 # is enabled.
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index ac88a7d..cfefa48 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -44,6 +44,7 @@
 #endif /* CONFIG_WPS */
 
 
+#ifdef CONFIG_P2P
 static bool is_chanwidth160_supported(struct hostapd_hw_modes *mode,
 				      struct hostapd_config *conf)
 {
@@ -63,6 +64,7 @@
 		return true;
 	return false;
 }
+#endif /* CONFIG_P2P */
 
 
 static void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s,
@@ -264,6 +266,16 @@
 				wpa_printf(MSG_DEBUG,
 					   "HT secondary channel offset %d for P2P group",
 					   conf->secondary_channel);
+			} else if (ssid->p2p_group && conf->secondary_channel &&
+				   conf->hw_mode != HOSTAPD_MODE_IEEE80211A) {
+				/* This ended up trying to configure invalid
+				 * 2.4 GHz channels (e.g., HT40+ on channel 11)
+				 * in some cases, so clear the secondary channel
+				 * configuration now to avoid such cases that
+				 * would lead to group formation failures. */
+				wpa_printf(MSG_DEBUG,
+					   "Disable HT secondary channel for P2P group on 2.4 GHz");
+				conf->secondary_channel = 0;
 			}
 #endif /* CONFIG_P2P */
 
diff --git a/wpa_supplicant/blacklist.c b/wpa_supplicant/blacklist.c
deleted file mode 100644
index 2f32644..0000000
--- a/wpa_supplicant/blacklist.c
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * wpa_supplicant - Temporary BSSID blacklist
- * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#include "includes.h"
-
-#include "common.h"
-#include "wpa_supplicant_i.h"
-#include "blacklist.h"
-
-/**
- * wpa_blacklist_get - Get the blacklist entry for a BSSID
- * @wpa_s: Pointer to wpa_supplicant data
- * @bssid: BSSID
- * Returns: Matching blacklist entry for the BSSID or %NULL if not found
- */
-struct wpa_blacklist * wpa_blacklist_get(struct wpa_supplicant *wpa_s,
-					 const u8 *bssid)
-{
-	struct wpa_blacklist *e;
-
-	if (wpa_s == NULL || bssid == NULL)
-		return NULL;
-
-	if (wpa_s->current_ssid &&
-	    wpa_s->current_ssid->was_recently_reconfigured) {
-		wpa_blacklist_clear(wpa_s);
-		wpa_s->current_ssid->was_recently_reconfigured = false;
-		return NULL;
-	}
-
-	wpa_blacklist_update(wpa_s);
-
-	e = wpa_s->blacklist;
-	while (e) {
-		if (os_memcmp(e->bssid, bssid, ETH_ALEN) == 0)
-			return e;
-		e = e->next;
-	}
-
-	return NULL;
-}
-
-
-/**
- * wpa_blacklist_add - Add an BSSID to the blacklist
- * @wpa_s: Pointer to wpa_supplicant data
- * @bssid: BSSID to be added to the blacklist
- * Returns: Current blacklist count on success, -1 on failure
- *
- * This function adds the specified BSSID to the blacklist or increases the
- * blacklist count if the BSSID was already listed. It should be called when
- * an association attempt fails either due to the selected BSS rejecting
- * association or due to timeout.
- *
- * This blacklist is used to force %wpa_supplicant to go through all available
- * BSSes before retrying to associate with an BSS that rejected or timed out
- * association. It does not prevent the listed BSS from being used; it only
- * changes the order in which they are tried.
- */
-int wpa_blacklist_add(struct wpa_supplicant *wpa_s, const u8 *bssid)
-{
-	struct wpa_blacklist *e;
-	struct os_reltime now;
-
-	if (wpa_s == NULL || bssid == NULL)
-		return -1;
-
-	e = wpa_blacklist_get(wpa_s, bssid);
-	os_get_reltime(&now);
-	if (e) {
-		e->blacklist_start = now;
-		e->count++;
-		if (e->count > 5)
-			e->timeout_secs = 1800;
-		else if (e->count == 5)
-			e->timeout_secs = 600;
-		else if (e->count == 4)
-			e->timeout_secs = 120;
-		else if (e->count == 3)
-			e->timeout_secs = 60;
-		else
-			e->timeout_secs = 10;
-		wpa_printf(MSG_INFO, "BSSID " MACSTR
-			   " blacklist count incremented to %d, blacklisting for %d seconds",
-			   MAC2STR(bssid), e->count, e->timeout_secs);
-		return e->count;
-	}
-
-	e = os_zalloc(sizeof(*e));
-	if (e == NULL)
-		return -1;
-	os_memcpy(e->bssid, bssid, ETH_ALEN);
-	e->count = 1;
-	e->timeout_secs = 10;
-	e->blacklist_start = now;
-	e->next = wpa_s->blacklist;
-	wpa_s->blacklist = e;
-	wpa_printf(MSG_DEBUG, "Added BSSID " MACSTR
-		   " into blacklist, blacklisting for %d seconds",
-		   MAC2STR(bssid), e->timeout_secs);
-
-	return e->count;
-}
-
-
-/**
- * wpa_blacklist_del - Remove an BSSID from the blacklist
- * @wpa_s: Pointer to wpa_supplicant data
- * @bssid: BSSID to be removed from the blacklist
- * Returns: 0 on success, -1 on failure
- */
-int wpa_blacklist_del(struct wpa_supplicant *wpa_s, const u8 *bssid)
-{
-	struct wpa_blacklist *e, *prev = NULL;
-
-	if (wpa_s == NULL || bssid == NULL)
-		return -1;
-
-	e = wpa_s->blacklist;
-	while (e) {
-		if (os_memcmp(e->bssid, bssid, ETH_ALEN) == 0) {
-			if (prev == NULL) {
-				wpa_s->blacklist = e->next;
-			} else {
-				prev->next = e->next;
-			}
-			wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR " from "
-				   "blacklist", MAC2STR(bssid));
-			os_free(e);
-			return 0;
-		}
-		prev = e;
-		e = e->next;
-	}
-	return -1;
-}
-
-
-/**
- * wpa_blacklist_is_blacklisted - Check the blacklist status of a BSS
- * @wpa_s: Pointer to wpa_supplicant data
- * @bssid: BSSID to be checked
- * Returns: count if BSS is currently considered to be blacklisted, 0 otherwise
- */
-int wpa_blacklist_is_blacklisted(struct wpa_supplicant *wpa_s, const u8 *bssid)
-{
-	struct wpa_blacklist *e;
-	struct os_reltime now;
-
-	e = wpa_blacklist_get(wpa_s, bssid);
-	if (!e)
-		return 0;
-	os_get_reltime(&now);
-	if (os_reltime_expired(&now, &e->blacklist_start, e->timeout_secs))
-		return 0;
-	return e->count;
-}
-
-
-/**
- * wpa_blacklist_clear - Clear the blacklist of all entries
- * @wpa_s: Pointer to wpa_supplicant data
- */
-void wpa_blacklist_clear(struct wpa_supplicant *wpa_s)
-{
-	struct wpa_blacklist *e, *prev;
-
-	e = wpa_s->blacklist;
-	wpa_s->blacklist = NULL;
-	while (e) {
-		prev = e;
-		e = e->next;
-		wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR " from "
-			   "blacklist (clear)", MAC2STR(prev->bssid));
-		os_free(prev);
-	}
-}
-
-
-/**
- * wpa_blacklist_update - Update the entries in the blacklist,
- * deleting entries that have been expired for over an hour.
- * @wpa_s: Pointer to wpa_supplicant data
- */
-void wpa_blacklist_update(struct wpa_supplicant *wpa_s)
-{
-	struct wpa_blacklist *e, *prev = NULL;
-	struct os_reltime now;
-
-	if (!wpa_s)
-		return;
-
-	e = wpa_s->blacklist;
-	os_get_reltime(&now);
-	while (e) {
-		if (os_reltime_expired(&now, &e->blacklist_start,
-				       e->timeout_secs + 3600)) {
-			struct wpa_blacklist *to_delete = e;
-
-			if (prev) {
-				prev->next = e->next;
-				e = prev->next;
-			} else {
-				wpa_s->blacklist = e->next;
-				e = wpa_s->blacklist;
-			}
-			wpa_printf(MSG_INFO, "Removed BSSID " MACSTR
-				   " from blacklist (expired)",
-				   MAC2STR(to_delete->bssid));
-			os_free(to_delete);
-		} else {
-			prev = e;
-			e = e->next;
-		}
-	}
-}
diff --git a/wpa_supplicant/blacklist.h b/wpa_supplicant/blacklist.h
deleted file mode 100644
index a1c60d5..0000000
--- a/wpa_supplicant/blacklist.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * wpa_supplicant - Temporary BSSID blacklist
- * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#ifndef BLACKLIST_H
-#define BLACKLIST_H
-
-struct wpa_blacklist {
-	struct wpa_blacklist *next;
-	u8 bssid[ETH_ALEN];
-	int count;
-	/* Time of most recent blacklist event. */
-	struct os_reltime blacklist_start;
-	/*
-	 * Number of seconds after blacklist_start that the entry will be
-	 * considered blacklisted.
-	 */
-	int timeout_secs;
-};
-
-struct wpa_blacklist * wpa_blacklist_get(struct wpa_supplicant *wpa_s,
-					 const u8 *bssid);
-int wpa_blacklist_add(struct wpa_supplicant *wpa_s, const u8 *bssid);
-int wpa_blacklist_del(struct wpa_supplicant *wpa_s, const u8 *bssid);
-int wpa_blacklist_is_blacklisted(struct wpa_supplicant *wpa_s, const u8 *bssid);
-void wpa_blacklist_clear(struct wpa_supplicant *wpa_s);
-void wpa_blacklist_update(struct wpa_supplicant *wpa_s);
-
-#endif /* BLACKLIST_H */
diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c
index 127f43e..e13783c 100644
--- a/wpa_supplicant/bss.c
+++ b/wpa_supplicant/bss.c
@@ -19,18 +19,6 @@
 #include "scan.h"
 #include "bss.h"
 
-
-#define WPA_BSS_FREQ_CHANGED_FLAG	BIT(0)
-#define WPA_BSS_SIGNAL_CHANGED_FLAG	BIT(1)
-#define WPA_BSS_PRIVACY_CHANGED_FLAG	BIT(2)
-#define WPA_BSS_MODE_CHANGED_FLAG	BIT(3)
-#define WPA_BSS_WPAIE_CHANGED_FLAG	BIT(4)
-#define WPA_BSS_RSNIE_CHANGED_FLAG	BIT(5)
-#define WPA_BSS_WPS_CHANGED_FLAG	BIT(6)
-#define WPA_BSS_RATES_CHANGED_FLAG	BIT(7)
-#define WPA_BSS_IES_CHANGED_FLAG	BIT(8)
-
-
 static void wpa_bss_set_hessid(struct wpa_bss *bss)
 {
 #ifdef CONFIG_INTERWORKING
@@ -351,10 +339,31 @@
 }
 
 
+static bool is_p2p_pending_bss(struct wpa_supplicant *wpa_s,
+			       struct wpa_bss *bss)
+{
+#ifdef CONFIG_P2P
+	u8 addr[ETH_ALEN];
+
+	if (os_memcmp(bss->bssid, wpa_s->pending_join_iface_addr,
+		      ETH_ALEN) == 0)
+		return true;
+	if (!is_zero_ether_addr(wpa_s->pending_join_dev_addr) &&
+	    p2p_parse_dev_addr(wpa_bss_ie_ptr(bss), bss->ie_len, addr) == 0 &&
+	    os_memcmp(addr, wpa_s->pending_join_dev_addr, ETH_ALEN) == 0)
+		return true;
+#endif /* CONFIG_P2P */
+	return false;
+}
+
+
 static int wpa_bss_known(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
 {
 	struct wpa_ssid *ssid;
 
+	if (is_p2p_pending_bss(wpa_s, bss))
+		return 1;
+
 	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
 		if (ssid->ssid == NULL || ssid->ssid_len == 0)
 			continue;
@@ -443,7 +452,7 @@
 	bss->ssid_len = ssid_len;
 	bss->ie_len = res->ie_len;
 	bss->beacon_ie_len = res->beacon_ie_len;
-	os_memcpy(bss + 1, res + 1, res->ie_len + res->beacon_ie_len);
+	os_memcpy(bss->ies, res + 1, res->ie_len + res->beacon_ie_len);
 	wpa_bss_set_hessid(bss);
 
 	if (wpa_s->num_bss + 1 > wpa_s->conf->bss_max_count &&
@@ -546,7 +555,7 @@
 		changes |= WPA_BSS_MODE_CHANGED_FLAG;
 
 	if (old->ie_len == new_res->ie_len &&
-	    os_memcmp(old + 1, new_res + 1, old->ie_len) == 0)
+	    os_memcmp(wpa_bss_ie_ptr(old), new_res + 1, old->ie_len) == 0)
 		return changes;
 	changes |= WPA_BSS_IES_CHANGED_FLAG;
 
@@ -567,8 +576,8 @@
 }
 
 
-static void notify_bss_changes(struct wpa_supplicant *wpa_s, u32 changes,
-			       const struct wpa_bss *bss)
+void notify_bss_changes(struct wpa_supplicant *wpa_s, u32 changes,
+			const struct wpa_bss *bss)
 {
 	if (changes & WPA_BSS_FREQ_CHANGED_FLAG)
 		wpas_notify_bss_freq_changed(wpa_s, bss->id);
@@ -670,7 +679,7 @@
 #endif /* CONFIG_P2P */
 	if (bss->ie_len + bss->beacon_ie_len >=
 	    res->ie_len + res->beacon_ie_len) {
-		os_memcpy(bss + 1, res + 1, res->ie_len + res->beacon_ie_len);
+		os_memcpy(bss->ies, res + 1, res->ie_len + res->beacon_ie_len);
 		bss->ie_len = res->ie_len;
 		bss->beacon_ie_len = res->beacon_ie_len;
 	} else {
@@ -691,7 +700,7 @@
 				wpa_s->current_bss = nbss;
 			wpa_bss_update_pending_connect(wpa_s, bss, nbss);
 			bss = nbss;
-			os_memcpy(bss + 1, res + 1,
+			os_memcpy(bss->ies, res + 1,
 				  res->ie_len + res->beacon_ie_len);
 			bss->ie_len = res->ie_len;
 			bss->beacon_ie_len = res->beacon_ie_len;
@@ -1053,7 +1062,7 @@
 	struct wpa_bss *bss, *found = NULL;
 	dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss, list) {
 		u8 addr[ETH_ALEN];
-		if (p2p_parse_dev_addr((const u8 *) (bss + 1), bss->ie_len,
+		if (p2p_parse_dev_addr(wpa_bss_ie_ptr(bss), bss->ie_len,
 				       addr) != 0 ||
 		    os_memcmp(addr, dev_addr, ETH_ALEN) != 0)
 			continue;
@@ -1117,7 +1126,22 @@
  */
 const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie)
 {
-	return get_ie((const u8 *) (bss + 1), bss->ie_len, ie);
+	return get_ie(wpa_bss_ie_ptr(bss), bss->ie_len, ie);
+}
+
+
+/**
+ * wpa_bss_get_ie_ext - Fetch a specified extended IE from a BSS entry
+ * @bss: BSS table entry
+ * @ext: Information element extension identifier (WLAN_EID_EXT_*)
+ * Returns: Pointer to the information element (id field) or %NULL if not found
+ *
+ * This function returns the first matching information element in the BSS
+ * entry.
+ */
+const u8 * wpa_bss_get_ie_ext(const struct wpa_bss *bss, u8 ext)
+{
+	return get_ie_ext(wpa_bss_ie_ptr(bss), bss->ie_len, ext);
 }
 
 
@@ -1132,18 +1156,15 @@
  */
 const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type)
 {
-	const u8 *end, *pos;
+	const u8 *ies;
+	const struct element *elem;
 
-	pos = (const u8 *) (bss + 1);
-	end = pos + bss->ie_len;
+	ies = wpa_bss_ie_ptr(bss);
 
-	while (end - pos > 1) {
-		if (2 + pos[1] > end - pos)
-			break;
-		if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
-		    vendor_type == WPA_GET_BE32(&pos[2]))
-			return pos;
-		pos += 2 + pos[1];
+	for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, ies, bss->ie_len) {
+		if (elem->datalen >= 4 &&
+		    vendor_type == WPA_GET_BE32(elem->data))
+			return &elem->id;
 	}
 
 	return NULL;
@@ -1165,22 +1186,20 @@
 const u8 * wpa_bss_get_vendor_ie_beacon(const struct wpa_bss *bss,
 					u32 vendor_type)
 {
-	const u8 *end, *pos;
+	const u8 *ies;
+	const struct element *elem;
 
 	if (bss->beacon_ie_len == 0)
 		return NULL;
 
-	pos = (const u8 *) (bss + 1);
-	pos += bss->ie_len;
-	end = pos + bss->beacon_ie_len;
+	ies = wpa_bss_ie_ptr(bss);
+	ies += bss->ie_len;
 
-	while (end - pos > 1) {
-		if (2 + pos[1] > end - pos)
-			break;
-		if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
-		    vendor_type == WPA_GET_BE32(&pos[2]))
-			return pos;
-		pos += 2 + pos[1];
+	for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, ies,
+			    bss->beacon_ie_len) {
+		if (elem->datalen >= 4 &&
+		    vendor_type == WPA_GET_BE32(elem->data))
+			return &elem->id;
 	}
 
 	return NULL;
@@ -1207,16 +1226,21 @@
 	if (buf == NULL)
 		return NULL;
 
-	pos = (const u8 *) (bss + 1);
+	pos = wpa_bss_ie_ptr(bss);
 	end = pos + bss->ie_len;
 
 	while (end - pos > 1) {
-		if (2 + pos[1] > end - pos)
+		u8 ie, len;
+
+		ie = pos[0];
+		len = pos[1];
+		if (len > end - pos - 2)
 			break;
-		if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
-		    vendor_type == WPA_GET_BE32(&pos[2]))
-			wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4);
-		pos += 2 + pos[1];
+		pos += 2;
+		if (ie == WLAN_EID_VENDOR_SPECIFIC && len >= 4 &&
+		    vendor_type == WPA_GET_BE32(pos))
+			wpabuf_put_data(buf, pos + 4, len - 4);
+		pos += len;
 	}
 
 	if (wpabuf_len(buf) == 0) {
@@ -1251,7 +1275,7 @@
 	if (buf == NULL)
 		return NULL;
 
-	pos = (const u8 *) (bss + 1);
+	pos = wpa_bss_ie_ptr(bss);
 	pos += bss->ie_len;
 	end = pos + bss->beacon_ie_len;
 
@@ -1337,7 +1361,7 @@
 
 
 #ifdef CONFIG_FILS
-const u8 * wpa_bss_get_fils_cache_id(struct wpa_bss *bss)
+const u8 * wpa_bss_get_fils_cache_id(const struct wpa_bss *bss)
 {
 	const u8 *ie;
 
@@ -1354,6 +1378,8 @@
 
 int wpa_bss_ext_capab(const struct wpa_bss *bss, unsigned int capab)
 {
+	if (!bss)
+		return 0;
 	return ieee802_11_ext_capab(wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB),
 				    capab);
 }
diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h
index 0716761..4078b9b 100644
--- a/wpa_supplicant/bss.h
+++ b/wpa_supplicant/bss.h
@@ -20,9 +20,20 @@
 #define WPA_BSS_ANQP_FETCH_TRIED	BIT(6)
 #define WPA_BSS_OWE_TRANSITION		BIT(7)
 
+#define WPA_BSS_FREQ_CHANGED_FLAG	BIT(0)
+#define WPA_BSS_SIGNAL_CHANGED_FLAG	BIT(1)
+#define WPA_BSS_PRIVACY_CHANGED_FLAG	BIT(2)
+#define WPA_BSS_MODE_CHANGED_FLAG	BIT(3)
+#define WPA_BSS_WPAIE_CHANGED_FLAG	BIT(4)
+#define WPA_BSS_RSNIE_CHANGED_FLAG	BIT(5)
+#define WPA_BSS_WPS_CHANGED_FLAG	BIT(6)
+#define WPA_BSS_RATES_CHANGED_FLAG	BIT(7)
+#define WPA_BSS_IES_CHANGED_FLAG	BIT(8)
+
 struct wpa_bss_anqp_elem {
 	struct dl_list list;
 	u16 infoid;
+	bool protected_response; /* received in a protected GAS response */
 	struct wpabuf *payload;
 };
 
@@ -111,8 +122,16 @@
 	size_t beacon_ie_len;
 	/* followed by ie_len octets of IEs */
 	/* followed by beacon_ie_len octets of IEs */
+	u8 ies[];
 };
 
+static inline const u8 * wpa_bss_ie_ptr(const struct wpa_bss *bss)
+{
+	return bss->ies;
+}
+
+void notify_bss_changes(struct wpa_supplicant *wpa_s, u32 changes,
+			const struct wpa_bss *bss);
 void wpa_bss_update_start(struct wpa_supplicant *wpa_s);
 void wpa_bss_update_scan_res(struct wpa_supplicant *wpa_s,
 			     struct wpa_scan_res *res,
@@ -137,6 +156,7 @@
 struct wpa_bss * wpa_bss_get_id_range(struct wpa_supplicant *wpa_s,
 				      unsigned int idf, unsigned int idl);
 const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie);
+const u8 * wpa_bss_get_ie_ext(const struct wpa_bss *bss, u8 ext);
 const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type);
 const u8 * wpa_bss_get_vendor_ie_beacon(const struct wpa_bss *bss,
 					u32 vendor_type);
@@ -148,7 +168,7 @@
 int wpa_bss_get_bit_rates(const struct wpa_bss *bss, u8 **rates);
 struct wpa_bss_anqp * wpa_bss_anqp_alloc(void);
 int wpa_bss_anqp_unshare_alloc(struct wpa_bss *bss);
-const u8 * wpa_bss_get_fils_cache_id(struct wpa_bss *bss);
+const u8 * wpa_bss_get_fils_cache_id(const struct wpa_bss *bss);
 int wpa_bss_ext_capab(const struct wpa_bss *bss, unsigned int capab);
 
 static inline int bss_is_dmg(const struct wpa_bss *bss)
@@ -169,7 +189,7 @@
 
 static inline void wpa_bss_update_level(struct wpa_bss *bss, int new_level)
 {
-	if (bss != NULL && new_level < 0)
+	if (bss != NULL && new_level > -WPA_INVALID_NOISE && new_level < 0)
 		bss->level = new_level;
 }
 
diff --git a/wpa_supplicant/bssid_ignore.c b/wpa_supplicant/bssid_ignore.c
new file mode 100644
index 0000000..e378577
--- /dev/null
+++ b/wpa_supplicant/bssid_ignore.c
@@ -0,0 +1,221 @@
+/*
+ * wpa_supplicant - List of temporarily ignored BSSIDs
+ * Copyright (c) 2003-2021, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "wpa_supplicant_i.h"
+#include "bssid_ignore.h"
+
+/**
+ * wpa_bssid_ignore_get - Get the ignore list entry for a BSSID
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @bssid: BSSID
+ * Returns: Matching entry for the BSSID or %NULL if not found
+ */
+struct wpa_bssid_ignore * wpa_bssid_ignore_get(struct wpa_supplicant *wpa_s,
+					       const u8 *bssid)
+{
+	struct wpa_bssid_ignore *e;
+
+	if (wpa_s == NULL || bssid == NULL)
+		return NULL;
+
+	if (wpa_s->current_ssid &&
+	    wpa_s->current_ssid->was_recently_reconfigured) {
+		wpa_bssid_ignore_clear(wpa_s);
+		wpa_s->current_ssid->was_recently_reconfigured = false;
+		return NULL;
+	}
+
+	wpa_bssid_ignore_update(wpa_s);
+
+	e = wpa_s->bssid_ignore;
+	while (e) {
+		if (os_memcmp(e->bssid, bssid, ETH_ALEN) == 0)
+			return e;
+		e = e->next;
+	}
+
+	return NULL;
+}
+
+
+/**
+ * wpa_bssid_ignore_add - Add an BSSID to the ignore list
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @bssid: BSSID to be added to the ignore list
+ * Returns: Current ignore list count on success, -1 on failure
+ *
+ * This function adds the specified BSSID to the ignore list or increases the
+ * ignore count if the BSSID was already listed. It should be called when
+ * an association attempt fails either due to the selected BSS rejecting
+ * association or due to timeout.
+ *
+ * This ignore list is used to force %wpa_supplicant to go through all available
+ * BSSes before retrying to associate with an BSS that rejected or timed out
+ * association. It does not prevent the listed BSS from being used; it only
+ * changes the order in which they are tried.
+ */
+int wpa_bssid_ignore_add(struct wpa_supplicant *wpa_s, const u8 *bssid)
+{
+	struct wpa_bssid_ignore *e;
+	struct os_reltime now;
+
+	if (wpa_s == NULL || bssid == NULL)
+		return -1;
+
+	e = wpa_bssid_ignore_get(wpa_s, bssid);
+	os_get_reltime(&now);
+	if (e) {
+		e->start = now;
+		e->count++;
+		if (e->count > 5)
+			e->timeout_secs = 1800;
+		else if (e->count == 5)
+			e->timeout_secs = 600;
+		else if (e->count == 4)
+			e->timeout_secs = 120;
+		else if (e->count == 3)
+			e->timeout_secs = 60;
+		else
+			e->timeout_secs = 10;
+		wpa_printf(MSG_INFO, "BSSID " MACSTR
+			   " ignore list count incremented to %d, ignoring for %d seconds",
+			   MAC2STR(bssid), e->count, e->timeout_secs);
+		return e->count;
+	}
+
+	e = os_zalloc(sizeof(*e));
+	if (e == NULL)
+		return -1;
+	os_memcpy(e->bssid, bssid, ETH_ALEN);
+	e->count = 1;
+	e->timeout_secs = 10;
+	e->start = now;
+	e->next = wpa_s->bssid_ignore;
+	wpa_s->bssid_ignore = e;
+	wpa_printf(MSG_DEBUG, "Added BSSID " MACSTR
+		   " into ignore list, ignoring for %d seconds",
+		   MAC2STR(bssid), e->timeout_secs);
+
+	return e->count;
+}
+
+
+/**
+ * wpa_bssid_ignore_del - Remove an BSSID from the ignore list
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @bssid: BSSID to be removed from the ignore list
+ * Returns: 0 on success, -1 on failure
+ */
+int wpa_bssid_ignore_del(struct wpa_supplicant *wpa_s, const u8 *bssid)
+{
+	struct wpa_bssid_ignore *e, *prev = NULL;
+
+	if (wpa_s == NULL || bssid == NULL)
+		return -1;
+
+	e = wpa_s->bssid_ignore;
+	while (e) {
+		if (os_memcmp(e->bssid, bssid, ETH_ALEN) == 0) {
+			if (prev == NULL) {
+				wpa_s->bssid_ignore = e->next;
+			} else {
+				prev->next = e->next;
+			}
+			wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR
+				   " from ignore list", MAC2STR(bssid));
+			os_free(e);
+			return 0;
+		}
+		prev = e;
+		e = e->next;
+	}
+	return -1;
+}
+
+
+/**
+ * wpa_bssid_ignore_is_listed - Check whether a BSSID is ignored temporarily
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @bssid: BSSID to be checked
+ * Returns: count if BSS is currently considered to be ignored, 0 otherwise
+ */
+int wpa_bssid_ignore_is_listed(struct wpa_supplicant *wpa_s, const u8 *bssid)
+{
+	struct wpa_bssid_ignore *e;
+	struct os_reltime now;
+
+	e = wpa_bssid_ignore_get(wpa_s, bssid);
+	if (!e)
+		return 0;
+	os_get_reltime(&now);
+	if (os_reltime_expired(&now, &e->start, e->timeout_secs))
+		return 0;
+	return e->count;
+}
+
+
+/**
+ * wpa_bssid_ignore_clear - Clear the ignore list of all entries
+ * @wpa_s: Pointer to wpa_supplicant data
+ */
+void wpa_bssid_ignore_clear(struct wpa_supplicant *wpa_s)
+{
+	struct wpa_bssid_ignore *e, *prev;
+
+	e = wpa_s->bssid_ignore;
+	wpa_s->bssid_ignore = NULL;
+	while (e) {
+		prev = e;
+		e = e->next;
+		wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR
+			   " from ignore list (clear)", MAC2STR(prev->bssid));
+		os_free(prev);
+	}
+}
+
+
+/**
+ * wpa_bssid_ignore_update - Update the entries in the ignore list,
+ * deleting entries that have been expired for over an hour.
+ * @wpa_s: Pointer to wpa_supplicant data
+ */
+void wpa_bssid_ignore_update(struct wpa_supplicant *wpa_s)
+{
+	struct wpa_bssid_ignore *e, *prev = NULL;
+	struct os_reltime now;
+
+	if (!wpa_s)
+		return;
+
+	e = wpa_s->bssid_ignore;
+	os_get_reltime(&now);
+	while (e) {
+		if (os_reltime_expired(&now, &e->start,
+				       e->timeout_secs + 3600)) {
+			struct wpa_bssid_ignore *to_delete = e;
+
+			if (prev) {
+				prev->next = e->next;
+				e = prev->next;
+			} else {
+				wpa_s->bssid_ignore = e->next;
+				e = wpa_s->bssid_ignore;
+			}
+			wpa_printf(MSG_INFO, "Removed BSSID " MACSTR
+				   " from ignore list (expired)",
+				   MAC2STR(to_delete->bssid));
+			os_free(to_delete);
+		} else {
+			prev = e;
+			e = e->next;
+		}
+	}
+}
diff --git a/wpa_supplicant/bssid_ignore.h b/wpa_supplicant/bssid_ignore.h
new file mode 100644
index 0000000..721b0e1
--- /dev/null
+++ b/wpa_supplicant/bssid_ignore.h
@@ -0,0 +1,33 @@
+/*
+ * wpa_supplicant - List of temporarily ignored BSSIDs
+ * Copyright (c) 2003-2021, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef BSSID_IGNORE_H
+#define BSSID_IGNORE_H
+
+struct wpa_bssid_ignore {
+	struct wpa_bssid_ignore *next;
+	u8 bssid[ETH_ALEN];
+	int count;
+	/* Time of the most recent trigger to ignore this BSSID. */
+	struct os_reltime start;
+	/*
+	 * Number of seconds after start that the entey will be considered
+	 * valid.
+	 */
+	int timeout_secs;
+};
+
+struct wpa_bssid_ignore * wpa_bssid_ignore_get(struct wpa_supplicant *wpa_s,
+					 const u8 *bssid);
+int wpa_bssid_ignore_add(struct wpa_supplicant *wpa_s, const u8 *bssid);
+int wpa_bssid_ignore_del(struct wpa_supplicant *wpa_s, const u8 *bssid);
+int wpa_bssid_ignore_is_listed(struct wpa_supplicant *wpa_s, const u8 *bssid);
+void wpa_bssid_ignore_clear(struct wpa_supplicant *wpa_s);
+void wpa_bssid_ignore_update(struct wpa_supplicant *wpa_s);
+
+#endif /* BSSID_IGNORE_H */
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index 0d5b285..5901946 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -442,47 +442,99 @@
 #endif /* NO_CONFIG_WRITE */
 
 
+static int wpa_config_parse_bssid_ignore(const struct parse_data *data,
+					 struct wpa_ssid *ssid, int line,
+					 const char *value)
+{
+	return wpa_config_parse_addr_list(data, line, value,
+					  &ssid->bssid_ignore,
+					  &ssid->num_bssid_ignore,
+					  "bssid_ignore", 1, 1);
+}
+
+
+/* deprecated alias for bssid_ignore for backwards compatibility */
 static int wpa_config_parse_bssid_blacklist(const struct parse_data *data,
 					    struct wpa_ssid *ssid, int line,
 					    const char *value)
 {
 	return wpa_config_parse_addr_list(data, line, value,
-					  &ssid->bssid_blacklist,
-					  &ssid->num_bssid_blacklist,
-					  "bssid_blacklist", 1, 1);
+					  &ssid->bssid_ignore,
+					  &ssid->num_bssid_ignore,
+					  "bssid_ignore", 1, 1);
 }
 
 
 #ifndef NO_CONFIG_WRITE
+
+static char * wpa_config_write_bssid_ignore(const struct parse_data *data,
+					    struct wpa_ssid *ssid)
+{
+	return wpa_config_write_addr_list(data, ssid->bssid_ignore,
+					  ssid->num_bssid_ignore,
+					  "bssid_ignore");
+}
+
+
+/* deprecated alias for bssid_ignore for backwards compatibility */
 static char * wpa_config_write_bssid_blacklist(const struct parse_data *data,
 					       struct wpa_ssid *ssid)
 {
-	return wpa_config_write_addr_list(data, ssid->bssid_blacklist,
-					  ssid->num_bssid_blacklist,
-					  "bssid_blacklist");
+	return wpa_config_write_addr_list(data, ssid->bssid_ignore,
+					  ssid->num_bssid_ignore,
+					  "bssid_ignore");
 }
+
 #endif /* NO_CONFIG_WRITE */
 
 
+static int wpa_config_parse_bssid_accept(const struct parse_data *data,
+					 struct wpa_ssid *ssid, int line,
+					 const char *value)
+{
+	return wpa_config_parse_addr_list(data, line, value,
+					  &ssid->bssid_accept,
+					  &ssid->num_bssid_accept,
+					  "bssid_accept", 1, 1);
+}
+
+
+/* deprecated alias for bssid_accept for backwards compatibility */
 static int wpa_config_parse_bssid_whitelist(const struct parse_data *data,
 					    struct wpa_ssid *ssid, int line,
 					    const char *value)
 {
 	return wpa_config_parse_addr_list(data, line, value,
-					  &ssid->bssid_whitelist,
-					  &ssid->num_bssid_whitelist,
-					  "bssid_whitelist", 1, 1);
+					  &ssid->bssid_accept,
+					  &ssid->num_bssid_accept,
+					  "bssid_accept", 1, 1);
 }
 
 
 #ifndef NO_CONFIG_WRITE
+
+static char * wpa_config_write_bssid_accept(const struct parse_data *data,
+					    struct wpa_ssid *ssid)
+{
+	return wpa_config_write_addr_list(data, ssid->bssid_accept,
+					  ssid->num_bssid_accept,
+					  "bssid_accept");
+}
+
+
+/* deprecated alias for bssid_accept for backwards compatibility */
 static char * wpa_config_write_bssid_whitelist(const struct parse_data *data,
 					       struct wpa_ssid *ssid)
 {
-	return wpa_config_write_addr_list(data, ssid->bssid_whitelist,
-					  ssid->num_bssid_whitelist,
-					  "bssid_whitelist");
+	return wpa_config_write_addr_list(data, ssid->bssid_accept,
+					  ssid->num_bssid_accept,
+					  "bssid_accept");
 }
+
+#endif /* NO_CONFIG_WRITE */
+
+
+#ifndef NO_CONFIG_WRITE
 #endif /* NO_CONFIG_WRITE */
 
 
@@ -2362,8 +2414,10 @@
 	{ INT_RANGE(scan_ssid, 0, 1) },
 	{ FUNC(bssid) },
 	{ FUNC(bssid_hint) },
-	{ FUNC(bssid_blacklist) },
-	{ FUNC(bssid_whitelist) },
+	{ FUNC(bssid_ignore) },
+	{ FUNC(bssid_accept) },
+	{ FUNC(bssid_blacklist) }, /* deprecated alias for bssid_ignore */
+	{ FUNC(bssid_whitelist) }, /* deprecated alias for bssid_accept */
 	{ FUNC_KEY(psk) },
 	{ INT(mem_only_psk) },
 	{ STR_KEY(sae_password) },
@@ -2763,8 +2817,8 @@
 	os_free(ssid->freq_list);
 	os_free(ssid->bgscan);
 	os_free(ssid->p2p_client_list);
-	os_free(ssid->bssid_blacklist);
-	os_free(ssid->bssid_whitelist);
+	os_free(ssid->bssid_ignore);
+	os_free(ssid->bssid_accept);
 #ifdef CONFIG_HT_OVERRIDES
 	os_free(ssid->ht_mcs);
 #endif /* CONFIG_HT_OVERRIDES */
@@ -2890,6 +2944,7 @@
 	os_free(config->p2p_no_go_freq.range);
 	os_free(config->autoscan);
 	os_free(config->freq_list);
+	os_free(config->initial_freq_list);
 	wpabuf_free(config->wps_nfc_dh_pubkey);
 	wpabuf_free(config->wps_nfc_dh_privkey);
 	wpabuf_free(config->wps_nfc_dev_pw);
@@ -4308,6 +4363,7 @@
 	config->ap_isolate = DEFAULT_AP_ISOLATE;
 	config->access_network_type = DEFAULT_ACCESS_NETWORK_TYPE;
 	config->scan_cur_freq = DEFAULT_SCAN_CUR_FREQ;
+	config->scan_res_valid_for_connect = DEFAULT_SCAN_RES_VALID_FOR_CONNECT;
 	config->wmm_ac_params[0] = ac_be;
 	config->wmm_ac_params[1] = ac_bk;
 	config->wmm_ac_params[2] = ac_vi;
@@ -4470,9 +4526,7 @@
 		prev_len = 0;
 
 	/* No change to the previously configured value */
-	if ((!(*dst) && !pos) ||
-	    (*dst && pos && prev_len == len &&
-	     os_memcmp(*dst, pos, len) == 0))
+	if (*dst && prev_len == len && os_memcmp(*dst, pos, len) == 0)
 		return 1;
 
 	tmp = os_strdup(pos);
@@ -4550,6 +4604,26 @@
 }
 
 
+static int
+wpa_config_process_initial_freq_list(const struct global_parse_data *data,
+				     struct wpa_config *config, int line,
+				     const char *value)
+{
+	int *freqs;
+
+	freqs = wpa_config_parse_int_array(value);
+	if (!freqs)
+		return -1;
+	if (freqs[0] == 0) {
+		os_free(freqs);
+		freqs = NULL;
+	}
+	os_free(config->initial_freq_list);
+	config->initial_freq_list = freqs;
+	return 0;
+}
+
+
 #ifdef CONFIG_P2P
 static int wpa_global_config_parse_ipv4(const struct global_parse_data *data,
 					struct wpa_config *config, int line,
@@ -5084,7 +5158,9 @@
 	{ FUNC(ap_vendor_elements), 0 },
 	{ INT_RANGE(ignore_old_scan_res, 0, 1), 0 },
 	{ FUNC(freq_list), 0 },
+	{ FUNC(initial_freq_list), 0},
 	{ INT(scan_cur_freq), 0 },
+	{ INT(scan_res_valid_for_connect), 0},
 	{ INT(sched_scan_interval), 0 },
 	{ INT(sched_scan_start_delay), 0 },
 	{ INT(tdls_external_control), 0},
@@ -5130,6 +5206,12 @@
 	{ INT_RANGE(disable_btm, 0, 1), CFG_CHANGED_DISABLE_BTM },
 	{ INT_RANGE(extended_key_id, 0, 1), 0 },
 #endif /* CONFIG_WNM */
+	{ INT_RANGE(wowlan_disconnect_on_deinit, 0, 1), 0},
+#ifdef CONFIG_PASN
+#ifdef CONFIG_TESTING_OPTIONS
+	{ INT_RANGE(force_kdk_derivation, 0, 1), 0 },
+#endif /* CONFIG_TESTING_OPTIONS */
+#endif /* CONFIG_PASN */
 };
 
 #undef FUNC
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index 868a8b3..7e69343 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -46,6 +46,7 @@
 #define DEFAULT_OCE_SUPPORT OCE_STA
 #define DEFAULT_EXTENDED_KEY_ID 0
 #define DEFAULT_BTM_OFFLOAD 0
+#define DEFAULT_SCAN_RES_VALID_FOR_CONNECT 5
 
 #include "config_ssid.h"
 #include "wps/wps.h"
@@ -652,7 +653,7 @@
 	 * This variable control whether wpa_supplicant is allow to re-write
 	 * its configuration with wpa_config_write(). If this is zero,
 	 * configuration data is only changed in memory and the external data
-	 * is not overriden. If this is non-zero, wpa_supplicant will update
+	 * is not overridden. If this is non-zero, wpa_supplicant will update
 	 * the configuration data (e.g., a file) whenever configuration is
 	 * changed. This update may replace the old configuration which can
 	 * remove comments from it in case of a text file configuration.
@@ -919,6 +920,19 @@
 	int *freq_list;
 
 	/**
+	 * initial_freq_list - like freq_list but for initial scan
+	 *
+	 * This is an optional zero-terminated array of frequencies in
+	 * megahertz (MHz) to allow for narrowing scanning range when
+	 * the application is started.
+	 *
+	 * This can be used to speed up initial connection time if the
+	 * channel is known ahead of time, without limiting the scanned
+	 * frequencies during normal use.
+	 */
+	int *initial_freq_list;
+
+	/**
 	 * scan_cur_freq - Whether to scan only the current channel
 	 *
 	 * If true, attempt to scan only the current channel if any other
@@ -927,6 +941,15 @@
 	int scan_cur_freq;
 
 	/**
+	 * scan_res_valid_for_connect - Seconds scans are valid for association
+	 *
+	 * This configures the number of seconds old scan results are considered
+	 * valid for association. When scan results are older than this value
+	 * a new scan is triggered prior to the association.
+	 */
+	int scan_res_valid_for_connect;
+
+	/**
 	 * changed_parameters - Bitmap of changed parameters since last update
 	 */
 	unsigned int changed_parameters;
@@ -1551,9 +1574,31 @@
 	/**
 	 * p2p_device_random_mac_addr - P2P Device MAC address policy default
 	 *
-	 * 0 = use permanent MAC address
+	 * 0 = use permanent MAC address (the one set by default by the device
+	 *     driver). Notice that, if the device driver is configured to
+	 *     always use random MAC addresses, this flag breaks reinvoking a
+	 *     persistent group, so flags 1 or 2 should be used instead with
+	 *     such drivers if persistent groups are used.
 	 * 1 = use random MAC address on creating the interface if there is no
-	 * persistent groups.
+	 *     persistent group. Besides, if a persistent group is created,
+	 *     p2p_device_persistent_mac_addr is set to the MAC address of the
+	 *     P2P Device interface, so that this address will be subsequently
+	 *     used to change the MAC address of the P2P Device interface. With
+	 *     no persistent group, the random MAC address is created by
+	 *     wpa_supplicant, changing the one set by the device driver.
+	 *     The device driver shall support SIOCGIFFLAGS/SIOCSIFFLAGS ioctl
+	 *     interface control operations.
+	 * 2 = this flag should be used when the device driver uses random MAC
+	 *     addresses by default when a P2P Device interface is created.
+	 *     If p2p_device_persistent_mac_addr is set, use this MAC address
+	 *     on creating the P2P Device interface. If not set, use the
+	 *     default method adopted by the device driver (e.g., random MAC
+	 *     address). Besides, if a persistent group is created,
+	 *     p2p_device_persistent_mac_addr is set to the MAC address of the
+	 *     P2P Device interface, so that this address will be subsequently
+	 *     used in place of the default address set by the device driver.
+	 *     (This option does not need support of SIOCGIFFLAGS/SIOCSIFFLAGS
+	 *     ioctl interface control operations and uses NL80211_ATTR_MAC).
 	 *
 	 * By default, permanent MAC address is used.
 	 */
@@ -1604,6 +1649,25 @@
 	 * 1 = use Extended Key ID when possible
 	 */
 	int extended_key_id;
+
+	/**
+	 * wowlan_disconnect_on_deinit - Trigger disconnect on wpa_supplicant
+	 * interface deinit even if the driver has enabled WoWLAN.
+	 *
+	 * 0 = Do not disconnect
+	 * 1 = Trigger disconnection
+	 */
+	int wowlan_disconnect_on_deinit;
+
+#ifdef CONFIG_PASN
+#ifdef CONFIG_TESTING_OPTIONS
+	/*
+	 * Normally, KDK should be derived if and only if both sides support
+	 * secure LTF. Allow forcing KDK derivation for testing purposes.
+	 */
+	int force_kdk_derivation;
+#endif /* CONFIG_TESTING_OPTIONS */
+#endif /* CONFIG_PASN*/
 };
 
 
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index 74f91d3..9fbfbf9 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -23,105 +23,7 @@
 #include "p2p/p2p.h"
 #include "eap_peer/eap_methods.h"
 #include "eap_peer/eap.h"
-
-
-static int newline_terminated(const char *buf, size_t buflen)
-{
-	size_t len = os_strlen(buf);
-	if (len == 0)
-		return 0;
-	if (len == buflen - 1 && buf[buflen - 1] != '\r' &&
-	    buf[len - 1] != '\n')
-		return 0;
-	return 1;
-}
-
-
-static void skip_line_end(FILE *stream)
-{
-	char buf[100];
-	while (fgets(buf, sizeof(buf), stream)) {
-		buf[sizeof(buf) - 1] = '\0';
-		if (newline_terminated(buf, sizeof(buf)))
-			return;
-	}
-}
-
-
-/**
- * wpa_config_get_line - Read the next configuration file line
- * @s: Buffer for the line
- * @size: The buffer length
- * @stream: File stream to read from
- * @line: Pointer to a variable storing the file line number
- * @_pos: Buffer for the pointer to the beginning of data on the text line or
- * %NULL if not needed (returned value used instead)
- * Returns: Pointer to the beginning of data on the text line or %NULL if no
- * more text lines are available.
- *
- * This function reads the next non-empty line from the configuration file and
- * removes comments. The returned string is guaranteed to be null-terminated.
- */
-static char * wpa_config_get_line(char *s, int size, FILE *stream, int *line,
-				  char **_pos)
-{
-	char *pos, *end, *sstart;
-
-	while (fgets(s, size, stream)) {
-		(*line)++;
-		s[size - 1] = '\0';
-		if (!newline_terminated(s, size)) {
-			/*
-			 * The line was truncated - skip rest of it to avoid
-			 * confusing error messages.
-			 */
-			wpa_printf(MSG_INFO, "Long line in configuration file "
-				   "truncated");
-			skip_line_end(stream);
-		}
-		pos = s;
-
-		/* Skip white space from the beginning of line. */
-		while (*pos == ' ' || *pos == '\t' || *pos == '\r')
-			pos++;
-
-		/* Skip comment lines and empty lines */
-		if (*pos == '#' || *pos == '\n' || *pos == '\0')
-			continue;
-
-		/*
-		 * Remove # comments unless they are within a double quoted
-		 * string.
-		 */
-		sstart = os_strchr(pos, '"');
-		if (sstart)
-			sstart = os_strrchr(sstart + 1, '"');
-		if (!sstart)
-			sstart = pos;
-		end = os_strchr(sstart, '#');
-		if (end)
-			*end-- = '\0';
-		else
-			end = pos + os_strlen(pos) - 1;
-
-		/* Remove trailing white space. */
-		while (end > pos &&
-		       (*end == '\n' || *end == ' ' || *end == '\t' ||
-			*end == '\r'))
-			*end-- = '\0';
-
-		if (*pos == '\0')
-			continue;
-
-		if (_pos)
-			*_pos = pos;
-		return pos;
-	}
-
-	if (_pos)
-		*_pos = NULL;
-	return NULL;
-}
+#include "utils/config.h"
 
 
 static int wpa_config_validate_network(struct wpa_ssid *ssid, int line)
@@ -767,8 +669,8 @@
 	INT(scan_ssid);
 	write_bssid(f, ssid);
 	write_bssid_hint(f, ssid);
-	write_str(f, "bssid_blacklist", ssid);
-	write_str(f, "bssid_whitelist", ssid);
+	write_str(f, "bssid_ignore", ssid);
+	write_str(f, "bssid_accept", ssid);
 	write_psk(f, ssid);
 	INT(mem_only_psk);
 	STR(sae_password);
@@ -1475,9 +1377,23 @@
 		}
 		fprintf(f, "\n");
 	}
+	if (config->initial_freq_list && config->initial_freq_list[0]) {
+		int i;
+		fprintf(f, "initial_freq_list=");
+		for (i = 0; config->initial_freq_list[i]; i++) {
+			fprintf(f, "%s%d", i > 0 ? " " : "",
+				config->initial_freq_list[i]);
+		}
+		fprintf(f, "\n");
+	}
 	if (config->scan_cur_freq != DEFAULT_SCAN_CUR_FREQ)
 		fprintf(f, "scan_cur_freq=%d\n", config->scan_cur_freq);
 
+	if (config->scan_res_valid_for_connect !=
+	    DEFAULT_SCAN_RES_VALID_FOR_CONNECT)
+		fprintf(f, "scan_res_valid_for_connect=%d\n",
+			config->scan_res_valid_for_connect);
+
 	if (config->sched_scan_interval)
 		fprintf(f, "sched_scan_interval=%u\n",
 			config->sched_scan_interval);
@@ -1614,6 +1530,9 @@
 	if (config->extended_key_id != DEFAULT_EXTENDED_KEY_ID)
 		fprintf(f, "extended_key_id=%d\n",
 			config->extended_key_id);
+	if (config->wowlan_disconnect_on_deinit)
+		fprintf(f, "wowlan_disconnect_on_deinit=%d\n",
+			config->wowlan_disconnect_on_deinit);
 }
 
 #endif /* CONFIG_NO_CONFIG_WRITE */
diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h
index ecf258c..d1ff5f8 100644
--- a/wpa_supplicant/config_ssid.h
+++ b/wpa_supplicant/config_ssid.h
@@ -152,16 +152,16 @@
 	u8 bssid[ETH_ALEN];
 
 	/**
-	 * bssid_blacklist - List of inacceptable BSSIDs
+	 * bssid_ignore - List of inacceptable BSSIDs
 	 */
-	u8 *bssid_blacklist;
-	size_t num_bssid_blacklist;
+	u8 *bssid_ignore;
+	size_t num_bssid_ignore;
 
 	/**
-	 * bssid_blacklist - List of acceptable BSSIDs
+	 * bssid_accept - List of acceptable BSSIDs
 	 */
-	u8 *bssid_whitelist;
-	size_t num_bssid_whitelist;
+	u8 *bssid_accept;
+	size_t num_bssid_accept;
 
 	/**
 	 * bssid_set - Whether BSSID is configured for this network
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index f5c6587..0d4c2bc 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -22,6 +22,7 @@
 #ifdef CONFIG_DPP
 #include "common/dpp.h"
 #endif /* CONFIG_DPP */
+#include "common/ptksa_cache.h"
 #include "crypto/tls.h"
 #include "ap/hostapd.h"
 #include "eap_peer/eap.h"
@@ -48,7 +49,7 @@
 #include "scan.h"
 #include "ctrl_iface.h"
 #include "interworking.h"
-#include "blacklist.h"
+#include "bssid_ignore.h"
 #include "autoscan.h"
 #include "wnm_sta.h"
 #include "offchannel.h"
@@ -299,20 +300,30 @@
 }
 
 
-static int wpas_ctrl_set_band(struct wpa_supplicant *wpa_s, char *band)
+static int wpas_ctrl_set_band(struct wpa_supplicant *wpa_s, char *bands)
 {
 	union wpa_event_data event;
+	u32 setband_mask = WPA_SETBAND_AUTO;
 
-	if (os_strcmp(band, "AUTO") == 0)
-		wpa_s->setband = WPA_SETBAND_AUTO;
-	else if (os_strcmp(band, "5G") == 0)
-		wpa_s->setband = WPA_SETBAND_5G;
-	else if (os_strcmp(band, "2G") == 0)
-		wpa_s->setband = WPA_SETBAND_2G;
-	else
-		return -1;
+	/*
+	 * For example:
+	 *  SET setband 2G,6G
+	 *  SET setband 5G
+	 *  SET setband AUTO
+	 */
+	if (!os_strstr(bands, "AUTO")) {
+		if (os_strstr(bands, "5G"))
+			setband_mask |= WPA_SETBAND_5G;
+		if (os_strstr(bands, "6G"))
+			setband_mask |= WPA_SETBAND_6G;
+		if (os_strstr(bands, "2G"))
+			setband_mask |= WPA_SETBAND_2G;
+		if (setband_mask == WPA_SETBAND_AUTO)
+			return -1;
+	}
 
-	if (wpa_drv_setband(wpa_s, wpa_s->setband) == 0) {
+	wpa_s->setband_mask = setband_mask;
+	if (wpa_drv_setband(wpa_s, wpa_s->setband_mask) == 0) {
 		os_memset(&event, 0, sizeof(event));
 		event.channel_list_changed.initiator = REGDOM_SET_BY_USER;
 		event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN;
@@ -2543,20 +2554,20 @@
 }
 
 
-static int wpa_supplicant_ctrl_iface_blacklist(struct wpa_supplicant *wpa_s,
-					       char *cmd, char *buf,
-					       size_t buflen)
+static int wpa_supplicant_ctrl_iface_bssid_ignore(struct wpa_supplicant *wpa_s,
+						  char *cmd, char *buf,
+						  size_t buflen)
 {
 	u8 bssid[ETH_ALEN];
-	struct wpa_blacklist *e;
+	struct wpa_bssid_ignore *e;
 	char *pos, *end;
 	int ret;
 
-	/* cmd: "BLACKLIST [<BSSID>]" */
+	/* cmd: "BSSID_IGNORE [<BSSID>]" */
 	if (*cmd == '\0') {
 		pos = buf;
 		end = buf + buflen;
-		e = wpa_s->blacklist;
+		e = wpa_s->bssid_ignore;
 		while (e) {
 			ret = os_snprintf(pos, end - pos, MACSTR "\n",
 					  MAC2STR(e->bssid));
@@ -2570,12 +2581,12 @@
 
 	cmd++;
 	if (os_strncmp(cmd, "clear", 5) == 0) {
-		wpa_blacklist_clear(wpa_s);
+		wpa_bssid_ignore_clear(wpa_s);
 		os_memcpy(buf, "OK\n", 3);
 		return 3;
 	}
 
-	wpa_printf(MSG_DEBUG, "CTRL_IFACE: BLACKLIST bssid='%s'", cmd);
+	wpa_printf(MSG_DEBUG, "CTRL_IFACE: BSSID_IGNORE bssid='%s'", cmd);
 	if (hwaddr_aton(cmd, bssid)) {
 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: invalid BSSID '%s'", cmd);
 		return -1;
@@ -2585,10 +2596,10 @@
 	 * Add the BSSID twice, so its count will be 2, causing it to be
 	 * skipped when processing scan results.
 	 */
-	ret = wpa_blacklist_add(wpa_s, bssid);
+	ret = wpa_bssid_ignore_add(wpa_s, bssid);
 	if (ret < 0)
 		return -1;
-	ret = wpa_blacklist_add(wpa_s, bssid);
+	ret = wpa_bssid_ignore_add(wpa_s, bssid);
 	if (ret < 0)
 		return -1;
 	os_memcpy(buf, "OK\n", 3);
@@ -3030,8 +3041,7 @@
 	if (bss_is_dmg(bss)) {
 		const char *s;
 
-		if (get_ie_ext((const u8 *) (bss + 1), bss->ie_len,
-			       WLAN_EID_EXT_EDMG_OPERATION)) {
+		if (wpa_bss_get_ie_ext(bss, WLAN_EID_EXT_EDMG_OPERATION)) {
 			ret = os_snprintf(pos, end - pos, "[EDMG]");
 			if (os_snprintf_error(end - pos, ret))
 				return -1;
@@ -4489,6 +4499,15 @@
 #endif /* CONFIG_FILS_SK_PFS */
 #endif /* CONFIG_FILS */
 
+#ifdef CONFIG_PASN
+	ret = os_snprintf(pos, end - pos, "%sPASN",
+			  pos == buf ? "" : " ");
+	if (os_snprintf_error(end - pos, ret))
+		return pos - buf;
+	pos += ret;
+
+#endif /* CONFIG_PASN */
+
 	return pos - buf;
 }
 
@@ -4814,6 +4833,31 @@
 	}
 #endif /* CONFIG_SAE */
 
+#ifdef CONFIG_OCV
+	if (os_strcmp(field, "ocv") == 0) {
+		if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
+		    (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OCV))
+			res = os_snprintf(buf, buflen, "supported");
+		else
+			res = os_snprintf(buf, buflen, "not supported");
+		if (os_snprintf_error(buflen, res))
+			return -1;
+		return res;
+	}
+#endif /* CONFIG_OCV */
+
+	if (os_strcmp(field, "beacon_prot") == 0) {
+		if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_BEACON_PROTECTION) ||
+		    (wpa_s->drv_flags2 &
+		     WPA_DRIVER_FLAGS2_BEACON_PROTECTION_CLIENT))
+			res = os_snprintf(buf, buflen, "supported");
+		else
+			res = os_snprintf(buf, buflen, "not supported");
+		if (os_snprintf_error(buflen, res))
+			return -1;
+		return res;
+	}
+
 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
 		   field);
 
@@ -5023,7 +5067,7 @@
 			return 0;
 		pos += ret;
 
-		ie = (const u8 *) (bss + 1);
+		ie = wpa_bss_ie_ptr(bss);
 		for (i = 0; i < bss->ie_len; i++) {
 			ret = os_snprintf(pos, end - pos, "%02x", *ie++);
 			if (os_snprintf_error(end - pos, ret))
@@ -5190,7 +5234,7 @@
 
 #ifdef CONFIG_WPS
 	if (mask & WPA_BSS_MASK_WPS_SCAN) {
-		ie = (const u8 *) (bss + 1);
+		ie = wpa_bss_ie_ptr(bss);
 		ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end);
 		if (ret >= end - pos)
 			return 0;
@@ -5201,7 +5245,7 @@
 
 #ifdef CONFIG_P2P
 	if (mask & WPA_BSS_MASK_P2P_SCAN) {
-		ie = (const u8 *) (bss + 1);
+		ie = wpa_bss_ie_ptr(bss);
 		ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end);
 		if (ret >= end - pos)
 			return 0;
@@ -5213,7 +5257,8 @@
 #ifdef CONFIG_WIFI_DISPLAY
 	if (mask & WPA_BSS_MASK_WIFI_DISPLAY) {
 		struct wpabuf *wfd;
-		ie = (const u8 *) (bss + 1);
+
+		ie = wpa_bss_ie_ptr(bss);
 		wfd = ieee802_11_vendor_ie_concat(ie, bss->ie_len,
 						  WFD_IE_VENDOR_TYPE);
 		if (wfd) {
@@ -5285,13 +5330,21 @@
 			os_snprintf(title, sizeof(title), "anqp[%u]",
 				    elem->infoid);
 			pos = anqp_add_hex(pos, end, title, elem->payload);
+			if (elem->protected_response) {
+				ret = os_snprintf(pos, end - pos,
+						  "protected-anqp-info[%u]=1\n",
+						  elem->infoid);
+				if (os_snprintf_error(end - pos, ret))
+					return 0;
+				pos += ret;
+			}
 		}
 	}
 #endif /* CONFIG_INTERWORKING */
 
 #ifdef CONFIG_MESH
 	if (mask & WPA_BSS_MASK_MESH_SCAN) {
-		ie = (const u8 *) (bss + 1);
+		ie = wpa_bss_ie_ptr(bss);
 		ret = wpas_mesh_scan_result_text(ie, bss->ie_len, pos, end);
 		if (ret >= end - pos)
 			return 0;
@@ -5338,7 +5391,7 @@
 			return 0;
 		pos += ret;
 
-		ie = (const u8 *) (bss + 1);
+		ie = wpa_bss_ie_ptr(bss);
 		ie += bss->ie_len;
 		for (i = 0; i < bss->beacon_ie_len; i++) {
 			ret = os_snprintf(pos, end - pos, "%02x", *ie++);
@@ -8236,13 +8289,17 @@
 				     char *buf, size_t buflen)
 {
 	int ret;
-	char *pos;
+	char *pos, *temp = NULL;
 	u8 *data = NULL;
 	unsigned int vendor_id, subcmd;
+	enum nested_attr nested_attr_flag = NESTED_ATTR_UNSPECIFIED;
 	struct wpabuf *reply;
 	size_t data_len = 0;
 
-	/* cmd: <vendor id> <subcommand id> [<hex formatted data>] */
+	/**
+	 * cmd: <vendor id> <subcommand id> [<hex formatted data>]
+	 * [nested=<0|1>]
+	 */
 	vendor_id = strtoul(cmd, &pos, 16);
 	if (!isblank((unsigned char) *pos))
 		return -EINVAL;
@@ -8252,7 +8309,9 @@
 	if (*pos != '\0') {
 		if (!isblank((unsigned char) *pos++))
 			return -EINVAL;
-		data_len = os_strlen(pos);
+
+		temp = os_strchr(pos, ' ');
+		data_len = temp ? (size_t) (temp - pos) : os_strlen(pos);
 	}
 
 	if (data_len) {
@@ -8269,6 +8328,11 @@
 		}
 	}
 
+	pos = os_strstr(cmd, "nested=");
+	if (pos)
+		nested_attr_flag = atoi(pos + 7) ? NESTED_ATTR_USED :
+			NESTED_ATTR_NOT_USED;
+
 	reply = wpabuf_alloc((buflen - 1) / 2);
 	if (!reply) {
 		os_free(data);
@@ -8276,7 +8340,7 @@
 	}
 
 	ret = wpa_drv_vendor_cmd(wpa_s, vendor_id, subcmd, data, data_len,
-				 reply);
+				 nested_attr_flag, reply);
 
 	if (ret == 0)
 		ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply),
@@ -8395,13 +8459,14 @@
 	wpa_s->consecutive_conn_failures = 0;
 
 	wpa_drv_radio_disable(wpa_s, 0);
-	wpa_blacklist_clear(wpa_s);
+	wpa_bssid_ignore_clear(wpa_s);
 	wpa_supplicant_ctrl_iface_remove_network(wpa_s, "all");
 	wpa_supplicant_ctrl_iface_remove_cred(wpa_s, "all");
 	wpa_config_flush_blobs(wpa_s->conf);
 	wpa_s->conf->auto_interworking = 0;
 	wpa_s->conf->okc = 0;
 
+	ptksa_cache_flush(wpa_s->ptksa, NULL, WPA_CIPHER_NONE);
 	wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
 	rsn_preauth_deinit(wpa_s->wpa);
 
@@ -8502,6 +8567,13 @@
 	free_bss_tmp_disallowed(wpa_s);
 
 	os_memset(&wpa_s->robust_av, 0, sizeof(struct robust_av_data));
+
+#ifdef CONFIG_PASN
+	wpas_pasn_auth_stop(wpa_s);
+#endif /* CONFIG_PASN */
+
+	if (wpa_s->mac_addr_changed && wpa_s->conf->mac_addr == 0)
+		wpas_restore_permanent_mac_addr(wpa_s);
 }
 
 
@@ -9755,8 +9827,7 @@
 
 	if (wpa_s->vendor_elem[frame] == NULL) {
 		wpa_s->vendor_elem[frame] = buf;
-		wpas_vendor_elem_update(wpa_s);
-		return 0;
+		goto update_ies;
 	}
 
 	if (wpabuf_resize(&wpa_s->vendor_elem[frame], len) < 0) {
@@ -9766,8 +9837,14 @@
 
 	wpabuf_put_buf(wpa_s->vendor_elem[frame], buf);
 	wpabuf_free(buf);
+
+update_ies:
 	wpas_vendor_elem_update(wpa_s);
 
+	if (frame == VENDOR_ELEM_PROBE_REQ ||
+	    frame == VENDOR_ELEM_PROBE_REQ_P2P)
+		wpa_supplicant_set_default_scan_ies(wpa_s);
+
 	return 0;
 }
 
@@ -10074,6 +10151,7 @@
 
 static void wpas_ctrl_iface_pmksa_flush(struct wpa_supplicant *wpa_s)
 {
+	ptksa_cache_flush(wpa_s->ptksa, NULL, WPA_CIPHER_NONE);
 	wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
 #ifdef CONFIG_AP
 	wpas_ap_pmksa_cache_flush(wpa_s);
@@ -10278,7 +10356,7 @@
 					  char *cmd)
 {
 	/*
-	 * We do not check mesh interface existance because PMKSA should be
+	 * We do not check mesh interface existence because PMKSA should be
 	 * stored before wpa_s->ifmsh creation to suppress commit message
 	 * creation.
 	 */
@@ -10406,6 +10484,73 @@
 }
 
 
+#ifdef CONFIG_PASN
+static int wpas_ctrl_iface_pasn_start(struct wpa_supplicant *wpa_s, char *cmd)
+{
+	char *token, *context = NULL;
+	u8 bssid[ETH_ALEN];
+	int akmp = -1, cipher = -1, got_bssid = 0;
+	u16 group = 0xFFFF;
+	int id = 0;
+
+	/*
+	 * Entry format: bssid=<BSSID> akmp=<AKMP> cipher=<CIPHER> group=<group>
+	 */
+	while ((token = str_token(cmd, " ", &context))) {
+		if (os_strncmp(token, "bssid=", 6) == 0) {
+			if (hwaddr_aton(token + 6, bssid))
+				return -1;
+			got_bssid = 1;
+		} else if (os_strcmp(token, "akmp=PASN") == 0) {
+			akmp = WPA_KEY_MGMT_PASN;
+#ifdef CONFIG_IEEE80211R
+		} else if (os_strcmp(token, "akmp=FT-PSK") == 0) {
+			akmp = WPA_KEY_MGMT_FT_PSK;
+		} else if (os_strcmp(token, "akmp=FT-EAP-SHA384") == 0) {
+			akmp = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
+		} else if (os_strcmp(token, "akmp=FT-EAP") == 0) {
+			akmp = WPA_KEY_MGMT_FT_IEEE8021X;
+#endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_SAE
+		} else if (os_strcmp(token, "akmp=SAE") == 0) {
+			akmp = WPA_KEY_MGMT_SAE;
+#endif /* CONFIG_SAE */
+#ifdef CONFIG_FILS
+		} else if (os_strcmp(token, "akmp=FILS-SHA256") == 0) {
+			akmp = WPA_KEY_MGMT_FILS_SHA256;
+		} else if (os_strcmp(token, "akmp=FILS-SHA384") == 0) {
+			akmp = WPA_KEY_MGMT_FILS_SHA384;
+#endif /* CONFIG_FILS */
+		} else if (os_strcmp(token, "cipher=CCMP-256") == 0) {
+			cipher = WPA_CIPHER_CCMP_256;
+		} else if (os_strcmp(token, "cipher=GCMP-256") == 0) {
+			cipher = WPA_CIPHER_GCMP_256;
+		} else if (os_strcmp(token, "cipher=CCMP") == 0) {
+			cipher = WPA_CIPHER_CCMP;
+		} else if (os_strcmp(token, "cipher=GCMP") == 0) {
+			cipher = WPA_CIPHER_GCMP;
+		} else if (os_strncmp(token, "group=", 6) == 0) {
+			group = atoi(token + 6);
+		} else if (os_strncmp(token, "nid=", 4) == 0) {
+			id = atoi(token + 4);
+		} else {
+			wpa_printf(MSG_DEBUG,
+				   "CTRL: PASN Invalid parameter: '%s'",
+				   token);
+			return -1;
+		}
+	}
+
+	if (!got_bssid || akmp == -1 || cipher == -1 || group == 0xFFFF) {
+		wpa_printf(MSG_DEBUG,"CTRL: PASN missing parameter");
+		return -1;
+	}
+
+	return wpas_pasn_auth_start(wpa_s, bssid, akmp, cipher, group, id);
+}
+#endif /* CONFIG_PASN */
+
+
 char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
 					 char *buf, size_t *resp_len)
 {
@@ -10864,8 +11009,12 @@
 	} else if (os_strncmp(buf, "BSSID ", 6) == 0) {
 		if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
 			reply_len = -1;
+	} else if (os_strncmp(buf, "BSSID_IGNORE", 12) == 0) {
+		reply_len = wpa_supplicant_ctrl_iface_bssid_ignore(
+			wpa_s, buf + 12, reply, reply_size);
 	} else if (os_strncmp(buf, "BLACKLIST", 9) == 0) {
-		reply_len = wpa_supplicant_ctrl_iface_blacklist(
+		/* deprecated backwards compatibility alias for BSSID_IGNORE */
+		reply_len = wpa_supplicant_ctrl_iface_bssid_ignore(
 			wpa_s, buf + 9, reply, reply_size);
 	} else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
 		reply_len = wpa_supplicant_ctrl_iface_log_level(
@@ -11300,6 +11449,15 @@
 	} else if (os_strncmp(buf, "MSCS ", 5) == 0) {
 		if (wpas_ctrl_iface_configure_mscs(wpa_s, buf + 5))
 			reply_len = -1;
+#ifdef CONFIG_PASN
+	} else if (os_strncmp(buf, "PASN_START ", 11) == 0) {
+		if (wpas_ctrl_iface_pasn_start(wpa_s, buf + 11) < 0)
+			reply_len = -1;
+	} else if (os_strcmp(buf, "PASN_STOP") == 0) {
+		wpas_pasn_auth_stop(wpa_s);
+	} else if (os_strcmp(buf, "PTKSA_CACHE_LIST") == 0) {
+		reply_len = ptksa_cache_list(wpa_s->ptksa, reply, reply_size);
+#endif /* CONFIG_PASN */
 	} else {
 		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
 		reply_len = 16;
diff --git a/wpa_supplicant/dbus/dbus_common.c b/wpa_supplicant/dbus/dbus_common.c
index efa6c7b..a727217 100644
--- a/wpa_supplicant/dbus/dbus_common.c
+++ b/wpa_supplicant/dbus/dbus_common.c
@@ -108,17 +108,18 @@
 	flags = dbus_watch_get_flags(watch);
 	fd = dbus_watch_get_unix_fd(watch);
 
-	eloop_register_sock(fd, EVENT_TYPE_EXCEPTION, process_watch_exception,
-			    priv, watch);
+	if (eloop_register_sock(fd, EVENT_TYPE_EXCEPTION,
+				process_watch_exception, priv, watch) < 0)
+		return FALSE;
 
-	if (flags & DBUS_WATCH_READABLE) {
-		eloop_register_sock(fd, EVENT_TYPE_READ, process_watch_read,
-				    priv, watch);
-	}
-	if (flags & DBUS_WATCH_WRITABLE) {
-		eloop_register_sock(fd, EVENT_TYPE_WRITE, process_watch_write,
-				    priv, watch);
-	}
+	if ((flags & DBUS_WATCH_READABLE) &&
+	    eloop_register_sock(fd, EVENT_TYPE_READ, process_watch_read,
+				priv, watch) < 0)
+		return FALSE;
+	if ((flags & DBUS_WATCH_WRITABLE) &&
+	    eloop_register_sock(fd, EVENT_TYPE_WRITE, process_watch_write,
+				priv, watch) < 0)
+		return FALSE;
 
 	dbus_watch_set_data(watch, priv, NULL);
 
diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c
index 6dcd948..2c01943 100644
--- a/wpa_supplicant/dbus/dbus_new.c
+++ b/wpa_supplicant/dbus/dbus_new.c
@@ -1824,7 +1824,7 @@
  * @sa: station addr (p2p i/f) of the peer
  * @dialog_token: service discovery request dialog token
  * @update_indic: service discovery request update indicator
- * @tlvs: service discovery request genrated byte array of tlvs
+ * @tlvs: service discovery request generated byte array of tlvs
  * @tlvs_len: service discovery request tlvs length
  */
 void wpas_dbus_signal_p2p_sd_request(struct wpa_supplicant *wpa_s,
@@ -1893,7 +1893,7 @@
  * @wpa_s: %wpa_supplicant network interface data
  * @sa: station addr (p2p i/f) of the peer
  * @update_indic: service discovery request update indicator
- * @tlvs: service discovery request genrated byte array of tlvs
+ * @tlvs: service discovery request generated byte array of tlvs
  * @tlvs_len: service discovery request tlvs length
  */
 void wpas_dbus_signal_p2p_sd_response(struct wpa_supplicant *wpa_s,
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c
index 86f8560..7d20f21 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers.c
@@ -138,7 +138,9 @@
 static const char * const dont_quote[] = {
 	"key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap",
 	"bssid", "scan_freq", "freq_list", "scan_ssid", "bssid_hint",
-	"bssid_blacklist", "bssid_whitelist", "group_mgmt",
+	"bssid_ignore", "bssid_accept", /* deprecated aliases */
+	"bssid_blacklist", "bssid_whitelist",
+	"group_mgmt",
 	"ignore_broadcast_ssid",
 #ifdef CONFIG_MESH
 	"mesh_basic_rates",
@@ -1011,7 +1013,7 @@
 	const struct wpa_dbus_property_desc *property_desc,
 	DBusMessageIter *iter, DBusError *error, void *user_data)
 {
-	const char *capabilities[12];
+	const char *capabilities[13];
 	size_t num_items = 0;
 	struct wpa_global *global = user_data;
 	struct wpa_supplicant *wpa_s;
@@ -1062,6 +1064,9 @@
 #ifdef CONFIG_OWE
 	capabilities[num_items++] = "owe";
 #endif /* CONFIG_OWE */
+#ifdef CONFIG_SUITEB192
+	capabilities[num_items++] = "suiteb192";
+#endif /* CONFIG_SUITEB192 */
 	if (ext_key_id_supported)
 		capabilities[num_items++] = "extended_key_id";
 
@@ -1697,7 +1702,8 @@
  * Returns: NULL
  *
  * Handler function for notifying system there will be a expected disconnect.
- * This will prevent wpa_supplicant from adding blacklists upon next disconnect..
+ * This will prevent wpa_supplicant from adding the BSSID to the ignore list
+ * upon next disconnect.
  */
 DBusMessage * wpas_dbus_handler_expect_disconnect(DBusMessage *message,
 						  struct wpa_global *global)
@@ -2568,7 +2574,7 @@
  * wpas_dbus_handler_save_config - Save configuration to configuration file
  * @message: Pointer to incoming dbus message
  * @wpa_s: wpa_supplicant structure for a network interface
- * Returns: NULL on Success, Otherwise errror message
+ * Returns: NULL on Success, Otherwise error message
  *
  * Handler function for "SaveConfig" method call of network interface.
  */
@@ -2869,6 +2875,12 @@
 			goto nomem;
 #endif /* CONFIG_SAE */
 
+#ifdef CONFIG_OWE
+		if ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OWE) &&
+		    !wpa_dbus_dict_string_array_add_element(&iter_array, "owe"))
+			goto nomem;
+#endif /* CONFIG_OWE */
+
 		if (!wpa_dbus_dict_end_string_array(&iter_dict,
 						    &iter_dict_entry,
 						    &iter_dict_val,
@@ -5073,8 +5085,8 @@
 		return FALSE;
 
 	return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
-						      res + 1, res->ie_len,
-						      error);
+						      wpa_bss_ie_ptr(res),
+						      res->ie_len, error);
 }
 
 
diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig
index 7e06fdd..a6cd933 100644
--- a/wpa_supplicant/defconfig
+++ b/wpa_supplicant/defconfig
@@ -530,6 +530,8 @@
 #
 # External password backend for testing purposes (developer use)
 #CONFIG_EXT_PASSWORD_TEST=y
+# File-based backend to read passwords from an external file.
+#CONFIG_EXT_PASSWORD_FILE=y
 
 # Enable Fast Session Transfer (FST)
 #CONFIG_FST=y
@@ -626,3 +628,9 @@
 # in the future.
 #CONFIG_NO_TKIP=y
 
+# Pre-Association Security Negotiation (PASN)
+# Experimental implementation based on IEEE P802.11z/D2.6 and the protocol
+# design is still subject to change. As such, this should not yet be enabled in
+# production use.
+#CONFIG_PASN=y
+
diff --git a/wpa_supplicant/doc/docbook/eapol_test.sgml b/wpa_supplicant/doc/docbook/eapol_test.sgml
index e7705ab..4cfa3c1 100644
--- a/wpa_supplicant/doc/docbook/eapol_test.sgml
+++ b/wpa_supplicant/doc/docbook/eapol_test.sgml
@@ -1,6 +1,10 @@
 <!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
 
 <refentry>
+  <refentryinfo>
+    <date>07 August 2019</date>
+  </refentryinfo>
+
   <refmeta>
     <refentrytitle>eapol_test</refentrytitle>
     <manvolnum>8</manvolnum>
diff --git a/wpa_supplicant/doc/docbook/wpa_background.sgml b/wpa_supplicant/doc/docbook/wpa_background.sgml
index f6a0ca8..22241cc 100644
--- a/wpa_supplicant/doc/docbook/wpa_background.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_background.sgml
@@ -1,6 +1,10 @@
 <!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
 
 <refentry>
+  <refentryinfo>
+    <date>07 August 2019</date>
+  </refentryinfo>
+
   <refmeta>
     <refentrytitle>wpa_background</refentrytitle>
     <manvolnum>8</manvolnum>
diff --git a/wpa_supplicant/doc/docbook/wpa_cli.sgml b/wpa_supplicant/doc/docbook/wpa_cli.sgml
index dc7fee4..2ba1fe4 100644
--- a/wpa_supplicant/doc/docbook/wpa_cli.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_cli.sgml
@@ -1,6 +1,10 @@
 <!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
 
 <refentry>
+  <refentryinfo>
+    <date>07 August 2019</date>
+  </refentryinfo>
+
   <refmeta>
     <refentrytitle>wpa_cli</refentrytitle>
     <manvolnum>8</manvolnum>
diff --git a/wpa_supplicant/doc/docbook/wpa_gui.sgml b/wpa_supplicant/doc/docbook/wpa_gui.sgml
index 31214e3..cb0c735 100644
--- a/wpa_supplicant/doc/docbook/wpa_gui.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_gui.sgml
@@ -1,6 +1,10 @@
 <!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
 
 <refentry>
+  <refentryinfo>
+    <date>07 August 2019</date>
+  </refentryinfo>
+
   <refmeta>
     <refentrytitle>wpa_gui</refentrytitle>
     <manvolnum>8</manvolnum>
diff --git a/wpa_supplicant/doc/docbook/wpa_passphrase.sgml b/wpa_supplicant/doc/docbook/wpa_passphrase.sgml
index ed9baf1..0772969 100644
--- a/wpa_supplicant/doc/docbook/wpa_passphrase.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_passphrase.sgml
@@ -1,6 +1,10 @@
 <!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
 
 <refentry>
+  <refentryinfo>
+    <date>07 August 2019</date>
+  </refentryinfo>
+
   <refmeta>
     <refentrytitle>wpa_passphrase</refentrytitle>
     <manvolnum>8</manvolnum>
diff --git a/wpa_supplicant/doc/docbook/wpa_priv.sgml b/wpa_supplicant/doc/docbook/wpa_priv.sgml
index dd44565..0d5c94a 100644
--- a/wpa_supplicant/doc/docbook/wpa_priv.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_priv.sgml
@@ -1,6 +1,10 @@
 <!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
 
 <refentry>
+  <refentryinfo>
+    <date>07 August 2019</date>
+  </refentryinfo>
+
   <refmeta>
     <refentrytitle>wpa_priv</refentrytitle>
     <manvolnum>8</manvolnum>
diff --git a/wpa_supplicant/doc/docbook/wpa_supplicant.conf.sgml b/wpa_supplicant/doc/docbook/wpa_supplicant.conf.sgml
index 462039d..8a0314e 100644
--- a/wpa_supplicant/doc/docbook/wpa_supplicant.conf.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_supplicant.conf.sgml
@@ -1,5 +1,9 @@
 <!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
 <refentry>
+  <refentryinfo>
+    <date>07 August 2019</date>
+  </refentryinfo>
+
   <refmeta>
     <refentrytitle>wpa_supplicant.conf</refentrytitle>
     <manvolnum>5</manvolnum>
diff --git a/wpa_supplicant/doc/docbook/wpa_supplicant.sgml b/wpa_supplicant/doc/docbook/wpa_supplicant.sgml
index aaff150..144654a 100644
--- a/wpa_supplicant/doc/docbook/wpa_supplicant.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_supplicant.sgml
@@ -1,6 +1,10 @@
 <!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
 
 <refentry>
+  <refentryinfo>
+    <date>07 August 2019</date>
+  </refentryinfo>
+
   <refmeta>
     <refentrytitle>wpa_supplicant</refentrytitle>
     <manvolnum>8</manvolnum>
diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c
index 2d0c636..d935215 100644
--- a/wpa_supplicant/dpp_supplicant.c
+++ b/wpa_supplicant/dpp_supplicant.c
@@ -33,6 +33,7 @@
 static int wpas_dpp_listen_start(struct wpa_supplicant *wpa_s,
 				 unsigned int freq);
 static void wpas_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx);
+static void wpas_dpp_auth_conf_wait_timeout(void *eloop_ctx, void *timeout_ctx);
 static void wpas_dpp_auth_success(struct wpa_supplicant *wpa_s, int initiator);
 static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s,
 			       unsigned int freq, const u8 *dst,
@@ -474,6 +475,8 @@
 			   "DPP: Terminate authentication exchange due to a request to do so on TX status");
 		eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
 		eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
+		eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s,
+				     NULL);
 		eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s,
 				     NULL);
 #ifdef CONFIG_DPP2
@@ -506,6 +509,17 @@
 		}
 	}
 
+	if (auth->waiting_auth_conf &&
+	    auth->auth_resp_status == DPP_STATUS_OK) {
+		/* Make sure we do not get stuck waiting for Auth Confirm
+		 * indefinitely after successfully transmitted Auth Response to
+		 * allow new authentication exchanges to be started. */
+		eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s,
+				     NULL);
+		eloop_register_timeout(1, 0, wpas_dpp_auth_conf_wait_timeout,
+				       wpa_s, NULL);
+	}
+
 	if (!is_broadcast_ether_addr(dst) && auth->waiting_auth_resp &&
 	    result == OFFCHANNEL_SEND_ACTION_SUCCESS) {
 		/* Allow timeout handling to stop iteration if no response is
@@ -595,6 +609,23 @@
 }
 
 
+static void wpas_dpp_auth_conf_wait_timeout(void *eloop_ctx, void *timeout_ctx)
+{
+	struct wpa_supplicant *wpa_s = eloop_ctx;
+	struct dpp_authentication *auth = wpa_s->dpp_auth;
+
+	if (!auth || !auth->waiting_auth_conf)
+		return;
+
+	wpa_printf(MSG_DEBUG,
+		   "DPP: Terminate authentication exchange due to Auth Confirm timeout");
+	wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL "No Auth Confirm received");
+	offchannel_send_action_done(wpa_s);
+	dpp_auth_deinit(auth);
+	wpa_s->dpp_auth = NULL;
+}
+
+
 static void wpas_dpp_set_testing_options(struct wpa_supplicant *wpa_s,
 					 struct dpp_authentication *auth)
 {
@@ -681,7 +712,9 @@
 	freq = auth->freq[auth->freq_idx++];
 	auth->curr_freq = freq;
 
-	if (is_zero_ether_addr(auth->peer_bi->mac_addr))
+	if (!is_zero_ether_addr(auth->peer_mac_addr))
+		dst = auth->peer_mac_addr;
+	else if (is_zero_ether_addr(auth->peer_bi->mac_addr))
 		dst = broadcast;
 	else
 		dst = auth->peer_bi->mac_addr;
@@ -812,6 +845,8 @@
 	if (!tcp && wpa_s->dpp_auth) {
 		eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
 		eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
+		eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s,
+				     NULL);
 		eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s,
 				     NULL);
 #ifdef CONFIG_DPP2
@@ -1414,6 +1449,8 @@
 				      struct dpp_config_obj *conf)
 {
 	wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
+	wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_AKM "%s",
+		dpp_akm_str(conf->akm));
 	if (conf->ssid_len)
 		wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s",
 			wpa_ssid_txt(conf->ssid, conf->ssid_len));
@@ -1429,6 +1466,21 @@
 		wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
 			conf->connector);
 	}
+	if (conf->passphrase[0]) {
+		char hex[64 * 2 + 1];
+
+		wpa_snprintf_hex(hex, sizeof(hex),
+				 (const u8 *) conf->passphrase,
+				 os_strlen(conf->passphrase));
+		wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_PASS "%s",
+			hex);
+	} else if (conf->psk_set) {
+		char hex[PMK_LEN * 2 + 1];
+
+		wpa_snprintf_hex(hex, sizeof(hex), conf->psk, PMK_LEN);
+		wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_PSK "%s",
+			hex);
+	}
 	if (conf->c_sign_key) {
 		char *hex;
 		size_t hexlen;
@@ -1818,6 +1870,8 @@
 		return;
 	}
 
+	eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
+
 	if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
 		wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
 		wpas_notify_dpp_auth_failure(wpa_s);
@@ -1877,9 +1931,22 @@
 		   MAC2STR(src));
 
 	if (!auth || !auth->waiting_conf_result) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: No DPP Configuration waiting for result - drop");
-		return;
+		if (auth &&
+		    os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) == 0 &&
+		    gas_server_response_sent(wpa_s->gas_server,
+					     auth->gas_server_ctx)) {
+			/* This could happen if the TX status event gets delayed
+			 * long enough for the Enrollee to have time to send
+			 * the next frame before the TX status gets processed
+			 * locally. */
+			wpa_printf(MSG_DEBUG,
+				   "DPP: GAS response was sent but TX status not yet received - assume it was ACKed since the Enrollee sent the next frame in the sequence");
+			auth->waiting_conf_result = 1;
+		} else {
+			wpa_printf(MSG_DEBUG,
+				   "DPP: No DPP Configuration waiting for result - drop");
+			return;
+		}
 	}
 
 	if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
@@ -2041,8 +2108,9 @@
 
 	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);
+	/* The source address of the Presence Announcement frame overrides any
+	 * MAC address information from the bootstrapping information. */
+	os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
 
 	wpa_s->dpp_auth = auth;
 	if (wpas_dpp_auth_init_next(wpa_s) < 0) {
@@ -2936,6 +3004,7 @@
 		wpas_notify_dpp_configuration_failure(wpa_s);
 	}
 	auth->conf_resp = resp;
+	auth->gas_server_ctx = resp_ctx;
 	return resp;
 }
 
@@ -2969,10 +3038,12 @@
 	wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)",
 		   ok);
 	eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
+	eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
 	eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
 #ifdef CONFIG_DPP2
 	if (ok && auth->peer_version >= 2 &&
-	    auth->conf_resp_status == DPP_STATUS_OK) {
+	    auth->conf_resp_status == DPP_STATUS_OK &&
+	    !auth->waiting_conf_result) {
 		wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
 		wpas_notify_dpp_config_sent_wait_response(wpa_s);
 		auth->waiting_conf_result = 1;
@@ -3351,6 +3422,7 @@
 		return;
 	eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
 	eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
+	eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
 	eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
 	eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
 #ifdef CONFIG_DPP2
@@ -3520,7 +3592,7 @@
 
 	/* Preferred chirping channels */
 	mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
-			HOSTAPD_MODE_IEEE80211G, 0);
+			HOSTAPD_MODE_IEEE80211G, false);
 	chan6 = mode == NULL;
 	if (mode) {
 		for (c = 0; c < mode->num_channels; c++) {
@@ -3537,7 +3609,7 @@
 		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);
+			HOSTAPD_MODE_IEEE80211A, false);
 	if (mode) {
 		int chan44 = 0, chan149 = 0;
 
@@ -3559,7 +3631,7 @@
 	}
 
 	mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
-			HOSTAPD_MODE_IEEE80211AD, 0);
+			HOSTAPD_MODE_IEEE80211AD, false);
 	if (mode) {
 		for (c = 0; c < mode->num_channels; c++) {
 			struct hostapd_channel_data *chan = &mode->channels[c];
@@ -3598,6 +3670,17 @@
 	if (wpa_s->dpp_chirp_freq == 0) {
 		if (wpa_s->dpp_chirp_round % 4 == 0 &&
 		    !wpa_s->dpp_chirp_scan_done) {
+			if (wpas_scan_scheduled(wpa_s)) {
+				wpa_printf(MSG_DEBUG,
+					   "DPP: Deferring chirp scan because another scan is planned already");
+				if (eloop_register_timeout(1, 0,
+							   wpas_dpp_chirp_next,
+							   wpa_s, NULL) < 0) {
+					wpas_dpp_chirp_stop(wpa_s);
+					return;
+				}
+				return;
+			}
 			wpa_printf(MSG_DEBUG,
 				   "DPP: Update channel list for chirping");
 			wpa_s->scan_req = MANUAL_SCAN_REQ;
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index ba8cc55..237f4e0 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -719,12 +719,14 @@
 
 static inline int wpa_drv_vendor_cmd(struct wpa_supplicant *wpa_s,
 				     int vendor_id, int subcmd, const u8 *data,
-				     size_t data_len, struct wpabuf *buf)
+				     size_t data_len,
+				     enum nested_attr nested_attr_flag,
+				     struct wpabuf *buf)
 {
 	if (!wpa_s->driver->vendor_cmd)
 		return -1;
 	return wpa_s->driver->vendor_cmd(wpa_s->drv_priv, vendor_id, subcmd,
-					 data, data_len, buf);
+					 data, data_len, nested_attr_flag, buf);
 }
 
 static inline int wpa_drv_roaming(struct wpa_supplicant *wpa_s, int allowed,
@@ -952,11 +954,11 @@
 #endif /* CONFIG_MACSEC */
 
 static inline int wpa_drv_setband(struct wpa_supplicant *wpa_s,
-				  enum set_band band)
+				  u32 band_mask)
 {
 	if (!wpa_s->driver->set_band)
 		return -1;
-	return wpa_s->driver->set_band(wpa_s->drv_priv, band);
+	return wpa_s->driver->set_band(wpa_s->drv_priv, band_mask);
 }
 
 static inline int wpa_drv_get_pref_freq_list(struct wpa_supplicant *wpa_s,
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 3165903..f821709 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -30,8 +30,9 @@
 #include "common/ieee802_11_common.h"
 #include "common/gas_server.h"
 #include "common/dpp.h"
+#include "common/ptksa_cache.h"
 #include "crypto/random.h"
-#include "blacklist.h"
+#include "bssid_ignore.h"
 #include "wpas_glue.h"
 #include "wps_supplicant.h"
 #include "ibss_rsn.h"
@@ -1086,7 +1087,7 @@
 
 static bool wpa_scan_res_ok(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
 			    const u8 *match_ssid, size_t match_ssid_len,
-			    struct wpa_bss *bss, int blacklist_count,
+			    struct wpa_bss *bss, int bssid_ignore_count,
 			    bool debug_print);
 
 
@@ -1118,7 +1119,7 @@
 		if (bss->est_throughput < 2000)
 			return false;
 
-		count = wpa_blacklist_is_blacklisted(wpa_s, bss->bssid);
+		count = wpa_bssid_ignore_is_listed(wpa_s, bss->bssid);
 		if (wpa_scan_res_ok(wpa_s, ssid, match_ssid, match_ssid_len,
 				    bss, count, 0))
 			return true;
@@ -1131,7 +1132,7 @@
 
 static bool wpa_scan_res_ok(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
 			    const u8 *match_ssid, size_t match_ssid_len,
-			    struct wpa_bss *bss, int blacklist_count,
+			    struct wpa_bss *bss, int bssid_ignore_count,
 			    bool debug_print)
 {
 	int res;
@@ -1179,10 +1180,10 @@
 	}
 
 #ifdef CONFIG_WPS
-	if ((ssid->key_mgmt & WPA_KEY_MGMT_WPS) && blacklist_count) {
+	if ((ssid->key_mgmt & WPA_KEY_MGMT_WPS) && bssid_ignore_count) {
 		if (debug_print)
 			wpa_dbg(wpa_s, MSG_DEBUG,
-				"   skip - blacklisted (WPS)");
+				"   skip - BSSID ignored (WPS)");
 		return false;
 	}
 
@@ -1217,23 +1218,23 @@
 		return false;
 	}
 
-	/* check blacklist */
-	if (ssid->num_bssid_blacklist &&
-	    addr_in_list(bss->bssid, ssid->bssid_blacklist,
-			 ssid->num_bssid_blacklist)) {
+	/* check the list of BSSIDs to ignore */
+	if (ssid->num_bssid_ignore &&
+	    addr_in_list(bss->bssid, ssid->bssid_ignore,
+			 ssid->num_bssid_ignore)) {
 		if (debug_print)
 			wpa_dbg(wpa_s, MSG_DEBUG,
-				"   skip - BSSID blacklisted");
+				"   skip - BSSID configured to be ignored");
 		return false;
 	}
 
-	/* if there is a whitelist, only accept those APs */
-	if (ssid->num_bssid_whitelist &&
-	    !addr_in_list(bss->bssid, ssid->bssid_whitelist,
-			  ssid->num_bssid_whitelist)) {
+	/* if there is a list of accepted BSSIDs, only accept those APs */
+	if (ssid->num_bssid_accept &&
+	    !addr_in_list(bss->bssid, ssid->bssid_accept,
+			  ssid->num_bssid_accept)) {
 		if (debug_print)
 			wpa_dbg(wpa_s, MSG_DEBUG,
-				"   skip - BSSID not in whitelist");
+				"   skip - BSSID not in list of accepted values");
 		return false;
 	}
 
@@ -1478,7 +1479,7 @@
 	int osen;
 	const u8 *match_ssid;
 	size_t match_ssid_len;
-	int blacklist_count;
+	int bssid_ignore_count;
 
 	ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
 	wpa_ie_len = ie ? ie[1] : 0;
@@ -1504,13 +1505,13 @@
 			osen ? " osen=1" : "");
 	}
 
-	blacklist_count = wpa_blacklist_is_blacklisted(wpa_s, bss->bssid);
-	if (blacklist_count) {
+	bssid_ignore_count = wpa_bssid_ignore_is_listed(wpa_s, bss->bssid);
+	if (bssid_ignore_count) {
 		int limit = 1;
 		if (wpa_supplicant_enabled_networks(wpa_s) == 1) {
 			/*
 			 * When only a single network is enabled, we can
-			 * trigger blacklisting on the first failure. This
+			 * trigger BSSID ignoring on the first failure. This
 			 * should not be done with multiple enabled networks to
 			 * avoid getting forced to move into a worse ESS on
 			 * single error if there are no other BSSes of the
@@ -1518,11 +1519,11 @@
 			 */
 			limit = 0;
 		}
-		if (blacklist_count > limit) {
+		if (bssid_ignore_count > limit) {
 			if (debug_print) {
 				wpa_dbg(wpa_s, MSG_DEBUG,
-					"   skip - blacklisted (count=%d limit=%d)",
-					blacklist_count, limit);
+					"   skip - BSSID ignored (count=%d limit=%d)",
+					bssid_ignore_count, limit);
 			}
 			return NULL;
 		}
@@ -1558,7 +1559,7 @@
 
 	for (ssid = group; ssid; ssid = only_first_ssid ? NULL : ssid->pnext) {
 		if (wpa_scan_res_ok(wpa_s, ssid, match_ssid, match_ssid_len,
-				    bss, blacklist_count, debug_print))
+				    bss, bssid_ignore_count, debug_print))
 			return ssid;
 	}
 
@@ -1660,12 +1661,12 @@
 				break;
 		}
 
-		if (selected == NULL && wpa_s->blacklist &&
+		if (selected == NULL && wpa_s->bssid_ignore &&
 		    !wpa_s->countermeasures) {
-			wpa_dbg(wpa_s, MSG_DEBUG, "No APs found - clear "
-				"blacklist and try again");
-			wpa_blacklist_clear(wpa_s);
-			wpa_s->blacklist_cleared++;
+			wpa_dbg(wpa_s, MSG_DEBUG,
+				"No APs found - clear BSSID ignore list and try again");
+			wpa_bssid_ignore_clear(wpa_s);
+			wpa_s->bssid_ignore_cleared = true;
 		} else if (selected == NULL)
 			break;
 	}
@@ -1853,7 +1854,7 @@
 				     const struct wpa_bss *bss, int snr)
 {
 	int rate = wpa_bss_get_max_rate(bss);
-	const u8 *ies = (const void *) (bss + 1);
+	const u8 *ies = wpa_bss_ie_ptr(bss);
 	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);
@@ -2092,9 +2093,18 @@
 			return -1;
 		if (data && data->scan_info.external_scan)
 			return -1;
-		wpa_dbg(wpa_s, MSG_DEBUG, "Failed to get scan results - try "
-			"scanning again");
-		wpa_supplicant_req_new_scan(wpa_s, 1, 0);
+		if (wpa_s->scan_res_fail_handler) {
+			void (*handler)(struct wpa_supplicant *wpa_s);
+
+			handler = wpa_s->scan_res_fail_handler;
+			wpa_s->scan_res_fail_handler = NULL;
+			handler(wpa_s);
+		} else {
+			wpa_dbg(wpa_s, MSG_DEBUG,
+				"Failed to get scan results - try scanning again");
+			wpa_supplicant_req_new_scan(wpa_s, 1, 0);
+		}
+
 		ret = -1;
 		goto scan_work_done;
 	}
@@ -2441,7 +2451,7 @@
 
 	os_get_reltime(&now);
 	if (os_reltime_expired(&now, &wpa_s->last_scan,
-			       SCAN_RES_VALID_FOR_CONNECT)) {
+			       wpa_s->conf->scan_res_valid_for_connect)) {
 		wpa_printf(MSG_DEBUG, "Fast associate: Old scan results");
 		return -1;
 	}
@@ -3063,7 +3073,7 @@
 	if (!bss)
 		return;
 
-	ieprb = (const u8 *) (bss + 1);
+	ieprb = wpa_bss_ie_ptr(bss);
 	iebcn = ieprb + bss->ie_len;
 
 	if (!wpas_fst_update_mbie(wpa_s, ieprb, bss->ie_len))
@@ -3540,6 +3550,8 @@
 	if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
 		wpas_connection_failed(wpa_s, bssid);
 	wpa_sm_notify_disassoc(wpa_s->wpa);
+	ptksa_cache_flush(wpa_s->ptksa, wpa_s->bssid, WPA_CIPHER_NONE);
+
 	if (locally_generated)
 		wpa_s->disconnect_reason = -reason_code;
 	else
@@ -3633,7 +3645,7 @@
 		/* initialize countermeasures */
 		wpa_s->countermeasures = 1;
 
-		wpa_blacklist_add(wpa_s, wpa_s->bssid);
+		wpa_bssid_ignore_add(wpa_s, wpa_s->bssid);
 
 		wpa_msg(wpa_s, MSG_WARNING, "TKIP countermeasures started");
 
@@ -4492,6 +4504,31 @@
 }
 
 
+static const char * connect_fail_reason(enum sta_connect_fail_reason_codes code)
+{
+	switch (code) {
+	case STA_CONNECT_FAIL_REASON_UNSPECIFIED:
+		return "";
+	case STA_CONNECT_FAIL_REASON_NO_BSS_FOUND:
+		return "no_bss_found";
+	case STA_CONNECT_FAIL_REASON_AUTH_TX_FAIL:
+		return "auth_tx_fail";
+	case STA_CONNECT_FAIL_REASON_AUTH_NO_ACK_RECEIVED:
+		return "auth_no_ack_received";
+	case STA_CONNECT_FAIL_REASON_AUTH_NO_RESP_RECEIVED:
+		return "auth_no_resp_received";
+	case STA_CONNECT_FAIL_REASON_ASSOC_REQ_TX_FAIL:
+		return "assoc_req_tx_fail";
+	case STA_CONNECT_FAIL_REASON_ASSOC_NO_ACK_RECEIVED:
+		return "assoc_no_ack_received";
+	case STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED:
+		return "assoc_no_resp_received";
+	default:
+		return "unknown_reason";
+	}
+}
+
+
 static void wpas_event_assoc_reject(struct wpa_supplicant *wpa_s,
 				    union wpa_event_data *data)
 {
@@ -4511,21 +4548,29 @@
 
 	if (data->assoc_reject.bssid)
 		wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT
-			"bssid=" MACSTR	" status_code=%u%s%s%s",
+			"bssid=" MACSTR	" status_code=%u%s%s%s%s%s",
 			MAC2STR(data->assoc_reject.bssid),
 			data->assoc_reject.status_code,
 			data->assoc_reject.timed_out ? " timeout" : "",
 			data->assoc_reject.timeout_reason ? "=" : "",
 			data->assoc_reject.timeout_reason ?
-			data->assoc_reject.timeout_reason : "");
+			data->assoc_reject.timeout_reason : "",
+			data->assoc_reject.reason_code !=
+			STA_CONNECT_FAIL_REASON_UNSPECIFIED ?
+			" qca_driver_reason=" : "",
+			connect_fail_reason(data->assoc_reject.reason_code));
 	else
 		wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT
-			"status_code=%u%s%s%s",
+			"status_code=%u%s%s%s%s%s",
 			data->assoc_reject.status_code,
 			data->assoc_reject.timed_out ? " timeout" : "",
 			data->assoc_reject.timeout_reason ? "=" : "",
 			data->assoc_reject.timeout_reason ?
-			data->assoc_reject.timeout_reason : "");
+			data->assoc_reject.timeout_reason : "",
+			data->assoc_reject.reason_code !=
+			STA_CONNECT_FAIL_REASON_UNSPECIFIED ?
+			" qca_driver_reason=" : "",
+			connect_fail_reason(data->assoc_reject.reason_code));
 	wpa_s->assoc_status_code = data->assoc_reject.status_code;
 	wpas_notify_assoc_status_code(wpa_s, bssid, data->assoc_reject.timed_out,
 				    data->assoc_reject.resp_ies, data->assoc_reject.resp_ies_len);
@@ -4815,7 +4860,7 @@
 			}
 		} else {
 			wpa_dbg(wpa_s, MSG_DEBUG, "External program started a scan");
-			wpa_s->radio->external_scan_running = 1;
+			wpa_s->radio->external_scan_req_interface = wpa_s;
 			wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_STARTED);
 		}
 		break;
@@ -4823,7 +4868,7 @@
 		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
 			wpa_s->scan_res_handler = NULL;
 			wpa_s->own_scan_running = 0;
-			wpa_s->radio->external_scan_running = 0;
+			wpa_s->radio->external_scan_req_interface = NULL;
 			wpa_s->last_scan_req = NORMAL_SCAN_REQ;
 			break;
 		}
@@ -4843,7 +4888,7 @@
 		if (!(data && data->scan_info.external_scan))
 			wpa_s->own_scan_running = 0;
 		if (data && data->scan_info.nl_scan_event)
-			wpa_s->radio->external_scan_running = 0;
+			wpa_s->radio->external_scan_req_interface = NULL;
 		radio_work_check_next(wpa_s);
 		break;
 #endif /* CONFIG_NO_SCAN_PROCESSING */
@@ -4906,6 +4951,14 @@
 			" type=%d stype=%d",
 			MAC2STR(data->tx_status.dst),
 			data->tx_status.type, data->tx_status.stype);
+#ifdef CONFIG_PASN
+		if (data->tx_status.type == WLAN_FC_TYPE_MGMT &&
+		    data->tx_status.stype == WLAN_FC_STYPE_AUTH &&
+		    wpas_pasn_auth_tx_status(wpa_s, data->tx_status.data,
+					     data->tx_status.data_len,
+					     data->tx_status.ack) == 0)
+			break;
+#endif /* CONFIG_PASN */
 #ifdef CONFIG_AP
 		if (wpa_s->ap_iface == NULL) {
 #ifdef CONFIG_OFFCHANNEL
@@ -5001,6 +5054,12 @@
 
 		wpa_s->assoc_freq = data->ch_switch.freq;
 		wpa_s->current_ssid->frequency = data->ch_switch.freq;
+		if (wpa_s->current_bss &&
+		    wpa_s->current_bss->freq != data->ch_switch.freq) {
+			wpa_s->current_bss->freq = data->ch_switch.freq;
+			notify_bss_changes(wpa_s, WPA_BSS_FREQ_CHANGED_FLAG,
+					   wpa_s->current_bss);
+		}
 
 #ifdef CONFIG_SME
 		switch (data->ch_switch.ch_offset) {
@@ -5134,6 +5193,12 @@
 				mesh_mpm_mgmt_rx(wpa_s, &data->rx_mgmt);
 				break;
 			}
+#ifdef CONFIG_PASN
+			if (stype == WLAN_FC_STYPE_AUTH &&
+			    wpas_pasn_auth_rx(wpa_s, mgmt,
+					      data->rx_mgmt.frame_len) != -2)
+				break;
+#endif /* CONFIG_PASN */
 
 #ifdef CONFIG_SAE
 			if (stype == WLAN_FC_STYPE_AUTH &&
@@ -5316,13 +5381,13 @@
 		}
 		wpa_supplicant_mark_disassoc(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;
+		if (age.sec >= wpa_s->conf->scan_res_valid_for_connect) {
+			clear_at.sec = wpa_s->conf->scan_res_valid_for_connect;
 			clear_at.usec = 0;
 		} else {
 			struct os_reltime tmp;
 
-			tmp.sec = SCAN_RES_VALID_FOR_CONNECT;
+			tmp.sec = wpa_s->conf->scan_res_valid_for_connect;
 			tmp.usec = 0;
 			os_reltime_sub(&tmp, &age, &clear_at);
 		}
diff --git a/wpa_supplicant/examples/p2p-action-udhcp.sh b/wpa_supplicant/examples/p2p-action-udhcp.sh
index d7d0e79..53d8b77 100755
--- a/wpa_supplicant/examples/p2p-action-udhcp.sh
+++ b/wpa_supplicant/examples/p2p-action-udhcp.sh
@@ -50,7 +50,7 @@
 if [ "$CMD" = "P2P-CROSS-CONNECT-ENABLE" ]; then
     GIFNAME=$3
     UPLINK=$4
-    # enable NAT/masquarade $GIFNAME -> $UPLINK
+    # enable NAT/masquerade $GIFNAME -> $UPLINK
     iptables -P FORWARD DROP
     iptables -t nat -A POSTROUTING -o $UPLINK -j MASQUERADE
     iptables -A FORWARD -i $UPLINK -o $GIFNAME -m state --state RELATED,ESTABLISHED -j ACCEPT
@@ -61,7 +61,7 @@
 if [ "$CMD" = "P2P-CROSS-CONNECT-DISABLE" ]; then
     GIFNAME=$3
     UPLINK=$4
-    # disable NAT/masquarade $GIFNAME -> $UPLINK
+    # disable NAT/masquerade $GIFNAME -> $UPLINK
     sysctl net.ipv4.ip_forward=0
     iptables -t nat -D POSTROUTING -o $UPLINK -j MASQUERADE
     iptables -D FORWARD -i $UPLINK -o $GIFNAME -m state --state RELATED,ESTABLISHED -j ACCEPT
diff --git a/wpa_supplicant/examples/p2p-action.sh b/wpa_supplicant/examples/p2p-action.sh
index 797d43a..6c27b27 100755
--- a/wpa_supplicant/examples/p2p-action.sh
+++ b/wpa_supplicant/examples/p2p-action.sh
@@ -77,7 +77,7 @@
 if [ "$CMD" = "P2P-CROSS-CONNECT-ENABLE" ]; then
     GIFNAME=$3
     UPLINK=$4
-    # enable NAT/masquarade $GIFNAME -> $UPLINK
+    # enable NAT/masquerade $GIFNAME -> $UPLINK
     iptables -P FORWARD DROP
     iptables -t nat -A POSTROUTING -o $UPLINK -j MASQUERADE
     iptables -A FORWARD -i $UPLINK -o $GIFNAME -m state --state RELATED,ESTABLISHED -j ACCEPT
@@ -88,7 +88,7 @@
 if [ "$CMD" = "P2P-CROSS-CONNECT-DISABLE" ]; then
     GIFNAME=$3
     UPLINK=$4
-    # disable NAT/masquarade $GIFNAME -> $UPLINK
+    # disable NAT/masquerade $GIFNAME -> $UPLINK
     sysctl net.ipv4.ip_forward=0
     iptables -t nat -D POSTROUTING -o $UPLINK -j MASQUERADE
     iptables -D FORWARD -i $UPLINK -o $GIFNAME -m state --state RELATED,ESTABLISHED -j ACCEPT
diff --git a/wpa_supplicant/examples/p2p/p2p_connect.py b/wpa_supplicant/examples/p2p/p2p_connect.py
index 2f62e9c..bfb5533 100644
--- a/wpa_supplicant/examples/p2p/p2p_connect.py
+++ b/wpa_supplicant/examples/p2p/p2p_connect.py
@@ -71,7 +71,7 @@
 	global wpas_dbus_interfaces_interface
 	global wpas_dbus_interfaces_p2pdevice
 
-	# Dictionary of Arguements
+	# Dictionary of Arguments
 	global p2p_connect_arguements
 
 	# Constructor
@@ -146,9 +146,9 @@
 			signal_name="WpsFailed")
 
 
-	#Constructing all the arguements needed to connect
+	#Constructing all the arguments needed to connect
 	def constructArguements(self):
-		# Adding required arguements
+		# Adding required arguments
 		self.p2p_connect_arguements = {'wps_method':self.wps_method,
 			'peer':dbus.ObjectPath(self.path+'/Peers/'+self.addr)}
 
@@ -198,7 +198,7 @@
 			usage()
 			quit()
 
-		# Go_intent is optional for all arguements
+		# Go_intent is optional for all arguments
 		if (self.go_intent != None):
 			self.p2p_connect_arguements.update(
 				{'go_intent':dbus.Int32(self.go_intent)})
@@ -239,7 +239,7 @@
 		usage()
 		quit()
 
-	# If theres a switch, override default option
+	# If there's a switch, override default option
 	for key, value in options:
 		# Help
 		if (key == "-h"):
@@ -266,9 +266,9 @@
 		else:
 			assert False, "unhandled option"
 
-	# Required Arguements check
+	# Required Arguments check
 	if (interface_name == None or wps_method == None or addr == None):
-		print("Error:\n  Required arguements not specified")
+		print("Error:\n  Required arguments not specified")
 		usage()
 		quit()
 
@@ -289,7 +289,7 @@
 			addr,pin,wps_method,go_intent)
 
 	except:
-		print("Error:\n  Invalid Arguements")
+		print("Error:\n  Invalid Arguments")
 		usage()
 		quit()
 
diff --git a/wpa_supplicant/examples/p2p/p2p_disconnect.py b/wpa_supplicant/examples/p2p/p2p_disconnect.py
index 85b5a8b..f04b98e 100644
--- a/wpa_supplicant/examples/p2p/p2p_disconnect.py
+++ b/wpa_supplicant/examples/p2p/p2p_disconnect.py
@@ -125,7 +125,7 @@
 		usage()
 		quit()
 
-	# If theres a switch, override default option
+	# If there's a switch, override default option
 	for key, value in options:
 		# Help
 		if (key == "-h"):
diff --git a/wpa_supplicant/examples/p2p/p2p_find.py b/wpa_supplicant/examples/p2p/p2p_find.py
index e2df528..412d812 100644
--- a/wpa_supplicant/examples/p2p/p2p_find.py
+++ b/wpa_supplicant/examples/p2p/p2p_find.py
@@ -136,7 +136,7 @@
 		usage()
 		quit()
 
-	# If theres a switch, override default option
+	# If there's a switch, override default option
 	for key, value in options:
 		# Help
 		if (key == "-h"):
diff --git a/wpa_supplicant/examples/p2p/p2p_flush.py b/wpa_supplicant/examples/p2p/p2p_flush.py
index 42fc7a3..5cc3a0e 100644
--- a/wpa_supplicant/examples/p2p/p2p_flush.py
+++ b/wpa_supplicant/examples/p2p/p2p_flush.py
@@ -125,7 +125,7 @@
 		usage()
 		quit()
 
-	# If theres a switch, override default option
+	# If there's a switch, override default option
 	for key, value in options:
 		# Help
 		if (key == "-h"):
diff --git a/wpa_supplicant/examples/p2p/p2p_group_add.py b/wpa_supplicant/examples/p2p/p2p_group_add.py
index 6d40821..db6d60d 100644
--- a/wpa_supplicant/examples/p2p/p2p_group_add.py
+++ b/wpa_supplicant/examples/p2p/p2p_group_add.py
@@ -18,7 +18,7 @@
 	print("  		[-w <wpas_dbus_interface>]")
 	print("Options:")
 	print("  -i = interface name")
-	print("  -p = persistant group = 0 (0=false, 1=true)")
+	print("  -p = persistent group = 0 (0=false, 1=true)")
 	print("  -f = frequency")
 	print("  -o = persistent group object path")
 	print("  -w = wpas dbus interface = fi.w1.wpa_supplicant1")
@@ -57,7 +57,7 @@
 	global wpas_dbus_interfaces_interface
 	global wpas_dbus_interfaces_p2pdevice
 
-	# Arguements
+	# Arguments
 	global P2PDictionary
 
 	# Constructor
@@ -120,7 +120,7 @@
 			signal_name="WpsFailed")
 
 		# Sets up p2p_group_add dictionary
-	def constructArguements(self):
+	def constructArguments(self):
 		self.P2PDictionary = {'persistent':self.persistent}
 
 		if (self.frequency != None):
@@ -141,7 +141,7 @@
 			self.p2p_interface.GroupAdd(self.P2PDictionary)
 
 		except:
-			print("Error:\n  Could not preform group add")
+			print("Error:\n  Could not perform group add")
 			usage()
 			os._exit(0)
 
@@ -172,7 +172,7 @@
 		usage()
 		quit()
 
-	# If theres a switch, override default option
+	# If there's a switch, override default option
 	for key, value in options:
 		# Help
 		if (key == "-h"):
@@ -213,9 +213,9 @@
 		p2p_group_add_test = P2P_Group_Add(interface_name,wpas_dbus_interface,
 					persistent,frequency,persistent_group_object)
 	except:
-		print("Error:\n  Invalid Arguements")
+		print("Error:\n  Invalid Arguments")
 
-	p2p_group_add_test.constructArguements()
+	p2p_group_add_test.constructArguments()
 	p2p_group_add_test.start()
 	time.sleep(5)
 	print("Error:\n  Group formation timed out")
diff --git a/wpa_supplicant/examples/p2p/p2p_invite.py b/wpa_supplicant/examples/p2p/p2p_invite.py
index 341dcd0..8944e11 100644
--- a/wpa_supplicant/examples/p2p/p2p_invite.py
+++ b/wpa_supplicant/examples/p2p/p2p_invite.py
@@ -25,7 +25,7 @@
 
 # Required Signals
 def InvitationResult(invite_result):
-	print("Inviation Result signal :")
+	print("Invitation Result signal :")
 	status = invite_result['status']
 	print("status = ", status)
 	if invite_result.has_key('BSSID'):
@@ -55,7 +55,7 @@
 	global wpas_dbus_interfaces_interface
 	global wpas_dbus_interfaces_p2pdevice
 
-	# Arguements
+	# Arguments
 	global P2PDictionary
 
 	# Constructor
@@ -127,7 +127,7 @@
 			self.p2p_interface.Invite(self.P2PDictionary)
 
 		except:
-			print("Error:\n  Invalid Arguements")
+			print("Error:\n  Invalid Arguments")
 			usage()
 			os._exit(0)
 
@@ -154,7 +154,7 @@
 		usage()
 		quit()
 
-	# If theres a switch, override default option
+	# If there's a switch, override default option
 	for key, value in options:
 		# Help
 		if (key == "-h"):
@@ -190,7 +190,7 @@
 			P2P_Invite(interface_name,wpas_dbus_interface,
 					addr,persistent_group_object)
 	except:
-		print("Error:\n  Invalid Arguements")
+		print("Error:\n  Invalid Arguments")
 		usage()
 		os._exit(1)
 
diff --git a/wpa_supplicant/examples/p2p/p2p_listen.py b/wpa_supplicant/examples/p2p/p2p_listen.py
index b0837d9..cbeda9f 100644
--- a/wpa_supplicant/examples/p2p/p2p_listen.py
+++ b/wpa_supplicant/examples/p2p/p2p_listen.py
@@ -126,7 +126,7 @@
 		usage()
 		quit()
 
-	# If theres a switch, override default option
+	# If there's a switch, override default option
 	for key, value in options:
 		# Help
 		if (key == "-h"):
diff --git a/wpa_supplicant/examples/p2p/p2p_stop_find.py b/wpa_supplicant/examples/p2p/p2p_stop_find.py
index bdb4c0e..f367196 100644
--- a/wpa_supplicant/examples/p2p/p2p_stop_find.py
+++ b/wpa_supplicant/examples/p2p/p2p_stop_find.py
@@ -130,7 +130,7 @@
 		usage()
 		quit()
 
-	# If theres a switch, override default option
+	# If there's a switch, override default option
 	for key, value in options:
 		# Help
 		if (key == "-h"):
diff --git a/wpa_supplicant/examples/udhcpd-p2p.conf b/wpa_supplicant/examples/udhcpd-p2p.conf
index df59094..f92cc61 100644
--- a/wpa_supplicant/examples/udhcpd-p2p.conf
+++ b/wpa_supplicant/examples/udhcpd-p2p.conf
@@ -11,8 +11,8 @@
 interface	wlan2		#default: eth0
 
 
-# The maximim number of leases (includes addressesd reserved
-# by OFFER's, DECLINE's, and ARP conficts
+# The maximum number of leases (includes addresses reserved
+# by OFFER's, DECLINE's, and ARP conflicts)
 
 #max_leases	254		#default: 254
 
@@ -52,12 +52,12 @@
 # If a lease to be given is below this value, the full lease time is
 # instead used (seconds).
 
-#min_lease	60		#defult: 60
+#min_lease	60		#default: 60
 
 
 # The location of the leases file
 
-#lease_file	/var/lib/misc/udhcpd.leases	#defualt: /var/lib/misc/udhcpd.leases
+#lease_file	/var/lib/misc/udhcpd.leases	#default: /var/lib/misc/udhcpd.leases
 
 # The location of the pid file
 pidfile	/var/run/udhcpd-wlan2.pid	#default: /var/run/udhcpd.pid
@@ -77,7 +77,7 @@
 
 #boot_file	/var/nfs_root		#default: (none)
 
-# The remainer of options are DHCP options and can be specifed with the
+# The remainder of options are DHCP options and can be specified with the
 # keyword 'opt' or 'option'. If an option can take multiple items, such
 # as the dns option, they can be listed on the same line, or multiple
 # lines. The only option with a default is 'lease'.
@@ -116,5 +116,3 @@
 # Static leases map
 #static_lease 00:60:08:11:CE:4E 192.168.0.54
 #static_lease 00:60:08:11:CE:3E 192.168.0.44
-
-
diff --git a/wpa_supplicant/hidl/1.4/hidl_manager.cpp b/wpa_supplicant/hidl/1.4/hidl_manager.cpp
index b57988d..b7a7cf7 100644
--- a/wpa_supplicant/hidl/1.4/hidl_manager.cpp
+++ b/wpa_supplicant/hidl/1.4/hidl_manager.cpp
@@ -842,7 +842,7 @@
 		struct wpa_bss_anqp_elem *elem;
 		dl_list_for_each(elem, &anqp->anqp_elems, struct wpa_bss_anqp_elem,
 				 list) {
-			if (elem->infoid == ANQP_VENUE_URL) {
+			if (elem->infoid == ANQP_VENUE_URL && elem->protected_response) {
 				hidl_anqp_data.venueUrl =
 						    misc_utils::convertWpaBufToVector(elem->payload);
 				break;
diff --git a/wpa_supplicant/hs20_supplicant.c b/wpa_supplicant/hs20_supplicant.c
index 907803b..8aeb3b0 100644
--- a/wpa_supplicant/hs20_supplicant.c
+++ b/wpa_supplicant/hs20_supplicant.c
@@ -22,7 +22,7 @@
 #include "scan.h"
 #include "notify.h"
 #include "bss.h"
-#include "blacklist.h"
+#include "bssid_ignore.h"
 #include "gas_query.h"
 #include "interworking.h"
 #include "hs20_supplicant.h"
@@ -906,14 +906,25 @@
 	/* OSU Friendly Name Duples */
 	while (pos - pos2 >= 4 && prov->friendly_name_count < OSU_MAX_ITEMS) {
 		struct osu_lang_string *f;
-		if (1 + pos2[0] > pos - pos2 || pos2[0] < 3) {
+		u8 slen;
+
+		slen = pos2[0];
+		if (1 + slen > pos - pos2) {
 			wpa_printf(MSG_DEBUG, "Invalid OSU Friendly Name");
 			break;
 		}
+		if (slen < 3) {
+			wpa_printf(MSG_DEBUG,
+				   "Invalid OSU Friendly Name (no room for language)");
+			break;
+		}
 		f = &prov->friendly_name[prov->friendly_name_count++];
-		os_memcpy(f->lang, pos2 + 1, 3);
-		os_memcpy(f->text, pos2 + 1 + 3, pos2[0] - 3);
-		pos2 += 1 + pos2[0];
+		pos2++;
+		os_memcpy(f->lang, pos2, 3);
+		pos2 += 3;
+		slen -= 3;
+		os_memcpy(f->text, pos2, slen);
+		pos2 += slen;
 	}
 
 	/* OSU Server URI */
@@ -1295,8 +1306,8 @@
 	wpas_notify_hs20_rx_deauth_imminent_notice(wpa_s, code, reauth_delay, url);
 
 	if (code == HS20_DEAUTH_REASON_CODE_BSS) {
-		wpa_printf(MSG_DEBUG, "HS 2.0: Add BSS to blacklist");
-		wpa_blacklist_add(wpa_s, wpa_s->bssid);
+		wpa_printf(MSG_DEBUG, "HS 2.0: Add BSS to ignore list");
+		wpa_bssid_ignore_add(wpa_s, wpa_s->bssid);
 		/* TODO: For now, disable full ESS since some drivers may not
 		 * support disabling per BSS. */
 		if (wpa_s->current_ssid) {
diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
index 3946252..b93f2a3 100644
--- a/wpa_supplicant/interworking.c
+++ b/wpa_supplicant/interworking.c
@@ -2482,7 +2482,7 @@
 		bss_load = cred_over_max_bss_load(wpa_s, cred, bss);
 		conn_capab = cred_conn_capab_missing(wpa_s, cred, bss);
 		wpa_msg(wpa_s, MSG_INFO, "%s" MACSTR " type=%s%s%s%s id=%d priority=%d sp_priority=%d",
-			excluded ? INTERWORKING_BLACKLISTED : INTERWORKING_AP,
+			excluded ? INTERWORKING_EXCLUDED : INTERWORKING_AP,
 			MAC2STR(bss->bssid), type,
 			bh ? " below_min_backhaul=1" : "",
 			bss_load ? " over_max_bss_load=1" : "",
@@ -2532,7 +2532,7 @@
 	    (selected_cred == NULL ||
 	     cred_prio_cmp(selected_home_cred, selected_cred) >= 0)) {
 		/* Prefer network operated by the Home SP */
-		wpa_printf(MSG_DEBUG, "Interworking: Overrided selected with selected_home");
+		wpa_printf(MSG_DEBUG, "Interworking: Overrode selected with selected_home");
 		selected = selected_home;
 		selected_cred = selected_home_cred;
 	}
@@ -2793,6 +2793,7 @@
 			wpa_printf(MSG_WARNING,
 				   "ANQP: Cannot send MBO query to unknown BSS "
 				   MACSTR, MAC2STR(dst));
+			wpabuf_free(extra_buf);
 			return -1;
 		}
 
@@ -2831,7 +2832,7 @@
 
 static void anqp_add_extra(struct wpa_supplicant *wpa_s,
 			   struct wpa_bss_anqp *anqp, u16 info_id,
-			   const u8 *data, size_t slen)
+			   const u8 *data, size_t slen, bool protected_response)
 {
 	struct wpa_bss_anqp_elem *tmp, *elem = NULL;
 
@@ -2856,6 +2857,7 @@
 		wpabuf_free(elem->payload);
 	}
 
+	elem->protected_response = protected_response;
 	elem->payload = wpabuf_alloc_copy(data, slen);
 	if (!elem->payload) {
 		dl_list_del(&elem->list);
@@ -2898,6 +2900,7 @@
 	const u8 *pos = data;
 	struct wpa_bss_anqp *anqp = NULL;
 	u8 type;
+	bool protected_response;
 
 	if (bss)
 		anqp = bss->anqp;
@@ -2998,13 +3001,15 @@
 	case ANQP_VENUE_URL:
 		wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR " Venue URL",
 			MAC2STR(sa));
+		protected_response = pmf_in_use(wpa_s, sa);
+		anqp_add_extra(wpa_s, anqp, info_id, pos, slen,
+			       protected_response);
 
-		if (!pmf_in_use(wpa_s, sa)) {
+		if (!protected_response) {
 			wpa_printf(MSG_DEBUG,
 				   "ANQP: Ignore Venue URL since PMF was not enabled");
 			break;
 		}
-		anqp_add_extra(wpa_s, anqp, info_id, pos, slen);
 		interworking_parse_venue_url(wpa_s, pos, slen);
 		break;
 	case ANQP_VENDOR_SPECIFIC:
@@ -3052,7 +3057,8 @@
 	default:
 		wpa_msg(wpa_s, MSG_DEBUG,
 			"Interworking: Unsupported ANQP Info ID %u", info_id);
-		anqp_add_extra(wpa_s, anqp, info_id, data, slen);
+		anqp_add_extra(wpa_s, anqp, info_id, data, slen,
+			       pmf_in_use(wpa_s, sa));
 		break;
 	}
 }
diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c
index 558d87a..901b49b 100644
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
@@ -13,6 +13,7 @@
 #include "utils/uuid.h"
 #include "common/ieee802_11_defs.h"
 #include "common/wpa_ctrl.h"
+#include "common/hw_features_common.h"
 #include "ap/sta_info.h"
 #include "ap/hostapd.h"
 #include "ap/ieee802_11.h"
@@ -27,22 +28,30 @@
 #include "mesh.h"
 
 
-static void wpa_supplicant_mesh_deinit(struct wpa_supplicant *wpa_s)
+static void wpa_supplicant_mesh_deinit(struct wpa_supplicant *wpa_s,
+				       bool also_clear_hostapd)
 {
-	wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
-	wpa_s->ifmsh = NULL;
-	wpa_s->current_ssid = NULL;
+	wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh,
+					 also_clear_hostapd);
+
+	if (also_clear_hostapd) {
+		wpa_s->ifmsh = NULL;
+		wpa_s->current_ssid = NULL;
+		os_free(wpa_s->mesh_params);
+		wpa_s->mesh_params = NULL;
+	}
+
 	os_free(wpa_s->mesh_rsn);
 	wpa_s->mesh_rsn = NULL;
-	os_free(wpa_s->mesh_params);
-	wpa_s->mesh_params = NULL;
-	/* TODO: leave mesh (stop beacon). This will happen on link down
-	 * anyway, so it's not urgent */
+
+	if (!also_clear_hostapd)
+		wpa_supplicant_leave_mesh(wpa_s, false);
 }
 
 
 void wpa_supplicant_mesh_iface_deinit(struct wpa_supplicant *wpa_s,
-				      struct hostapd_iface *ifmsh)
+				      struct hostapd_iface *ifmsh,
+				      bool also_clear_hostapd)
 {
 	if (!ifmsh)
 		return;
@@ -63,8 +72,10 @@
 	}
 
 	/* take care of shared data */
-	hostapd_interface_deinit(ifmsh);
-	hostapd_interface_free(ifmsh);
+	if (also_clear_hostapd) {
+		hostapd_interface_deinit(ifmsh);
+		hostapd_interface_free(ifmsh);
+	}
 }
 
 
@@ -194,6 +205,40 @@
 }
 
 
+static int wpas_mesh_update_freq_params(struct wpa_supplicant *wpa_s)
+{
+	struct wpa_driver_mesh_join_params *params = wpa_s->mesh_params;
+	struct hostapd_iface *ifmsh = wpa_s->ifmsh;
+	struct he_capabilities *he_capab = NULL;
+
+	if (ifmsh->current_mode)
+		he_capab = &ifmsh->current_mode->he_capab[IEEE80211_MODE_MESH];
+
+	if (hostapd_set_freq_params(
+		    &params->freq,
+		    ifmsh->conf->hw_mode,
+		    ifmsh->freq,
+		    ifmsh->conf->channel,
+		    ifmsh->conf->enable_edmg,
+		    ifmsh->conf->edmg_channel,
+		    ifmsh->conf->ieee80211n,
+		    ifmsh->conf->ieee80211ac,
+		    ifmsh->conf->ieee80211ax,
+		    ifmsh->conf->secondary_channel,
+		    hostapd_get_oper_chwidth(ifmsh->conf),
+		    hostapd_get_oper_centr_freq_seg0_idx(ifmsh->conf),
+		    hostapd_get_oper_centr_freq_seg1_idx(ifmsh->conf),
+		    ifmsh->conf->vht_capab,
+		    he_capab)) {
+		wpa_printf(MSG_ERROR, "Error updating mesh frequency params");
+		wpa_supplicant_mesh_deinit(wpa_s, true);
+		return -1;
+	}
+
+	return 0;
+}
+
+
 static int wpas_mesh_complete(struct wpa_supplicant *wpa_s)
 {
 	struct hostapd_iface *ifmsh = wpa_s->ifmsh;
@@ -207,12 +252,22 @@
 		return -1;
 	}
 
+	/*
+	 * Update channel configuration if the channel has changed since the
+	 * initial setting, i.e., due to DFS radar detection during CAC.
+	 */
+	if (ifmsh->freq > 0 && ifmsh->freq != params->freq.freq) {
+		wpa_s->assoc_freq = ifmsh->freq;
+		ssid->frequency = ifmsh->freq;
+		if (wpas_mesh_update_freq_params(wpa_s) < 0)
+			return -1;
+	}
+
 	if (ifmsh->mconf->security != MESH_CONF_SEC_NONE &&
 	    wpas_mesh_init_rsn(wpa_s)) {
 		wpa_printf(MSG_ERROR,
 			   "mesh: RSN initialization failed - deinit mesh");
-		wpa_supplicant_mesh_deinit(wpa_s);
-		wpa_drv_leave_mesh(wpa_s);
+		wpa_supplicant_mesh_deinit(wpa_s, false);
 		return -1;
 	}
 
@@ -237,13 +292,90 @@
 	/* hostapd sets the interface down until we associate */
 	wpa_drv_set_operstate(wpa_s, 1);
 
-	if (!ret)
+	if (!ret) {
 		wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
 
+		wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d",
+			wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
+			ssid->id);
+		wpas_notify_mesh_group_started(wpa_s, ssid);
+	}
+
 	return ret;
 }
 
 
+static void wpas_mesh_complete_cb(void *arg)
+{
+	struct wpa_supplicant *wpa_s = arg;
+
+	wpas_mesh_complete(wpa_s);
+}
+
+
+static int wpa_supplicant_mesh_enable_iface_cb(struct hostapd_iface *ifmsh)
+{
+	struct wpa_supplicant *wpa_s = ifmsh->owner;
+	struct hostapd_data *bss;
+
+	ifmsh->mconf = mesh_config_create(wpa_s, wpa_s->current_ssid);
+
+	bss = ifmsh->bss[0];
+	bss->msg_ctx = wpa_s;
+	os_memcpy(bss->own_addr, wpa_s->own_addr, ETH_ALEN);
+	bss->driver = wpa_s->driver;
+	bss->drv_priv = wpa_s->drv_priv;
+	bss->iface = ifmsh;
+	bss->mesh_sta_free_cb = mesh_mpm_free_sta;
+	bss->setup_complete_cb = wpas_mesh_complete_cb;
+	bss->setup_complete_cb_ctx = wpa_s;
+
+	bss->conf->start_disabled = 1;
+	bss->conf->mesh = MESH_ENABLED;
+	bss->conf->ap_max_inactivity = wpa_s->conf->mesh_max_inactivity;
+
+	if (wpa_drv_init_mesh(wpa_s)) {
+		wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh in driver");
+		return -1;
+	}
+
+	if (hostapd_setup_interface(ifmsh)) {
+		wpa_printf(MSG_ERROR,
+			   "Failed to initialize hostapd interface for mesh");
+		return -1;
+	}
+
+	return 0;
+}
+
+
+static int wpa_supplicant_mesh_disable_iface_cb(struct hostapd_iface *ifmsh)
+{
+	struct wpa_supplicant *wpa_s = ifmsh->owner;
+	size_t j;
+
+	wpa_supplicant_mesh_deinit(wpa_s, false);
+
+#ifdef NEED_AP_MLME
+	for (j = 0; j < ifmsh->num_bss; j++)
+		hostapd_cleanup_cs_params(ifmsh->bss[j]);
+#endif /* NEED_AP_MLME */
+
+	/* Same as hostapd_interface_deinit() without deinitializing control
+	 * interface */
+	for (j = 0; j < ifmsh->num_bss; j++) {
+		struct hostapd_data *hapd = ifmsh->bss[j];
+
+		hostapd_bss_deinit_no_free(hapd);
+		hostapd_free_hapd_data(hapd);
+	}
+
+	hostapd_cleanup_iface_partial(ifmsh);
+
+	return 0;
+}
+
+
 static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
 				    struct wpa_ssid *ssid,
 				    struct hostapd_freq_params *freq)
@@ -267,9 +399,12 @@
 	if (!ifmsh)
 		return -ENOMEM;
 
+	ifmsh->owner = wpa_s;
 	ifmsh->drv_flags = wpa_s->drv_flags;
 	ifmsh->drv_flags2 = wpa_s->drv_flags2;
 	ifmsh->num_bss = 1;
+	ifmsh->enable_iface_cb = wpa_supplicant_mesh_enable_iface_cb;
+	ifmsh->disable_iface_cb = wpa_supplicant_mesh_disable_iface_cb;
 	ifmsh->bss = os_calloc(wpa_s->ifmsh->num_bss,
 			       sizeof(struct hostapd_data *));
 	if (!ifmsh->bss)
@@ -285,11 +420,14 @@
 	bss->drv_priv = wpa_s->drv_priv;
 	bss->iface = ifmsh;
 	bss->mesh_sta_free_cb = mesh_mpm_free_sta;
+	bss->setup_complete_cb = wpas_mesh_complete_cb;
+	bss->setup_complete_cb_ctx = wpa_s;
 	frequency = ssid->frequency;
 	if (frequency != freq->freq &&
 	    frequency == freq->freq + freq->sec_channel_offset * 20) {
 		wpa_printf(MSG_DEBUG, "mesh: pri/sec channels switched");
 		frequency = freq->freq;
+		ssid->frequency = frequency;
 	}
 	wpa_s->assoc_freq = frequency;
 	wpa_s->current_ssid = ssid;
@@ -311,6 +449,7 @@
 		conf->country[0] = wpa_s->conf->country[0];
 		conf->country[1] = wpa_s->conf->country[1];
 		conf->country[2] = ' ';
+		wpa_s->mesh_params->handle_dfs = true;
 	}
 
 	bss->iconf = conf;
@@ -401,7 +540,7 @@
 
 	return 0;
 out_free:
-	wpa_supplicant_mesh_deinit(wpa_s);
+	wpa_supplicant_mesh_deinit(wpa_s, true);
 	return -ENOMEM;
 }
 
@@ -449,7 +588,7 @@
 		goto out;
 	}
 
-	wpa_supplicant_mesh_deinit(wpa_s);
+	wpa_supplicant_mesh_deinit(wpa_s, true);
 
 	wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
 	wpa_s->group_cipher = WPA_CIPHER_NONE;
@@ -520,25 +659,25 @@
 	wpa_s->mesh_params = params;
 	if (wpa_supplicant_mesh_init(wpa_s, ssid, &params->freq)) {
 		wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh");
-		wpa_drv_leave_mesh(wpa_s);
+		wpa_supplicant_leave_mesh(wpa_s, true);
 		ret = -1;
 		goto out;
 	}
 
-	ret = wpas_mesh_complete(wpa_s);
 out:
 	return ret;
 }
 
 
-int wpa_supplicant_leave_mesh(struct wpa_supplicant *wpa_s)
+int wpa_supplicant_leave_mesh(struct wpa_supplicant *wpa_s, bool need_deinit)
 {
 	int ret = 0;
 
 	wpa_msg(wpa_s, MSG_INFO, "leaving mesh");
 
 	/* Need to send peering close messages first */
-	wpa_supplicant_mesh_deinit(wpa_s);
+	if (need_deinit)
+		wpa_supplicant_mesh_deinit(wpa_s, true);
 
 	ret = wpa_drv_leave_mesh(wpa_s);
 	if (ret)
diff --git a/wpa_supplicant/mesh.h b/wpa_supplicant/mesh.h
index 7317083..a429e5e 100644
--- a/wpa_supplicant/mesh.h
+++ b/wpa_supplicant/mesh.h
@@ -11,9 +11,11 @@
 
 int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s,
 			     struct wpa_ssid *ssid);
-int wpa_supplicant_leave_mesh(struct wpa_supplicant *wpa_s);
+int wpa_supplicant_leave_mesh(struct wpa_supplicant *wpa_s,
+			      bool need_deinit);
 void wpa_supplicant_mesh_iface_deinit(struct wpa_supplicant *wpa_s,
-				      struct hostapd_iface *ifmsh);
+				      struct hostapd_iface *ifmsh,
+				      bool also_clear_hostapd);
 int wpas_mesh_scan_result_text(const u8 *ies, size_t ies_len, char *buf,
 			       char *end);
 int wpas_mesh_add_interface(struct wpa_supplicant *wpa_s, char *ifname,
diff --git a/wpa_supplicant/nmake.mak b/wpa_supplicant/nmake.mak
index 80e0ac8..617df03 100644
--- a/wpa_supplicant/nmake.mak
+++ b/wpa_supplicant/nmake.mak
@@ -114,7 +114,7 @@
 	$(OBJDIR)\driver_ndis_.obj \
 	$(OBJDIR)\scan_helpers.obj \
 	$(OBJDIR)\events.obj \
-	$(OBJDIR)\blacklist.obj \
+	$(OBJDIR)\bssid_ignore.obj \
 	$(OBJDIR)\scan.obj \
 	$(OBJDIR)\wpas_glue.obj \
 	$(OBJDIR)\eap_register.obj \
diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index c01a6ee..d62c96d 100644
--- a/wpa_supplicant/notify.c
+++ b/wpa_supplicant/notify.c
@@ -428,6 +428,11 @@
 		wpas_notify_persistent_group_removed(wpa_s, ssid);
 
 	wpas_p2p_network_removed(wpa_s, ssid);
+
+#ifdef CONFIG_PASN
+	if (wpa_s->pasn.ssid == ssid)
+		wpa_s->pasn.ssid = NULL;
+#endif /* CONFIG_PASN */
 }
 
 
diff --git a/wpa_supplicant/op_classes.c b/wpa_supplicant/op_classes.c
index 91e15e7..a0ad0c2 100644
--- a/wpa_supplicant/op_classes.c
+++ b/wpa_supplicant/op_classes.c
@@ -22,10 +22,10 @@
 				       unsigned int *flags)
 {
 	int i;
-	int is_6ghz = op_class >= 131 && op_class <= 136;
+	bool is_6ghz = op_class >= 131 && op_class <= 136;
 
 	for (i = 0; i < mode->num_channels; i++) {
-		int chan_is_6ghz;
+		bool chan_is_6ghz;
 
 		chan_is_6ghz = mode->channels[i].freq >= 5935 &&
 			mode->channels[i].freq <= 7115;
@@ -47,15 +47,15 @@
 }
 
 
-static int get_center_80mhz(struct hostapd_hw_modes *mode, u8 channel)
+static int get_center_80mhz(struct hostapd_hw_modes *mode, u8 channel,
+			    const u8 *center_channels, size_t num_chan)
 {
-	u8 center_channels[] = { 42, 58, 106, 122, 138, 155 };
 	size_t i;
 
 	if (mode->mode != HOSTAPD_MODE_IEEE80211A)
 		return 0;
 
-	for (i = 0; i < ARRAY_SIZE(center_channels); i++) {
+	for (i = 0; i < num_chan; i++) {
 		/*
 		 * In 80 MHz, the bandwidth "spans" 12 channels (e.g., 36-48),
 		 * so the center channel is 6 channels away from the start/end.
@@ -75,8 +75,22 @@
 	u8 center_chan;
 	unsigned int i;
 	unsigned int no_ir = 0;
+	const u8 *center_channels;
+	size_t num_chan;
+	const u8 center_channels_5ghz[] = { 42, 58, 106, 122, 138, 155, 171 };
+	const u8 center_channels_6ghz[] = { 7, 23, 39, 55, 71, 87, 103, 119,
+					    135, 151, 167, 183, 199, 215 };
 
-	center_chan = get_center_80mhz(mode, channel);
+	if (is_6ghz_op_class(op_class)) {
+		center_channels = center_channels_6ghz;
+		num_chan = ARRAY_SIZE(center_channels_6ghz);
+	} else {
+		center_channels = center_channels_5ghz;
+		num_chan = ARRAY_SIZE(center_channels_5ghz);
+	}
+
+	center_chan = get_center_80mhz(mode, channel, center_channels,
+				       num_chan);
 	if (!center_chan)
 		return NOT_ALLOWED;
 
@@ -106,15 +120,15 @@
 }
 
 
-static int get_center_160mhz(struct hostapd_hw_modes *mode, u8 channel)
+static int get_center_160mhz(struct hostapd_hw_modes *mode, u8 channel,
+			     const u8 *center_channels, size_t num_chan)
 {
-	u8 center_channels[] = { 50, 114 };
 	unsigned int i;
 
 	if (mode->mode != HOSTAPD_MODE_IEEE80211A)
 		return 0;
 
-	for (i = 0; i < ARRAY_SIZE(center_channels); i++) {
+	for (i = 0; i < num_chan; i++) {
 		/*
 		 * In 160 MHz, the bandwidth "spans" 28 channels (e.g., 36-64),
 		 * so the center channel is 14 channels away from the start/end.
@@ -134,8 +148,21 @@
 	u8 center_chan;
 	unsigned int i;
 	unsigned int no_ir = 0;
+	const u8 *center_channels;
+	size_t num_chan;
+	const u8 center_channels_5ghz[] = { 50, 114, 163 };
+	const u8 center_channels_6ghz[] = { 15, 47, 79, 111, 143, 175, 207 };
 
-	center_chan = get_center_160mhz(mode, channel);
+	if (is_6ghz_op_class(op_class)) {
+		center_channels = center_channels_6ghz;
+		num_chan = ARRAY_SIZE(center_channels_6ghz);
+	} else {
+		center_channels = center_channels_5ghz;
+		num_chan = ARRAY_SIZE(center_channels_5ghz);
+	}
+
+	center_chan = get_center_160mhz(mode, channel, center_channels,
+					num_chan);
 	if (!center_chan)
 		return NOT_ALLOWED;
 
@@ -176,11 +203,12 @@
 	enum chan_allowed res, res2;
 
 	res2 = res = allow_channel(mode, op_class, channel, &flag);
-	if (bw == BW40MINUS) {
+	if (bw == BW40MINUS || (bw == BW40 && (((channel - 1) / 4) % 2))) {
 		if (!(flag & HOSTAPD_CHAN_HT40MINUS))
 			return NOT_ALLOWED;
 		res2 = allow_channel(mode, op_class, channel - 4, NULL);
-	} else if (bw == BW40PLUS) {
+	} else if (bw == BW40PLUS ||
+		   (bw == BW40 && !(((channel - 1) / 4) % 2))) {
 		if (!(flag & HOSTAPD_CHAN_HT40PLUS))
 			return NOT_ALLOWED;
 		res2 = allow_channel(mode, op_class, channel + 4, NULL);
@@ -292,7 +320,7 @@
 #endif /* CONFIG_VHT_OVERRIDES */
 
 	if (op_class->op_class == 128) {
-		u8 channels[] = { 42, 58, 106, 122, 138, 155 };
+		u8 channels[] = { 42, 58, 106, 122, 138, 155, 171 };
 
 		for (i = 0; i < ARRAY_SIZE(channels); i++) {
 			if (verify_channel(mode, op_class->op_class,
@@ -309,6 +337,8 @@
 		return verify_channel(mode, op_class->op_class, 50,
 				      op_class->bw) != NOT_ALLOWED ||
 			verify_channel(mode, op_class->op_class, 114,
+				       op_class->bw) != NOT_ALLOWED ||
+			verify_channel(mode, op_class->op_class, 163,
 				       op_class->bw) != NOT_ALLOWED;
 	}
 
@@ -326,6 +356,10 @@
 		    verify_channel(mode, op_class->op_class, 122,
 				   op_class->bw) != NOT_ALLOWED ||
 		    verify_channel(mode, op_class->op_class, 138,
+				   op_class->bw) != NOT_ALLOWED ||
+		    verify_channel(mode, op_class->op_class, 155,
+				   op_class->bw) != NOT_ALLOWED ||
+		    verify_channel(mode, op_class->op_class, 171,
 				   op_class->bw) != NOT_ALLOWED)
 			found++;
 		if (verify_channel(mode, op_class->op_class, 106,
@@ -333,7 +367,14 @@
 		    verify_channel(mode, op_class->op_class, 138,
 				   op_class->bw) != NOT_ALLOWED)
 			found++;
-		if (verify_channel(mode, op_class->op_class, 155,
+		if (verify_channel(mode, op_class->op_class, 122,
+				   op_class->bw) != NOT_ALLOWED &&
+		    verify_channel(mode, op_class->op_class, 155,
+				   op_class->bw) != NOT_ALLOWED)
+			found++;
+		if (verify_channel(mode, op_class->op_class, 138,
+				   op_class->bw) != NOT_ALLOWED &&
+		    verify_channel(mode, op_class->op_class, 171,
 				   op_class->bw) != NOT_ALLOWED)
 			found++;
 
@@ -343,6 +384,41 @@
 		return 0;
 	}
 
+	if (op_class->op_class == 135) {
+		/* Need at least two 80 MHz segments which do not fall under the
+		 * same 160 MHz segment to support 80+80 in 6 GHz.
+		 */
+		int first_seg = 0;
+		int curr_seg = 0;
+
+		for (chan = op_class->min_chan; chan <= op_class->max_chan;
+		     chan += op_class->inc) {
+			curr_seg++;
+			if (verify_channel(mode, op_class->op_class, chan,
+					   op_class->bw) != NOT_ALLOWED) {
+				if (!first_seg) {
+					first_seg = curr_seg;
+					continue;
+				}
+
+				/* Supported if at least two non-consecutive 80
+				 * MHz segments allowed.
+				 */
+				if ((curr_seg - first_seg) > 1)
+					return 1;
+
+				/* Supported even if the 80 MHz segments are
+				 * consecutive when they do not fall under the
+				 * same 160 MHz segment.
+				 */
+				if ((first_seg % 2) == 0)
+					return 1;
+			}
+		}
+
+		return 0;
+	}
+
 	found = 0;
 	for (chan = op_class->min_chan; chan <= op_class->max_chan;
 	     chan += op_class->inc) {
@@ -361,12 +437,13 @@
 					     u8 *channel)
 {
 
-	u8 *ies, phy_type;
+	const u8 *ies;
+	u8 phy_type;
 	size_t ies_len;
 
 	if (!bss)
 		return -1;
-	ies = (u8 *) (bss + 1);
+	ies = wpa_bss_ie_ptr(bss);
 	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);
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index dc5c16d..45c8744 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -242,6 +242,22 @@
 }
 
 
+static void wpas_p2p_scan_res_handled(struct wpa_supplicant *wpa_s)
+{
+	unsigned int delay = wpas_p2p_search_delay(wpa_s);
+
+	/* In case of concurrent P2P and external scans, delay P2P search. */
+	if (external_scan_running(wpa_s->radio)) {
+		delay = wpa_s->conf->p2p_search_delay;
+		wpa_printf(MSG_DEBUG,
+			   "P2P: Delay next P2P search by %d ms to let externally triggered scan complete",
+			   delay);
+	}
+
+	p2p_scan_res_handled(wpa_s->global->p2p, delay);
+}
+
+
 static void wpas_p2p_scan_res_handler(struct wpa_supplicant *wpa_s,
 				      struct wpa_scan_results *scan_res)
 {
@@ -287,42 +303,25 @@
 			break;
 	}
 
-	p2p_scan_res_handled(wpa_s->global->p2p);
+	wpas_p2p_scan_res_handled(wpa_s);
 }
 
 
-static int wpas_p2p_add_scan_freq_list(struct wpa_supplicant *wpa_s,
-				       enum hostapd_hw_mode band,
-				       struct wpa_driver_scan_params *params)
+static void wpas_p2p_scan_res_fail_handler(struct wpa_supplicant *wpa_s)
 {
-	struct hostapd_hw_modes *mode;
-	int num_chans = 0;
-	int *freqs, i;
+	if (wpa_s->p2p_scan_work) {
+		struct wpa_radio_work *work = wpa_s->p2p_scan_work;
 
-	mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, band, 0);
-	if (!mode)
-		return -1;
-
-	if (params->freqs) {
-		while (params->freqs[num_chans])
-			num_chans++;
+		wpa_s->p2p_scan_work = NULL;
+		radio_work_done(work);
 	}
 
-	freqs = os_realloc(params->freqs,
-			   (num_chans + mode->num_channels + 1) * sizeof(int));
-	if (!freqs)
-		return -1;
+	if (wpa_s->global->p2p_disabled || !wpa_s->global->p2p)
+		return;
 
-	params->freqs = freqs;
-
-	for (i = 0; i < mode->num_channels; i++) {
-		if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED)
-			continue;
-		params->freqs[num_chans++] = mode->channels[i].freq;
-	}
-	params->freqs[num_chans] = 0;
-
-	return 0;
+	wpa_dbg(wpa_s, MSG_DEBUG,
+		"P2P: Failed to get scan results - try to continue");
+	wpas_p2p_scan_res_handled(wpa_s);
 }
 
 
@@ -351,10 +350,10 @@
 	if (wpa_s->conf->p2p_6ghz_disable && !params->freqs) {
 		wpa_printf(MSG_DEBUG,
 			   "P2P: 6 GHz disabled - update the scan frequency list");
-		wpas_p2p_add_scan_freq_list(wpa_s, HOSTAPD_MODE_IEEE80211G,
-					    params);
-		wpas_p2p_add_scan_freq_list(wpa_s, HOSTAPD_MODE_IEEE80211A,
-					    params);
+		wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G, params,
+					0);
+		wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, params,
+					0);
 	}
 	ret = wpa_drv_scan(wpa_s, params);
 	if (ret == 0)
@@ -370,6 +369,7 @@
 	p2p_notify_scan_trigger_status(wpa_s->global->p2p, ret);
 	os_get_reltime(&wpa_s->scan_trigger_time);
 	wpa_s->scan_res_handler = wpas_p2p_scan_res_handler;
+	wpa_s->scan_res_fail_handler = wpas_p2p_scan_res_fail_handler;
 	wpa_s->own_scan_requested = 1;
 	wpa_s->clear_driver_scan_cache = 0;
 	wpa_s->p2p_scan_work = work;
@@ -1107,9 +1107,9 @@
 			   "group is persistent - BSS " MACSTR
 			   " did not include P2P IE", MAC2STR(bssid));
 		wpa_hexdump(MSG_DEBUG, "P2P: Probe Response IEs",
-			    (u8 *) (bss + 1), bss->ie_len);
+			    wpa_bss_ie_ptr(bss), bss->ie_len);
 		wpa_hexdump(MSG_DEBUG, "P2P: Beacon IEs",
-			    ((u8 *) bss + 1) + bss->ie_len,
+			    wpa_bss_ie_ptr(bss) + bss->ie_len,
 			    bss->beacon_ie_len);
 		return 0;
 	}
@@ -1956,7 +1956,7 @@
 		return -1;
 
 	hwmode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
-			  HOSTAPD_MODE_IEEE80211AD, 0);
+			  HOSTAPD_MODE_IEEE80211AD, false);
 	if (!hwmode) {
 		wpa_printf(MSG_ERROR,
 			   "Unsupported AP mode: HOSTAPD_MODE_IEEE80211AD");
@@ -2161,6 +2161,7 @@
 	d->go_internet = s->go_internet;
 	d->go_venue_group = s->go_venue_group;
 	d->go_venue_type = s->go_venue_type;
+	d->p2p_add_cli_chan = s->p2p_add_cli_chan;
 }
 
 
@@ -3587,7 +3588,7 @@
 				     struct hostapd_hw_modes *mode,
 				     u8 channel)
 {
-	u8 center_channels[] = { 42, 58, 106, 122, 138, 155 };
+	u8 center_channels[] = { 42, 58, 106, 122, 138, 155, 171 };
 	size_t i;
 
 	if (mode->mode != HOSTAPD_MODE_IEEE80211A)
@@ -3648,7 +3649,7 @@
 				     struct hostapd_hw_modes *mode,
 				     u8 channel)
 {
-	u8 center_channels[] = { 50, 114 };
+	u8 center_channels[] = { 50, 114, 163 };
 	unsigned int i;
 
 	if (mode->mode != HOSTAPD_MODE_IEEE80211A)
@@ -3761,7 +3762,8 @@
 
 static int wpas_p2p_setup_channels(struct wpa_supplicant *wpa_s,
 				   struct p2p_channels *chan,
-				   struct p2p_channels *cli_chan)
+				   struct p2p_channels *cli_chan,
+				   bool p2p_disable_6ghz)
 {
 	struct hostapd_hw_modes *mode;
 	int cla, op, cli_cla;
@@ -3781,8 +3783,7 @@
 		struct p2p_reg_class *reg = NULL, *cli_reg = NULL;
 
 		if (o->p2p == NO_P2P_SUPP ||
-		    (is_6ghz_op_class(o->op_class) &&
-		     wpa_s->conf->p2p_6ghz_disable))
+		    (is_6ghz_op_class(o->op_class) && p2p_disable_6ghz))
 			continue;
 
 		mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, o->mode,
@@ -3796,7 +3797,7 @@
 
 			/* Check for non-continuous jump in channel index
 			 * incrementation */
-			if ((o->op_class == 128 || o->op_class == 130) &&
+			if ((o->op_class >= 128 && o->op_class <= 130) &&
 			    ch < 149 && ch + o->inc > 149)
 				ch = 149;
 
@@ -3989,6 +3990,7 @@
 	char ifname[100];
 	char force_name[100];
 	int ret;
+	const u8 *if_addr = NULL;
 
 	ret = os_snprintf(ifname, sizeof(ifname), P2P_MGMT_DEVICE_PREFIX "%s",
 			  wpa_s->ifname);
@@ -4000,7 +4002,12 @@
 	ifname[IFNAMSIZ - 1] = '\0';
 	force_name[0] = '\0';
 	wpa_s->pending_interface_type = WPA_IF_P2P_DEVICE;
-	ret = wpa_drv_if_add(wpa_s, WPA_IF_P2P_DEVICE, ifname, NULL, NULL,
+
+	if (wpa_s->conf->p2p_device_random_mac_addr == 2 &&
+	    !is_zero_ether_addr(wpa_s->conf->p2p_device_persistent_mac_addr))
+		if_addr = wpa_s->conf->p2p_device_persistent_mac_addr;
+
+	ret = wpa_drv_if_add(wpa_s, WPA_IF_P2P_DEVICE, ifname, if_addr, NULL,
 			     force_name, wpa_s->pending_interface_addr, NULL);
 	if (ret < 0) {
 		wpa_printf(MSG_DEBUG, "P2P: Failed to create P2P Device interface");
@@ -4576,7 +4583,17 @@
 	if (wpa_s->conf->p2p_device_random_mac_addr == 0)
 		return 0;
 
-	if (wpa_s->conf->ssid == NULL) {
+	if (wpa_s->conf->p2p_device_random_mac_addr == 2) {
+		if (is_zero_ether_addr(
+			    wpa_s->conf->p2p_device_persistent_mac_addr) &&
+		    !is_zero_ether_addr(wpa_s->own_addr)) {
+			os_memcpy(wpa_s->conf->p2p_device_persistent_mac_addr,
+				  wpa_s->own_addr, ETH_ALEN);
+		}
+		return 0;
+	}
+
+	if (!wpa_s->conf->ssid) {
 		if (random_mac_addr(addr) < 0) {
 			wpa_msg(wpa_s, MSG_INFO,
 				"Failed to generate random MAC address");
@@ -4676,6 +4693,7 @@
 	p2p.prov_disc_resp_cb = wpas_prov_disc_resp_cb;
 	p2p.p2ps_group_capability = p2ps_group_capability;
 	p2p.get_pref_freq_list = wpas_p2p_get_pref_freq_list;
+	p2p.p2p_6ghz_disable = wpa_s->conf->p2p_6ghz_disable;
 
 	os_memcpy(wpa_s->global->p2p_dev_addr, wpa_s->own_addr, ETH_ALEN);
 	os_memcpy(p2p.dev_addr, wpa_s->global->p2p_dev_addr, ETH_ALEN);
@@ -4689,7 +4707,8 @@
 		p2p.config_methods = wpa_s->wps->config_methods;
 	}
 
-	if (wpas_p2p_setup_channels(wpa_s, &p2p.channels, &p2p.cli_channels)) {
+	if (wpas_p2p_setup_channels(wpa_s, &p2p.channels, &p2p.cli_channels,
+				    p2p.p2p_6ghz_disable)) {
 		wpa_printf(MSG_ERROR,
 			   "P2P: Failed to configure supported channel list");
 		return -1;
@@ -5205,7 +5224,7 @@
 		wpa_printf(MSG_DEBUG, "P2P: Target GO operating frequency "
 			   "from BSS table: %d MHz (SSID %s)", freq,
 			   wpa_ssid_txt(bss->ssid, bss->ssid_len));
-		if (p2p_parse_dev_addr((const u8 *) (bss + 1), bss->ie_len,
+		if (p2p_parse_dev_addr(wpa_bss_ie_ptr(bss), bss->ie_len,
 				       dev_addr) == 0 &&
 		    os_memcmp(wpa_s->pending_join_dev_addr,
 			      wpa_s->pending_join_iface_addr, ETH_ALEN) == 0 &&
@@ -5347,10 +5366,10 @@
 	} else if (wpa_s->conf->p2p_6ghz_disable) {
 		wpa_printf(MSG_DEBUG,
 			   "P2P: 6 GHz disabled - update the scan frequency list");
-		wpas_p2p_add_scan_freq_list(wpa_s, HOSTAPD_MODE_IEEE80211G,
-					    &params);
-		wpas_p2p_add_scan_freq_list(wpa_s, HOSTAPD_MODE_IEEE80211A,
-					    &params);
+		wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G, &params,
+					0);
+		wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, &params,
+					0);
 	}
 
 	ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p);
@@ -7133,7 +7152,7 @@
 	 * Indicate that results have been processed so that the P2P module can
 	 * continue pending tasks.
 	 */
-	p2p_scan_res_handled(wpa_s->global->p2p);
+	wpas_p2p_scan_res_handled(wpa_s);
 }
 
 
@@ -8048,7 +8067,8 @@
 
 	os_memset(&chan, 0, sizeof(chan));
 	os_memset(&cli_chan, 0, sizeof(cli_chan));
-	if (wpas_p2p_setup_channels(wpa_s, &chan, &cli_chan)) {
+	if (wpas_p2p_setup_channels(wpa_s, &chan, &cli_chan,
+				    is_p2p_6ghz_disabled(wpa_s->global->p2p))) {
 		wpa_printf(MSG_ERROR, "P2P: Failed to update supported "
 			   "channel list");
 		return;
diff --git a/wpa_supplicant/pasn_supplicant.c b/wpa_supplicant/pasn_supplicant.c
new file mode 100644
index 0000000..4f5ac58
--- /dev/null
+++ b/wpa_supplicant/pasn_supplicant.c
@@ -0,0 +1,1509 @@
+/*
+ * wpa_supplicant - PASN processing
+ *
+ * Copyright (C) 2019 Intel Corporation
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "includes.h"
+
+#include "common/ieee802_11_defs.h"
+#include "common/ieee802_11_common.h"
+#include "common/dragonfly.h"
+#include "common/ptksa_cache.h"
+#include "utils/eloop.h"
+#include "drivers/driver.h"
+#include "crypto/crypto.h"
+#include "crypto/random.h"
+#include "eap_common/eap_defs.h"
+#include "rsn_supp/wpa.h"
+#include "rsn_supp/pmksa_cache.h"
+#include "wpa_supplicant_i.h"
+#include "driver_i.h"
+#include "bss.h"
+#include "config.h"
+
+static const int dot11RSNAConfigPMKLifetime = 43200;
+
+struct wpa_pasn_auth_work {
+	u8 bssid[ETH_ALEN];
+	int akmp;
+	int cipher;
+	u16 group;
+	int network_id;
+};
+
+
+static void wpas_pasn_auth_work_timeout(void *eloop_ctx, void *timeout_ctx)
+{
+	struct wpa_supplicant *wpa_s = eloop_ctx;
+
+	wpa_printf(MSG_DEBUG, "PASN: Auth work timeout - stopping auth");
+
+	wpas_pasn_auth_stop(wpa_s);
+}
+
+
+static void wpas_pasn_cancel_auth_work(struct wpa_supplicant *wpa_s)
+{
+	wpa_printf(MSG_DEBUG, "PASN: Cancel pasn-start-auth work");
+
+	/* Remove pending/started work */
+	radio_remove_works(wpa_s, "pasn-start-auth", 0);
+}
+
+
+static void wpas_pasn_auth_status(struct wpa_supplicant *wpa_s, const u8 *bssid,
+				  int akmp, int cipher, u8 status)
+{
+	wpa_msg(wpa_s, MSG_INFO,
+		PASN_AUTH_STATUS MACSTR " akmp=%s, status=%u",
+		MAC2STR(bssid), wpa_key_mgmt_txt(akmp, WPA_PROTO_RSN),
+		status);
+}
+
+
+#ifdef CONFIG_SAE
+
+static struct wpabuf * wpas_pasn_wd_sae_commit(struct wpa_supplicant *wpa_s)
+{
+	struct wpas_pasn *pasn = &wpa_s->pasn;
+	struct wpabuf *buf = NULL;
+	const char *password = NULL;
+	int ret;
+
+	if (pasn->ssid) {
+		password = pasn->ssid->sae_password;
+		if (!password)
+			password = pasn->ssid->passphrase;
+	}
+
+	if (!password) {
+		wpa_printf(MSG_DEBUG, "PASN: SAE without a password");
+		return NULL;
+	}
+
+	ret = sae_set_group(&pasn->sae, pasn->group);
+	if (ret) {
+		wpa_printf(MSG_DEBUG, "PASN: Failed to set SAE group");
+		return NULL;
+	}
+
+	/* TODO: SAE H2E */
+	ret = sae_prepare_commit(wpa_s->own_addr, pasn->bssid,
+				 (const u8 *) password, os_strlen(password), 0,
+				 &pasn->sae);
+	if (ret) {
+		wpa_printf(MSG_DEBUG, "PASN: Failed to prepare SAE commit");
+		return NULL;
+	}
+
+	/* Need to add the entire Authentication frame body */
+	buf = wpabuf_alloc(6 + SAE_COMMIT_MAX_LEN);
+	if (!buf) {
+		wpa_printf(MSG_DEBUG, "PASN: Failed to allocate SAE buffer");
+		return NULL;
+	}
+
+	wpabuf_put_le16(buf, WLAN_AUTH_SAE);
+	wpabuf_put_le16(buf, 1);
+	wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
+
+	sae_write_commit(&pasn->sae, buf, NULL, 0);
+	pasn->sae.state = SAE_COMMITTED;
+
+	return buf;
+}
+
+
+static int wpas_pasn_wd_sae_rx(struct wpa_supplicant *wpa_s, struct wpabuf *wd)
+{
+	struct wpas_pasn *pasn = &wpa_s->pasn;
+	const u8 *data;
+	size_t buf_len;
+	u16 len, res, alg, seq, status;
+	int groups[] = { pasn->group, 0 };
+	int ret;
+
+	if (!wd)
+		return -1;
+
+	data = wpabuf_head_u8(wd);
+	buf_len = wpabuf_len(wd);
+
+	/* first handle the commit message */
+	if (buf_len < 2) {
+		wpa_printf(MSG_DEBUG, "PASN: SAE buffer too short (commit)");
+		return -1;
+	}
+
+	len = WPA_GET_LE16(data);
+	if (len < 6 || buf_len - 2 < len) {
+		wpa_printf(MSG_DEBUG, "PASN: SAE buffer too short for commit");
+		return -1;
+	}
+
+	buf_len -= 2;
+	data += 2;
+
+	alg = WPA_GET_LE16(data);
+	seq = WPA_GET_LE16(data + 2);
+	status = WPA_GET_LE16(data + 4);
+
+	wpa_printf(MSG_DEBUG, "PASN: SAE: commit: alg=%u, seq=%u, status=%u",
+		   alg, seq, status);
+
+	/* TODO: SAE H2E */
+	if (alg != WLAN_AUTH_SAE || seq != 1 || status != WLAN_STATUS_SUCCESS) {
+		wpa_printf(MSG_DEBUG, "PASN: SAE: dropping peer commit");
+		return -1;
+	}
+
+	res = sae_parse_commit(&pasn->sae, data + 6, len - 6, NULL, 0, groups,
+			       0);
+	if (res != WLAN_STATUS_SUCCESS) {
+		wpa_printf(MSG_DEBUG, "PASN: SAE failed parsing commit");
+		return -1;
+	}
+
+	/* Process the commit message and derive the PMK */
+	ret = sae_process_commit(&pasn->sae);
+	if (ret) {
+		wpa_printf(MSG_DEBUG, "SAE: Failed to process peer commit");
+		return -1;
+	}
+
+	buf_len -= len;
+	data += len;
+
+	/* Handle the confirm message */
+	if (buf_len < 2) {
+		wpa_printf(MSG_DEBUG, "PASN: SAE buffer too short (confirm)");
+		return -1;
+	}
+
+	len = WPA_GET_LE16(data);
+	if (len < 6 || buf_len - 2 < len) {
+		wpa_printf(MSG_DEBUG, "PASN: SAE buffer too short for confirm");
+		return -1;
+	}
+
+	buf_len -= 2;
+	data += 2;
+
+	alg = WPA_GET_LE16(data);
+	seq = WPA_GET_LE16(data + 2);
+	status = WPA_GET_LE16(data + 4);
+
+	wpa_printf(MSG_DEBUG, "PASN: SAE confirm: alg=%u, seq=%u, status=%u",
+		   alg, seq, status);
+
+	if (alg != WLAN_AUTH_SAE || seq != 2 || status != WLAN_STATUS_SUCCESS) {
+		wpa_printf(MSG_DEBUG, "PASN: Dropping peer SAE confirm");
+		return -1;
+	}
+
+	res = sae_check_confirm(&pasn->sae, data + 6, len - 6);
+	if (res != WLAN_STATUS_SUCCESS) {
+		wpa_printf(MSG_DEBUG, "PASN: SAE failed checking confirm");
+		return -1;
+	}
+
+	wpa_printf(MSG_DEBUG, "PASN: SAE completed successfully");
+	pasn->sae.state = SAE_ACCEPTED;
+
+	return 0;
+}
+
+
+static struct wpabuf * wpas_pasn_wd_sae_confirm(struct wpa_supplicant *wpa_s)
+{
+	struct wpas_pasn *pasn = &wpa_s->pasn;
+	struct wpabuf *buf = NULL;
+
+	/* Need to add the entire authentication frame body */
+	buf = wpabuf_alloc(6 + SAE_CONFIRM_MAX_LEN);
+	if (!buf) {
+		wpa_printf(MSG_DEBUG, "PASN: Failed to allocate SAE buffer");
+		return NULL;
+	}
+
+	wpabuf_put_le16(buf, WLAN_AUTH_SAE);
+	wpabuf_put_le16(buf, 2);
+	wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
+
+	sae_write_confirm(&pasn->sae, buf);
+	pasn->sae.state = SAE_CONFIRMED;
+
+	return buf;
+}
+
+#endif /* CONFIG_SAE */
+
+
+#ifdef CONFIG_FILS
+
+static struct wpabuf * wpas_pasn_fils_build_auth(struct wpa_supplicant *wpa_s)
+{
+	struct wpas_pasn *pasn = &wpa_s->pasn;
+	struct wpabuf *buf = NULL;
+	struct wpabuf *erp_msg;
+	int ret;
+
+	erp_msg = eapol_sm_build_erp_reauth_start(wpa_s->eapol);
+	if (!erp_msg) {
+		wpa_printf(MSG_DEBUG,
+			   "PASN: FILS: ERP EAP-Initiate/Re-auth unavailable");
+		return NULL;
+	}
+
+	if (random_get_bytes(pasn->fils.nonce, FILS_NONCE_LEN) < 0 ||
+	    random_get_bytes(pasn->fils.session, FILS_SESSION_LEN) < 0)
+		goto fail;
+
+	wpa_hexdump(MSG_DEBUG, "PASN: FILS: Nonce", pasn->fils.nonce,
+		    FILS_NONCE_LEN);
+
+	wpa_hexdump(MSG_DEBUG, "PASN: FILS: Session", pasn->fils.session,
+		    FILS_SESSION_LEN);
+
+	buf = wpabuf_alloc(1500);
+	if (!buf)
+		goto fail;
+
+	/* Add the authentication algorithm */
+	wpabuf_put_le16(buf, WLAN_AUTH_FILS_SK);
+
+	/* Authentication Transaction seq# */
+	wpabuf_put_le16(buf, 1);
+
+	/* Status Code */
+	wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
+
+	/* Own RSNE */
+	wpa_pasn_add_rsne(buf, NULL, pasn->akmp, pasn->cipher);
+
+	/* FILS Nonce */
+	wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
+	wpabuf_put_u8(buf, 1 + FILS_NONCE_LEN);
+	wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_NONCE);
+	wpabuf_put_data(buf, pasn->fils.nonce, FILS_NONCE_LEN);
+
+	/* FILS Session */
+	wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
+	wpabuf_put_u8(buf, 1 + FILS_SESSION_LEN);
+	wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_SESSION);
+	wpabuf_put_data(buf, pasn->fils.session, FILS_SESSION_LEN);
+
+	/* Wrapped Data (ERP) */
+	wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
+	wpabuf_put_u8(buf, 1 + wpabuf_len(erp_msg));
+	wpabuf_put_u8(buf, WLAN_EID_EXT_WRAPPED_DATA);
+	wpabuf_put_buf(buf, erp_msg);
+
+	/*
+	 * Calculate pending PMKID here so that we do not need to maintain a
+	 * copy of the EAP-Initiate/Reauth message.
+	 */
+	ret = fils_pmkid_erp(pasn->akmp, wpabuf_head(erp_msg),
+			     wpabuf_len(erp_msg),
+			     pasn->fils.erp_pmkid);
+	if (ret) {
+		wpa_printf(MSG_DEBUG, "PASN: FILS: Failed to get ERP PMKID");
+		goto fail;
+	}
+
+	wpabuf_free(erp_msg);
+	erp_msg = NULL;
+
+	wpa_hexdump_buf(MSG_DEBUG, "PASN: FILS: Authentication frame", buf);
+	return buf;
+fail:
+	wpabuf_free(erp_msg);
+	wpabuf_free(buf);
+	return NULL;
+}
+
+
+static void wpas_pasn_initiate_eapol(struct wpa_supplicant *wpa_s)
+{
+	struct wpas_pasn *pasn = &wpa_s->pasn;
+	struct eapol_config eapol_conf;
+	struct wpa_ssid *ssid = pasn->ssid;
+
+	wpa_printf(MSG_DEBUG, "PASN: FILS: Initiating EAPOL");
+
+	eapol_sm_notify_eap_success(wpa_s->eapol, false);
+	eapol_sm_notify_eap_fail(wpa_s->eapol, false);
+	eapol_sm_notify_portControl(wpa_s->eapol, Auto);
+
+	os_memset(&eapol_conf, 0, sizeof(eapol_conf));
+	eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
+	eapol_conf.workaround = ssid->eap_workaround;
+
+	eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
+}
+
+
+static struct wpabuf * wpas_pasn_wd_fils_auth(struct wpa_supplicant *wpa_s)
+{
+	struct wpas_pasn *pasn = &wpa_s->pasn;
+	struct wpa_bss *bss;
+	const u8 *indic;
+	u16 fils_info;
+
+	wpa_printf(MSG_DEBUG, "PASN: FILS: wrapped data - completed=%u",
+		   pasn->fils.completed);
+
+	/* Nothing to add as we are done */
+	if (pasn->fils.completed)
+		return NULL;
+
+	if (!pasn->ssid) {
+		wpa_printf(MSG_DEBUG, "PASN: FILS: No network block");
+		return NULL;
+	}
+
+	bss = wpa_bss_get_bssid(wpa_s, pasn->bssid);
+	if (!bss) {
+		wpa_printf(MSG_DEBUG, "PASN: FILS: BSS not found");
+		return NULL;
+	}
+
+	indic = wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION);
+	if (!indic || indic[1] < 2) {
+		wpa_printf(MSG_DEBUG, "PASN: Missing FILS Indication IE");
+		return NULL;
+	}
+
+	fils_info = WPA_GET_LE16(indic + 2);
+	if (!(fils_info & BIT(9))) {
+		wpa_printf(MSG_DEBUG,
+			   "PASN: FILS auth without PFS not supported");
+		return NULL;
+	}
+
+	wpas_pasn_initiate_eapol(wpa_s);
+
+	return wpas_pasn_fils_build_auth(wpa_s);
+}
+
+
+static int wpas_pasn_wd_fils_rx(struct wpa_supplicant *wpa_s, struct wpabuf *wd)
+{
+	struct wpas_pasn *pasn = &wpa_s->pasn;
+	struct ieee802_11_elems elems;
+	struct wpa_ie_data rsne_data;
+	u8 rmsk[ERP_MAX_KEY_LEN];
+	size_t rmsk_len;
+	u8 anonce[FILS_NONCE_LEN];
+	const u8 *data;
+	size_t buf_len;
+	struct wpabuf *fils_wd = NULL;
+	u16 alg, seq, status;
+	int ret;
+
+	if (!wd)
+		return -1;
+
+	data = wpabuf_head(wd);
+	buf_len = wpabuf_len(wd);
+
+	wpa_hexdump(MSG_DEBUG, "PASN: FILS: Authentication frame len=%zu",
+		    data, buf_len);
+
+	/* first handle the header */
+	if (buf_len < 6) {
+		wpa_printf(MSG_DEBUG, "PASN: FILS: Buffer too short");
+		return -1;
+	}
+
+	alg = WPA_GET_LE16(data);
+	seq = WPA_GET_LE16(data + 2);
+	status = WPA_GET_LE16(data + 4);
+
+	wpa_printf(MSG_DEBUG, "PASN: FILS: commit: alg=%u, seq=%u, status=%u",
+		   alg, seq, status);
+
+	if (alg != WLAN_AUTH_FILS_SK || seq != 2 ||
+	    status != WLAN_STATUS_SUCCESS) {
+		wpa_printf(MSG_DEBUG,
+			   "PASN: FILS: Dropping peer authentication");
+		return -1;
+	}
+
+	data += 6;
+	buf_len -= 6;
+
+	if (ieee802_11_parse_elems(data, buf_len, &elems, 1) == ParseFailed) {
+		wpa_printf(MSG_DEBUG, "PASN: FILS: Could not parse elements");
+		return -1;
+	}
+
+	if (!elems.rsn_ie || !elems.fils_nonce || !elems.fils_nonce ||
+	    !elems.wrapped_data) {
+		wpa_printf(MSG_DEBUG, "PASN: FILS: Missing IEs");
+		return -1;
+	}
+
+	ret = wpa_parse_wpa_ie(elems.rsn_ie - 2, elems.rsn_ie_len + 2,
+			       &rsne_data);
+	if (ret) {
+		wpa_printf(MSG_DEBUG, "PASN: FILS: Failed parsing RNSE");
+		return -1;
+	}
+
+	ret = wpa_pasn_validate_rsne(&rsne_data);
+	if (ret) {
+		wpa_printf(MSG_DEBUG, "PASN: FILS: Failed validating RSNE");
+		return -1;
+	}
+
+	if (rsne_data.num_pmkid) {
+		wpa_printf(MSG_DEBUG,
+			   "PASN: FILS: Not expecting PMKID in RSNE");
+		return -1;
+	}
+
+	wpa_hexdump(MSG_DEBUG, "PASN: FILS: ANonce", elems.fils_nonce,
+		    FILS_NONCE_LEN);
+	os_memcpy(anonce, elems.fils_nonce, FILS_NONCE_LEN);
+
+	wpa_hexdump(MSG_DEBUG, "PASN: FILS: FILS Session", elems.fils_session,
+		    FILS_SESSION_LEN);
+
+	if (os_memcmp(pasn->fils.session, elems.fils_session,
+		      FILS_SESSION_LEN)) {
+		wpa_printf(MSG_DEBUG, "PASN: FILS: Session mismatch");
+		return -1;
+	}
+
+	fils_wd = ieee802_11_defrag(&elems, WLAN_EID_EXTENSION,
+				    WLAN_EID_EXT_WRAPPED_DATA);
+
+	if (!fils_wd) {
+		wpa_printf(MSG_DEBUG,
+			   "PASN: FILS: Failed getting wrapped data");
+		return -1;
+	}
+
+	eapol_sm_process_erp_finish(wpa_s->eapol, wpabuf_head(fils_wd),
+				    wpabuf_len(fils_wd));
+
+	wpabuf_free(fils_wd);
+	fils_wd = NULL;
+
+	if (eapol_sm_failed(wpa_s->eapol)) {
+		wpa_printf(MSG_DEBUG, "PASN: FILS: ERP finish failed");
+		return -1;
+	}
+
+	rmsk_len = ERP_MAX_KEY_LEN;
+	ret = eapol_sm_get_key(wpa_s->eapol, rmsk, rmsk_len);
+
+	if (ret == PMK_LEN) {
+		rmsk_len = PMK_LEN;
+		ret = eapol_sm_get_key(wpa_s->eapol, rmsk, rmsk_len);
+	}
+
+	if (ret) {
+		wpa_printf(MSG_DEBUG, "PASN: FILS: Failed getting RMSK");
+		return -1;
+	}
+
+	ret = fils_rmsk_to_pmk(pasn->akmp, rmsk, rmsk_len,
+			       pasn->fils.nonce, anonce, NULL, 0,
+			       pasn->pmk, &pasn->pmk_len);
+
+	forced_memzero(rmsk, sizeof(rmsk));
+
+	if (ret) {
+		wpa_printf(MSG_DEBUG, "PASN: FILS: Failed to derive PMK");
+		return -1;
+	}
+
+	wpa_hexdump(MSG_DEBUG, "PASN: FILS: PMKID", pasn->fils.erp_pmkid,
+		    PMKID_LEN);
+
+	wpa_printf(MSG_DEBUG, "PASN: FILS: ERP processing succeeded");
+
+	wpa_pasn_pmksa_cache_add(wpa_s->wpa, pasn->pmk,
+				 pasn->pmk_len, pasn->fils.erp_pmkid,
+				 pasn->bssid, pasn->akmp);
+
+	pasn->fils.completed = true;
+	return 0;
+}
+
+#endif /* CONFIG_FILS */
+
+
+static struct wpabuf * wpas_pasn_get_wrapped_data(struct wpa_supplicant *wpa_s)
+{
+	struct wpas_pasn *pasn = &wpa_s->pasn;
+
+	if (pasn->using_pmksa)
+		return NULL;
+
+	switch (pasn->akmp) {
+	case WPA_KEY_MGMT_PASN:
+		/* no wrapped data */
+		return NULL;
+	case WPA_KEY_MGMT_SAE:
+#ifdef CONFIG_SAE
+		if (pasn->trans_seq == 0)
+			return wpas_pasn_wd_sae_commit(wpa_s);
+		if (pasn->trans_seq == 2)
+			return wpas_pasn_wd_sae_confirm(wpa_s);
+#endif /* CONFIG_SAE */
+		wpa_printf(MSG_ERROR,
+			   "PASN: SAE: Cannot derive wrapped data");
+		return NULL;
+	case WPA_KEY_MGMT_FILS_SHA256:
+	case WPA_KEY_MGMT_FILS_SHA384:
+#ifdef CONFIG_FILS
+		return wpas_pasn_wd_fils_auth(wpa_s);
+#endif /* CONFIG_FILS */
+	case WPA_KEY_MGMT_FT_PSK:
+	case WPA_KEY_MGMT_FT_IEEE8021X:
+	case WPA_KEY_MGMT_FT_IEEE8021X_SHA384:
+		/*
+		 * Wrapped data with these AKMs is optional and is only needed
+		 * for further validation of FT security parameters. For now do
+		 * not use them.
+		 */
+		return NULL;
+	default:
+		wpa_printf(MSG_ERROR,
+			   "PASN: TODO: Wrapped data for akmp=0x%x",
+			   pasn->akmp);
+		return NULL;
+	}
+}
+
+
+static u8 wpas_pasn_get_wrapped_data_format(struct wpas_pasn *pasn)
+{
+	if (pasn->using_pmksa)
+		return WPA_PASN_WRAPPED_DATA_NO;
+
+	/* Note: Valid AKMP is expected to already be validated */
+	switch (pasn->akmp) {
+	case WPA_KEY_MGMT_SAE:
+		return WPA_PASN_WRAPPED_DATA_SAE;
+	case WPA_KEY_MGMT_FILS_SHA256:
+	case WPA_KEY_MGMT_FILS_SHA384:
+		return WPA_PASN_WRAPPED_DATA_FILS_SK;
+	case WPA_KEY_MGMT_FT_PSK:
+	case WPA_KEY_MGMT_FT_IEEE8021X:
+	case WPA_KEY_MGMT_FT_IEEE8021X_SHA384:
+		/*
+		 * Wrapped data with these AKMs is optional and is only needed
+		 * for further validation of FT security parameters. For now do
+		 * not use them.
+		 */
+		return WPA_PASN_WRAPPED_DATA_NO;
+	case WPA_KEY_MGMT_PASN:
+	default:
+		return WPA_PASN_WRAPPED_DATA_NO;
+	}
+}
+
+
+static struct wpabuf * wpas_pasn_build_auth_1(struct wpa_supplicant *wpa_s)
+{
+	struct wpas_pasn *pasn = &wpa_s->pasn;
+	struct wpabuf *buf, *pubkey = NULL, *wrapped_data_buf = NULL;
+	const u8 *pmkid;
+	u8 wrapped_data;
+	int ret;
+	u16 capab;
+
+	wpa_printf(MSG_DEBUG, "PASN: Building frame 1");
+
+	if (pasn->trans_seq)
+		return NULL;
+
+	buf = wpabuf_alloc(1500);
+	if (!buf)
+		goto fail;
+
+	/* Get public key */
+	pubkey = crypto_ecdh_get_pubkey(pasn->ecdh, 0);
+	pubkey = wpabuf_zeropad(pubkey, crypto_ecdh_prime_len(pasn->ecdh));
+	if (!pubkey) {
+		wpa_printf(MSG_DEBUG, "PASN: Failed to get pubkey");
+		goto fail;
+	}
+
+	wrapped_data = wpas_pasn_get_wrapped_data_format(pasn);
+
+	wpa_pasn_build_auth_header(buf, pasn->bssid,
+				   wpa_s->own_addr, pasn->bssid,
+				   pasn->trans_seq + 1, WLAN_STATUS_SUCCESS);
+
+	pmkid = NULL;
+	if (wpa_key_mgmt_ft(pasn->akmp)) {
+		ret = wpa_pasn_ft_derive_pmk_r1(wpa_s->wpa, pasn->akmp,
+						pasn->bssid,
+						pasn->pmk_r1,
+						&pasn->pmk_r1_len,
+						pasn->pmk_r1_name);
+		if (ret) {
+			wpa_printf(MSG_DEBUG,
+				   "PASN: FT: Failed to derive keys");
+			goto fail;
+		}
+
+		pmkid = pasn->pmk_r1_name;
+	} else if (wrapped_data != WPA_PASN_WRAPPED_DATA_NO) {
+		struct rsn_pmksa_cache_entry *pmksa;
+
+		pmksa = wpa_sm_pmksa_cache_get(wpa_s->wpa, pasn->bssid,
+					       NULL, NULL, pasn->akmp);
+		if (pmksa)
+			pmkid = pmksa->pmkid;
+
+		/*
+		 * Note: Even when PMKSA is available, also add wrapped data as
+		 * it is possible that the PMKID is no longer valid at the AP.
+		 */
+		wrapped_data_buf = wpas_pasn_get_wrapped_data(wpa_s);
+	}
+
+	if (wpa_pasn_add_rsne(buf, pmkid, pasn->akmp, pasn->cipher) < 0)
+		goto fail;
+
+	if (!wrapped_data_buf)
+		wrapped_data = WPA_PASN_WRAPPED_DATA_NO;
+
+	wpa_pasn_add_parameter_ie(buf, pasn->group, wrapped_data,
+				  pubkey, NULL, -1);
+
+	if (wpa_pasn_add_wrapped_data(buf, wrapped_data_buf) < 0)
+		goto fail;
+
+	/* Add own RNSXE */
+	/* TODO: How to handle protected TWT and SAE H2E? */
+	capab = 0;
+	if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_LTF)
+		capab |= BIT(WLAN_RSNX_CAPAB_SECURE_LTF);
+	if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_RTT)
+		capab |= BIT(WLAN_RSNX_CAPAB_SECURE_RTT);
+	if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_PROT_RANGE_NEG)
+		capab |= BIT(WLAN_RSNX_CAPAB_PROT_RANGE_NEG);
+	wpa_pasn_add_rsnxe(buf, capab);
+
+	ret = pasn_auth_frame_hash(pasn->akmp, pasn->cipher,
+				   wpabuf_head_u8(buf) + IEEE80211_HDRLEN,
+				   wpabuf_len(buf) - IEEE80211_HDRLEN,
+				   pasn->hash);
+	if (ret) {
+		wpa_printf(MSG_DEBUG, "PASN: Failed to compute hash");
+		goto fail;
+	}
+
+	pasn->trans_seq++;
+
+	wpabuf_free(wrapped_data_buf);
+	wpabuf_free(pubkey);
+
+	wpa_printf(MSG_DEBUG, "PASN: Frame 1: Success");
+	return buf;
+fail:
+	pasn->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+	wpabuf_free(wrapped_data_buf);
+	wpabuf_free(pubkey);
+	wpabuf_free(buf);
+	return NULL;
+}
+
+
+static struct wpabuf * wpas_pasn_build_auth_3(struct wpa_supplicant *wpa_s)
+{
+	struct wpas_pasn *pasn = &wpa_s->pasn;
+	struct wpabuf *buf, *wrapped_data_buf = NULL;
+	u8 mic[WPA_PASN_MAX_MIC_LEN];
+	u8 mic_len, data_len;
+	const u8 *data;
+	u8 *ptr;
+	u8 wrapped_data;
+	int ret;
+
+	wpa_printf(MSG_DEBUG, "PASN: Building frame 3");
+
+	if (pasn->trans_seq != 2)
+		return NULL;
+
+	buf = wpabuf_alloc(1500);
+	if (!buf)
+		goto fail;
+
+	wrapped_data = wpas_pasn_get_wrapped_data_format(pasn);
+
+	wpa_pasn_build_auth_header(buf, pasn->bssid,
+				   wpa_s->own_addr, pasn->bssid,
+				   pasn->trans_seq + 1, WLAN_STATUS_SUCCESS);
+
+	wrapped_data_buf = wpas_pasn_get_wrapped_data(wpa_s);
+
+	if (!wrapped_data_buf)
+		wrapped_data = WPA_PASN_WRAPPED_DATA_NO;
+
+	wpa_pasn_add_parameter_ie(buf, pasn->group, wrapped_data,
+				  NULL, NULL, -1);
+
+	if (wpa_pasn_add_wrapped_data(buf, wrapped_data_buf) < 0)
+		goto fail;
+	wpabuf_free(wrapped_data_buf);
+	wrapped_data_buf = NULL;
+
+	/* Add the MIC */
+	mic_len = pasn_mic_len(pasn->akmp, pasn->cipher);
+	wpabuf_put_u8(buf, WLAN_EID_MIC);
+	wpabuf_put_u8(buf, mic_len);
+	ptr = wpabuf_put(buf, mic_len);
+
+	os_memset(ptr, 0, mic_len);
+
+	data = wpabuf_head_u8(buf) + IEEE80211_HDRLEN;
+	data_len = wpabuf_len(buf) - IEEE80211_HDRLEN;
+
+	ret = pasn_mic(pasn->ptk.kck, pasn->akmp, pasn->cipher,
+		       wpa_s->own_addr, pasn->bssid,
+		       pasn->hash, mic_len * 2, data, data_len, mic);
+	if (ret) {
+		wpa_printf(MSG_DEBUG, "PASN: frame 3: Failed MIC calculation");
+		goto fail;
+	}
+
+	os_memcpy(ptr, mic, mic_len);
+
+	pasn->trans_seq++;
+
+	wpa_printf(MSG_DEBUG, "PASN: frame 3: Success");
+	return buf;
+fail:
+	pasn->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+	wpabuf_free(wrapped_data_buf);
+	wpabuf_free(buf);
+	return NULL;
+}
+
+
+static void wpas_pasn_reset(struct wpa_supplicant *wpa_s)
+{
+	struct wpas_pasn *pasn = &wpa_s->pasn;
+
+	wpa_printf(MSG_DEBUG, "PASN: Reset");
+
+	crypto_ecdh_deinit(pasn->ecdh);
+	pasn->ecdh = NULL;
+
+	wpas_pasn_cancel_auth_work(wpa_s);
+	wpa_s->pasn_auth_work = NULL;
+
+	eloop_cancel_timeout(wpas_pasn_auth_work_timeout, wpa_s, NULL);
+
+	pasn->akmp = 0;
+	pasn->cipher = 0;
+	pasn->group = 0;
+	pasn->trans_seq = 0;
+	pasn->pmk_len = 0;
+	pasn->using_pmksa = false;
+
+	forced_memzero(pasn->pmk, sizeof(pasn->pmk));
+	forced_memzero(&pasn->ptk, sizeof(pasn->ptk));
+	forced_memzero(&pasn->hash, sizeof(pasn->hash));
+
+	wpabuf_free(pasn->beacon_rsne_rsnxe);
+	pasn->beacon_rsne_rsnxe = NULL;
+
+#ifdef CONFIG_SAE
+	sae_clear_data(&pasn->sae);
+#endif /* CONFIG_SAE */
+
+#ifdef CONFIG_FILS
+	os_memset(&pasn->fils, 0, sizeof(pasn->fils));
+#endif /* CONFIG_FILS*/
+
+#ifdef CONFIG_IEEE80211R
+	forced_memzero(pasn->pmk_r1, sizeof(pasn->pmk_r1));
+	pasn->pmk_r1_len = 0;
+	os_memset(pasn->pmk_r1_name, 0, sizeof(pasn->pmk_r1_name));
+#endif /* CONFIG_IEEE80211R */
+	pasn->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+}
+
+
+static int wpas_pasn_set_pmk(struct wpa_supplicant *wpa_s,
+			     struct wpa_ie_data *rsn_data,
+			     struct wpa_pasn_params_data *pasn_data,
+			     struct wpabuf *wrapped_data)
+{
+	static const u8 pasn_default_pmk[] = {'P', 'M', 'K', 'z'};
+	struct wpas_pasn *pasn = &wpa_s->pasn;
+
+	os_memset(pasn->pmk, 0, sizeof(pasn->pmk));
+	pasn->pmk_len = 0;
+
+	if (pasn->akmp == WPA_KEY_MGMT_PASN) {
+		wpa_printf(MSG_DEBUG, "PASN: Using default PMK");
+
+		pasn->pmk_len = WPA_PASN_PMK_LEN;
+		os_memcpy(pasn->pmk, pasn_default_pmk,
+			  sizeof(pasn_default_pmk));
+		return 0;
+	}
+
+	if (wpa_key_mgmt_ft(pasn->akmp)) {
+#ifdef CONFIG_IEEE80211R
+		wpa_printf(MSG_DEBUG, "PASN: FT: Using PMK-R1");
+		pasn->pmk_len = pasn->pmk_r1_len;
+		os_memcpy(pasn->pmk, pasn->pmk_r1, pasn->pmk_r1_len);
+		pasn->using_pmksa = true;
+		return 0;
+#else /* CONFIG_IEEE80211R */
+		wpa_printf(MSG_DEBUG, "PASN: FT: Not supported");
+		return -1;
+#endif /* CONFIG_IEEE80211R */
+	}
+
+	if (rsn_data->num_pmkid) {
+		struct rsn_pmksa_cache_entry *pmksa;
+
+		pmksa = wpa_sm_pmksa_cache_get(wpa_s->wpa, pasn->bssid,
+					       rsn_data->pmkid, NULL,
+					       pasn->akmp);
+		if (pmksa) {
+			wpa_printf(MSG_DEBUG, "PASN: Using PMKSA");
+
+			pasn->pmk_len = pmksa->pmk_len;
+			os_memcpy(pasn->pmk, pmksa->pmk, pmksa->pmk_len);
+			pasn->using_pmksa = true;
+
+			return 0;
+		}
+	}
+
+#ifdef CONFIG_SAE
+	if (pasn->akmp == WPA_KEY_MGMT_SAE) {
+		int ret;
+
+		ret = wpas_pasn_wd_sae_rx(wpa_s, wrapped_data);
+		if (ret) {
+			wpa_printf(MSG_DEBUG,
+				   "PASN: Failed processing SAE wrapped data");
+			pasn->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+			return -1;
+		}
+
+		wpa_printf(MSG_DEBUG, "PASN: Success deriving PMK with SAE");
+		pasn->pmk_len = PMK_LEN;
+		os_memcpy(pasn->pmk, pasn->sae.pmk, PMK_LEN);
+
+		wpa_pasn_pmksa_cache_add(wpa_s->wpa, pasn->pmk,
+					 pasn->pmk_len, pasn->sae.pmkid,
+					 pasn->bssid, pasn->akmp);
+		return 0;
+	}
+#endif /* CONFIG_SAE */
+
+#ifdef CONFIG_FILS
+	if (pasn->akmp == WPA_KEY_MGMT_FILS_SHA256 ||
+	    pasn->akmp == WPA_KEY_MGMT_FILS_SHA384) {
+		int ret;
+
+		ret = wpas_pasn_wd_fils_rx(wpa_s, wrapped_data);
+		if (ret) {
+			wpa_printf(MSG_DEBUG,
+				   "PASN: Failed processing FILS wrapped data");
+			pasn->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+			return -1;
+		}
+
+		return 0;
+	}
+#endif	/* CONFIG_FILS */
+
+	/* TODO: Derive PMK based on wrapped data */
+	wpa_printf(MSG_DEBUG, "PASN: Missing implementation to derive PMK");
+	pasn->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+	return -1;
+}
+
+
+static int wpas_pasn_start(struct wpa_supplicant *wpa_s, const u8 *bssid,
+			   int akmp, int cipher, u16 group, int freq,
+			   const u8 *beacon_rsne, u8 beacon_rsne_len,
+			   const u8 *beacon_rsnxe, u8 beacon_rsnxe_len,
+			   int network_id)
+{
+	struct wpas_pasn *pasn = &wpa_s->pasn;
+	struct wpa_ssid *ssid = NULL;
+	struct wpabuf *frame;
+	int ret;
+
+	/* TODO: Currently support only ECC groups */
+	if (!dragonfly_suitable_group(group, 1)) {
+		wpa_printf(MSG_DEBUG,
+			   "PASN: Reject unsuitable group %u", group);
+		return -1;
+	}
+
+	ssid = wpa_config_get_network(wpa_s->conf, network_id);
+
+	switch (akmp) {
+	case WPA_KEY_MGMT_PASN:
+		break;
+#ifdef CONFIG_SAE
+	case WPA_KEY_MGMT_SAE:
+		if (!ssid) {
+			wpa_printf(MSG_DEBUG,
+				   "PASN: No network profile found for SAE");
+			return -1;
+		}
+		pasn->sae.state = SAE_NOTHING;
+		pasn->sae.send_confirm = 0;
+		pasn->ssid = ssid;
+		break;
+#endif /* CONFIG_SAE */
+#ifdef CONFIG_FILS
+	case WPA_KEY_MGMT_FILS_SHA256:
+	case WPA_KEY_MGMT_FILS_SHA384:
+		pasn->ssid = ssid;
+		break;
+#endif /* CONFIG_FILS */
+#ifdef CONFIG_IEEE80211R
+	case WPA_KEY_MGMT_FT_PSK:
+	case WPA_KEY_MGMT_FT_IEEE8021X:
+	case WPA_KEY_MGMT_FT_IEEE8021X_SHA384:
+		break;
+#endif /* CONFIG_IEEE80211R */
+	default:
+		wpa_printf(MSG_ERROR, "PASN: Unsupported AKMP=0x%x", akmp);
+		return -1;
+	}
+
+	pasn->ecdh = crypto_ecdh_init(group);
+	if (!pasn->ecdh) {
+		wpa_printf(MSG_DEBUG, "PASN: Failed to init ECDH");
+		goto fail;
+	}
+
+	pasn->beacon_rsne_rsnxe = wpabuf_alloc(beacon_rsne_len +
+					       beacon_rsnxe_len);
+	if (!pasn->beacon_rsne_rsnxe) {
+		wpa_printf(MSG_DEBUG, "PASN: Failed storing beacon RSNE/RSNXE");
+		goto fail;
+	}
+
+	wpabuf_put_data(pasn->beacon_rsne_rsnxe, beacon_rsne, beacon_rsne_len);
+	if (beacon_rsnxe && beacon_rsnxe_len)
+		wpabuf_put_data(pasn->beacon_rsne_rsnxe, beacon_rsnxe,
+				beacon_rsnxe_len);
+
+	pasn->akmp = akmp;
+	pasn->cipher = cipher;
+	pasn->group = group;
+	pasn->freq = freq;
+	os_memcpy(pasn->bssid, bssid, ETH_ALEN);
+
+	wpa_printf(MSG_DEBUG,
+		   "PASN: Init: " MACSTR " akmp=0x%x, cipher=0x%x, group=%u",
+		   MAC2STR(pasn->bssid), pasn->akmp, pasn->cipher,
+		   pasn->group);
+
+	frame = wpas_pasn_build_auth_1(wpa_s);
+	if (!frame) {
+		wpa_printf(MSG_DEBUG, "PASN: Failed building 1st auth frame");
+		goto fail;
+	}
+
+	ret = wpa_drv_send_mlme(wpa_s, wpabuf_head(frame), wpabuf_len(frame), 0,
+				pasn->freq, 1000);
+
+	wpabuf_free(frame);
+	if (ret) {
+		wpa_printf(MSG_DEBUG, "PASN: Failed sending 1st auth frame");
+		goto fail;
+	}
+
+	eloop_register_timeout(2, 0, wpas_pasn_auth_work_timeout, wpa_s, NULL);
+	return 0;
+
+fail:
+	return -1;
+}
+
+
+static struct wpa_bss * wpas_pasn_allowed(struct wpa_supplicant *wpa_s,
+					  const u8 *bssid, int akmp, int cipher)
+{
+	struct wpa_bss *bss;
+	const u8 *rsne;
+	struct wpa_ie_data rsne_data;
+	int ret;
+
+	if (os_memcmp(wpa_s->bssid, bssid, ETH_ALEN) == 0) {
+		wpa_printf(MSG_DEBUG,
+			   "PASN: Not doing authentication with current BSS");
+		return NULL;
+	}
+
+	bss = wpa_bss_get_bssid(wpa_s, bssid);
+	if (!bss) {
+		wpa_printf(MSG_DEBUG, "PASN: BSS not found");
+		return NULL;
+	}
+
+	rsne = wpa_bss_get_ie(bss, WLAN_EID_RSN);
+	if (!rsne) {
+		wpa_printf(MSG_DEBUG, "PASN: BSS without RSNE");
+		return NULL;
+	}
+
+	ret = wpa_parse_wpa_ie(rsne, *(rsne + 1) + 2, &rsne_data);
+	if (ret) {
+		wpa_printf(MSG_DEBUG, "PASN: Failed parsing RSNE data");
+		return NULL;
+	}
+
+	if (!(rsne_data.key_mgmt & akmp) ||
+	    !(rsne_data.pairwise_cipher & cipher)) {
+		wpa_printf(MSG_DEBUG,
+			   "PASN: AP does not support requested AKMP or cipher");
+		return NULL;
+	}
+
+	return bss;
+}
+
+
+static void wpas_pasn_auth_start_cb(struct wpa_radio_work *work, int deinit)
+{
+	struct wpa_supplicant *wpa_s = work->wpa_s;
+	struct wpa_pasn_auth_work *awork = work->ctx;
+	struct wpa_bss *bss;
+	const u8 *rsne, *rsnxe;
+	int ret;
+
+	wpa_printf(MSG_DEBUG, "PASN: auth_start_cb: deinit=%d", deinit);
+
+	if (deinit) {
+		if (work->started) {
+			eloop_cancel_timeout(wpas_pasn_auth_work_timeout,
+					     wpa_s, NULL);
+			wpa_s->pasn_auth_work = NULL;
+		}
+		os_free(awork);
+		return;
+	}
+
+	/*
+	 * It is possible that by the time the callback is called, the PASN
+	 * authentication is not allowed, e.g., a connection with the AP was
+	 * established.
+	 */
+	bss = wpas_pasn_allowed(wpa_s, awork->bssid, awork->akmp,
+				awork->cipher);
+	if (!bss) {
+		wpa_printf(MSG_DEBUG, "PASN: auth_start_cb: Not allowed");
+		goto fail;
+	}
+
+	rsne = wpa_bss_get_ie(bss, WLAN_EID_RSN);
+	if (!rsne) {
+		wpa_printf(MSG_DEBUG, "PASN: BSS without RSNE");
+		goto fail;
+	}
+
+	rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
+
+	ret = wpas_pasn_start(wpa_s, awork->bssid, awork->akmp, awork->cipher,
+			      awork->group, bss->freq, rsne, *(rsne + 1) + 2,
+			      rsnxe, rsnxe ? *(rsnxe + 1) + 2 : 0,
+			      awork->network_id);
+	if (ret) {
+		wpa_printf(MSG_DEBUG,
+			   "PASN: Failed to start PASN authentication");
+		goto fail;
+	}
+
+	wpa_s->pasn_auth_work = work;
+	return;
+fail:
+	os_free(awork);
+	work->ctx = NULL;
+	radio_work_done(work);
+}
+
+
+int wpas_pasn_auth_start(struct wpa_supplicant *wpa_s, const u8 *bssid,
+			 int akmp, int cipher, u16 group, int network_id)
+{
+	struct wpa_pasn_auth_work *awork;
+	struct wpa_bss *bss;
+
+	wpa_printf(MSG_DEBUG, "PASN: Start: " MACSTR " akmp=0x%x, cipher=0x%x",
+		   MAC2STR(bssid), akmp, cipher);
+
+	/*
+	 * TODO: Consider modifying the offchannel logic to handle additional
+	 * Management frames other then Action frames. For now allow PASN only
+	 * with drivers that support off-channel TX.
+	 */
+	if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX)) {
+		wpa_printf(MSG_DEBUG,
+			   "PASN: Driver does not support offchannel TX");
+		return -1;
+	}
+
+	if (radio_work_pending(wpa_s, "pasn-start-auth")) {
+		wpa_printf(MSG_DEBUG,
+			   "PASN: send_auth: Work is already pending");
+		return -1;
+	}
+
+	if (wpa_s->pasn_auth_work) {
+		wpa_printf(MSG_DEBUG, "PASN: send_auth: Already in progress");
+		return -1;
+	}
+
+	bss = wpas_pasn_allowed(wpa_s, bssid, akmp, cipher);
+	if (!bss)
+		return -1;
+
+	wpas_pasn_reset(wpa_s);
+
+	awork = os_zalloc(sizeof(*awork));
+	if (!awork)
+		return -1;
+
+	os_memcpy(awork->bssid, bssid, ETH_ALEN);
+	awork->akmp = akmp;
+	awork->cipher = cipher;
+	awork->group = group;
+	awork->network_id = network_id;
+
+	if (radio_add_work(wpa_s, bss->freq, "pasn-start-auth", 1,
+			   wpas_pasn_auth_start_cb, awork) < 0) {
+		os_free(awork);
+		return -1;
+	}
+
+	wpa_printf(MSG_DEBUG, "PASN: Auth work successfully added");
+	return 0;
+}
+
+
+void wpas_pasn_auth_stop(struct wpa_supplicant *wpa_s)
+{
+	struct wpas_pasn *pasn = &wpa_s->pasn;
+
+	if (!wpa_s->pasn.ecdh)
+		return;
+
+	wpa_printf(MSG_DEBUG, "PASN: Stopping authentication");
+
+	wpas_pasn_auth_status(wpa_s, pasn->bssid, pasn->akmp, pasn->cipher,
+			      pasn->status);
+
+	wpas_pasn_reset(wpa_s);
+}
+
+
+int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s,
+		      const struct ieee80211_mgmt *mgmt, size_t len)
+{
+	struct wpas_pasn *pasn = &wpa_s->pasn;
+	struct ieee802_11_elems elems;
+	struct wpa_ie_data rsn_data;
+	struct wpa_pasn_params_data pasn_params;
+	struct wpabuf *wrapped_data = NULL, *secret = NULL, *frame = NULL;
+	u8 mic[WPA_PASN_MAX_MIC_LEN], out_mic[WPA_PASN_MAX_MIC_LEN];
+	u8 mic_len;
+	u16 status;
+	int ret;
+	u16 fc = host_to_le16((WLAN_FC_TYPE_MGMT << 2) |
+			      (WLAN_FC_STYPE_AUTH << 4));
+
+	if (!wpa_s->pasn_auth_work || !mgmt ||
+	    len < offsetof(struct ieee80211_mgmt, u.auth.variable))
+		return -2;
+
+	/* Not an Authentication frame; do nothing */
+	if ((mgmt->frame_control & fc) != fc)
+		return -2;
+
+	/* Not our frame; do nothing */
+	if (os_memcmp(mgmt->da, wpa_s->own_addr, ETH_ALEN) != 0 ||
+	    os_memcmp(mgmt->sa, pasn->bssid, ETH_ALEN) != 0 ||
+	    os_memcmp(mgmt->bssid, pasn->bssid, ETH_ALEN) != 0)
+		return -2;
+
+	/* Not PASN; do nothing */
+	if (mgmt->u.auth.auth_alg != host_to_le16(WLAN_AUTH_PASN))
+		return -2;
+
+	if (mgmt->u.auth.auth_transaction !=
+	    host_to_le16(pasn->trans_seq + 1)) {
+		wpa_printf(MSG_DEBUG,
+			   "PASN: RX: Invalid transaction sequence: (%u != %u)",
+			   le_to_host16(mgmt->u.auth.auth_transaction),
+			   pasn->trans_seq + 1);
+		return -1;
+	}
+
+	status = le_to_host16(mgmt->u.auth.status_code);
+
+	if (status != WLAN_STATUS_SUCCESS &&
+	    status != WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) {
+		wpa_printf(MSG_DEBUG,
+			   "PASN: Authentication rejected - status=%u", status);
+		pasn->status = status;
+		wpas_pasn_auth_stop(wpa_s);
+		return -1;
+	}
+
+	if (ieee802_11_parse_elems(mgmt->u.auth.variable,
+				   len - offsetof(struct ieee80211_mgmt,
+						  u.auth.variable),
+				   &elems, 0) == ParseFailed) {
+		wpa_printf(MSG_DEBUG,
+			   "PASN: Failed parsing Authentication frame");
+		goto fail;
+	}
+
+	/* Check that the MIC IE exists. Save it and zero out the memory */
+	mic_len = pasn_mic_len(pasn->akmp, pasn->cipher);
+	if (status == WLAN_STATUS_SUCCESS) {
+		if (!elems.mic || elems.mic_len != mic_len) {
+			wpa_printf(MSG_DEBUG,
+				   "PASN: Invalid MIC. Expecting len=%u",
+				   mic_len);
+			goto fail;
+		} else {
+			os_memcpy(mic, elems.mic, mic_len);
+			/* TODO: Clean this up.. Should not be modifying the
+			 * received message buffer. */
+			os_memset((u8 *) elems.mic, 0, mic_len);
+		}
+	}
+
+	if (!elems.pasn_params || !elems.pasn_params_len) {
+		wpa_printf(MSG_DEBUG,
+			   "PASN: Missing PASN Parameters IE");
+		goto fail;
+	}
+
+	ret = wpa_pasn_parse_parameter_ie(elems.pasn_params - 3,
+					  elems.pasn_params_len + 3,
+					  true, &pasn_params);
+	if (ret) {
+		wpa_printf(MSG_DEBUG,
+			   "PASN: Failed validation PASN of Parameters IE");
+		goto fail;
+	}
+
+	/* TODO: handle comeback flow */
+	if (status == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) {
+		wpa_printf(MSG_DEBUG,
+			   "PASN: Authentication temporarily rejected");
+		goto fail;
+	}
+
+	ret = wpa_parse_wpa_ie(elems.rsn_ie - 2, elems.rsn_ie_len + 2,
+			       &rsn_data);
+	if (ret) {
+		wpa_printf(MSG_DEBUG, "PASN: Failed parsing RNSE");
+		goto fail;
+	}
+
+	ret = wpa_pasn_validate_rsne(&rsn_data);
+	if (ret) {
+		wpa_printf(MSG_DEBUG, "PASN: Failed validating RSNE");
+		goto fail;
+	}
+
+	if (pasn->akmp != rsn_data.key_mgmt ||
+	    pasn->cipher != rsn_data.pairwise_cipher) {
+		wpa_printf(MSG_DEBUG, "PASN: Mismatch in AKMP/cipher");
+		goto fail;
+	}
+
+	if (pasn->group != pasn_params.group) {
+		wpa_printf(MSG_DEBUG, "PASN: Mismatch in group");
+		goto fail;
+	}
+
+	if (!pasn_params.pubkey || !pasn_params.pubkey_len) {
+		wpa_printf(MSG_DEBUG, "PASN: Invalid public key");
+		goto fail;
+	}
+
+	secret = crypto_ecdh_set_peerkey(pasn->ecdh, 0,
+					 pasn_params.pubkey,
+					 pasn_params.pubkey_len);
+
+	if (!secret) {
+		wpa_printf(MSG_DEBUG, "PASN: Failed to derive shared secret");
+		goto fail;
+	}
+
+	if (pasn_params.wrapped_data_format != WPA_PASN_WRAPPED_DATA_NO) {
+		wrapped_data = ieee802_11_defrag(&elems,
+						 WLAN_EID_EXTENSION,
+						 WLAN_EID_EXT_WRAPPED_DATA);
+
+		if (!wrapped_data) {
+			wpa_printf(MSG_DEBUG, "PASN: Missing wrapped data");
+			goto fail;
+		}
+	}
+
+	ret = wpas_pasn_set_pmk(wpa_s, &rsn_data, &pasn_params, wrapped_data);
+	if (ret) {
+		wpa_printf(MSG_DEBUG, "PASN: Failed to set PMK");
+		goto fail;
+	}
+
+	ret = pasn_pmk_to_ptk(pasn->pmk, pasn->pmk_len,
+			      wpa_s->own_addr, pasn->bssid,
+			      wpabuf_head(secret), wpabuf_len(secret),
+			      &pasn->ptk, pasn->akmp, pasn->cipher,
+			      WPA_KDK_MAX_LEN);
+	if (ret) {
+		wpa_printf(MSG_DEBUG, "PASN: Failed to derive PTK");
+		goto fail;
+	}
+
+	wpabuf_free(wrapped_data);
+	wrapped_data = NULL;
+	wpabuf_free(secret);
+	secret = NULL;
+
+	/* Verify the MIC */
+	ret = pasn_mic(pasn->ptk.kck, pasn->akmp, pasn->cipher,
+		       pasn->bssid, wpa_s->own_addr,
+		       wpabuf_head(pasn->beacon_rsne_rsnxe),
+		       wpabuf_len(pasn->beacon_rsne_rsnxe),
+		       (u8 *) &mgmt->u.auth,
+		       len - offsetof(struct ieee80211_mgmt, u.auth),
+		       out_mic);
+
+	wpa_hexdump_key(MSG_DEBUG, "PASN: Frame MIC", mic, mic_len);
+	if (ret || os_memcmp(mic, out_mic, mic_len) != 0) {
+		wpa_printf(MSG_DEBUG, "PASN: Failed MIC verification");
+		goto fail;
+	}
+
+	pasn->trans_seq++;
+
+	wpa_printf(MSG_DEBUG, "PASN: Success verifying Authentication frame");
+
+	frame = wpas_pasn_build_auth_3(wpa_s);
+	if (!frame) {
+		wpa_printf(MSG_DEBUG, "PASN: Failed building 3rd auth frame");
+		goto fail;
+	}
+
+	ret = wpa_drv_send_mlme(wpa_s, wpabuf_head(frame), wpabuf_len(frame), 0,
+				pasn->freq, 100);
+	wpabuf_free(frame);
+	if (ret) {
+		wpa_printf(MSG_DEBUG, "PASN: Failed sending 3st auth frame");
+		goto fail;
+	}
+
+	wpa_printf(MSG_DEBUG, "PASN: Success sending last frame. Store PTK");
+
+	ptksa_cache_add(wpa_s->ptksa, pasn->bssid, pasn->cipher,
+			dot11RSNAConfigPMKLifetime, &pasn->ptk);
+
+	forced_memzero(&pasn->ptk, sizeof(pasn->ptk));
+
+	pasn->status = WLAN_STATUS_SUCCESS;
+	return 0;
+fail:
+	wpa_printf(MSG_DEBUG, "PASN: Failed RX processing - terminating");
+	wpabuf_free(wrapped_data);
+	wpabuf_free(secret);
+
+	/*
+	 * TODO: In case of an error the standard allows to silently drop
+	 * the frame and terminate the authentication exchange. However, better
+	 * reply to the AP with an error status.
+	 */
+	pasn->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+	wpas_pasn_auth_stop(wpa_s);
+	return -1;
+}
+
+
+int wpas_pasn_auth_tx_status(struct wpa_supplicant *wpa_s,
+			     const u8 *data, size_t data_len, u8 acked)
+
+{
+	struct wpas_pasn *pasn = &wpa_s->pasn;
+	const struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) data;
+	u16 fc = host_to_le16((WLAN_FC_TYPE_MGMT << 2) |
+			      (WLAN_FC_STYPE_AUTH << 4));
+
+	wpa_printf(MSG_DEBUG, "PASN: auth_tx_status: acked=%u", acked);
+
+	if (!wpa_s->pasn_auth_work) {
+		wpa_printf(MSG_DEBUG,
+			   "PASN: auth_tx_status: no work in progress");
+		return -1;
+	}
+
+	if (!mgmt ||
+	    data_len < offsetof(struct ieee80211_mgmt, u.auth.variable))
+		return -1;
+
+	/* Not an authentication frame; do nothing */
+	if ((mgmt->frame_control & fc) != fc)
+		return -1;
+
+	/* Not our frame; do nothing */
+	if (os_memcmp(mgmt->da, pasn->bssid, ETH_ALEN) ||
+	    os_memcmp(mgmt->sa, wpa_s->own_addr, ETH_ALEN) ||
+	    os_memcmp(mgmt->bssid, pasn->bssid, ETH_ALEN))
+		return -1;
+
+	/* Not PASN; do nothing */
+	if (mgmt->u.auth.auth_alg !=  host_to_le16(WLAN_AUTH_PASN))
+		return -1;
+
+	if (mgmt->u.auth.auth_transaction != host_to_le16(pasn->trans_seq)) {
+		wpa_printf(MSG_ERROR,
+			   "PASN: Invalid transaction sequence: (%u != %u)",
+			   pasn->trans_seq,
+			   le_to_host16(mgmt->u.auth.auth_transaction));
+		return 0;
+	}
+
+	wpa_printf(MSG_ERROR,
+		   "PASN: auth with trans_seq=%u, acked=%u", pasn->trans_seq,
+		   acked);
+
+	/*
+	 * Even if the frame was not acked, do not treat this is an error, and
+	 * try to complete the flow, relying on the PASN timeout callback to
+	 * clean up.
+	 */
+	if (pasn->trans_seq == 3) {
+		wpa_printf(MSG_DEBUG, "PASN: auth complete with: " MACSTR,
+			   MAC2STR(pasn->bssid));
+		/*
+		 * Either frame was not ACKed or it was ACKed but the trans_seq
+		 * != 1, i.e., not expecting an RX frame, so we are done.
+		 */
+		wpas_pasn_auth_stop(wpa_s);
+	}
+
+	return 0;
+}
diff --git a/wpa_supplicant/robust_av.c b/wpa_supplicant/robust_av.c
index 1280f5d..f6da56e 100644
--- a/wpa_supplicant/robust_av.c
+++ b/wpa_supplicant/robust_av.c
@@ -48,18 +48,13 @@
 int wpas_send_mscs_req(struct wpa_supplicant *wpa_s)
 {
 	struct wpabuf *buf;
-	const u8 *ext_capab = NULL;
 	size_t buf_len;
 	int ret;
 
 	if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid)
 		return 0;
 
-	if (wpa_s->current_bss)
-		ext_capab = wpa_bss_get_ie(wpa_s->current_bss,
-					   WLAN_EID_EXT_CAPAB);
-
-	if (!ext_capab || ext_capab[1] < 11 || !(ext_capab[12] & 0x20)) {
+	if (!wpa_bss_ext_capab(wpa_s->current_bss, WLAN_EXT_CAPAB_MSCS)) {
 		wpa_dbg(wpa_s, MSG_INFO,
 			"AP does not support MSCS - could not send MSCS Req");
 		return -1;
diff --git a/wpa_supplicant/rrm.c b/wpa_supplicant/rrm.c
index afc1172..cf107eb 100644
--- a/wpa_supplicant/rrm.c
+++ b/wpa_supplicant/rrm.c
@@ -556,23 +556,32 @@
 static int * wpas_op_class_freqs(const struct oper_class_map *op,
 				 struct hostapd_hw_modes *mode, int active)
 {
-	u8 channels_80mhz[] = { 42, 58, 106, 122, 138, 155 };
-	u8 channels_160mhz[] = { 50, 114 };
+	u8 channels_80mhz_5ghz[] = { 42, 58, 106, 122, 138, 155, 171 };
+	u8 channels_160mhz_5ghz[] = { 50, 114, 163 };
+	u8 channels_80mhz_6ghz[] = { 7, 23, 39, 55, 71, 87, 103, 119, 135, 151,
+				     167, 183, 199, 215 };
+	u8 channels_160mhz_6ghz[] = { 15, 47, 79, 111, 143, 175, 207 };
+	const u8 *channels = NULL;
+	size_t num_chan = 0;
+	bool is_6ghz = is_6ghz_op_class(op->op_class);
 
 	/*
 	 * When adding all channels in the operating class, 80 + 80 MHz
 	 * operating classes are like 80 MHz channels because we add all valid
 	 * channels anyway.
 	 */
-	if (op->bw == BW80 || op->bw == BW80P80)
-		return wpas_add_channels(op, mode, active, channels_80mhz,
-					 ARRAY_SIZE(channels_80mhz));
+	if (op->bw == BW80 || op->bw == BW80P80) {
+		channels = is_6ghz ? channels_80mhz_6ghz : channels_80mhz_5ghz;
+		num_chan = is_6ghz ? ARRAY_SIZE(channels_80mhz_6ghz) :
+			ARRAY_SIZE(channels_80mhz_5ghz);
+	} else if (op->bw == BW160) {
+		channels = is_6ghz ? channels_160mhz_6ghz :
+			channels_160mhz_5ghz;
+		num_chan =  is_6ghz ? ARRAY_SIZE(channels_160mhz_6ghz) :
+			ARRAY_SIZE(channels_160mhz_5ghz);
+	}
 
-	if (op->bw == BW160)
-		return wpas_add_channels(op, mode, active, channels_160mhz,
-					 ARRAY_SIZE(channels_160mhz));
-
-	return wpas_add_channels(op, mode, active, NULL, 0);
+	return wpas_add_channels(op, mode, active, channels, num_chan);
 }
 
 
@@ -766,10 +775,10 @@
 static int wpas_beacon_rep_add_frame_body(struct bitfield *eids,
 					  enum beacon_report_detail detail,
 					  struct wpa_bss *bss, u8 *buf,
-					  size_t buf_len, u8 **ies_buf,
+					  size_t buf_len, const u8 **ies_buf,
 					  size_t *ie_len, int add_fixed)
 {
-	u8 *ies = *ies_buf;
+	const u8 *ies = *ies_buf;
 	size_t ies_len = *ie_len;
 	u8 *pos = buf;
 	int rem_len;
@@ -851,7 +860,7 @@
 				    struct wpa_bss *bss,
 				    struct wpabuf **wpa_buf,
 				    struct rrm_measurement_beacon_report *rep,
-				    u8 **ie, size_t *ie_len, u8 idx)
+				    const u8 **ie, size_t *ie_len, u8 idx)
 {
 	int ret;
 	u8 *buf, *pos;
@@ -918,8 +927,8 @@
 			       u64 start, u64 parent_tsf)
 {
 	struct beacon_rep_data *data = &wpa_s->beacon_rep_data;
-	u8 *ies = (u8 *) (bss + 1);
-	u8 *pos = ies;
+	const u8 *ies = wpa_bss_ie_ptr(bss);
+	const u8 *pos = ies;
 	size_t ies_len = bss->ie_len ? bss->ie_len : bss->beacon_ie_len;
 	struct rrm_measurement_beacon_report rep;
 	u8 idx = 0;
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index b9e4162..c53474d 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -521,7 +521,7 @@
 {
 	struct wpabuf *default_ies = NULL;
 	u8 ext_capab[18];
-	int ext_capab_len;
+	int ext_capab_len, frame_id;
 	enum wpa_driver_if_type type = WPA_IF_STATION;
 
 #ifdef CONFIG_P2P
@@ -545,6 +545,20 @@
 		wpas_mbo_scan_ie(wpa_s, default_ies);
 #endif /* CONFIG_MBO */
 
+	if (type == WPA_IF_P2P_CLIENT)
+		frame_id = VENDOR_ELEM_PROBE_REQ_P2P;
+	else
+		frame_id = VENDOR_ELEM_PROBE_REQ;
+
+	if (wpa_s->vendor_elem[frame_id]) {
+		size_t len;
+
+		len = wpabuf_len(wpa_s->vendor_elem[frame_id]);
+		if (len > 0 && wpabuf_resize(&default_ies, len) == 0)
+			wpabuf_put_buf(default_ies,
+				       wpa_s->vendor_elem[frame_id]);
+	}
+
 	if (default_ies)
 		wpa_drv_set_default_scan_ies(wpa_s, wpabuf_head(default_ies),
 					     wpabuf_len(default_ies));
@@ -670,30 +684,38 @@
 #endif /* CONFIG_P2P */
 
 
-static void wpa_setband_scan_freqs_list(struct wpa_supplicant *wpa_s,
-					enum hostapd_hw_mode band,
-					struct wpa_driver_scan_params *params,
-					int is_6ghz)
+int wpa_add_scan_freqs_list(struct wpa_supplicant *wpa_s,
+			    enum hostapd_hw_mode band,
+			    struct wpa_driver_scan_params *params, bool is_6ghz)
 {
 	/* Include only supported channels for the specified band */
 	struct hostapd_hw_modes *mode;
-	int count, i;
+	int num_chans = 0;
+	int *freqs, i;
 
 	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));
-		return;
+	if (!mode)
+		return -1;
+
+	if (params->freqs) {
+		while (params->freqs[num_chans])
+			num_chans++;
 	}
 
-	params->freqs = os_calloc(mode->num_channels + 1, sizeof(int));
-	if (params->freqs == NULL)
-		return;
-	for (count = 0, i = 0; i < mode->num_channels; i++) {
+	freqs = os_realloc(params->freqs,
+			   (num_chans + mode->num_channels + 1) * sizeof(int));
+	if (!freqs)
+		return -1;
+
+	params->freqs = freqs;
+	for (i = 0; i < mode->num_channels; i++) {
 		if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED)
 			continue;
-		params->freqs[count++] = mode->channels[i].freq;
+		params->freqs[num_chans++] = mode->channels[i].freq;
 	}
+	params->freqs[num_chans] = 0;
+
+	return 0;
 }
 
 
@@ -704,12 +726,16 @@
 		return; /* unknown what channels the driver supports */
 	if (params->freqs)
 		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, 0);
-	else if (wpa_s->setband == WPA_SETBAND_2G)
-		wpa_setband_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G,
-					    params, 0);
+
+	if (wpa_s->setband_mask & WPA_SETBAND_5G)
+		wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, params,
+					0);
+	if (wpa_s->setband_mask & WPA_SETBAND_2G)
+		wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G, params,
+					0);
+	if (wpa_s->setband_mask & WPA_SETBAND_6G)
+		wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, params,
+					1);
 }
 
 
@@ -1201,7 +1227,12 @@
 	wpa_setband_scan_freqs(wpa_s, &params);
 
 	/* See if user specified frequencies. If so, scan only those. */
-	if (wpa_s->conf->freq_list && !params.freqs) {
+	if (wpa_s->last_scan_req == INITIAL_SCAN_REQ &&
+	    wpa_s->conf->initial_freq_list && !params.freqs) {
+		wpa_dbg(wpa_s, MSG_DEBUG,
+			"Optimize scan based on conf->initial_freq_list");
+		int_array_concat(&params.freqs, wpa_s->conf->initial_freq_list);
+	} else if (wpa_s->conf->freq_list && !params.freqs) {
 		wpa_dbg(wpa_s, MSG_DEBUG,
 			"Optimize scan based on conf->freq_list");
 		int_array_concat(&params.freqs, wpa_s->conf->freq_list);
@@ -1869,18 +1900,15 @@
 const u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res,
 				  u32 vendor_type)
 {
-	const u8 *end, *pos;
+	const u8 *ies;
+	const struct element *elem;
 
-	pos = (const u8 *) (res + 1);
-	end = pos + res->ie_len;
+	ies = (const u8 *) (res + 1);
 
-	while (end - pos > 1) {
-		if (2 + pos[1] > end - pos)
-			break;
-		if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
-		    vendor_type == WPA_GET_BE32(&pos[2]))
-			return pos;
-		pos += 2 + pos[1];
+	for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, ies, res->ie_len) {
+		if (elem->datalen >= 4 &&
+		    vendor_type == WPA_GET_BE32(elem->data))
+			return &elem->id;
 	}
 
 	return NULL;
@@ -1902,22 +1930,20 @@
 const u8 * wpa_scan_get_vendor_ie_beacon(const struct wpa_scan_res *res,
 					 u32 vendor_type)
 {
-	const u8 *end, *pos;
+	const u8 *ies;
+	const struct element *elem;
 
 	if (res->beacon_ie_len == 0)
 		return NULL;
 
-	pos = (const u8 *) (res + 1);
-	pos += res->ie_len;
-	end = pos + res->beacon_ie_len;
+	ies = (const u8 *) (res + 1);
+	ies += res->ie_len;
 
-	while (end - pos > 1) {
-		if (2 + pos[1] > end - pos)
-			break;
-		if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
-		    vendor_type == WPA_GET_BE32(&pos[2]))
-			return pos;
-		pos += 2 + pos[1];
+	for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, ies,
+			    res->beacon_ie_len) {
+		if (elem->datalen >= 4 &&
+		    vendor_type == WPA_GET_BE32(elem->data))
+			return &elem->id;
 	}
 
 	return NULL;
@@ -1948,12 +1974,17 @@
 	end = pos + res->ie_len;
 
 	while (end - pos > 1) {
-		if (2 + pos[1] > end - pos)
+		u8 ie, len;
+
+		ie = pos[0];
+		len = pos[1];
+		if (len > end - pos - 2)
 			break;
-		if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
-		    vendor_type == WPA_GET_BE32(&pos[2]))
-			wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4);
-		pos += 2 + pos[1];
+		pos += 2;
+		if (ie == WLAN_EID_VENDOR_SPECIFIC && len >= 4 &&
+		    vendor_type == WPA_GET_BE32(pos))
+			wpabuf_put_data(buf, pos + 4, len - 4);
+		pos += len;
 	}
 
 	if (wpabuf_len(buf) == 0) {
diff --git a/wpa_supplicant/scan.h b/wpa_supplicant/scan.h
index c9ce2ce..8eb5c73 100644
--- a/wpa_supplicant/scan.h
+++ b/wpa_supplicant/scan.h
@@ -86,5 +86,9 @@
 			      const u8 *ies, size_t ies_len, int rate,
 			      int snr);
 void wpa_supplicant_set_default_scan_ies(struct wpa_supplicant *wpa_s);
+int wpa_add_scan_freqs_list(struct wpa_supplicant *wpa_s,
+			    enum hostapd_hw_mode band,
+			    struct wpa_driver_scan_params *params,
+			    bool is_6ghz);
 
 #endif /* SCAN_H */
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index 7fec1cd..c6cef5b 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -300,7 +300,7 @@
 	*pos++ = WLAN_EID_RRM_ENABLED_CAPABILITIES;
 	*pos++ = rrm_ie_len;
 
-	/* Set supported capabilites flags */
+	/* Set supported capabilities flags */
 	if (wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION)
 		*pos |= WLAN_RRM_CAPS_LINK_MEASUREMENT;
 
@@ -1881,13 +1881,11 @@
 #endif /* CONFIG_DPP2 */
 
 	wpa_s->mscs_setup_done = false;
-	if (wpa_s->current_bss && wpa_s->robust_av.valid_config) {
+	if (wpa_bss_ext_capab(wpa_s->current_bss, WLAN_EXT_CAPAB_MSCS) &&
+	    wpa_s->robust_av.valid_config) {
 		struct wpabuf *mscs_ie;
 		size_t mscs_ie_len, buf_len, *wpa_ie_len, max_ie_len;
 
-		if (!wpa_bss_ext_capab(wpa_s->current_bss, WLAN_EXT_CAPAB_MSCS))
-			goto mscs_fail;
-
 		buf_len = 3 +	/* MSCS descriptor IE header */
 			  1 +	/* Request type */
 			  2 +	/* User priority control */
@@ -2462,7 +2460,7 @@
 	int start, end;
 
 	mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
-			HOSTAPD_MODE_IEEE80211G, 0);
+			HOSTAPD_MODE_IEEE80211G, false);
 	if (mode == NULL) {
 		/* No channels supported in this band - use empty list */
 		params->freqs = os_zalloc(sizeof(int));
diff --git a/wpa_supplicant/wmm_ac.c b/wpa_supplicant/wmm_ac.c
index 38800cc..d0fdd55 100644
--- a/wpa_supplicant/wmm_ac.c
+++ b/wpa_supplicant/wmm_ac.c
@@ -400,7 +400,7 @@
 
 	req_ac = up_to_ac[params->user_priority];
 
-	/* Requested accesss category must have acm */
+	/* Requested access category must have acm */
 	if (!wpa_s->wmm_ac_assoc_info->ac_params[req_ac].acm) {
 		wpa_printf(MSG_DEBUG, "WMM AC: AC %d is not ACM", req_ac);
 		return 0;
diff --git a/wpa_supplicant/wnm_sta.c b/wpa_supplicant/wnm_sta.c
index 6996b09..1b6c1b4 100644
--- a/wpa_supplicant/wnm_sta.c
+++ b/wpa_supplicant/wnm_sta.c
@@ -552,7 +552,7 @@
 			freq = 2407 + chan * 5;
 		else if (chan == 14)
 			freq = 2484;
-		else if (chan >= 36 && chan <= 169)
+		else if (chan >= 36 && chan <= 177)
 			freq = 5000 + chan * 5;
 	}
 	return freq;
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index 51c9642..b98a833 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -493,7 +493,8 @@
 		"p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
 		"sae_groups", "dtim_period", "beacon_int",
 		"ap_vendor_elements", "ignore_old_scan_res", "freq_list",
-		"scan_cur_freq", "sched_scan_interval",
+		"scan_cur_freq", "scan_res_valid_for_connect",
+		"sched_scan_interval",
 		"tdls_external_control", "osu_dir", "wowlan_triggers",
 		"p2p_search_delay", "mac_addr", "rand_addr_lifetime",
 		"preassoc_mac_addr", "key_mgmt_offload", "passive_scan",
@@ -589,7 +590,8 @@
 		"wps_nfc_dev_pw_id", "ext_password_backend",
 		"p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
 		"dtim_period", "beacon_int", "ignore_old_scan_res",
-		"scan_cur_freq", "sched_scan_interval",
+		"scan_cur_freq", "scan_res_valid_for_connect",
+		"sched_scan_interval",
 		"sched_scan_start_delay",
 		"tdls_external_control", "osu_dir", "wowlan_triggers",
 		"p2p_search_delay", "mac_addr", "rand_addr_lifetime",
@@ -1288,9 +1290,10 @@
 }
 
 
-static int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[])
+static int wpa_cli_cmd_bssid_ignore(struct wpa_ctrl *ctrl, int argc,
+				    char *argv[])
 {
-	return wpa_cli_cmd(ctrl, "BLACKLIST", 0, argc, argv);
+	return wpa_cli_cmd(ctrl, "BSSID_IGNORE", 0, argc, argv);
 }
 
 
@@ -1406,8 +1409,8 @@
 
 
 static const char *network_fields[] = {
-	"ssid", "scan_ssid", "bssid", "bssid_blacklist",
-	"bssid_whitelist", "psk", "proto", "key_mgmt",
+	"ssid", "scan_ssid", "bssid", "bssid_ignore",
+	"bssid_accept", "psk", "proto", "key_mgmt",
 	"bg_scan_period", "pairwise", "group", "auth_alg", "scan_freq",
 	"freq_list", "max_oper_chwidth", "ht40", "vht", "vht_center_freq1",
 	"vht_center_freq2", "ht", "edmg",
@@ -3066,6 +3069,20 @@
 
 #ifdef CONFIG_DPP2
 
+static int wpa_cli_cmd_dpp_controller_start(struct wpa_ctrl *ctrl, int argc,
+					    char *argv[])
+{
+	return wpa_cli_cmd(ctrl, "DPP_CONTROLLER_START", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_dpp_controller_stop(struct wpa_ctrl *ctrl, int argc,
+					    char *argv[])
+{
+	return wpa_ctrl_command(ctrl, "DPP_CONTROLLER_STOP");
+}
+
+
 static int wpa_cli_cmd_dpp_chirp(struct wpa_ctrl *ctrl, int argc,
 				 char *argv[])
 {
@@ -3085,7 +3102,8 @@
 
 static int wpa_ctrl_command_bss(struct wpa_ctrl *ctrl, const char *cmd)
 {
-	char buf[512], *pos, *bssid, *freq, *level, *flags, *ssid;
+	char buf[512], *pos, *bssid = NULL, *freq = NULL, *level = NULL,
+		*flags = NULL, *ssid = NULL;
 	size_t len;
 	int ret, id = -1;
 
@@ -3126,7 +3144,9 @@
 		*pos++ = '\0';
 	}
 	if (id != -1)
-		printf("%s\t%s\t%s\t%s\t%s\n", bssid, freq, level, flags, ssid);
+		printf("%s\t%s\t%s\t%s\t%s\n", bssid ? bssid : "N/A",
+		       freq ? freq : "N/A", level ? level : "N/A",
+		       flags ? flags : "N/A", ssid ? ssid : "N/A");
 	return id;
 }
 
@@ -3155,6 +3175,30 @@
 }
 
 
+#ifdef CONFIG_PASN
+
+static int wpa_cli_cmd_pasn_auth_start(struct wpa_ctrl *ctrl, int argc,
+				       char *argv[])
+{
+	return wpa_cli_cmd(ctrl, "PASN_AUTH_START", 4, argc, argv);
+}
+
+
+static int wpa_cli_cmd_pasn_auth_stop(struct wpa_ctrl *ctrl, int argc,
+				      char *argv[])
+{
+	return wpa_cli_cmd(ctrl, "PASN_AUTH_STOP", 0, argc, argv);
+}
+
+static int wpa_cli_cmd_ptksa_cache_list(struct wpa_ctrl *ctrl, int argc,
+					char *argv[])
+{
+	return wpa_cli_cmd(ctrl, "PTKSA_CACHE_LIST", 0, argc, argv);
+}
+
+#endif /* CONFIG_PASN */
+
+
 enum wpa_cli_cmd_flags {
 	cli_cmd_flag_none		= 0x00,
 	cli_cmd_flag_sensitive		= 0x01
@@ -3281,11 +3325,15 @@
 	{ "bssid", wpa_cli_cmd_bssid, wpa_cli_complete_network_id,
 	  cli_cmd_flag_none,
 	  "<network id> <BSSID> = set preferred BSSID for an SSID" },
-	{ "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
+	{ "bssid_ignore", wpa_cli_cmd_bssid_ignore, wpa_cli_complete_bss,
 	  cli_cmd_flag_none,
-	  "<BSSID> = add a BSSID to the blacklist\n"
-	  "blacklist clear = clear the blacklist\n"
-	  "blacklist = display the blacklist" },
+	  "<BSSID> = add a BSSID to the list of temporarily ignored BSSs\n"
+	  "bssid_ignore clear = clear the list of temporarily ignored BSSIDs\n"
+	  "bssid_ignore = display the list of temporarily ignored BSSIDs" },
+	{ "blacklist", /* deprecated alias for bssid_ignore */
+	  wpa_cli_cmd_bssid_ignore, wpa_cli_complete_bss,
+	  cli_cmd_flag_none,
+	  "= deprecated alias for bssid_ignore" },
 	{ "log_level", wpa_cli_cmd_log_level, NULL,
 	  cli_cmd_flag_none,
 	  "<level> [<timestamp>] = update the log level/timestamp\n"
@@ -3817,6 +3865,12 @@
 	  cli_cmd_flag_none,
 	  "*|<id> = remove DPP pkex information" },
 #ifdef CONFIG_DPP2
+	{ "dpp_controller_start", wpa_cli_cmd_dpp_controller_start, NULL,
+	  cli_cmd_flag_none,
+	  "[tcp_port=<port>] [role=..] = start DPP controller" },
+	{ "dpp_controller_stop", wpa_cli_cmd_dpp_controller_stop, NULL,
+	  cli_cmd_flag_none,
+	  "= stop DPP controller" },
 	{ "dpp_chirp", wpa_cli_cmd_dpp_chirp, NULL,
 	  cli_cmd_flag_none,
 	  "own=<BI ID> iter=<count> = start DPP chirp" },
@@ -3827,6 +3881,17 @@
 #endif /* CONFIG_DPP */
 	{ "all_bss", wpa_cli_cmd_all_bss, NULL, cli_cmd_flag_none,
 	  "= list all BSS entries (scan results)" },
+#ifdef CONFIG_PASN
+	{ "pasn_auth_start", wpa_cli_cmd_pasn_auth_start, NULL,
+	  cli_cmd_flag_none,
+	  "bssid=<BSSID> akmp=<WPA key mgmt> cipher=<WPA cipher> group=<group> nid=<network id> = Start PASN authentication" },
+	{ "pasn_auth_stop", wpa_cli_cmd_pasn_auth_stop, NULL,
+	  cli_cmd_flag_none,
+	  "= Stop PASN authentication" },
+	{ "ptksa_cache_list", wpa_cli_cmd_ptksa_cache_list, NULL,
+	  cli_cmd_flag_none,
+	  "= Get the PTKSA Cache" },
+#endif /* CONFIG_PASN */
 	{ NULL, NULL, NULL, cli_cmd_flag_none, NULL }
 };
 
@@ -4149,6 +4214,8 @@
 		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_OVERLAP)) {
+		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)) {
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index e1b4b4e..ffe162c 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -41,9 +41,10 @@
 #include "common/hw_features_common.h"
 #include "common/gas_server.h"
 #include "common/dpp.h"
+#include "common/ptksa_cache.h"
 #include "p2p/p2p.h"
 #include "fst/fst.h"
-#include "blacklist.h"
+#include "bssid_ignore.h"
 #include "wpas_glue.h"
 #include "wps_supplicant.h"
 #include "ibss_rsn.h"
@@ -222,7 +223,7 @@
 		bssid = wpa_s->pending_bssid;
 	wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
 		MAC2STR(bssid));
-	wpa_blacklist_add(wpa_s, bssid);
+	wpa_bssid_ignore_add(wpa_s, bssid);
 	wpas_notify_auth_timeout(wpa_s);
 	wpa_sm_notify_disassoc(wpa_s->wpa);
 	wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
@@ -291,7 +292,7 @@
 {
 	wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
 	eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
-	wpa_blacklist_del(wpa_s, wpa_s->bssid);
+	wpa_bssid_ignore_del(wpa_s, wpa_s->bssid);
 	os_free(wpa_s->last_con_fail_realm);
 	wpa_s->last_con_fail_realm = NULL;
 	wpa_s->last_con_fail_realm_len = 0;
@@ -574,9 +575,15 @@
 
 	wmm_ac_clear_saved_tspecs(wpa_s);
 	pmksa_candidate_free(wpa_s->wpa);
+	ptksa_cache_deinit(wpa_s->ptksa);
+	wpa_s->ptksa = NULL;
 	wpa_sm_deinit(wpa_s->wpa);
 	wpa_s->wpa = NULL;
-	wpa_blacklist_clear(wpa_s);
+	wpa_bssid_ignore_clear(wpa_s);
+
+#ifdef CONFIG_PASN
+	wpas_pasn_auth_stop(wpa_s);
+#endif /* CONFIG_PASN */
 
 	wpa_bss_deinit(wpa_s);
 
@@ -727,6 +734,10 @@
 	dpp_global_deinit(wpa_s->dpp);
 	wpa_s->dpp = NULL;
 #endif /* CONFIG_DPP */
+
+#ifdef CONFIG_PASN
+	wpas_pasn_auth_stop(wpa_s);
+#endif /* CONFIG_PASN */
 }
 
 
@@ -1089,13 +1100,19 @@
 void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
 {
 	enum wpa_states old_state = wpa_s->wpa_state;
+	enum wpa_states new_state;
+
+	if (old_state == WPA_SCANNING)
+		new_state = WPA_SCANNING;
+	else
+		new_state = WPA_DISCONNECTED;
 
 	wpa_s->pairwise_cipher = 0;
 	wpa_s->group_cipher = 0;
 	wpa_s->mgmt_group_cipher = 0;
 	wpa_s->key_mgmt = 0;
 	if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
-		wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
+		wpa_supplicant_set_state(wpa_s, new_state);
 
 	if (wpa_s->wpa_state != old_state)
 		wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
@@ -1190,7 +1207,7 @@
 		wpa_s->reassociate = 1;
 		wpa_supplicant_req_scan(wpa_s, 0, 0);
 	}
-	wpa_blacklist_clear(wpa_s);
+	wpa_bssid_ignore_clear(wpa_s);
 	wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
 	return 0;
 }
@@ -1640,7 +1657,9 @@
 	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
 			 wpas_get_ssid_pmf(wpa_s, ssid));
 #ifdef CONFIG_OCV
-	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv);
+	if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
+	    (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OCV))
+		wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv);
 #endif /* CONFIG_OCV */
 	sae_pwe = wpa_s->conf->sae_pwe;
 	if (ssid->sae_password_id && sae_pwe != 3)
@@ -2127,6 +2146,24 @@
 }
 
 
+int wpas_restore_permanent_mac_addr(struct wpa_supplicant *wpa_s)
+{
+	if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
+		wpa_msg(wpa_s, MSG_INFO,
+			"Could not restore permanent MAC address");
+		return -1;
+	}
+	wpa_s->mac_addr_changed = 0;
+	if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
+		wpa_msg(wpa_s, MSG_INFO,
+			"Could not update MAC address information");
+		return -1;
+	}
+	wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
+	return 0;
+}
+
+
 static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
 
 /**
@@ -2187,18 +2224,8 @@
 			return;
 		wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
 	} else if (rand_style == 0 && wpa_s->mac_addr_changed) {
-		if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
-			wpa_msg(wpa_s, MSG_INFO,
-				"Could not restore permanent MAC address");
+		if (wpas_restore_permanent_mac_addr(wpa_s) < 0)
 			return;
-		}
-		wpa_s->mac_addr_changed = 0;
-		if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
-			wpa_msg(wpa_s, MSG_INFO,
-				"Could not update MAC address information");
-			return;
-		}
-		wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
 	}
 	wpa_s->last_ssid = ssid;
 
@@ -2250,10 +2277,6 @@
 			return;
 		}
 		wpa_s->current_bss = bss;
-		wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d",
-			wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
-			ssid->id);
-		wpas_notify_mesh_group_started(wpa_s, ssid);
 #else /* CONFIG_MESH */
 		wpa_msg(wpa_s, MSG_ERROR,
 			"mesh mode support not included in the build");
@@ -2277,8 +2300,7 @@
 
 #ifdef CONFIG_TDLS
 	if (bss)
-		wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
-				bss->ie_len);
+		wpa_tdls_ap_ies(wpa_s->wpa, wpa_bss_ie_ptr(bss), bss->ie_len);
 #endif /* CONFIG_TDLS */
 
 #ifdef CONFIG_MBO
@@ -2425,6 +2447,8 @@
 	if (!mode)
 		return;
 
+	freq->channel = channel;
+
 	is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G ||
 		hw_mode == HOSTAPD_MODE_IEEE80211B;
 
@@ -3199,13 +3223,11 @@
 		wpa_ie_len += wpa_s->rsnxe_len;
 	}
 
-	if (bss && wpa_s->robust_av.valid_config) {
+	if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS) &&
+	    wpa_s->robust_av.valid_config) {
 		struct wpabuf *mscs_ie;
 		size_t mscs_ie_len, buf_len;
 
-		if (!wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS))
-			goto mscs_fail;
-
 		buf_len = 3 +	/* MSCS descriptor IE header */
 			  1 +	/* Request type */
 			  2 +	/* User priority control */
@@ -3401,7 +3423,7 @@
 	if (hw_mode == NUM_HOSTAPD_MODES)
 		goto fail;
 
-	mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, 0);
+	mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, false);
 	if (!mode)
 		goto fail;
 
@@ -3493,6 +3515,20 @@
 	os_memset(&params, 0, sizeof(params));
 	wpa_s->reassociate = 0;
 	wpa_s->eap_expected_failure = 0;
+
+	/* Starting new association, so clear the possibly used WPA IE from the
+	 * previous association. */
+	wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
+	wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
+	wpa_s->rsnxe_len = 0;
+	wpa_s->mscs_setup_done = false;
+
+	wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
+	if (!wpa_ie) {
+		wpas_connect_work_done(wpa_s);
+		return;
+	}
+
 	if (bss &&
 	    (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
 #ifdef CONFIG_IEEE80211R
@@ -3541,19 +3577,6 @@
 
 	wpa_supplicant_cancel_scan(wpa_s);
 
-	/* Starting new association, so clear the possibly used WPA IE from the
-	 * previous association. */
-	wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
-	wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
-	wpa_s->rsnxe_len = 0;
-	wpa_s->mscs_setup_done = false;
-
-	wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
-	if (!wpa_ie) {
-		wpas_connect_work_done(wpa_s);
-		return;
-	}
-
 	wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
 	use_crypt = 1;
 	cipher_pairwise = wpa_s->pairwise_cipher;
@@ -3641,8 +3664,8 @@
 	}
 
 	if (bss && ssid->enable_edmg)
-		edmg_ie_oper = get_ie_ext((const u8 *) (bss + 1), bss->ie_len,
-					  WLAN_EID_EXT_EDMG_OPERATION);
+		edmg_ie_oper = wpa_bss_get_ie_ext(bss,
+						  WLAN_EID_EXT_EDMG_OPERATION);
 	else
 		edmg_ie_oper = NULL;
 
@@ -3832,6 +3855,10 @@
 	    wpa_s->current_ssid)
 		params.prev_bssid = prev_bssid;
 
+#ifdef CONFIG_SAE
+	params.sae_pwe = wpa_s->conf->sae_pwe;
+#endif /* CONFIG_SAE */
+
 	ret = wpa_drv_associate(wpa_s, &params);
 	os_free(wpa_ie);
 	if (ret < 0) {
@@ -3990,7 +4017,7 @@
 			wpa_s->ifname);
 		wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
 					       mconf->meshid_len, reason_code);
-		wpa_supplicant_leave_mesh(wpa_s);
+		wpa_supplicant_leave_mesh(wpa_s, true);
 	}
 #endif /* CONFIG_MESH */
 
@@ -5115,6 +5142,7 @@
 	wpa_s->parent = parent ? parent : wpa_s;
 	wpa_s->p2pdev = wpa_s->parent;
 	wpa_s->sched_scanning = 0;
+	wpa_s->setband_mask = WPA_SETBAND_AUTO;
 
 	dl_list_init(&wpa_s->bss_tmp_disallowed);
 	dl_list_init(&wpa_s->fils_hlp_req);
@@ -5859,7 +5887,7 @@
 		dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
 				 list) {
 			if (os_strcmp(tmp->type, "scan") == 0 &&
-			    radio->external_scan_running &&
+			    external_scan_running(radio) &&
 			    (((struct wpa_driver_scan_params *)
 			      tmp->ctx)->only_new_results ||
 			     tmp->wpa_s->clear_driver_scan_cache))
@@ -5915,7 +5943,7 @@
 			 * rejected by kernel.
 			 */
 			if (os_strcmp(tmp->type, "scan") == 0 &&
-			    radio->external_scan_running &&
+			    external_scan_running(radio) &&
 			    (((struct wpa_driver_scan_params *)
 			      tmp->ctx)->only_new_results ||
 			     tmp->wpa_s->clear_driver_scan_cache))
@@ -5954,7 +5982,7 @@
 		if (work->started)
 			return; /* already started and still in progress */
 
-		if (wpa_s && wpa_s->radio->external_scan_running) {
+		if (wpa_s && external_scan_running(wpa_s->radio)) {
 			wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
 			return;
 		}
@@ -6050,6 +6078,10 @@
 		   wpa_s->ifname, radio->name);
 	dl_list_del(&wpa_s->radio_list);
 	radio_remove_works(wpa_s, NULL, 0);
+	/* If the interface that triggered the external scan was removed, the
+	 * external scan is no longer running. */
+	if (wpa_s == radio->external_scan_req_interface)
+		radio->external_scan_req_interface = NULL;
 	wpa_s->radio = NULL;
 	if (!dl_list_empty(&radio->ifaces))
 		return; /* Interfaces remain for this radio */
@@ -6671,8 +6703,12 @@
 
 	wpa_s->disconnected = 1;
 	if (wpa_s->drv_priv) {
-		/* Don't deauthenticate if WoWLAN is enabled */
-		if (!wpa_drv_get_wowlan(wpa_s)) {
+		/*
+		 * Don't deauthenticate if WoWLAN is enable and not explicitly
+		 * been configured to disconnect.
+		 */
+		if (!wpa_drv_get_wowlan(wpa_s) ||
+		    wpa_s->conf->wowlan_disconnect_on_deinit) {
 			wpa_supplicant_deauthenticate(
 				wpa_s, WLAN_REASON_DEAUTH_LEAVING);
 
@@ -6717,7 +6753,7 @@
 
 #ifdef CONFIG_MESH
 	if (wpa_s->ifmsh) {
-		wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
+		wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, true);
 		wpa_s->ifmsh = NULL;
 	}
 #endif /* CONFIG_MESH */
@@ -6792,7 +6828,7 @@
 			continue;
 		iface = wpa_supplicant_match_iface(global, ifi->if_name);
 		if (iface) {
-			wpa_s = wpa_supplicant_add_iface(global, iface, NULL);
+			wpa_supplicant_add_iface(global, iface, NULL);
 			os_free(iface);
 		}
 	}
@@ -7375,7 +7411,7 @@
 			continue;
 		if (bss->ssid_len == cbss->ssid_len &&
 		    os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
-		    !wpa_blacklist_is_blacklisted(wpa_s, bss->bssid)) {
+		    !wpa_bssid_ignore_is_listed(wpa_s, bss->bssid)) {
 			add_freq(freqs, &num_freqs, bss->freq);
 			if (num_freqs == max_freqs)
 				break;
@@ -7405,7 +7441,7 @@
 	eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
 
 	/*
-	 * There is no point in blacklisting the AP if this event is
+	 * There is no point in ignoring the AP temporarily if this event is
 	 * generated based on local request to disconnect.
 	 */
 	if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) {
@@ -7427,13 +7463,13 @@
 	}
 
 	/*
-	 * Add the failed BSSID into the blacklist and speed up next scan
+	 * Add the failed BSSID into the ignore list and speed up next scan
 	 * attempt if there could be other APs that could accept association.
 	 */
-	count = wpa_blacklist_add(wpa_s, bssid);
+	count = wpa_bssid_ignore_add(wpa_s, bssid);
 	if (count == 1 && wpa_s->current_bss) {
 		/*
-		 * This BSS was not in the blacklist before. If there is
+		 * This BSS was not in the ignore list before. If there is
 		 * another BSS available for the same ESS, we should try that
 		 * next. Otherwise, we may as well try this one once more
 		 * before allowing other, likely worse, ESSes to be considered.
@@ -7442,7 +7478,7 @@
 		if (freqs) {
 			wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
 				"has been seen; try it next");
-			wpa_blacklist_add(wpa_s, bssid);
+			wpa_bssid_ignore_add(wpa_s, bssid);
 			/*
 			 * On the next scan, go through only the known channels
 			 * used in this ESS based on previous scans to speed up
@@ -8100,7 +8136,7 @@
 
 struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
 				   u16 num_modes, enum hostapd_hw_mode mode,
-				   int is_6ghz)
+				   bool is_6ghz)
 {
 	u16 i;
 
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index 2f1e31b..11d1885 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -366,7 +366,14 @@
 
 # Password (and passphrase, etc.) backend for external storage
 # format: <backend name>[:<optional backend parameters>]
+# Test backend which stores passwords in memory. Should only be used for
+# development purposes.
 #ext_password_backend=test:pw1=password|pw2=testing
+# File-based backend which reads passwords from a file. The parameter
+# identifies the file to read passwords from. The password file follows the
+# format of wpa_supplicant.conf and accepts simple `key=passphrase` formatted
+# passwords.
+#ext_password_backend=file:/path/to/passwords.conf
 
 
 # Disable P2P functionality
@@ -458,6 +465,9 @@
 # 1:  Scan current operating frequency if another VIF on the same radio
 #     is already associated.
 
+# Seconds to consider old scan results valid for association (default: 5)
+#scan_res_valid_for_connect=5
+
 # MAC address policy default
 # 0 = use permanent MAC address
 # 1 = use random MAC address for each ESS connection
@@ -526,7 +536,7 @@
 #go_venue_group=7
 #go_venue_type=1
 
-# Homogenous ESS identifier
+# Homogeneous ESS identifier
 # If this is set, scans will be used to request response only from BSSes
 # belonging to the specified Homogeneous ESS. This is used only if interworking
 # is enabled.
@@ -981,7 +991,8 @@
 # This is a countermeasure against multi-channel man-in-the-middle attacks.
 # Enabling this automatically also enables ieee80211w, if not yet enabled.
 # 0 = disabled (default)
-# 1 = enabled
+# 1 = enabled if wpa_supplicant's SME in use. Otherwise enabled only when the
+#     driver indicates support for operating channel validation.
 #ocv=1
 #
 # auth_alg: list of allowed IEEE 802.11 authentication algorithms
@@ -1482,8 +1493,11 @@
 # 2: do not allow PFS to be used
 #dpp_pfs=0
 
-# Whether Beacon protection is enabled
-# This depends on management frame protection (ieee80211w) being enabled.
+# Whether beacon protection is enabled
+# This depends on management frame protection (ieee80211w) being enabled and
+# beacon protection support indication from the driver.
+# 0 = disabled (default)
+# 1 = enabled
 #beacon_prot=0
 
 # OWE DH Group
@@ -2012,12 +2026,12 @@
 	key_mgmt=NONE
 }
 
-# Example configuration blacklisting two APs - these will be ignored
+# Example configuration ignoring two APs - these will be ignored
 # for this network.
 network={
 	ssid="example"
 	psk="very secret passphrase"
-	bssid_blacklist=02:11:22:33:44:55 02:22:aa:44:55:66
+	bssid_ignore=02:11:22:33:44:55 02:22:aa:44:55:66
 }
 
 # Example configuration limiting AP selection to a specific set of APs;
@@ -2025,7 +2039,7 @@
 network={
 	ssid="example"
 	psk="very secret passphrase"
-	bssid_whitelist=02:55:ae:bc:00:00/ff:ff:ff:ff:00:00 00:00:77:66:55:44/00:00:ff:ff:ff:ff
+	bssid_accept=02:55:ae:bc:00:00/ff:ff:ff:ff:00:00 00:00:77:66:55:44/00:00:ff:ff:ff:ff
 }
 
 # Example config file that will only scan on channel 36.
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 3fcd95a..56adf89 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -14,6 +14,8 @@
 #include "common/defs.h"
 #include "common/sae.h"
 #include "common/wpa_ctrl.h"
+#include "crypto/sha384.h"
+#include "eapol_supp/eapol_supp_sm.h"
 #include "wps/wps_defs.h"
 #include "config_ssid.h"
 #include "wmm_ac.h"
@@ -47,9 +49,6 @@
 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()
  */
@@ -330,12 +329,23 @@
 struct wpa_radio {
 	char name[16]; /* from driver_ops get_radio_name() or empty if not
 			* available */
-	unsigned int external_scan_running:1;
+	/** NULL if no external scan running. */
+	struct wpa_supplicant *external_scan_req_interface;
 	unsigned int num_active_works;
 	struct dl_list ifaces; /* struct wpa_supplicant::radio_list entries */
 	struct dl_list work; /* struct wpa_radio_work::list entries */
 };
 
+/**
+ * Checks whether an external scan is running on a given radio.
+ * @radio: Pointer to radio struct
+ * Returns: true if an external scan is running, false otherwise.
+ */
+static inline bool external_scan_running(struct wpa_radio *radio)
+{
+	return radio && radio->external_scan_req_interface;
+}
+
 #define MAX_ACTIVE_WORKS 2
 
 
@@ -514,6 +524,54 @@
 	bool valid_config;
 };
 
+#ifdef CONFIG_PASN
+
+struct pasn_fils {
+	u8 nonce[FILS_NONCE_LEN];
+	u8 anonce[FILS_NONCE_LEN];
+	u8 session[FILS_SESSION_LEN];
+	u8 erp_pmkid[PMKID_LEN];
+	bool completed;
+};
+
+struct wpas_pasn {
+	int akmp;
+	int cipher;
+	u16 group;
+	int freq;
+
+	u8 trans_seq;
+	u8 status;
+
+	u8 bssid[ETH_ALEN];
+	size_t pmk_len;
+	u8 pmk[PMK_LEN_MAX];
+	bool using_pmksa;
+
+	u8 hash[SHA384_MAC_LEN];
+
+	struct wpabuf *beacon_rsne_rsnxe;
+	struct wpa_ptk ptk;
+	struct crypto_ecdh *ecdh;
+
+#ifdef CONFIG_SAE
+	struct sae_data sae;
+#endif /* CONFIG_SAE */
+
+	struct wpa_ssid *ssid;
+
+#ifdef CONFIG_FILS
+	struct pasn_fils fils;
+#endif /* CONFIG_FILS */
+
+#ifdef CONFIG_IEEE80211R
+	u8 pmk_r1[PMK_LEN_MAX];
+	size_t pmk_r1_len;
+	u8 pmk_r1_name[WPA_PMK_NAME_LEN];
+#endif /* CONFIG_IEEE80211R */
+};
+#endif /* CONFIG_PASN */
+
 /**
  * struct wpa_supplicant - Internal data for wpa_supplicant interface
  *
@@ -594,7 +652,7 @@
 	struct wpa_ssid_value *disallow_aps_ssid;
 	size_t disallow_aps_ssid_count;
 
-	enum set_band setband;
+	u32 setband_mask;
 
 	/* Preferred network for the next connection attempt */
 	struct wpa_ssid *next_ssid;
@@ -619,6 +677,7 @@
 
 	void (*scan_res_handler)(struct wpa_supplicant *wpa_s,
 				 struct wpa_scan_results *scan_res);
+	void (*scan_res_fail_handler)(struct wpa_supplicant *wpa_s);
 	struct dl_list bss; /* struct wpa_bss::list */
 	struct dl_list bss_id; /* struct wpa_bss::list_id */
 	size_t num_bss;
@@ -638,6 +697,8 @@
 	int interface_removed; /* whether the network interface has been
 				* removed */
 	struct wpa_sm *wpa;
+	struct ptksa_cache *ptksa;
+
 	struct eapol_sm *eapol;
 
 	struct ctrl_iface_priv *ctrl_iface;
@@ -664,7 +725,7 @@
 	unsigned int keys_cleared; /* bitfield of key indexes that the driver is
 				    * known not to be configured with a key */
 
-	struct wpa_blacklist *blacklist;
+	struct wpa_bssid_ignore *bssid_ignore;
 
 	/* Number of connection failures since last successful connection */
 	unsigned int consecutive_conn_failures;
@@ -772,7 +833,7 @@
 	struct wps_er *wps_er;
 	unsigned int wps_run;
 	struct os_reltime wps_pin_start_time;
-	int blacklist_cleared;
+	bool bssid_ignore_cleared;
 
 	struct wpabuf *pending_eapol_rx;
 	struct os_reltime pending_eapol_rx_time;
@@ -1339,6 +1400,11 @@
 	unsigned int multi_ap_fronthaul:1;
 	struct robust_av_data robust_av;
 	bool mscs_setup_done;
+
+#ifdef CONFIG_PASN
+	struct wpas_pasn pasn;
+	struct wpa_radio_work *pasn_auth_work;
+#endif /* CONFIG_PASN */
 };
 
 
@@ -1367,6 +1433,7 @@
 int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
 			      struct wpa_bss *bss, struct wpa_ssid *ssid,
 			      u8 *wpa_ie, size_t *wpa_ie_len);
+int wpas_restore_permanent_mac_addr(struct wpa_supplicant *wpa_s);
 void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
 			      struct wpa_bss *bss,
 			      struct wpa_ssid *ssid);
@@ -1641,7 +1708,7 @@
 
 struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
 				   u16 num_modes, enum hostapd_hw_mode mode,
-				   int is_6ghz);
+				   bool is_6ghz);
 
 void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
 			  unsigned int sec, int rssi_threshold);
@@ -1673,4 +1740,13 @@
 void wpas_handle_assoc_resp_mscs(struct wpa_supplicant *wpa_s, const u8 *bssid,
 				 const u8 *ies, size_t ies_len);
 
+int wpas_pasn_auth_start(struct wpa_supplicant *wpa_s,
+			 const u8 *bssid, int akmp, int cipher,
+			 u16 group, int network_id);
+void wpas_pasn_auth_stop(struct wpa_supplicant *wpa_s);
+int wpas_pasn_auth_tx_status(struct wpa_supplicant *wpa_s,
+			     const u8 *data, size_t data_len, u8 acked);
+int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s,
+		      const struct ieee80211_mgmt *mgmt, size_t len);
+
 #endif /* WPA_SUPPLICANT_I_H */
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index 4462afc..b1c606f 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -16,6 +16,7 @@
 #include "config.h"
 #include "l2_packet/l2_packet.h"
 #include "common/wpa_common.h"
+#include "common/ptksa_cache.h"
 #include "wpa_supplicant_i.h"
 #include "driver_i.h"
 #include "rsn_supp/pmksa_cache.h"
@@ -1343,6 +1344,15 @@
 #endif /* CONFIG_NO_CONFIG_WRITE */
 }
 
+
+static void wpa_supplicant_store_ptk(void *ctx, u8 *addr, int cipher,
+				     u32 life_time, const struct wpa_ptk *ptk)
+{
+	struct wpa_supplicant *wpa_s = ctx;
+
+	ptksa_cache_add(wpa_s->ptksa, addr, cipher, life_time, ptk);
+}
+
 #endif /* CONFIG_NO_WPA */
 
 
@@ -1350,9 +1360,20 @@
 {
 #ifndef CONFIG_NO_WPA
 	struct wpa_sm_ctx *ctx;
+
+	wpa_s->ptksa = ptksa_cache_init();
+	if (!wpa_s->ptksa) {
+		wpa_printf(MSG_ERROR, "Failed to allocate PTKSA");
+		return -1;
+	}
+
 	ctx = os_zalloc(sizeof(*ctx));
 	if (ctx == NULL) {
 		wpa_printf(MSG_ERROR, "Failed to allocate WPA context.");
+
+		ptksa_cache_deinit(wpa_s->ptksa);
+		wpa_s->ptksa = NULL;
+
 		return -1;
 	}
 
@@ -1396,12 +1417,15 @@
 	ctx->fils_hlp_rx = wpa_supplicant_fils_hlp_rx;
 	ctx->channel_info = wpa_supplicant_channel_info;
 	ctx->transition_disable = wpa_supplicant_transition_disable;
+	ctx->store_ptk = wpa_supplicant_store_ptk;
 
 	wpa_s->wpa = wpa_sm_init(ctx);
 	if (wpa_s->wpa == NULL) {
-		wpa_printf(MSG_ERROR, "Failed to initialize WPA state "
-			   "machine");
+		wpa_printf(MSG_ERROR,
+			   "Failed to initialize WPA state machine");
 		os_free(ctx);
+		ptksa_cache_deinit(wpa_s->ptksa);
+		wpa_s->ptksa = NULL;
 		return -1;
 	}
 #endif /* CONFIG_NO_WPA */
@@ -1451,7 +1475,16 @@
 			conf.fils_cache_id =
 				wpa_bss_get_fils_cache_id(wpa_s->current_bss);
 #endif /* CONFIG_FILS */
-		conf.beacon_prot = ssid->beacon_prot;
+		if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_BEACON_PROTECTION) ||
+		    (wpa_s->drv_flags2 &
+		     WPA_DRIVER_FLAGS2_BEACON_PROTECTION_CLIENT))
+			conf.beacon_prot = ssid->beacon_prot;
+
+#ifdef CONFIG_PASN
+#ifdef CONFIG_TESTING_OPTIONS
+		conf.force_kdk_derivation = wpa_s->conf->force_kdk_derivation;
+#endif /* CONFIG_TESTING_OPTIONS */
+#endif /* CONFIG_PASN */
 	}
 	wpa_sm_set_config(wpa_s->wpa, ssid ? &conf : NULL);
 }
diff --git a/wpa_supplicant/wpas_module_tests.c b/wpa_supplicant/wpas_module_tests.c
index 1c136f7..ce5398c 100644
--- a/wpa_supplicant/wpas_module_tests.c
+++ b/wpa_supplicant/wpas_module_tests.c
@@ -11,77 +11,77 @@
 #include "utils/common.h"
 #include "utils/module_tests.h"
 #include "wpa_supplicant_i.h"
-#include "blacklist.h"
+#include "bssid_ignore.h"
 
 
-static int wpas_blacklist_module_tests(void)
+static int wpas_bssid_ignore_module_tests(void)
 {
 	struct wpa_supplicant wpa_s;
 	int ret = -1;
 
 	os_memset(&wpa_s, 0, sizeof(wpa_s));
 
-	wpa_blacklist_clear(&wpa_s);
+	wpa_bssid_ignore_clear(&wpa_s);
 
-	if (wpa_blacklist_get(NULL, NULL) != NULL ||
-	    wpa_blacklist_get(NULL, (u8 *) "123456") != NULL ||
-	    wpa_blacklist_get(&wpa_s, NULL) != NULL ||
-	    wpa_blacklist_get(&wpa_s, (u8 *) "123456") != NULL)
+	if (wpa_bssid_ignore_get(NULL, NULL) != NULL ||
+	    wpa_bssid_ignore_get(NULL, (u8 *) "123456") != NULL ||
+	    wpa_bssid_ignore_get(&wpa_s, NULL) != NULL ||
+	    wpa_bssid_ignore_get(&wpa_s, (u8 *) "123456") != NULL)
 		goto fail;
 
-	if (wpa_blacklist_add(NULL, NULL) == 0 ||
-	    wpa_blacklist_add(NULL, (u8 *) "123456") == 0 ||
-	    wpa_blacklist_add(&wpa_s, NULL) == 0)
+	if (wpa_bssid_ignore_add(NULL, NULL) == 0 ||
+	    wpa_bssid_ignore_add(NULL, (u8 *) "123456") == 0 ||
+	    wpa_bssid_ignore_add(&wpa_s, NULL) == 0)
 		goto fail;
 
-	if (wpa_blacklist_del(NULL, NULL) == 0 ||
-	    wpa_blacklist_del(NULL, (u8 *) "123456") == 0 ||
-	    wpa_blacklist_del(&wpa_s, NULL) == 0 ||
-	    wpa_blacklist_del(&wpa_s, (u8 *) "123456") == 0)
+	if (wpa_bssid_ignore_del(NULL, NULL) == 0 ||
+	    wpa_bssid_ignore_del(NULL, (u8 *) "123456") == 0 ||
+	    wpa_bssid_ignore_del(&wpa_s, NULL) == 0 ||
+	    wpa_bssid_ignore_del(&wpa_s, (u8 *) "123456") == 0)
 		goto fail;
 
-	if (wpa_blacklist_add(&wpa_s, (u8 *) "111111") < 0 ||
-	    wpa_blacklist_add(&wpa_s, (u8 *) "111111") < 0 ||
-	    wpa_blacklist_add(&wpa_s, (u8 *) "222222") < 0 ||
-	    wpa_blacklist_add(&wpa_s, (u8 *) "333333") < 0 ||
-	    wpa_blacklist_add(&wpa_s, (u8 *) "444444") < 0 ||
-	    wpa_blacklist_del(&wpa_s, (u8 *) "333333") < 0 ||
-	    wpa_blacklist_del(&wpa_s, (u8 *) "xxxxxx") == 0 ||
-	    wpa_blacklist_get(&wpa_s, (u8 *) "xxxxxx") != NULL ||
-	    wpa_blacklist_get(&wpa_s, (u8 *) "111111") == NULL ||
-	    wpa_blacklist_get(&wpa_s, (u8 *) "222222") == NULL ||
-	    wpa_blacklist_get(&wpa_s, (u8 *) "444444") == NULL ||
-	    wpa_blacklist_del(&wpa_s, (u8 *) "111111") < 0 ||
-	    wpa_blacklist_del(&wpa_s, (u8 *) "222222") < 0 ||
-	    wpa_blacklist_del(&wpa_s, (u8 *) "444444") < 0 ||
-	    wpa_blacklist_add(&wpa_s, (u8 *) "111111") < 0 ||
-	    wpa_blacklist_add(&wpa_s, (u8 *) "222222") < 0 ||
-	    wpa_blacklist_add(&wpa_s, (u8 *) "333333") < 0)
+	if (wpa_bssid_ignore_add(&wpa_s, (u8 *) "111111") < 0 ||
+	    wpa_bssid_ignore_add(&wpa_s, (u8 *) "111111") < 0 ||
+	    wpa_bssid_ignore_add(&wpa_s, (u8 *) "222222") < 0 ||
+	    wpa_bssid_ignore_add(&wpa_s, (u8 *) "333333") < 0 ||
+	    wpa_bssid_ignore_add(&wpa_s, (u8 *) "444444") < 0 ||
+	    wpa_bssid_ignore_del(&wpa_s, (u8 *) "333333") < 0 ||
+	    wpa_bssid_ignore_del(&wpa_s, (u8 *) "xxxxxx") == 0 ||
+	    wpa_bssid_ignore_get(&wpa_s, (u8 *) "xxxxxx") != NULL ||
+	    wpa_bssid_ignore_get(&wpa_s, (u8 *) "111111") == NULL ||
+	    wpa_bssid_ignore_get(&wpa_s, (u8 *) "222222") == NULL ||
+	    wpa_bssid_ignore_get(&wpa_s, (u8 *) "444444") == NULL ||
+	    wpa_bssid_ignore_del(&wpa_s, (u8 *) "111111") < 0 ||
+	    wpa_bssid_ignore_del(&wpa_s, (u8 *) "222222") < 0 ||
+	    wpa_bssid_ignore_del(&wpa_s, (u8 *) "444444") < 0 ||
+	    wpa_bssid_ignore_add(&wpa_s, (u8 *) "111111") < 0 ||
+	    wpa_bssid_ignore_add(&wpa_s, (u8 *) "222222") < 0 ||
+	    wpa_bssid_ignore_add(&wpa_s, (u8 *) "333333") < 0)
 		goto fail;
 
-	wpa_blacklist_clear(&wpa_s);
+	wpa_bssid_ignore_clear(&wpa_s);
 
-	if (wpa_blacklist_add(&wpa_s, (u8 *) "111111") < 0 ||
-	    wpa_blacklist_add(&wpa_s, (u8 *) "222222") < 0 ||
-	    wpa_blacklist_add(&wpa_s, (u8 *) "333333") < 0 ||
-	    wpa_blacklist_add(&wpa_s, (u8 *) "444444") < 0 ||
-	    !wpa_blacklist_is_blacklisted(&wpa_s, (u8 *) "111111") ||
-	    wpa_blacklist_del(&wpa_s, (u8 *) "111111") < 0 ||
-	    wpa_blacklist_is_blacklisted(&wpa_s, (u8 *) "111111") ||
-	    wpa_blacklist_add(&wpa_s, (u8 *) "111111") < 0)
+	if (wpa_bssid_ignore_add(&wpa_s, (u8 *) "111111") < 0 ||
+	    wpa_bssid_ignore_add(&wpa_s, (u8 *) "222222") < 0 ||
+	    wpa_bssid_ignore_add(&wpa_s, (u8 *) "333333") < 0 ||
+	    wpa_bssid_ignore_add(&wpa_s, (u8 *) "444444") < 0 ||
+	    !wpa_bssid_ignore_is_listed(&wpa_s, (u8 *) "111111") ||
+	    wpa_bssid_ignore_del(&wpa_s, (u8 *) "111111") < 0 ||
+	    wpa_bssid_ignore_is_listed(&wpa_s, (u8 *) "111111") ||
+	    wpa_bssid_ignore_add(&wpa_s, (u8 *) "111111") < 0)
 		goto fail;
 
-	wpa_blacklist_update(&wpa_s);
+	wpa_bssid_ignore_update(&wpa_s);
 
-	if (!wpa_blacklist_is_blacklisted(&wpa_s, (u8 *) "111111"))
+	if (!wpa_bssid_ignore_is_listed(&wpa_s, (u8 *) "111111"))
 		goto fail;
 
 	ret = 0;
 fail:
-	wpa_blacklist_clear(&wpa_s);
+	wpa_bssid_ignore_clear(&wpa_s);
 
 	if (ret)
-		wpa_printf(MSG_ERROR, "blacklist module test failure");
+		wpa_printf(MSG_ERROR, "bssid_ignore module test failure");
 
 	return ret;
 }
@@ -93,7 +93,7 @@
 
 	wpa_printf(MSG_INFO, "wpa_supplicant module tests");
 
-	if (wpas_blacklist_module_tests() < 0)
+	if (wpas_bssid_ignore_module_tests() < 0)
 		ret = -1;
 
 #ifdef CONFIG_WPS
diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c
index 47d85dc..1dd3d82 100644
--- a/wpa_supplicant/wps_supplicant.c
+++ b/wpa_supplicant/wps_supplicant.c
@@ -26,7 +26,7 @@
 #include "wpa_supplicant_i.h"
 #include "driver_i.h"
 #include "notify.h"
-#include "blacklist.h"
+#include "bssid_ignore.h"
 #include "bss.h"
 #include "scan.h"
 #include "ap.h"
@@ -94,14 +94,14 @@
 		wpa_printf(MSG_DEBUG, "WPS: PIN registration with " MACSTR
 			   " did not succeed - continue trying to find "
 			   "suitable AP", MAC2STR(bssid));
-		wpa_blacklist_add(wpa_s, bssid);
+		wpa_bssid_ignore_add(wpa_s, bssid);
 
 		wpa_supplicant_deauthenticate(wpa_s,
 					      WLAN_REASON_DEAUTH_LEAVING);
 		wpa_s->reassociate = 1;
 		wpa_supplicant_req_scan(wpa_s,
-					wpa_s->blacklist_cleared ? 5 : 0, 0);
-		wpa_s->blacklist_cleared = 0;
+					wpa_s->bssid_ignore_cleared ? 5 : 0, 0);
+		wpa_s->bssid_ignore_cleared = false;
 		return 1;
 	}
 
@@ -1139,7 +1139,7 @@
 	wpa_s->scan_runs = 0;
 	wpa_s->normal_scans = 0;
 	wpa_s->wps_success = 0;
-	wpa_s->blacklist_cleared = 0;
+	wpa_s->bssid_ignore_cleared = false;
 
 	wpa_supplicant_cancel_sched_scan(wpa_s);
 	wpa_supplicant_req_scan(wpa_s, 0, 0);
@@ -2883,10 +2883,11 @@
 
 	for (i = 0; i < wpa_s->num_wps_ap; i++) {
 		struct wps_ap_info *ap = &wpa_s->wps_ap[i];
-		struct wpa_blacklist *e = wpa_blacklist_get(wpa_s, ap->bssid);
+		struct wpa_bssid_ignore *e = wpa_bssid_ignore_get(wpa_s,
+								  ap->bssid);
 
 		wpa_printf(MSG_DEBUG, "WPS: AP[%d] " MACSTR " type=%d "
-			   "tries=%d last_attempt=%d sec ago blacklist=%d",
+			   "tries=%d last_attempt=%d sec ago bssid_ignore=%d",
 			   (int) i, MAC2STR(ap->bssid), ap->type, ap->tries,
 			   ap->last_attempt.sec > 0 ?
 			   (int) now.sec - (int) ap->last_attempt.sec : -1,
@@ -2948,7 +2949,7 @@
 				   MAC2STR(res->bssid), ap->type, type);
 			ap->type = type;
 			if (type != WPS_AP_NOT_SEL_REG)
-				wpa_blacklist_del(wpa_s, ap->bssid);
+				wpa_bssid_ignore_del(wpa_s, ap->bssid);
 		}
 		ap->pbc_active = pbc_active;
 		if (uuid)