[wpa_supplicant] Cumulative patch from c4e90da6d

Bug: 124017368
Test: Device boots up and connects to WPA3/OWE wifi networks, run traffic.
Test: Able to turn on/off softap, associate wifi STA, run traffic.
Test: DPP functional test.
Test: Regression test passed (Bug: 124052942)

c4e90da6d MBO: Move the WNM-Notification subtype definitions to common location
105b14f54 HS 2.0: Update the T&C Acceptance subtype value
65b487ae5 HS 2.0: Add QUIET=1 support for building hs20-osu-client
73f285dad Add FT-PSK to GET_CAPABILITY key_mgmt
6110753b1 nl80211: Clear PMKID add command message buffer
0fa33e05b nl80211: Clear connect command message buffer
b14e8ea1d nl80211: Request kernel to trim off payload of netlink requests from acks
789b48bb4 EAP peer: Clear temporary message buffers before freeing
8f99a3c26 Clear config item writing buffer before freeing it
a68e9b698 D-Bus: Fix P2P DeleteService dict iteration
0607346f1 D-Bus: Fix a memory leak in DeleteService handler
d05dda61d PEAP: Explicitly clear temporary keys from memory when using CMK
4e1cd3468 EAP-PEAP: Derive EMSK and use 128-octet derivation for MSK
d8c20ec59 DPP: Clear dpp_listen_freq on remain-on-channel failure
59fa20538 P2P: Allow the avoid channels for P2P discovery/negotiation
e34cd9f06 WNM: Fix WNM-Sleep Mode Request bounds checking
159a7fbde crl_reload_interval: Add CRL reloading support
83c860813 AP: Add wpa_psk_file reloading in runtime
ec5c39a55 AP: Allow identifying which passphrase station used with wpa_psk_file
b08c9ad0c AP: Expose PMK outside of wpa_auth module
89896c000 tests: Use python3 compatible print statement
bab493b90 tests: Use python3 compatible "except" statement
0dab47733 Write multi_ap_backhaul_sta to wpa_supplicant config
98251c6f2 dbus: Document more possible BSS/RSA/KeyMgmt values
1e591df06 Check supported types in wpas_mac_addr_rand_scan_set()
c85249aa1 Fix test compilation error related to sme_event_unprot_disconnect()
42d308635 SAE: Advertise Password Identifier use
59c693064 HS 2.0 server: Command line option to fetch the version information
2d1762fa4 HS 2.0 server: Alternative subrem updateNode for certificate credentials
d97cf2a11 HS 2.0 server: Use noMOUpdate in client certificate subrem
13a200a92 FILS: Remove notes about experimental implementation
86d4e0537 dbus: Expose support of SAE key management in BSS properties

Change-Id: I83ffca34ff5349c226db6215ff1ae35c3b7ab335
diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
index 39f8b50..1834fc5 100644
--- a/wpa_supplicant/Android.mk
+++ b/wpa_supplicant/Android.mk
@@ -238,6 +238,12 @@
 NEED_SHA384=y
 endif
 
+ifdef CONFIG_OCV
+L_CFLAGS += -DCONFIG_OCV
+OBJS += src/common/ocv.c
+CONFIG_IEEE80211W=y
+endif
+
 ifdef CONFIG_IEEE80211W
 L_CFLAGS += -DCONFIG_IEEE80211W
 NEED_SHA256=y
diff --git a/wpa_supplicant/ChangeLog b/wpa_supplicant/ChangeLog
index f28055f..bf4daaa 100644
--- a/wpa_supplicant/ChangeLog
+++ b/wpa_supplicant/ChangeLog
@@ -1,5 +1,75 @@
 ChangeLog for wpa_supplicant
 
+2018-12-02 - v2.7
+	* fixed WPA packet number reuse with replayed messages and key
+	  reinstallation
+	  [https://w1.fi/security/2017-1/] (CVE-2017-13077, CVE-2017-13078,
+	  CVE-2017-13079, CVE-2017-13080, CVE-2017-13081, CVE-2017-13082,
+	  CVE-2017-13086, CVE-2017-13087, CVE-2017-13088)
+	* fixed unauthenticated EAPOL-Key decryption in wpa_supplicant
+	  [https://w1.fi/security/2018-1/] (CVE-2018-14526)
+	* added support for FILS (IEEE 802.11ai) shared key authentication
+	* added support for OWE (Opportunistic Wireless Encryption, RFC 8110;
+	  and transition mode defined by WFA)
+	* added support for DPP (Wi-Fi Device Provisioning Protocol)
+	* added support for RSA 3k key case with Suite B 192-bit level
+	* fixed Suite B PMKSA caching not to update PMKID during each 4-way
+	  handshake
+	* fixed EAP-pwd pre-processing with PasswordHashHash
+	* added EAP-pwd client support for salted passwords
+	* fixed a regression in TDLS prohibited bit validation
+	* started to use estimated throughput to avoid undesired signal
+	  strength based roaming decision
+	* MACsec/MKA:
+	  - new macsec_linux driver interface support for the Linux
+	    kernel macsec module
+	  - number of fixes and extensions
+	* added support for external persistent storage of PMKSA cache
+	  (PMKSA_GET/PMKSA_ADD control interface commands; and
+	   MESH_PMKSA_GET/MESH_PMKSA_SET for the mesh case)
+	* fixed mesh channel configuration pri/sec switch case
+	* added support for beacon report
+	* large number of other fixes, cleanup, and extensions
+	* added support for randomizing local address for GAS queries
+	  (gas_rand_mac_addr parameter)
+	* fixed EAP-SIM/AKA/AKA' ext auth cases within TLS tunnel
+	* added option for using random WPS UUID (auto_uuid=1)
+	* added SHA256-hash support for OCSP certificate matching
+	* fixed EAP-AKA' to add AT_KDF into Synchronization-Failure
+	* fixed a regression in RSN pre-authentication candidate selection
+	* added option to configure allowed group management cipher suites
+	  (group_mgmt network profile parameter)
+	* removed all PeerKey functionality
+	* fixed nl80211 AP and mesh mode configuration regression with
+	  Linux 4.15 and newer
+	* added ap_isolate configuration option for AP mode
+	* added support for nl80211 to offload 4-way handshake into the driver
+	* added support for using wolfSSL cryptographic library
+	* SAE
+	  - added support for configuring SAE password separately of the
+	    WPA2 PSK/passphrase
+	  - fixed PTK and EAPOL-Key integrity and key-wrap algorithm selection
+	    for SAE;
+	    note: this is not backwards compatible, i.e., both the AP and
+	    station side implementations will need to be update at the same
+	    time to maintain interoperability
+	  - added support for Password Identifier
+	  - fixed FT-SAE PMKID matching
+	* Hotspot 2.0
+	  - added support for fetching of Operator Icon Metadata ANQP-element
+	  - added support for Roaming Consortium Selection element
+	  - added support for Terms and Conditions
+	  - added support for OSEN connection in a shared RSN BSS
+	  - added support for fetching Venue URL information
+	* added support for using OpenSSL 1.1.1
+	* FT
+	  - disabled PMKSA caching with FT since it is not fully functional
+	  - added support for SHA384 based AKM
+	  - added support for BIP ciphers BIP-CMAC-256, BIP-GMAC-128,
+	    BIP-GMAC-256 in addition to previously supported BIP-CMAC-128
+	  - fixed additional IE inclusion in Reassociation Request frame when
+	    using FT protocol
+
 2016-10-02 - v2.6
 	* fixed WNM Sleep Mode processing when PMF is not enabled
 	  [http://w1.fi/security/2015-6/] (CVE-2015-5310)
diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile
index c2e93e2..e55e062 100644
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -240,6 +240,12 @@
 NEED_SHA384=y
 endif
 
+ifdef CONFIG_OCV
+CFLAGS += -DCONFIG_OCV
+OBJS += ../src/common/ocv.o
+CONFIG_IEEE80211W=y
+endif
+
 ifdef CONFIG_IEEE80211W
 CFLAGS += -DCONFIG_IEEE80211W
 NEED_SHA256=y
@@ -1526,6 +1532,9 @@
 ifdef CONFIG_NO_RANDOM_POOL
 CFLAGS += -DCONFIG_NO_RANDOM_POOL
 else
+ifdef CONFIG_GETRANDOM
+CFLAGS += -DCONFIG_GETRANDOM
+endif
 OBJS += ../src/crypto/random.o
 endif
 
diff --git a/wpa_supplicant/README b/wpa_supplicant/README
index 730714b..bbc86b1 100644
--- a/wpa_supplicant/README
+++ b/wpa_supplicant/README
@@ -1,7 +1,7 @@
-WPA Supplicant
+wpa_supplicant
 ==============
 
-Copyright (c) 2003-2017, Jouni Malinen <j@w1.fi> and contributors
+Copyright (c) 2003-2019, Jouni Malinen <j@w1.fi> and contributors
 All Rights Reserved.
 
 This program is licensed under the BSD license (the one with
diff --git a/wpa_supplicant/README-DPP b/wpa_supplicant/README-DPP
new file mode 100644
index 0000000..6496733
--- /dev/null
+++ b/wpa_supplicant/README-DPP
@@ -0,0 +1,195 @@
+Device Provisioning Protocol (DPP)
+==================================
+
+This document describes how the Device Provisioning Protocol (DPP)
+implementation in wpa_supplicant and hostapd can be configured and how
+the STA device and AP can be configured to connect each other using DPP
+Connector mechanism.
+
+Introduction to DPP
+-------------------
+
+Device provisioning Protocol allows enrolling of interface-less devices
+in a secure Wi-Fi network using many methods like QR code based
+authentication( detailed below ), PKEX based authentication etc. In DPP
+a Configurator is used to provide network credentials to the devices.
+The three phases of DPP connection are authentication, configuration and
+network introduction.
+
+Build config setup
+------------------
+
+The following changes must go in the config file used to compile hostapd
+and wpa_supplicant.
+
+wpa_supplicant build config
+---------------------------
+
+Enable DPP and protected management frame in wpa_supplicant build config
+file
+
+CONFIG_IEEE80211W=y
+CONFIG_DPP=y
+
+hostapd build config
+--------------------
+
+Enable DPP and protected management frame in hostapd build config file
+
+CONFIG_IEEE80211W=y
+CONFIG_DPP=y
+
+Configurator build config
+-------------------------
+
+Any STA or AP device can act as a Configurator. Enable DPP and protected
+managment frames in build config. For an AP to act as Configurator,
+Interworking needs to be enabled. For wpa_supplicant it is not required.
+
+CONFIG_INTERWORKING=y
+
+
+Sample supplicant config file before provisioning
+-------------------------------------------------
+
+ctrl_interface=DIR=/var/run/wpa_supplicant
+ctrl_interface_group=0
+update_config=1
+pmf=2
+dpp_config_processing=2
+
+Sample hostapd config file before provisioning
+----------------------------------------------
+
+interface=wlan0
+driver=nl80211
+ctrl_interface=/var/run/hostapd
+ssid=test
+channel=1
+wpa=2
+wpa_key_mgmt=DPP
+ieee80211w=1
+wpa_pairwise=CCMP
+rsn_pairwise=CCMP
+
+
+Pre-requisites
+--------------
+
+It is assumed that an AP and client station are up by running hostapd
+and wpa_supplicant using respective config files.
+
+
+Creating Configurator
+---------------------
+
+Add a Configurator over the control interface (wpa_cli/hostapd_cli)
+
+> dpp_configurator_add
+(returns id)
+
+To get key of Configurator
+> dpp_configurator_get_key <id>
+
+
+How to configure an enrollee using Configurator
+-----------------------------------------------
+
+On enrollee side:
+
+Generate QR code for the device. Store the qr code id returned by the
+command.
+
+> dpp_bootstrap_gen type=qrcode mac=<mac-address-of-device> chan=<operating-channel> key=<key of the device>
+(returns bootstrapping info id)
+
+Get QR Code of device using the bootstrap info id.
+> dpp_bootstrap_get_uri <bootstrap-id>
+
+Make device listen to DPP request (The central frequency of channel 1 is
+2412) in case if enrollee is a client device.
+
+> dpp_listen <frequency>
+
+On Configurator side:
+
+Enter the QR Code in the Configurator.
+> dpp_qr_code "<QR-Code-read-from-enrollee>"
+
+On successfully adding QR Code, a bootstrapping info id is returned.
+
+Send provisioning request to enrollee. (conf is ap-dpp if enrollee is an
+AP. conf is sta-dpp if enrollee is a client)
+> dpp_auth_init peer=<qr-code-id> conf=<ap-dpp|sta-dpp> configurator=<configurator-id>
+
+The DPP values will be printed in the console. Save this values into the
+config file. If the enrollee is an AP, we need to manually write these
+values to the hostapd config file. If the enrollee is a client device,
+these details can be automatically saved to config file using the
+following command.
+
+> save_config
+
+To set values in runtime for AP enrollees
+
+> set dpp_connector <Connector-value-printed-on-console>
+> set dpp_csign <csign-value-on-console>
+> set dpp_netaccesskey <netaccess-value-on-console>
+
+To set values in runtime for client enrollees, set dpp_config_processing
+to 2 in wpa_supplicant conf file.
+
+Once the values are set in run-time (if not set in run-time, but saved
+in config files, they are taken up in next restart), the client device
+will automatically connect to the already provisioned AP and connection
+will be established.
+
+
+Self-configuring a device
+-------------------------
+
+It is possible for a device to configure itself if it is the
+Configurator for the network.
+
+Create a Configurator in the device and use the dpp_configurator_sign
+command to get DPP credentials.
+
+> dpp_configurator_add
+(returns configurator id)
+> dpp_configurator_sign conf=<ap-dpp|sta-dpp> configurator=<configurator-id>
+
+
+Sample AP configuration files after provisioning
+------------------------------------------------
+
+interface=wlan0
+driver=nl80211
+ctrl_interface=/var/run/hostapd
+ssid=test
+channel=1
+wpa=2
+wpa_key_mgmt=DPP
+ieee80211w=1
+wpa_pairwise=CCMP
+rsn_pairwise=CCMP
+dpp_connector=<Connector value provided by Configurator>
+dpp_csign=<C-Sign-Key value provided by Configurator>
+dpp_netaccesskey=<Net access key provided by Configurator>
+
+
+Sample station configuration file after provisioning
+----------------------------------------------------
+
+ctrl_interface=DIR=/var/run/wpa_supplicant
+ctrl_interface_group=0
+update_config=1
+pmf=2
+dpp_config_processing=2
+network={
+	ssid="test"
+	key_mgmt=DPP
+	ieee80211w=2
+	dpp_connector="<Connector value provided by Configurator>"
+	dpp_netaccesskey=<Net access key provided by Configurator>
+	dpp_csign=<C-sign-key value provided by Configurator>
+}
diff --git a/wpa_supplicant/README-P2P b/wpa_supplicant/README-P2P
index 23ac7fa..55a60a2 100644
--- a/wpa_supplicant/README-P2P
+++ b/wpa_supplicant/README-P2P
@@ -150,7 +150,7 @@
 
 p2p_connect <peer device address> <pbc|pin|PIN#|p2ps> [display|keypad|p2ps]
 	[persistent|persistent=<network id>] [join|auth]
-	[go_intent=<0..15>] [freq=<in MHz>] [ht40] [vht] [provdisc] [auto]
+	[go_intent=<0..15>] [freq=<in MHz>] [ht40] [vht] [he] [provdisc] [auto]
 	[ssid=<hexdump>]
 
 Start P2P group formation with a discovered P2P peer. This includes
@@ -262,7 +262,7 @@
     session_mac - Mandatory MAC address that owns/initiated the session
 
 p2p_group_add [persistent|persistent=<network id>] [freq=<freq in MHz>]
-	[ht40] [vht]
+	[ht40] [vht] [he]
 
 Set up a P2P group owner manually (i.e., without group owner
 negotiation with a specific peer). This is also known as autonomous
@@ -558,7 +558,7 @@
 Invitation
 
 p2p_invite [persistent=<network id>|group=<group ifname>] [peer=address]
-	[go_dev_addr=address] [freq=<freq in MHz>] [ht40] [vht]
+	[go_dev_addr=address] [freq=<freq in MHz>] [ht40] [vht] [he]
 	[pref=<MHz>]
 
 Invite a peer to join a group (e.g., group=wlan1) or to reinvoke a
diff --git a/wpa_supplicant/android.config b/wpa_supplicant/android.config
index d4146db..feff916 100644
--- a/wpa_supplicant/android.config
+++ b/wpa_supplicant/android.config
@@ -277,6 +277,9 @@
 # Driver support is also needed for IEEE 802.11w.
 CONFIG_IEEE80211W=y
 
+# Support Operating Channel Validation
+#CONFIG_OCV=y
+
 # Select TLS implementation
 # openssl = OpenSSL (default)
 # gnutls = GnuTLS
@@ -514,8 +517,6 @@
 #CONFIG_MBO=y
 
 # Fast Initial Link Setup (FILS) (IEEE 802.11ai)
-# Note: This is an experimental and not yet complete implementation. This
-# should not be enabled for production use.
 #CONFIG_FILS=y
 
 # Support RSN on IBSS networks
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index ea846a0..453c99d 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -334,6 +334,9 @@
 			list[8] = -1;
 		}
 		conf->supported_rates = list;
+#ifdef CONFIG_IEEE80211AX
+		conf->ieee80211ax = ssid->he;
+#endif /* CONFIG_IEEE80211AX */
 	}
 
 	bss->isolate = !wpa_s->conf->p2p_intra_bss;
@@ -494,6 +497,10 @@
 		bss->ieee80211w = ssid->ieee80211w;
 #endif /* CONFIG_IEEE80211W */
 
+#ifdef CONFIG_OCV
+	bss->ocv = ssid->ocv;
+#endif /* CONFIG_OCV */
+
 #ifdef CONFIG_WPS
 	/*
 	 * Enable WPS by default for open and WPA/WPA2-Personal network, but
@@ -1379,13 +1386,16 @@
 void wpas_ap_ch_switch(struct wpa_supplicant *wpa_s, int freq, int ht,
 		       int offset, int width, int cf1, int cf2)
 {
-	if (!wpa_s->ap_iface)
-		return;
+	struct hostapd_iface *iface = wpa_s->ap_iface;
 
+	if (!iface)
+		iface = wpa_s->ifmsh;
+	if (!iface)
+		return;
 	wpa_s->assoc_freq = freq;
 	if (wpa_s->current_ssid)
 		wpa_s->current_ssid->frequency = freq;
-	hostapd_event_ch_switch(wpa_s->ap_iface->bss[0], freq, ht,
+	hostapd_event_ch_switch(iface->bss[0], freq, ht,
 				offset, width, cf1, cf2);
 }
 
@@ -1582,10 +1592,14 @@
 void wpas_ap_event_dfs_radar_detected(struct wpa_supplicant *wpa_s,
 				      struct dfs_event *radar)
 {
-	if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0])
+	struct hostapd_iface *iface = wpa_s->ap_iface;
+
+	if (!iface)
+		iface = wpa_s->ifmsh;
+	if (!iface || !iface->bss[0])
 		return;
 	wpa_printf(MSG_DEBUG, "DFS radar detected on %d MHz", radar->freq);
-	hostapd_dfs_radar_detected(wpa_s->ap_iface, radar->freq,
+	hostapd_dfs_radar_detected(iface, radar->freq,
 				   radar->ht_enabled, radar->chan_offset,
 				   radar->chan_width,
 				   radar->cf1, radar->cf2);
@@ -1595,10 +1609,14 @@
 void wpas_ap_event_dfs_cac_started(struct wpa_supplicant *wpa_s,
 				   struct dfs_event *radar)
 {
-	if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0])
+	struct hostapd_iface *iface = wpa_s->ap_iface;
+
+	if (!iface)
+		iface = wpa_s->ifmsh;
+	if (!iface || !iface->bss[0])
 		return;
 	wpa_printf(MSG_DEBUG, "DFS CAC started on %d MHz", radar->freq);
-	hostapd_dfs_start_cac(wpa_s->ap_iface, radar->freq,
+	hostapd_dfs_start_cac(iface, radar->freq,
 			      radar->ht_enabled, radar->chan_offset,
 			      radar->chan_width, radar->cf1, radar->cf2);
 }
@@ -1607,10 +1625,14 @@
 void wpas_ap_event_dfs_cac_finished(struct wpa_supplicant *wpa_s,
 				    struct dfs_event *radar)
 {
-	if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0])
+	struct hostapd_iface *iface = wpa_s->ap_iface;
+
+	if (!iface)
+		iface = wpa_s->ifmsh;
+	if (!iface || !iface->bss[0])
 		return;
 	wpa_printf(MSG_DEBUG, "DFS CAC finished on %d MHz", radar->freq);
-	hostapd_dfs_complete_cac(wpa_s->ap_iface, 1, radar->freq,
+	hostapd_dfs_complete_cac(iface, 1, radar->freq,
 				 radar->ht_enabled, radar->chan_offset,
 				 radar->chan_width, radar->cf1, radar->cf2);
 }
@@ -1619,10 +1641,14 @@
 void wpas_ap_event_dfs_cac_aborted(struct wpa_supplicant *wpa_s,
 				   struct dfs_event *radar)
 {
-	if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0])
+	struct hostapd_iface *iface = wpa_s->ap_iface;
+
+	if (!iface)
+		iface = wpa_s->ifmsh;
+	if (!iface || !iface->bss[0])
 		return;
 	wpa_printf(MSG_DEBUG, "DFS CAC aborted on %d MHz", radar->freq);
-	hostapd_dfs_complete_cac(wpa_s->ap_iface, 0, radar->freq,
+	hostapd_dfs_complete_cac(iface, 0, radar->freq,
 				 radar->ht_enabled, radar->chan_offset,
 				 radar->chan_width, radar->cf1, radar->cf2);
 }
@@ -1631,10 +1657,14 @@
 void wpas_ap_event_dfs_cac_nop_finished(struct wpa_supplicant *wpa_s,
 					struct dfs_event *radar)
 {
-	if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0])
+	struct hostapd_iface *iface = wpa_s->ap_iface;
+
+	if (!iface)
+		iface = wpa_s->ifmsh;
+	if (!iface || !iface->bss[0])
 		return;
 	wpa_printf(MSG_DEBUG, "DFS NOP finished on %d MHz", radar->freq);
-	hostapd_dfs_nop_finished(wpa_s->ap_iface, radar->freq,
+	hostapd_dfs_nop_finished(iface, radar->freq,
 				 radar->ht_enabled, radar->chan_offset,
 				 radar->chan_width, radar->cf1, radar->cf2);
 }
diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c
index 3a41db9..9b19f37 100644
--- a/wpa_supplicant/bss.c
+++ b/wpa_supplicant/bss.c
@@ -1,6 +1,6 @@
 /*
  * BSS table
- * Copyright (c) 2009-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2009-2019, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -1337,3 +1337,10 @@
 	return NULL;
 }
 #endif /* CONFIG_FILS */
+
+
+int wpa_bss_ext_capab(const struct wpa_bss *bss, unsigned int capab)
+{
+	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 5251b2c..3ce8cd3 100644
--- a/wpa_supplicant/bss.h
+++ b/wpa_supplicant/bss.h
@@ -1,6 +1,6 @@
 /*
  * BSS table
- * Copyright (c) 2009-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2009-2019, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -148,6 +148,7 @@
 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);
+int wpa_bss_ext_capab(const struct wpa_bss *bss, unsigned int capab);
 
 static inline int bss_is_dmg(const struct wpa_bss *bss)
 {
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index 5cdc059..2902413 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -1043,6 +1043,30 @@
 #endif /* CONFIG_IEEE80211R */
 #endif /* CONFIG_FILS */
 
+#ifdef CONFIG_DPP
+	if (ssid->key_mgmt & WPA_KEY_MGMT_DPP) {
+		ret = os_snprintf(pos, end - pos, "%sDPP",
+				  pos == buf ? "" : " ");
+		if (os_snprintf_error(end - pos, ret)) {
+			end[-1] = '\0';
+			return buf;
+		}
+		pos += ret;
+	}
+#endif /* CONFIG_DPP */
+
+#ifdef CONFIG_OWE
+	if (ssid->key_mgmt & WPA_KEY_MGMT_OWE) {
+		ret = os_snprintf(pos, end - pos, "%sOWE",
+				  pos == buf ? "" : " ");
+		if (os_snprintf_error(end - pos, ret)) {
+			end[-1] = '\0';
+			return buf;
+		}
+		pos += ret;
+	}
+#endif /* CONFIG_OWE */
+
 	if (pos == buf) {
 		os_free(buf);
 		buf = NULL;
@@ -1978,16 +2002,21 @@
 				    struct wpa_ssid *ssid, int line,
 				    const char *value)
 {
-	if (hexstr2bin(value, ssid->mka_cak, MACSEC_CAK_LEN) ||
-	    value[MACSEC_CAK_LEN * 2] != '\0') {
+	size_t len;
+
+	len = os_strlen(value);
+	if (len > 2 * MACSEC_CAK_MAX_LEN ||
+	    (len != 2 * 16 && len != 2 * 32) ||
+	    hexstr2bin(value, ssid->mka_cak, len / 2)) {
 		wpa_printf(MSG_ERROR, "Line %d: Invalid MKA-CAK '%s'.",
 			   line, value);
 		return -1;
 	}
-
+	ssid->mka_cak_len = len / 2;
 	ssid->mka_psk_set |= MKA_PSK_SET_CAK;
 
-	wpa_hexdump_key(MSG_MSGDUMP, "MKA-CAK", ssid->mka_cak, MACSEC_CAK_LEN);
+	wpa_hexdump_key(MSG_MSGDUMP, "MKA-CAK", ssid->mka_cak,
+			ssid->mka_cak_len);
 	return 0;
 }
 
@@ -1996,8 +2025,18 @@
 				    struct wpa_ssid *ssid, int line,
 				    const char *value)
 {
-	if (hexstr2bin(value, ssid->mka_ckn, MACSEC_CKN_LEN) ||
-	    value[MACSEC_CKN_LEN * 2] != '\0') {
+	size_t len;
+
+	len = os_strlen(value);
+	if (len > 2 * MACSEC_CKN_MAX_LEN || /* too long */
+	    len < 2 || /* too short */
+	    len % 2 != 0 /* not an integral number of bytes */) {
+		wpa_printf(MSG_ERROR, "Line %d: Invalid MKA-CKN '%s'.",
+			   line, value);
+		return -1;
+	}
+	ssid->mka_ckn_len = len / 2;
+	if (hexstr2bin(value, ssid->mka_ckn, ssid->mka_ckn_len)) {
 		wpa_printf(MSG_ERROR, "Line %d: Invalid MKA-CKN '%s'.",
 			   line, value);
 		return -1;
@@ -2005,7 +2044,8 @@
 
 	ssid->mka_psk_set |= MKA_PSK_SET_CKN;
 
-	wpa_hexdump_key(MSG_MSGDUMP, "MKA-CKN", ssid->mka_ckn, MACSEC_CKN_LEN);
+	wpa_hexdump_key(MSG_MSGDUMP, "MKA-CKN", ssid->mka_ckn,
+			ssid->mka_ckn_len);
 	return 0;
 }
 
@@ -2018,7 +2058,7 @@
 	if (!(ssid->mka_psk_set & MKA_PSK_SET_CAK))
 		return NULL;
 
-	return wpa_config_write_string_hex(ssid->mka_cak, MACSEC_CAK_LEN);
+	return wpa_config_write_string_hex(ssid->mka_cak, ssid->mka_cak_len);
 }
 
 
@@ -2027,7 +2067,7 @@
 {
 	if (!(ssid->mka_psk_set & MKA_PSK_SET_CKN))
 		return NULL;
-	return wpa_config_write_string_hex(ssid->mka_ckn, MACSEC_CKN_LEN);
+	return wpa_config_write_string_hex(ssid->mka_ckn, ssid->mka_ckn_len);
 }
 
 #endif /* NO_CONFIG_WRITE */
@@ -2035,6 +2075,43 @@
 #endif /* CONFIG_MACSEC */
 
 
+#ifdef CONFIG_OCV
+
+static int wpa_config_parse_ocv(const struct parse_data *data,
+				struct wpa_ssid *ssid, int line,
+				const char *value)
+{
+	char *end;
+
+	ssid->ocv = strtol(value, &end, 0);
+	if (*end || ssid->ocv < 0 || ssid->ocv > 1) {
+		wpa_printf(MSG_ERROR, "Line %d: Invalid ocv value '%s'.",
+			   line, value);
+		return -1;
+	}
+	if (ssid->ocv && ssid->ieee80211w == NO_MGMT_FRAME_PROTECTION)
+		ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
+	return 0;
+}
+
+
+#ifndef NO_CONFIG_WRITE
+static char * wpa_config_write_ocv(const struct parse_data *data,
+				   struct wpa_ssid *ssid)
+{
+	char *value = os_malloc(20);
+
+	if (!value)
+		return NULL;
+	os_snprintf(value, 20, "%d", ssid->ocv);
+	value[20 - 1] = '\0';
+	return value;
+}
+#endif /* NO_CONFIG_WRITE */
+
+#endif /* CONFIG_OCV */
+
+
 static int wpa_config_parse_peerkey(const struct parse_data *data,
 				    struct wpa_ssid *ssid, int line,
 				    const char *value)
@@ -2238,6 +2315,9 @@
 #ifdef CONFIG_IEEE80211W
 	{ INT_RANGE(ieee80211w, 0, 2) },
 #endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_OCV
+	{ FUNC(ocv) },
+#endif /* CONFIG_OCV */
 	{ FUNC(peerkey) /* obsolete - removed */ },
 	{ INT_RANGE(mixed_cell, 0, 1) },
 	{ INT_RANGE(frequency, 0, 65000) },
@@ -2267,6 +2347,8 @@
 	{ INT_RANGE(disable_sgi, 0, 1) },
 	{ INT_RANGE(disable_ldpc, 0, 1) },
 	{ INT_RANGE(ht40_intolerant, 0, 1) },
+	{ INT_RANGE(tx_stbc, -1, 1) },
+	{ INT_RANGE(rx_stbc, -1, 3) },
 	{ INT_RANGE(disable_max_amsdu, -1, 1) },
 	{ INT_RANGE(ampdu_factor, -1, 3) },
 	{ INT_RANGE(ampdu_density, -1, 7) },
@@ -2299,6 +2381,8 @@
 #ifdef CONFIG_MACSEC
 	{ INT_RANGE(macsec_policy, 0, 1) },
 	{ INT_RANGE(macsec_integ_only, 0, 1) },
+	{ INT_RANGE(macsec_replay_protect, 0, 1) },
+	{ INT(macsec_replay_window) },
 	{ INT_RANGE(macsec_port, 1, 65534) },
 	{ INT_RANGE(mka_priority, 0, 255) },
 	{ FUNC_KEY(mka_cak) },
@@ -2320,6 +2404,7 @@
 #endif /* CONFIG_DPP */
 	{ INT_RANGE(owe_group, 0, 65535) },
 	{ INT_RANGE(owe_only, 0, 1) },
+	{ INT_RANGE(multi_ap_backhaul_sta, 0, 1) },
 };
 
 #undef OFFSET
@@ -2786,6 +2871,8 @@
 	ssid->disable_ht40 = DEFAULT_DISABLE_HT40;
 	ssid->disable_sgi = DEFAULT_DISABLE_SGI;
 	ssid->disable_ldpc = DEFAULT_DISABLE_LDPC;
+	ssid->tx_stbc = DEFAULT_TX_STBC;
+	ssid->rx_stbc = DEFAULT_RX_STBC;
 	ssid->disable_max_amsdu = DEFAULT_DISABLE_MAX_AMSDU;
 	ssid->ampdu_factor = DEFAULT_AMPDU_FACTOR;
 	ssid->ampdu_density = DEFAULT_AMPDU_DENSITY;
@@ -2816,6 +2903,7 @@
 	ssid->mka_priority = DEFAULT_PRIO_NOT_KEY_SERVER;
 #endif /* CONFIG_MACSEC */
 	ssid->mac_addr = -1;
+	ssid->max_oper_chwidth = DEFAULT_MAX_OPER_CHWIDTH;
 }
 
 
@@ -4686,6 +4774,7 @@
 	{ INT_RANGE(p2p_optimize_listen_chan, 0, 1), 0 },
 	{ INT(p2p_go_ht40), 0 },
 	{ INT(p2p_go_vht), 0 },
+	{ INT(p2p_go_he), 0 },
 	{ INT(p2p_disabled), 0 },
 	{ INT_RANGE(p2p_go_ctwindow, 0, 127), 0 },
 	{ INT(p2p_no_group_iface), 0 },
@@ -4772,9 +4861,7 @@
 	{ INT(gas_rand_addr_lifetime), 0 },
 	{ INT_RANGE(gas_rand_mac_addr, 0, 2), 0 },
 	{ INT_RANGE(dpp_config_processing, 0, 2), 0 },
-	{ INT_RANGE(bss_no_flush_when_down, 0, 1), 0 },
 	{ INT_RANGE(coloc_intf_reporting, 0, 1), 0 },
-	{ INT_RANGE(bss_no_flush_when_down, 0, 1), 0 },
 };
 
 #undef FUNC
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index 6eb0074..4b84200 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -1079,6 +1079,16 @@
 	int p2p_go_vht;
 
 	/**
+	 * p2p_go_he - Default mode for 11ax HE enable when operating as GO
+	 *
+	 * This will take effect for p2p_group_add, p2p_connect, and p2p_invite.
+	 * Note that regulatory constraints and driver capabilities are
+	 * consulted anyway, so setting it to 1 can't do real harm.
+	 * By default: 0 (disabled)
+	 */
+	int p2p_go_he;
+
+	/**
 	 * p2p_go_ctwindow - CTWindow to use when operating as GO
 	 *
 	 * By default: 0 (no CTWindow). Values 0-127 can be used to indicate
@@ -1483,7 +1493,8 @@
 	 * p2p_device_random_mac_addr - P2P Device MAC address policy default
 	 *
 	 * 0 = use permanent MAC address
-	 * 1 = use random MAC address on creating the interface if there is no persistent groups.
+	 * 1 = use random MAC address on creating the interface if there is no
+	 * persistent groups.
 	 *
 	 * By default, permanent MAC address is used.
 	 */
@@ -1492,9 +1503,8 @@
 	/**
 	 * p2p_device_persistent_mac_addr - Record last used MAC address
 	 *
-	 * If there are saved persistent groups, P2P cannot generate another random MAC address,
-	 * and need to restore to last used MAC address.
-	 * format: aa:bb:cc:dd:ee:ff
+	 * If there are saved persistent groups, P2P cannot generate another
+	 * random MAC address, and need to restore to last used MAC address.
 	 */
 	u8 p2p_device_persistent_mac_addr[ETH_ALEN];
 
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index becc809..f1d865c 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -160,6 +160,15 @@
 		errors++;
 	}
 
+#ifdef CONFIG_OCV
+	if (ssid->ocv && ssid->ieee80211w == NO_MGMT_FRAME_PROTECTION) {
+		wpa_printf(MSG_ERROR,
+			   "Line %d: PMF needs to be enabled whenever using OCV",
+			   line);
+		errors++;
+	}
+#endif /* CONFIG_OCV */
+
 	return errors;
 }
 
@@ -484,7 +493,7 @@
 	if (value == NULL)
 		return;
 	fprintf(f, "\t%s=%s\n", field, value);
-	os_free(value);
+	str_clear_free(value);
 }
 
 
@@ -829,7 +838,7 @@
 	INT(vht);
 	INT_DEF(ht, 1);
 	INT(ht40);
-	INT(max_oper_chwidth);
+	INT_DEF(max_oper_chwidth, DEFAULT_MAX_OPER_CHWIDTH);
 	INT(vht_center_freq1);
 	INT(vht_center_freq2);
 	INT(pbss);
@@ -853,6 +862,8 @@
 	write_mka_cak(f, ssid);
 	write_mka_ckn(f, ssid);
 	INT(macsec_integ_only);
+	INT(macsec_replay_protect);
+	INT(macsec_replay_window);
 	INT(macsec_port);
 	INT_DEF(mka_priority, DEFAULT_PRIO_NOT_KEY_SERVER);
 #endif /* CONFIG_MACSEC */
@@ -880,12 +891,15 @@
 #endif /* CONFIG_DPP */
 	INT(owe_group);
 	INT(owe_only);
+	INT(multi_ap_backhaul_sta);
 #ifdef CONFIG_HT_OVERRIDES
 	INT_DEF(disable_ht, DEFAULT_DISABLE_HT);
 	INT_DEF(disable_ht40, DEFAULT_DISABLE_HT40);
 	INT_DEF(disable_sgi, DEFAULT_DISABLE_SGI);
 	INT_DEF(disable_ldpc, DEFAULT_DISABLE_LDPC);
 	INT(ht40_intolerant);
+	INT_DEF(tx_stbc, DEFAULT_TX_STBC);
+	INT_DEF(rx_stbc, DEFAULT_RX_STBC);
 	INT_DEF(disable_max_amsdu, DEFAULT_DISABLE_MAX_AMSDU);
 	INT_DEF(ampdu_factor, DEFAULT_AMPDU_FACTOR);
 	INT_DEF(ampdu_density, DEFAULT_AMPDU_DENSITY);
@@ -1248,6 +1262,8 @@
 		fprintf(f, "p2p_go_ht40=%d\n", config->p2p_go_ht40);
 	if (config->p2p_go_vht)
 		fprintf(f, "p2p_go_vht=%d\n", config->p2p_go_vht);
+	if (config->p2p_go_he)
+		fprintf(f, "p2p_go_he=%d\n", config->p2p_go_he);
 	if (config->p2p_go_ctwindow != DEFAULT_P2P_GO_CTWINDOW)
 		fprintf(f, "p2p_go_ctwindow=%d\n", config->p2p_go_ctwindow);
 	if (config->p2p_disabled)
@@ -1523,9 +1539,6 @@
 	if (config->p2p_interface_random_mac_addr)
 		fprintf(f, "p2p_interface_random_mac_addr=%d\n",
 			config->p2p_interface_random_mac_addr);
-	if (config->bss_no_flush_when_down)
-		fprintf(f, "bss_no_flush_when_down=%d\n",
-			config->bss_no_flush_when_down);
 }
 
 #endif /* CONFIG_NO_CONFIG_WRITE */
diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h
index d2a52d7..1b2b1f1 100644
--- a/wpa_supplicant/config_ssid.h
+++ b/wpa_supplicant/config_ssid.h
@@ -33,10 +33,13 @@
 #define DEFAULT_DISABLE_HT40 0
 #define DEFAULT_DISABLE_SGI 0
 #define DEFAULT_DISABLE_LDPC 0
+#define DEFAULT_TX_STBC -1 /* no change */
+#define DEFAULT_RX_STBC -1 /* no change */
 #define DEFAULT_DISABLE_MAX_AMSDU -1 /* no change */
 #define DEFAULT_AMPDU_FACTOR -1 /* no change */
 #define DEFAULT_AMPDU_DENSITY -1 /* no change */
 #define DEFAULT_USER_SELECTED_SIM 1
+#define DEFAULT_MAX_OPER_CHWIDTH -1
 
 struct psk_list_entry {
 	struct dl_list list;
@@ -457,6 +460,17 @@
 	enum mfp_options ieee80211w;
 #endif /* CONFIG_IEEE80211W */
 
+#ifdef CONFIG_OCV
+	/**
+	 * ocv - Enable/disable operating channel validation
+	 *
+	 * If this parameter is set to 1, stations will exchange OCI element
+	 * to cryptographically verify the operating channel. Setting this
+	 * parameter to 0 disables this option. Default value: 0.
+	 */
+	int ocv;
+#endif /* CONFIG_OCV */
+
 	/**
 	 * frequency - Channel frequency in megahertz (MHz) for IBSS
 	 *
@@ -505,6 +519,8 @@
 
 	int vht;
 
+	int he;
+
 	int max_oper_chwidth;
 
 	unsigned int vht_center_freq1;
@@ -682,6 +698,22 @@
 	 * By default (empty string): Use whatever the OS has configured.
 	 */
 	char *ht_mcs;
+
+	/**
+	 * tx_stbc - Indicate STBC support for TX streams
+	 *
+	 * Value: -1..1, by default (-1): use whatever the OS or card has
+	 * configured. See IEEE Std 802.11-2016, 9.4.2.56.2.
+	 */
+	int tx_stbc;
+
+	/**
+	 * rx_stbc - Indicate STBC support for RX streams
+	 *
+	 * Value: -1..3, by default (-1): use whatever the OS or card has
+	 * configured. See IEEE Std 802.11-2016, 9.4.2.56.2.
+	 */
+	int rx_stbc;
 #endif /* CONFIG_HT_OVERRIDES */
 
 #ifdef CONFIG_VHT_OVERRIDES
@@ -774,6 +806,33 @@
 	int macsec_integ_only;
 
 	/**
+	 * macsec_replay_protect - Enable MACsec replay protection
+	 *
+	 * This setting applies only when MACsec is in use, i.e.,
+	 *  - macsec_policy is enabled
+	 *  - the key server has decided to enable MACsec
+	 *
+	 * 0: Replay protection disabled (default)
+	 * 1: Replay protection enabled
+	 */
+	int macsec_replay_protect;
+
+	/**
+	 * macsec_replay_window - MACsec replay protection window
+	 *
+	 * A window in which replay is tolerated, to allow receipt of frames
+	 * that have been misordered by the network.
+	 *
+	 * This setting applies only when MACsec replay protection active, i.e.,
+	 *  - macsec_replay_protect is enabled
+	 *  - the key server has decided to enable MACsec
+	 *
+	 * 0: No replay window, strict check (default)
+	 * 1..2^32-1: number of packets that could be misordered
+	 */
+	u32 macsec_replay_window;
+
+	/**
 	 * macsec_port - MACsec port (in SCI)
 	 *
 	 * Port component of the SCI.
@@ -792,14 +851,16 @@
 	/**
 	 * mka_ckn - MKA pre-shared CKN
 	 */
-#define MACSEC_CKN_LEN 32
-	u8 mka_ckn[MACSEC_CKN_LEN];
+#define MACSEC_CKN_MAX_LEN 32
+	size_t mka_ckn_len;
+	u8 mka_ckn[MACSEC_CKN_MAX_LEN];
 
 	/**
 	 * mka_cak - MKA pre-shared CAK
 	 */
-#define MACSEC_CAK_LEN 16
-	u8 mka_cak[MACSEC_CAK_LEN];
+#define MACSEC_CAK_MAX_LEN 32
+	size_t mka_cak_len;
+	u8 mka_cak[MACSEC_CAK_MAX_LEN];
 
 #define MKA_PSK_SET_CKN BIT(0)
 #define MKA_PSK_SET_CAK BIT(1)
@@ -937,6 +998,13 @@
 	 * the selection attempts for OWE BSS exceed the configured threshold.
 	 */
 	int owe_transition_bss_select_count;
+
+	/**
+	 * multi_ap_backhaul_sta - Multi-AP backhaul STA
+	 * 0 = normal (non-Multi-AP) station
+	 * 1 = Multi-AP backhaul station
+	 */
+	int multi_ap_backhaul_sta;
 };
 
 #endif /* CONFIG_SSID_H */
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 77a3133..a0db9e4 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / Control interface (shared code for all backends)
- * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -56,6 +56,7 @@
 #include "drivers/driver.h"
 #include "mesh.h"
 #include "dpp_supplicant.h"
+#include "sme.h"
 
 static int wpa_supplicant_global_iface_list(struct wpa_global *global,
 					    char *buf, int len);
@@ -2912,6 +2913,12 @@
 		pos += ret;
 	}
 #endif /* CONFIG_FST */
+	if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_UTF_8_SSID)) {
+		ret = os_snprintf(pos, end - pos, "[UTF-8]");
+		if (os_snprintf_error(end - pos, ret))
+			return -1;
+		pos += ret;
+	}
 
 	ret = os_snprintf(pos, end - pos, "\t%s",
 			  wpa_ssid_txt(bss->ssid, bss->ssid_len));
@@ -3987,6 +3994,22 @@
 	}
 #endif /* CONFIG_IEEE80211R */
 #endif /* CONFIG_FILS */
+#ifdef CONFIG_IEEE80211R
+	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) {
+		ret = os_snprintf(pos, end - pos, " FT-PSK");
+		if (os_snprintf_error(end - pos, ret))
+			return pos - buf;
+		pos += ret;
+	}
+#endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_SAE
+	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE) {
+		ret = os_snprintf(pos, end - pos, " SAE");
+		if (os_snprintf_error(end - pos, ret))
+			return pos - buf;
+		pos += ret;
+	}
+#endif /* CONFIG_SAE */
 
 	return pos - buf;
 }
@@ -4387,6 +4410,13 @@
 	}
 #endif /* CONFIG_FILS */
 
+	if (os_strcmp(field, "multibss") == 0 && wpa_s->multi_bss_support) {
+		res = os_snprintf(buf, buflen, "MULTIBSS-STA");
+		if (os_snprintf_error(buflen, res))
+			return -1;
+		return res;
+	}
+
 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
 		   field);
 
@@ -4717,6 +4747,20 @@
 			pos += ret;
 		}
 #endif /* CONFIG_FILS */
+#ifdef CONFIG_FST
+		if (wpa_bss_get_ie(bss, WLAN_EID_MULTI_BAND)) {
+			ret = os_snprintf(pos, end - pos, "[FST]");
+			if (os_snprintf_error(end - pos, ret))
+				return 0;
+			pos += ret;
+		}
+#endif /* CONFIG_FST */
+		if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_UTF_8_SSID)) {
+			ret = os_snprintf(pos, end - pos, "[UTF-8]");
+			if (os_snprintf_error(end - pos, ret))
+				return 0;
+			pos += ret;
+		}
 
 		ret = os_snprintf(pos, end - pos, "\n");
 		if (os_snprintf_error(end - pos, ret))
@@ -5502,6 +5546,7 @@
 	int ht40, vht, max_oper_chwidth, chwidth = 0, freq2 = 0;
 	u8 _group_ssid[SSID_MAX_LEN], *group_ssid = NULL;
 	size_t group_ssid_len = 0;
+	int he;
 
 	if (!wpa_s->global->p2p_init_wpa_s)
 		return -1;
@@ -5514,7 +5559,7 @@
 	/* <addr> <"pbc" | "pin" | PIN> [label|display|keypad|p2ps]
 	 * [persistent|persistent=<network id>]
 	 * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc]
-	 * [ht40] [vht] [auto] [ssid=<hexdump>] */
+	 * [ht40] [vht] [he] [auto] [ssid=<hexdump>] */
 
 	if (hwaddr_aton(cmd, addr))
 		return -1;
@@ -5545,6 +5590,7 @@
 	vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
 	ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
 		vht;
+	he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he;
 
 	pos2 = os_strstr(pos, " go_intent=");
 	if (pos2) {
@@ -5615,7 +5661,7 @@
 	new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
 				   persistent_group, automatic, join,
 				   auth, go_intent, freq, freq2, persistent_id,
-				   pd, ht40, vht, max_oper_chwidth,
+				   pd, ht40, vht, max_oper_chwidth, he,
 				   group_ssid, group_ssid_len);
 	if (new_pin == -2) {
 		os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
@@ -6171,7 +6217,7 @@
 	struct wpa_ssid *ssid;
 	u8 *_peer = NULL, peer[ETH_ALEN];
 	int freq = 0, pref_freq = 0;
-	int ht40, vht, max_oper_chwidth, chwidth = 0, freq2 = 0;
+	int ht40, vht, he, max_oper_chwidth, chwidth = 0, freq2 = 0;
 
 	id = atoi(cmd);
 	pos = os_strstr(cmd, " peer=");
@@ -6208,6 +6254,7 @@
 	vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
 	ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
 		vht;
+	he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he;
 
 	pos = os_strstr(cmd, "freq2=");
 	if (pos)
@@ -6222,7 +6269,7 @@
 		return -1;
 
 	return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, freq2, ht40, vht,
-			       max_oper_chwidth, pref_freq);
+			       max_oper_chwidth, pref_freq, he);
 }
 
 
@@ -6270,7 +6317,8 @@
 
 static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
 					 int id, int freq, int vht_center_freq2,
-					 int ht40, int vht, int vht_chwidth)
+					 int ht40, int vht, int vht_chwidth,
+					 int he)
 {
 	struct wpa_ssid *ssid;
 
@@ -6284,7 +6332,7 @@
 
 	return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq,
 					     vht_center_freq2, 0, ht40, vht,
-					     vht_chwidth, NULL, 0, 0);
+					     vht_chwidth, he, NULL, 0, 0);
 }
 
 
@@ -6293,6 +6341,7 @@
 	int freq = 0, persistent = 0, group_id = -1;
 	int vht = wpa_s->conf->p2p_go_vht;
 	int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
+	int he = wpa_s->conf->p2p_go_he;
 	int max_oper_chwidth, chwidth = 0, freq2 = 0;
 	char *token, *context = NULL;
 #ifdef CONFIG_ACS
@@ -6315,6 +6364,8 @@
 		} else if (os_strcmp(token, "vht") == 0) {
 			vht = 1;
 			ht40 = 1;
+		} else if (os_strcmp(token, "he") == 0) {
+			he = 1;
 		} else if (os_strcmp(token, "persistent") == 0) {
 			persistent = 1;
 		} else {
@@ -6350,10 +6401,10 @@
 	if (group_id >= 0)
 		return p2p_ctrl_group_add_persistent(wpa_s, group_id,
 						     freq, freq2, ht40, vht,
-						     max_oper_chwidth);
+						     max_oper_chwidth, he);
 
 	return wpas_p2p_group_add(wpa_s, persistent, freq, freq2, ht40, vht,
-				  max_oper_chwidth);
+				  max_oper_chwidth, he);
 }
 
 
@@ -7941,6 +7992,10 @@
 
 	wpabuf_free(wpa_s->ric_ies);
 	wpa_s->ric_ies = NULL;
+
+	wpa_supplicant_update_channel_list(wpa_s, NULL);
+
+	free_bss_tmp_disallowed(wpa_s);
 }
 
 
@@ -8763,26 +8818,39 @@
 	struct iphdr ip;
 	const u8 *pos;
 	unsigned int i;
+	char extra[30];
 
-	if (len != HWSIM_PACKETLEN)
+	if (len < sizeof(*eth) + sizeof(ip) || len > HWSIM_PACKETLEN) {
+		wpa_printf(MSG_DEBUG,
+			   "test data: RX - ignore unexpected length %d",
+			   (int) len);
 		return;
+	}
 
 	eth = (const struct ether_header *) buf;
 	os_memcpy(&ip, eth + 1, sizeof(ip));
 	pos = &buf[sizeof(*eth) + sizeof(ip)];
 
 	if (ip.ihl != 5 || ip.version != 4 ||
-	    ntohs(ip.tot_len) != HWSIM_IP_LEN)
+	    ntohs(ip.tot_len) > HWSIM_IP_LEN) {
+		wpa_printf(MSG_DEBUG,
+			   "test data: RX - ignore unexpect IP header");
 		return;
-
-	for (i = 0; i < HWSIM_IP_LEN - sizeof(ip); i++) {
-		if (*pos != (u8) i)
-			return;
-		pos++;
 	}
 
-	wpa_msg(wpa_s, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR,
-		MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost));
+	for (i = 0; i < ntohs(ip.tot_len) - sizeof(ip); i++) {
+		if (*pos != (u8) i) {
+			wpa_printf(MSG_DEBUG,
+				   "test data: RX - ignore mismatching payload");
+			return;
+		}
+		pos++;
+	}
+	extra[0] = '\0';
+	if (ntohs(ip.tot_len) != HWSIM_IP_LEN)
+		os_snprintf(extra, sizeof(extra), " len=%d", ntohs(ip.tot_len));
+	wpa_msg(wpa_s, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR "%s",
+		MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost), extra);
 }
 
 
@@ -8826,7 +8894,7 @@
 static int wpas_ctrl_iface_data_test_tx(struct wpa_supplicant *wpa_s, char *cmd)
 {
 	u8 dst[ETH_ALEN], src[ETH_ALEN];
-	char *pos;
+	char *pos, *pos2;
 	int used;
 	long int val;
 	u8 tos;
@@ -8835,11 +8903,12 @@
 	struct iphdr *ip;
 	u8 *dpos;
 	unsigned int i;
+	size_t send_len = HWSIM_IP_LEN;
 
 	if (wpa_s->l2_test == NULL)
 		return -1;
 
-	/* format: <dst> <src> <tos> */
+	/* format: <dst> <src> <tos> [len=<length>] */
 
 	pos = cmd;
 	used = hwaddr_aton2(pos, dst);
@@ -8853,11 +8922,19 @@
 		return -1;
 	pos += used;
 
-	val = strtol(pos, NULL, 0);
+	val = strtol(pos, &pos2, 0);
 	if (val < 0 || val > 0xff)
 		return -1;
 	tos = val;
 
+	pos = os_strstr(pos2, " len=");
+	if (pos) {
+		i = atoi(pos + 5);
+		if (i < sizeof(*ip) || i > HWSIM_IP_LEN)
+			return -1;
+		send_len = i;
+	}
+
 	eth = (struct ether_header *) &buf[2];
 	os_memcpy(eth->ether_dhost, dst, ETH_ALEN);
 	os_memcpy(eth->ether_shost, src, ETH_ALEN);
@@ -8868,17 +8945,17 @@
 	ip->version = 4;
 	ip->ttl = 64;
 	ip->tos = tos;
-	ip->tot_len = htons(HWSIM_IP_LEN);
+	ip->tot_len = htons(send_len);
 	ip->protocol = 1;
 	ip->saddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1);
 	ip->daddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2);
 	ip->check = ipv4_hdr_checksum(ip, sizeof(*ip));
 	dpos = (u8 *) (ip + 1);
-	for (i = 0; i < HWSIM_IP_LEN - sizeof(*ip); i++)
+	for (i = 0; i < send_len - sizeof(*ip); i++)
 		*dpos++ = i;
 
 	if (l2_packet_send(wpa_s->l2_test, dst, ETHERTYPE_IP, &buf[2],
-			   HWSIM_PACKETLEN) < 0)
+			   sizeof(struct ether_header) + send_len) < 0)
 		return -1;
 
 	wpa_dbg(wpa_s, MSG_DEBUG, "test data: TX dst=" MACSTR " src=" MACSTR
@@ -9458,13 +9535,6 @@
 		return -1;
 	}
 
-	if ((wpa_s->mac_addr_rand_supported & type) != type) {
-		wpa_printf(MSG_INFO,
-			   "CTRL: MAC_RAND_SCAN types=%u != supported=%u",
-			   type, wpa_s->mac_addr_rand_supported);
-		return -1;
-	}
-
 	if (enable > 1) {
 		wpa_printf(MSG_INFO,
 			   "CTRL: MAC_RAND_SCAN enable=<0/1> not specified");
@@ -9498,21 +9568,25 @@
 	}
 
 	if (type & MAC_ADDR_RAND_SCAN) {
-		wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
-					    addr, mask);
+		if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
+					    addr, mask))
+			return -1;
 	}
 
 	if (type & MAC_ADDR_RAND_SCHED_SCAN) {
-		wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
-					    addr, mask);
+		if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
+					    addr, mask))
+			return -1;
 
 		if (wpa_s->sched_scanning && !wpa_s->pno)
 			wpas_scan_restart_sched_scan(wpa_s);
 	}
 
 	if (type & MAC_ADDR_RAND_PNO) {
-		wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
-					    addr, mask);
+		if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
+					    addr, mask))
+			return -1;
+
 		if (wpa_s->pno) {
 			wpas_stop_pno(wpa_s);
 			wpas_start_pno(wpa_s);
@@ -9858,6 +9932,11 @@
 			reply_len += eapol_sm_get_mib(wpa_s->eapol,
 						      reply + reply_len,
 						      reply_size - reply_len);
+#ifdef CONFIG_MACSEC
+			reply_len += ieee802_1x_kay_get_mib(
+				wpa_s->kay, reply + reply_len,
+				reply_size - reply_len);
+#endif /* CONFIG_MACSEC */
 		}
 	} else if (os_strncmp(buf, "STATUS", 6) == 0) {
 		reply_len = wpa_supplicant_ctrl_iface_status(
@@ -10506,6 +10585,12 @@
 	} else if (os_strcmp(buf, "RESEND_ASSOC") == 0) {
 		if (wpas_ctrl_resend_assoc(wpa_s) < 0)
 			reply_len = -1;
+#ifdef CONFIG_IEEE80211W
+	} else if (os_strcmp(buf, "UNPROT_DEAUTH") == 0) {
+		sme_event_unprot_disconnect(
+			wpa_s, wpa_s->bssid, NULL,
+			WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
+#endif /* CONFIG_IEEE80211W */
 #endif /* CONFIG_TESTING_OPTIONS */
 	} else if (os_strncmp(buf, "VENDOR_ELEM_ADD ", 16) == 0) {
 		if (wpas_ctrl_vendor_elem_add(wpa_s, buf + 16) < 0)
@@ -10598,7 +10683,7 @@
 		if (wpas_dpp_configurator_remove(wpa_s, buf + 24) < 0)
 			reply_len = -1;
 	} else if (os_strncmp(buf, "DPP_CONFIGURATOR_SIGN ", 22) == 0) {
-		if (wpas_dpp_configurator_sign(wpa_s, buf + 22) < 0)
+		if (wpas_dpp_configurator_sign(wpa_s, buf + 21) < 0)
 			reply_len = -1;
 	} else if (os_strncmp(buf, "DPP_CONFIGURATOR_GET_KEY ", 25) == 0) {
 		reply_len = wpas_dpp_configurator_get_key(wpa_s, atoi(buf + 25),
diff --git a/wpa_supplicant/ctrl_iface_unix.c b/wpa_supplicant/ctrl_iface_unix.c
index b88c80a..71fe7ed 100644
--- a/wpa_supplicant/ctrl_iface_unix.c
+++ b/wpa_supplicant/ctrl_iface_unix.c
@@ -570,8 +570,8 @@
 		}
 	}
 
-	if (gid_set && chown(dir, -1, gid) < 0) {
-		wpa_printf(MSG_ERROR, "chown[ctrl_interface=%s,gid=%d]: %s",
+	if (gid_set && lchown(dir, -1, gid) < 0) {
+		wpa_printf(MSG_ERROR, "lchown[ctrl_interface=%s,gid=%d]: %s",
 			   dir, (int) gid, strerror(errno));
 		goto fail;
 	}
@@ -638,8 +638,8 @@
 		}
 	}
 
-	if (gid_set && chown(fname, -1, gid) < 0) {
-		wpa_printf(MSG_ERROR, "chown[ctrl_interface=%s,gid=%d]: %s",
+	if (gid_set && lchown(fname, -1, gid) < 0) {
+		wpa_printf(MSG_ERROR, "lchown[ctrl_interface=%s,gid=%d]: %s",
 			   fname, (int) gid, strerror(errno));
 		goto fail;
 	}
@@ -1235,9 +1235,9 @@
 			wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d",
 				   (int) gid);
 		}
-		if (chown(ctrl, -1, gid) < 0) {
+		if (lchown(ctrl, -1, gid) < 0) {
 			wpa_printf(MSG_ERROR,
-				   "chown[global_ctrl_interface=%s,gid=%d]: %s",
+				   "lchown[global_ctrl_interface=%s,gid=%d]: %s",
 				   ctrl, (int) gid, strerror(errno));
 			goto fail;
 		}
diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c
index e0f16bb..fc2fc2e 100644
--- a/wpa_supplicant/dbus/dbus_new.c
+++ b/wpa_supplicant/dbus/dbus_new.c
@@ -13,6 +13,7 @@
 #include "common.h"
 #include "common/ieee802_11_defs.h"
 #include "wps/wps.h"
+#include "ap/sta_info.h"
 #include "../config.h"
 #include "../wpa_supplicant_i.h"
 #include "../bss.h"
@@ -128,7 +129,8 @@
  * Notify listeners about event related with interface
  */
 static void wpas_dbus_signal_interface(struct wpa_supplicant *wpa_s,
-				       const char *sig_name, int properties)
+				       const char *sig_name,
+				       dbus_bool_t properties)
 {
 	struct wpas_dbus_priv *iface;
 	DBusMessage *msg;
@@ -230,7 +232,7 @@
  */
 static void wpas_dbus_signal_bss(struct wpa_supplicant *wpa_s,
 				 const char *bss_obj_path,
-				 const char *sig_name, int properties)
+				 const char *sig_name, dbus_bool_t properties)
 {
 	struct wpas_dbus_priv *iface;
 	DBusMessage *msg;
@@ -364,7 +366,7 @@
  */
 static void wpas_dbus_signal_network(struct wpa_supplicant *wpa_s,
 				     int id, const char *sig_name,
-				     int properties)
+				     dbus_bool_t properties)
 {
 	struct wpas_dbus_priv *iface;
 	DBusMessage *msg;
@@ -1077,6 +1079,79 @@
 }
 
 
+/**
+ * wpas_dbus_signal_station - Send an event signal related to a station object
+ * @wpa_s: %wpa_supplicant network interface data
+ * @station_obj_path: Station object path
+ * @sig_name: signal name - StationAdded or StationRemoved
+ * @properties: Whether to add second argument with object properties
+ *
+ * Notify listeners about event related with station.
+ */
+static void wpas_dbus_signal_station(struct wpa_supplicant *wpa_s,
+				     const char *station_obj_path,
+				     const char *sig_name,
+				     dbus_bool_t properties)
+{
+	struct wpas_dbus_priv *iface;
+	DBusMessage *msg;
+	DBusMessageIter iter;
+
+	iface = wpa_s->global->dbus;
+
+	/* Do nothing if the control interface is not turned on */
+	if (!iface || !wpa_s->dbus_new_path)
+		return;
+
+	wpa_printf(MSG_DEBUG, "dbus: STA signal %s", sig_name);
+	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
+				      WPAS_DBUS_NEW_IFACE_INTERFACE, sig_name);
+	if (!msg)
+		return;
+
+	dbus_message_iter_init_append(msg, &iter);
+	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
+					    &station_obj_path) ||
+	    (properties &&
+	     !wpa_dbus_get_object_properties(iface, station_obj_path,
+					     WPAS_DBUS_NEW_IFACE_STA,
+					     &iter)))
+		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
+	else
+		dbus_connection_send(iface->con, msg, NULL);
+	dbus_message_unref(msg);
+}
+
+
+/**
+ * wpas_dbus_signal_station_added - Send a Station added signal
+ * @wpa_s: %wpa_supplicant network interface data
+ * @station_obj_path: new Station object path
+ *
+ * Notify listeners about adding new Station
+ */
+static void wpas_dbus_signal_station_added(struct wpa_supplicant *wpa_s,
+					   const char *station_obj_path)
+{
+	wpas_dbus_signal_station(wpa_s, station_obj_path, "StationAdded", TRUE);
+}
+
+
+/**
+ * wpas_dbus_signal_station_removed - Send a Station removed signal
+ * @wpa_s: %wpa_supplicant network interface data
+ * @station_obj_path: Station object path
+ *
+ * Notify listeners about removing Station
+ */
+static void wpas_dbus_signal_station_removed(struct wpa_supplicant *wpa_s,
+					     const char *station_obj_path)
+{
+	wpas_dbus_signal_station(wpa_s, station_obj_path, "StationRemoved",
+				 FALSE);
+}
+
+
 #ifdef CONFIG_P2P
 
 /**
@@ -1882,7 +1957,7 @@
  */
 static void wpas_dbus_signal_persistent_group(struct wpa_supplicant *wpa_s,
 					      int id, const char *sig_name,
-					      int properties)
+					      dbus_bool_t properties)
 {
 	struct wpas_dbus_priv *iface;
 	DBusMessage *msg;
@@ -2131,11 +2206,6 @@
 	case WPAS_DBUS_PROP_AP_SCAN:
 		prop = "ApScan";
 		break;
-#ifdef CONFIG_IEEE80211W
-	case WPAS_DBUS_PROP_PMF:
-		prop = "Pmf";
-		break;
-#endif /* CONFIG_IEEE80211W */
 	case WPAS_DBUS_PROP_SCANNING:
 		prop = "Scanning";
 		break;
@@ -2151,6 +2221,9 @@
 	case WPAS_DBUS_PROP_BSSS:
 		prop = "BSSs";
 		break;
+	case WPAS_DBUS_PROP_STATIONS:
+		prop = "Stations";
+		break;
 	case WPAS_DBUS_PROP_CURRENT_AUTH_MODE:
 		prop = "CurrentAuthMode";
 		break;
@@ -2158,10 +2231,26 @@
 		prop = "DisconnectReason";
 		flush = TRUE;
 		break;
+	case WPAS_DBUS_PROP_AUTH_STATUS_CODE:
+		prop = "AuthStatusCode";
+		flush = TRUE;
+		break;
 	case WPAS_DBUS_PROP_ASSOC_STATUS_CODE:
 		prop = "AssocStatusCode";
 		flush = TRUE;
 		break;
+	case WPAS_DBUS_PROP_ROAM_TIME:
+		prop = "RoamTime";
+		break;
+	case WPAS_DBUS_PROP_ROAM_COMPLETE:
+		prop = "RoamComplete";
+		break;
+	case WPAS_DBUS_PROP_SESSION_LENGTH:
+		prop = "SessionLength";
+		break;
+	case WPAS_DBUS_PROP_BSS_TM_STATUS:
+		prop = "BSSTMStatus";
+		break;
 	default:
 		wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
 			   __func__, property);
@@ -2244,6 +2333,41 @@
 
 
 /**
+ * wpas_dbus_sta_signal_prop_changed - Signals change of STA property
+ * @wpa_s: %wpa_supplicant network interface data
+ * @property: indicates which property has changed
+ * @address: unique BSS identifier
+ *
+ * Sends PropertyChanged signals with path, interface, and arguments depending
+ * on which property has changed.
+ */
+void wpas_dbus_sta_signal_prop_changed(struct wpa_supplicant *wpa_s,
+				       enum wpas_dbus_bss_prop property,
+				       u8 address[ETH_ALEN])
+{
+	char path[WPAS_DBUS_OBJECT_PATH_MAX];
+	char *prop;
+
+	switch (property) {
+	case WPAS_DBUS_STA_PROP_ADDRESS:
+		prop = "Address";
+		break;
+	default:
+		wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
+			   __func__, property);
+		return;
+	}
+
+	os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
+		    "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR,
+		    wpa_s->dbus_new_path, MAC2STR(address));
+
+	wpa_dbus_mark_property_changed(wpa_s->global->dbus, path,
+				       WPAS_DBUS_NEW_IFACE_STA, prop);
+}
+
+
+/**
  * wpas_dbus_signal_debug_level_changed - Signals change of debug param
  * @global: wpa_global structure
  *
@@ -2731,6 +2855,30 @@
 	  NULL,
 	  NULL
 	},
+	{
+	  "RoamTime", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
+	  wpas_dbus_getter_roam_time,
+	  NULL,
+	  NULL
+	},
+	{
+	  "RoamComplete", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
+	  wpas_dbus_getter_roam_complete,
+	  NULL,
+	  NULL
+	},
+	{
+	  "SessionLength", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
+	  wpas_dbus_getter_session_length,
+	  NULL,
+	  NULL
+	},
+	{
+	  "BSSTMStatus", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
+	  wpas_dbus_getter_bss_tm_status,
+	  NULL,
+	  NULL
+	},
 	{ NULL, NULL, NULL, NULL, NULL, NULL }
 };
 
@@ -2857,6 +3005,157 @@
 }
 
 
+static const struct wpa_dbus_property_desc wpas_dbus_sta_properties[] = {
+	{ "Address", WPAS_DBUS_NEW_IFACE_STA, "ay",
+	  wpas_dbus_getter_sta_address,
+	  NULL, NULL
+	},
+	{ "AID", WPAS_DBUS_NEW_IFACE_STA, "q",
+	  wpas_dbus_getter_sta_aid,
+	  NULL, NULL
+	},
+	{ "Capabilities", WPAS_DBUS_NEW_IFACE_STA, "q",
+	  wpas_dbus_getter_sta_caps,
+	  NULL, NULL
+	},
+	{ "RxPackets", WPAS_DBUS_NEW_IFACE_STA, "t",
+	  wpas_dbus_getter_sta_rx_packets,
+	  NULL, NULL
+	},
+	{ "TxPackets", WPAS_DBUS_NEW_IFACE_STA, "t",
+	  wpas_dbus_getter_sta_tx_packets,
+	  NULL, NULL
+	},
+	{ "RxBytes", WPAS_DBUS_NEW_IFACE_STA, "t",
+	  wpas_dbus_getter_sta_rx_bytes,
+	  NULL, NULL
+	},
+	{ "TxBytes", WPAS_DBUS_NEW_IFACE_STA, "t",
+	  wpas_dbus_getter_sta_tx_bytes,
+	  NULL, NULL
+	},
+	{ NULL, NULL, NULL, NULL, NULL, NULL }
+};
+
+
+static const struct wpa_dbus_signal_desc wpas_dbus_sta_signals[] = {
+	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
+	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_STA,
+	  {
+		  { "properties", "a{sv}", ARG_OUT },
+		  END_ARGS
+	  }
+	},
+	{ NULL, NULL, { END_ARGS } }
+};
+
+
+/**
+ * wpas_dbus_unregister_sta - Unregister a connected station from dbus
+ * @wpa_s: wpa_supplicant interface structure
+ * @sta: station MAC address
+ * Returns: 0 on success, -1 on failure
+ *
+ * Unregisters STA representing object from dbus.
+ */
+int wpas_dbus_unregister_sta(struct wpa_supplicant *wpa_s, const u8 *sta)
+{
+	struct wpas_dbus_priv *ctrl_iface;
+	char station_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
+
+	/* Do nothing if the control interface is not turned on */
+	if (!wpa_s || !wpa_s->global)
+		return 0;
+	ctrl_iface = wpa_s->global->dbus;
+	if (!ctrl_iface)
+		return 0;
+
+	os_snprintf(station_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+		    "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR,
+		    wpa_s->dbus_new_path, MAC2STR(sta));
+
+	wpa_printf(MSG_DEBUG, "dbus: Unregister STA object '%s'",
+		   station_obj_path);
+	if (wpa_dbus_unregister_object_per_iface(ctrl_iface,
+						 station_obj_path)) {
+		wpa_printf(MSG_ERROR, "dbus: Cannot unregister STA object %s",
+			   station_obj_path);
+		return -1;
+	}
+
+	wpas_dbus_signal_station_removed(wpa_s, station_obj_path);
+	wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STATIONS);
+
+	return 0;
+}
+
+
+/**
+ * wpas_dbus_register_sta - Register a connected station with dbus
+ * @wpa_s: wpa_supplicant interface structure
+ * @sta: station MAC address
+ * Returns: 0 on success, -1 on failure
+ *
+ * Registers STA representing object with dbus.
+ */
+int wpas_dbus_register_sta(struct wpa_supplicant *wpa_s, const u8 *sta)
+{
+	struct wpas_dbus_priv *ctrl_iface;
+	struct wpa_dbus_object_desc *obj_desc;
+	char station_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
+	struct sta_handler_args *arg;
+
+	/* Do nothing if the control interface is not turned on */
+	if (!wpa_s || !wpa_s->global)
+		return 0;
+	ctrl_iface = wpa_s->global->dbus;
+	if (!ctrl_iface)
+		return 0;
+
+	os_snprintf(station_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+		    "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR,
+		    wpa_s->dbus_new_path, MAC2STR(sta));
+
+	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
+	if (!obj_desc) {
+		wpa_printf(MSG_ERROR,
+			   "Not enough memory to create object description");
+		goto err;
+	}
+
+	arg = os_zalloc(sizeof(struct sta_handler_args));
+	if (!arg) {
+		wpa_printf(MSG_ERROR,
+			   "Not enough memory to create arguments for handler");
+		goto err;
+	}
+	arg->wpa_s = wpa_s;
+	arg->sta = sta;
+
+	wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
+			   wpas_dbus_sta_properties, wpas_dbus_sta_signals);
+
+	wpa_printf(MSG_DEBUG, "dbus: Register STA object '%s'",
+		   station_obj_path);
+	if (wpa_dbus_register_object_per_iface(ctrl_iface, station_obj_path,
+					       wpa_s->ifname, obj_desc)) {
+		wpa_printf(MSG_ERROR,
+			   "Cannot register STA dbus object %s",
+			   station_obj_path);
+		goto err;
+	}
+
+	wpas_dbus_signal_station_added(wpa_s, station_obj_path);
+	wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STATIONS);
+
+	return 0;
+
+err:
+	free_dbus_object_desc(obj_desc);
+	return -1;
+}
+
+
 static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = {
 	{ "Scan", WPAS_DBUS_NEW_IFACE_INTERFACE,
 	  (WPADBusMethodHandler) wpas_dbus_handler_scan,
@@ -3307,13 +3606,6 @@
 	  wpas_dbus_setter_ap_scan,
 	  NULL
 	},
-#ifdef CONFIG_IEEE80211W
-	{ "Pmf", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
-	  wpas_dbus_getter_pmf,
-	  wpas_dbus_setter_pmf,
-	  NULL
-	},
-#endif /* CONFIG_IEEE80211W */
 	{ "BSSExpireAge", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
 	  wpas_dbus_getter_bss_expire_age,
 	  wpas_dbus_setter_bss_expire_age,
@@ -3484,6 +3776,11 @@
 	  NULL,
 	  NULL
 	},
+	{ "AuthStatusCode", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
+	  wpas_dbus_getter_auth_status_code,
+	  NULL,
+	  NULL
+	},
 	{ "AssocStatusCode", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
 	  wpas_dbus_getter_assoc_status_code,
 	  NULL,
@@ -3501,6 +3798,11 @@
 	  NULL
 	},
 #endif /* CONFIG_MESH */
+	{ "Stations", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
+	  wpas_dbus_getter_stas,
+	  NULL,
+	  NULL
+	},
 	{ NULL, NULL, NULL, NULL, NULL, NULL }
 };
 
@@ -3770,6 +4072,19 @@
 		  END_ARGS
 	  }
 	},
+	{ "StationAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
+	  {
+		  { "path", "o", ARG_OUT },
+		  { "properties", "a{sv}", ARG_OUT },
+		  END_ARGS
+	  }
+	},
+	{ "StationRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
+	  {
+		  { "path", "o", ARG_OUT },
+		  END_ARGS
+	  }
+	},
 	{ "NetworkRequest", WPAS_DBUS_NEW_IFACE_INTERFACE,
 	  {
 		  { "path", "o", ARG_OUT },
@@ -4050,6 +4365,11 @@
 	  NULL,
 	  NULL
 	},
+	{ "VSIE", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
+	  wpas_dbus_getter_p2p_peer_vsie,
+	  NULL,
+	  NULL
+	},
 	{ NULL, NULL, NULL, NULL, NULL, NULL }
 };
 
@@ -4078,7 +4398,7 @@
  */
 static void wpas_dbus_signal_peer(struct wpa_supplicant *wpa_s,
 				  const u8 *dev_addr, const char *interface,
-				  const char *sig_name, int properties)
+				  const char *sig_name, dbus_bool_t properties)
 {
 	struct wpas_dbus_priv *iface;
 	DBusMessage *msg;
diff --git a/wpa_supplicant/dbus/dbus_new.h b/wpa_supplicant/dbus/dbus_new.h
index e68acb7..42db389 100644
--- a/wpa_supplicant/dbus/dbus_new.h
+++ b/wpa_supplicant/dbus/dbus_new.h
@@ -22,15 +22,20 @@
 
 enum wpas_dbus_prop {
 	WPAS_DBUS_PROP_AP_SCAN,
-	WPAS_DBUS_PROP_PMF,
 	WPAS_DBUS_PROP_SCANNING,
 	WPAS_DBUS_PROP_STATE,
 	WPAS_DBUS_PROP_CURRENT_BSS,
 	WPAS_DBUS_PROP_CURRENT_NETWORK,
 	WPAS_DBUS_PROP_CURRENT_AUTH_MODE,
 	WPAS_DBUS_PROP_BSSS,
+	WPAS_DBUS_PROP_STATIONS,
 	WPAS_DBUS_PROP_DISCONNECT_REASON,
+	WPAS_DBUS_PROP_AUTH_STATUS_CODE,
 	WPAS_DBUS_PROP_ASSOC_STATUS_CODE,
+	WPAS_DBUS_PROP_ROAM_TIME,
+	WPAS_DBUS_PROP_ROAM_COMPLETE,
+	WPAS_DBUS_PROP_SESSION_LENGTH,
+	WPAS_DBUS_PROP_BSS_TM_STATUS,
 };
 
 enum wpas_dbus_bss_prop {
@@ -46,6 +51,10 @@
 	WPAS_DBUS_BSS_PROP_AGE,
 };
 
+enum wpas_dbus_sta_prop {
+	WPAS_DBUS_STA_PROP_ADDRESS,
+};
+
 #define WPAS_DBUS_OBJECT_PATH_MAX 150
 
 #define WPAS_DBUS_NEW_SERVICE		"fi.w1.wpa_supplicant1"
@@ -62,6 +71,9 @@
 #define WPAS_DBUS_NEW_BSSIDS_PART "BSSs"
 #define WPAS_DBUS_NEW_IFACE_BSS	WPAS_DBUS_NEW_INTERFACE ".BSS"
 
+#define WPAS_DBUS_NEW_STAS_PART "Stations"
+#define WPAS_DBUS_NEW_IFACE_STA	WPAS_DBUS_NEW_INTERFACE ".Station"
+
 #define WPAS_DBUS_NEW_IFACE_P2PDEVICE	\
 		WPAS_DBUS_NEW_IFACE_INTERFACE ".P2PDevice"
 
@@ -164,6 +176,8 @@
 			     u8 bssid[ETH_ALEN], unsigned int id);
 int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
 			   u8 bssid[ETH_ALEN], unsigned int id);
+int wpas_dbus_unregister_sta(struct wpa_supplicant *wpa_s, const u8 *sta);
+int wpas_dbus_register_sta(struct wpa_supplicant *wpa_s, const u8 *sta);
 void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s,
 				 const char *name);
 void wpas_dbus_signal_blob_removed(struct wpa_supplicant *wpa_s,
@@ -346,6 +360,18 @@
 	return 0;
 }
 
+static inline int wpas_dbus_unregister_sta(struct wpa_supplicant *wpa_s,
+					   const u8 *sta)
+{
+	return 0;
+}
+
+static inline int wpas_dbus_register_sta(struct wpa_supplicant *wpa_s,
+					 const u8 *sta)
+{
+	return 0;
+}
+
 static inline void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s,
 					       const char *name)
 {
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c
index a3c98fa..6c36d91 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers.c
@@ -15,6 +15,9 @@
 #include "eap_peer/eap_methods.h"
 #include "eapol_supp/eapol_supp_sm.h"
 #include "rsn_supp/wpa.h"
+#include "ap/hostapd.h"
+#include "ap/sta_info.h"
+#include "ap/ap_drv_ops.h"
 #include "../config.h"
 #include "../wpa_supplicant_i.h"
 #include "../driver_i.h"
@@ -22,6 +25,7 @@
 #include "../bss.h"
 #include "../scan.h"
 #include "../autoscan.h"
+#include "../ap.h"
 #include "dbus_new_helpers.h"
 #include "dbus_new.h"
 #include "dbus_new_handlers.h"
@@ -980,8 +984,8 @@
 	const struct wpa_dbus_property_desc *property_desc,
 	DBusMessageIter *iter, DBusError *error, void *user_data)
 {
-	const char *capabilities[8] = { NULL, NULL, NULL, NULL, NULL, NULL,
-					NULL, NULL };
+	const char *capabilities[10] = { NULL, NULL, NULL, NULL, NULL, NULL,
+					NULL, NULL, NULL, NULL };
 	size_t num_items = 0;
 #ifdef CONFIG_FILS
 	struct wpa_global *global = user_data;
@@ -1020,6 +1024,12 @@
 	if (fils_sk_pfs_supported)
 		capabilities[num_items++] = "fils_sk_pfs";
 #endif /* CONFIG_FILS */
+#ifdef CONFIG_IEEE80211R
+	capabilities[num_items++] = "ft";
+#endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_SHA384
+	capabilities[num_items++] = "sha384";
+#endif /* CONFIG_SHA384 */
 
 	return wpas_dbus_simple_array_property_getter(iter,
 						      DBUS_TYPE_STRING,
@@ -3012,61 +3022,6 @@
 }
 
 
-#ifdef CONFIG_IEEE80211W
-
-/**
- * wpas_dbus_getter_pmf - Control PMF default
- * @iter: Pointer to incoming dbus message iter
- * @error: Location to store error on failure
- * @user_data: Function specific data
- * Returns: TRUE on success, FALSE on failure
- *
- * Getter function for "Pmf" property.
- */
-dbus_bool_t wpas_dbus_getter_pmf(
-	const struct wpa_dbus_property_desc *property_desc,
-	DBusMessageIter *iter, DBusError *error, void *user_data)
-{
-	struct wpa_supplicant *wpa_s = user_data;
-	dbus_uint32_t pmf = wpa_s->conf->pmf;
-
-	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
-						&pmf, error);
-}
-
-
-/**
- * wpas_dbus_setter_pmf - Control PMF default
- * @iter: Pointer to incoming dbus message iter
- * @error: Location to store error on failure
- * @user_data: Function specific data
- * Returns: TRUE on success, FALSE on failure
- *
- * Setter function for "Pmf" property.
- */
-dbus_bool_t wpas_dbus_setter_pmf(
-	const struct wpa_dbus_property_desc *property_desc,
-	DBusMessageIter *iter, DBusError *error, void *user_data)
-{
-	struct wpa_supplicant *wpa_s = user_data;
-	dbus_uint32_t pmf;
-
-	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
-					      &pmf))
-		return FALSE;
-
-	if (pmf > 2) {
-		dbus_set_error_const(error, DBUS_ERROR_FAILED,
-				     "Pmf must be 0, 1, or 2");
-		return FALSE;
-	}
-	wpa_s->conf->pmf = pmf;
-	return TRUE;
-}
-
-#endif /* CONFIG_IEEE80211W */
-
-
 /**
  * wpas_dbus_getter_fast_reauth - Control fast
  * reauthentication (TLS session resumption)
@@ -3138,6 +3093,27 @@
 
 
 /**
+ * wpas_dbus_getter_auth_status_code - Get most recent auth status code
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "AuthStatusCode" property.
+ */
+dbus_bool_t wpas_dbus_getter_auth_status_code(
+	const struct wpa_dbus_property_desc *property_desc,
+	DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+	struct wpa_supplicant *wpa_s = user_data;
+	dbus_int32_t reason = wpa_s->auth_status_code;
+
+	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
+						&reason, error);
+}
+
+
+/**
  * wpas_dbus_getter_assoc_status_code - Get most recent failed assoc status code
  * @iter: Pointer to incoming dbus message iter
  * @error: Location to store error on failure
@@ -3159,6 +3135,97 @@
 
 
 /**
+ * wpas_dbus_getter_roam_time - Get most recent roam time
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "RoamTime" property.
+ */
+dbus_bool_t wpas_dbus_getter_roam_time(
+	const struct wpa_dbus_property_desc *property_desc,
+	DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+	struct wpa_supplicant *wpa_s = user_data;
+	dbus_uint32_t roam_time = wpa_s->roam_time.sec * 1000 +
+		wpa_s->roam_time.usec / 1000;
+
+	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
+						&roam_time, error);
+}
+
+
+/**
+ * wpas_dbus_getter_roam_complete - Get most recent roam success or failure
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "RoamComplete" property.
+ */
+dbus_bool_t wpas_dbus_getter_roam_complete(
+	const struct wpa_dbus_property_desc *property_desc,
+	DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+	struct wpa_supplicant *wpa_s = user_data;
+	dbus_bool_t roam_complete = os_reltime_initialized(&wpa_s->roam_time);
+
+	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
+						&roam_complete, error);
+}
+
+
+/**
+ * wpas_dbus_getter_session_length - Get most recent BSS session length
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "SessionLength" property.
+ */
+dbus_bool_t wpas_dbus_getter_session_length(
+	const struct wpa_dbus_property_desc *property_desc,
+	DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+	struct wpa_supplicant *wpa_s = user_data;
+	dbus_uint32_t session_length = wpa_s->session_length.sec * 1000 +
+		wpa_s->session_length.usec / 1000;
+
+	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
+						&session_length, error);
+}
+
+
+/**
+ * wpas_dbus_getter_bss_tm_status - Get most BSS Transition Management request
+ * status code
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "BSSTMStatus" property.
+ */
+dbus_bool_t wpas_dbus_getter_bss_tm_status(
+	const struct wpa_dbus_property_desc *property_desc,
+	DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+#ifdef CONFIG_WNM
+	struct wpa_supplicant *wpa_s = user_data;
+	dbus_uint32_t bss_tm_status = wpa_s->bss_tm_status;
+#else /* CONFIG_WNM */
+	dbus_uint32_t bss_tm_status = 0;
+#endif /* CONFIG_WNM */
+
+	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
+						&bss_tm_status, error);
+}
+
+
+/**
  * wpas_dbus_getter_bss_expire_age - Get BSS entry expiration age
  * @iter: Pointer to incoming dbus message iter
  * @error: Location to store error on failure
@@ -3854,6 +3921,320 @@
 }
 
 
+/**
+ * wpas_dbus_getter_stas - Get connected stations for an interface
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: a list of stations
+ *
+ * Getter for "Stations" property.
+ */
+dbus_bool_t wpas_dbus_getter_stas(
+	const struct wpa_dbus_property_desc *property_desc,
+	DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+	struct wpa_supplicant *wpa_s = user_data;
+	struct sta_info *sta = NULL;
+	char **paths = NULL;
+	unsigned int i = 0, num = 0;
+	dbus_bool_t success = FALSE;
+
+	if (!wpa_s->dbus_new_path) {
+		dbus_set_error(error, DBUS_ERROR_FAILED,
+			       "%s: no D-Bus interface", __func__);
+		return FALSE;
+	}
+
+#ifdef CONFIG_AP
+	if (wpa_s->ap_iface) {
+		struct hostapd_data *hapd;
+
+		hapd = wpa_s->ap_iface->bss[0];
+		sta = hapd->sta_list;
+		num = hapd->num_sta;
+	}
+#endif /* CONFIG_AP */
+
+	paths = os_calloc(num, sizeof(char *));
+	if (!paths) {
+		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
+		return FALSE;
+	}
+
+	/* Loop through scan results and append each result's object path */
+	for (; sta; sta = sta->next) {
+		paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
+		if (!paths[i]) {
+			dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
+					     "no memory");
+			goto out;
+		}
+		/* Construct the object path for this BSS. */
+		os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
+			    "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR,
+			    wpa_s->dbus_new_path, MAC2STR(sta->addr));
+	}
+
+	success = wpas_dbus_simple_array_property_getter(iter,
+							 DBUS_TYPE_OBJECT_PATH,
+							 paths, num,
+							 error);
+
+out:
+	while (i)
+		os_free(paths[--i]);
+	os_free(paths);
+	return success;
+}
+
+
+/**
+ * wpas_dbus_getter_sta_address - Return the address of a connected station
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "Address" property.
+ */
+dbus_bool_t wpas_dbus_getter_sta_address(
+	const struct wpa_dbus_property_desc *property_desc,
+	DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+#ifdef CONFIG_AP
+	struct sta_handler_args *args = user_data;
+	struct sta_info *sta;
+
+	sta = ap_get_sta(args->wpa_s->ap_iface->bss[0], args->sta);
+	if (!sta)
+		return FALSE;
+
+	return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
+						      sta->addr, ETH_ALEN,
+						      error);
+#else /* CONFIG_AP */
+    return FALSE;
+#endif /* CONFIG_AP */
+}
+
+
+/**
+ * wpas_dbus_getter_sta_aid - Return the AID of a connected station
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "AID" property.
+ */
+dbus_bool_t wpas_dbus_getter_sta_aid(
+	const struct wpa_dbus_property_desc *property_desc,
+	DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+#ifdef CONFIG_AP
+	struct sta_handler_args *args = user_data;
+	struct sta_info *sta;
+
+	sta = ap_get_sta(args->wpa_s->ap_iface->bss[0], args->sta);
+	if (!sta)
+		return FALSE;
+
+	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
+						&sta->aid,
+						error);
+#else /* CONFIG_AP */
+    return FALSE;
+#endif /* CONFIG_AP */
+}
+
+
+/**
+ * wpas_dbus_getter_sta_caps - Return the capabilities of a station
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "Capabilities" property.
+ */
+dbus_bool_t wpas_dbus_getter_sta_caps(
+	const struct wpa_dbus_property_desc *property_desc,
+	DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+#ifdef CONFIG_AP
+	struct sta_handler_args *args = user_data;
+	struct sta_info *sta;
+
+	sta = ap_get_sta(args->wpa_s->ap_iface->bss[0], args->sta);
+	if (!sta)
+		return FALSE;
+
+	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
+						&sta->capability,
+						error);
+#else /* CONFIG_AP */
+    return FALSE;
+#endif /* CONFIG_AP */
+}
+
+
+/**
+ * wpas_dbus_getter_rx_packets - Return the received packets for a station
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "RxPackets" property.
+ */
+dbus_bool_t wpas_dbus_getter_sta_rx_packets(
+	const struct wpa_dbus_property_desc *property_desc,
+	DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+#ifdef CONFIG_AP
+	struct sta_handler_args *args = user_data;
+	struct sta_info *sta;
+	struct hostap_sta_driver_data data;
+	struct hostapd_data *hapd;
+
+	if (!args->wpa_s->ap_iface)
+		return FALSE;
+
+	hapd = args->wpa_s->ap_iface->bss[0];
+	sta = ap_get_sta(hapd, args->sta);
+	if (!sta)
+		return FALSE;
+
+	if (hostapd_drv_read_sta_data(hapd, &data, sta->addr) < 0)
+		return FALSE;
+
+	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT64,
+						&data.rx_packets,
+						error);
+#else /* CONFIG_AP */
+    return FALSE;
+#endif /* CONFIG_AP */
+}
+
+
+/**
+ * wpas_dbus_getter_tx_packets - Return the transmitted packets for a station
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "TxPackets" property.
+ */
+dbus_bool_t wpas_dbus_getter_sta_tx_packets(
+	const struct wpa_dbus_property_desc *property_desc,
+	DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+#ifdef CONFIG_AP
+	struct sta_handler_args *args = user_data;
+	struct sta_info *sta;
+	struct hostap_sta_driver_data data;
+	struct hostapd_data *hapd;
+
+	if (!args->wpa_s->ap_iface)
+		return FALSE;
+
+	hapd = args->wpa_s->ap_iface->bss[0];
+	sta = ap_get_sta(hapd, args->sta);
+	if (!sta)
+		return FALSE;
+
+	if (hostapd_drv_read_sta_data(hapd, &data, sta->addr) < 0)
+		return FALSE;
+
+	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT64,
+						&data.tx_packets,
+						error);
+#else /* CONFIG_AP */
+    return FALSE;
+#endif /* CONFIG_AP */
+}
+
+
+/**
+ * wpas_dbus_getter_tx_bytes - Return the transmitted bytes for a station
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "TxBytes" property.
+ */
+dbus_bool_t wpas_dbus_getter_sta_tx_bytes(
+	const struct wpa_dbus_property_desc *property_desc,
+	DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+#ifdef CONFIG_AP
+	struct sta_handler_args *args = user_data;
+	struct sta_info *sta;
+	struct hostap_sta_driver_data data;
+	struct hostapd_data *hapd;
+
+	if (!args->wpa_s->ap_iface)
+		return FALSE;
+
+	hapd = args->wpa_s->ap_iface->bss[0];
+	sta = ap_get_sta(hapd, args->sta);
+	if (!sta)
+		return FALSE;
+
+	if (hostapd_drv_read_sta_data(hapd, &data, sta->addr) < 0)
+		return FALSE;
+
+	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT64,
+						&data.tx_bytes,
+						error);
+#else /* CONFIG_AP */
+    return FALSE;
+#endif /* CONFIG_AP */
+}
+
+
+/**
+ * wpas_dbus_getter_rx_bytes - Return the received bytes for a station
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "RxBytes" property.
+ */
+dbus_bool_t wpas_dbus_getter_sta_rx_bytes(
+	const struct wpa_dbus_property_desc *property_desc,
+	DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+#ifdef CONFIG_AP
+	struct sta_handler_args *args = user_data;
+	struct sta_info *sta;
+	struct hostap_sta_driver_data data;
+	struct hostapd_data *hapd;
+
+	if (!args->wpa_s->ap_iface)
+		return FALSE;
+
+	hapd = args->wpa_s->ap_iface->bss[0];
+	sta = ap_get_sta(hapd, args->sta);
+	if (!sta)
+		return FALSE;
+
+	if (hostapd_drv_read_sta_data(hapd, &data, sta->addr) < 0)
+		return FALSE;
+
+	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT64,
+						&data.rx_bytes,
+						error);
+#else /* CONFIG_AP */
+    return FALSE;
+#endif /* CONFIG_AP */
+}
+
+
 static struct wpa_bss * get_bss_helper(struct bss_handler_args *args,
 				       DBusError *error, const char *func_name)
 {
@@ -4116,7 +4497,7 @@
 	DBusMessageIter iter_dict, variant_iter;
 	const char *group;
 	const char *pairwise[5]; /* max 5 pairwise ciphers is supported */
-	const char *key_mgmt[13]; /* max 13 key managements may be supported */
+	const char *key_mgmt[15]; /* max 15 key managements may be supported */
 	int n;
 
 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
@@ -4126,7 +4507,12 @@
 	if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
 		goto nomem;
 
-	/* KeyMgmt */
+	/*
+	 * KeyMgmt
+	 *
+	 * When adding a new entry here, please take care to extend key_mgmt[]
+	 * and keep documentation in doc/dbus.doxygen up to date.
+	 */
 	n = 0;
 	if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK)
 		key_mgmt[n++] = "wpa-psk";
@@ -4158,6 +4544,12 @@
 	if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384)
 		key_mgmt[n++] = "wpa-ft-fils-sha384";
 #endif /* CONFIG_FILS */
+#ifdef CONFIG_SAE
+	if (ie_data->key_mgmt & WPA_KEY_MGMT_SAE)
+		key_mgmt[n++] = "sae";
+	if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_SAE)
+		key_mgmt[n++] = "ft-sae";
+#endif /* CONFIG_SAE */
 	if (ie_data->key_mgmt & WPA_KEY_MGMT_NONE)
 		key_mgmt[n++] = "wpa-none";
 
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.h b/wpa_supplicant/dbus/dbus_new_handlers.h
index 26652ad..d922ce1 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.h
+++ b/wpa_supplicant/dbus/dbus_new_handlers.h
@@ -22,6 +22,11 @@
 	unsigned int id;
 };
 
+struct sta_handler_args {
+	struct wpa_supplicant *wpa_s;
+	const u8 *sta;
+};
+
 dbus_bool_t wpas_dbus_simple_property_getter(DBusMessageIter *iter,
 					     const int type,
 					     const void *val,
@@ -141,13 +146,16 @@
 DECLARE_ACCESSOR(wpas_dbus_getter_scanning);
 DECLARE_ACCESSOR(wpas_dbus_getter_ap_scan);
 DECLARE_ACCESSOR(wpas_dbus_setter_ap_scan);
-DECLARE_ACCESSOR(wpas_dbus_getter_pmf);
-DECLARE_ACCESSOR(wpas_dbus_setter_pmf);
 DECLARE_ACCESSOR(wpas_dbus_getter_fast_reauth);
 DECLARE_ACCESSOR(wpas_dbus_setter_fast_reauth);
 DECLARE_ACCESSOR(wpas_dbus_getter_disconnect_reason);
 DECLARE_ACCESSOR(wpas_dbus_getter_disassociate_reason);
+DECLARE_ACCESSOR(wpas_dbus_getter_auth_status_code);
 DECLARE_ACCESSOR(wpas_dbus_getter_assoc_status_code);
+DECLARE_ACCESSOR(wpas_dbus_getter_roam_time);
+DECLARE_ACCESSOR(wpas_dbus_getter_roam_complete);
+DECLARE_ACCESSOR(wpas_dbus_getter_session_length);
+DECLARE_ACCESSOR(wpas_dbus_getter_bss_tm_status);
 DECLARE_ACCESSOR(wpas_dbus_getter_bss_expire_age);
 DECLARE_ACCESSOR(wpas_dbus_setter_bss_expire_age);
 DECLARE_ACCESSOR(wpas_dbus_getter_bss_expire_count);
@@ -168,6 +176,14 @@
 DECLARE_ACCESSOR(wpas_dbus_getter_pkcs11_engine_path);
 DECLARE_ACCESSOR(wpas_dbus_getter_pkcs11_module_path);
 DECLARE_ACCESSOR(wpas_dbus_getter_blobs);
+DECLARE_ACCESSOR(wpas_dbus_getter_stas);
+DECLARE_ACCESSOR(wpas_dbus_getter_sta_address);
+DECLARE_ACCESSOR(wpas_dbus_getter_sta_aid);
+DECLARE_ACCESSOR(wpas_dbus_getter_sta_caps);
+DECLARE_ACCESSOR(wpas_dbus_getter_sta_rx_packets);
+DECLARE_ACCESSOR(wpas_dbus_getter_sta_tx_packets);
+DECLARE_ACCESSOR(wpas_dbus_getter_sta_tx_bytes);
+DECLARE_ACCESSOR(wpas_dbus_getter_sta_rx_bytes);
 DECLARE_ACCESSOR(wpas_dbus_getter_bss_bssid);
 DECLARE_ACCESSOR(wpas_dbus_getter_bss_ssid);
 DECLARE_ACCESSOR(wpas_dbus_getter_bss_privacy);
diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
index 9305b9a..8cdd885 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
@@ -384,14 +384,14 @@
 			goto inv_args;
 
 		if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, 0, 0,
-						  0, 0, NULL, 0, 0)) {
+						  0, 0, 0, NULL, 0, 0)) {
 			reply = wpas_dbus_error_unknown_error(
 				message,
 				"Failed to reinvoke a persistent group");
 			goto out;
 		}
 	} else if (wpas_p2p_group_add(wpa_s, persistent_group, freq, 0, 0, 0,
-				      0))
+				      0, 0))
 		goto inv_args;
 
 out:
@@ -505,6 +505,7 @@
 
 	wpa_s = wpa_s->global->p2p_init_wpa_s;
 
+	wpas_p2p_stop_find(wpa_s);
 	os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
 	wpa_s->force_long_sd = 0;
 	p2p_flush(wpa_s->global->p2p);
@@ -532,6 +533,7 @@
 	int new_pin;
 	char *err_msg = NULL;
 	char *iface = NULL;
+	int ret;
 
 	if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
 		return reply;
@@ -603,13 +605,19 @@
 
 	new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
 				   persistent_group, 0, join, authorize_only,
-				   go_intent, freq, 0, -1, 0, 0, 0, 0, NULL, 0);
+				   go_intent, freq, 0, -1, 0, 0, 0, 0, 0,
+				   NULL, 0);
 
 	if (new_pin >= 0) {
 		char npin[9];
 		char *generated_pin;
 
-		os_snprintf(npin, sizeof(npin), "%08d", new_pin);
+		ret = os_snprintf(npin, sizeof(npin), "%08d", new_pin);
+		if (os_snprintf_error(sizeof(npin), ret)) {
+			reply = wpas_dbus_error_unknown_error(message,
+							      "invalid PIN");
+			goto out;
+		}
 		generated_pin = npin;
 		reply = dbus_message_new_method_return(message);
 		dbus_message_append_args(reply, DBUS_TYPE_STRING,
@@ -755,7 +763,7 @@
 			goto err;
 
 		if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL, 0, 0, 0, 0, 0,
-				    0) < 0) {
+				    0, 0) < 0) {
 			reply = wpas_dbus_error_unknown_error(
 				message,
 				"Failed to reinvoke a persistent group");
@@ -1910,6 +1918,30 @@
 	return success;
 }
 
+dbus_bool_t wpas_dbus_getter_p2p_peer_vsie(
+	const struct wpa_dbus_property_desc *property_desc,
+	DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+	struct peer_handler_args *peer_args = user_data;
+	const struct p2p_peer_info *info;
+
+	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
+				  peer_args->p2p_device_addr, 0);
+	if (!info) {
+		dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
+		return FALSE;
+	}
+
+	if (!info->vendor_elems)
+		return wpas_dbus_simple_array_property_getter(iter,
+							      DBUS_TYPE_BYTE,
+							      NULL, 0, error);
+
+	return wpas_dbus_simple_array_property_getter(
+		iter, DBUS_TYPE_BYTE, (char *) info->vendor_elems->buf,
+		info->vendor_elems->used, error);
+}
+
 
 /**
  * wpas_dbus_getter_persistent_groups - Get array of persistent group objects
@@ -2661,7 +2693,7 @@
 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
 		goto error;
 
-	if (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
+	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
 			goto error;
 
@@ -2673,26 +2705,27 @@
 				bonjour = 1;
 			else
 				goto error_clear;
-			wpa_dbus_dict_entry_clear(&entry);
+		} else if (os_strcmp(entry.key, "version") == 0 &&
+			   entry.type == DBUS_TYPE_INT32) {
+			version = entry.uint32_value;
+		} else if (os_strcmp(entry.key, "service") == 0 &&
+			   entry.type == DBUS_TYPE_STRING) {
+			os_free(service);
+			service = os_strdup(entry.str_value);
+		} else if (os_strcmp(entry.key, "query") == 0) {
+			if (entry.type != DBUS_TYPE_ARRAY ||
+			    entry.array_type != DBUS_TYPE_BYTE)
+				goto error_clear;
+			wpabuf_free(query);
+			query = wpabuf_alloc_copy(entry.bytearray_value,
+						  entry.array_len);
+		} else {
+			goto error_clear;
 		}
+
+		wpa_dbus_dict_entry_clear(&entry);
 	}
 	if (upnp == 1) {
-		while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
-			if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
-				goto error;
-			if (os_strcmp(entry.key, "version") == 0 &&
-			    entry.type == DBUS_TYPE_INT32)
-				version = entry.uint32_value;
-			else if (os_strcmp(entry.key, "service") == 0 &&
-				 entry.type == DBUS_TYPE_STRING) {
-				os_free(service);
-				service = os_strdup(entry.str_value);
-			} else
-				goto error_clear;
-
-			wpa_dbus_dict_entry_clear(&entry);
-		}
-
 		if (version <= 0 || service == NULL)
 			goto error;
 
@@ -2700,24 +2733,6 @@
 		if (ret != 0)
 			goto error;
 	} else if (bonjour == 1) {
-		while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
-			if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
-				goto error;
-
-			if (os_strcmp(entry.key, "query") == 0) {
-				if (entry.type != DBUS_TYPE_ARRAY ||
-				    entry.array_type != DBUS_TYPE_BYTE)
-					goto error_clear;
-				wpabuf_free(query);
-				query = wpabuf_alloc_copy(
-					entry.bytearray_value,
-					entry.array_len);
-			} else
-				goto error_clear;
-
-			wpa_dbus_dict_entry_clear(&entry);
-		}
-
 		if (query == NULL)
 			goto error;
 
diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.h b/wpa_supplicant/dbus/dbus_new_handlers_p2p.h
index c4c0261..b3c45c1 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.h
+++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.h
@@ -114,6 +114,7 @@
 DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_ies);
 DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_device_address);
 DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_groups);
+DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_vsie);
 
 /*
  * P2P Group properties
diff --git a/wpa_supplicant/dbus/dbus_new_handlers_wps.c b/wpa_supplicant/dbus/dbus_new_handlers_wps.c
index f762b3f..19c1a61 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers_wps.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers_wps.c
@@ -286,8 +286,12 @@
 		ret = wpas_wps_start_pin(wpa_s, params.bssid,
 					 params.pin, 0,
 					 DEV_PW_DEFAULT);
-		if (ret > 0)
-			os_snprintf(npin, sizeof(npin), "%08d", ret);
+		if (ret > 0) {
+			ret = os_snprintf(npin, sizeof(npin), "%08d", ret);
+			if (os_snprintf_error(sizeof(npin), ret))
+				return wpas_dbus_error_unknown_error(
+					message, "invalid PIN");
+		}
 	} else {
 		ret = wpas_wps_start_pbc(wpa_s, params.bssid, 0);
 	}
diff --git a/wpa_supplicant/dbus/dbus_old_handlers_wps.c b/wpa_supplicant/dbus/dbus_old_handlers_wps.c
index 5309a53..987e12d 100644
--- a/wpa_supplicant/dbus/dbus_old_handlers_wps.c
+++ b/wpa_supplicant/dbus/dbus_old_handlers_wps.c
@@ -71,7 +71,7 @@
 	char *arg_bssid;
 	char *pin = NULL;
 	u8 bssid[ETH_ALEN], *_bssid = NULL;
-	int ret = 0;
+	int ret;
 	char npin[9];
 
 	if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg_bssid,
@@ -105,7 +105,11 @@
 		return NULL;
 
 	if (ret > 0) {
-		os_snprintf(npin, sizeof(npin), "%08d", ret);
+		ret = os_snprintf(npin, sizeof(npin), "%08d", ret);
+		if (os_snprintf_error(sizeof(npin), ret))
+			return wpas_dbus_new_invalid_opts_error(message,
+								"invalid PIN");
+
 		pin = npin;
 	}
 	dbus_message_append_args(reply, DBUS_TYPE_STRING, &pin,
diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig
index 08f5857..b51675b 100644
--- a/wpa_supplicant/defconfig
+++ b/wpa_supplicant/defconfig
@@ -44,7 +44,7 @@
 #CONFIG_LIBNL20=y
 
 # Use libnl 3.2 libraries (if this is selected, CONFIG_LIBNL20 is ignored)
-#CONFIG_LIBNL32=y
+CONFIG_LIBNL32=y
 
 
 # Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
@@ -301,6 +301,9 @@
 # Driver support is also needed for IEEE 802.11w.
 #CONFIG_IEEE80211W=y
 
+# Support Operating Channel Validation
+#CONFIG_OCV=y
+
 # Select TLS implementation
 # openssl = OpenSSL (default)
 # gnutls = GnuTLS
@@ -458,6 +461,11 @@
 # that meet the requirements described above.
 #CONFIG_NO_RANDOM_POOL=y
 
+# Should we attempt to use the getrandom(2) call that provides more reliable
+# yet secure randomness source than /dev/random on Linux 3.17 and newer.
+# Requires glibc 2.25 to build, falls back to /dev/random if unavailable.
+#CONFIG_GETRANDOM=y
+
 # IEEE 802.11n (High Throughput) support (mainly for AP mode)
 #CONFIG_IEEE80211N=y
 
@@ -561,8 +569,6 @@
 #CONFIG_MBO=y
 
 # Fast Initial Link Setup (FILS) (IEEE 802.11ai)
-# Note: This is an experimental and not yet complete implementation. This
-# should not be enabled for production use.
 #CONFIG_FILS=y
 # FILS shared key authentication with PFS
 #CONFIG_FILS_SK_PFS=y
diff --git a/wpa_supplicant/doc/docbook/eapol_test.sgml b/wpa_supplicant/doc/docbook/eapol_test.sgml
index 25cfd06..e7705ab 100644
--- a/wpa_supplicant/doc/docbook/eapol_test.sgml
+++ b/wpa_supplicant/doc/docbook/eapol_test.sgml
@@ -194,7 +194,7 @@
   </refsect1>
   <refsect1>
     <title>Legal</title>
-    <para>wpa_supplicant is copyright (c) 2003-2017,
+    <para>wpa_supplicant is copyright (c) 2003-2019,
     Jouni Malinen <email>j@w1.fi</email> and
     contributors.
     All Rights Reserved.</para>
diff --git a/wpa_supplicant/doc/docbook/wpa_background.sgml b/wpa_supplicant/doc/docbook/wpa_background.sgml
index fa94ae4..f6a0ca8 100644
--- a/wpa_supplicant/doc/docbook/wpa_background.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_background.sgml
@@ -90,7 +90,7 @@
 
   <refsect1>
     <title>Legal</title>
-    <para>wpa_supplicant is copyright (c) 2003-2017,
+    <para>wpa_supplicant is copyright (c) 2003-2019,
     Jouni Malinen <email>j@w1.fi</email> and
     contributors.
     All Rights Reserved.</para>
diff --git a/wpa_supplicant/doc/docbook/wpa_cli.sgml b/wpa_supplicant/doc/docbook/wpa_cli.sgml
index be3045a..dc7fee4 100644
--- a/wpa_supplicant/doc/docbook/wpa_cli.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_cli.sgml
@@ -345,7 +345,7 @@
   </refsect1>
   <refsect1>
     <title>Legal</title>
-    <para>wpa_supplicant is copyright (c) 2003-2017,
+    <para>wpa_supplicant is copyright (c) 2003-2019,
     Jouni Malinen <email>j@w1.fi</email> and
     contributors.
     All Rights Reserved.</para>
diff --git a/wpa_supplicant/doc/docbook/wpa_gui.sgml b/wpa_supplicant/doc/docbook/wpa_gui.sgml
index cee9ed6..31214e3 100644
--- a/wpa_supplicant/doc/docbook/wpa_gui.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_gui.sgml
@@ -91,7 +91,7 @@
   </refsect1>
   <refsect1>
     <title>Legal</title>
-    <para>wpa_supplicant is copyright (c) 2003-2017,
+    <para>wpa_supplicant is copyright (c) 2003-2019,
     Jouni Malinen <email>j@w1.fi</email> and
     contributors.
     All Rights Reserved.</para>
diff --git a/wpa_supplicant/doc/docbook/wpa_passphrase.sgml b/wpa_supplicant/doc/docbook/wpa_passphrase.sgml
index 6667a07..ed9baf1 100644
--- a/wpa_supplicant/doc/docbook/wpa_passphrase.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_passphrase.sgml
@@ -62,7 +62,7 @@
   </refsect1>
   <refsect1>
     <title>Legal</title>
-    <para>wpa_supplicant is copyright (c) 2003-2017,
+    <para>wpa_supplicant is copyright (c) 2003-2019,
     Jouni Malinen <email>j@w1.fi</email> and
     contributors.
     All Rights Reserved.</para>
diff --git a/wpa_supplicant/doc/docbook/wpa_priv.sgml b/wpa_supplicant/doc/docbook/wpa_priv.sgml
index 3796b93..dd44565 100644
--- a/wpa_supplicant/doc/docbook/wpa_priv.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_priv.sgml
@@ -137,7 +137,7 @@
   </refsect1>
   <refsect1>
     <title>Legal</title>
-    <para>wpa_supplicant is copyright (c) 2003-2017,
+    <para>wpa_supplicant is copyright (c) 2003-2019,
     Jouni Malinen <email>j@w1.fi</email> and
     contributors.
     All Rights Reserved.</para>
diff --git a/wpa_supplicant/doc/docbook/wpa_supplicant.sgml b/wpa_supplicant/doc/docbook/wpa_supplicant.sgml
index 80b3878..ebf102e 100644
--- a/wpa_supplicant/doc/docbook/wpa_supplicant.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_supplicant.sgml
@@ -246,9 +246,18 @@
 
     <variablelist>
       <varlistentry>
+	<term>nl80211</term>
+	<listitem>
+	  <para>Uses the modern Linux nl80211/cfg80211 netlink-based
+	  interface (most new drivers).</para>
+	</listitem>
+      </varlistentry>
+
+      <varlistentry>
 	<term>wext</term>
 	<listitem>
-	  <para>Linux wireless extensions (generic).</para>
+	  <para>Uses the legacy Linux wireless extensions ioctl-based
+	  interface (older hardware/drivers).</para>
 	</listitem>
       </varlistentry>
 
@@ -538,10 +547,14 @@
 
     <itemizedlist>
       <listitem>
-	<para>Linux kernel 2.4.x or 2.6.x with Linux Wireless
-	Extensions v15 or newer</para>
+	<para>Linux kernel 2.6.30 or higher with
+	nl80211/cfg80211 support</para>
       </listitem>
 
+      <listitem>
+	<para>Linux kernel 2.4.x or higher with Linux Wireless
+	Extensions v15 or newer</para>
+      </listitem>
 
       <listitem>
 	<para>FreeBSD 6-CURRENT</para>
@@ -558,6 +571,13 @@
     <title>Supported Drivers</title>
     <variablelist>
       <varlistentry>
+	<term>Linux nl80211/cfg80211</term>
+	<listitem>
+	  <para>This is the preferred driver for Linux.</para>
+	</listitem>
+      </varlistentry>
+
+      <varlistentry>
 	<term>Linux wireless extensions</term>
 	<listitem>
 	  <para>In theory, any driver that supports Linux wireless
@@ -729,7 +749,7 @@
   </refsect1>
   <refsect1>
     <title>Legal</title>
-    <para>wpa_supplicant is copyright (c) 2003-2017,
+    <para>wpa_supplicant is copyright (c) 2003-2019,
     Jouni Malinen <email>j@w1.fi</email> and
     contributors.
     All Rights Reserved.</para>
diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c
index 22ba902..8877f7a 100644
--- a/wpa_supplicant/dpp_supplicant.c
+++ b/wpa_supplicant/dpp_supplicant.c
@@ -529,9 +529,9 @@
 }
 
 
-static void wpas_dpp_set_configurator(struct wpa_supplicant *wpa_s,
-				      struct dpp_authentication *auth,
-				      const char *cmd)
+static int wpas_dpp_set_configurator(struct wpa_supplicant *wpa_s,
+				     struct dpp_authentication *auth,
+				     const char *cmd)
 {
 	const char *pos, *end;
 	struct dpp_configuration *conf_sta = NULL, *conf_ap = NULL;
@@ -545,7 +545,7 @@
 	char *group_id = NULL;
 
 	if (!cmd)
-		return;
+		return 0;
 
 	wpa_printf(MSG_DEBUG, "DPP: Set configurator parameters: %s", cmd);
 	pos = os_strstr(cmd, " ssid=");
@@ -609,10 +609,12 @@
 				conf_sta->akm = DPP_AKM_PSK;
 			if (psk_set) {
 				os_memcpy(conf_sta->psk, psk, PMK_LEN);
-			} else {
+			} else if (pass_len > 0) {
 				conf_sta->passphrase = os_strdup(pass);
 				if (!conf_sta->passphrase)
 					goto fail;
+			} else {
+				goto fail;
 			}
 		} else if (os_strstr(cmd, " conf=sta-dpp")) {
 			conf_sta->akm = DPP_AKM_DPP;
@@ -686,13 +688,14 @@
 	auth->conf_ap = conf_ap;
 	auth->conf = conf;
 	os_free(group_id);
-	return;
+	return 0;
 
 fail:
-	wpa_printf(MSG_DEBUG, "DPP: Failed to set configurator parameters");
+	wpa_msg(wpa_s, MSG_INFO, "DPP: Failed to set configurator parameters");
 	dpp_configuration_free(conf_sta);
 	dpp_configuration_free(conf_ap);
 	os_free(group_id);
+	return -1;
 }
 
 
@@ -872,7 +875,11 @@
 	if (!wpa_s->dpp_auth)
 		goto fail;
 	wpas_dpp_set_testing_options(wpa_s, wpa_s->dpp_auth);
-	wpas_dpp_set_configurator(wpa_s, wpa_s->dpp_auth, cmd);
+	if (wpas_dpp_set_configurator(wpa_s, wpa_s->dpp_auth, cmd) < 0) {
+		dpp_auth_deinit(wpa_s->dpp_auth);
+		wpa_s->dpp_auth = NULL;
+		goto fail;
+	}
 
 	wpa_s->dpp_auth->neg_freq = neg_freq;
 
@@ -938,6 +945,7 @@
 		wpa_printf(MSG_DEBUG,
 			   "DPP: Failed to request the driver to remain on channel (%u MHz) for listen",
 			   lwork->freq);
+		wpa_s->dpp_listen_freq = 0;
 		wpas_dpp_listen_work_done(wpa_s);
 		wpa_s->dpp_pending_listen_freq = 0;
 		return;
@@ -1018,29 +1026,6 @@
 }
 
 
-void wpas_dpp_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
-				   unsigned int freq)
-{
-	if (!wpa_s->dpp_listen_freq && !wpa_s->dpp_pending_listen_freq)
-		return;
-
-	wpa_printf(MSG_DEBUG,
-		   "DPP: remain-on-channel callback (off_channel_freq=%u dpp_pending_listen_freq=%d roc_waiting_drv_freq=%d freq=%u)",
-		   wpa_s->off_channel_freq, wpa_s->dpp_pending_listen_freq,
-		   wpa_s->roc_waiting_drv_freq, freq);
-	if (wpa_s->off_channel_freq &&
-	    wpa_s->off_channel_freq == wpa_s->dpp_pending_listen_freq) {
-		wpa_printf(MSG_DEBUG, "DPP: Listen on %u MHz started", freq);
-		wpa_s->dpp_pending_listen_freq = 0;
-	} else {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Ignore remain-on-channel callback (off_channel_freq=%u dpp_pending_listen_freq=%d freq=%u)",
-			   wpa_s->off_channel_freq,
-			   wpa_s->dpp_pending_listen_freq, freq);
-	}
-}
-
-
 void wpas_dpp_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
 					  unsigned int freq)
 {
@@ -1145,8 +1130,12 @@
 		return;
 	}
 	wpas_dpp_set_testing_options(wpa_s, wpa_s->dpp_auth);
-	wpas_dpp_set_configurator(wpa_s, wpa_s->dpp_auth,
-				  wpa_s->dpp_configurator_params);
+	if (wpas_dpp_set_configurator(wpa_s, wpa_s->dpp_auth,
+				      wpa_s->dpp_configurator_params) < 0) {
+		dpp_auth_deinit(wpa_s->dpp_auth);
+		wpa_s->dpp_auth = NULL;
+		return;
+	}
 	os_memcpy(wpa_s->dpp_auth->peer_mac_addr, src, ETH_ALEN);
 
 	if (wpa_s->dpp_listen_freq &&
@@ -1353,7 +1342,8 @@
 		wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
 		return;
 	}
-	if (!resp || status_code != WLAN_STATUS_SUCCESS) {
+	if (result != GAS_QUERY_SUCCESS ||
+	    !resp || status_code != WLAN_STATUS_SUCCESS) {
 		wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed");
 		goto fail;
 	}
@@ -2303,9 +2293,9 @@
 		return -1;
 
 	curve = get_param(cmd, " curve=");
-	wpas_dpp_set_configurator(wpa_s, auth, cmd);
-
-	if (dpp_configurator_own_config(auth, curve, 0) == 0) {
+	wpas_dpp_set_testing_options(wpa_s, auth);
+	if (wpas_dpp_set_configurator(wpa_s, auth, cmd) == 0 &&
+	    dpp_configurator_own_config(auth, curve, 0) == 0) {
 		wpas_dpp_handle_config_obj(wpa_s, auth);
 		ret = 0;
 	}
diff --git a/wpa_supplicant/dpp_supplicant.h b/wpa_supplicant/dpp_supplicant.h
index 9b539df..5a4f06e 100644
--- a/wpa_supplicant/dpp_supplicant.h
+++ b/wpa_supplicant/dpp_supplicant.h
@@ -19,8 +19,6 @@
 int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd);
 int wpas_dpp_listen(struct wpa_supplicant *wpa_s, const char *cmd);
 void wpas_dpp_listen_stop(struct wpa_supplicant *wpa_s);
-void wpas_dpp_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
-				   unsigned int freq);
 void wpas_dpp_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
 					  unsigned int freq);
 void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index 078de23..4a9f472 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -492,6 +492,14 @@
 	return -1;
 }
 
+static inline int wpa_drv_channel_info(struct wpa_supplicant *wpa_s,
+				       struct wpa_channel_info *ci)
+{
+	if (wpa_s->driver->channel_info)
+		return wpa_s->driver->channel_info(wpa_s->drv_priv, ci);
+	return -1;
+}
+
 static inline int wpa_drv_pktcnt_poll(struct wpa_supplicant *wpa_s,
 				      struct hostap_sta_driver_data *sta)
 {
@@ -796,6 +804,14 @@
 	return wpa_s->driver->set_transmit_next_pn(wpa_s->drv_priv, sa);
 }
 
+static inline int wpa_drv_set_receive_lowest_pn(struct wpa_supplicant *wpa_s,
+						struct receive_sa *sa)
+{
+	if (!wpa_s->driver->set_receive_lowest_pn)
+		return -1;
+	return wpa_s->driver->set_receive_lowest_pn(wpa_s->drv_priv, sa);
+}
+
 static inline int
 wpa_drv_create_receive_sc(struct wpa_supplicant *wpa_s, struct receive_sc *sc,
 			  unsigned int conf_offset, int validation)
@@ -1046,4 +1062,12 @@
 							params);
 }
 
+static inline int wpa_drv_set_4addr_mode(struct wpa_supplicant *wpa_s, int val)
+{
+	if (!wpa_s->driver->set_4addr_mode)
+		return -1;
+	return wpa_s->driver->set_4addr_mode(wpa_s->drv_priv,
+					     wpa_s->bridge_ifname, val);
+}
+
 #endif /* DRIVER_I_H */
diff --git a/wpa_supplicant/eapol_test.c b/wpa_supplicant/eapol_test.c
index 6548bd1..3fd4ce6 100644
--- a/wpa_supplicant/eapol_test.c
+++ b/wpa_supplicant/eapol_test.c
@@ -711,7 +711,8 @@
 
 	eap = (struct eap_hdr *) (hdr + 1);
 	eap->code = EAP_CODE_REQUEST;
-	eap->identifier = 0;
+	if (os_get_random((u8 *) &eap->identifier, sizeof(eap->identifier)) < 0)
+		eap->identifier = os_random() & 0xff;
 	eap->length = htons(5);
 	pos = (u8 *) (eap + 1);
 	*pos = EAP_TYPE_IDENTITY;
diff --git a/wpa_supplicant/eapol_test.py b/wpa_supplicant/eapol_test.py
index 80e7dfc..734428d 100644
--- a/wpa_supplicant/eapol_test.py
+++ b/wpa_supplicant/eapol_test.py
@@ -136,7 +136,7 @@
             results = res[i].get(False)
         except:
             results = "N/A"
-        print "%d: %s" % (i, results)
+        print("%d: %s" % (i, results))
 
 if __name__ == "__main__":
     main()
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index ef28ffe..8ede2bb 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -293,6 +293,13 @@
 	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
 		return;
 
+	if (os_reltime_initialized(&wpa_s->session_start)) {
+		os_reltime_age(&wpa_s->session_start, &wpa_s->session_length);
+		wpa_s->session_start.sec = 0;
+		wpa_s->session_start.usec = 0;
+		wpas_notify_session_length(wpa_s);
+	}
+
 	wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
 	bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
 	os_memset(wpa_s->bssid, 0, ETH_ALEN);
@@ -324,6 +331,9 @@
 	os_memset(wpa_s->last_tk, 0, sizeof(wpa_s->last_tk));
 #endif /* CONFIG_TESTING_OPTIONS */
 	wpa_s->ieee80211ac = 0;
+
+	if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
+		wpa_s->enabled_4addr_mode = 0;
 }
 
 
@@ -1335,10 +1345,10 @@
 			continue;
 		}
 
-		if (wpa_is_bss_tmp_disallowed(wpa_s, bss->bssid)) {
+		if (wpa_is_bss_tmp_disallowed(wpa_s, bss)) {
 			if (debug_print)
 				wpa_dbg(wpa_s, MSG_DEBUG,
-					"   skip - MBO retry delay has not passed yet");
+					"   skip - AP temporarily disallowed");
 			continue;
 		}
 #ifdef CONFIG_TESTING_OPTIONS
@@ -2267,6 +2277,50 @@
 #endif /* CONFIG_INTERWORKING */
 
 
+static void multi_ap_process_assoc_resp(struct wpa_supplicant *wpa_s,
+					const u8 *ies, size_t ies_len)
+{
+	struct ieee802_11_elems elems;
+	const u8 *map_sub_elem, *pos;
+	size_t len;
+
+	if (!wpa_s->current_ssid ||
+	    !wpa_s->current_ssid->multi_ap_backhaul_sta ||
+	    !ies ||
+	    ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed)
+		return;
+
+	if (!elems.multi_ap || elems.multi_ap_len < 7) {
+		wpa_printf(MSG_INFO, "AP doesn't support Multi-AP protocol");
+		goto fail;
+	}
+
+	pos = elems.multi_ap + 4;
+	len = elems.multi_ap_len - 4;
+
+	map_sub_elem = get_ie(pos, len, MULTI_AP_SUB_ELEM_TYPE);
+	if (!map_sub_elem || map_sub_elem[1] < 1) {
+		wpa_printf(MSG_INFO, "invalid Multi-AP sub elem type");
+		goto fail;
+	}
+
+	if (!(map_sub_elem[2] & MULTI_AP_BACKHAUL_BSS)) {
+		wpa_printf(MSG_INFO, "AP doesn't support backhaul BSS");
+		goto fail;
+	}
+
+	if (wpa_drv_set_4addr_mode(wpa_s, 1) < 0) {
+		wpa_printf(MSG_ERROR, "Failed to set 4addr mode");
+		goto fail;
+	}
+	wpa_s->enabled_4addr_mode = 1;
+	return;
+
+fail:
+	wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
+}
+
+
 #ifdef CONFIG_FST
 static int wpas_fst_update_mbie(struct wpa_supplicant *wpa_s,
 				const u8 *ie, size_t ie_len)
@@ -2343,6 +2397,9 @@
 		    get_ie(data->assoc_info.resp_ies,
 			   data->assoc_info.resp_ies_len, WLAN_EID_VHT_CAP))
 			wpa_s->ieee80211ac = 1;
+
+		multi_ap_process_assoc_resp(wpa_s, data->assoc_info.resp_ies,
+					    data->assoc_info.resp_ies_len);
 	}
 	if (data->assoc_info.beacon_ies)
 		wpa_hexdump(MSG_DEBUG, "beacon_ies",
@@ -2648,6 +2705,16 @@
 
 	wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATED);
 	if (os_memcmp(bssid, wpa_s->bssid, ETH_ALEN) != 0) {
+		if (os_reltime_initialized(&wpa_s->session_start)) {
+			os_reltime_age(&wpa_s->session_start,
+				       &wpa_s->session_length);
+			wpa_s->session_start.sec = 0;
+			wpa_s->session_start.usec = 0;
+			wpas_notify_session_length(wpa_s);
+		} else {
+			wpas_notify_auth_changed(wpa_s);
+			os_get_reltime(&wpa_s->session_start);
+		}
 		wpa_dbg(wpa_s, MSG_DEBUG, "Associated to a new BSS: BSSID="
 			MACSTR, MAC2STR(bssid));
 		new_bss = 1;
@@ -2738,7 +2805,7 @@
 	}
 	wpa_supplicant_cancel_scan(wpa_s);
 
-	if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
+	if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
 	    wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
 		/*
 		 * We are done; the driver will take care of RSN 4-way
@@ -2748,7 +2815,7 @@
 		wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
 		eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
 		eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
-	} else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
+	} else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
 		   wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
 		/*
 		 * The driver will take care of RSN 4-way handshake, so we need
@@ -3010,7 +3077,7 @@
 	    !disallowed_ssid(wpa_s, fast_reconnect->ssid,
 			     fast_reconnect->ssid_len) &&
 	    !wpas_temp_disabled(wpa_s, fast_reconnect_ssid) &&
-	    !wpa_is_bss_tmp_disallowed(wpa_s, fast_reconnect->bssid)) {
+	    !wpa_is_bss_tmp_disallowed(wpa_s, fast_reconnect)) {
 #ifndef CONFIG_NO_SCAN_PROCESSING
 		wpa_dbg(wpa_s, MSG_DEBUG, "Try to reconnect to the same BSS");
 		if (wpa_supplicant_connect(wpa_s, fast_reconnect,
@@ -3583,8 +3650,8 @@
 }
 
 
-static void wpa_supplicant_update_channel_list(
-	struct wpa_supplicant *wpa_s, struct channel_list_changed *info)
+void wpa_supplicant_update_channel_list(struct wpa_supplicant *wpa_s,
+					struct channel_list_changed *info)
 {
 	struct wpa_supplicant *ifs;
 	u8 dfs_domain;
@@ -3598,10 +3665,13 @@
 	for (ifs = wpa_s; ifs->parent && ifs != ifs->parent; ifs = ifs->parent)
 		;
 
-	wpa_msg(ifs, MSG_INFO, WPA_EVENT_REGDOM_CHANGE "init=%s type=%s%s%s",
-		reg_init_str(info->initiator), reg_type_str(info->type),
-		info->alpha2[0] ? " alpha2=" : "",
-		info->alpha2[0] ? info->alpha2 : "");
+	if (info) {
+		wpa_msg(ifs, MSG_INFO,
+			WPA_EVENT_REGDOM_CHANGE "init=%s type=%s%s%s",
+			reg_init_str(info->initiator), reg_type_str(info->type),
+			info->alpha2[0] ? " alpha2=" : "",
+			info->alpha2[0] ? info->alpha2 : "");
+	}
 
 	if (wpa_s->drv_priv == NULL)
 		return; /* Ignore event during drv initialization */
@@ -3840,7 +3910,7 @@
 				       struct dfs_event *radar)
 {
 #if defined(NEED_AP_MLME) && defined(CONFIG_AP)
-	if (wpa_s->ap_iface) {
+	if (wpa_s->ap_iface || wpa_s->ifmsh) {
 		wpas_ap_event_dfs_cac_started(wpa_s, radar);
 	} else
 #endif /* NEED_AP_MLME && CONFIG_AP */
@@ -3861,7 +3931,7 @@
 					struct dfs_event *radar)
 {
 #if defined(NEED_AP_MLME) && defined(CONFIG_AP)
-	if (wpa_s->ap_iface) {
+	if (wpa_s->ap_iface || wpa_s->ifmsh) {
 		wpas_ap_event_dfs_cac_finished(wpa_s, radar);
 	} else
 #endif /* NEED_AP_MLME && CONFIG_AP */
@@ -3877,7 +3947,7 @@
 				       struct dfs_event *radar)
 {
 #if defined(NEED_AP_MLME) && defined(CONFIG_AP)
-	if (wpa_s->ap_iface) {
+	if (wpa_s->ap_iface || wpa_s->ifmsh) {
 		wpas_ap_event_dfs_cac_aborted(wpa_s, radar);
 	} else
 #endif /* NEED_AP_MLME && CONFIG_AP */
@@ -3985,6 +4055,32 @@
 	}
 #endif /* CONFIG_OWE */
 
+#ifdef CONFIG_MBO
+	if (data->assoc_reject.status_code ==
+	    WLAN_STATUS_DENIED_POOR_CHANNEL_CONDITIONS &&
+	    wpa_s->current_bss && data->assoc_reject.bssid &&
+	    data->assoc_reject.resp_ies) {
+		const u8 *rssi_rej;
+
+		rssi_rej = mbo_get_attr_from_ies(
+			data->assoc_reject.resp_ies,
+			data->assoc_reject.resp_ies_len,
+			OCE_ATTR_ID_RSSI_BASED_ASSOC_REJECT);
+		if (rssi_rej && rssi_rej[1] == 2) {
+			wpa_printf(MSG_DEBUG,
+				   "OCE: RSSI-based association rejection from "
+				   MACSTR " (Delta RSSI: %u, Retry Delay: %u)",
+				   MAC2STR(data->assoc_reject.bssid),
+				   rssi_rej[2], rssi_rej[3]);
+			wpa_bss_tmp_disallow(wpa_s,
+					     data->assoc_reject.bssid,
+					     rssi_rej[3],
+					     rssi_rej[2] +
+					     wpa_s->current_bss->level);
+		}
+	}
+#endif /* CONFIG_MBO */
+
 	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) {
 		sme_event_assoc_reject(wpa_s, data);
 		return;
@@ -4032,6 +4128,9 @@
 {
 	struct wpa_supplicant *wpa_s = ctx;
 	int resched;
+#ifndef CONFIG_NO_STDOUT_DEBUG
+	int level = MSG_DEBUG;
+#endif /* CONFIG_NO_STDOUT_DEBUG */
 
 	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED &&
 	    event != EVENT_INTERFACE_ENABLED &&
@@ -4045,9 +4144,6 @@
 	}
 
 #ifndef CONFIG_NO_STDOUT_DEBUG
-{
-	int level = MSG_DEBUG;
-
 	if (event == EVENT_RX_MGMT && data->rx_mgmt.frame_len >= 24) {
 		const struct ieee80211_hdr *hdr;
 		u16 fc;
@@ -4060,7 +4156,6 @@
 
 	wpa_dbg(wpa_s, level, "Event %s (%d) received",
 		event_to_string(event), event);
-}
 #endif /* CONFIG_NO_STDOUT_DEBUG */
 
 	switch (event) {
@@ -4072,6 +4167,8 @@
 				   "FST: MB IEs updated from auth IE");
 #endif /* CONFIG_FST */
 		sme_event_auth(wpa_s, data);
+		wpa_s->auth_status_code = data->auth.status_code;
+		wpas_notify_auth_status_code(wpa_s);
 		break;
 	case EVENT_ASSOC:
 #ifdef CONFIG_TESTING_OPTIONS
@@ -4087,6 +4184,7 @@
 		}
 #endif /* CONFIG_TESTING_OPTIONS */
 		wpa_supplicant_event_assoc(wpa_s, data);
+		wpa_s->assoc_status_code = WLAN_STATUS_SUCCESS;
 		if (data &&
 		    (data->assoc_info.authorized ||
 		     (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
@@ -4329,6 +4427,7 @@
 #ifdef CONFIG_AP
 		if (wpa_s->current_ssid->mode == WPAS_MODE_AP ||
 		    wpa_s->current_ssid->mode == WPAS_MODE_P2P_GO ||
+		    wpa_s->current_ssid->mode == WPAS_MODE_MESH ||
 		    wpa_s->current_ssid->mode ==
 		    WPAS_MODE_P2P_GROUP_FORMATION) {
 			wpas_ap_ch_switch(wpa_s, data->ch_switch.freq,
@@ -4340,6 +4439,9 @@
 		}
 #endif /* CONFIG_AP */
 
+#ifdef CONFIG_IEEE80211W
+		sme_event_ch_switch(wpa_s);
+#endif /* CONFIG_IEEE80211W */
 		wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_CS);
 		wnm_clear_coloc_intf_reporting(wpa_s);
 		break;
diff --git a/wpa_supplicant/examples/dbus-listen-preq.py b/wpa_supplicant/examples/dbus-listen-preq.py
index 5ac9859..337519f 100755
--- a/wpa_supplicant/examples/dbus-listen-preq.py
+++ b/wpa_supplicant/examples/dbus-listen-preq.py
@@ -1,5 +1,6 @@
 #!/usr/bin/python
 
+from __future__ import print_function
 import dbus
 import sys
 import time
@@ -12,21 +13,24 @@
 WPAS_DBUS_INTERFACES_INTERFACE = "fi.w1.wpa_supplicant1.Interface"
 
 def usage():
-	print "Usage: %s <ifname>" % sys.argv[0]
-	print "Press Ctrl-C to stop"
+	print("Usage: %s <ifname>" % sys.argv[0])
+	print("Press Ctrl-C to stop")
 
 def ProbeRequest(args):
 	if 'addr' in args:
-		print '%.2x:%.2x:%.2x:%.2x:%.2x:%.2x' % tuple(args['addr']),
+		print('%.2x:%.2x:%.2x:%.2x:%.2x:%.2x' % tuple(args['addr']),
+                      end=' ')
 	if 'dst' in args:
-		print '-> %.2x:%.2x:%.2x:%.2x:%.2x:%.2x' % tuple(args['dst']),
+		print('-> %.2x:%.2x:%.2x:%.2x:%.2x:%.2x' % tuple(args['dst']),
+                      end=' ')
 	if 'bssid' in args:
-		print '(bssid %.2x:%.2x:%.2x:%.2x:%.2x:%.2x)' % tuple(args['dst']),
+		print('(bssid %.2x:%.2x:%.2x:%.2x:%.2x:%.2x)' % tuple(args['dst']),
+                      end=' ')
 	if 'signal' in args:
-		print 'signal:%d' % args['signal'],
+		print('signal:%d' % args['signal'], end=' ')
 	if 'ies' in args:
-		print 'have IEs (%d bytes)' % len(args['ies']),
-        print ''
+		print('have IEs (%d bytes)' % len(args['ies']), end=' ')
+        print('')
 
 if __name__ == "__main__":
 	global bus
diff --git a/wpa_supplicant/examples/dpp-qrcode.py b/wpa_supplicant/examples/dpp-qrcode.py
index e2a00c9..b468d15 100644
--- a/wpa_supplicant/examples/dpp-qrcode.py
+++ b/wpa_supplicant/examples/dpp-qrcode.py
@@ -24,19 +24,19 @@
     if os.path.isdir(wpas_ctrl):
         try:
             ifaces = [os.path.join(wpas_ctrl, i) for i in os.listdir(wpas_ctrl)]
-        except OSError, error:
-            print "Could not find wpa_supplicant: ", error
+        except OSError as error:
+            print("Could not find wpa_supplicant: ", error)
             return None
 
     if len(ifaces) < 1:
-        print "No wpa_supplicant control interface found"
+        print("No wpa_supplicant control interface found")
         return None
 
     for ctrl in ifaces:
         try:
             wpas = wpaspy.Ctrl(ctrl)
             return wpas
-        except Exception, e:
+        except Exception as e:
             pass
     return None
 
@@ -55,27 +55,27 @@
             continue
         if not uri.startswith('DPP:'):
             continue
-        print "Found DPP bootstrap info URI:"
-        print uri
+        print("Found DPP bootstrap info URI:")
+        print(uri)
         wpas = wpas_connect()
         if not wpas:
-            print "Could not connect to wpa_supplicant"
-            print
+            print("Could not connect to wpa_supplicant")
+            print('')
             continue
         res = wpas.request("DPP_QR_CODE " + uri);
         try:
             id = int(res)
         except ValueError:
-            print "QR Code URI rejected"
+            print("QR Code URI rejected")
             continue
-        print "QR Code URI accepted - ID=%d" % id
-        print wpas.request("DPP_BOOTSTRAP_INFO %d" % id)
+        print("QR Code URI accepted - ID=%d" % id)
+        print(wpas.request("DPP_BOOTSTRAP_INFO %d" % id))
         del wpas
 
 def dpp_display(curve):
         wpas = wpas_connect()
         if not wpas:
-            print "Could not connect to wpa_supplicant"
+            print("Could not connect to wpa_supplicant")
             return
         res = wpas.request("STATUS")
         addr = None
@@ -93,18 +93,18 @@
         try:
             id = int(res)
         except ValueError:
-            print "Failed to generate bootstrap info URI"
+            print("Failed to generate bootstrap info URI")
             return
-        print "Bootstrap information - ID=%d" % id
-        print wpas.request("DPP_BOOTSTRAP_INFO %d" % id)
+        print("Bootstrap information - ID=%d" % id)
+        print(wpas.request("DPP_BOOTSTRAP_INFO %d" % id))
         uri = wpas.request("DPP_BOOTSTRAP_GET_URI %d" % id)
-        print uri
-        print "ID=%d" % id
+        print(uri)
+        print("ID=%d" % id)
         qr = qrcode.QRCode(error_correction=qrcode.constants.ERROR_CORRECT_M,
                            border=3)
         qr.add_data(uri, optimize=5)
         qr.print_ascii(tty=True)
-        print "ID=%d" % id
+        print("ID=%d" % id)
         del wpas
 
 def main():
diff --git a/wpa_supplicant/examples/p2p-nfc.py b/wpa_supplicant/examples/p2p-nfc.py
index 91eba28..889ac8b 100644
--- a/wpa_supplicant/examples/p2p-nfc.py
+++ b/wpa_supplicant/examples/p2p-nfc.py
@@ -37,7 +37,7 @@
 success_file = None
 
 def summary(txt):
-    print txt
+    print(txt)
     if summary_file:
         with open(summary_file, 'a') as f:
             f.write(txt + "\n")
@@ -53,12 +53,12 @@
     if os.path.isdir(wpas_ctrl):
         try:
             ifaces = [os.path.join(wpas_ctrl, i) for i in os.listdir(wpas_ctrl)]
-        except OSError, error:
-            print "Could not find wpa_supplicant: ", error
+        except OSError as error:
+            print("Could not find wpa_supplicant: ", error)
             return None
 
     if len(ifaces) < 1:
-        print "No wpa_supplicant control interface found"
+        print("No wpa_supplicant control interface found")
         return None
 
     for ctrl in ifaces:
@@ -66,10 +66,10 @@
             if ifname not in ctrl:
                 continue
         try:
-            print "Trying to use control interface " + ctrl
+            print("Trying to use control interface " + ctrl)
             wpas = wpaspy.Ctrl(ctrl)
             return wpas
-        except Exception, e:
+        except Exception as e:
             pass
     return None
 
@@ -160,30 +160,30 @@
         if (data == None):
             summary("Could not get handover request carrier record from wpa_supplicant")
             return
-        print "Handover request carrier record from wpa_supplicant: " + data.encode("hex")
+        print("Handover request carrier record from wpa_supplicant: " + data.encode("hex"))
         datamsg = nfc.ndef.Message(data)
         message.add_carrier(datamsg[0], "active", datamsg[1:])
 
     global include_wps_req
     if include_wps_req:
-        print "Handover request (pre-WPS):"
+        print("Handover request (pre-WPS):")
         try:
-            print message.pretty()
-        except Exception, e:
-            print e
+            print(message.pretty())
+        except Exception as e:
+            print(e)
 
         data = wpas_get_handover_req_wps()
         if data:
-            print "Add WPS request in addition to P2P"
+            print("Add WPS request in addition to P2P")
             datamsg = nfc.ndef.Message(data)
             message.add_carrier(datamsg[0], "active", datamsg[1:])
 
-    print "Handover request:"
+    print("Handover request:")
     try:
-        print message.pretty()
-    except Exception, e:
-        print e
-    print str(message).encode("hex")
+        print(message.pretty())
+    except Exception as e:
+        print(e)
+    print(str(message).encode("hex"))
 
     client = nfc.handover.HandoverClient(llc)
     try:
@@ -194,7 +194,7 @@
         summary("Handover connection refused")
         client.close()
         return
-    except Exception, e:
+    except Exception as e:
         summary("Other exception: " + str(e))
         client.close()
         return
@@ -217,41 +217,41 @@
         client.close()
         return
 
-    print "Received message"
+    print("Received message")
     try:
-        print message.pretty()
-    except Exception, e:
-        print e
-    print str(message).encode("hex")
+        print(message.pretty())
+    except Exception as e:
+        print(e)
+    print(str(message).encode("hex"))
     message = nfc.ndef.HandoverSelectMessage(message)
     summary("Handover select received")
     try:
-        print message.pretty()
-    except Exception, e:
-        print e
+        print(message.pretty())
+    except Exception as e:
+        print(e)
 
     for carrier in message.carriers:
-        print "Remote carrier type: " + carrier.type
+        print("Remote carrier type: " + carrier.type)
         if carrier.type == "application/vnd.wfa.p2p":
-            print "P2P carrier type match - send to wpa_supplicant"
+            print("P2P carrier type match - send to wpa_supplicant")
             if "OK" in wpas_report_handover(data, carrier.record, "INIT"):
                 success_report("P2P handover reported successfully (initiator)")
             else:
                 summary("P2P handover report rejected")
             break
 
-    print "Remove peer"
+    print("Remove peer")
     client.close()
-    print "Done with handover"
+    print("Done with handover")
     global only_one
     if only_one:
-        print "only_one -> stop loop"
+        print("only_one -> stop loop")
         global continue_loop
         continue_loop = False
 
     global no_wait
     if no_wait:
-        print "Trying to exit.."
+        print("Trying to exit..")
         global terminate_now
         terminate_now = True
 
@@ -283,33 +283,33 @@
     def process_request(self, request):
         self.ho_server_processing = True
         clear_raw_mode()
-        print "HandoverServer - request received"
+        print("HandoverServer - request received")
         try:
-            print "Parsed handover request: " + request.pretty()
-        except Exception, e:
-            print e
+            print("Parsed handover request: " + request.pretty())
+        except Exception as e:
+            print(e)
 
         sel = nfc.ndef.HandoverSelectMessage(version="1.2")
 
         found = False
 
         for carrier in request.carriers:
-            print "Remote carrier type: " + carrier.type
+            print("Remote carrier type: " + carrier.type)
             if carrier.type == "application/vnd.wfa.p2p":
-                print "P2P carrier type match - add P2P carrier record"
+                print("P2P carrier type match - add P2P carrier record")
                 found = True
                 self.received_carrier = carrier.record
-                print "Carrier record:"
+                print("Carrier record:")
                 try:
-                    print carrier.record.pretty()
-                except Exception, e:
-                    print e
+                    print(carrier.record.pretty())
+                except Exception as e:
+                    print(e)
                 data = wpas_get_handover_sel()
                 if data is None:
-                    print "Could not get handover select carrier record from wpa_supplicant"
+                    print("Could not get handover select carrier record from wpa_supplicant")
                     continue
-                print "Handover select carrier record from wpa_supplicant:"
-                print data.encode("hex")
+                print("Handover select carrier record from wpa_supplicant:")
+                print(data.encode("hex"))
                 self.sent_carrier = data
                 if "OK" in wpas_report_handover(self.received_carrier, self.sent_carrier, "RESP"):
                     success_report("P2P handover reported successfully (responder)")
@@ -324,22 +324,22 @@
         for carrier in request.carriers:
             if found:
                 break
-            print "Remote carrier type: " + carrier.type
+            print("Remote carrier type: " + carrier.type)
             if carrier.type == "application/vnd.wfa.wsc":
-                print "WSC carrier type match - add WSC carrier record"
+                print("WSC carrier type match - add WSC carrier record")
                 found = True
                 self.received_carrier = carrier.record
-                print "Carrier record:"
+                print("Carrier record:")
                 try:
-                    print carrier.record.pretty()
-                except Exception, e:
-                    print e
+                    print(carrier.record.pretty())
+                except Exception as e:
+                    print(e)
                 data = wpas_get_handover_sel_wps()
                 if data is None:
-                    print "Could not get handover select carrier record from wpa_supplicant"
+                    print("Could not get handover select carrier record from wpa_supplicant")
                     continue
-                print "Handover select carrier record from wpa_supplicant:"
-                print data.encode("hex")
+                print("Handover select carrier record from wpa_supplicant:")
+                print(data.encode("hex"))
                 self.sent_carrier = data
                 if "OK" in wpas_report_handover_wsc(self.received_carrier, self.sent_carrier, "RESP"):
                     success_report("WSC handover reported successfully")
@@ -352,12 +352,12 @@
                 found = True
                 break
 
-        print "Handover select:"
+        print("Handover select:")
         try:
-            print sel.pretty()
-        except Exception, e:
-            print e
-        print str(sel).encode("hex")
+            print(sel.pretty())
+        except Exception as e:
+            print(e)
+        print(str(sel).encode("hex"))
 
         summary("Sending handover select")
         self.success = True
@@ -396,7 +396,7 @@
     success = False
     if len(tag.ndef.message):
         for record in tag.ndef.message:
-            print "record type " + record.type
+            print("record type " + record.type)
             if record.type == "application/vnd.wfa.wsc":
                 summary("WPS tag - send to wpa_supplicant")
                 success = wpas_tag_read(tag.ndef.message)
@@ -419,7 +419,7 @@
     global p2p_sel_data
     tag.ndef.message = str(p2p_sel_data)
     success_report("Tag write succeeded")
-    print "Done - remove tag"
+    print("Done - remove tag")
     global only_one
     if only_one:
         global continue_loop
@@ -428,7 +428,7 @@
     return p2p_sel_wait_remove
 
 def wps_write_p2p_handover_sel(clf, wait_remove=True):
-    print "Write P2P handover select"
+    print("Write P2P handover select")
     data = wpas_get_handover_sel(tag=True)
     if (data == None):
         summary("Could not get P2P handover select from wpa_supplicant")
@@ -440,14 +440,14 @@
     p2p_sel_data = nfc.ndef.HandoverSelectMessage(version="1.2")
     message = nfc.ndef.Message(data);
     p2p_sel_data.add_carrier(message[0], "active", message[1:])
-    print "Handover select:"
+    print("Handover select:")
     try:
-        print p2p_sel_data.pretty()
-    except Exception, e:
-        print e
-    print str(p2p_sel_data).encode("hex")
+        print(p2p_sel_data.pretty())
+    except Exception as e:
+        print(e)
+    print(str(p2p_sel_data).encode("hex"))
 
-    print "Touch an NFC tag"
+    print("Touch an NFC tag")
     clf.connect(rdwr={'on-connect': rdwr_connected_p2p_write})
 
 
@@ -456,11 +456,11 @@
     summary("Tag connected: " + str(tag))
 
     if tag.ndef:
-        print "NDEF tag: " + tag.type
+        print("NDEF tag: " + tag.type)
         try:
-            print tag.ndef.message.pretty()
-        except Exception, e:
-            print e
+            print(tag.ndef.message.pretty())
+        except Exception as e:
+            print(e)
         success = p2p_tag_read(tag)
         if only_one and success:
             global continue_loop
@@ -475,15 +475,15 @@
 def llcp_worker(llc):
     global init_on_touch
     if init_on_touch:
-            print "Starting handover client"
+            print("Starting handover client")
             p2p_handover_client(llc)
             return
 
     global no_input
     if no_input:
-        print "Wait for handover to complete"
+        print("Wait for handover to complete")
     else:
-        print "Wait for handover to complete - press 'i' to initiate ('w' for WPS only, 'p' for P2P only)"
+        print("Wait for handover to complete - press 'i' to initiate ('w' for WPS only, 'p' for P2P only)")
     global srv
     global wait_connection
     while not wait_connection and srv.sent_carrier is None:
@@ -506,21 +506,21 @@
             else:
                 continue
             clear_raw_mode()
-            print "Starting handover client"
+            print("Starting handover client")
             p2p_handover_client(llc)
             return
             
     clear_raw_mode()
-    print "Exiting llcp_worker thread"
+    print("Exiting llcp_worker thread")
 
 def llcp_startup(clf, llc):
-    print "Start LLCP server"
+    print("Start LLCP server")
     global srv
     srv = HandoverServer(llc)
     return llc
 
 def llcp_connected(llc):
-    print "P2P LLCP connected"
+    print("P2P LLCP connected")
     global wait_connection
     wait_connection = False
     global init_on_touch
@@ -587,7 +587,7 @@
     if args.ifname:
         global ifname
         ifname = args.ifname
-        print "Selected ifname " + ifname
+        print("Selected ifname " + ifname)
 
     if args.no_wps_req:
         global include_wps_req
@@ -610,7 +610,7 @@
 
     try:
         if not clf.open("usb"):
-            print "Could not open connection with an NFC device"
+            print("Could not open connection with an NFC device")
             raise SystemExit
 
         if args.command == "write-p2p-sel":
@@ -619,7 +619,7 @@
 
         global continue_loop
         while continue_loop:
-            print "Waiting for a tag or peer to be touched"
+            print("Waiting for a tag or peer to be touched")
             wait_connection = True
             try:
                 if args.tag_read_only:
@@ -636,8 +636,8 @@
                                              'on-connect': llcp_connected},
                                        terminate=terminate_loop):
                         break
-            except Exception, e:
-                print "clf.connect failed"
+            except Exception as e:
+                print("clf.connect failed")
 
             global srv
             if only_one and srv and srv.success:
diff --git a/wpa_supplicant/examples/p2p/p2p_connect.py b/wpa_supplicant/examples/p2p/p2p_connect.py
index 59b0a9d..6e3d94e 100644
--- a/wpa_supplicant/examples/p2p/p2p_connect.py
+++ b/wpa_supplicant/examples/p2p/p2p_connect.py
@@ -13,40 +13,40 @@
 
 
 def usage():
-	print "Usage:"
-	print "  %s -i <interface_name> -m <wps_method> \ " \
-		% sys.argv[0]
-	print "		-a <addr> [-p <pin>] [-g <go_intent>] \ "
-	print "  		[-w <wpas_dbus_interface>]"
-	print "Options:"
-	print "  -i = interface name"
-	print "  -m = wps method"
-	print "  -a = peer address"
-	print "  -p = pin number (8 digits)"
-	print "  -g = group owner intent"
-	print "  -w = wpas dbus interface = fi.w1.wpa_supplicant1"
-	print "Example:"
-	print "  %s -i wlan0 -a 0015008352c0 -m display -p 12345670" % sys.argv[0]
+	print("Usage:")
+	print("  %s -i <interface_name> -m <wps_method> \ " \
+		% sys.argv[0])
+	print("		-a <addr> [-p <pin>] [-g <go_intent>] \ ")
+	print("  		[-w <wpas_dbus_interface>]")
+	print("Options:")
+	print("  -i = interface name")
+	print("  -m = wps method")
+	print("  -a = peer address")
+	print("  -p = pin number (8 digits)")
+	print("  -g = group owner intent")
+	print("  -w = wpas dbus interface = fi.w1.wpa_supplicant1")
+	print("Example:")
+	print("  %s -i wlan0 -a 0015008352c0 -m display -p 12345670" % sys.argv[0])
 
 
 # Required Signals
 def GONegotiationSuccess(status):
-	print "Go Negotiation Success"
+	print("Go Negotiation Success")
 
 def GONegotiationFailure(status):
-	print 'Go Negotiation Failed. Status:'
-	print format(status)
+	print('Go Negotiation Failed. Status:')
+	print(format(status))
 	os._exit(0)
 
 def GroupStarted(properties):
 	if properties.has_key("group_object"):
-		print 'Group Formation Complete %s' \
-			% properties["group_object"]
+		print('Group Formation Complete %s' \
+			% properties["group_object"])
 	os._exit(0)
 
 def WpsFailure(status, etc):
-	print "WPS Authentication Failure".format(status)
-	print etc
+	print("WPS Authentication Failure".format(status))
+	print(etc)
 	os._exit(0)
 
 class P2P_Connect():
@@ -118,7 +118,7 @@
 					{'Ifname': ifname, 'Driver': 'test'})
 				time.sleep(1)
 
-			except dbus.DBusException, exc:
+			except dbus.DBusException as exc:
 				if not str(exc).startswith(
 					self.wpas_dbus_interface + \
 					".InterfaceExists:"):
@@ -157,12 +157,12 @@
 			if (self.pin != None):
 				self.p2p_connect_arguements.update({'pin':self.pin})
 			else:
-				print "Error:\n  Pin required for wps_method=display"
+				print("Error:\n  Pin required for wps_method=display")
 				usage()
 				quit()
 
 			if (self.go_intent != None and int(self.go_intent) != 15):
-				print "go_intent overwritten to 15"
+				print("go_intent overwritten to 15")
 
 			self.go_intent = '15'
 
@@ -171,14 +171,14 @@
 			if (self.pin != None):
 				self.p2p_connect_arguements.update({'pin':self.pin})
 			else:
-				print "Error:\n  Pin required for wps_method=keypad"
+				print("Error:\n  Pin required for wps_method=keypad")
 				usage()
 				quit()
 
 			if (self.go_intent != None and int(self.go_intent) == 15):
 				error = "Error :\n Group Owner intent cannot be" + \
 					" 15 for wps_method=keypad"
-				print error
+				print(error)
 				usage()
 				quit()
 
@@ -186,15 +186,15 @@
 		# for ./wpa_cli, p2p_connect [mac] [pin#], wps_method=keypad
 		elif (self.wps_method == 'pin'):
 			if (self.pin != None):
-				print "pin ignored"
+				print("pin ignored")
 
 		# No pin is required for pbc so it is ignored
 		elif (self.wps_method == 'pbc'):
 			if (self.pin != None):
-				print "pin ignored"
+				print("pin ignored")
 
 		else:
-			print "Error:\n  wps_method not supported or does not exist"
+			print("Error:\n  wps_method not supported or does not exist")
 			usage()
 			quit()
 
@@ -209,12 +209,12 @@
 			result_pin = self.p2p_interface.Connect(
 				self.p2p_connect_arguements)
 
-		except dbus.DBusException, exc:
+		except dbus.DBusException as exc:
 				raise exc
 
 		if (self.wps_method == 'pin' and \
 		not self.p2p_connect_arguements.has_key('pin') ):
-			print "Connect return with pin value of %d " % int(result_pin)
+			print("Connect return with pin value of %d " % int(result_pin))
 		gobject.MainLoop().run()
 
 if __name__ == "__main__":
@@ -268,19 +268,19 @@
 
 	# Required Arguements check
 	if (interface_name == None or wps_method == None or addr == None):
-		print "Error:\n  Required arguements not specified"
+		print("Error:\n  Required arguements not specified")
 		usage()
 		quit()
 
 	# Group Owner Intent Check
 	if (go_intent != None and (int(go_intent) > 15 or int(go_intent) < 0) ):
-		print "Error:\n  Group Owner Intent must be between 0 and 15 inclusive"
+		print("Error:\n  Group Owner Intent must be between 0 and 15 inclusive")
 		usage()
 		quit()
 
 	# Pin Check
 	if (pin != None and len(pin) != 8):
-		print "Error:\n  Pin is not 8 digits"
+		print("Error:\n  Pin is not 8 digits")
 		usage()
 		quit()
 
@@ -289,7 +289,7 @@
 			addr,pin,wps_method,go_intent)
 
 	except:
-		print "Error:\n  Invalid Arguements"
+		print("Error:\n  Invalid Arguements")
 		usage()
 		quit()
 
diff --git a/wpa_supplicant/examples/p2p/p2p_disconnect.py b/wpa_supplicant/examples/p2p/p2p_disconnect.py
index c3e39b3..85b5a8b 100644
--- a/wpa_supplicant/examples/p2p/p2p_disconnect.py
+++ b/wpa_supplicant/examples/p2p/p2p_disconnect.py
@@ -12,19 +12,19 @@
 from dbus.mainloop.glib import DBusGMainLoop
 
 def usage():
-	print "Usage:"
-	print "  %s -i <interface_name> \ " \
-		% sys.argv[0]
-	print "  		[-w <wpas_dbus_interface>]"
-	print "Options:"
-	print "  -i = interface name"
-	print "  -w = wpas dbus interface = fi.w1.wpa_supplicant1"
-	print "Example:"
-	print "  %s -i p2p-wlan0-0" % sys.argv[0]
+	print("Usage:")
+	print("  %s -i <interface_name> \ " \
+		% sys.argv[0])
+	print("  		[-w <wpas_dbus_interface>]")
+	print("Options:")
+	print("  -i = interface name")
+	print("  -w = wpas dbus interface = fi.w1.wpa_supplicant1")
+	print("Example:")
+	print("  %s -i p2p-wlan0-0" % sys.argv[0])
 
 # Required Signals
 def GroupFinished(status, etc):
-	print "Disconnected"	
+	print("Disconnected")
 	os._exit(0)
 
 class P2P_Disconnect (threading.Thread):
@@ -81,10 +81,10 @@
 		try:
 			self.path = self.wpas.GetInterface(
 					self.interface_name)
-		except dbus.DBusException, exc:
+		except dbus.DBusException as exc:
 			error = 'Error:\n  Interface ' + self.interface_name \
 				+ ' was not found'
-			print error
+			print(error)
 			usage()
 			os._exit(0)
 
@@ -142,7 +142,7 @@
 
 	# Interface name is required and was not given
 	if (interface_name == None):
-		print "Error:\n  interface_name is required"
+		print("Error:\n  interface_name is required")
 		usage()
 		quit()
 
@@ -152,7 +152,7 @@
 						wpas_dbus_interface,timeout)
 
 	except:
-		print "Error:\n  Invalid wpas_dbus_interface"
+		print("Error:\n  Invalid wpas_dbus_interface")
 		usage()
 		quit()
 
@@ -165,5 +165,5 @@
 	except:
 		pass
 
-	print "Disconnect timed out"
+	print("Disconnect timed out")
 	quit()
diff --git a/wpa_supplicant/examples/p2p/p2p_find.py b/wpa_supplicant/examples/p2p/p2p_find.py
index 973d46a..e2df528 100644
--- a/wpa_supplicant/examples/p2p/p2p_find.py
+++ b/wpa_supplicant/examples/p2p/p2p_find.py
@@ -13,23 +13,23 @@
 from dbus.mainloop.glib import DBusGMainLoop
 
 def usage():
-	print "Usage:"
-	print "  %s -i <interface_name> [-t <timeout>] \ " \
-		% sys.argv[0]
-	print "  		[-w <wpas_dbus_interface>]"
-	print "Options:"
-	print "  -i = interface name"
-	print "  -t = timeout = 0s (infinite)"
-	print "  -w = wpas dbus interface = fi.w1.wpa_supplicant1"
-	print "Example:"
-	print "  %s -i wlan0 -t 10" % sys.argv[0]
+	print("Usage:")
+	print("  %s -i <interface_name> [-t <timeout>] \ " \
+		% sys.argv[0])
+	print("  		[-w <wpas_dbus_interface>]")
+	print("Options:")
+	print("  -i = interface name")
+	print("  -t = timeout = 0s (infinite)")
+	print("  -w = wpas dbus interface = fi.w1.wpa_supplicant1")
+	print("Example:")
+	print("  %s -i wlan0 -t 10" % sys.argv[0])
 
 # Required Signals
 def deviceFound(devicepath):
-	print "Device found: %s" % (devicepath)
+	print("Device found: %s" % (devicepath))
 
 def deviceLost(devicepath):
-	print "Device lost: %s" % (devicepath)
+	print("Device lost: %s" % (devicepath))
 
 class P2P_Find (threading.Thread):
 	# Needed Variables
@@ -85,10 +85,10 @@
 		try:
 			self.path = self.wpas.GetInterface(
 					self.interface_name)
-		except dbus.DBusException, exc:
+		except dbus.DBusException as exc:
 			error = 'Error:\n  Interface ' + self.interface_name \
 				+ ' was not found'
-			print error
+			print(error)
 			usage()
 			os._exit(0)
 
@@ -150,7 +150,7 @@
 			if ( int(value) >= 0):
 				timeout = value
 			else:
-				print "Error:\n  Timeout cannot be negative"
+				print("Error:\n  Timeout cannot be negative")
 				usage()
 				quit()
 		# Dbus interface
@@ -161,7 +161,7 @@
 
 	# Interface name is required and was not given
 	if (interface_name == None):
-		print "Error:\n  interface_name is required"
+		print("Error:\n  interface_name is required")
 		usage()
 		quit()
 
@@ -170,7 +170,7 @@
 		p2p_find_test = P2P_Find(interface_name, wpas_dbus_interface, timeout)
 
 	except:
-		print "Error:\n  Invalid wpas_dbus_interface"
+		print("Error:\n  Invalid wpas_dbus_interface")
 		usage()
 		quit()
 
diff --git a/wpa_supplicant/examples/p2p/p2p_flush.py b/wpa_supplicant/examples/p2p/p2p_flush.py
index ff8509d..42fc7a3 100644
--- a/wpa_supplicant/examples/p2p/p2p_flush.py
+++ b/wpa_supplicant/examples/p2p/p2p_flush.py
@@ -13,19 +13,19 @@
 from dbus.mainloop.glib import DBusGMainLoop
 
 def usage():
-	print "Usage:"
-	print "  %s -i <interface_name> \ " \
-		% sys.argv[0]
-	print "  		[-w <wpas_dbus_interface>]"
-	print "Options:"
-	print "  -i = interface name"
-	print "  -w = wpas dbus interface = fi.w1.wpa_supplicant1"
-	print "Example:"
-	print "  %s -i wlan0" % sys.argv[0]
+	print("Usage:")
+	print("  %s -i <interface_name> \ " \
+		% sys.argv[0])
+	print("  		[-w <wpas_dbus_interface>]")
+	print("Options:")
+	print("  -i = interface name")
+	print("  -w = wpas dbus interface = fi.w1.wpa_supplicant1")
+	print("Example:")
+	print("  %s -i wlan0" % sys.argv[0])
 
 # Required Signals\
 def deviceLost(devicepath):
-	print "Device lost: %s" % (devicepath)
+	print("Device lost: %s" % (devicepath))
 
 class P2P_Flush (threading.Thread):
 	# Needed Variables
@@ -81,10 +81,10 @@
 		try:
 			self.path = self.wpas.GetInterface(
 					self.interface_name)
-		except dbus.DBusException, exc:
+		except dbus.DBusException as exc:
 			error = 'Error:\n  Interface ' + self.interface_name \
 				+ ' was not found'
-			print error
+			print(error)
 			usage()
 			os._exit(0)
 
@@ -142,7 +142,7 @@
 
 	# Interface name is required and was not given
 	if (interface_name == None):
-		print "Error:\n  interface_name is required"
+		print("Error:\n  interface_name is required")
 		usage()
 		quit()
 
@@ -151,7 +151,7 @@
 		p2p_flush_test = P2P_Flush(interface_name, wpas_dbus_interface,timeout)
 
 	except:
-		print "Error:\n  Invalid wpas_dbus_interface"
+		print("Error:\n  Invalid wpas_dbus_interface")
 		usage()
 		quit()
 
@@ -164,5 +164,5 @@
 	except:
 		pass
 
-	print "p2p_flush complete"
+	print("p2p_flush complete")
 	quit()
diff --git a/wpa_supplicant/examples/p2p/p2p_group_add.py b/wpa_supplicant/examples/p2p/p2p_group_add.py
index 5c8fdaf..6d40821 100644
--- a/wpa_supplicant/examples/p2p/p2p_group_add.py
+++ b/wpa_supplicant/examples/p2p/p2p_group_add.py
@@ -11,30 +11,30 @@
 from dbus.mainloop.glib import DBusGMainLoop
 
 def usage():
-	print "Usage:"
-	print "  %s -i <interface_name> [-p <persistent>] \ " \
-		% sys.argv[0]
-	print "		[-f <frequency>] [-o <group_object_path>] \ "
-	print "  		[-w <wpas_dbus_interface>]"
-	print "Options:"
-	print "  -i = interface name"
-	print "  -p = persistant group = 0 (0=false, 1=true)"
-	print "  -f = frequency"
-	print "  -o = persistent group object path"
-	print "  -w = wpas dbus interface = fi.w1.wpa_supplicant1"
-	print "Example:"
-	print "  %s -i wlan0" % sys.argv[0]
+	print("Usage:")
+	print("  %s -i <interface_name> [-p <persistent>] \ " \
+		% sys.argv[0])
+	print("		[-f <frequency>] [-o <group_object_path>] \ ")
+	print("  		[-w <wpas_dbus_interface>]")
+	print("Options:")
+	print("  -i = interface name")
+	print("  -p = persistant group = 0 (0=false, 1=true)")
+	print("  -f = frequency")
+	print("  -o = persistent group object path")
+	print("  -w = wpas dbus interface = fi.w1.wpa_supplicant1")
+	print("Example:")
+	print("  %s -i wlan0" % sys.argv[0])
 
 # Required Signals
 def GroupStarted(properties):
 	if properties.has_key("group_object"):
-		print 'Group Formation Complete %s' \
-			% properties["group_object"]
+		print('Group Formation Complete %s' \
+			% properties["group_object"])
 	os._exit(0)
 
 def WpsFailure(status, etc):
-	print "WPS Authentication Failure".format(status)
-	print etc
+	print("WPS Authentication Failure".format(status))
+	print(etc)
 	os._exit(0)
 
 class P2P_Group_Add (threading.Thread):
@@ -99,10 +99,10 @@
 		try:
 			self.path = self.wpas.GetInterface(
 					self.interface_name)
-		except dbus.DBusException, exc:
+		except dbus.DBusException as exc:
 			error = 'Error:\n  Interface ' + self.interface_name \
 				+ ' was not found'
-			print error
+			print(error)
 			usage()
 			os._exit(0)
 
@@ -127,7 +127,7 @@
 			if (int(self.frequency) > 0):
 				self.P2PDictionary.update({'frequency':int(self.frequency)})
 			else:
-				print "Error:\n  Frequency must be greater than 0"
+				print("Error:\n  Frequency must be greater than 0")
 				usage()
 				os._exit(0)
 
@@ -141,7 +141,7 @@
 			self.p2p_interface.GroupAdd(self.P2PDictionary)
 
 		except:
-			print "Error:\n  Could not preform group add"
+			print("Error:\n  Could not preform group add")
 			usage()
 			os._exit(0)
 
@@ -188,7 +188,7 @@
 			elif (value == '1'):
 				persistent = True
 			else:
-				print "Error:\n  Persistent can only be 1 or 0"
+				print("Error:\n  Persistent can only be 1 or 0")
 				usage()
 				os._exit(0)
 		# Frequency
@@ -205,7 +205,7 @@
 
 	# Interface name is required and was not given
 	if (interface_name == None):
-		print "Error:\n  interface_name is required"
+		print("Error:\n  interface_name is required")
 		usage()
 		quit()
 
@@ -213,10 +213,10 @@
 		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 Arguements")
 
 	p2p_group_add_test.constructArguements()
 	p2p_group_add_test.start()
 	time.sleep(5)
-	print "Error:\n  Group formation timed out"
+	print("Error:\n  Group formation timed out")
 	os._exit(0)
diff --git a/wpa_supplicant/examples/p2p/p2p_invite.py b/wpa_supplicant/examples/p2p/p2p_invite.py
index 6deb397..341dcd0 100644
--- a/wpa_supplicant/examples/p2p/p2p_invite.py
+++ b/wpa_supplicant/examples/p2p/p2p_invite.py
@@ -11,29 +11,29 @@
 from dbus.mainloop.glib import DBusGMainLoop
 
 def usage():
-	print "Usage:"
-	print "  %s -i <interface_name> -a <addr> \ " \
-		% sys.argv[0]
-	print "		[-o <persistent_group_object>] [-w <wpas_dbus_interface>]"
-	print "Options:"
-	print "  -i = interface name"
-	print "  -a = address of peer"
-	print "  -o = persistent group object path"
-	print "  -w = wpas dbus interface = fi.w1.wpa_supplicant1"
-	print "Example:"
-	print "  %s -i p2p-wlan0-0 -a 00150083523c" % sys.argv[0]
+	print("Usage:")
+	print("  %s -i <interface_name> -a <addr> \ " \
+		% sys.argv[0])
+	print("		[-o <persistent_group_object>] [-w <wpas_dbus_interface>]")
+	print("Options:")
+	print("  -i = interface name")
+	print("  -a = address of peer")
+	print("  -o = persistent group object path")
+	print("  -w = wpas dbus interface = fi.w1.wpa_supplicant1")
+	print("Example:")
+	print("  %s -i p2p-wlan0-0 -a 00150083523c" % sys.argv[0])
 
 # Required Signals
 def InvitationResult(invite_result):
-	print "Inviation Result signal :"
+	print("Inviation Result signal :")
 	status = invite_result['status']
-	print "status = ", status
+	print("status = ", status)
 	if invite_result.has_key('BSSID'):
 		bssid = invite_result['BSSID']
-		print "BSSID = ", hex(bssid[0]) , ":" , \
+		print("BSSID = ", hex(bssid[0]) , ":" , \
 		 hex(bssid[1]) , ":" , hex(bssid[2]) , ":", \
 		 hex(bssid[3]) , ":" , hex(bssid[4]) , ":" , \
-		hex(bssid[5])
+		hex(bssid[5]))
 	os._exit(0)
 
 class P2P_Invite (threading.Thread):
@@ -96,10 +96,10 @@
 		try:
 			self.path = self.wpas.GetInterface(
 					self.interface_name)
-		except dbus.DBusException, exc:
+		except dbus.DBusException as exc:
 			error = 'Error:\n  Interface ' + self.interface_name \
 				+ ' was not found'
-			print error
+			print(error)
 			usage()
 			os._exit(0)
 
@@ -127,7 +127,7 @@
 			self.p2p_interface.Invite(self.P2PDictionary)
 
 		except:
-			print "Error:\n  Invalid Arguements"
+			print("Error:\n  Invalid Arguements")
 			usage()
 			os._exit(0)
 
@@ -176,12 +176,12 @@
 
 	# Interface name is required and was not given
 	if (interface_name == None):
-		print "Error:\n  interface_name is required"
+		print("Error:\n  interface_name is required")
 		usage()
 		quit()
 
 	if (addr == None):
-		print "Error:\n  peer address is required"
+		print("Error:\n  peer address is required")
 		usage()
 		quit()
 
@@ -190,12 +190,12 @@
 			P2P_Invite(interface_name,wpas_dbus_interface,
 					addr,persistent_group_object)
 	except:
-		print "Error:\n  Invalid Arguements"
+		print("Error:\n  Invalid Arguements")
 		usage()
 		os._exit(1)
 
 	p2p_invite_test.constructArguements()
 	p2p_invite_test.start()
 	time.sleep(10)
-	print "Error:\n  p2p_invite timed out"
+	print("Error:\n  p2p_invite timed out")
 	os._exit(0)
diff --git a/wpa_supplicant/examples/p2p/p2p_listen.py b/wpa_supplicant/examples/p2p/p2p_listen.py
index bb3c1e4..b0837d9 100644
--- a/wpa_supplicant/examples/p2p/p2p_listen.py
+++ b/wpa_supplicant/examples/p2p/p2p_listen.py
@@ -13,20 +13,20 @@
 from dbus.mainloop.glib import DBusGMainLoop
 
 def usage():
-	print "Usage:"
-	print "  %s -i <interface_name> [-t <timeout>] \ " \
-		% sys.argv[0]
-	print "  		[-w <wpas_dbus_interface>]"
-	print "Options:"
-	print "  -i = interface name"
-	print "  -t = timeout = 0s (infinite)"
-	print "  -w = wpas dbus interface = fi.w1.wpa_supplicant1"
-	print "Example:"
-	print "  %s -i wlan0 -t 5" % sys.argv[0]
+	print("Usage:")
+	print("  %s -i <interface_name> [-t <timeout>] \ " \
+		% sys.argv[0])
+	print("  		[-w <wpas_dbus_interface>]")
+	print("Options:")
+	print("  -i = interface name")
+	print("  -t = timeout = 0s (infinite)")
+	print("  -w = wpas dbus interface = fi.w1.wpa_supplicant1")
+	print("Example:")
+	print("  %s -i wlan0 -t 5" % sys.argv[0])
 
 # Required Signals
 def p2pStateChange(status):
-	print status
+	print(status)
 
 class P2P_Listen(threading.Thread):
 	# Needed Variables
@@ -82,10 +82,10 @@
 		try:
 			self.path = self.wpas.GetInterface(
 					self.interface_name)
-		except dbus.DBusException, exc:
+		except dbus.DBusException as exc:
 			error = 'Error:\n  Interface ' + self.interface_name \
 				+ ' was not found'
-			print error
+			print(error)
 			usage()
 			os._exit(0)
 
@@ -140,7 +140,7 @@
 			if ( int(value) >= 0):
 				timeout = value
 			else:
-				print "Error:\n  Timeout cannot be negative"
+				print("Error:\n  Timeout cannot be negative")
 				usage()
 				quit()
 		# Dbus interface
@@ -151,7 +151,7 @@
 
 	# Interface name is required and was not given
 	if (interface_name == None):
-		print "Error:\n  interface_name is required"
+		print("Error:\n  interface_name is required")
 		usage()
 		quit()
 
@@ -160,7 +160,7 @@
 		p2p_listen_test = P2P_Listen(interface_name, wpas_dbus_interface, timeout)
 
 	except:
-		print "Error:\n  Invalid wpas_dbus_interface"
+		print("Error:\n  Invalid wpas_dbus_interface")
 		usage()
 		quit()
 
diff --git a/wpa_supplicant/examples/p2p/p2p_stop_find.py b/wpa_supplicant/examples/p2p/p2p_stop_find.py
index f6c03b0..bdb4c0e 100644
--- a/wpa_supplicant/examples/p2p/p2p_stop_find.py
+++ b/wpa_supplicant/examples/p2p/p2p_stop_find.py
@@ -11,22 +11,22 @@
 from dbus.mainloop.glib import DBusGMainLoop
 
 def usage():
-	print "Usage:"
-	print "  %s -i <interface_name> \ " \
-		% sys.argv[0]
-	print "  		[-w <wpas_dbus_interface>]"
-	print "Options:"
-	print "  -i = interface name"
-	print "  -w = wpas dbus interface = fi.w1.wpa_supplicant1"
-	print "Example:"
-	print "  %s -i wlan0" % sys.argv[0]
+	print("Usage:")
+	print("  %s -i <interface_name> \ " \
+		% sys.argv[0])
+	print("  		[-w <wpas_dbus_interface>]")
+	print("Options:")
+	print("  -i = interface name")
+	print("  -w = wpas dbus interface = fi.w1.wpa_supplicant1")
+	print("Example:")
+	print("  %s -i wlan0" % sys.argv[0])
 
 # Required Signals
 def deviceLost(devicepath):
-	print "Device lost: %s" % (devicepath)
+	print("Device lost: %s" % (devicepath))
 
 def p2pStateChange(status):
-	print status
+	print(status)
 	os._exit(0)
 
 class P2P_Stop_Find (threading.Thread):
@@ -83,10 +83,10 @@
 		try:
 			self.path = self.wpas.GetInterface(
 					self.interface_name)
-		except dbus.DBusException, exc:
+		except dbus.DBusException as exc:
 			error = 'Error:\n  Interface ' + self.interface_name \
 				+ ' was not found'
-			print error
+			print(error)
 			usage()
 			os._exit(0)
 
@@ -147,7 +147,7 @@
 
 	# Interface name is required and was not given
 	if (interface_name == None):
-		print "Error:\n  interface_name is required"
+		print("Error:\n  interface_name is required")
 		usage()
 		quit()
 
@@ -157,7 +157,7 @@
 						wpas_dbus_interface,timeout)
 
 	except:
-		print "Error:\n  Invalid wpas_dbus_interface"
+		print("Error:\n  Invalid wpas_dbus_interface")
 		usage()
 		quit()
 
@@ -170,5 +170,5 @@
 	except:
 		pass
 
-	print "p2p find stopped"
+	print("p2p find stopped")
 	quit()
diff --git a/wpa_supplicant/examples/wpas-dbus-new-getall.py b/wpa_supplicant/examples/wpas-dbus-new-getall.py
index 03da187..732f54d 100755
--- a/wpa_supplicant/examples/wpas-dbus-new-getall.py
+++ b/wpa_supplicant/examples/wpas-dbus-new-getall.py
@@ -11,8 +11,8 @@
 				  "/fi/w1/wpa_supplicant1")
 	props = wpas_obj.GetAll("fi.w1.wpa_supplicant1",
 				dbus_interface=dbus.PROPERTIES_IFACE)
-	print "GetAll(fi.w1.wpa_supplicant1, /fi/w1/wpa_supplicant1):"
-	print props
+	print("GetAll(fi.w1.wpa_supplicant1, /fi/w1/wpa_supplicant1):")
+	print(props)
 
 	if len(sys.argv) != 2:
 		os._exit(1)
@@ -24,15 +24,15 @@
 	if_obj = bus.get_object("fi.w1.wpa_supplicant1", path)
 	props = if_obj.GetAll("fi.w1.wpa_supplicant1.Interface",
 			      dbus_interface=dbus.PROPERTIES_IFACE)
-	print
-	print "GetAll(fi.w1.wpa_supplicant1.Interface, %s):" % (path)
-	print props
+	print('')
+	print("GetAll(fi.w1.wpa_supplicant1.Interface, %s):" % (path))
+	print(props)
 
 	props = if_obj.GetAll("fi.w1.wpa_supplicant1.Interface.WPS",
 			      dbus_interface=dbus.PROPERTIES_IFACE)
-	print
-	print "GetAll(fi.w1.wpa_supplicant1.Interface.WPS, %s):" % (path)
-	print props
+	print('')
+	print("GetAll(fi.w1.wpa_supplicant1.Interface.WPS, %s):" % (path))
+	print(props)
 
 	res = if_obj.Get("fi.w1.wpa_supplicant1.Interface", 'BSSs',
 			 dbus_interface=dbus.PROPERTIES_IFACE)
@@ -40,9 +40,9 @@
 		bss_obj = bus.get_object("fi.w1.wpa_supplicant1", res[0])
 		props = bss_obj.GetAll("fi.w1.wpa_supplicant1.BSS",
 				       dbus_interface=dbus.PROPERTIES_IFACE)
-		print
-		print "GetAll(fi.w1.wpa_supplicant1.BSS, %s):" % (res[0])
-		print props
+		print('')
+		print("GetAll(fi.w1.wpa_supplicant1.BSS, %s):" % (res[0]))
+		print(props)
 
 	res = if_obj.Get("fi.w1.wpa_supplicant1.Interface", 'Networks',
 			 dbus_interface=dbus.PROPERTIES_IFACE)
@@ -50,10 +50,9 @@
 		net_obj = bus.get_object("fi.w1.wpa_supplicant1", res[0])
 		props = net_obj.GetAll("fi.w1.wpa_supplicant1.Network",
 				       dbus_interface=dbus.PROPERTIES_IFACE)
-		print
-		print "GetAll(fi.w1.wpa_supplicant1.Network, %s):" % (res[0])
-		print props
+		print('')
+		print("GetAll(fi.w1.wpa_supplicant1.Network, %s):" % (res[0]))
+		print(props)
 
 if __name__ == "__main__":
 	main()
-
diff --git a/wpa_supplicant/examples/wpas-dbus-new-signals.py b/wpa_supplicant/examples/wpas-dbus-new-signals.py
index d90ef18..366a655 100755
--- a/wpa_supplicant/examples/wpas-dbus-new-signals.py
+++ b/wpa_supplicant/examples/wpas-dbus-new-signals.py
@@ -32,17 +32,17 @@
 		if_obj = bus.get_object(WPAS_DBUS_SERVICE, path)
 		ifname = if_obj.Get(WPAS_DBUS_INTERFACES_INTERFACE, 'Ifname',
 			      dbus_interface=dbus.PROPERTIES_IFACE)
-		print ifname
+		print(ifname)
 
 def interfaceAdded(interface, properties):
-	print "InterfaceAdded(%s): Ifname=%s" % (interface, properties['Ifname'])
+	print("InterfaceAdded(%s): Ifname=%s" % (interface, properties['Ifname']))
 
 def interfaceRemoved(interface):
-	print "InterfaceRemoved(%s)" % (interface)
+	print("InterfaceRemoved(%s)" % (interface))
 
 def propertiesChanged(properties):
 	for i in properties:
-		print "PropertiesChanged: %s=%s" % (i, properties[i])
+		print("PropertiesChanged: %s=%s" % (i, properties[i]))
 
 def showBss(bss):
 	net_obj = bus.get_object(WPAS_DBUS_SERVICE, bss)
@@ -80,48 +80,48 @@
 	else:
 		maxrate = 0
 
-	print "  %s  ::  ssid='%s'  wpa=%s  wpa2=%s  signal=%d  rate=%d  freq=%d" % (bssid, ssid, wpa, wpa2, signal, maxrate, freq)
+	print("  %s  ::  ssid='%s'  wpa=%s  wpa2=%s  signal=%d  rate=%d  freq=%d" % (bssid, ssid, wpa, wpa2, signal, maxrate, freq))
 
 def scanDone(success):
 	gobject.MainLoop().quit()
-	print "Scan done: success=%s" % success
+	print("Scan done: success=%s" % success)
 
 def scanDone2(success, path=None):
-	print "Scan done: success=%s [path=%s]" % (success, path)
+	print("Scan done: success=%s [path=%s]" % (success, path))
 
 def bssAdded(bss, properties):
-	print "BSS added: %s" % (bss)
+	print("BSS added: %s" % (bss))
 	showBss(bss)
 
 def bssRemoved(bss):
-	print "BSS removed: %s" % (bss)
+	print("BSS removed: %s" % (bss))
 
 def blobAdded(blob):
-	print "BlobAdded(%s)" % (blob)
+	print("BlobAdded(%s)" % (blob))
 
 def blobRemoved(blob):
-	print "BlobRemoved(%s)" % (blob)
+	print("BlobRemoved(%s)" % (blob))
 
 def networkAdded(network, properties):
-	print "NetworkAdded(%s)" % (network)
+	print("NetworkAdded(%s)" % (network))
 
 def networkRemoved(network):
-	print "NetworkRemoved(%s)" % (network)
+	print("NetworkRemoved(%s)" % (network))
 
 def networkSelected(network):
-	print "NetworkSelected(%s)" % (network)
+	print("NetworkSelected(%s)" % (network))
 
 def propertiesChangedInterface(properties):
 	for i in properties:
-		print "PropertiesChanged(interface): %s=%s" % (i, properties[i])
+		print("PropertiesChanged(interface): %s=%s" % (i, properties[i]))
 
 def propertiesChangedBss(properties):
 	for i in properties:
-		print "PropertiesChanged(BSS): %s=%s" % (i, properties[i])
+		print("PropertiesChanged(BSS): %s=%s" % (i, properties[i]))
 
 def propertiesChangedNetwork(properties):
 	for i in properties:
-		print "PropertiesChanged(Network): %s=%s" % (i, properties[i])
+		print("PropertiesChanged(Network): %s=%s" % (i, properties[i]))
 
 def main():
 	dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
diff --git a/wpa_supplicant/examples/wpas-dbus-new-wps.py b/wpa_supplicant/examples/wpas-dbus-new-wps.py
index b886385..7d87b1e 100755
--- a/wpa_supplicant/examples/wpas-dbus-new-wps.py
+++ b/wpa_supplicant/examples/wpas-dbus-new-wps.py
@@ -15,23 +15,23 @@
 
 def propertiesChanged(properties):
 	if properties.has_key("State"):
-		print "PropertiesChanged: State: %s" % (properties["State"])
+		print("PropertiesChanged: State: %s" % (properties["State"]))
 
 def scanDone(success):
-	print "Scan done: success=%s" % success
+	print("Scan done: success=%s" % success)
 
 def bssAdded(bss, properties):
-	print "BSS added: %s" % (bss)
+	print("BSS added: %s" % (bss))
 
 def bssRemoved(bss):
-	print "BSS removed: %s" % (bss)
+	print("BSS removed: %s" % (bss))
 
 def wpsEvent(name, args):
-	print "WPS event: %s" % (name)
-	print args
+	print("WPS event: %s" % (name))
+	print(args)
 
 def credentials(cred):
-	print "WPS credentials: %s" % (cred)
+	print("WPS credentials: %s" % (cred))
 
 def main():
 	dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
@@ -40,7 +40,7 @@
 	wpas_obj = bus.get_object(WPAS_DBUS_SERVICE, WPAS_DBUS_OPATH)
 
 	if len(sys.argv) != 2:
-		print "Missing ifname argument"
+		print("Missing ifname argument")
 		os._exit(1)
 
 	wpas = dbus.Interface(wpas_obj, WPAS_DBUS_INTERFACE)
diff --git a/wpa_supplicant/examples/wpas-dbus-new.py b/wpa_supplicant/examples/wpas-dbus-new.py
index 25072ce..6bf74ae 100755
--- a/wpa_supplicant/examples/wpas-dbus-new.py
+++ b/wpa_supplicant/examples/wpas-dbus-new.py
@@ -31,11 +31,11 @@
 		if_obj = bus.get_object(WPAS_DBUS_SERVICE, path)
 		ifname = if_obj.Get(WPAS_DBUS_INTERFACES_INTERFACE, 'Ifname',
 			      dbus_interface=dbus.PROPERTIES_IFACE)
-		print ifname
+		print(ifname)
 
 def propertiesChanged(properties):
 	if properties.has_key("State"):
-		print "PropertiesChanged: State: %s" % (properties["State"])
+		print("PropertiesChanged: State: %s" % (properties["State"]))
 
 def showBss(bss):
 	net_obj = bus.get_object(WPAS_DBUS_SERVICE, bss)
@@ -73,25 +73,25 @@
 	else:
 		maxrate = 0
 
-	print "  %s  ::  ssid='%s'  wpa=%s  wpa2=%s  signal=%d  rate=%d  freq=%d" % (bssid, ssid, wpa, wpa2, signal, maxrate, freq)
+	print("  %s  ::  ssid='%s'  wpa=%s  wpa2=%s  signal=%d  rate=%d  freq=%d" % (bssid, ssid, wpa, wpa2, signal, maxrate, freq))
 
 def scanDone(success):
-	print "Scan done: success=%s" % success
+	print("Scan done: success=%s" % success)
 	
 	res = if_obj.Get(WPAS_DBUS_INTERFACES_INTERFACE, 'BSSs',
 			 dbus_interface=dbus.PROPERTIES_IFACE)
 
-	print "Scanned wireless networks:"
+	print("Scanned wireless networks:")
 	for opath in res:
-		print opath
+		print(opath)
 		showBss(opath)
 
 def bssAdded(bss, properties):
-	print "BSS added: %s" % (bss)
+	print("BSS added: %s" % (bss))
 	showBss(bss)
 
 def bssRemoved(bss):
-	print "BSS removed: %s" % (bss)
+	print("BSS removed: %s" % (bss))
 
 def main():
 	dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
@@ -123,14 +123,14 @@
 	path = None
 	try:
 		path = wpas.GetInterface(ifname)
-	except dbus.DBusException, exc:
+	except dbus.DBusException as exc:
 		if not str(exc).startswith("fi.w1.wpa_supplicant1.InterfaceUnknown:"):
 			raise exc
 		try:
 			path = wpas.CreateInterface({'Ifname': ifname, 'Driver': 'test'})
 			time.sleep(1)
 
-		except dbus.DBusException, exc:
+		except dbus.DBusException as exc:
 			if not str(exc).startswith("fi.w1.wpa_supplicant1.InterfaceExists:"):
 				raise exc
 
diff --git a/wpa_supplicant/examples/wpas-test.py b/wpa_supplicant/examples/wpas-test.py
index fd7f73d..bdd16a8 100755
--- a/wpa_supplicant/examples/wpas-test.py
+++ b/wpa_supplicant/examples/wpas-test.py
@@ -24,7 +24,7 @@
 
 def main():
 	if len(sys.argv) != 2:
-		print "Usage: wpas-test.py <interface>"
+		print("Usage: wpas-test.py <interface>")
 		os._exit(1)
 
 	ifname = sys.argv[1]
@@ -37,12 +37,12 @@
 	path = None
 	try:
 		path = wpas.getInterface(ifname)
-	except dbus.dbus_bindings.DBusException, exc:
+	except dbus.dbus_bindings.DBusException as exc:
 		if str(exc) != "wpa_supplicant knows nothing about this interface.":
 			raise exc
 		try:
 			path = wpas.addInterface(ifname, {'driver': dbus.Variant('wext')})
-		except dbus.dbus_bindings.DBusException, exc:
+		except dbus.dbus_bindings.DBusException as exc:
 			if str(exc) != "wpa_supplicant already controls this interface.":
 				raise exc
 
@@ -53,7 +53,7 @@
 	time.sleep(5)
 	res = iface.scanResults()
 
-	print "Scanned wireless networks:"
+	print("Scanned wireless networks:")
 	for opath in res:
 		net_obj = bus.get_object(WPAS_DBUS_SERVICE, opath)
 		net = dbus.Interface(net_obj, WPAS_DBUS_BSSID_INTERFACE)
@@ -80,7 +80,7 @@
 		noise = props["noise"]
 		maxrate = props["maxrate"] / 1000000
 
-		print "  %s  ::  ssid='%s'  wpa=%s  wpa2=%s  quality=%d%%  rate=%d  freq=%d" % (bssid, ssid, wpa, wpa2, qual, maxrate, freq)
+		print("  %s  ::  ssid='%s'  wpa=%s  wpa2=%s  quality=%d%%  rate=%d  freq=%d" % (bssid, ssid, wpa, wpa2, qual, maxrate, freq))
 
 	wpas.removeInterface(dbus.ObjectPath(path))
 	# Should fail here with unknown interface error
diff --git a/wpa_supplicant/examples/wps-ap-cli b/wpa_supplicant/examples/wps-ap-cli
index cc2cff2..15d913e 100755
--- a/wpa_supplicant/examples/wps-ap-cli
+++ b/wpa_supplicant/examples/wps-ap-cli
@@ -14,12 +14,12 @@
 enter_pin()
 {
 	echo "Enter a PIN from a station to be enrolled to the network."
-	echo -n "Enrollee PIN: "
+	printf "Enrollee PIN: "
 	read pin
 	cpin=`$CLI wps_check_pin "$pin" | tail -1`
 	if [ "$cpin" = "FAIL-CHECKSUM" ]; then
 		echo "Checksum digit is not valid"
-		echo -n "Do you want to use this PIN (y/n)? "
+		printf "Do you want to use this PIN (y/n)? "
 		read resp
 		case "$resp" in
 			y*)
@@ -52,7 +52,7 @@
 	echo "3: Show current configuration"
 	echo "0: Exit wps-ap-cli"
 
-	echo -n "Command: "
+	printf "Command: "
 	read cmd
 
 	case "$cmd" in
diff --git a/wpa_supplicant/examples/wps-nfc.py b/wpa_supplicant/examples/wps-nfc.py
index 7459eb9..bb458fb 100755
--- a/wpa_supplicant/examples/wps-nfc.py
+++ b/wpa_supplicant/examples/wps-nfc.py
@@ -30,7 +30,7 @@
 success_file = None
 
 def summary(txt):
-    print txt
+    print(txt)
     if summary_file:
         with open(summary_file, 'a') as f:
             f.write(txt + "\n")
@@ -46,19 +46,19 @@
     if os.path.isdir(wpas_ctrl):
         try:
             ifaces = [os.path.join(wpas_ctrl, i) for i in os.listdir(wpas_ctrl)]
-        except OSError, error:
-            print "Could not find wpa_supplicant: ", error
+        except OSError as error:
+            print("Could not find wpa_supplicant: ", error)
             return None
 
     if len(ifaces) < 1:
-        print "No wpa_supplicant control interface found"
+        print("No wpa_supplicant control interface found")
         return None
 
     for ctrl in ifaces:
         try:
             wpas = wpaspy.Ctrl(ctrl)
             return wpas
-        except Exception, e:
+        except Exception as e:
             pass
     return None
 
@@ -163,22 +163,22 @@
         self.ho_server_processing = True
         summary("HandoverServer - request received")
         try:
-            print "Parsed handover request: " + request.pretty()
-        except Exception, e:
-            print e
+            print("Parsed handover request: " + request.pretty())
+        except Exception as e:
+            print(e)
 
         sel = nfc.ndef.HandoverSelectMessage(version="1.2")
 
         for carrier in request.carriers:
-            print "Remote carrier type: " + carrier.type
+            print("Remote carrier type: " + carrier.type)
             if carrier.type == "application/vnd.wfa.wsc":
                 summary("WPS carrier type match - add WPS carrier record")
                 data = wpas_get_handover_sel(self.uuid)
                 if data is None:
                     summary("Could not get handover select carrier record from wpa_supplicant")
                     continue
-                print "Handover select carrier record from wpa_supplicant:"
-                print data.encode("hex")
+                print("Handover select carrier record from wpa_supplicant:")
+                print(data.encode("hex"))
                 self.sent_carrier = data
                 if "OK" in wpas_report_handover(carrier.record, self.sent_carrier, "RESP"):
                     success_report("Handover reported successfully (responder)")
@@ -188,12 +188,12 @@
                 message = nfc.ndef.Message(data);
                 sel.add_carrier(message[0], "active", message[1:])
 
-        print "Handover select:"
+        print("Handover select:")
         try:
-            print sel.pretty()
-        except Exception, e:
-            print e
-        print str(sel).encode("hex")
+            print(sel.pretty())
+        except Exception as e:
+            print(e)
+        print(str(sel).encode("hex"))
 
         summary("Sending handover select")
         self.success = True
@@ -207,19 +207,19 @@
     if (data == None):
         summary("Could not get handover request carrier record from wpa_supplicant")
         return
-    print "Handover request carrier record from wpa_supplicant: " + data.encode("hex")
+    print("Handover request carrier record from wpa_supplicant: " + data.encode("hex"))
 
     message = nfc.ndef.HandoverRequestMessage(version="1.2")
     message.nonce = random.randint(0, 0xffff)
     datamsg = nfc.ndef.Message(data)
     message.add_carrier(datamsg[0], "active", datamsg[1:])
 
-    print "Handover request:"
+    print("Handover request:")
     try:
-        print message.pretty()
-    except Exception, e:
-        print e
-    print str(message).encode("hex")
+        print(message.pretty())
+    except Exception as e:
+        print(e)
+    print(str(message).encode("hex"))
 
     client = nfc.handover.HandoverClient(llc)
     try:
@@ -230,7 +230,7 @@
         summary("Handover connection refused")
         client.close()
         return
-    except Exception, e:
+    except Exception as e:
         summary("Other exception: " + str(e))
         client.close()
         return
@@ -253,23 +253,23 @@
         client.close()
         return
 
-    print "Received message"
+    print("Received message")
     try:
-        print message.pretty()
-    except Exception, e:
-        print e
-    print str(message).encode("hex")
+        print(message.pretty())
+    except Exception as e:
+        print(e)
+    print(str(message).encode("hex"))
     message = nfc.ndef.HandoverSelectMessage(message)
     summary("Handover select received")
     try:
-        print message.pretty()
-    except Exception, e:
-        print e
+        print(message.pretty())
+    except Exception as e:
+        print(e)
 
     for carrier in message.carriers:
-        print "Remote carrier type: " + carrier.type
+        print("Remote carrier type: " + carrier.type)
         if carrier.type == "application/vnd.wfa.wsc":
-            print "WPS carrier type match - send to wpa_supplicant"
+            print("WPS carrier type match - send to wpa_supplicant")
             if "OK" in wpas_report_handover(data, carrier.record, "INIT"):
                 success_report("Handover reported successfully (initiator)")
             else:
@@ -278,9 +278,9 @@
             #wifi = nfc.ndef.WifiConfigRecord(carrier.record)
             #print wifi.pretty()
 
-    print "Remove peer"
+    print("Remove peer")
     client.close()
-    print "Done with handover"
+    print("Done with handover")
     global only_one
     if only_one:
         global continue_loop
@@ -288,7 +288,7 @@
 
     global no_wait
     if no_wait:
-        print "Trying to exit.."
+        print("Trying to exit..")
         global terminate_now
         terminate_now = True
 
@@ -296,7 +296,7 @@
     success = False
     if len(tag.ndef.message):
         for record in tag.ndef.message:
-            print "record type " + record.type
+            print("record type " + record.type)
             if record.type == "application/vnd.wfa.wsc":
                 summary("WPS tag - send to wpa_supplicant")
                 success = wpas_tag_read(tag.ndef.message)
@@ -308,7 +308,7 @@
         success_report("Tag read succeeded")
 
     if wait_remove:
-        print "Remove tag"
+        print("Remove tag")
         while tag.is_present:
             time.sleep(0.1)
 
@@ -320,7 +320,7 @@
     global write_data
     tag.ndef.message = str(write_data)
     success_report("Tag write succeeded")
-    print "Done - remove tag"
+    print("Done - remove tag")
     global only_one
     if only_one:
         global continue_loop
@@ -330,41 +330,41 @@
         time.sleep(0.1)
 
 def wps_write_config_tag(clf, id=None, wait_remove=True):
-    print "Write WPS config token"
+    print("Write WPS config token")
     global write_data, write_wait_remove
     write_wait_remove = wait_remove
     write_data = wpas_get_config_token(id)
     if write_data == None:
-        print "Could not get WPS config token from wpa_supplicant"
+        print("Could not get WPS config token from wpa_supplicant")
         sys.exit(1)
         return
-    print "Touch an NFC tag"
+    print("Touch an NFC tag")
     clf.connect(rdwr={'on-connect': rdwr_connected_write})
 
 
 def wps_write_er_config_tag(clf, uuid, wait_remove=True):
-    print "Write WPS ER config token"
+    print("Write WPS ER config token")
     global write_data, write_wait_remove
     write_wait_remove = wait_remove
     write_data = wpas_get_er_config_token(uuid)
     if write_data == None:
-        print "Could not get WPS config token from wpa_supplicant"
+        print("Could not get WPS config token from wpa_supplicant")
         return
 
-    print "Touch an NFC tag"
+    print("Touch an NFC tag")
     clf.connect(rdwr={'on-connect': rdwr_connected_write})
 
 
 def wps_write_password_tag(clf, wait_remove=True):
-    print "Write WPS password token"
+    print("Write WPS password token")
     global write_data, write_wait_remove
     write_wait_remove = wait_remove
     write_data = wpas_get_password_token()
     if write_data == None:
-        print "Could not get WPS password token from wpa_supplicant"
+        print("Could not get WPS password token from wpa_supplicant")
         return
 
-    print "Touch an NFC tag"
+    print("Touch an NFC tag")
     clf.connect(rdwr={'on-connect': rdwr_connected_write})
 
 
@@ -373,11 +373,11 @@
     summary("Tag connected: " + str(tag))
 
     if tag.ndef:
-        print "NDEF tag: " + tag.type
+        print("NDEF tag: " + tag.type)
         try:
-            print tag.ndef.message.pretty()
-        except Exception, e:
-            print e
+            print(tag.ndef.message.pretty())
+        except Exception as e:
+            print(e)
         success = wps_tag_read(tag, not only_one)
         if only_one and success:
             global continue_loop
@@ -393,7 +393,7 @@
     global arg_uuid
     if arg_uuid is None:
         wps_handover_init(llc)
-        print "Exiting llcp_worker thread"
+        print("Exiting llcp_worker thread")
         return
 
     global srv
@@ -405,19 +405,19 @@
 def llcp_startup(clf, llc):
     global arg_uuid
     if arg_uuid:
-        print "Start LLCP server"
+        print("Start LLCP server")
         global srv
         srv = HandoverServer(llc)
         if arg_uuid is "ap":
-            print "Trying to handle WPS handover"
+            print("Trying to handle WPS handover")
             srv.uuid = None
         else:
-            print "Trying to handle WPS handover with AP " + arg_uuid
+            print("Trying to handle WPS handover with AP " + arg_uuid)
             srv.uuid = arg_uuid
     return llc
 
 def llcp_connected(llc):
-    print "P2P LLCP connected"
+    print("P2P LLCP connected")
     global wait_connection
     wait_connection = False
     global arg_uuid
@@ -426,7 +426,7 @@
         srv.start()
     else:
         threading.Thread(target=llcp_worker, args=(llc,)).start()
-    print "llcp_connected returning"
+    print("llcp_connected returning")
     return True
 
 
@@ -482,7 +482,7 @@
 
     try:
         if not clf.open("usb"):
-            print "Could not open connection with an NFC device"
+            print("Could not open connection with an NFC device")
             raise SystemExit
 
         if args.command == "write-config":
@@ -499,7 +499,7 @@
 
         global continue_loop
         while continue_loop:
-            print "Waiting for a tag or peer to be touched"
+            print("Waiting for a tag or peer to be touched")
             wait_connection = True
             try:
                 if not clf.connect(rdwr={'on-connect': rdwr_connected},
@@ -507,8 +507,8 @@
                                          'on-connect': llcp_connected},
                                    terminate=terminate_loop):
                     break
-            except Exception, e:
-                print "clf.connect failed"
+            except Exception as e:
+                print("clf.connect failed")
 
             global srv
             if only_one and srv and srv.success:
diff --git a/wpa_supplicant/gas_query.c b/wpa_supplicant/gas_query.c
index f4f60c5..8e977a3 100644
--- a/wpa_supplicant/gas_query.c
+++ b/wpa_supplicant/gas_query.c
@@ -272,7 +272,7 @@
 }
 
 
-static int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr)
+int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr)
 {
 	if (wpa_s->current_ssid == NULL ||
 	    wpa_s->wpa_state < WPA_4WAY_HANDSHAKE ||
diff --git a/wpa_supplicant/gas_query.h b/wpa_supplicant/gas_query.h
index 982c0f7..d2b4554 100644
--- a/wpa_supplicant/gas_query.h
+++ b/wpa_supplicant/gas_query.h
@@ -19,6 +19,7 @@
 int gas_query_rx(struct gas_query *gas, const u8 *da, const u8 *sa,
 		 const u8 *bssid, u8 categ, const u8 *data, size_t len,
 		 int freq);
+int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr);
 
 /**
  * enum gas_query_result - GAS query result
diff --git a/wpa_supplicant/hidl/1.2/p2p_iface.cpp b/wpa_supplicant/hidl/1.2/p2p_iface.cpp
index 4c16743..56f8344 100644
--- a/wpa_supplicant/hidl/1.2/p2p_iface.cpp
+++ b/wpa_supplicant/hidl/1.2/p2p_iface.cpp
@@ -330,7 +330,7 @@
 
 	if (wpas_p2p_group_add_persistent(
 		wpa_s, wpa_network, 0, 0, 0, 0, ht40, vht,
-		VHT_CHANWIDTH_USE_HT, NULL, 0, 1)) {
+		VHT_CHANWIDTH_USE_HT, 0, NULL, 0, 1)) {
 		ret = -1;
 	}
 
@@ -1048,7 +1048,7 @@
 	int new_pin = wpas_p2p_connect(
 	    wpa_s, peer_address.data(), pin, wps_method, persistent, false,
 	    join_existing_group, false, go_intent_signed, 0, 0, -1, false, ht40,
-	    vht, VHT_CHANWIDTH_USE_HT, nullptr, 0);
+	    vht, VHT_CHANWIDTH_USE_HT, 0, nullptr, 0);
 	if (new_pin < 0) {
 		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
 	}
@@ -1111,7 +1111,7 @@
 	if (ssid == NULL) {
 		if (wpas_p2p_group_add(
 			wpa_s, persistent, 0, 0, ht40, vht,
-			VHT_CHANWIDTH_USE_HT)) {
+			VHT_CHANWIDTH_USE_HT, 0)) {
 			return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
 		} else {
 			return {SupplicantStatusCode::SUCCESS, ""};
@@ -1119,7 +1119,7 @@
 	} else if (ssid->disabled == 2) {
 		if (wpas_p2p_group_add_persistent(
 			wpa_s, ssid, 0, 0, 0, 0, ht40, vht,
-			VHT_CHANWIDTH_USE_HT, NULL, 0, 0)) {
+			VHT_CHANWIDTH_USE_HT, 0, NULL, 0, 0)) {
 			return {SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN,
 				""};
 		} else {
@@ -1183,7 +1183,7 @@
 	}
 	if (wpas_p2p_invite(
 		wpa_s, peer_address.data(), ssid, NULL, 0, 0, ht40, vht,
-		VHT_CHANWIDTH_USE_HT, 0)) {
+		VHT_CHANWIDTH_USE_HT, 0, 0)) {
 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
 	}
 	return {SupplicantStatusCode::SUCCESS, ""};
@@ -1639,7 +1639,7 @@
 
 		if (wpas_p2p_group_add(
 		    wpa_s, persistent, freq, 0, ht40, vht,
-		    VHT_CHANWIDTH_USE_HT)) {
+		    VHT_CHANWIDTH_USE_HT, 0)) {
 			return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
 		}
 		return {SupplicantStatusCode::SUCCESS, ""};
diff --git a/wpa_supplicant/hs20_supplicant.c b/wpa_supplicant/hs20_supplicant.c
index 814d18e..e81fef1 100644
--- a/wpa_supplicant/hs20_supplicant.c
+++ b/wpa_supplicant/hs20_supplicant.c
@@ -96,8 +96,7 @@
 		return;
 	}
 
-	/* Check if Proxy ARP is enabled (2nd byte in the IE) */
-	if (ext_capa[3] & BIT(4))
+	if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_PROXY_ARP))
 		filter |= WPA_DATA_FRAME_FILTER_FLAG_ARP |
 			WPA_DATA_FRAME_FILTER_FLAG_NA;
 
@@ -105,15 +104,22 @@
 }
 
 
-void wpas_hs20_add_indication(struct wpabuf *buf, int pps_mo_id)
+void wpas_hs20_add_indication(struct wpabuf *buf, int pps_mo_id, int ap_release)
 {
+	int release;
 	u8 conf;
 
+	release = (HS20_VERSION >> 4) + 1;
+	if (ap_release > 0 && release > ap_release)
+		release = ap_release;
+	if (release < 2)
+		pps_mo_id = -1;
+
 	wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
 	wpabuf_put_u8(buf, pps_mo_id >= 0 ? 7 : 5);
 	wpabuf_put_be24(buf, OUI_WFA);
 	wpabuf_put_u8(buf, HS20_INDICATION_OUI_TYPE);
-	conf = HS20_VERSION;
+	conf = (release - 1) << 4;
 	if (pps_mo_id >= 0)
 		conf |= HS20_PPS_MO_ID_PRESENT;
 	wpabuf_put_u8(buf, conf);
@@ -138,6 +144,21 @@
 }
 
 
+int get_hs20_version(struct wpa_bss *bss)
+{
+	const u8 *ie;
+
+	if (!bss)
+		return 0;
+
+	ie = wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE);
+	if (!ie || ie[1] < 5)
+		return 0;
+
+	return ((ie[6] >> 4) & 0x0f) + 1;
+}
+
+
 int is_hs20_network(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
 		    struct wpa_bss *bss)
 {
@@ -411,7 +432,7 @@
 		return;
 	}
 
-	if (chown(fname, statbuf.st_uid, statbuf.st_gid) < 0) {
+	if (lchown(fname, statbuf.st_uid, statbuf.st_gid) < 0) {
 		wpa_printf(MSG_WARNING, "Cannot change the ownership for %s",
 			   fname);
 	}
diff --git a/wpa_supplicant/hs20_supplicant.h b/wpa_supplicant/hs20_supplicant.h
index 66fc540..e43414b 100644
--- a/wpa_supplicant/hs20_supplicant.h
+++ b/wpa_supplicant/hs20_supplicant.h
@@ -9,7 +9,8 @@
 #define HS20_SUPPLICANT_H
 
 void hs20_configure_frame_filters(struct wpa_supplicant *wpa_s);
-void wpas_hs20_add_indication(struct wpabuf *buf, int pps_mo_id);
+void wpas_hs20_add_indication(struct wpabuf *buf, int pps_mo_id,
+			      int ap_release);
 void wpas_hs20_add_roam_cons_sel(struct wpabuf *buf,
 				 const struct wpa_ssid *ssid);
 
@@ -20,6 +21,7 @@
 void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s,
 				  struct wpa_bss *bss, const u8 *sa,
 				  const u8 *data, size_t slen, u8 dialog_token);
+int get_hs20_version(struct wpa_bss *bss);
 int is_hs20_network(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
 		    struct wpa_bss *bss);
 int hs20_get_pps_mo_id(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
index ebb3a50..c66a09b 100644
--- a/wpa_supplicant/interworking.c
+++ b/wpa_supplicant/interworking.c
@@ -958,6 +958,7 @@
 			"WPA-EAP WPA-EAP-SHA256" : "WPA-EAP";
 	if (wpa_config_set(ssid, "key_mgmt", key_mgmt, 0) < 0 ||
 	    wpa_config_set(ssid, "proto", "RSN", 0) < 0 ||
+	    wpa_config_set(ssid, "ieee80211w", "1", 0) < 0 ||
 	    wpa_config_set(ssid, "pairwise", "CCMP", 0) < 0)
 		return -1;
 	return 0;
@@ -2625,7 +2626,6 @@
 {
 	struct wpa_bss *bss;
 	int found = 0;
-	const u8 *ie;
 
 	wpa_printf(MSG_DEBUG, "Interworking: next_anqp_fetch - "
 		   "fetch_anqp_in_progress=%d fetch_osu_icon_in_progress=%d",
@@ -2648,8 +2648,7 @@
 	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
 		if (!(bss->caps & IEEE80211_CAP_ESS))
 			continue;
-		ie = wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB);
-		if (ie == NULL || ie[1] < 4 || !(ie[5] & 0x80))
+		if (!wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_INTERWORKING))
 			continue; /* AP does not support Interworking */
 		if (disallowed_bssid(wpa_s, bss->bssid) ||
 		    disallowed_ssid(wpa_s, bss->ssid, bss->ssid_len))
@@ -2982,7 +2981,7 @@
 			MAC2STR(sa));
 		anqp_add_extra(wpa_s, anqp, info_id, pos, slen);
 
-		if (!wpa_sm_pmf_enabled(wpa_s->wpa)) {
+		if (!pmf_in_use(wpa_s, sa)) {
 			wpa_printf(MSG_DEBUG,
 				   "ANQP: Ignore Venue URL since PMF was not enabled");
 			break;
diff --git a/wpa_supplicant/mbo.c b/wpa_supplicant/mbo.c
index 5adf61e..bd5020a 100644
--- a/wpa_supplicant/mbo.c
+++ b/wpa_supplicant/mbo.c
@@ -51,6 +51,19 @@
 }
 
 
+const u8 * mbo_get_attr_from_ies(const u8 *ies, size_t ies_len,
+				 enum mbo_attr_id attr)
+{
+	const u8 *mbo_ie;
+
+	mbo_ie = get_vendor_ie(ies, ies_len, MBO_IE_VENDOR_TYPE);
+	if (!mbo_ie)
+		return NULL;
+
+	return mbo_attr_from_mbo_ie(mbo_ie, attr);
+}
+
+
 const u8 * wpas_mbo_get_bss_attr(struct wpa_bss *bss, enum mbo_attr_id attr)
 {
 	const u8 *mbo, *end;
@@ -501,7 +514,7 @@
 
 	if (disallowed_sec && wpa_s->current_bss)
 		wpa_bss_tmp_disallow(wpa_s, wpa_s->current_bss->bssid,
-				     disallowed_sec);
+				     disallowed_sec, 0);
 
 	return;
 fail:
diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c
index 38b9fb3..e9457f0 100644
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
@@ -34,6 +34,8 @@
 	wpa_s->current_ssid = 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 */
 }
@@ -93,6 +95,9 @@
 			conf->ieee80211w = NO_MGMT_FRAME_PROTECTION;
 	}
 #endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_OCV
+	conf->ocv = ssid->ocv;
+#endif /* CONFIG_OCV */
 
 	cipher = wpa_pick_pairwise_cipher(ssid->pairwise_cipher, 0);
 	if (cipher < 0 || cipher == WPA_CIPHER_TKIP) {
@@ -147,6 +152,95 @@
 }
 
 
+static int wpas_mesh_init_rsn(struct wpa_supplicant *wpa_s)
+{
+	struct hostapd_iface *ifmsh = wpa_s->ifmsh;
+	struct wpa_ssid *ssid = wpa_s->current_ssid;
+	struct hostapd_data *bss = ifmsh->bss[0];
+	static int default_groups[] = { 19, 20, 21, 25, 26, -1 };
+	const char *password;
+	size_t len;
+
+	password = ssid->sae_password;
+	if (!password)
+		password = ssid->passphrase;
+	if (!password) {
+		wpa_printf(MSG_ERROR,
+			   "mesh: Passphrase for SAE not configured");
+		return -1;
+	}
+
+	bss->conf->wpa = ssid->proto;
+	bss->conf->wpa_key_mgmt = ssid->key_mgmt;
+
+	if (wpa_s->conf->sae_groups && wpa_s->conf->sae_groups[0] > 0) {
+		wpas_mesh_copy_groups(bss, wpa_s);
+	} else {
+		bss->conf->sae_groups = os_memdup(default_groups,
+						  sizeof(default_groups));
+		if (!bss->conf->sae_groups)
+			return -1;
+	}
+
+	len = os_strlen(password);
+	bss->conf->ssid.wpa_passphrase = dup_binstr(password, len);
+
+	wpa_s->mesh_rsn = mesh_rsn_auth_init(wpa_s, ifmsh->mconf);
+	return !wpa_s->mesh_rsn ? -1 : 0;
+}
+
+
+static int wpas_mesh_complete(struct wpa_supplicant *wpa_s)
+{
+	struct hostapd_iface *ifmsh = wpa_s->ifmsh;
+	struct wpa_driver_mesh_join_params *params = wpa_s->mesh_params;
+	struct wpa_ssid *ssid = wpa_s->current_ssid;
+	int ret;
+
+	if (!params || !ssid) {
+		wpa_printf(MSG_ERROR, "mesh: %s called without active mesh",
+			   __func__);
+		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);
+		return -1;
+	}
+
+	if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
+		wpa_s->pairwise_cipher = wpa_s->mesh_rsn->pairwise_cipher;
+		wpa_s->group_cipher = wpa_s->mesh_rsn->group_cipher;
+		wpa_s->mgmt_group_cipher = wpa_s->mesh_rsn->mgmt_group_cipher;
+	}
+
+	if (ifmsh) {
+		params->ies = ifmsh->mconf->rsn_ie;
+		params->ie_len = ifmsh->mconf->rsn_ie_len;
+		params->basic_rates = ifmsh->basic_rates;
+		params->conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE;
+		params->conf.ht_opmode = ifmsh->bss[0]->iface->ht_op_mode;
+	}
+
+	wpa_msg(wpa_s, MSG_INFO, "joining mesh %s",
+		wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
+	ret = wpa_drv_join_mesh(wpa_s, params);
+	if (ret)
+		wpa_msg(wpa_s, MSG_ERROR, "mesh join error=%d", ret);
+
+	/* hostapd sets the interface down until we associate */
+	wpa_drv_set_operstate(wpa_s, 1);
+
+	if (!ret)
+		wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
+
+	return ret;
+}
+
+
 static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
 				    struct wpa_ssid *ssid,
 				    struct hostapd_freq_params *freq)
@@ -156,9 +250,6 @@
 	struct hostapd_config *conf;
 	struct mesh_conf *mconf;
 	int basic_rates_erp[] = { 10, 20, 55, 60, 110, 120, 240, -1 };
-	static int default_groups[] = { 19, 20, 21, 25, 26, -1 };
-	const char *password;
-	size_t len;
 	int rate_len;
 	int frequency;
 
@@ -208,6 +299,16 @@
 	bss->conf->start_disabled = 1;
 	bss->conf->mesh = MESH_ENABLED;
 	bss->conf->ap_max_inactivity = wpa_s->conf->mesh_max_inactivity;
+
+	if (ieee80211_is_dfs(ssid->frequency, wpa_s->hw.modes,
+			     wpa_s->hw.num_modes) && wpa_s->conf->country[0]) {
+		conf->ieee80211h = 1;
+		conf->ieee80211d = 1;
+		conf->country[0] = wpa_s->conf->country[0];
+		conf->country[1] = wpa_s->conf->country[1];
+		conf->country[2] = ' ';
+	}
+
 	bss->iconf = conf;
 	ifmsh->conf = conf;
 
@@ -231,7 +332,8 @@
 	if (ssid->ht40)
 		conf->secondary_channel = ssid->ht40;
 	if (conf->hw_mode == HOSTAPD_MODE_IEEE80211A && ssid->vht) {
-		conf->vht_oper_chwidth = ssid->max_oper_chwidth;
+		if (ssid->max_oper_chwidth != DEFAULT_MAX_OPER_CHWIDTH)
+			conf->vht_oper_chwidth = ssid->max_oper_chwidth;
 		switch (conf->vht_oper_chwidth) {
 		case VHT_CHANWIDTH_80MHZ:
 		case VHT_CHANWIDTH_80P80MHZ:
@@ -281,48 +383,15 @@
 		conf->basic_rates[rate_len] = -1;
 	}
 
-	if (hostapd_setup_interface(ifmsh)) {
-		wpa_printf(MSG_ERROR,
-			   "Failed to initialize hostapd interface for mesh");
-		return -1;
-	}
-
 	if (wpa_drv_init_mesh(wpa_s)) {
 		wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh in driver");
 		return -1;
 	}
 
-	if (mconf->security != MESH_CONF_SEC_NONE) {
-		password = ssid->sae_password;
-		if (!password)
-			password = ssid->passphrase;
-		if (!password) {
-			wpa_printf(MSG_ERROR,
-				   "mesh: Passphrase for SAE not configured");
-			goto out_free;
-		}
-
-		bss->conf->wpa = ssid->proto;
-		bss->conf->wpa_key_mgmt = ssid->key_mgmt;
-
-		if (wpa_s->conf->sae_groups &&
-		    wpa_s->conf->sae_groups[0] > 0) {
-			wpas_mesh_copy_groups(bss, wpa_s);
-		} else {
-			bss->conf->sae_groups =
-				os_memdup(default_groups,
-					  sizeof(default_groups));
-			if (!bss->conf->sae_groups)
-				goto out_free;
-		}
-
-		len = os_strlen(password);
-		bss->conf->ssid.wpa_passphrase =
-			dup_binstr(password, len);
-
-		wpa_s->mesh_rsn = mesh_rsn_auth_init(wpa_s, mconf);
-		if (!wpa_s->mesh_rsn)
-			goto out_free;
+	if (hostapd_setup_interface(ifmsh)) {
+		wpa_printf(MSG_ERROR,
+			   "Failed to initialize hostapd interface for mesh");
+		return -1;
 	}
 
 	wpa_supplicant_conf_ap_ht(wpa_s, ssid, conf);
@@ -367,11 +436,13 @@
 int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s,
 			     struct wpa_ssid *ssid)
 {
-	struct wpa_driver_mesh_join_params params;
+	struct wpa_driver_mesh_join_params *params = os_zalloc(sizeof(*params));
 	int ret = 0;
 
-	if (!ssid || !ssid->ssid || !ssid->ssid_len || !ssid->frequency) {
+	if (!ssid || !ssid->ssid || !ssid->ssid_len || !ssid->frequency ||
+	    !params) {
 		ret = -ENOENT;
+		os_free(params);
 		goto out;
 	}
 
@@ -381,22 +452,23 @@
 	wpa_s->group_cipher = WPA_CIPHER_NONE;
 	wpa_s->mgmt_group_cipher = 0;
 
-	os_memset(&params, 0, sizeof(params));
-	params.meshid = ssid->ssid;
-	params.meshid_len = ssid->ssid_len;
-	ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
-	wpa_s->mesh_ht_enabled = !!params.freq.ht_enabled;
-	wpa_s->mesh_vht_enabled = !!params.freq.vht_enabled;
-	if (params.freq.ht_enabled && params.freq.sec_channel_offset)
-		ssid->ht40 = params.freq.sec_channel_offset;
+	params->meshid = ssid->ssid;
+	params->meshid_len = ssid->ssid_len;
+	ibss_mesh_setup_freq(wpa_s, ssid, &params->freq);
+	wpa_s->mesh_ht_enabled = !!params->freq.ht_enabled;
+	wpa_s->mesh_vht_enabled = !!params->freq.vht_enabled;
+	if (params->freq.ht_enabled && params->freq.sec_channel_offset)
+		ssid->ht40 = params->freq.sec_channel_offset;
+
 	if (wpa_s->mesh_vht_enabled) {
 		ssid->vht = 1;
-		switch (params.freq.bandwidth) {
+		ssid->vht_center_freq1 = params->freq.center_freq1;
+		switch (params->freq.bandwidth) {
 		case 80:
-			if (params.freq.center_freq2) {
+			if (params->freq.center_freq2) {
 				ssid->max_oper_chwidth = VHT_CHANWIDTH_80P80MHZ;
 				ssid->vht_center_freq2 =
-					params.freq.center_freq2;
+					params->freq.center_freq2;
 			} else {
 				ssid->max_oper_chwidth = VHT_CHANWIDTH_80MHZ;
 			}
@@ -410,67 +482,44 @@
 		}
 	}
 	if (ssid->beacon_int > 0)
-		params.beacon_int = ssid->beacon_int;
+		params->beacon_int = ssid->beacon_int;
 	else if (wpa_s->conf->beacon_int > 0)
-		params.beacon_int = wpa_s->conf->beacon_int;
+		params->beacon_int = wpa_s->conf->beacon_int;
 	if (ssid->dtim_period > 0)
-		params.dtim_period = ssid->dtim_period;
+		params->dtim_period = ssid->dtim_period;
 	else if (wpa_s->conf->dtim_period > 0)
-		params.dtim_period = wpa_s->conf->dtim_period;
-	params.conf.max_peer_links = wpa_s->conf->max_peer_links;
+		params->dtim_period = wpa_s->conf->dtim_period;
+	params->conf.max_peer_links = wpa_s->conf->max_peer_links;
 	if (ssid->mesh_rssi_threshold < DEFAULT_MESH_RSSI_THRESHOLD) {
-		params.conf.rssi_threshold = ssid->mesh_rssi_threshold;
-		params.conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_RSSI_THRESHOLD;
+		params->conf.rssi_threshold = ssid->mesh_rssi_threshold;
+		params->conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_RSSI_THRESHOLD;
 	}
 
 	if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
-		params.flags |= WPA_DRIVER_MESH_FLAG_SAE_AUTH;
-		params.flags |= WPA_DRIVER_MESH_FLAG_AMPE;
+		params->flags |= WPA_DRIVER_MESH_FLAG_SAE_AUTH;
+		params->flags |= WPA_DRIVER_MESH_FLAG_AMPE;
 		wpa_s->conf->user_mpm = 1;
 	}
 
 	if (wpa_s->conf->user_mpm) {
-		params.flags |= WPA_DRIVER_MESH_FLAG_USER_MPM;
-		params.conf.auto_plinks = 0;
+		params->flags |= WPA_DRIVER_MESH_FLAG_USER_MPM;
+		params->conf.auto_plinks = 0;
 	} else {
-		params.flags |= WPA_DRIVER_MESH_FLAG_DRIVER_MPM;
-		params.conf.auto_plinks = 1;
+		params->flags |= WPA_DRIVER_MESH_FLAG_DRIVER_MPM;
+		params->conf.auto_plinks = 1;
 	}
-	params.conf.peer_link_timeout = wpa_s->conf->mesh_max_inactivity;
+	params->conf.peer_link_timeout = wpa_s->conf->mesh_max_inactivity;
 
-	if (wpa_supplicant_mesh_init(wpa_s, ssid, &params.freq)) {
+	os_free(wpa_s->mesh_params);
+	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);
 		ret = -1;
 		goto out;
 	}
 
-	if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
-		wpa_s->pairwise_cipher = wpa_s->mesh_rsn->pairwise_cipher;
-		wpa_s->group_cipher = wpa_s->mesh_rsn->group_cipher;
-		wpa_s->mgmt_group_cipher = wpa_s->mesh_rsn->mgmt_group_cipher;
-	}
-
-	if (wpa_s->ifmsh) {
-		params.ies = wpa_s->ifmsh->mconf->rsn_ie;
-		params.ie_len = wpa_s->ifmsh->mconf->rsn_ie_len;
-		params.basic_rates = wpa_s->ifmsh->basic_rates;
-		params.conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE;
-		params.conf.ht_opmode = wpa_s->ifmsh->bss[0]->iface->ht_op_mode;
-	}
-
-	wpa_msg(wpa_s, MSG_INFO, "joining mesh %s",
-		wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
-	ret = wpa_drv_join_mesh(wpa_s, &params);
-	if (ret)
-		wpa_msg(wpa_s, MSG_ERROR, "mesh join error=%d", ret);
-
-	/* hostapd sets the interface down until we associate */
-	wpa_drv_set_operstate(wpa_s, 1);
-
-	if (!ret)
-		wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
-
+	ret = wpas_mesh_complete(wpa_s);
 out:
 	return ret;
 }
diff --git a/wpa_supplicant/mesh_mpm.c b/wpa_supplicant/mesh_mpm.c
index d166cfe..4485939 100644
--- a/wpa_supplicant/mesh_mpm.c
+++ b/wpa_supplicant/mesh_mpm.c
@@ -12,6 +12,7 @@
 #include "utils/eloop.h"
 #include "common/ieee802_11_defs.h"
 #include "common/hw_features_common.h"
+#include "common/ocv.h"
 #include "ap/hostapd.h"
 #include "ap/sta_info.h"
 #include "ap/ieee802_11.h"
@@ -222,13 +223,14 @@
 	if (!sta)
 		return;
 
-	buf_len = 2 +      /* capability info */
+	buf_len = 2 +      /* Category and Action */
+		  2 +      /* capability info */
 		  2 +      /* AID */
 		  2 + 8 +  /* supported rates */
 		  2 + (32 - 8) +
 		  2 + 32 + /* mesh ID */
 		  2 + 7 +  /* mesh config */
-		  2 + 23 + /* peering management */
+		  2 + 24 + /* peering management */
 		  2 + 96 + /* AMPE */
 		  2 + 16;  /* MIC */
 #ifdef CONFIG_IEEE80211N
@@ -245,6 +247,11 @@
 #endif /* CONFIG_IEEE80211AC */
 	if (type != PLINK_CLOSE)
 		buf_len += conf->rsn_ie_len; /* RSN IE */
+#ifdef CONFIG_OCV
+	/* OCI is included even when the other STA doesn't support OCV */
+	if (type != PLINK_CLOSE && conf->ocv)
+		buf_len += OCV_OCI_EXTENDED_LEN;
+#endif /* CONFIG_OCV */
 
 	buf = wpabuf_alloc(buf_len);
 	if (!buf)
@@ -356,6 +363,22 @@
 	}
 #endif /* CONFIG_IEEE80211AC */
 
+#ifdef CONFIG_OCV
+	if (type != PLINK_CLOSE && conf->ocv) {
+		struct wpa_channel_info ci;
+
+		if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
+			wpa_printf(MSG_WARNING,
+				   "Mesh MPM: Failed to get channel info for OCI element");
+			goto fail;
+		}
+
+		pos = wpabuf_put(buf, OCV_OCI_EXTENDED_LEN);
+		if (ocv_insert_extended_oci(&ci, pos) < 0)
+			goto fail;
+	}
+#endif /* CONFIG_OCV */
+
 	if (ampe && mesh_rsn_protect_frame(wpa_s->mesh_rsn, sta, cat, buf)) {
 		wpa_msg(wpa_s, MSG_INFO,
 			"Mesh MPM: failed to add AMPE and MIC IE");
@@ -698,6 +721,7 @@
 
 #ifdef CONFIG_IEEE80211AC
 	copy_sta_vht_capab(data, sta, elems->vht_capabilities);
+	copy_sta_vht_oper(data, sta, elems->vht_operation);
 	set_sta_vht_opmode(data, sta, elems->vht_opmode_notif);
 #endif /* CONFIG_IEEE80211AC */
 
@@ -1195,6 +1219,56 @@
 			}
 			return;
 		}
+
+#ifdef CONFIG_OCV
+		if (action_field == PLINK_OPEN && elems.rsn_ie) {
+			struct wpa_state_machine *sm = sta->wpa_sm;
+			struct wpa_ie_data data;
+
+			res = wpa_parse_wpa_ie_rsn(elems.rsn_ie - 2,
+						   elems.rsn_ie_len + 2,
+						   &data);
+			if (res) {
+				wpa_printf(MSG_DEBUG,
+					   "Failed to parse RSN IE (res=%d)",
+					   res);
+				wpa_hexdump(MSG_DEBUG, "RSN IE", elems.rsn_ie,
+					    elems.rsn_ie_len);
+				return;
+			}
+
+			wpa_auth_set_ocv(sm, mconf->ocv &&
+					 (data.capabilities &
+					  WPA_CAPABILITY_OCVC));
+		}
+
+		if (action_field != PLINK_CLOSE &&
+		    wpa_auth_uses_ocv(sta->wpa_sm)) {
+			struct wpa_channel_info ci;
+			int tx_chanwidth;
+			int tx_seg1_idx;
+
+			if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
+				wpa_printf(MSG_WARNING,
+					   "MPM: Failed to get channel info to validate received OCI in MPM Confirm");
+				return;
+			}
+
+			if (get_tx_parameters(
+				    sta, channel_width_to_int(ci.chanwidth),
+				    ci.seg1_idx, &tx_chanwidth,
+				    &tx_seg1_idx) < 0)
+				return;
+
+			if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci,
+						 tx_chanwidth, tx_seg1_idx) !=
+			    0) {
+				wpa_printf(MSG_WARNING, "MPM: %s",
+					   ocv_errorstr);
+				return;
+			}
+		}
+#endif /* CONFIG_OCV */
 	}
 
 	if (sta->plink_state == PLINK_BLOCKED) {
diff --git a/wpa_supplicant/mesh_rsn.c b/wpa_supplicant/mesh_rsn.c
index e74cb16..04ac747 100644
--- a/wpa_supplicant/mesh_rsn.c
+++ b/wpa_supplicant/mesh_rsn.c
@@ -140,7 +140,7 @@
 
 
 static int __mesh_rsn_auth_init(struct mesh_rsn *rsn, const u8 *addr,
-				enum mfp_options ieee80211w)
+				enum mfp_options ieee80211w, int ocv)
 {
 	struct wpa_auth_config conf;
 	static const struct wpa_auth_callbacks cb = {
@@ -168,6 +168,9 @@
 	if (ieee80211w != NO_MGMT_FRAME_PROTECTION)
 		conf.group_mgmt_cipher = rsn->mgmt_group_cipher;
 #endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_OCV
+	conf.ocv = ocv;
+#endif /* CONFIG_OCV */
 
 	rsn->auth = wpa_init(addr, &conf, &cb, rsn);
 	if (rsn->auth == NULL) {
@@ -240,7 +243,7 @@
 	mesh_rsn->mgmt_group_cipher = conf->mgmt_group_cipher;
 
 	if (__mesh_rsn_auth_init(mesh_rsn, wpa_s->own_addr,
-				 conf->ieee80211w) < 0) {
+				 conf->ieee80211w, conf->ocv) < 0) {
 		mesh_rsn_deinit(mesh_rsn);
 		os_free(mesh_rsn);
 		return NULL;
diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index 30bdb6d..a7fdab9 100644
--- a/wpa_supplicant/notify.c
+++ b/wpa_supplicant/notify.c
@@ -149,6 +149,15 @@
 }
 
 
+void wpas_notify_auth_status_code(struct wpa_supplicant *wpa_s)
+{
+	if (wpa_s->p2p_mgmt)
+		return;
+
+	wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_AUTH_STATUS_CODE);
+}
+
+
 void wpas_notify_assoc_status_code(struct wpa_supplicant *wpa_s)
 {
 	if (wpa_s->p2p_mgmt)
@@ -166,6 +175,42 @@
 	wpas_hidl_notify_auth_timeout(wpa_s);
 }
 
+void wpas_notify_roam_time(struct wpa_supplicant *wpa_s)
+{
+	if (wpa_s->p2p_mgmt)
+		return;
+
+	wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_ROAM_TIME);
+}
+
+
+void wpas_notify_roam_complete(struct wpa_supplicant *wpa_s)
+{
+	if (wpa_s->p2p_mgmt)
+		return;
+
+	wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_ROAM_COMPLETE);
+}
+
+
+void wpas_notify_session_length(struct wpa_supplicant *wpa_s)
+{
+	if (wpa_s->p2p_mgmt)
+		return;
+
+	wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_SESSION_LENGTH);
+}
+
+
+void wpas_notify_bss_tm_status(struct wpa_supplicant *wpa_s)
+{
+	if (wpa_s->p2p_mgmt)
+		return;
+
+	wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSS_TM_STATUS);
+}
+
+
 void wpas_notify_network_changed(struct wpa_supplicant *wpa_s)
 {
 	if (wpa_s->p2p_mgmt)
@@ -788,6 +833,9 @@
 		wpas_dbus_signal_p2p_peer_joined(wpa_s, p2p_dev_addr);
 #endif /* CONFIG_P2P */
 
+	/* Register the station */
+	wpas_dbus_register_sta(wpa_s, sta);
+
 	/* Notify listeners a new station has been authorized */
 	wpas_dbus_signal_sta_authorized(wpa_s, sta);
 
@@ -811,7 +859,8 @@
 	/* Notify listeners a station has been deauthorized */
 	wpas_dbus_signal_sta_deauthorized(wpa_s, sta);
 
-	wpas_hidl_notify_ap_sta_deauthorized(wpa_s, sta, p2p_dev_addr);
+	/* Unregister the station */
+	wpas_dbus_unregister_sta(wpa_s, sta);
 }
 
 
diff --git a/wpa_supplicant/notify.h b/wpa_supplicant/notify.h
index 703ef8f..2f194ce 100644
--- a/wpa_supplicant/notify.h
+++ b/wpa_supplicant/notify.h
@@ -24,8 +24,13 @@
 			       enum wpa_states new_state,
 			       enum wpa_states old_state);
 void wpas_notify_disconnect_reason(struct wpa_supplicant *wpa_s);
+void wpas_notify_auth_status_code(struct wpa_supplicant *wpa_s);
 void wpas_notify_assoc_status_code(struct wpa_supplicant *wpa_s);
 void wpas_notify_auth_timeout(struct wpa_supplicant *wpa_s);
+void wpas_notify_roam_time(struct wpa_supplicant *wpa_s);
+void wpas_notify_roam_complete(struct wpa_supplicant *wpa_s);
+void wpas_notify_session_length(struct wpa_supplicant *wpa_s);
+void wpas_notify_bss_tm_status(struct wpa_supplicant *wpa_s);
 void wpas_notify_network_changed(struct wpa_supplicant *wpa_s);
 void wpas_notify_ap_scan_changed(struct wpa_supplicant *wpa_s);
 void wpas_notify_bssid_changed(struct wpa_supplicant *wpa_s);
diff --git a/wpa_supplicant/op_classes.c b/wpa_supplicant/op_classes.c
index d23b009..947917b 100644
--- a/wpa_supplicant/op_classes.c
+++ b/wpa_supplicant/op_classes.c
@@ -208,17 +208,78 @@
 
 
 static int wpas_op_class_supported(struct wpa_supplicant *wpa_s,
+				   struct wpa_ssid *ssid,
 				   const struct oper_class_map *op_class)
 {
 	int chan;
 	size_t i;
 	struct hostapd_hw_modes *mode;
 	int found;
+	int z;
+	int freq2 = 0;
+	int freq5 = 0;
 
 	mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, op_class->mode);
 	if (!mode)
 		return 0;
 
+	/* If we are configured to disable certain things, take that into
+	 * account here. */
+	if (ssid->freq_list && ssid->freq_list[0]) {
+		for (z = 0; ; z++) {
+			int f = ssid->freq_list[z];
+
+			if (f == 0)
+				break; /* end of list */
+			if (f > 4000 && f < 6000)
+				freq5 = 1;
+			else if (f > 2400 && f < 2500)
+				freq2 = 1;
+		}
+	} else {
+		/* No frequencies specified, can use anything hardware supports.
+		 */
+		freq2 = freq5 = 1;
+	}
+
+	if (op_class->op_class >= 115 && op_class->op_class <= 130 && !freq5)
+		return 0;
+	if (op_class->op_class >= 81 && op_class->op_class <= 84 && !freq2)
+		return 0;
+
+#ifdef CONFIG_HT_OVERRIDES
+	if (ssid->disable_ht) {
+		switch (op_class->op_class) {
+		case 83:
+		case 84:
+		case 104:
+		case 105:
+		case 116:
+		case 117:
+		case 119:
+		case 120:
+		case 122:
+		case 123:
+		case 126:
+		case 127:
+		case 128:
+		case 129:
+		case 130:
+			/* Disable >= 40 MHz channels if HT is disabled */
+			return 0;
+		}
+	}
+#endif /* CONFIG_HT_OVERRIDES */
+
+#ifdef CONFIG_VHT_OVERRIDES
+	if (ssid->disable_vht) {
+		if (op_class->op_class >= 128 && op_class->op_class <= 130) {
+			/* Disable >= 80 MHz channels if VHT is disabled */
+			return 0;
+		}
+	}
+#endif /* CONFIG_VHT_OVERRIDES */
+
 	if (op_class->op_class == 128) {
 		u8 channels[] = { 42, 58, 106, 122, 138, 155 };
 
@@ -273,8 +334,9 @@
 }
 
 
-size_t wpas_supp_op_class_ie(struct wpa_supplicant *wpa_s, int freq, u8 *pos,
-			      size_t len)
+size_t wpas_supp_op_class_ie(struct wpa_supplicant *wpa_s,
+			     struct wpa_ssid *ssid,
+			     int freq, u8 *pos, size_t len)
 {
 	struct wpabuf *buf;
 	u8 op, current, chan;
@@ -304,7 +366,7 @@
 	wpabuf_put_u8(buf, current);
 
 	for (op = 0; global_op_class[op].op_class; op++) {
-		if (wpas_op_class_supported(wpa_s, &global_op_class[op]))
+		if (wpas_op_class_supported(wpa_s, ssid, &global_op_class[op]))
 			wpabuf_put_u8(buf, global_op_class[op].op_class);
 	}
 
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 3626ea3..78011c6 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -1912,6 +1912,7 @@
 	ssid->vht = params->vht;
 	ssid->max_oper_chwidth = params->max_oper_chwidth;
 	ssid->vht_center_freq2 = params->vht_center_freq2;
+	ssid->he = params->he;
 	ssid->ssid = os_zalloc(params->ssid_len + 1);
 	if (ssid->ssid) {
 		os_memcpy(ssid->ssid, params->ssid, params->ssid_len);
@@ -2076,16 +2077,12 @@
 	}
 
 	if (wpa_s->conf->p2p_interface_random_mac_addr) {
-		if (random_mac_addr(wpa_s->pending_interface_addr) < 0) {
-			wpa_printf(MSG_ERROR, "P2P: Failed to generate random MAC address "
-					      "for the group interface");
-			return -1;
-		}
-		wpa_printf(MSG_DEBUG, "P2P: Generate random MAC address " MACSTR " for the group",
-			MAC2STR(wpa_s->pending_interface_addr));
+		random_mac_addr(wpa_s->pending_interface_addr);
+		wpa_printf(MSG_DEBUG, "P2P: Generate random MAC address " MACSTR
+			   " for the group",
+			   MAC2STR(wpa_s->pending_interface_addr));
 	}
 
-
 	if (force_ifname[0]) {
 		wpa_printf(MSG_DEBUG, "P2P: Driver forced interface name %s",
 			   force_ifname);
@@ -2165,22 +2162,26 @@
 	wpas_p2p_clone_config(group_wpa_s, wpa_s);
 
 	if (wpa_s->conf->p2p_interface_random_mac_addr) {
-		if (wpa_drv_set_mac_addr(group_wpa_s, wpa_s->pending_interface_addr) < 0) {
+		if (wpa_drv_set_mac_addr(group_wpa_s,
+					 wpa_s->pending_interface_addr) < 0) {
 			wpa_msg(group_wpa_s, MSG_INFO,
 				"Failed to set random MAC address");
-			wpa_supplicant_remove_iface(wpa_s->global, group_wpa_s, 0);
+			wpa_supplicant_remove_iface(wpa_s->global, group_wpa_s,
+						    0);
 			return NULL;
 		}
 
 		if (wpa_supplicant_update_mac_addr(group_wpa_s) < 0) {
 			wpa_msg(group_wpa_s, MSG_INFO,
 				"Could not update MAC address information");
-			wpa_supplicant_remove_iface(wpa_s->global, group_wpa_s, 0);
+			wpa_supplicant_remove_iface(wpa_s->global, group_wpa_s,
+						    0);
 			return NULL;
 		}
 
-		wpa_printf(MSG_DEBUG, "P2P: Using random MAC address " MACSTR " for the group",
-			MAC2STR(wpa_s->pending_interface_addr));
+		wpa_printf(MSG_DEBUG, "P2P: Using random MAC address " MACSTR
+			   " for the group",
+			   MAC2STR(wpa_s->pending_interface_addr));
 	}
 
 	return group_wpa_s;
@@ -3088,7 +3089,7 @@
 					       MAC2STR(sa), s->id);
 			}
 			wpas_p2p_group_add_persistent(
-				wpa_s, s, go, 0, op_freq, 0, 0, 0, 0, NULL,
+				wpa_s, s, go, 0, op_freq, 0, 0, 0, 0, 0, NULL,
 				go ? P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0,
 				1);
 		} else if (bssid) {
@@ -3314,6 +3315,7 @@
 				      wpa_s->p2p_go_vht_center_freq2,
 				      wpa_s->p2p_go_ht40, wpa_s->p2p_go_vht,
 				      wpa_s->p2p_go_max_oper_chwidth,
+				      wpa_s->p2p_go_he,
 				      channels,
 				      ssid->mode == WPAS_MODE_P2P_GO ?
 				      P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE :
@@ -3958,6 +3960,10 @@
 
 		/* Remove stale persistent group */
 		if (s->mode != WPAS_MODE_P2P_GO || s->num_p2p_clients <= 1) {
+			wpa_dbg(wpa_s, MSG_DEBUG,
+				"P2P: Remove stale persistent group id=%d",
+				s->id);
+			wpas_notify_persistent_group_removed(wpa_s, s);
 			wpa_config_remove_network(wpa_s->conf, s->id);
 			save_config = 1;
 			continue;
@@ -4081,6 +4087,11 @@
 
 		if (persistent_go && !persistent_go->num_p2p_clients) {
 			/* remove empty persistent GO */
+			wpa_dbg(wpa_s, MSG_DEBUG,
+				"P2P: Remove empty persistent group id=%d",
+				persistent_go->id);
+			wpas_notify_persistent_group_removed(wpa_s,
+							     persistent_go);
 			wpa_config_remove_network(wpa_s->conf,
 						  persistent_go->id);
 		}
@@ -4121,6 +4132,10 @@
 		/* Remove stale persistent group */
 		if (stale->mode != WPAS_MODE_P2P_GO ||
 		    stale->num_p2p_clients <= 1) {
+			wpa_dbg(wpa_s, MSG_DEBUG,
+				"P2P: Remove stale persistent group id=%d",
+				stale->id);
+			wpas_notify_persistent_group_removed(wpa_s, stale);
 			wpa_config_remove_network(wpa_s->conf, stale->id);
 		} else {
 			size_t i;
@@ -4153,6 +4168,11 @@
 		if (persistent_go && s != persistent_go &&
 		    !persistent_go->num_p2p_clients) {
 			/* remove empty persistent GO */
+			wpa_dbg(wpa_s, MSG_DEBUG,
+				"P2P: Remove empty persistent group id=%d",
+				persistent_go->id);
+			wpas_notify_persistent_group_removed(wpa_s,
+							     persistent_go);
 			wpa_config_remove_network(wpa_s->conf,
 						  persistent_go->id);
 			/* Save config */
@@ -4205,13 +4225,14 @@
 			if (response_done && persistent_go) {
 				wpas_p2p_group_add_persistent(
 					wpa_s, persistent_go,
-					0, 0, freq, 0, 0, 0, 0, NULL,
+					0, 0, freq, 0, 0, 0, 0, 0, NULL,
 					persistent_go->mode ==
 					WPAS_MODE_P2P_GO ?
 					P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE :
 					0, 0);
 			} else if (response_done) {
-				wpas_p2p_group_add(wpa_s, 1, freq, 0, 0, 0, 0);
+				wpas_p2p_group_add(wpa_s, 1, freq,
+						   0, 0, 0, 0, 0);
 			}
 
 			if (passwd_id == DEV_PW_P2PS_DEFAULT) {
@@ -4260,6 +4281,10 @@
 
 	if (persistent_go && !persistent_go->num_p2p_clients) {
 		/* remove empty persistent GO */
+		wpa_dbg(wpa_s, MSG_DEBUG,
+			"P2P: Remove empty persistent group id=%d",
+			persistent_go->id);
+		wpas_notify_persistent_group_removed(wpa_s, persistent_go);
 		wpa_config_remove_network(wpa_s->conf, persistent_go->id);
 	}
 
@@ -4323,11 +4348,11 @@
 
 	if (persistent_go) {
 		wpas_p2p_group_add_persistent(
-			wpa_s, persistent_go, 0, 0, 0, 0, 0, 0, 0, NULL,
+			wpa_s, persistent_go, 0, 0, 0, 0, 0, 0, 0, 0, NULL,
 			persistent_go->mode == WPAS_MODE_P2P_GO ?
 			P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0, 0);
 	} else {
-		wpas_p2p_group_add(wpa_s, 1, freq, 0, 0, 0, 0);
+		wpas_p2p_group_add(wpa_s, 1, freq, 0, 0, 0, 0, 0);
 	}
 
 	return 1;
@@ -4391,7 +4416,6 @@
 	return 0;
 }
 
-
 /**
  * wpas_p2p_init - Initialize P2P module for %wpa_supplicant
  * @global: Pointer to global data from wpa_supplicant_init()
@@ -4482,7 +4506,10 @@
 		 * channel.
 		 */
 		if (p2p_config_get_random_social(&p2p, &p2p.reg_class,
-						 &p2p.channel) != 0) {
+						 &p2p.channel,
+						 &global->p2p_go_avoid_freq,
+						 &global->p2p_disallow_freq) !=
+		    0) {
 			wpa_printf(MSG_INFO,
 				   "P2P: No social channels supported by the driver - do not enable P2P");
 			return 0;
@@ -4507,10 +4534,14 @@
 		 * other preference is indicated.
 		 */
 		if (p2p_config_get_random_social(&p2p, &p2p.op_reg_class,
-						 &p2p.op_channel) != 0) {
-			wpa_printf(MSG_ERROR,
+						 &p2p.op_channel, NULL,
+						 NULL) != 0) {
+			wpa_printf(MSG_INFO,
 				   "P2P: Failed to select random social channel as operation channel");
-			return -1;
+			p2p.op_reg_class = 0;
+			p2p.op_channel = 0;
+			/* This will be overridden during group setup in
+			 * p2p_prepare_channel(), so allow setup to continue. */
 		}
 		p2p.cfg_op_channel = 0;
 		wpa_printf(MSG_DEBUG, "P2P: Random operating channel: "
@@ -4903,6 +4934,7 @@
 					 wpa_s->p2p_go_ht40,
 					 wpa_s->p2p_go_vht,
 					 wpa_s->p2p_go_max_oper_chwidth,
+					 wpa_s->p2p_go_he,
 					 NULL, 0);
 			return;
 		}
@@ -5200,17 +5232,18 @@
 		os_memcpy(group->p2p_pin, wpa_s->p2p_pin,
 			  sizeof(group->p2p_pin));
 		group->p2p_wps_method = wpa_s->p2p_wps_method;
-	} else {
-		/*
-		 * Need to mark the current interface for p2p_group_formation
-		 * when a separate group interface is not used. This is needed
-		 * to allow p2p_cancel stop a pending p2p_connect-join.
-		 * wpas_p2p_init_group_interface() addresses this for the case
-		 * where a separate group interface is used.
-		 */
-		wpa_s->global->p2p_group_formation = wpa_s;
 	}
 
+	/*
+	 * Need to mark the current interface for p2p_group_formation
+	 * when a separate group interface is not used. This is needed
+	 * to allow p2p_cancel stop a pending p2p_connect-join.
+	 * wpas_p2p_init_group_interface() addresses this for the case
+	 * where a separate group interface is used.
+	 */
+	if (group == wpa_s->parent)
+		wpa_s->global->p2p_group_formation = group;
+
 	group->p2p_in_provisioning = 1;
 	group->p2p_fallback_to_go_neg = wpa_s->p2p_fallback_to_go_neg;
 
@@ -5450,7 +5483,7 @@
 		     int persistent_group, int auto_join, int join, int auth,
 		     int go_intent, int freq, unsigned int vht_center_freq2,
 		     int persistent_id, int pd, int ht40, int vht,
-		     unsigned int vht_chwidth, const u8 *group_ssid,
+		     unsigned int vht_chwidth, int he, const u8 *group_ssid,
 		     size_t group_ssid_len)
 {
 	int force_freq = 0, pref_freq = 0;
@@ -5495,6 +5528,7 @@
 	wpa_s->p2p_go_vht = !!vht;
 	wpa_s->p2p_go_vht_center_freq2 = vht_center_freq2;
 	wpa_s->p2p_go_max_oper_chwidth = vht_chwidth;
+	wpa_s->p2p_go_he = !!he;
 
 	if (pin)
 		os_strlcpy(wpa_s->p2p_pin, pin, sizeof(wpa_s->p2p_pin));
@@ -5918,7 +5952,7 @@
 static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s,
 				   struct p2p_go_neg_results *params,
 				   int freq, int vht_center_freq2, int ht40,
-				   int vht, int max_oper_chwidth,
+				   int vht, int max_oper_chwidth, int he,
 				   const struct p2p_channels *channels)
 {
 	struct wpa_used_freq_data *freqs;
@@ -5931,6 +5965,7 @@
 	params->role_go = 1;
 	params->ht40 = ht40;
 	params->vht = vht;
+	params->he = he;
 	params->max_oper_chwidth = max_oper_chwidth;
 	params->vht_center_freq2 = vht_center_freq2;
 
@@ -6287,7 +6322,7 @@
  */
 int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
 		       int freq, int vht_center_freq2, int ht40, int vht,
-		       int max_oper_chwidth)
+		       int max_oper_chwidth, int he)
 {
 	struct p2p_go_neg_results params;
 
@@ -6308,7 +6343,7 @@
 	}
 
 	if (wpas_p2p_init_go_params(wpa_s, &params, freq, vht_center_freq2,
-				    ht40, vht, max_oper_chwidth, NULL))
+				    ht40, vht, max_oper_chwidth, he, NULL))
 		return -1;
 
 	p2p_go_params(wpa_s->global->p2p, &params);
@@ -6387,7 +6422,7 @@
 				  struct wpa_ssid *ssid, int addr_allocated,
 				  int force_freq, int neg_freq,
 				  int vht_center_freq2, int ht40,
-				  int vht, int max_oper_chwidth,
+				  int vht, int max_oper_chwidth, int he,
 				  const struct p2p_channels *channels,
 				  int connection_timeout, int force_scan)
 {
@@ -6463,7 +6498,7 @@
 	}
 
 	if (wpas_p2p_init_go_params(wpa_s, &params, freq, vht_center_freq2,
-				    ht40, vht, max_oper_chwidth, channels))
+				    ht40, vht, max_oper_chwidth, he, channels))
 		return -1;
 
 	params.role_go = 1;
@@ -7015,7 +7050,7 @@
 int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
 		    struct wpa_ssid *ssid, const u8 *go_dev_addr, int freq,
 		    int vht_center_freq2, int ht40, int vht, int max_chwidth,
-		    int pref_freq)
+		    int pref_freq, int he)
 {
 	enum p2p_invite_role role;
 	u8 *bssid = NULL;
@@ -7033,6 +7068,7 @@
 	wpa_s->p2p_persistent_go_freq = freq;
 	wpa_s->p2p_go_ht40 = !!ht40;
 	wpa_s->p2p_go_vht = !!vht;
+	wpa_s->p2p_go_he = !!he;
 	wpa_s->p2p_go_max_oper_chwidth = max_chwidth;
 	wpa_s->p2p_go_vht_center_freq2 = vht_center_freq2;
 	if (ssid->mode == WPAS_MODE_P2P_GO) {
@@ -8055,7 +8091,8 @@
 			 wpa_s->p2p_pd_before_go_neg,
 			 wpa_s->p2p_go_ht40,
 			 wpa_s->p2p_go_vht,
-			 wpa_s->p2p_go_max_oper_chwidth, NULL, 0);
+			 wpa_s->p2p_go_max_oper_chwidth,
+			 wpa_s->p2p_go_he, NULL, 0);
 	return ret;
 }
 
@@ -8591,6 +8628,7 @@
 				WPS_NFC, 0, 0, 1, 0, wpa_s->conf->p2p_go_intent,
 				params->go_freq, wpa_s->p2p_go_vht_center_freq2,
 				-1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth,
+				wpa_s->p2p_go_he,
 				params->go_ssid_len ? params->go_ssid : NULL,
 				params->go_ssid_len);
 }
@@ -8670,7 +8708,7 @@
 				WPS_NFC, 0, 0, 0, 0, wpa_s->conf->p2p_go_intent,
 				forced_freq, wpa_s->p2p_go_vht_center_freq2,
 				-1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth,
-				NULL, 0);
+				wpa_s->p2p_go_he, NULL, 0);
 }
 
 
@@ -8686,7 +8724,7 @@
 			       WPS_NFC, 0, 0, 0, 1, wpa_s->conf->p2p_go_intent,
 			       forced_freq, wpa_s->p2p_go_vht_center_freq2,
 			       -1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth,
-			       NULL, 0);
+			       wpa_s->p2p_go_he, NULL, 0);
 	if (res)
 		return res;
 
@@ -9071,7 +9109,7 @@
 	 * TODO: This function may not always work correctly. For example,
 	 * when we have a running GO and a BSS on a DFS channel.
 	 */
-	if (wpas_p2p_init_go_params(wpa_s, &params, 0, 0, 0, 0, 0, NULL)) {
+	if (wpas_p2p_init_go_params(wpa_s, &params, 0, 0, 0, 0, 0, 0, NULL)) {
 		wpa_dbg(wpa_s, MSG_DEBUG,
 			"P2P CSA: Failed to select new frequency for GO");
 		return -1;
@@ -9183,7 +9221,7 @@
 	wpa_supplicant_ap_deinit(wpa_s);
 
 	/* Reselect the GO frequency */
-	if (wpas_p2p_init_go_params(wpa_s, &params, 0, 0, 0, 0, 0, NULL)) {
+	if (wpas_p2p_init_go_params(wpa_s, &params, 0, 0, 0, 0, 0, 0, NULL)) {
 		wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Failed to reselect freq");
 		wpas_p2p_group_delete(wpa_s,
 				      P2P_GROUP_REMOVAL_GO_LEAVE_CHANNEL);
diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h
index 0a08a88..24ec2ca 100644
--- a/wpa_supplicant/p2p_supplicant.h
+++ b/wpa_supplicant/p2p_supplicant.h
@@ -37,18 +37,18 @@
 		     int persistent_group, int auto_join, int join, int auth,
 		     int go_intent, int freq, unsigned int vht_center_freq2,
 		     int persistent_id, int pd, int ht40, int vht,
-		     unsigned int vht_chwidth, const u8 *group_ssid,
+		     unsigned int vht_chwidth, int he, const u8 *group_ssid,
 		     size_t group_ssid_len);
 int wpas_p2p_handle_frequency_conflicts(struct wpa_supplicant *wpa_s,
                                           int freq, struct wpa_ssid *ssid);
 int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
 		       int freq, int vht_center_freq2, int ht40, int vht,
-		       int max_oper_chwidth);
+		       int max_oper_chwidth, int he);
 int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
 				  struct wpa_ssid *ssid, int addr_allocated,
 				  int force_freq, int neg_freq,
 				  int vht_center_freq2, int ht40,
-				  int vht, int max_oper_chwidth,
+				  int vht, int max_oper_chwidth, int he,
 				  const struct p2p_channels *channels,
 				  int connection_timeout, int force_scan);
 struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s,
@@ -117,7 +117,7 @@
 int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
 		    struct wpa_ssid *ssid, const u8 *go_dev_addr, int freq,
 		    int vht_center_freq2, int ht40, int vht,
-		    int max_oper_chwidth, int pref_freq);
+		    int max_oper_chwidth, int pref_freq, int he);
 int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
 			  const u8 *peer_addr, const u8 *go_dev_addr);
 int wpas_p2p_presence_req(struct wpa_supplicant *wpa_s, u32 duration1,
diff --git a/wpa_supplicant/rrm.c b/wpa_supplicant/rrm.c
index f4fbfa7..ab5e6db 100644
--- a/wpa_supplicant/rrm.c
+++ b/wpa_supplicant/rrm.c
@@ -392,17 +392,66 @@
 }
 
 
+static int wpas_rrm_beacon_rep_update_last_frame(u8 *pos, size_t len)
+{
+	struct rrm_measurement_report_element *msr_rep;
+	u8 *end = pos + len;
+	u8 *msr_rep_end;
+
+	while (end - pos >= (int) sizeof(*msr_rep)) {
+		msr_rep = (struct rrm_measurement_report_element *) pos;
+		msr_rep_end = pos + msr_rep->len + 2;
+
+		if (msr_rep->eid != WLAN_EID_MEASURE_REPORT ||
+		    msr_rep_end > end) {
+			/* Should not happen. This indicates a bug. */
+			wpa_printf(MSG_ERROR,
+				   "RRM: non-measurement report element in measurement report frame");
+			return -1;
+		}
+
+		if (msr_rep->type == MEASURE_TYPE_BEACON) {
+			struct rrm_measurement_beacon_report *rep;
+			u8 *subelem;
+
+			rep = (struct rrm_measurement_beacon_report *)
+				msr_rep->variable;
+			subelem = rep->variable;
+			while (subelem + 2 < msr_rep_end &&
+			       subelem[0] !=
+			       WLAN_BEACON_REPORT_SUBELEM_LAST_INDICATION)
+				subelem += 2 + subelem[1];
+
+			if (subelem + 2 < msr_rep_end &&
+			    subelem[0] ==
+			    WLAN_BEACON_REPORT_SUBELEM_LAST_INDICATION &&
+			    subelem[1] == 1 &&
+			    subelem +
+			    BEACON_REPORT_LAST_INDICATION_SUBELEM_LEN <= end)
+				subelem[2] = 1;
+		}
+
+		pos += pos[1] + 2;
+	}
+
+	return 0;
+}
+
+
 static void wpas_rrm_send_msr_report(struct wpa_supplicant *wpa_s,
 				     struct wpabuf *buf)
 {
 	int len = wpabuf_len(buf);
-	const u8 *pos = wpabuf_head_u8(buf), *next = pos;
+	u8 *pos = wpabuf_mhead_u8(buf), *next = pos;
 
 #define MPDU_REPORT_LEN (int) (IEEE80211_MAX_MMPDU_SIZE - IEEE80211_HDRLEN - 3)
 
 	while (len) {
 		int send_len = (len > MPDU_REPORT_LEN) ? next - pos : len;
 
+		if (send_len == len)
+			wpas_rrm_beacon_rep_update_last_frame(pos, len);
+
 		if (send_len == len ||
 		    (send_len + next[1] + 2) > MPDU_REPORT_LEN) {
 			wpas_rrm_send_msr_report_mpdu(wpa_s, pos, send_len);
@@ -707,15 +756,17 @@
 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)
+					  size_t buf_len, u8 **ies_buf,
+					  size_t *ie_len, int add_fixed)
 {
-	u8 *ies = (u8 *) (bss + 1);
-	size_t ies_len = bss->ie_len ? bss->ie_len : bss->beacon_ie_len;
+	u8 *ies = *ies_buf;
+	size_t ies_len = *ie_len;
 	u8 *pos = buf;
 	int rem_len;
 
 	rem_len = 255 - sizeof(struct rrm_measurement_beacon_report) -
-		sizeof(struct rrm_measurement_report_element) - 2;
+		sizeof(struct rrm_measurement_report_element) - 2 -
+		REPORTED_FRAME_BODY_SUBELEM_LEN;
 
 	if (detail > BEACON_REPORT_DETAIL_ALL_FIELDS_AND_ELEMENTS) {
 		wpa_printf(MSG_DEBUG,
@@ -731,18 +782,21 @@
 	 * Minimal frame body subelement size: EID(1) + length(1) + TSF(8) +
 	 * beacon interval(2) + capabilities(2) = 14 bytes
 	 */
-	if (buf_len < 14)
-		return 0;
+	if (add_fixed && buf_len < 14)
+		return -1;
 
 	*pos++ = WLAN_BEACON_REPORT_SUBELEM_FRAME_BODY;
 	/* The length will be filled later */
 	pos++;
-	WPA_PUT_LE64(pos, bss->tsf);
-	pos += sizeof(bss->tsf);
-	WPA_PUT_LE16(pos, bss->beacon_int);
-	pos += 2;
-	WPA_PUT_LE16(pos, bss->caps);
-	pos += 2;
+
+	if (add_fixed) {
+		WPA_PUT_LE64(pos, bss->tsf);
+		pos += sizeof(bss->tsf);
+		WPA_PUT_LE16(pos, bss->beacon_int);
+		pos += 2;
+		WPA_PUT_LE16(pos, bss->caps);
+		pos += 2;
+	}
 
 	rem_len -= pos - buf;
 
@@ -757,15 +811,7 @@
 	while (ies_len > 2 && 2U + ies[1] <= ies_len && rem_len > 0) {
 		if (detail == BEACON_REPORT_DETAIL_ALL_FIELDS_AND_ELEMENTS ||
 		    (eids && bitfield_is_set(eids, ies[0]))) {
-			u8 eid = ies[0], elen = ies[1];
-
-			if ((eid == WLAN_EID_TIM || eid == WLAN_EID_RSN) &&
-			    elen > 4)
-				elen = 4;
-			/*
-			 * TODO: Truncate IBSS DFS element as described in
-			 * IEEE Std 802.11-2016, 9.4.2.22.7.
-			 */
+			u8 elen = ies[1];
 
 			if (2 + elen > buf + buf_len - pos ||
 			    2 + elen > rem_len)
@@ -782,22 +828,91 @@
 		ies += 2 + ies[1];
 	}
 
+	*ie_len = ies_len;
+	*ies_buf = ies;
+
 	/* Now the length is known */
 	buf[1] = pos - buf - 2;
 	return pos - buf;
 }
 
 
+static int wpas_add_beacon_rep_elem(struct beacon_rep_data *data,
+				    struct wpa_bss *bss,
+				    struct wpabuf **wpa_buf,
+				    struct rrm_measurement_beacon_report *rep,
+				    u8 **ie, size_t *ie_len, u8 idx)
+{
+	int ret;
+	u8 *buf, *pos;
+	u32 subelems_len = REPORTED_FRAME_BODY_SUBELEM_LEN +
+		(data->last_indication ?
+		 BEACON_REPORT_LAST_INDICATION_SUBELEM_LEN : 0);
+
+	/* Maximum element length: Beacon Report element + Reported Frame Body
+	 * subelement + all IEs of the reported Beacon frame + Reported Frame
+	 * Body Fragment ID subelement */
+	buf = os_malloc(sizeof(*rep) + 14 + *ie_len + subelems_len);
+	if (!buf)
+		return -1;
+
+	os_memcpy(buf, rep, sizeof(*rep));
+
+	ret = wpas_beacon_rep_add_frame_body(data->eids, data->report_detail,
+					     bss, buf + sizeof(*rep),
+					     14 + *ie_len, ie, ie_len,
+					     idx == 0);
+	if (ret < 0)
+		goto out;
+
+	pos = buf + ret + sizeof(*rep);
+	pos[0] = WLAN_BEACON_REPORT_SUBELEM_FRAME_BODY_FRAGMENT_ID;
+	pos[1] = 2;
+
+	/*
+	 * Only one Beacon Report Measurement is supported at a time, so
+	 * the Beacon Report ID can always be set to 1.
+	 */
+	pos[2] = 1;
+
+	/* Fragment ID Number (bits 0..6) and More Frame Body Fragments (bit 7)
+ */
+	pos[3] = idx;
+	if (data->report_detail != BEACON_REPORT_DETAIL_NONE && *ie_len)
+		pos[3] |= REPORTED_FRAME_BODY_MORE_FRAGMENTS;
+	else
+		pos[3] &= ~REPORTED_FRAME_BODY_MORE_FRAGMENTS;
+
+	pos += REPORTED_FRAME_BODY_SUBELEM_LEN;
+
+	if (data->last_indication) {
+		pos[0] = WLAN_BEACON_REPORT_SUBELEM_LAST_INDICATION;
+		pos[1] = 1;
+
+		/* This field will be updated later if this is the last frame */
+		pos[2] = 0;
+	}
+
+	ret = wpas_rrm_report_elem(wpa_buf, data->token,
+				   MEASUREMENT_REPORT_MODE_ACCEPT,
+				   MEASURE_TYPE_BEACON, buf,
+				   ret + sizeof(*rep) + subelems_len);
+out:
+	os_free(buf);
+	return ret;
+}
+
+
 static int wpas_add_beacon_rep(struct wpa_supplicant *wpa_s,
 			       struct wpabuf **wpa_buf, struct wpa_bss *bss,
 			       u64 start, u64 parent_tsf)
 {
 	struct beacon_rep_data *data = &wpa_s->beacon_rep_data;
-	u8 *ie = (u8 *) (bss + 1);
-	size_t ie_len = bss->ie_len + bss->beacon_ie_len;
-	int ret;
-	u8 *buf;
-	struct rrm_measurement_beacon_report *rep;
+	u8 *ies = (u8 *) (bss + 1);
+	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;
 
 	if (os_memcmp(data->bssid, broadcast_ether_addr, ETH_ALEN) != 0 &&
 	    os_memcmp(data->bssid, bss->bssid, ETH_ALEN) != 0)
@@ -808,39 +923,29 @@
 	     os_memcmp(data->ssid, bss->ssid, bss->ssid_len) != 0))
 		return 0;
 
-	/* Maximum element length: beacon report element + reported frame body
-	 * subelement + all IEs of the reported beacon */
-	buf = os_malloc(sizeof(*rep) + 14 + ie_len);
-	if (!buf)
-		return -1;
+	if (wpas_get_op_chan_phy(bss->freq, ies, ies_len, &rep.op_class,
+				 &rep.channel, &rep.report_info) < 0)
+		return 0;
 
-	rep = (struct rrm_measurement_beacon_report *) buf;
-	if (wpas_get_op_chan_phy(bss->freq, ie, ie_len, &rep->op_class,
-				 &rep->channel, &rep->report_info) < 0) {
-		ret = 0;
-		goto out;
-	}
+	rep.start_time = host_to_le64(start);
+	rep.duration = host_to_le16(data->scan_params.duration);
+	rep.rcpi = rssi_to_rcpi(bss->level);
+	rep.rsni = 255; /* 255 indicates that RSNI is not available */
+	os_memcpy(rep.bssid, bss->bssid, ETH_ALEN);
+	rep.antenna_id = 0; /* unknown */
+	rep.parent_tsf = host_to_le32(parent_tsf);
 
-	rep->start_time = host_to_le64(start);
-	rep->duration = host_to_le16(data->scan_params.duration);
-	rep->rcpi = rssi_to_rcpi(bss->level);
-	rep->rsni = 255; /* 255 indicates that RSNI is not available */
-	os_memcpy(rep->bssid, bss->bssid, ETH_ALEN);
-	rep->antenna_id = 0; /* unknown */
-	rep->parent_tsf = host_to_le32(parent_tsf);
+	do {
+		int ret;
 
-	ret = wpas_beacon_rep_add_frame_body(data->eids, data->report_detail,
-					     bss, rep->variable, 14 + ie_len);
-	if (ret < 0)
-		goto out;
+		ret = wpas_add_beacon_rep_elem(data, bss, wpa_buf, &rep,
+					       &pos, &ies_len, idx++);
+		if (ret)
+			return ret;
+	} while (data->report_detail != BEACON_REPORT_DETAIL_NONE &&
+		 ies_len >= 2);
 
-	ret = wpas_rrm_report_elem(wpa_buf, wpa_s->beacon_rep_data.token,
-				   MEASUREMENT_REPORT_MODE_ACCEPT,
-				   MEASURE_TYPE_BEACON, buf,
-				   ret + sizeof(*rep));
-out:
-	os_free(buf);
-	return ret;
+	return 0;
 }
 
 
@@ -1006,6 +1111,16 @@
 	case WLAN_BEACON_REQUEST_SUBELEM_AP_CHANNEL:
 		/* Skip - it will be processed when freqs are added */
 		break;
+	case WLAN_BEACON_REQUEST_SUBELEM_LAST_INDICATION:
+		if (slen != 1) {
+			wpa_printf(MSG_DEBUG,
+				   "Beacon request: Invalid last indication request subelement length: %u",
+				   slen);
+			return -1;
+		}
+
+		data->last_indication = subelem[0];
+		break;
 	default:
 		wpa_printf(MSG_DEBUG,
 			   "Beacon request: Unknown subelement id %u", sid);
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index ee39e0c..727c49a 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -581,8 +581,8 @@
 #endif /* CONFIG_WPS */
 
 #ifdef CONFIG_HS20
-	if (wpa_s->conf->hs20 && wpabuf_resize(&extra_ie, 7) == 0)
-		wpas_hs20_add_indication(extra_ie, -1);
+	if (wpa_s->conf->hs20 && wpabuf_resize(&extra_ie, 9) == 0)
+		wpas_hs20_add_indication(extra_ie, -1, 0);
 #endif /* CONFIG_HS20 */
 
 #ifdef CONFIG_FST
@@ -2806,6 +2806,13 @@
 {
 	u8 *tmp = NULL;
 
+	if ((wpa_s->mac_addr_rand_supported & type) != type ) {
+		wpa_printf(MSG_INFO,
+			   "scan: MAC randomization type %u != supported=%u",
+			   type, wpa_s->mac_addr_rand_supported);
+		return -1;
+	}
+
 	wpas_mac_addr_rand_scan_clear(wpa_s, type);
 
 	if (addr) {
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index d23dc06..ba22a93 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -12,6 +12,7 @@
 #include "utils/eloop.h"
 #include "common/ieee802_11_defs.h"
 #include "common/ieee802_11_common.h"
+#include "common/ocv.h"
 #include "eapol_supp/eapol_supp_sm.h"
 #include "common/wpa_common.h"
 #include "common/sae.h"
@@ -72,7 +73,7 @@
 		if (sae_set_group(&wpa_s->sme.sae, group) == 0) {
 			wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected SAE group %d",
 				wpa_s->sme.sae.group);
-		       return 0;
+			return 0;
 		}
 		wpa_s->sme.sae_group_index++;
 	}
@@ -354,6 +355,20 @@
 			wpas_connect_work_done(wpa_s);
 			return;
 		}
+#ifdef CONFIG_HS20
+	} else if (wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
+		   (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
+		/* No PMKSA caching, but otherwise similar to RSN/WPA */
+		wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
+		if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
+					      wpa_s->sme.assoc_req_ie,
+					      &wpa_s->sme.assoc_req_ie_len)) {
+			wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA "
+				"key management and encryption suites");
+			wpas_connect_work_done(wpa_s);
+			return;
+		}
+#endif /* CONFIG_HS20 */
 	} else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) &&
 		   wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
 		/*
@@ -445,7 +460,7 @@
 			wpa_s->sme.assoc_req_ie_len += 5;
 		}
 
-		if (wpa_s->sme.ft_used &&
+		if (wpa_s->sme.prev_bssid_set && wpa_s->sme.ft_used &&
 		    os_memcmp(md, wpa_s->sme.mobility_domain, 2) == 0 &&
 		    wpa_sm_has_ptk(wpa_s->wpa)) {
 			wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying to use FT "
@@ -505,7 +520,7 @@
 	sme_auth_handle_rrm(wpa_s, bss);
 
 	wpa_s->sme.assoc_req_ie_len += wpas_supp_op_class_ie(
-		wpa_s, bss->freq,
+		wpa_s, ssid, bss->freq,
 		wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
 		sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len);
 
@@ -536,7 +551,8 @@
 			int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
 			size_t len;
 
-			wpas_hs20_add_indication(hs20, pps_mo_id);
+			wpas_hs20_add_indication(hs20, pps_mo_id,
+						 get_hs20_version(bss));
 			wpas_hs20_add_roam_cons_sel(hs20, ssid);
 			len = sizeof(wpa_s->sme.assoc_req_ie) -
 				wpa_s->sme.assoc_req_ie_len;
@@ -881,10 +897,10 @@
 	os_memcpy(resp->da, da, ETH_ALEN);
 	os_memcpy(resp->sa, sa, ETH_ALEN);
 	os_memcpy(resp->bssid, da, ETH_ALEN);
-	resp->u.auth.auth_alg = WLAN_AUTH_SAE;
-	resp->seq_ctrl = seq_num << 4;
-	resp->u.auth.auth_transaction = auth_transaction;
-	resp->u.auth.status_code = WLAN_STATUS_SUCCESS;
+	resp->u.auth.auth_alg = host_to_le16(WLAN_AUTH_SAE);
+	resp->seq_ctrl = host_to_le16(seq_num << 4);
+	resp->u.auth.auth_transaction = host_to_le16(auth_transaction);
+	resp->u.auth.status_code = host_to_le16(WLAN_STATUS_SUCCESS);
 	if (params)
 		wpabuf_put_buf(buf, params);
 
@@ -944,7 +960,8 @@
 	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
 		if (!wpas_network_disabled(wpa_s, ssid) &&
 		    ssid_str_len == ssid->ssid_len &&
-		    os_memcmp(ssid_str, ssid->ssid, ssid_str_len) == 0)
+		    os_memcmp(ssid_str, ssid->ssid, ssid_str_len) == 0 &&
+		    (ssid->key_mgmt & WPA_KEY_MGMT_SAE))
 			break;
 	}
 	if (ssid)
@@ -1163,13 +1180,14 @@
 		return;
 	}
 
-	if (header->u.auth.auth_alg == WLAN_AUTH_SAE) {
+	if (le_to_host16(header->u.auth.auth_alg) == WLAN_AUTH_SAE) {
 		int res;
 
-		res = sme_sae_auth(wpa_s, header->u.auth.auth_transaction,
-				   header->u.auth.status_code,
-				   header->u.auth.variable,
-				   len - auth_length, 1, header->sa);
+		res = sme_sae_auth(
+			wpa_s, le_to_host16(header->u.auth.auth_transaction),
+			le_to_host16(header->u.auth.status_code),
+			header->u.auth.variable,
+			len - auth_length, 1, header->sa);
 		if (res < 0) {
 			/* Notify failure to the driver */
 			sme_send_external_auth_status(
@@ -1370,7 +1388,6 @@
 }
 
 
-#ifdef CONFIG_FILS
 #ifdef CONFIG_IEEE80211R
 static void remove_ie(u8 *buf, size_t *len, u8 eid)
 {
@@ -1385,7 +1402,6 @@
 	}
 }
 #endif /* CONFIG_IEEE80211R */
-#endif /* CONFIG_FILS */
 
 
 void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode,
@@ -1504,14 +1520,18 @@
 
 		if (wpa_s->current_ssid && wpa_s->current_ssid->owe_group) {
 			group = wpa_s->current_ssid->owe_group;
-		} else {
+		} else if (wpa_s->assoc_status_code ==
+			   WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
 			if (wpa_s->last_owe_group == 19)
 				group = 20;
 			else if (wpa_s->last_owe_group == 20)
 				group = 21;
 			else
 				group = OWE_DH_GROUP;
+		} else {
+			group = OWE_DH_GROUP;
 		}
+
 		wpa_s->last_owe_group = group;
 		wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
 		owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
@@ -1534,6 +1554,22 @@
 	}
 #endif /* CONFIG_OWE */
 
+	if (wpa_s->current_ssid && wpa_s->current_ssid->multi_ap_backhaul_sta) {
+		size_t multi_ap_ie_len;
+
+		multi_ap_ie_len = add_multi_ap_ie(
+			wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
+			sizeof(wpa_s->sme.assoc_req_ie) -
+			wpa_s->sme.assoc_req_ie_len,
+			MULTI_AP_BACKHAUL_STA);
+		if (multi_ap_ie_len == 0) {
+			wpa_printf(MSG_ERROR,
+				   "Multi-AP: Failed to build Multi-AP IE");
+			return;
+		}
+		wpa_s->sme.assoc_req_ie_len += multi_ap_ie_len;
+	}
+
 	params.bssid = bssid;
 	params.ssid = wpa_s->sme.ssid;
 	params.ssid_len = wpa_s->sme.ssid_len;
@@ -1543,6 +1579,8 @@
 	params.wpa_ie = wpa_s->sme.assoc_req_ie_len ?
 		wpa_s->sme.assoc_req_ie : NULL;
 	params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
+	wpa_hexdump(MSG_DEBUG, "SME: Association Request IEs",
+		    params.wpa_ie, params.wpa_ie_len);
 	params.pairwise_suite = wpa_s->pairwise_cipher;
 	params.group_suite = wpa_s->group_cipher;
 	params.mgmt_group_suite = wpa_s->mgmt_group_cipher;
@@ -1563,9 +1601,85 @@
 	wpa_supplicant_apply_vht_overrides(wpa_s, wpa_s->current_ssid, &params);
 #endif /* CONFIG_VHT_OVERRIDES */
 #ifdef CONFIG_IEEE80211R
-	if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies) {
+	if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies &&
+	    get_ie(wpa_s->sme.ft_ies, wpa_s->sme.ft_ies_len,
+		   WLAN_EID_RIC_DATA)) {
+		/* There seems to be a pretty inconvenient bug in the Linux
+		 * kernel IE splitting functionality when RIC is used. For now,
+		 * skip correct behavior in IE construction here (i.e., drop the
+		 * additional non-FT-specific IEs) to avoid kernel issues. This
+		 * is fine since RIC is used only for testing purposes in the
+		 * current implementation. */
+		wpa_printf(MSG_INFO,
+			   "SME: Linux kernel workaround - do not try to include additional IEs with RIC");
 		params.wpa_ie = wpa_s->sme.ft_ies;
 		params.wpa_ie_len = wpa_s->sme.ft_ies_len;
+	} else if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies) {
+		const u8 *rm_en, *pos, *end;
+		size_t rm_en_len = 0;
+		u8 *rm_en_dup = NULL, *wpos;
+
+		/* Remove RSNE, MDE, FTE to allow them to be overridden with
+		 * FT specific values */
+		remove_ie(wpa_s->sme.assoc_req_ie,
+			  &wpa_s->sme.assoc_req_ie_len,
+			  WLAN_EID_RSN);
+		remove_ie(wpa_s->sme.assoc_req_ie,
+			  &wpa_s->sme.assoc_req_ie_len,
+			  WLAN_EID_MOBILITY_DOMAIN);
+		remove_ie(wpa_s->sme.assoc_req_ie,
+			  &wpa_s->sme.assoc_req_ie_len,
+			  WLAN_EID_FAST_BSS_TRANSITION);
+		rm_en = get_ie(wpa_s->sme.assoc_req_ie,
+			       wpa_s->sme.assoc_req_ie_len,
+			       WLAN_EID_RRM_ENABLED_CAPABILITIES);
+		if (rm_en) {
+			/* Need to remove RM Enabled Capabilities element as
+			 * well temporarily, so that it can be placed between
+			 * RSNE and MDE. */
+			rm_en_len = 2 + rm_en[1];
+			rm_en_dup = os_memdup(rm_en, rm_en_len);
+			remove_ie(wpa_s->sme.assoc_req_ie,
+				  &wpa_s->sme.assoc_req_ie_len,
+				  WLAN_EID_RRM_ENABLED_CAPABILITIES);
+		}
+		wpa_hexdump(MSG_DEBUG,
+			    "SME: Association Request IEs after FT IE removal",
+			    wpa_s->sme.assoc_req_ie,
+			    wpa_s->sme.assoc_req_ie_len);
+		if (wpa_s->sme.assoc_req_ie_len + wpa_s->sme.ft_ies_len +
+		    rm_en_len > sizeof(wpa_s->sme.assoc_req_ie)) {
+			wpa_printf(MSG_ERROR,
+				   "SME: Not enough buffer room for FT IEs in Association Request frame");
+			os_free(rm_en_dup);
+			return;
+		}
+
+		os_memmove(wpa_s->sme.assoc_req_ie + wpa_s->sme.ft_ies_len +
+			   rm_en_len,
+			   wpa_s->sme.assoc_req_ie,
+			   wpa_s->sme.assoc_req_ie_len);
+		pos = wpa_s->sme.ft_ies;
+		end = pos + wpa_s->sme.ft_ies_len;
+		wpos = wpa_s->sme.assoc_req_ie;
+		if (*pos == WLAN_EID_RSN) {
+			os_memcpy(wpos, pos, 2 + pos[1]);
+			wpos += 2 + pos[1];
+			pos += 2 + pos[1];
+		}
+		if (rm_en_dup) {
+			os_memcpy(wpos, rm_en_dup, rm_en_len);
+			wpos += rm_en_len;
+			os_free(rm_en_dup);
+		}
+		os_memcpy(wpos, pos, end - pos);
+		wpa_s->sme.assoc_req_ie_len += wpa_s->sme.ft_ies_len +
+			rm_en_len;
+		params.wpa_ie = wpa_s->sme.assoc_req_ie;
+		params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
+		wpa_hexdump(MSG_DEBUG,
+			    "SME: Association Request IEs after FT override",
+			    params.wpa_ie, params.wpa_ie_len);
 	}
 #endif /* CONFIG_IEEE80211R */
 	params.mode = mode;
@@ -2122,6 +2236,7 @@
 
 static const unsigned int sa_query_max_timeout = 1000;
 static const unsigned int sa_query_retry_timeout = 201;
+static const unsigned int sa_query_ch_switch_max_delay = 5000; /* in usec */
 
 static int sme_check_sa_query_timeout(struct wpa_supplicant *wpa_s)
 {
@@ -2145,7 +2260,9 @@
 static void sme_send_sa_query_req(struct wpa_supplicant *wpa_s,
 				  const u8 *trans_id)
 {
-	u8 req[2 + WLAN_SA_QUERY_TR_ID_LEN];
+	u8 req[2 + WLAN_SA_QUERY_TR_ID_LEN + OCV_OCI_EXTENDED_LEN];
+	u8 req_len = 2 + WLAN_SA_QUERY_TR_ID_LEN;
+
 	wpa_dbg(wpa_s, MSG_DEBUG, "SME: Sending SA Query Request to "
 		MACSTR, MAC2STR(wpa_s->bssid));
 	wpa_hexdump(MSG_DEBUG, "SME: SA Query Transaction ID",
@@ -2153,9 +2270,27 @@
 	req[0] = WLAN_ACTION_SA_QUERY;
 	req[1] = WLAN_SA_QUERY_REQUEST;
 	os_memcpy(req + 2, trans_id, WLAN_SA_QUERY_TR_ID_LEN);
+
+#ifdef CONFIG_OCV
+	if (wpa_sm_ocv_enabled(wpa_s->wpa)) {
+		struct wpa_channel_info ci;
+
+		if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
+			wpa_printf(MSG_WARNING,
+				   "Failed to get channel info for OCI element in SA Query Request frame");
+			return;
+		}
+
+		if (ocv_insert_extended_oci(&ci, req + req_len) < 0)
+			return;
+
+		req_len += OCV_OCI_EXTENDED_LEN;
+	}
+#endif /* CONFIG_OCV */
+
 	if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
 				wpa_s->own_addr, wpa_s->bssid,
-				req, sizeof(req), 0) < 0)
+				req, req_len, 0) < 0)
 		wpa_msg(wpa_s, MSG_INFO, "SME: Failed to send SA Query "
 			"Request");
 }
@@ -2250,15 +2385,74 @@
 }
 
 
-void sme_sa_query_rx(struct wpa_supplicant *wpa_s, const u8 *sa,
-		     const u8 *data, size_t len)
+void sme_event_ch_switch(struct wpa_supplicant *wpa_s)
+{
+	unsigned int usec;
+	u32 _rand;
+
+	if (wpa_s->wpa_state != WPA_COMPLETED ||
+	    !wpa_sm_ocv_enabled(wpa_s->wpa))
+		return;
+
+	wpa_dbg(wpa_s, MSG_DEBUG,
+		"SME: Channel switch completed - trigger new SA Query to verify new operating channel");
+	sme_stop_sa_query(wpa_s);
+
+	if (os_get_random((u8 *) &_rand, sizeof(_rand)) < 0)
+		_rand = os_random();
+	usec = _rand % (sa_query_ch_switch_max_delay + 1);
+	eloop_register_timeout(0, usec, sme_sa_query_timer, wpa_s, NULL);
+}
+
+
+static void sme_process_sa_query_request(struct wpa_supplicant *wpa_s,
+					 const u8 *sa, const u8 *data,
+					 size_t len)
+{
+	u8 resp[2 + WLAN_SA_QUERY_TR_ID_LEN + OCV_OCI_EXTENDED_LEN];
+	u8 resp_len = 2 + WLAN_SA_QUERY_TR_ID_LEN;
+
+	wpa_dbg(wpa_s, MSG_DEBUG, "SME: Sending SA Query Response to "
+		MACSTR, MAC2STR(wpa_s->bssid));
+
+	resp[0] = WLAN_ACTION_SA_QUERY;
+	resp[1] = WLAN_SA_QUERY_RESPONSE;
+	os_memcpy(resp + 2, data + 1, WLAN_SA_QUERY_TR_ID_LEN);
+
+#ifdef CONFIG_OCV
+	if (wpa_sm_ocv_enabled(wpa_s->wpa)) {
+		struct wpa_channel_info ci;
+
+		if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
+			wpa_printf(MSG_WARNING,
+				   "Failed to get channel info for OCI element in SA Query Response frame");
+			return;
+		}
+
+		if (ocv_insert_extended_oci(&ci, resp + resp_len) < 0)
+			return;
+
+		resp_len += OCV_OCI_EXTENDED_LEN;
+	}
+#endif /* CONFIG_OCV */
+
+	if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
+				wpa_s->own_addr, wpa_s->bssid,
+				resp, resp_len, 0) < 0)
+		wpa_msg(wpa_s, MSG_INFO,
+			"SME: Failed to send SA Query Response");
+}
+
+
+static void sme_process_sa_query_response(struct wpa_supplicant *wpa_s,
+					  const u8 *sa, const u8 *data,
+					  size_t len)
 {
 	int i;
 
-	if (wpa_s->sme.sa_query_trans_id == NULL ||
-	    len < 1 + WLAN_SA_QUERY_TR_ID_LEN ||
-	    data[0] != WLAN_SA_QUERY_RESPONSE)
+	if (!wpa_s->sme.sa_query_trans_id)
 		return;
+
 	wpa_dbg(wpa_s, MSG_DEBUG, "SME: Received SA Query response from "
 		MACSTR " (trans_id %02x%02x)", MAC2STR(sa), data[1], data[2]);
 
@@ -2283,4 +2477,48 @@
 	sme_stop_sa_query(wpa_s);
 }
 
+
+void sme_sa_query_rx(struct wpa_supplicant *wpa_s, const u8 *sa,
+		     const u8 *data, size_t len)
+{
+	if (len < 1 + WLAN_SA_QUERY_TR_ID_LEN)
+		return;
+
+	wpa_dbg(wpa_s, MSG_DEBUG, "SME: Received SA Query frame from "
+		MACSTR " (trans_id %02x%02x)", MAC2STR(sa), data[1], data[2]);
+
+#ifdef CONFIG_OCV
+	if (wpa_sm_ocv_enabled(wpa_s->wpa)) {
+		struct ieee802_11_elems elems;
+		struct wpa_channel_info ci;
+
+		if (ieee802_11_parse_elems(data + 1 + WLAN_SA_QUERY_TR_ID_LEN,
+					   len - 1 - WLAN_SA_QUERY_TR_ID_LEN,
+					   &elems, 1) == ParseFailed) {
+			wpa_printf(MSG_DEBUG,
+				   "SA Query: Failed to parse elements");
+			return;
+		}
+
+		if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
+			wpa_printf(MSG_WARNING,
+				   "Failed to get channel info to validate received OCI in SA Query Action frame");
+			return;
+		}
+
+		if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci,
+					 channel_width_to_int(ci.chanwidth),
+					 ci.seg1_idx) != 0) {
+			wpa_printf(MSG_WARNING, "%s", ocv_errorstr);
+			return;
+		}
+	}
+#endif /* CONFIG_OCV */
+
+	if (data[0] == WLAN_SA_QUERY_REQUEST)
+		sme_process_sa_query_request(wpa_s, sa, data, len);
+	else if (data[0] == WLAN_SA_QUERY_RESPONSE)
+		sme_process_sa_query_response(wpa_s, sa, data, len);
+}
+
 #endif /* CONFIG_IEEE80211W */
diff --git a/wpa_supplicant/sme.h b/wpa_supplicant/sme.h
index f3c8220..1a7f9e8 100644
--- a/wpa_supplicant/sme.h
+++ b/wpa_supplicant/sme.h
@@ -28,6 +28,7 @@
 			struct disassoc_info *info);
 void sme_event_unprot_disconnect(struct wpa_supplicant *wpa_s, const u8 *sa,
 				 const u8 *da, u16 reason_code);
+void sme_event_ch_switch(struct wpa_supplicant *wpa_s);
 void sme_sa_query_rx(struct wpa_supplicant *wpa_s, const u8 *sa,
 		     const u8 *data, size_t len);
 void sme_state_changed(struct wpa_supplicant *wpa_s);
@@ -89,6 +90,10 @@
 {
 }
 
+static inline void sme_event_ch_switch(struct wpa_supplicant *wpa_s)
+{
+}
+
 static inline void sme_state_changed(struct wpa_supplicant *wpa_s)
 {
 }
diff --git a/wpa_supplicant/utils/log2pcap.py b/wpa_supplicant/utils/log2pcap.py
index 65e2fa1..141aecb 100755
--- a/wpa_supplicant/utils/log2pcap.py
+++ b/wpa_supplicant/utils/log2pcap.py
@@ -28,7 +28,7 @@
         input = sys.argv[1]
         pcap = sys.argv[2]
     except IndexError:
-        print "Usage: %s <log file> <pcap file>" % sys.argv[0]
+        print("Usage: %s <log file> <pcap file>" % sys.argv[0])
         sys.exit(2)
 
     input_file = open(input, 'r')
diff --git a/wpa_supplicant/wmm_ac.c b/wpa_supplicant/wmm_ac.c
index a88cc46..38800cc 100644
--- a/wpa_supplicant/wmm_ac.c
+++ b/wpa_supplicant/wmm_ac.c
@@ -471,13 +471,8 @@
 		return -1;
 	}
 
-	if (!ies) {
-		wpa_printf(MSG_ERROR, "WMM AC: Missing IEs");
-		return -1;
-	}
-
-	if (!(wmm_params->info_bitmap & WMM_PARAMS_UAPSD_QUEUES_INFO)) {
-		wpa_printf(MSG_DEBUG, "WMM AC: Missing U-APSD configuration");
+	if (!ies || !(wmm_params->info_bitmap & WMM_PARAMS_UAPSD_QUEUES_INFO)) {
+		/* WMM AC not in use for this connection */
 		return -1;
 	}
 
@@ -522,7 +517,7 @@
 	for (i = 0; i < WMM_AC_NUM; i++)
 		wmm_ac_del_ts(wpa_s, i, TS_DIR_IDX_ALL);
 
-	/* delete pending add_ts requset */
+	/* delete pending add_ts request */
 	wmm_ac_del_req(wpa_s, 1);
 
 	os_free(wpa_s->wmm_ac_assoc_info);
diff --git a/wpa_supplicant/wnm_sta.c b/wpa_supplicant/wnm_sta.c
index 912f4c4..39cd163 100644
--- a/wpa_supplicant/wnm_sta.c
+++ b/wpa_supplicant/wnm_sta.c
@@ -12,6 +12,7 @@
 #include "common/ieee802_11_defs.h"
 #include "common/ieee802_11_common.h"
 #include "common/wpa_ctrl.h"
+#include "common/ocv.h"
 #include "rsn_supp/wpa.h"
 #include "config.h"
 #include "wpa_supplicant_i.h"
@@ -20,6 +21,7 @@
 #include "ctrl_iface.h"
 #include "bss.h"
 #include "wnm_sta.h"
+#include "notify.h"
 #include "hs20_supplicant.h"
 
 #define MAX_TFS_IE_LEN  1024
@@ -58,8 +60,8 @@
 	int res;
 	size_t len;
 	struct wnm_sleep_element *wnmsleep_ie;
-	u8 *wnmtfs_ie;
-	u8 wnmsleep_ie_len;
+	u8 *wnmtfs_ie, *oci_ie;
+	u8 wnmsleep_ie_len, oci_ie_len;
 	u16 wnmtfs_ie_len;  /* possibly multiple IE(s) */
 	enum wnm_oper tfs_oper = action == 0 ? WNM_SLEEP_TFS_REQ_IE_ADD :
 		WNM_SLEEP_TFS_REQ_IE_NONE;
@@ -106,7 +108,41 @@
 	wpa_hexdump(MSG_DEBUG, "WNM: TFS Request element",
 		    (u8 *) wnmtfs_ie, wnmtfs_ie_len);
 
-	mgmt = os_zalloc(sizeof(*mgmt) + wnmsleep_ie_len + wnmtfs_ie_len);
+	oci_ie = NULL;
+	oci_ie_len = 0;
+#ifdef CONFIG_OCV
+	if (action == WNM_SLEEP_MODE_EXIT && wpa_sm_ocv_enabled(wpa_s->wpa)) {
+		struct wpa_channel_info ci;
+
+		if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
+			wpa_printf(MSG_WARNING,
+				   "Failed to get channel info for OCI element in WNM-Sleep Mode frame");
+			os_free(wnmsleep_ie);
+			os_free(wnmtfs_ie);
+			return -1;
+		}
+
+		oci_ie_len = OCV_OCI_EXTENDED_LEN;
+		oci_ie = os_zalloc(oci_ie_len);
+		if (!oci_ie) {
+			wpa_printf(MSG_WARNING,
+				   "Failed to allocate buffer for for OCI element in WNM-Sleep Mode frame");
+			os_free(wnmsleep_ie);
+			os_free(wnmtfs_ie);
+			return -1;
+		}
+
+		if (ocv_insert_extended_oci(&ci, oci_ie) < 0) {
+			os_free(wnmsleep_ie);
+			os_free(wnmtfs_ie);
+			os_free(oci_ie);
+			return -1;
+		}
+	}
+#endif /* CONFIG_OCV */
+
+	mgmt = os_zalloc(sizeof(*mgmt) + wnmsleep_ie_len + wnmtfs_ie_len +
+			 oci_ie_len);
 	if (mgmt == NULL) {
 		wpa_printf(MSG_DEBUG, "MLME: Failed to allocate buffer for "
 			   "WNM-Sleep Request action frame");
@@ -131,8 +167,16 @@
 			  wnmsleep_ie_len, wnmtfs_ie, wnmtfs_ie_len);
 	}
 
+#ifdef CONFIG_OCV
+	/* copy OCV OCI here */
+	if (oci_ie_len > 0) {
+		os_memcpy(mgmt->u.action.u.wnm_sleep_req.variable +
+			  wnmsleep_ie_len + wnmtfs_ie_len, oci_ie, oci_ie_len);
+	}
+#endif /* CONFIG_OCV */
+
 	len = 1 + sizeof(mgmt->u.action.u.wnm_sleep_req) + wnmsleep_ie_len +
-		wnmtfs_ie_len;
+		wnmtfs_ie_len + oci_ie_len;
 
 	res = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
 				  wpa_s->own_addr, wpa_s->bssid,
@@ -145,6 +189,7 @@
 
 	os_free(wnmsleep_ie);
 	os_free(wnmtfs_ie);
+	os_free(oci_ie);
 	os_free(mgmt);
 
 	return res;
@@ -256,6 +301,10 @@
 	/* multiple TFS Resp IE (assuming consecutive) */
 	const u8 *tfsresp_ie_start = NULL;
 	const u8 *tfsresp_ie_end = NULL;
+#ifdef CONFIG_OCV
+	const u8 *oci_ie = NULL;
+	u8 oci_ie_len = 0;
+#endif /* CONFIG_OCV */
 	size_t left;
 
 	if (!wpa_s->wnmsleep_used) {
@@ -289,6 +338,12 @@
 			if (!tfsresp_ie_start)
 				tfsresp_ie_start = pos;
 			tfsresp_ie_end = pos;
+#ifdef CONFIG_OCV
+		} else if (*pos == WLAN_EID_EXTENSION && ie_len >= 1 &&
+			   pos[2] == WLAN_EID_EXT_OCV_OCI) {
+			oci_ie = pos + 3;
+			oci_ie_len = ie_len - 1;
+#endif /* CONFIG_OCV */
 		} else
 			wpa_printf(MSG_DEBUG, "EID %d not recognized", *pos);
 		pos += ie_len + 2;
@@ -299,6 +354,26 @@
 		return;
 	}
 
+#ifdef CONFIG_OCV
+	if (wnmsleep_ie->action_type == WNM_SLEEP_MODE_EXIT &&
+	    wpa_sm_ocv_enabled(wpa_s->wpa)) {
+		struct wpa_channel_info ci;
+
+		if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
+			wpa_msg(wpa_s, MSG_WARNING,
+				"Failed to get channel info to validate received OCI in WNM-Sleep Mode frame");
+			return;
+		}
+
+		if (ocv_verify_tx_params(oci_ie, oci_ie_len, &ci,
+					 channel_width_to_int(ci.chanwidth),
+					 ci.seg1_idx) != 0) {
+			wpa_msg(wpa_s, MSG_WARNING, "WNM: %s", ocv_errorstr);
+			return;
+		}
+	}
+#endif /* CONFIG_OCV */
+
 	wpa_s->wnmsleep_used = 0;
 
 	if (wnmsleep_ie->status == WNM_STATUS_SLEEP_ACCEPT ||
@@ -700,7 +775,7 @@
 			continue;
 		}
 
-		if (wpa_is_bss_tmp_disallowed(wpa_s, target->bssid)) {
+		if (wpa_is_bss_tmp_disallowed(wpa_s, target)) {
 			wpa_printf(MSG_DEBUG,
 				   "MBO: Candidate BSS " MACSTR
 				   " retry delay is not over yet",
@@ -945,6 +1020,9 @@
 		return;
 	}
 
+	wpa_s->bss_tm_status = status;
+	wpas_notify_bss_tm_status(wpa_s);
+
 	wpabuf_put_u8(buf, WLAN_ACTION_WNM);
 	wpabuf_put_u8(buf, WNM_BSS_TRANS_MGMT_RESP);
 	wpabuf_put_u8(buf, dialog_token);
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index 05e3ebf..9881021 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant - command line interface for wpa_supplicant daemon
- * Copyright (c) 2004-2017, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -29,7 +29,7 @@
 
 static const char *const wpa_cli_version =
 "wpa_cli v" VERSION_STR "\n"
-"Copyright (c) 2004-2017, Jouni Malinen <j@w1.fi> and contributors";
+"Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi> and contributors";
 
 #define VENDOR_ELEM_FRAME_ID \
 	"  0: Probe Req (P2P), 1: Probe Resp (P2P) , 2: Probe Resp (GO), " \
@@ -49,6 +49,7 @@
 static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
 static const char *client_socket_dir = NULL;
 static char *ctrl_ifname = NULL;
+static const char *global = NULL;
 static const char *pid_file = NULL;
 static const char *action_file = NULL;
 static int ping_interval = 5;
@@ -74,6 +75,7 @@
 static void update_creds(struct wpa_ctrl *ctrl);
 static void update_networks(struct wpa_ctrl *ctrl);
 static void update_stations(struct wpa_ctrl *ctrl);
+static void update_ifnames(struct wpa_ctrl *ctrl);
 
 
 static void usage(void)
@@ -1203,6 +1205,39 @@
 }
 
 
+static int wpa_cli_cmd_psk_passphrase(struct wpa_ctrl *ctrl, int argc,
+				      char *argv[])
+{
+	char cmd[256], *pos, *end;
+	int i, ret;
+
+	if (argc < 2) {
+		printf("Invalid PSK_PASSPHRASE command: needs two arguments (network id and PSK/passphrase)\n");
+		return -1;
+	}
+
+	end = cmd + sizeof(cmd);
+	pos = cmd;
+	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PSK_PASSPHRASE-%s:%s",
+			  argv[0], argv[1]);
+	if (os_snprintf_error(end - pos, ret)) {
+		printf("Too long PSK_PASSPHRASE command.\n");
+		return -1;
+	}
+	pos += ret;
+	for (i = 2; i < argc; i++) {
+		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
+		if (os_snprintf_error(end - pos, ret)) {
+			printf("Too long PSK_PASSPHRASE command.\n");
+			return -1;
+		}
+		pos += ret;
+	}
+
+	return wpa_ctrl_command(ctrl, cmd);
+}
+
+
 static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
 				  char *argv[])
 {
@@ -1412,7 +1447,7 @@
 #ifdef CONFIG_HT_OVERRIDES
 	"disable_ht", "disable_ht40", "disable_sgi", "disable_ldpc",
 	"ht40_intolerant", "disable_max_amsdu", "ampdu_factor",
-	"ampdu_density", "ht_mcs",
+	"ampdu_density", "ht_mcs", "rx_stbc", "tx_stbc",
 #endif /* CONFIG_HT_OVERRIDES */
 #ifdef CONFIG_VHT_OVERRIDES
 	"disable_vht", "vht_capa", "vht_capa_mask", "vht_rx_mcs_nss_1",
@@ -1426,6 +1461,8 @@
 #ifdef CONFIG_MACSEC
 	"macsec_policy",
 	"macsec_integ_only",
+	"macsec_replay_protect",
+	"macsec_replay_window",
 	"macsec_port",
 	"mka_priority",
 #endif /* CONFIG_MACSEC */
@@ -2955,6 +2992,13 @@
 }
 
 
+static int wpa_cli_cmd_dpp_configurator_sign(struct wpa_ctrl *ctrl, int argc,
+					     char *argv[])
+{
+	return wpa_cli_cmd(ctrl, "DPP_CONFIGURATOR_SIGN", 1, argc, argv);
+}
+
+
 static int wpa_cli_cmd_dpp_pkex_add(struct wpa_ctrl *ctrl, int argc,
 				    char *argv[])
 {
@@ -3084,6 +3128,9 @@
 	  cli_cmd_flag_sensitive,
 	  "<network id> <password> = configure one-time-password for an SSID"
 	},
+	{ "psk_passphrase", wpa_cli_cmd_psk_passphrase,
+	  wpa_cli_complete_network_id, cli_cmd_flag_sensitive,
+	  "<network id> <PSK/passphrase> = configure PSK/passphrase for an SSID" },
 	{ "passphrase", wpa_cli_cmd_passphrase, wpa_cli_complete_network_id,
 	  cli_cmd_flag_sensitive,
 	  "<network id> <passphrase> = configure private key passphrase\n"
@@ -3614,6 +3661,9 @@
 	{ "dpp_configurator_get_key", wpa_cli_cmd_dpp_configurator_get_key,
 	  NULL, cli_cmd_flag_none,
 	  "<id> = Get DPP configurator's private key" },
+	{ "dpp_configurator_sign", wpa_cli_cmd_dpp_configurator_sign, NULL,
+	  cli_cmd_flag_none,
+	  "conf=<role> configurator=<id> = generate self DPP configuration" },
 	{ "dpp_pkex_add", wpa_cli_cmd_dpp_pkex_add, NULL,
 	  cli_cmd_flag_sensitive,
 	  "add PKEX code" },
@@ -3972,10 +4022,46 @@
 #endif /* CONFIG_ANSI_C_EXTRA */
 
 
+static int wpa_cli_open_global_ctrl(void)
+{
+#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
+	ctrl_conn = wpa_ctrl_open(NULL);
+#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
+	ctrl_conn = wpa_ctrl_open(global);
+#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
+	if (!ctrl_conn) {
+		fprintf(stderr,
+			"Failed to connect to wpa_supplicant global interface: %s  error: %s\n",
+			global, strerror(errno));
+		return -1;
+	}
+
+	if (interactive) {
+		update_ifnames(ctrl_conn);
+		mon_conn = wpa_ctrl_open(global);
+		if (mon_conn) {
+			if (wpa_ctrl_attach(mon_conn) == 0) {
+				wpa_cli_attached = 1;
+				eloop_register_read_sock(
+					wpa_ctrl_get_fd(mon_conn),
+					wpa_cli_mon_receive,
+					NULL, NULL);
+			} else {
+				printf("Failed to open monitor connection through global control interface\n");
+			}
+		}
+		update_stations(ctrl_conn);
+	}
+
+	return 0;
+}
+
+
 static void wpa_cli_reconnect(void)
 {
 	wpa_cli_close_connection();
-	if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
+	if ((global && wpa_cli_open_global_ctrl() < 0) ||
+	    (!global && wpa_cli_open_connection(ctrl_ifname, 1) < 0))
 		return;
 
 	if (interactive) {
@@ -4534,7 +4620,6 @@
 	int c;
 	int daemonize = 0;
 	int ret = 0;
-	const char *global = NULL;
 
 	if (os_program_init())
 		return -1;
@@ -4589,38 +4674,8 @@
 	if (eloop_init())
 		return -1;
 
-	if (global) {
-#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
-		ctrl_conn = wpa_ctrl_open(NULL);
-#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
-		ctrl_conn = wpa_ctrl_open(global);
-#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
-		if (ctrl_conn == NULL) {
-			fprintf(stderr, "Failed to connect to wpa_supplicant "
-				"global interface: %s  error: %s\n",
-				global, strerror(errno));
-			return -1;
-		}
-
-		if (interactive) {
-			update_ifnames(ctrl_conn);
-			mon_conn = wpa_ctrl_open(global);
-			if (mon_conn) {
-				if (wpa_ctrl_attach(mon_conn) == 0) {
-					wpa_cli_attached = 1;
-					eloop_register_read_sock(
-						wpa_ctrl_get_fd(mon_conn),
-						wpa_cli_mon_receive,
-						NULL, NULL);
-				} else {
-					printf("Failed to open monitor "
-					       "connection through global "
-					       "control interface\n");
-				}
-			}
-			update_stations(ctrl_conn);
-		}
-	}
+	if (global && wpa_cli_open_global_ctrl() < 0)
+		return -1;
 
 	eloop_register_signal_terminate(wpa_cli_terminate, NULL);
 
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 4432ec3..a2f0b31 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant
- * Copyright (c) 2003-2018, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2019, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -68,7 +68,7 @@
 
 const char *const wpa_supplicant_version =
 "wpa_supplicant v" VERSION_STR "\n"
-"Copyright (c) 2003-2017, Jouni Malinen <j@w1.fi> and contributors";
+"Copyright (c) 2003-2019, Jouni Malinen <j@w1.fi> and contributors";
 
 const char *const wpa_supplicant_license =
 "This software may be distributed under the terms of the BSD license.\n"
@@ -445,7 +445,7 @@
 }
 
 
-static void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
+void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
 {
 	struct wpa_bss_tmp_disallowed *bss, *prev;
 
@@ -847,6 +847,23 @@
 		wpa_supplicant_state_txt(wpa_s->wpa_state),
 		wpa_supplicant_state_txt(state));
 
+	if (state == WPA_COMPLETED &&
+	    os_reltime_initialized(&wpa_s->roam_start)) {
+		os_reltime_age(&wpa_s->roam_start, &wpa_s->roam_time);
+		wpa_s->roam_start.sec = 0;
+		wpa_s->roam_start.usec = 0;
+		wpas_notify_auth_changed(wpa_s);
+		wpas_notify_roam_time(wpa_s);
+		wpas_notify_roam_complete(wpa_s);
+	} else if (state == WPA_DISCONNECTED &&
+		   os_reltime_initialized(&wpa_s->roam_start)) {
+		wpa_s->roam_start.sec = 0;
+		wpa_s->roam_start.usec = 0;
+		wpa_s->roam_time.sec = 0;
+		wpa_s->roam_time.usec = 0;
+		wpas_notify_roam_complete(wpa_s);
+	}
+
 	if (state == WPA_INTERFACE_DISABLED) {
 		/* Assure normal scan when interface is restored */
 		wpa_s->normal_scans = 0;
@@ -1217,13 +1234,12 @@
 		wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
 		proto = WPA_PROTO_WPA;
 #ifdef CONFIG_HS20
-	} else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN)) {
+	} else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN) &&
+		   wpa_parse_wpa_ie(bss_osen, 2 + bss_osen[1], &ie) == 0 &&
+		   (ie.group_cipher & ssid->group_cipher) &&
+		   (ie.pairwise_cipher & ssid->pairwise_cipher) &&
+		   (ie.key_mgmt & ssid->key_mgmt)) {
 		wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
-		/* TODO: parse OSEN element */
-		os_memset(&ie, 0, sizeof(ie));
-		ie.group_cipher = WPA_CIPHER_CCMP;
-		ie.pairwise_cipher = WPA_CIPHER_CCMP;
-		ie.key_mgmt = WPA_KEY_MGMT_OSEN;
 		proto = WPA_PROTO_OSEN;
 	} else if (bss_rsn && (ssid->proto & WPA_PROTO_OSEN) &&
 	    wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
@@ -1513,6 +1529,9 @@
 	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
 			 wpas_get_ssid_pmf(wpa_s, ssid));
 #endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_OCV
+	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv);
+#endif /* CONFIG_OCV */
 
 	if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
 		wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
@@ -1903,6 +1922,8 @@
 		if (wpa_s->current_bss && wpa_s->current_bss == bss) {
 			wmm_ac_save_tspecs(wpa_s);
 			wpa_s->reassoc_same_bss = 1;
+		} else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
+			os_get_reltime(&wpa_s->roam_start);
 		}
 	}
 
@@ -2171,9 +2192,14 @@
 	if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
 		return;
 
+	freq->channel = pri_chan->chan;
+
 #ifdef CONFIG_HT_OVERRIDES
-	if (ssid->disable_ht40)
-		return;
+	if (ssid->disable_ht40) {
+		if (ssid->disable_vht)
+			return;
+		goto skip_ht40;
+	}
 #endif /* CONFIG_HT_OVERRIDES */
 
 	/* Check/setup HT40+/HT40- */
@@ -2198,8 +2224,6 @@
 	if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
 		return;
 
-	freq->channel = pri_chan->chan;
-
 	if (ht40 == -1) {
 		if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
 			return;
@@ -2243,6 +2267,9 @@
 		wpa_scan_results_free(scan_res);
 	}
 
+#ifdef CONFIG_HT_OVERRIDES
+skip_ht40:
+#endif /* CONFIG_HT_OVERRIDES */
 	wpa_printf(MSG_DEBUG,
 		   "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
 		   freq->channel, freq->sec_channel_offset);
@@ -2332,6 +2359,13 @@
 			vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
 			seg0 = 114;
 		}
+	} else if (ssid->max_oper_chwidth == VHT_CHANWIDTH_USE_HT) {
+		chwidth = VHT_CHANWIDTH_USE_HT;
+		seg0 = vht80[j] + 2;
+#ifdef CONFIG_HT_OVERRIDES
+		if (ssid->disable_ht40)
+			seg0 = 0;
+#endif /* CONFIG_HT_OVERRIDES */
 	}
 
 	if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
@@ -2499,6 +2533,19 @@
 			os_free(wpa_ie);
 			return NULL;
 		}
+#ifdef CONFIG_HS20
+	} else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
+		   (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
+		/* No PMKSA caching, but otherwise similar to RSN/WPA */
+		wpa_ie_len = max_wpa_ie_len;
+		if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
+					      wpa_ie, &wpa_ie_len)) {
+			wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
+				"key management and encryption suites");
+			os_free(wpa_ie);
+			return NULL;
+		}
+#endif /* CONFIG_HS20 */
 	} else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
 		   wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
 		/*
@@ -2622,7 +2669,7 @@
 #endif /* CONFIG_P2P */
 
 	if (bss) {
-		wpa_ie_len += wpas_supp_op_class_ie(wpa_s, bss->freq,
+		wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss->freq,
 						    wpa_ie + wpa_ie_len,
 						    max_wpa_ie_len -
 						    wpa_ie_len);
@@ -2667,7 +2714,8 @@
 			int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
 			size_t len;
 
-			wpas_hs20_add_indication(hs20, pps_mo_id);
+			wpas_hs20_add_indication(hs20, pps_mo_id,
+						 get_hs20_version(bss));
 			wpas_hs20_add_roam_cons_sel(hs20, ssid);
 			len = max_wpa_ie_len - wpa_ie_len;
 			if (wpabuf_len(hs20) <= len) {
@@ -2743,14 +2791,18 @@
 
 		if (ssid->owe_group) {
 			group = ssid->owe_group;
-		} else {
+		} else if (wpa_s->assoc_status_code ==
+			   WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
 			if (wpa_s->last_owe_group == 19)
 				group = 20;
 			else if (wpa_s->last_owe_group == 20)
 				group = 21;
 			else
 				group = OWE_DH_GROUP;
+		} else {
+			group = OWE_DH_GROUP;
 		}
+
 		wpa_s->last_owe_group = group;
 		wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
 		owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
@@ -2797,6 +2849,21 @@
 	}
 #endif /* CONFIG_IEEE80211R */
 
+	if (ssid->multi_ap_backhaul_sta) {
+		size_t multi_ap_ie_len;
+
+		multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
+						  max_wpa_ie_len - wpa_ie_len,
+						  MULTI_AP_BACKHAUL_STA);
+		if (multi_ap_ie_len == 0) {
+			wpa_printf(MSG_ERROR,
+				   "Multi-AP: Failed to build Multi-AP IE");
+			os_free(wpa_ie);
+			return NULL;
+		}
+		wpa_ie_len += multi_ap_ie_len;
+	}
+
 	params->wpa_ie = wpa_ie;
 	params->wpa_ie_len = wpa_ie_len;
 	params->auth_alg = algs;
@@ -3040,7 +3107,7 @@
 	}
 	params.wep_tx_keyidx = ssid->wep_tx_keyidx;
 
-	if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
+	if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
 	    (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
 	     params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
 		params.passphrase = ssid->passphrase;
@@ -3048,6 +3115,13 @@
 			params.psk = ssid->psk;
 	}
 
+	if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
+	    (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
+	     params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
+	     params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
+	     params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192))
+		params.req_key_mgmt_offload = 1;
+
 	if (wpa_s->conf->key_mgmt_offload) {
 		if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
 		    params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
@@ -3275,6 +3349,9 @@
 		zero_addr = 1;
 	}
 
+	if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
+		wpa_s->enabled_4addr_mode = 0;
+
 #ifdef CONFIG_TDLS
 	wpa_tdls_teardown_peers(wpa_s->wpa);
 #endif /* CONFIG_TDLS */
@@ -4044,7 +4121,7 @@
 	}
 
 	if (wpa_s->eapol_received == 0 &&
-	    (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
+	    (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
 	     !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
 	     wpa_s->wpa_state != WPA_COMPLETED) &&
 	    (wpa_s->current_ssid == NULL ||
@@ -4110,7 +4187,7 @@
 	    eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
 		return;
 	wpa_drv_poll(wpa_s);
-	if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
+	if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
 		wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
 	else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
 		/*
@@ -4474,6 +4551,58 @@
 }
 
 
+static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
+			   struct ieee80211_ht_capabilities *htcaps,
+			   struct ieee80211_ht_capabilities *htcaps_mask,
+			   int tx_stbc)
+{
+	le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
+
+	wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
+
+	if (tx_stbc == -1)
+		return 0;
+
+	if (tx_stbc < 0 || tx_stbc > 1) {
+		wpa_msg(wpa_s, MSG_ERROR,
+			"tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
+		return -EINVAL;
+	}
+
+	htcaps_mask->ht_capabilities_info |= msk;
+	htcaps->ht_capabilities_info &= ~msk;
+	htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
+
+	return 0;
+}
+
+
+static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
+			   struct ieee80211_ht_capabilities *htcaps,
+			   struct ieee80211_ht_capabilities *htcaps_mask,
+			   int rx_stbc)
+{
+	le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
+
+	wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
+
+	if (rx_stbc == -1)
+		return 0;
+
+	if (rx_stbc < 0 || rx_stbc > 3) {
+		wpa_msg(wpa_s, MSG_ERROR,
+			"rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
+		return -EINVAL;
+	}
+
+	htcaps_mask->ht_capabilities_info |= msk;
+	htcaps->ht_capabilities_info &= ~msk;
+	htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
+
+	return 0;
+}
+
+
 void wpa_supplicant_apply_ht_overrides(
 	struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
 	struct wpa_driver_associate_params *params)
@@ -4498,6 +4627,8 @@
 	wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
 	wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
 	wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
+	wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
+	wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
 
 	if (ssid->ht40_intolerant) {
 		le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
@@ -4532,6 +4663,16 @@
 	vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
 
 #ifdef CONFIG_HT_OVERRIDES
+	if (ssid->disable_sgi) {
+		vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
+							VHT_CAP_SHORT_GI_160);
+		vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
+						    VHT_CAP_SHORT_GI_160);
+		wpa_msg(wpa_s, MSG_DEBUG,
+			"disable-sgi override specified, vht-caps: 0x%x",
+			vhtcaps->vht_capabilities_info);
+	}
+
 	/* if max ampdu is <= 3, we have to make the HT cap the same */
 	if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
 		int max_ampdu;
@@ -5545,6 +5686,12 @@
 		    capa.mac_addr_rand_sched_scan_supported)
 			wpa_s->mac_addr_rand_supported |=
 				(MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
+
+		wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
+		if (wpa_s->extended_capa &&
+		    wpa_s->extended_capa_len >= 3 &&
+		    wpa_s->extended_capa[2] & 0x40)
+			wpa_s->multi_bss_support = 1;
 	}
 	if (wpa_s->max_remain_on_chan == 0)
 		wpa_s->max_remain_on_chan = 1000;
@@ -7204,16 +7351,14 @@
 
 
 void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
-			  unsigned int sec)
+			  unsigned int sec, int rssi_threshold)
 {
 	struct wpa_bss_tmp_disallowed *bss;
 
 	bss = wpas_get_disallowed_bss(wpa_s, bssid);
 	if (bss) {
 		eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
-		eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
-				       wpa_s, bss);
-		return;
+		goto finish;
 	}
 
 	bss = os_malloc(sizeof(*bss));
@@ -7226,23 +7371,31 @@
 	os_memcpy(bss->bssid, bssid, ETH_ALEN);
 	dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
 	wpa_set_driver_tmp_disallow_list(wpa_s);
+
+finish:
+	bss->rssi_threshold = rssi_threshold;
 	eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
 			       wpa_s, bss);
 }
 
 
-int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s, const u8 *bssid)
+int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
+			      struct wpa_bss *bss)
 {
-	struct wpa_bss_tmp_disallowed *bss = NULL, *tmp, *prev;
+	struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
 
 	dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
 			 struct wpa_bss_tmp_disallowed, list) {
-		if (os_memcmp(bssid, tmp->bssid, ETH_ALEN) == 0) {
-			bss = tmp;
+		if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) {
+			disallowed = tmp;
 			break;
 		}
 	}
-	if (!bss)
+	if (!disallowed)
+		return 0;
+
+	if (disallowed->rssi_threshold != 0 &&
+	    bss->level > disallowed->rssi_threshold)
 		return 0;
 
 	return 1;
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index 4f59160..1bd43b2 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -907,6 +907,13 @@
 # PMF required: ieee80211w=2 and key_mgmt=WPA-EAP-SHA256
 # (and similarly for WPA-PSK and WPA-WPSK-SHA256 if WPA2-Personal is used)
 #
+# ocv: whether operating channel validation is enabled
+# 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
+#ocv=1
+#
 # auth_alg: list of allowed IEEE 802.11 authentication algorithms
 # OPEN = Open System authentication (required for WPA/WPA2)
 # SHARED = Shared Key authentication (requires static WEP keys)
@@ -987,6 +994,22 @@
 # 0: Encrypt traffic (default)
 # 1: Integrity only
 #
+# macsec_replay_protect: IEEE 802.1X/MACsec replay protection
+# This setting applies only when MACsec is in use, i.e.,
+#  - macsec_policy is enabled
+#  - the key server has decided to enable MACsec
+# 0: Replay protection disabled (default)
+# 1: Replay protection enabled
+#
+# macsec_replay_window: IEEE 802.1X/MACsec replay protection window
+# This determines a window in which replay is tolerated, to allow receipt
+# of frames that have been misordered by the network.
+# This setting applies only when MACsec replay protection active, i.e.,
+#  - macsec_replay_protect is enabled
+#  - the key server has decided to enable MACsec
+# 0: No replay window, strict check (default)
+# 1..2^32-1: number of packets that could be misordered
+#
 # macsec_port: IEEE 802.1X/MACsec port
 # Port component of the SCI
 # Range: 1-65534 (default: 1)
@@ -995,9 +1018,10 @@
 # This allows to configure MACsec with a pre-shared key using a (CAK,CKN) pair.
 # In this mode, instances of wpa_supplicant can act as MACsec peers. The peer
 # with lower priority will become the key server and start distributing SAKs.
-# mka_cak (CAK = Secure Connectivity Association Key) takes a 16-bytes (128 bit)
-# hex-string (32 hex-digits)
-# mka_ckn (CKN = CAK Name) takes a 32-bytes (256 bit) hex-string (64 hex-digits)
+# mka_cak (CAK = Secure Connectivity Association Key) takes a 16-byte (128-bit)
+# hex-string (32 hex-digits) or a 32-byte (256-bit) hex-string (64 hex-digits)
+# mka_ckn (CKN = CAK Name) takes a 1..32-bytes (8..256 bit) hex-string
+# (2..64 hex-digits)
 # mka_priority (Priority of MKA Actor) is in 0..255 range with 255 being
 # default priority
 #
@@ -1216,12 +1240,19 @@
 #	For EAP-FAST, this must be set to 0 (or left unconfigured for the
 #	default value to be used automatically).
 # tls_disable_tlsv1_0=1 - disable use of TLSv1.0
+# tls_disable_tlsv1_0=0 - explicitly enable use of TLSv1.0 (this allows
+#	systemwide TLS policies to be overridden)
 # tls_disable_tlsv1_1=1 - disable use of TLSv1.1 (a workaround for AAA servers
 #	that have issues interoperating with updated TLS version)
+# tls_disable_tlsv1_1=0 - explicitly enable use of TLSv1.1 (this allows
+#	systemwide TLS policies to be overridden)
 # tls_disable_tlsv1_2=1 - disable use of TLSv1.2 (a workaround for AAA servers
 #	that have issues interoperating with updated TLS version)
+# tls_disable_tlsv1_2=0 - explicitly enable use of TLSv1.2 (this allows
+#	systemwide TLS policies to be overridden)
 # tls_disable_tlsv1_3=1 - disable use of TLSv1.3 (a workaround for AAA servers
 #	that have issues interoperating with updated TLS version)
+# tls_disable_tlsv1_3=0 - enable TLSv1.3 (experimental - disabled by default)
 # tls_ext_cert_check=0 - No external server certificate validation (default)
 # tls_ext_cert_check=1 - External server certificate validation enabled; this
 #	requires an external program doing validation of server certificate
@@ -1381,6 +1412,20 @@
 #  Treated as hint by the kernel.
 # -1 = Do not make any changes.
 # 0-3 = Set AMPDU density (aka factor) to specified value.
+#
+# tx_stbc: Allow overriding STBC support for TX streams
+# Value: 0-1, see IEEE Std 802.11-2016, 9.4.2.56.2.
+# -1 = Do not make any changes (default)
+# 0 = Set if not supported
+# 1 = Set if supported
+#
+# rx_stbc: Allow overriding STBC support for RX streams
+# Value: 0-3, see IEEE Std 802.11-2016, 9.4.2.56.2.
+# -1 = Do not make any changes (default)
+# 0 = Set if not supported
+# 1 = Set for support of one spatial stream
+# 2 = Set for support of one and two spatial streams
+# 3 = Set for support of one, two and three spatial streams
 
 # disable_vht: Whether VHT should be disabled.
 # 0 = VHT enabled (if AP supports it)
@@ -1396,6 +1441,13 @@
 #  2: MCS 0-9
 #  3: not supported
 
+# multi_ap_backhaul_sta: Multi-AP backhaul STA functionality
+# 0 = normal STA (default)
+# 1 = backhaul STA
+# A backhaul STA sends the Multi-AP IE, fails to associate if the AP does not
+# support Multi-AP, and sets 4-address mode if it does. Thus, the netdev can be
+# added to a bridge to allow forwarding frames over this backhaul link.
+
 ##### Fast Session Transfer (FST) support #####################################
 #
 # The options in this section are only available when the build configuration
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index abacaa9..9cb4ad3 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -451,10 +451,12 @@
 struct wpa_bss_tmp_disallowed {
 	struct dl_list list;
 	u8 bssid[ETH_ALEN];
+	int rssi_threshold;
 };
 
 struct beacon_rep_data {
 	u8 token;
+	u8 last_indication;
 	struct wpa_driver_scan_params scan_params;
 	u8 ssid[SSID_MAX_LEN];
 	size_t ssid_len;
@@ -492,6 +494,10 @@
 	struct wpa_supplicant *next;
 	struct l2_packet_data *l2;
 	struct l2_packet_data *l2_br;
+	struct os_reltime roam_start;
+	struct os_reltime roam_time;
+	struct os_reltime session_start;
+	struct os_reltime session_length;
 	unsigned char own_addr[ETH_ALEN];
 	unsigned char perm_addr[ETH_ALEN];
 	char ifname[100];
@@ -814,6 +820,7 @@
 	unsigned int mesh_if_created:1;
 	unsigned int mesh_ht_enabled:1;
 	unsigned int mesh_vht_enabled:1;
+	struct wpa_driver_mesh_join_params *mesh_params;
 #ifdef CONFIG_PMKSA_CACHE_EXTERNAL
 	/* struct external_pmksa_cache::list */
 	struct dl_list mesh_external_pmksa_cache;
@@ -911,6 +918,7 @@
 	unsigned int p2p_pd_before_go_neg:1;
 	unsigned int p2p_go_ht40:1;
 	unsigned int p2p_go_vht:1;
+	unsigned int p2p_go_he:1;
 	unsigned int user_initiated_pd:1;
 	unsigned int p2p_go_group_formation_completed:1;
 	unsigned int group_formation_reported:1;
@@ -1018,6 +1026,10 @@
 	/* WLAN_REASON_* reason codes. Negative if locally generated. */
 	int disconnect_reason;
 
+	/* WLAN_STATUS_* status codes from last received Authentication frame
+	 * from the AP. */
+	u16 auth_status_code;
+
 	/* WLAN_STATUS_* status codes from (Re)Association Response frame. */
 	u16 assoc_status_code;
 	/* Indicates if the previous association request timed out. */
@@ -1061,6 +1073,7 @@
 	struct neighbor_report *wnm_neighbor_report_elements;
 	struct os_reltime wnm_cand_valid_until;
 	u8 wnm_cand_from_bss[ETH_ALEN];
+	enum bss_trans_mgmt_status_code bss_tm_status;
 	struct wpabuf *coloc_intf_elems;
 	u8 coloc_intf_dialog_token;
 	u8 coloc_intf_auto_report;
@@ -1236,6 +1249,8 @@
 	unsigned int disable_fils:1;
 #endif /* CONFIG_FILS */
 	unsigned int ieee80211ac:1;
+	unsigned int enabled_4addr_mode:1;
+	unsigned int multi_bss_support:1;
 };
 
 
@@ -1371,6 +1386,8 @@
 		int add_oce_capa);
 const u8 * mbo_attr_from_mbo_ie(const u8 *mbo_ie, enum mbo_attr_id attr);
 const u8 * wpas_mbo_get_bss_attr(struct wpa_bss *bss, enum mbo_attr_id attr);
+const u8 * mbo_get_attr_from_ies(const u8 *ies, size_t ies_len,
+				 enum mbo_attr_id attr);
 int wpas_mbo_update_non_pref_chan(struct wpa_supplicant *wpa_s,
 				  const char *non_pref_chan);
 void wpas_mbo_scan_ie(struct wpa_supplicant *wpa_s, struct wpabuf *ie);
@@ -1393,8 +1410,9 @@
 
 enum chan_allowed verify_channel(struct hostapd_hw_modes *mode, u8 channel,
 				 u8 bw);
-size_t wpas_supp_op_class_ie(struct wpa_supplicant *wpa_s, int freq, u8 *pos,
-			      size_t len);
+size_t wpas_supp_op_class_ie(struct wpa_supplicant *wpa_s,
+			     struct wpa_ssid *ssid,
+			     int freq, u8 *pos, size_t len);
 
 /**
  * wpa_supplicant_ctrl_iface_ctrl_rsp_handle - Handle a control response
@@ -1441,6 +1459,8 @@
 struct wpa_bss * wpa_supplicant_pick_network(struct wpa_supplicant *wpa_s,
 					     struct wpa_ssid **selected_ssid);
 int wpas_temp_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
+void wpa_supplicant_update_channel_list(struct wpa_supplicant *wpa_s,
+					struct channel_list_changed *info);
 
 /* eap_register.c */
 int eap_register_methods(void);
@@ -1493,8 +1513,10 @@
 				   u16 num_modes, enum hostapd_hw_mode mode);
 
 void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
-			  unsigned int sec);
-int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s, const u8 *bssid);
+			  unsigned int sec, int rssi_threshold);
+int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
+			      struct wpa_bss *bss);
+void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s);
 
 struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
 				     int i, struct wpa_bss *bss,
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index 4634ed7..449e04a 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -296,7 +296,7 @@
 	}
 
 	if (result != EAPOL_SUPP_RESULT_SUCCESS ||
-	    !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
+	    !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X))
 		return;
 
 	if (!wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt))
@@ -1183,6 +1183,15 @@
 	os_free(hex);
 }
 
+
+static int wpa_supplicant_channel_info(void *_wpa_s,
+				       struct wpa_channel_info *ci)
+{
+	struct wpa_supplicant *wpa_s = _wpa_s;
+
+	return wpa_drv_channel_info(wpa_s, ci);
+}
+
 #endif /* CONFIG_NO_WPA */
 
 
@@ -1233,6 +1242,7 @@
 	ctx->set_rekey_offload = wpa_supplicant_set_rekey_offload;
 	ctx->key_mgmt_set_pmk = wpa_supplicant_key_mgmt_set_pmk;
 	ctx->fils_hlp_rx = wpa_supplicant_fils_hlp_rx;
+	ctx->channel_info = wpa_supplicant_channel_info;
 
 	wpa_s->wpa = wpa_sm_init(ctx);
 	if (wpa_s->wpa == NULL) {
diff --git a/wpa_supplicant/wpas_kay.c b/wpa_supplicant/wpas_kay.c
index d3d06b8..41477d5 100644
--- a/wpa_supplicant/wpas_kay.c
+++ b/wpa_supplicant/wpas_kay.c
@@ -92,6 +92,12 @@
 }
 
 
+static int wpas_set_receive_lowest_pn(void *wpa_s, struct receive_sa *sa)
+{
+	return wpa_drv_set_receive_lowest_pn(wpa_s, sa);
+}
+
+
 static unsigned int conf_offset_val(enum confidentiality_offset co)
 {
 	switch (co) {
@@ -219,6 +225,7 @@
 	kay_ctx->get_receive_lowest_pn = wpas_get_receive_lowest_pn;
 	kay_ctx->get_transmit_next_pn = wpas_get_transmit_next_pn;
 	kay_ctx->set_transmit_next_pn = wpas_set_transmit_next_pn;
+	kay_ctx->set_receive_lowest_pn = wpas_set_receive_lowest_pn;
 	kay_ctx->create_receive_sc = wpas_create_receive_sc;
 	kay_ctx->delete_receive_sc = wpas_delete_receive_sc;
 	kay_ctx->create_receive_sa = wpas_create_receive_sa;
@@ -232,7 +239,8 @@
 	kay_ctx->enable_transmit_sa = wpas_enable_transmit_sa;
 	kay_ctx->disable_transmit_sa = wpas_disable_transmit_sa;
 
-	res = ieee802_1x_kay_init(kay_ctx, policy, ssid->macsec_port,
+	res = ieee802_1x_kay_init(kay_ctx, policy, ssid->macsec_replay_protect,
+				  ssid->macsec_replay_window, ssid->macsec_port,
 				  ssid->mka_priority, wpa_s->ifname,
 				  wpa_s->own_addr);
 	/* ieee802_1x_kay_init() frees kay_ctx on failure */
@@ -349,8 +357,8 @@
 
 	/* Derive CAK from MSK */
 	cak->len = DEFAULT_KEY_LEN;
-	if (ieee802_1x_cak_128bits_aes_cmac(msk->key, wpa_s->own_addr,
-					    peer_addr, cak->key)) {
+	if (ieee802_1x_cak_aes_cmac(msk->key, msk->len, wpa_s->own_addr,
+				    peer_addr, cak->key, cak->len)) {
 		wpa_printf(MSG_ERROR,
 			   "IEEE 802.1X: Deriving CAK failed");
 		goto fail;
@@ -359,9 +367,8 @@
 
 	/* Derive CKN from MSK */
 	ckn->len = DEFAULT_CKN_LEN;
-	if (ieee802_1x_ckn_128bits_aes_cmac(msk->key, wpa_s->own_addr,
-					    peer_addr, sid, sid_len,
-					    ckn->name)) {
+	if (ieee802_1x_ckn_aes_cmac(msk->key, msk->len, wpa_s->own_addr,
+				    peer_addr, sid, sid_len, ckn->name)) {
 		wpa_printf(MSG_ERROR,
 			   "IEEE 802.1X: Deriving CKN failed");
 		goto fail;
@@ -411,10 +418,10 @@
 	if (wpa_s->kay->policy == DO_NOT_SECURE)
 		goto dealloc;
 
-	cak->len = MACSEC_CAK_LEN;
+	cak->len = ssid->mka_cak_len;
 	os_memcpy(cak->key, ssid->mka_cak, cak->len);
 
-	ckn->len = MACSEC_CKN_LEN;
+	ckn->len = ssid->mka_ckn_len;
 	os_memcpy(ckn->name, ssid->mka_ckn, ckn->len);
 
 	res = ieee802_1x_kay_create_mka(wpa_s->kay, ckn, cak, 0, PSK, FALSE);