Cumulative patch from commit 12c1fdf19a721aaf29e1c77d63445c7f5b8c61c0

12c1fdf P2P: Update peer listen channel from Probe Request frames
a805731 P2P: Abort ongoing scan when p2p_find is stopped
7441698 nl80211: Abort an ongoing scan upon scan timeout indication
1446afc wpa_supplicant: Handle EVENT_SCAN_RESULTS when an interface is disabled
d14e63a WNM: Do not scan based on malformed BSS Transition Management Request
f420577 WNM: Fix candidates count in BSS Transition Management Request
3c58df7 wpa_cli: Support running action script on global control interface
b8f02d8 EAP-PWD peer: Fix possible memory leak on error path
8f38eed Android: Remove superfluous OpenSSL include paths
cbf8d18 HS 2.0R2: Clear fetch_anqp_in_progress if fopen fails
4a6e9e5 Fix CONFIG_WPA_TRACE=y compilation without CONFIG_WPA_TRACE_BFD=y
2bf9a53 Add EAP-AKA' and EAP-pwd to wpa_supplicant README
4196c08 Update notes about OpenSSL versions
5d7b1a3 Fix some typos in wpa_supplicant README files
4194fee README-P2P: Fix a typo
c58eed6 P2P: Add Dev Info attribute to Probe Request frames in 60 GHz
2b6e9f9 wpa_supplicant: Expose wpas_get_bands() and related API
94ad3c3 P2P: Change order of P2P IE and frequencies set up
61697c7 Android: Allow wpa_supplicant to write files to osu-info dir
0147afa FST: Enlarge State Transition Timeout (STT)
e1d00d4 Add error handling for offloaded ACS with vendor command failures
bef5e9a Fix scan rescheduling from wpas_stop_pno to check postponed case
b9ca12a nl80211: Add more address fields into RX frame debug message
debde14 RADIUS: Add Acct-Delay-Time into accounting messages
669b532 RADIUS: Update full message for interim accounting updates
251953b Document nas_identifier requirements for RADIUS accounting
902c07a Replace hostapd_mac_comp_empty() with is_zero_ether_addr()
5aef495 VLAN: Avoid use of libnl cache
732b1d2 nl80211: Clean up ifidx properly if interface in a bridge is removed
170c545 FT: Check destination MAC address on RRB receive
57b2c91 RADIUS: Allow RADIUS server to provide PSK instead of passphrase
d8912fd Cache hashed passphrase in RADIUS-based PSK delivery
f8e09bc Defer passphrase-to-PSK hashing out of 802.11 authentication ACL check
cc9c805 VLAN: Use stack instead of heap allocation for new interface name
d48d1b8 FT: Use BSSID as r1_key_holder if no value is configured
71456db FT: Check hapd->wpa_auth before RRB internal delivery
0270bde FT: Fix R0KH-R1KH protocol data length values
96a26ab P2P: Support dedicated P2P_DEVICE without separate group interface
ba307f8 P2P: Add a separate pointer to the P2P Device instance
e040197 GAS client: Make PMF check on RX more consistent
0645492 WNM: Optimize a single BSS transition management candidate scan
eb20cea nl80211: Add an option to specify the BSSID to scan for
adf0478 AP: Store STA supported operating classes information

Change-Id: If0ce28aae5591be783c38e5b60f7f9ff0fb9f8f2
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index d535eec..3d5c5e2 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -909,11 +909,23 @@
 # The own IP address of the access point (used as NAS-IP-Address)
 own_ip_addr=127.0.0.1
 
-# Optional NAS-Identifier string for RADIUS messages. When used, this should be
-# a unique to the NAS within the scope of the RADIUS server. For example, a
-# fully qualified domain name can be used here.
+# NAS-Identifier string for RADIUS messages. When used, this should be unique
+# to the NAS within the scope of the RADIUS server. Please note that hostapd
+# uses a separate RADIUS client for each BSS and as such, a unique
+# nas_identifier value should be configured separately for each BSS. This is
+# particularly important for cases where RADIUS accounting is used
+# (Accounting-On/Off messages are interpreted as clearing all ongoing sessions
+# and that may get interpreted as applying to all BSSes if the same
+# NAS-Identifier value is used.) For example, a fully qualified domain name
+# prefixed with a unique identifier of the BSS (e.g., BSSID) can be used here.
+#
 # When using IEEE 802.11r, nas_identifier must be set and must be between 1 and
 # 48 octets long.
+#
+# It is mandatory to configure either own_ip_addr or nas_identifier to be
+# compliant with the RADIUS protocol. When using RADIUS accounting, it is
+# strongly recommended that nas_identifier is set to a unique value for each
+# BSS.
 #nas_identifier=ap.example.com
 
 # RADIUS client forced local IP address for the access point
@@ -1260,6 +1272,7 @@
 
 # PMK-R1 Key Holder identifier (dot11FTR1KeyHolderID)
 # 6-octet identifier as a hex string.
+# Defaults to BSSID.
 #r1_key_holder=000102030405
 
 # Reassociation deadline in time units (TUs / 1.024 ms; range 1000..65535)
diff --git a/hs20/client/osu_client.c b/hs20/client/osu_client.c
index 35793c8..2907c64 100644
--- a/hs20/client/osu_client.c
+++ b/hs20/client/osu_client.c
@@ -2339,12 +2339,23 @@
 		return -1;
 
 	snprintf(fname, sizeof(fname), "%s/osu-info", dir);
-	if (mkdir(fname, S_IRWXU | S_IRWXG) < 0 && errno != EEXIST) {
+	if (mkdir(fname, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) < 0 &&
+	    errno != EEXIST) {
 		wpa_printf(MSG_INFO, "mkdir(%s) failed: %s",
 			   fname, strerror(errno));
 		return -1;
 	}
 
+#ifdef ANDROID
+	/* Allow processes running with Group ID as AID_WIFI
+	 * to read/write files from osu-info directory
+	 */
+	if (chown(fname, -1, AID_WIFI)) {
+		wpa_printf(MSG_INFO, "Could not chown osu-info directory: %s",
+			   strerror(errno));
+	}
+#endif /* ANDROID */
+
 	snprintf(buf, sizeof(buf), "SET osu_dir %s", fname);
 	if (wpa_command(ifname, buf) < 0) {
 		wpa_printf(MSG_INFO, "Failed to configure osu_dir to wpa_supplicant");
diff --git a/src/ap/accounting.c b/src/ap/accounting.c
index 9357a46..854174e 100644
--- a/src/ap/accounting.c
+++ b/src/ap/accounting.c
@@ -152,6 +152,15 @@
 		goto fail;
 	}
 
+	/*
+	 * Add Acct-Delay-Time with zero value for the first transmission. This
+	 * will be updated within radius_client.c when retransmitting the frame.
+	 */
+	if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_DELAY_TIME, 0)) {
+		wpa_printf(MSG_INFO, "Could not add Acct-Delay-Time");
+		goto fail;
+	}
+
 	return msg;
 
  fail:
@@ -450,6 +459,63 @@
 }
 
 
+static void accounting_interim_error_cb(const u8 *addr, void *ctx)
+{
+	struct hostapd_data *hapd = ctx;
+	struct sta_info *sta;
+	unsigned int i, wait_time;
+	int res;
+
+	sta = ap_get_sta(hapd, addr);
+	if (!sta)
+		return;
+	sta->acct_interim_errors++;
+	if (sta->acct_interim_errors > 10 /* RADIUS_CLIENT_MAX_RETRIES */) {
+		wpa_printf(MSG_DEBUG,
+			   "Interim RADIUS accounting update failed for " MACSTR
+			   " - too many errors, abandon this interim accounting update",
+			   MAC2STR(addr));
+		sta->acct_interim_errors = 0;
+		/* Next update will be tried after normal update interval */
+		return;
+	}
+
+	/*
+	 * Use a shorter update interval as an improved retransmission mechanism
+	 * for failed interim accounting updates. This allows the statistics to
+	 * be updated for each retransmission.
+	 *
+	 * RADIUS client code has already waited RADIUS_CLIENT_FIRST_WAIT.
+	 * Schedule the first retry attempt immediately and every following one
+	 * with exponential backoff.
+	 */
+	if (sta->acct_interim_errors == 1) {
+		wait_time = 0;
+	} else {
+		wait_time = 3; /* RADIUS_CLIENT_FIRST_WAIT */
+		for (i = 1; i < sta->acct_interim_errors; i++)
+			wait_time *= 2;
+	}
+	res = eloop_deplete_timeout(wait_time, 0, accounting_interim_update,
+				    hapd, sta);
+	if (res == 1)
+		wpa_printf(MSG_DEBUG,
+			   "Interim RADIUS accounting update failed for " MACSTR
+			   " (error count: %u) - schedule next update in %u seconds",
+			   MAC2STR(addr), sta->acct_interim_errors, wait_time);
+	else if (res == 0)
+		wpa_printf(MSG_DEBUG,
+			   "Interim RADIUS accounting update failed for " MACSTR
+			   " (error count: %u)", MAC2STR(addr),
+			   sta->acct_interim_errors);
+	else
+		wpa_printf(MSG_DEBUG,
+			   "Interim RADIUS accounting update failed for " MACSTR
+			   " (error count: %u) - no timer found", MAC2STR(addr),
+			   sta->acct_interim_errors);
+}
+
+
 /**
  * accounting_init: Initialize accounting
  * @hapd: hostapd BSS data
@@ -464,6 +530,8 @@
 	if (radius_client_register(hapd->radius, RADIUS_ACCT,
 				   accounting_receive, hapd))
 		return -1;
+	radius_client_set_interim_error_cb(hapd->radius,
+					   accounting_interim_error_cb, hapd);
 
 	accounting_report_state(hapd, 1);
 
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index 477ea5b..66b843c 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -202,13 +202,6 @@
 }
 
 
-int hostapd_mac_comp_empty(const void *a)
-{
-	macaddr empty = { 0 };
-	return os_memcmp(a, empty, sizeof(macaddr));
-}
-
-
 static int hostapd_config_read_wpa_psk(const char *fname,
 				       struct hostapd_ssid *ssid)
 {
@@ -790,7 +783,7 @@
 		return -1;
 	}
 
-	if (full_config && hostapd_mac_comp_empty(bss->bssid) != 0) {
+	if (full_config && !is_zero_ether_addr(bss->bssid)) {
 		size_t i;
 
 		for (i = 0; i < conf->num_bss; i++) {
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 9afca48..f19cac6 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -128,9 +128,14 @@
 };
 
 #define PMK_LEN 32
+#define MIN_PASSPHRASE_LEN 8
+#define MAX_PASSPHRASE_LEN 63
 struct hostapd_sta_wpa_psk_short {
 	struct hostapd_sta_wpa_psk_short *next;
+	unsigned int is_passphrase:1;
 	u8 psk[PMK_LEN];
+	char passphrase[MAX_PASSPHRASE_LEN + 1];
+	int ref; /* (number of references held) - 1 */
 };
 
 struct hostapd_wpa_psk {
@@ -689,7 +694,6 @@
 
 
 int hostapd_mac_comp(const void *a, const void *b);
-int hostapd_mac_comp_empty(const void *a);
 struct hostapd_config * hostapd_config_defaults(void);
 void hostapd_config_defaults_bss(struct hostapd_bss_config *bss);
 void hostapd_config_free_eap_user(struct hostapd_eap_user *user);
diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
index a95230e..9f249d7 100644
--- a/src/ap/ctrl_iface_ap.c
+++ b/src/ap/ctrl_iface_ap.c
@@ -166,6 +166,15 @@
 	if (res >= 0)
 		len += res;
 
+	if (sta->supp_op_classes &&
+	    buflen - len > (unsigned) (17 + 2 * sta->supp_op_classes[0])) {
+		len += os_snprintf(buf + len, buflen - len, "supp_op_classes=");
+		len += wpa_snprintf_hex(buf + len, buflen - len,
+					sta->supp_op_classes + 1,
+					sta->supp_op_classes[0]);
+		len += os_snprintf(buf + len, buflen - len, "\n");
+	}
+
 	return len;
 }
 
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index 702ee64..f54d1ad 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -176,6 +176,9 @@
 
 	mbo_ap_check_sta_assoc(hapd, sta, &elems);
 
+	ap_copy_sta_supp_op_classes(sta, elems.supp_op_classes,
+				    elems.supp_op_classes_len);
+
 	if (hapd->conf->wpa) {
 		if (ie == NULL || ielen == 0) {
 #ifdef CONFIG_WPS
@@ -567,6 +570,7 @@
 				  struct acs_selected_channels *acs_res)
 {
 	int ret, i;
+	int err = 0;
 
 	if (hapd->iconf->channel) {
 		wpa_printf(MSG_INFO, "ACS: Channel was already set to %d",
@@ -588,7 +592,8 @@
 			hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
 				       HOSTAPD_LEVEL_WARNING,
 				       "driver selected to bad hw_mode");
-			return;
+			err = 1;
+			goto out;
 		}
 	}
 
@@ -598,7 +603,8 @@
 		hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
 			       HOSTAPD_LEVEL_WARNING,
 			       "driver switched to bad channel");
-		return;
+		err = 1;
+		goto out;
 	}
 
 	hapd->iconf->channel = acs_res->pri_channel;
@@ -612,7 +618,8 @@
 		hapd->iconf->secondary_channel = 1;
 	else {
 		wpa_printf(MSG_ERROR, "Invalid secondary channel!");
-		return;
+		err = 1;
+		goto out;
 	}
 
 	if (hapd->iface->conf->ieee80211ac) {
@@ -641,7 +648,8 @@
 		}
 	}
 
-	ret = hostapd_acs_completed(hapd->iface, 0);
+out:
+	ret = hostapd_acs_completed(hapd->iface, err);
 	if (ret) {
 		wpa_printf(MSG_ERROR,
 			   "ACS: Possibly channel configuration is invalid");
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index dd2dc17..303786b 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -521,7 +521,7 @@
 	/* Determine the bits necessary to any configured BSSIDs,
 	   if they are higher than the number of BSSIDs. */
 	for (j = 0; j < iface->conf->num_bss; j++) {
-		if (hostapd_mac_comp_empty(iface->conf->bss[j]->bssid) == 0) {
+		if (is_zero_ether_addr(iface->conf->bss[j]->bssid)) {
 			if (j)
 				auto_addr++;
 			continue;
@@ -905,7 +905,7 @@
 	hapd->started = 1;
 
 	if (!first || first == -1) {
-		if (hostapd_mac_comp_empty(conf->bssid) == 0) {
+		if (is_zero_ether_addr(conf->bssid)) {
 			/* Allocate the next available BSSID. */
 			do {
 				inc_byte_array(hapd->own_addr, ETH_ALEN);
@@ -940,6 +940,11 @@
 	if (conf->wmm_enabled < 0)
 		conf->wmm_enabled = hapd->iconf->ieee80211n;
 
+#ifdef CONFIG_IEEE80211R
+	if (is_zero_ether_addr(conf->r1_key_holder))
+		os_memcpy(conf->r1_key_holder, hapd->own_addr, ETH_ALEN);
+#endif /* CONFIG_IEEE80211R */
+
 #ifdef CONFIG_MESH
 	if (hapd->iface->mconf == NULL)
 		flush_old_stations = 0;
@@ -1626,7 +1631,7 @@
 			} while (j-- > 0);
 			goto fail;
 		}
-		if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0)
+		if (is_zero_ether_addr(hapd->conf->bssid))
 			prev_addr = hapd->own_addr;
 	}
 	hapd = iface->bss[0];
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 84e6e15..b36e68d 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -1726,6 +1726,9 @@
 	}
 #endif /* CONFIG_MBO */
 
+	ap_copy_sta_supp_op_classes(sta, elems.supp_op_classes,
+				    elems.supp_op_classes_len);
+
 	return WLAN_STATUS_SUCCESS;
 }
 
diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
index 78db204..1a96b33 100644
--- a/src/ap/ieee802_11.h
+++ b/src/ap/ieee802_11.h
@@ -130,4 +130,8 @@
 
 #endif /* CONFIG_MBO */
 
+void ap_copy_sta_supp_op_classes(struct sta_info *sta,
+				 const u8 *supp_op_classes,
+				 size_t supp_op_classes_len);
+
 #endif /* IEEE802_11_H */
diff --git a/src/ap/ieee802_11_auth.c b/src/ap/ieee802_11_auth.c
index f280709..9609152 100644
--- a/src/ap/ieee802_11_auth.c
+++ b/src/ap/ieee802_11_auth.c
@@ -15,7 +15,6 @@
 
 #include "utils/common.h"
 #include "utils/eloop.h"
-#include "crypto/sha1.h"
 #include "radius/radius.h"
 #include "radius/radius_client.h"
 #include "hostapd.h"
@@ -77,23 +76,13 @@
 static void copy_psk_list(struct hostapd_sta_wpa_psk_short **psk,
 			  struct hostapd_sta_wpa_psk_short *src)
 {
-	struct hostapd_sta_wpa_psk_short **copy_to;
-	struct hostapd_sta_wpa_psk_short *copy_from;
+	if (!psk)
+		return;
 
-	/* Copy PSK linked list */
-	copy_to = psk;
-	copy_from = src;
-	while (copy_from && copy_to) {
-		*copy_to = os_zalloc(sizeof(struct hostapd_sta_wpa_psk_short));
-		if (*copy_to == NULL)
-			break;
-		os_memcpy(*copy_to, copy_from,
-			  sizeof(struct hostapd_sta_wpa_psk_short));
-		copy_from = copy_from->next;
-		copy_to = &((*copy_to)->next);
-	}
-	if (copy_to)
-		*copy_to = NULL;
+	if (src)
+		src->ref++;
+
+	*psk = src;
 }
 
 
@@ -443,7 +432,7 @@
 				    struct hostapd_cached_radius_acl *cache)
 {
 	int passphraselen;
-	char *passphrase, *strpassphrase;
+	char *passphrase;
 	size_t i;
 	struct hostapd_sta_wpa_psk_short *psk;
 
@@ -460,23 +449,40 @@
 		 */
 		if (passphrase == NULL)
 			break;
+
+		/*
+		 * Passphase should be 8..63 chars (to be hashed with SSID)
+		 * or 64 chars hex string (no separate hashing with SSID).
+		 */
+
+		if (passphraselen < MIN_PASSPHRASE_LEN ||
+		    passphraselen > MAX_PASSPHRASE_LEN + 1)
+			continue;
+
 		/*
 		 * passphrase does not contain the NULL termination.
 		 * Add it here as pbkdf2_sha1() requires it.
 		 */
-		strpassphrase = os_zalloc(passphraselen + 1);
 		psk = os_zalloc(sizeof(struct hostapd_sta_wpa_psk_short));
-		if (strpassphrase && psk) {
-			os_memcpy(strpassphrase, passphrase, passphraselen);
-			pbkdf2_sha1(strpassphrase,
-				    hapd->conf->ssid.ssid,
-				    hapd->conf->ssid.ssid_len, 4096,
-				    psk->psk, PMK_LEN);
+		if (psk) {
+			if ((passphraselen == MAX_PASSPHRASE_LEN + 1) &&
+			    (hexstr2bin(passphrase, psk->psk, PMK_LEN) < 0)) {
+				hostapd_logger(hapd, cache->addr,
+					       HOSTAPD_MODULE_RADIUS,
+					       HOSTAPD_LEVEL_WARNING,
+					       "invalid hex string (%d chars) in Tunnel-Password",
+					       passphraselen);
+				goto skip;
+			} else if (passphraselen <= MAX_PASSPHRASE_LEN) {
+				os_memcpy(psk->passphrase, passphrase,
+					  passphraselen);
+				psk->is_passphrase = 1;
+			}
 			psk->next = cache->psk;
 			cache->psk = psk;
 			psk = NULL;
 		}
-		os_free(strpassphrase);
+skip:
 		os_free(psk);
 		os_free(passphrase);
 	}
@@ -671,6 +677,12 @@
 
 void hostapd_free_psk_list(struct hostapd_sta_wpa_psk_short *psk)
 {
+	if (psk && psk->ref) {
+		/* This will be freed when the last reference is dropped. */
+		psk->ref--;
+		return;
+	}
+
 	while (psk) {
 		struct hostapd_sta_wpa_psk_short *prev = psk;
 		psk = psk->next;
diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c
index 1077635..af858f0 100644
--- a/src/ap/ieee802_11_shared.c
+++ b/src/ap/ieee802_11_shared.c
@@ -558,3 +558,20 @@
 }
 
 #endif /* CONFIG_MBO */
+
+
+void ap_copy_sta_supp_op_classes(struct sta_info *sta,
+				 const u8 *supp_op_classes,
+				 size_t supp_op_classes_len)
+{
+	if (!supp_op_classes)
+		return;
+	os_free(sta->supp_op_classes);
+	sta->supp_op_classes = os_malloc(1 + supp_op_classes_len);
+	if (!sta->supp_op_classes)
+		return;
+
+	sta->supp_op_classes[0] = supp_op_classes_len;
+	os_memcpy(sta->supp_op_classes + 1, supp_op_classes,
+		  supp_op_classes_len);
+}
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index 60058e4..c36842b 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -328,6 +328,7 @@
 #endif /* CONFIG_SAE */
 
 	mbo_ap_sta_free(sta);
+	os_free(sta->supp_op_classes);
 
 	os_free(sta);
 }
diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
index 08e795e..cd89e99 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -118,6 +118,7 @@
 	int acct_session_started;
 	int acct_terminate_cause; /* Acct-Terminate-Cause */
 	int acct_interim_interval; /* Acct-Interim-Interval */
+	unsigned int acct_interim_errors;
 
 	/* For extending 32-bit driver counters to 64-bit counters */
 	u32 last_rx_bytes_hi;
@@ -190,6 +191,9 @@
 		       * enum mbo_cellular_capa values */
 	struct mbo_non_pref_chan_info *non_pref_chan;
 #endif /* CONFIG_MBO */
+
+	u8 *supp_op_classes; /* Supported Operating Classes element, if
+			      * received, starting from the Length field */
 };
 
 
diff --git a/src/ap/vlan_init.c b/src/ap/vlan_init.c
index 8eab6cb..45d1a1c 100644
--- a/src/ap/vlan_init.c
+++ b/src/ap/vlan_init.c
@@ -1119,25 +1119,23 @@
 				       int vlan_id,
 				       struct vlan_description *vlan_desc)
 {
-	struct hostapd_vlan *n = NULL;
-	char *ifname, *pos;
+	struct hostapd_vlan *n;
+	char ifname[IFNAMSIZ + 1], *pos;
 
 	if (vlan == NULL || vlan->vlan_id != VLAN_ID_WILDCARD)
 		return NULL;
 
 	wpa_printf(MSG_DEBUG, "VLAN: %s(vlan_id=%d ifname=%s)",
 		   __func__, vlan_id, vlan->ifname);
-	ifname = os_strdup(vlan->ifname);
-	if (ifname == NULL)
-		return NULL;
+	os_strlcpy(ifname, vlan->ifname, sizeof(ifname));
 	pos = os_strchr(ifname, '#');
 	if (pos == NULL)
-		goto free_ifname;
+		return NULL;
 	*pos++ = '\0';
 
 	n = os_zalloc(sizeof(*n));
 	if (n == NULL)
-		goto free_ifname;
+		return NULL;
 
 	n->vlan_id = vlan_id;
 	if (vlan_desc)
@@ -1155,11 +1153,8 @@
 		hapd->conf->vlan = n->next;
 		os_free(n);
 		n = NULL;
-		goto free_ifname;
 	}
 
-free_ifname:
-	os_free(ifname);
 	return n;
 }
 
diff --git a/src/ap/vlan_util.c b/src/ap/vlan_util.c
index d4e0efb..313d89f 100644
--- a/src/ap/vlan_util.c
+++ b/src/ap/vlan_util.c
@@ -33,7 +33,6 @@
 {
 	int err, ret = -1;
 	struct nl_sock *handle = NULL;
-	struct nl_cache *cache = NULL;
 	struct rtnl_link *rlink = NULL;
 	int if_idx = 0;
 
@@ -65,22 +64,19 @@
 		goto vlan_add_error;
 	}
 
-	err = rtnl_link_alloc_cache(handle, AF_UNSPEC, &cache);
+	err = rtnl_link_get_kernel(handle, 0, if_name, &rlink);
 	if (err < 0) {
-		cache = NULL;
-		wpa_printf(MSG_ERROR, "VLAN: failed to alloc cache: %s",
-			   nl_geterror(err));
-		goto vlan_add_error;
-	}
-
-	if (!(if_idx = rtnl_link_name2i(cache, if_name))) {
 		/* link does not exist */
 		wpa_printf(MSG_ERROR, "VLAN: interface %s does not exist",
 			   if_name);
 		goto vlan_add_error;
 	}
+	if_idx = rtnl_link_get_ifindex(rlink);
+	rtnl_link_put(rlink);
+	rlink = NULL;
 
-	if ((rlink = rtnl_link_get_by_name(cache, vlan_if_name))) {
+	err = rtnl_link_get_kernel(handle, 0, vlan_if_name, &rlink);
+	if (err >= 0) {
 		/* link does exist */
 		rtnl_link_put(rlink);
 		rlink = NULL;
@@ -127,8 +123,6 @@
 vlan_add_error:
 	if (rlink)
 		rtnl_link_put(rlink);
-	if (cache)
-		nl_cache_free(cache);
 	if (handle)
 		nl_socket_free(handle);
 	return ret;
@@ -139,7 +133,6 @@
 {
 	int err, ret = -1;
 	struct nl_sock *handle = NULL;
-	struct nl_cache *cache = NULL;
 	struct rtnl_link *rlink = NULL;
 
 	wpa_printf(MSG_DEBUG, "VLAN: vlan_rem(if_name=%s)", if_name);
@@ -157,15 +150,8 @@
 		goto vlan_rem_error;
 	}
 
-	err = rtnl_link_alloc_cache(handle, AF_UNSPEC, &cache);
+	err = rtnl_link_get_kernel(handle, 0, if_name, &rlink);
 	if (err < 0) {
-		cache = NULL;
-		wpa_printf(MSG_ERROR, "VLAN: failed to alloc cache: %s",
-			   nl_geterror(err));
-		goto vlan_rem_error;
-	}
-
-	if (!(rlink = rtnl_link_get_by_name(cache, if_name))) {
 		/* link does not exist */
 		wpa_printf(MSG_ERROR, "VLAN: interface %s does not exists",
 			   if_name);
@@ -184,8 +170,6 @@
 vlan_rem_error:
 	if (rlink)
 		rtnl_link_put(rlink);
-	if (cache)
-		nl_cache_free(cache);
 	if (handle)
 		nl_socket_free(handle);
 	return ret;
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index b303324..2b60114 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -42,10 +42,11 @@
 #define FT_PACKET_R0KH_R1KH_RESP 201
 #define FT_PACKET_R0KH_R1KH_PUSH 202
 
-#define FT_R0KH_R1KH_PULL_DATA_LEN 44
-#define FT_R0KH_R1KH_RESP_DATA_LEN 76
-#define FT_R0KH_R1KH_PUSH_DATA_LEN 88
 #define FT_R0KH_R1KH_PULL_NONCE_LEN 16
+#define FT_R0KH_R1KH_PULL_DATA_LEN (FT_R0KH_R1KH_PULL_NONCE_LEN + \
+				    WPA_PMK_NAME_LEN + FT_R1KH_ID_LEN + \
+				    ETH_ALEN)
+#define FT_R0KH_R1KH_PULL_PAD_LEN ((8 - FT_R0KH_R1KH_PULL_DATA_LEN % 8) % 8)
 
 struct ft_r0kh_r1kh_pull_frame {
 	u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */
@@ -57,14 +58,18 @@
 	u8 pmk_r0_name[WPA_PMK_NAME_LEN];
 	u8 r1kh_id[FT_R1KH_ID_LEN];
 	u8 s1kh_id[ETH_ALEN];
-	u8 pad[4]; /* 8-octet boundary for AES key wrap */
+	u8 pad[FT_R0KH_R1KH_PULL_PAD_LEN]; /* 8-octet boundary for AES block */
 	u8 key_wrap_extra[8];
 } STRUCT_PACKED;
 
+#define FT_R0KH_R1KH_RESP_DATA_LEN (FT_R0KH_R1KH_PULL_NONCE_LEN + \
+				    FT_R1KH_ID_LEN + ETH_ALEN + PMK_LEN + \
+				    WPA_PMK_NAME_LEN + 2)
+#define FT_R0KH_R1KH_RESP_PAD_LEN ((8 - FT_R0KH_R1KH_RESP_DATA_LEN % 8) % 8)
 struct ft_r0kh_r1kh_resp_frame {
 	u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */
 	u8 packet_type; /* FT_PACKET_R0KH_R1KH_RESP */
-	le16 data_length; /* little endian length of data (76) */
+	le16 data_length; /* little endian length of data (78) */
 	u8 ap_address[ETH_ALEN];
 
 	u8 nonce[FT_R0KH_R1KH_PULL_NONCE_LEN]; /* copied from pull */
@@ -73,14 +78,18 @@
 	u8 pmk_r1[PMK_LEN];
 	u8 pmk_r1_name[WPA_PMK_NAME_LEN];
 	le16 pairwise;
-	u8 pad[2]; /* 8-octet boundary for AES key wrap */
+	u8 pad[FT_R0KH_R1KH_RESP_PAD_LEN]; /* 8-octet boundary for AES block */
 	u8 key_wrap_extra[8];
 } STRUCT_PACKED;
 
+#define FT_R0KH_R1KH_PUSH_DATA_LEN (4 + FT_R1KH_ID_LEN + ETH_ALEN + \
+				    WPA_PMK_NAME_LEN + PMK_LEN + \
+				    WPA_PMK_NAME_LEN + 2)
+#define FT_R0KH_R1KH_PUSH_PAD_LEN ((8 - FT_R0KH_R1KH_PUSH_DATA_LEN % 8) % 8)
 struct ft_r0kh_r1kh_push_frame {
 	u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */
 	u8 packet_type; /* FT_PACKET_R0KH_R1KH_PUSH */
-	le16 data_length; /* little endian length of data (88) */
+	le16 data_length; /* little endian length of data (82) */
 	u8 ap_address[ETH_ALEN];
 
 	/* Encrypted with AES key-wrap */
@@ -92,7 +101,7 @@
 	u8 pmk_r1[PMK_LEN];
 	u8 pmk_r1_name[WPA_PMK_NAME_LEN];
 	le16 pairwise;
-	u8 pad[6]; /* 8-octet boundary for AES key wrap */
+	u8 pad[FT_R0KH_R1KH_PUSH_PAD_LEN]; /* 8-octet boundary for AES block */
 	u8 key_wrap_extra[8];
 } STRUCT_PACKED;
 
diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
index ffd0790..5fe0987 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -12,6 +12,7 @@
 #include "common/ieee802_11_defs.h"
 #include "common/sae.h"
 #include "common/wpa_ctrl.h"
+#include "crypto/sha1.h"
 #include "eapol_auth/eapol_auth_sm.h"
 #include "eapol_auth/eapol_auth_sm_i.h"
 #include "eap_server/eap.h"
@@ -246,6 +247,13 @@
 		struct hostapd_sta_wpa_psk_short *pos;
 		psk = sta->psk->psk;
 		for (pos = sta->psk; pos; pos = pos->next) {
+			if (pos->is_passphrase) {
+				pbkdf2_sha1(pos->passphrase,
+					    hapd->conf->ssid.ssid,
+					    hapd->conf->ssid.ssid_len, 4096,
+					    pos->psk, PMK_LEN);
+				pos->is_passphrase = 0;
+			}
 			if (pos->psk == prev_psk) {
 				psk = pos->next ? pos->next->psk : NULL;
 				break;
@@ -413,6 +421,8 @@
 		hapd = iface->bss[j];
 		if (hapd == idata->src_hapd)
 			continue;
+		if (!hapd->wpa_auth)
+			continue;
 		if (os_memcmp(hapd->own_addr, idata->dst, ETH_ALEN) == 0) {
 			wpa_printf(MSG_DEBUG, "FT: Send RRB data directly to "
 				   "locally managed BSS " MACSTR "@%s -> "
@@ -563,6 +573,9 @@
 	ethhdr = (struct l2_ethhdr *) buf;
 	wpa_printf(MSG_DEBUG, "FT: RRB received packet " MACSTR " -> "
 		   MACSTR, MAC2STR(ethhdr->h_source), MAC2STR(ethhdr->h_dest));
+	if (!is_multicast_ether_addr(ethhdr->h_dest) &&
+	    os_memcmp(hapd->own_addr, ethhdr->h_dest, ETH_ALEN) != 0)
+		return;
 	wpa_ft_rrb_rx(hapd->wpa_auth, ethhdr->h_source, buf + sizeof(*ethhdr),
 		      len - sizeof(*ethhdr));
 }
diff --git a/src/common/defs.h b/src/common/defs.h
index b3ac4e8..6ef929c 100644
--- a/src/common/defs.h
+++ b/src/common/defs.h
@@ -335,4 +335,10 @@
 	WPA_SETBAND_2G
 };
 
+enum wpa_radio_work_band {
+	BAND_2_4_GHZ = BIT(0),
+	BAND_5_GHZ = BIT(1),
+	BAND_60_GHZ = BIT(2),
+};
+
 #endif /* DEFS_H */
diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
index 2e503b9..5b05b68 100644
--- a/src/common/ieee802_11_common.c
+++ b/src/common/ieee802_11_common.c
@@ -371,6 +371,10 @@
 			elems->mb_ies.ies[elems->mb_ies.nof_ies].ie_len = elen;
 			elems->mb_ies.nof_ies++;
 			break;
+		case WLAN_EID_SUPPORTED_OPERATING_CLASSES:
+			elems->supp_op_classes = pos;
+			elems->supp_op_classes_len = elen;
+			break;
 		default:
 			unknown++;
 			if (!show_errors)
diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h
index 3a3dd4d..d9fecd6 100644
--- a/src/common/ieee802_11_common.h
+++ b/src/common/ieee802_11_common.h
@@ -62,6 +62,7 @@
 	const u8 *ampe;
 	const u8 *mic;
 	const u8 *pref_freq_list;
+	const u8 *supp_op_classes;
 
 	u8 ssid_len;
 	u8 supp_rates_len;
@@ -92,6 +93,8 @@
 	u8 ampe_len;
 	u8 mic_len;
 	u8 pref_freq_list_len;
+	u8 supp_op_classes_len;
+
 	struct mb_ies_info mb_ies;
 };
 
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 2315226..642276c 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -439,6 +439,15 @@
 	 */
 	 unsigned int sched_scan_plans_num;
 
+	/**
+	 * bssid - Specific BSSID to scan for
+	 *
+	 * This optional parameter can be used to replace the default wildcard
+	 * BSSID with a specific BSSID to scan for if results are needed from
+	 * only a single BSS.
+	 */
+	const u8 *bssid;
+
 	/*
 	 * NOTE: Whenever adding new parameters here, please make sure
 	 * wpa_scan_clone_params() and wpa_scan_free_params() get updated with
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 5fec430..570dee6 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -181,9 +181,14 @@
 static int wpa_driver_nl80211_probe_req_report(struct i802_bss *bss,
 					       int report);
 
-static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
-static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
-static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
+#define IFIDX_ANY -1
+
+static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx,
+		      int ifidx_reason);
+static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx,
+		      int ifidx_reason);
+static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx,
+		      int ifidx_reason);
 
 static int nl80211_set_channel(struct i802_bss *bss,
 			       struct hostapd_freq_params *freq, int set_chan);
@@ -883,7 +888,7 @@
 	dl_list_for_each(drv, &global->interfaces,
 			 struct wpa_driver_nl80211_data, list) {
 		if (wpa_driver_nl80211_own_ifindex(drv, idx, buf, len) ||
-		    have_ifidx(drv, idx))
+		    have_ifidx(drv, idx, IFIDX_ANY))
 			return drv;
 	}
 	return NULL;
@@ -1062,7 +1067,7 @@
 		}
 		wpa_printf(MSG_DEBUG, "nl80211: Add ifindex %u for bridge %s",
 			   brid, namebuf);
-		add_ifidx(drv, brid);
+		add_ifidx(drv, brid, ifi->ifi_index);
 
 		for (bss = drv->first_bss; bss; bss = bss->next) {
 			if (os_strcmp(ifname, bss->ifname) == 0) {
@@ -1149,7 +1154,7 @@
 				   "nl80211: Remove ifindex %u for bridge %s",
 				   brid, namebuf);
 		}
-		del_ifidx(drv, brid);
+		del_ifidx(drv, brid, ifi->ifi_index);
 	}
 }
 
@@ -1716,6 +1721,7 @@
 
 	drv->num_if_indices = sizeof(drv->default_if_indices) / sizeof(int);
 	drv->if_indices = drv->default_if_indices;
+	drv->if_indices_reason = drv->default_if_indices_reason;
 
 	drv->first_bss = os_zalloc(sizeof(*drv->first_bss));
 	if (!drv->first_bss) {
@@ -2390,6 +2396,9 @@
 	if (drv->if_indices != drv->default_if_indices)
 		os_free(drv->if_indices);
 
+	if (drv->if_indices_reason != drv->default_if_indices_reason)
+		os_free(drv->if_indices_reason);
+
 	if (drv->disabled_11b_rates)
 		nl80211_disable_11b_rates(drv, drv->ifindex, 0);
 
@@ -4069,7 +4078,11 @@
 	/* stop listening for EAPOL on this interface */
 	dl_list_for_each(drv2, &drv->global->interfaces,
 			 struct wpa_driver_nl80211_data, list)
-		del_ifidx(drv2, ifidx);
+	{
+		del_ifidx(drv2, ifidx, IFIDX_ANY);
+		/* Remove all bridges learned for this iface */
+		del_ifidx(drv2, IFIDX_ANY, ifidx);
+	}
 
 	msg = nl80211_ifindex_msg(drv, ifidx, 0, NL80211_CMD_DEL_INTERFACE);
 	if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0)
@@ -4177,7 +4190,7 @@
 	    iftype == NL80211_IFTYPE_WDS ||
 	    iftype == NL80211_IFTYPE_MONITOR) {
 		/* start listening for EAPOL on this interface */
-		add_ifidx(drv, ifidx);
+		add_ifidx(drv, ifidx, IFIDX_ANY);
 	}
 
 	if (addr && iftype != NL80211_IFTYPE_MONITOR &&
@@ -5635,7 +5648,9 @@
 	for (i = 0; i < drv->num_if_indices; i++) {
 		if (!drv->if_indices[i])
 			continue;
-		res = os_snprintf(pos, end - pos, " %d", drv->if_indices[i]);
+		res = os_snprintf(pos, end - pos, " %d(%d)",
+				  drv->if_indices[i],
+				  drv->if_indices_reason[i]);
 		if (os_snprintf_error(end - pos, res))
 			break;
 		pos += res;
@@ -5647,14 +5662,16 @@
 }
 
 
-static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
+static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx,
+		      int ifidx_reason)
 {
 	int i;
-	int *old;
+	int *old, *old_reason;
 
-	wpa_printf(MSG_DEBUG, "nl80211: Add own interface ifindex %d",
-		   ifidx);
-	if (have_ifidx(drv, ifidx)) {
+	wpa_printf(MSG_DEBUG,
+		   "nl80211: Add own interface ifindex %d (ifidx_reason %d)",
+		   ifidx, ifidx_reason);
+	if (have_ifidx(drv, ifidx, ifidx_reason)) {
 		wpa_printf(MSG_DEBUG, "nl80211: ifindex %d already in the list",
 			   ifidx);
 		return;
@@ -5662,6 +5679,7 @@
 	for (i = 0; i < drv->num_if_indices; i++) {
 		if (drv->if_indices[i] == 0) {
 			drv->if_indices[i] = ifidx;
+			drv->if_indices_reason[i] = ifidx_reason;
 			dump_ifidx(drv);
 			return;
 		}
@@ -5672,32 +5690,57 @@
 	else
 		old = NULL;
 
+	if (drv->if_indices_reason != drv->default_if_indices_reason)
+		old_reason = drv->if_indices_reason;
+	else
+		old_reason = NULL;
+
 	drv->if_indices = os_realloc_array(old, drv->num_if_indices + 1,
 					   sizeof(int));
+	drv->if_indices_reason = os_realloc_array(old_reason,
+						  drv->num_if_indices + 1,
+						  sizeof(int));
 	if (!drv->if_indices) {
 		if (!old)
 			drv->if_indices = drv->default_if_indices;
 		else
 			drv->if_indices = old;
+	}
+	if (!drv->if_indices_reason) {
+		if (!old_reason)
+			drv->if_indices_reason = drv->default_if_indices_reason;
+		else
+			drv->if_indices = old_reason;
+	}
+	if (!drv->if_indices || !drv->if_indices_reason) {
 		wpa_printf(MSG_ERROR, "Failed to reallocate memory for "
 			   "interfaces");
 		wpa_printf(MSG_ERROR, "Ignoring EAPOL on interface %d", ifidx);
 		return;
-	} else if (!old)
+	}
+	if (!old)
 		os_memcpy(drv->if_indices, drv->default_if_indices,
 			  sizeof(drv->default_if_indices));
+	if (!old_reason)
+		os_memcpy(drv->if_indices_reason,
+			  drv->default_if_indices_reason,
+			  sizeof(drv->default_if_indices_reason));
 	drv->if_indices[drv->num_if_indices] = ifidx;
+	drv->if_indices_reason[drv->num_if_indices] = ifidx_reason;
 	drv->num_if_indices++;
 	dump_ifidx(drv);
 }
 
 
-static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
+static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx,
+		      int ifidx_reason)
 {
 	int i;
 
 	for (i = 0; i < drv->num_if_indices; i++) {
-		if (drv->if_indices[i] == ifidx) {
+		if ((drv->if_indices[i] == ifidx || ifidx == IFIDX_ANY) &&
+		    (drv->if_indices_reason[i] == ifidx_reason ||
+		     ifidx_reason == IFIDX_ANY)) {
 			drv->if_indices[i] = 0;
 			break;
 		}
@@ -5706,12 +5749,15 @@
 }
 
 
-static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
+static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx,
+		      int ifidx_reason)
 {
 	int i;
 
 	for (i = 0; i < drv->num_if_indices; i++)
-		if (drv->if_indices[i] == ifidx)
+		if (drv->if_indices[i] == ifidx &&
+		    (drv->if_indices_reason[i] == ifidx_reason ||
+		     ifidx_reason == IFIDX_ANY))
 			return 1;
 
 	return 0;
@@ -5776,7 +5822,7 @@
 		return;
 	}
 
-	if (have_ifidx(drv, lladdr.sll_ifindex))
+	if (have_ifidx(drv, lladdr.sll_ifindex, IFIDX_ANY))
 		drv_event_eapol_rx(drv->ctx, lladdr.sll_addr, buf, len);
 }
 
@@ -5803,7 +5849,7 @@
 		}
 		bss->added_bridge = 1;
 		br_ifindex = if_nametoindex(brname);
-		add_ifidx(drv, br_ifindex);
+		add_ifidx(drv, br_ifindex, drv->ifindex);
 	}
 	bss->br_ifindex = br_ifindex;
 
@@ -5865,7 +5911,7 @@
 		wpa_printf(MSG_DEBUG, "nl80211: Interface %s is in master %s",
 			params->ifname, master_ifname);
 		/* start listening for EAPOL on the master interface */
-		add_ifidx(drv, if_nametoindex(master_ifname));
+		add_ifidx(drv, if_nametoindex(master_ifname), drv->ifindex);
 	} else {
 		master_ifname[0] = '\0';
 	}
@@ -5876,14 +5922,14 @@
 		if (params->bridge[i]) {
 			ifindex = if_nametoindex(params->bridge[i]);
 			if (ifindex)
-				add_ifidx(drv, ifindex);
+				add_ifidx(drv, ifindex, drv->ifindex);
 			if (ifindex == br_ifindex)
 				br_added = 1;
 		}
 	}
 
 	/* start listening for EAPOL on the default AP interface */
-	add_ifidx(drv, drv->ifindex);
+	add_ifidx(drv, drv->ifindex, IFIDX_ANY);
 
 	if (params->num_bridge && params->bridge[0]) {
 		if (i802_check_bridge(drv, bss, params->bridge[0],
@@ -5895,7 +5941,7 @@
 
 	if (!br_added && br_ifindex &&
 	    (params->num_bridge == 0 || !params->bridge[0]))
-		add_ifidx(drv, br_ifindex);
+		add_ifidx(drv, br_ifindex, drv->ifindex);
 
 #ifdef CONFIG_LIBNL3_ROUTE
 	if (bss->added_if_into_bridge) {
@@ -6181,7 +6227,7 @@
 	     nlmode == NL80211_IFTYPE_AP_VLAN ||
 	     nlmode == NL80211_IFTYPE_WDS ||
 	     nlmode == NL80211_IFTYPE_MONITOR))
-		add_ifidx(drv, ifidx);
+		add_ifidx(drv, ifidx, IFIDX_ANY);
 
 	return 0;
 }
@@ -6201,8 +6247,10 @@
 	else if (ifindex > 0 && !bss->added_if) {
 		struct wpa_driver_nl80211_data *drv2;
 		dl_list_for_each(drv2, &drv->global->interfaces,
-				 struct wpa_driver_nl80211_data, list)
-			del_ifidx(drv2, ifindex);
+				 struct wpa_driver_nl80211_data, list) {
+			del_ifidx(drv2, ifindex, IFIDX_ANY);
+			del_ifidx(drv2, IFIDX_ANY, ifindex);
+		}
 	}
 
 	if (type != WPA_IF_AP_BSS)
diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
index 4fa7d5f..430369f 100644
--- a/src/drivers/driver_nl80211.h
+++ b/src/drivers/driver_nl80211.h
@@ -172,7 +172,10 @@
 	struct nl_handle *rtnl_sk; /* nl_sock for NETLINK_ROUTE */
 
 	int default_if_indices[16];
+	/* the AP/AP_VLAN iface that is in this bridge */
+	int default_if_indices_reason[16];
 	int *if_indices;
+	int *if_indices_reason;
 	int num_if_indices;
 
 	/* From failed authentication command */
diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
index 98a2744..dae203a 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -572,9 +572,10 @@
 		rx_freq = drv->last_mgmt_freq = event.rx_mgmt.freq;
 	}
 	wpa_printf(MSG_DEBUG,
-		   "nl80211: RX frame sa=" MACSTR
+		   "nl80211: RX frame da=" MACSTR " sa=" MACSTR " bssid=" MACSTR
 		   " freq=%d ssi_signal=%d fc=0x%x seq_ctrl=0x%x stype=%u (%s) len=%u",
-		   MAC2STR(mgmt->sa), rx_freq, ssi_signal, fc,
+		   MAC2STR(mgmt->da), MAC2STR(mgmt->sa), MAC2STR(mgmt->bssid),
+		   rx_freq, ssi_signal, fc,
 		   le_to_host16(mgmt->seq_ctrl), stype, fc2str(fc),
 		   (unsigned int) len);
 	event.rx_mgmt.frame = frame;
diff --git a/src/drivers/driver_nl80211_scan.c b/src/drivers/driver_nl80211_scan.c
index 2145022..c089891 100644
--- a/src/drivers/driver_nl80211_scan.c
+++ b/src/drivers/driver_nl80211_scan.c
@@ -96,12 +96,20 @@
 void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx)
 {
 	struct wpa_driver_nl80211_data *drv = eloop_ctx;
+
+	wpa_printf(MSG_DEBUG, "nl80211: Scan timeout - try to abort it");
+	if (!wpa_driver_nl80211_abort_scan(drv->first_bss))
+		return;
+
+	wpa_printf(MSG_DEBUG, "nl80211: Failed to abort scan");
+
 	if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED) {
 		wpa_driver_nl80211_set_mode(drv->first_bss,
 					    drv->ap_scan_as_station);
 		drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
 	}
-	wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
+
+	wpa_printf(MSG_DEBUG, "nl80211: Try to get scan results");
 	wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
 }
 
@@ -257,6 +265,13 @@
 			goto fail;
 	}
 
+	if (params->bssid) {
+		wpa_printf(MSG_DEBUG, "nl80211: Scan for a specific BSSID: "
+			   MACSTR, MAC2STR(params->bssid));
+		if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid))
+			goto fail;
+	}
+
 	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
 	msg = NULL;
 	if (ret) {
diff --git a/src/eap_peer/eap_pwd.c b/src/eap_peer/eap_pwd.c
index 1c8e88f..d2bc981 100644
--- a/src/eap_peer/eap_pwd.c
+++ b/src/eap_peer/eap_pwd.c
@@ -418,7 +418,6 @@
 		wpa_printf(MSG_INFO, "EAP-PWD (peer): element inversion fail");
 		goto fin;
 	}
-	BN_clear_free(mask);
 
 	if (((x = BN_new()) == NULL) ||
 	    ((y = BN_new()) == NULL)) {
@@ -555,6 +554,7 @@
 	os_free(element);
 	BN_clear_free(x);
 	BN_clear_free(y);
+	BN_clear_free(mask);
 	BN_clear_free(cofactor);
 	EC_POINT_clear_free(K);
 	EC_POINT_clear_free(point);
diff --git a/src/fst/fst_session.c b/src/fst/fst_session.c
index 11f3b63..449e304 100644
--- a/src/fst/fst_session.c
+++ b/src/fst/fst_session.c
@@ -181,7 +181,8 @@
 
 static void fst_session_stt_arm(struct fst_session *s)
 {
-	eloop_register_timeout(0, TU_TO_US(FST_DEFAULT_SESSION_TIMEOUT_TU),
+	/* Action frames sometimes get delayed. Use relaxed timeout (2*) */
+	eloop_register_timeout(0, 2 * TU_TO_US(FST_DEFAULT_SESSION_TIMEOUT_TU),
 			       fst_session_timeout_handler, NULL, s);
 	s->stt_armed = TRUE;
 }
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index d28b4cd..6942c85 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -10,6 +10,7 @@
 
 #include "common.h"
 #include "eloop.h"
+#include "common/defs.h"
 #include "common/ieee802_11_defs.h"
 #include "common/ieee802_11_common.h"
 #include "common/wpa_ctrl.h"
@@ -2034,8 +2035,23 @@
 
 	dev = p2p_get_device(p2p, addr);
 	if (dev) {
-		if (dev->country[0] == 0 && msg.listen_channel)
-			os_memcpy(dev->country, msg.listen_channel, 3);
+		if (msg.listen_channel) {
+			int freq;
+
+			if (dev->country[0] == 0)
+				os_memcpy(dev->country, msg.listen_channel, 3);
+
+			freq = p2p_channel_to_freq(msg.listen_channel[3],
+						   msg.listen_channel[4]);
+
+			if (freq > 0 && dev->listen_freq != freq) {
+				p2p_dbg(p2p,
+					"Updated peer " MACSTR " Listen channel (Probe Request): %d -> %d MHz",
+					MAC2STR(addr), dev->listen_freq, freq);
+				dev->listen_freq = freq;
+			}
+		}
+
 		os_get_reltime(&dev->last_seen);
 		p2p_parse_free(&msg);
 		return; /* already known */
@@ -3494,7 +3510,8 @@
 }
 
 
-void p2p_scan_ie(struct p2p_data *p2p, struct wpabuf *ies, const u8 *dev_id)
+void p2p_scan_ie(struct p2p_data *p2p, struct wpabuf *ies, const u8 *dev_id,
+		 unsigned int bands)
 {
 	u8 dev_capab;
 	u8 *len;
@@ -3528,6 +3545,9 @@
 		p2p_buf_add_ext_listen_timing(ies, p2p->ext_listen_period,
 					      p2p->ext_listen_interval);
 
+	if (bands & BAND_60_GHZ)
+		p2p_buf_add_device_info(ies, p2p, NULL);
+
 	if (p2p->p2ps_seek && p2p->p2ps_seek_count)
 		p2p_buf_add_service_hash(ies, p2p);
 
diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h
index 244fca4..fc545b4 100644
--- a/src/p2p/p2p.h
+++ b/src/p2p/p2p.h
@@ -1902,8 +1902,10 @@
  * @p2p: P2P module context from p2p_init()
  * @ies: Buffer for writing P2P IE
  * @dev_id: Device ID to search for or %NULL for any
+ * @bands: Frequency bands used in the scan (enum wpa_radio_work_band bitmap)
  */
-void p2p_scan_ie(struct p2p_data *p2p, struct wpabuf *ies, const u8 *dev_id);
+void p2p_scan_ie(struct p2p_data *p2p, struct wpabuf *ies, const u8 *dev_id,
+		 unsigned int bands);
 
 /**
  * p2p_scan_ie_buf_len - Get maximum buffer length needed for p2p_scan_ie
diff --git a/src/radius/radius_client.c b/src/radius/radius_client.c
index b24bbf8..a4edd5f 100644
--- a/src/radius/radius_client.c
+++ b/src/radius/radius_client.c
@@ -226,6 +226,16 @@
 	 * next_radius_identifier - Next RADIUS message identifier to use
 	 */
 	u8 next_radius_identifier;
+
+	/**
+	 * interim_error_cb - Interim accounting error callback
+	 */
+	void (*interim_error_cb)(const u8 *addr, void *ctx);
+
+	/**
+	 * interim_error_cb_ctx - interim_error_cb() context data
+	 */
+	void *interim_error_cb_ctx;
 };
 
 
@@ -297,6 +307,25 @@
 }
 
 
+/**
+ * radius_client_set_interim_erro_cb - Register an interim acct error callback
+ * @radius: RADIUS client context from radius_client_init()
+ * @addr: Station address from the failed message
+ * @cb: Handler for interim accounting errors
+ * @ctx: Context pointer for handler callbacks
+ *
+ * This function is used to register a handler for processing failed
+ * transmission attempts of interim accounting update messages.
+ */
+void radius_client_set_interim_error_cb(struct radius_client_data *radius,
+					void (*cb)(const u8 *addr, void *ctx),
+					void *ctx)
+{
+	radius->interim_error_cb = cb;
+	radius->interim_error_cb_ctx = ctx;
+}
+
+
 /*
  * Returns >0 if message queue was flushed (i.e., the message that triggered
  * the error is not available anymore)
@@ -336,6 +365,8 @@
 	int s;
 	struct wpabuf *buf;
 	size_t prev_num_msgs;
+	u8 *acct_delay_time;
+	size_t acct_delay_time_len;
 
 	if (entry->msg_type == RADIUS_ACCT ||
 	    entry->msg_type == RADIUS_ACCT_INTERIM) {
@@ -371,12 +402,52 @@
 			conf->auth_server->retransmissions++;
 		}
 	}
+
+	if (entry->msg_type == RADIUS_ACCT_INTERIM) {
+		wpa_printf(MSG_DEBUG,
+			   "RADIUS: Failed to transmit interim accounting update to "
+			   MACSTR " - drop message and request a new update",
+			   MAC2STR(entry->addr));
+		if (radius->interim_error_cb)
+			radius->interim_error_cb(entry->addr,
+						 radius->interim_error_cb_ctx);
+		return 1;
+	}
+
 	if (s < 0) {
 		wpa_printf(MSG_INFO,
 			   "RADIUS: No valid socket for retransmission");
 		return 1;
 	}
 
+	if (entry->msg_type == RADIUS_ACCT &&
+	    radius_msg_get_attr_ptr(entry->msg, RADIUS_ATTR_ACCT_DELAY_TIME,
+				    &acct_delay_time, &acct_delay_time_len,
+				    NULL) == 0 &&
+	    acct_delay_time_len == 4) {
+		struct radius_hdr *hdr;
+		u32 delay_time;
+
+		/*
+		 * Need to assign a new identifier since attribute contents
+		 * changes.
+		 */
+		hdr = radius_msg_get_hdr(entry->msg);
+		hdr->identifier = radius_client_get_id(radius);
+
+		/* Update Acct-Delay-Time to show wait time in queue */
+		delay_time = now - entry->first_try;
+		WPA_PUT_BE32(acct_delay_time, delay_time);
+
+		wpa_printf(MSG_DEBUG,
+			   "RADIUS: Updated Acct-Delay-Time to %u for retransmission",
+			   delay_time);
+		radius_msg_finish_acct(entry->msg, entry->shared_secret,
+				       entry->shared_secret_len);
+		if (radius->conf->msg_dumps)
+			radius_msg_dump(entry->msg);
+	}
+
 	/* retransmit; remove entry if too many attempts */
 	entry->attempts++;
 	hostapd_logger(radius->ctx, entry->addr, HOSTAPD_MODULE_RADIUS,
@@ -624,39 +695,6 @@
 }
 
 
-static void radius_client_list_del(struct radius_client_data *radius,
-				   RadiusType msg_type, const u8 *addr)
-{
-	struct radius_msg_list *entry, *prev, *tmp;
-
-	if (addr == NULL)
-		return;
-
-	entry = radius->msgs;
-	prev = NULL;
-	while (entry) {
-		if (entry->msg_type == msg_type &&
-		    os_memcmp(entry->addr, addr, ETH_ALEN) == 0) {
-			if (prev)
-				prev->next = entry->next;
-			else
-				radius->msgs = entry->next;
-			tmp = entry;
-			entry = entry->next;
-			hostapd_logger(radius->ctx, addr,
-				       HOSTAPD_MODULE_RADIUS,
-				       HOSTAPD_LEVEL_DEBUG,
-				       "Removing matching RADIUS message");
-			radius_client_msg_free(tmp);
-			radius->num_msgs--;
-			continue;
-		}
-		prev = entry;
-		entry = entry->next;
-	}
-}
-
-
 /**
  * radius_client_send - Send a RADIUS request
  * @radius: RADIUS client context from radius_client_init()
@@ -668,16 +706,19 @@
  * This function is used to transmit a RADIUS authentication (RADIUS_AUTH) or
  * accounting request (RADIUS_ACCT or RADIUS_ACCT_INTERIM). The only difference
  * between accounting and interim accounting messages is that the interim
- * message will override any pending interim accounting updates while a new
- * accounting message does not remove any pending messages.
+ * message will not be retransmitted. Instead, a callback is used to indicate
+ * that the transmission failed for the specific station @addr so that a new
+ * interim accounting update message can be generated with up-to-date session
+ * data instead of trying to resend old information.
  *
  * The message is added on the retransmission queue and will be retransmitted
  * automatically until a response is received or maximum number of retries
- * (RADIUS_CLIENT_MAX_RETRIES) is reached.
+ * (RADIUS_CLIENT_MAX_RETRIES) is reached. No such retries are used with
+ * RADIUS_ACCT_INTERIM, i.e., such a pending message is removed from the queue
+ * automatically on transmission failure.
  *
  * The related device MAC address can be used to identify pending messages that
- * can be removed with radius_client_flush_auth() or with interim accounting
- * updates.
+ * can be removed with radius_client_flush_auth().
  */
 int radius_client_send(struct radius_client_data *radius,
 		       struct radius_msg *msg, RadiusType msg_type,
@@ -690,11 +731,6 @@
 	int s, res;
 	struct wpabuf *buf;
 
-	if (msg_type == RADIUS_ACCT_INTERIM) {
-		/* Remove any pending interim acct update for the same STA. */
-		radius_client_list_del(radius, msg_type, addr);
-	}
-
 	if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) {
 		if (conf->acct_server && radius->acct_sock < 0)
 			radius_client_init_acct(radius);
diff --git a/src/radius/radius_client.h b/src/radius/radius_client.h
index 3db16aa..8ca0874 100644
--- a/src/radius/radius_client.h
+++ b/src/radius/radius_client.h
@@ -241,6 +241,9 @@
 			    const u8 *shared_secret, size_t shared_secret_len,
 			    void *data),
 			   void *data);
+void radius_client_set_interim_error_cb(struct radius_client_data *radius,
+					void (*cb)(const u8 *addr, void *ctx),
+					void *ctx);
 int radius_client_send(struct radius_client_data *radius,
 		       struct radius_msg *msg,
 		       RadiusType msg_type, const u8 *addr);
diff --git a/src/utils/trace.c b/src/utils/trace.c
index d98c4b0..d72cf60 100644
--- a/src/utils/trace.c
+++ b/src/utils/trace.c
@@ -369,8 +369,10 @@
 
 void wpa_trace_deinit(void)
 {
+#ifdef WPA_TRACE_BFD
 	free(syms);
 	syms = NULL;
+#endif /* WPA_TRACE_BFD */
 }
 
 #endif /* WPA_TRACE */
diff --git a/wpa_supplicant/README b/wpa_supplicant/README
index 3223312..fefc0d3 100644
--- a/wpa_supplicant/README
+++ b/wpa_supplicant/README
@@ -72,11 +72,13 @@
   * EAP-TTLS/CHAP
   * EAP-SIM
   * EAP-AKA
+  * EAP-AKA'
   * EAP-PSK
   * EAP-PAX
   * EAP-SAKE
   * EAP-IKEv2
   * EAP-GPSK
+  * EAP-pwd
   * LEAP (note: requires special support from the driver for IEEE 802.11
 	  authentication)
   (following methods are supported, but since they do not generate keying
@@ -163,18 +165,12 @@
 
 
 Optional libraries for EAP-TLS, EAP-PEAP, and EAP-TTLS:
-- OpenSSL (tested with 0.9.7c and 0.9.7d, and 0.9.8 versions; assumed to
+- OpenSSL (tested with 1.0.1 and 1.0.2 versions; assumed to
   work with most relatively recent versions; this is likely to be
   available with most distributions, http://www.openssl.org/)
 - GnuTLS
 - internal TLSv1 implementation
 
-TLS options for EAP-FAST:
-- OpenSSL 0.9.8d _with_ openssl-0.9.8d-tls-extensions.patch applied
-  (i.e., the default OpenSSL package does not include support for
-  extensions needed for EAP-FAST)
-- internal TLSv1 implementation
-
 One of these libraries is needed when EAP-TLS, EAP-PEAP, EAP-TTLS, or
 EAP-FAST support is enabled. WPA-PSK mode does not require this or EAPOL/EAP
 implementation. A configuration file, .config, for compilation is
@@ -308,7 +304,7 @@
 802.1X/EAPOL and EAP state machines and all EAP methods. Including
 TLS, PEAP, or TTLS will require linking wpa_supplicant with OpenSSL
 library for TLS implementation. Alternatively, GnuTLS or the internal
-TLSv1 implementation can be used for TLS functionaly.
+TLSv1 implementation can be used for TLS functionality.
 
 CONFIG_IEEE8021X_EAPOL=y
 CONFIG_EAP_MD5=y
@@ -320,15 +316,17 @@
 CONFIG_EAP_OTP=y
 CONFIG_EAP_SIM=y
 CONFIG_EAP_AKA=y
+CONFIG_EAP_AKA_PRIME=y
 CONFIG_EAP_PSK=y
 CONFIG_EAP_SAKE=y
 CONFIG_EAP_GPSK=y
 CONFIG_EAP_PAX=y
 CONFIG_EAP_LEAP=y
 CONFIG_EAP_IKEV2=y
+CONFIG_EAP_PWD=y
 
 Following option can be used to include GSM SIM/USIM interface for GSM/UMTS
-authentication algorithm (for EAP-SIM/EAP-AKA). This requires pcsc-lite
+authentication algorithm (for EAP-SIM/EAP-AKA/EAP-AKA'). This requires pcsc-lite
 (http://www.linuxnet.com/) for smart card access.
 
 CONFIG_PCSC=y
@@ -499,7 +497,7 @@
 
 Configuration file can include one or more network blocks, e.g., one
 for each used SSID. wpa_supplicant will automatically select the best
-betwork based on the order of network blocks in the configuration
+network based on the order of network blocks in the configuration
 file, network security level (WPA/WPA2 is preferred), and signal
 strength.
 
@@ -791,7 +789,7 @@
 
 One wpa_cli process in "action" mode needs to be started for each
 interface. For example, the following command starts wpa_cli for the
-default ingterface (-i can be used to select the interface in case of
+default interface (-i can be used to select the interface in case of
 more than one interface being used at the same time):
 
 wpa_cli -a/sbin/wpa_action.sh -B
@@ -1007,8 +1005,8 @@
 the operation has been completed, "RADIO_WORK done <id>" is used to
 indicate that to wpa_supplicant. This allows other radio works to be
 performed. If this command is forgotten (e.g., due to the external
-program terminating), wpa_supplicant will time out the radio owrk item
-and send "EXT-RADIO-WORK-TIMEOUT <id>" event ot indicate that this has
+program terminating), wpa_supplicant will time out the radio work item
+and send "EXT-RADIO-WORK-TIMEOUT <id>" event to indicate that this has
 happened. "RADIO_WORK done <id>" can also be used to cancel items that
 have not yet been started.
 
diff --git a/wpa_supplicant/README-HS20 b/wpa_supplicant/README-HS20
index e523b58..e4eed20 100644
--- a/wpa_supplicant/README-HS20
+++ b/wpa_supplicant/README-HS20
@@ -229,7 +229,7 @@
 #
 # sp_priority: Credential priority within a provisioning SP
 #	This is the priority of the credential among all credentials
-#	provisionined by the same SP (i.e., for entries that have identical
+#	provisioned by the same SP (i.e., for entries that have identical
 #	provisioning_sp value). The range of this priority is 0-255 with 0
 #	being the highest and 255 the lower priority.
 #
diff --git a/wpa_supplicant/README-P2P b/wpa_supplicant/README-P2P
index 19cf155..b8cf209 100644
--- a/wpa_supplicant/README-P2P
+++ b/wpa_supplicant/README-P2P
@@ -205,8 +205,8 @@
 P2PS attribute changes to p2p_connect command:
 
 P2PS supports two WPS provisioning methods namely PIN method and P2PS default.
-The remaining paramters hold same role as in legacy P2P. In case of P2PS default
-config method "p2ps" keyword is added in p2p_connect command.
+The remaining parameters hold same role as in legacy P2P. In case of P2PS
+default config method "p2ps" keyword is added in p2p_connect command.
 
 For example:
 p2p_connect 02:0a:f5:85:11:00 12345670 p2ps persistent join
@@ -288,7 +288,7 @@
 p2p_cancel
 
 Cancel an ongoing P2P group formation and joining-a-group related
-operation. This operations unauthorizes the specific peer device (if any
+operation. This operation unauthorizes the specific peer device (if any
 had been authorized to start group formation), stops P2P find (if in
 progress), stops pending operations for join-a-group, and removes the
 P2P group interface (if one was used) that is in the WPS provisioning
@@ -657,7 +657,7 @@
 Disabled(default)/enables use of per-client PSK in the P2P groups. This
 can be used to request GO to assign a unique PSK for each client during
 WPS provisioning. When enabled, this allow clients to be removed from
-the group securily with p2p_remove_client command since that client's
+the group securely with p2p_remove_client command since that client's
 PSK is removed at the same time to prevent it from connecting back using
 the old PSK. When per-client PSK is not used, the client can still be
 disconnected, but it will be able to re-join the group since the PSK it
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index 60f8c0d..fd5b03f 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -262,12 +262,12 @@
 	bss->force_per_enrollee_psk = wpa_s->global->p2p_per_sta_psk;
 
 	if (ssid->p2p_group) {
-		os_memcpy(bss->ip_addr_go, wpa_s->parent->conf->ip_addr_go, 4);
-		os_memcpy(bss->ip_addr_mask, wpa_s->parent->conf->ip_addr_mask,
+		os_memcpy(bss->ip_addr_go, wpa_s->p2pdev->conf->ip_addr_go, 4);
+		os_memcpy(bss->ip_addr_mask, wpa_s->p2pdev->conf->ip_addr_mask,
 			  4);
 		os_memcpy(bss->ip_addr_start,
-			  wpa_s->parent->conf->ip_addr_start, 4);
-		os_memcpy(bss->ip_addr_end, wpa_s->parent->conf->ip_addr_end,
+			  wpa_s->p2pdev->conf->ip_addr_start, 4);
+		os_memcpy(bss->ip_addr_end, wpa_s->p2pdev->conf->ip_addr_end,
 			  4);
 	}
 #endif /* CONFIG_P2P */
@@ -487,14 +487,14 @@
 	if (event == WPS_EV_FAIL) {
 		struct wps_event_fail *fail = &data->fail;
 
-		if (wpa_s->parent && wpa_s->parent != wpa_s &&
+		if (wpa_s->p2pdev && wpa_s->p2pdev != wpa_s &&
 		    wpa_s == wpa_s->global->p2p_group_formation) {
 			/*
 			 * src/ap/wps_hostapd.c has already sent this on the
 			 * main interface, so only send on the parent interface
 			 * here if needed.
 			 */
-			wpa_msg(wpa_s->parent, MSG_INFO, WPS_EVENT_FAIL
+			wpa_msg(wpa_s->p2pdev, MSG_INFO, WPS_EVENT_FAIL
 				"msg=%d config_error=%d",
 				fail->msg, fail->config_error);
 		}
@@ -639,8 +639,8 @@
 		params.p2p = 1;
 #endif /* CONFIG_P2P */
 
-	if (wpa_s->parent->set_ap_uapsd)
-		params.uapsd = wpa_s->parent->ap_uapsd;
+	if (wpa_s->p2pdev->set_ap_uapsd)
+		params.uapsd = wpa_s->p2pdev->ap_uapsd;
 	else if (params.p2p && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP_UAPSD))
 		params.uapsd = 1; /* mandatory for P2P GO */
 	else
@@ -719,7 +719,7 @@
 		}
 
 		hapd_iface->bss[i]->msg_ctx = wpa_s;
-		hapd_iface->bss[i]->msg_ctx_parent = wpa_s->parent;
+		hapd_iface->bss[i]->msg_ctx_parent = wpa_s->p2pdev;
 		hapd_iface->bss[i]->public_action_cb = ap_public_action_rx;
 		hapd_iface->bss[i]->public_action_cb_ctx = wpa_s;
 		hapd_iface->bss[i]->vendor_action_cb = ap_vendor_action_rx;
@@ -1320,8 +1320,8 @@
 	hapd = wpa_s->ap_iface->bss[0];
 	wps = hapd->wps;
 
-	if (wpa_s->parent->conf->wps_nfc_dh_pubkey == NULL ||
-	    wpa_s->parent->conf->wps_nfc_dh_privkey == NULL) {
+	if (wpa_s->p2pdev->conf->wps_nfc_dh_pubkey == NULL ||
+	    wpa_s->p2pdev->conf->wps_nfc_dh_privkey == NULL) {
 		wpa_printf(MSG_DEBUG, "P2P: No NFC DH key known");
 		return -1;
 	}
@@ -1330,9 +1330,9 @@
 	wpabuf_free(wps->dh_pubkey);
 	wpabuf_free(wps->dh_privkey);
 	wps->dh_privkey = wpabuf_dup(
-		wpa_s->parent->conf->wps_nfc_dh_privkey);
+		wpa_s->p2pdev->conf->wps_nfc_dh_privkey);
 	wps->dh_pubkey = wpabuf_dup(
-		wpa_s->parent->conf->wps_nfc_dh_pubkey);
+		wpa_s->p2pdev->conf->wps_nfc_dh_pubkey);
 	if (wps->dh_privkey == NULL || wps->dh_pubkey == NULL) {
 		wps->dh_ctx = NULL;
 		wpabuf_free(wps->dh_pubkey);
diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c
index 91a1511..d74630e 100644
--- a/wpa_supplicant/dbus/dbus_new.c
+++ b/wpa_supplicant/dbus/dbus_new.c
@@ -1207,7 +1207,7 @@
 					 cfg->ssid_len);
 	if (wpa_s_go != NULL && wpa_s_go == data->wpa_s) {
 		wpas_dbus_signal_peer_groups_changed(
-			data->wpa_s->parent, data->info->p2p_device_addr);
+			data->wpa_s->p2pdev, data->info->p2p_device_addr);
 		return 0;
 	}
 
@@ -1224,7 +1224,7 @@
 	wpa_s_go = wpas_get_p2p_client_iface(data->wpa_s,
 					     info->p2p_device_addr);
 	if (wpa_s_go != NULL && wpa_s_go == data->wpa_s) {
-		wpas_dbus_signal_peer_groups_changed(data->wpa_s->parent,
+		wpas_dbus_signal_peer_groups_changed(data->wpa_s->p2pdev,
 						     info->p2p_device_addr);
 		return;
 	}
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index ecb22e2..b3e730f 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -3347,6 +3347,7 @@
 	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED &&
 	    event != EVENT_INTERFACE_ENABLED &&
 	    event != EVENT_INTERFACE_STATUS &&
+	    event != EVENT_SCAN_RESULTS &&
 	    event != EVENT_SCHED_SCAN_STOPPED) {
 		wpa_dbg(wpa_s, MSG_DEBUG,
 			"Ignore event %s (%d) while interface is disabled",
@@ -3433,6 +3434,14 @@
 		}
 		break;
 	case EVENT_SCAN_RESULTS:
+		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
+			wpa_s->scan_res_handler = NULL;
+			wpa_s->own_scan_running = 0;
+			wpa_s->radio->external_scan_running = 0;
+			wpa_s->last_scan_req = NORMAL_SCAN_REQ;
+			break;
+		}
+
 		if (!(data && data->scan_info.external_scan) &&
 		    os_reltime_initialized(&wpa_s->scan_start_time)) {
 			struct os_reltime now, diff;
@@ -3931,7 +3940,7 @@
 	case EVENT_SCHED_SCAN_STOPPED:
 		wpa_s->pno = 0;
 		wpa_s->sched_scanning = 0;
-		resched = wpa_s->scanning;
+		resched = wpa_s->scanning && wpas_scan_scheduled(wpa_s);
 		wpa_supplicant_notify_scanning(wpa_s, 0);
 
 		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
diff --git a/wpa_supplicant/gas_query.c b/wpa_supplicant/gas_query.c
index 457f5fb..4f0d0e6 100644
--- a/wpa_supplicant/gas_query.c
+++ b/wpa_supplicant/gas_query.c
@@ -501,7 +501,7 @@
 		return -1;
 
 	prot = categ == WLAN_ACTION_PROTECTED_DUAL;
-	pmf = pmf_in_use(gas->wpa_s, bssid);
+	pmf = pmf_in_use(gas->wpa_s, sa);
 	if (prot && !pmf) {
 		wpa_printf(MSG_DEBUG, "GAS: Drop unexpected protected GAS frame when PMF is disabled");
 		return 0;
diff --git a/wpa_supplicant/hs20_supplicant.c b/wpa_supplicant/hs20_supplicant.c
index 57b9943..3128fcb 100644
--- a/wpa_supplicant/hs20_supplicant.c
+++ b/wpa_supplicant/hs20_supplicant.c
@@ -664,6 +664,7 @@
 	f = fopen(fname, "w");
 	if (f == NULL) {
 		hs20_free_osu_prov(wpa_s);
+		wpa_s->fetch_anqp_in_progress = 0;
 		return;
 	}
 
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index d274667..cf2653d 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -351,6 +351,7 @@
 	int social_channels_freq[] = { 2412, 2437, 2462, 60480 };
 	size_t ielen;
 	u8 *n, i;
+	unsigned int bands;
 
 	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
 		return -1;
@@ -380,28 +381,6 @@
 	if (wps_ie == NULL)
 		goto fail;
 
-	ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p);
-	ies = wpabuf_alloc(wpabuf_len(wps_ie) + ielen);
-	if (ies == NULL) {
-		wpabuf_free(wps_ie);
-		goto fail;
-	}
-	wpabuf_put_buf(ies, wps_ie);
-	wpabuf_free(wps_ie);
-
-	p2p_scan_ie(wpa_s->global->p2p, ies, dev_id);
-
-	params->p2p_probe = 1;
-	n = os_malloc(wpabuf_len(ies));
-	if (n == NULL) {
-		wpabuf_free(ies);
-		goto fail;
-	}
-	os_memcpy(n, wpabuf_head(ies), wpabuf_len(ies));
-	params->extra_ies = n;
-	params->extra_ies_len = wpabuf_len(ies);
-	wpabuf_free(ies);
-
 	switch (type) {
 	case P2P_SCAN_SOCIAL:
 		params->freqs = os_calloc(ARRAY_SIZE(social_channels_freq) + 1,
@@ -442,6 +421,29 @@
 		break;
 	}
 
+	ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p);
+	ies = wpabuf_alloc(wpabuf_len(wps_ie) + ielen);
+	if (ies == NULL) {
+		wpabuf_free(wps_ie);
+		goto fail;
+	}
+	wpabuf_put_buf(ies, wps_ie);
+	wpabuf_free(wps_ie);
+
+	bands = wpas_get_bands(wpa_s, params->freqs);
+	p2p_scan_ie(wpa_s->global->p2p, ies, dev_id, bands);
+
+	params->p2p_probe = 1;
+	n = os_malloc(wpabuf_len(ies));
+	if (n == NULL) {
+		wpabuf_free(ies);
+		goto fail;
+	}
+	os_memcpy(n, wpabuf_head(ies), wpabuf_len(ies));
+	params->extra_ies = n;
+	params->extra_ies_len = wpabuf_len(ies);
+	wpabuf_free(ies);
+
 	radio_remove_works(wpa_s, "p2p-scan", 0);
 	if (radio_add_work(wpa_s, 0, "p2p-scan", 0, wpas_p2p_trigger_scan_cb,
 			   params) < 0)
@@ -800,6 +802,8 @@
 		s = wpas_p2p_get_persistent_go(wpa_s);
 		if (!s && !go_wpa_s && p2p_no_group_iface) {
 			p2p_set_intended_addr(wpa_s->global->p2p,
+					      wpa_s->p2p_mgmt ?
+					      wpa_s->parent->own_addr :
 					      wpa_s->own_addr);
 		} else if (!s && !go_wpa_s) {
 			if (wpas_p2p_add_group_interface(wpa_s,
@@ -873,7 +877,7 @@
 
 	if (wpa_s->cross_connect_in_use) {
 		wpa_s->cross_connect_in_use = 0;
-		wpa_msg_global(wpa_s->parent, MSG_INFO,
+		wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
 			       P2P_EVENT_CROSS_CONNECT_DISABLE "%s %s",
 			       wpa_s->ifname, wpa_s->cross_connect_uplink);
 	}
@@ -904,7 +908,7 @@
 		break;
 	}
 	if (removal_reason != P2P_GROUP_REMOVAL_SILENT) {
-		wpa_msg_global(wpa_s->parent, MSG_INFO,
+		wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
 			       P2P_EVENT_GROUP_REMOVED "%s %s%s",
 			       wpa_s->ifname, gtype, reason);
 	}
@@ -914,7 +918,7 @@
 	if (eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL) > 0)
 		wpa_printf(MSG_DEBUG, "P2P: Cancelled P2P group idle timeout");
 	if (eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
-				 wpa_s->parent, NULL) > 0) {
+				 wpa_s->p2pdev, NULL) > 0) {
 		wpa_printf(MSG_DEBUG, "P2P: Cancelled P2P group formation "
 			   "timeout");
 		wpa_s->p2p_in_provisioning = 0;
@@ -949,6 +953,12 @@
 		return 1;
 	}
 
+	/*
+	 * The primary interface was used for P2P group operations, so
+	 * need to reset its p2pdev.
+	 */
+	wpa_s->p2pdev = wpa_s->parent;
+
 	if (!wpa_s->p2p_go_group_formation_completed) {
 		wpa_s->global->p2p_group_formation = NULL;
 		wpa_s->p2p_in_provisioning = 0;
@@ -1264,7 +1274,7 @@
 	 * Include PSK/passphrase only in the control interface message and
 	 * leave it out from the debug log entry.
 	 */
-	wpa_msg_global_ctrl(wpa_s->parent, MSG_INFO,
+	wpa_msg_global_ctrl(wpa_s->p2pdev, MSG_INFO,
 			    P2P_EVENT_GROUP_STARTED
 			    "%s %s ssid=\"%s\" freq=%d%s%s%s%s%s go_dev_addr="
 			    MACSTR "%s%s",
@@ -1307,7 +1317,7 @@
 	wpa_s->group_formation_reported = 1;
 
 	if (!success) {
-		wpa_msg_global(wpa_s->parent, MSG_INFO,
+		wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
 			       P2P_EVENT_GROUP_FORMATION_FAILURE);
 		wpas_notify_p2p_group_formation_failure(wpa_s, "");
 		if (already_deleted)
@@ -1317,7 +1327,7 @@
 		return;
 	}
 
-	wpa_msg_global(wpa_s->parent, MSG_INFO,
+	wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
 		       P2P_EVENT_GROUP_FORMATION_SUCCESS);
 
 	ssid = wpa_s->current_ssid;
@@ -1365,7 +1375,7 @@
 	}
 
 	if (persistent)
-		network_id = wpas_p2p_store_persistent_group(wpa_s->parent,
+		network_id = wpas_p2p_store_persistent_group(wpa_s->p2pdev,
 							     ssid, go_dev_addr);
 	else {
 		os_free(wpa_s->global->add_psk);
@@ -1489,7 +1499,7 @@
 		wpa_s->pending_pd_before_join = 0;
 		wpa_dbg(wpa_s, MSG_DEBUG, "P2P: No ACK for PD Req "
 			"during p2p_connect-auto");
-		wpa_msg_global(wpa_s->parent, MSG_INFO,
+		wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
 			       P2P_EVENT_FALLBACK_TO_GO_NEG
 			       "reason=no-ACK-to-PD-Req");
 		wpas_p2p_fallback_to_go_neg(wpa_s, 0);
@@ -1632,11 +1642,11 @@
 	} else if (res->wps_method == WPS_NFC) {
 		wpas_wps_start_nfc(wpa_s, res->peer_device_addr,
 				   res->peer_interface_addr,
-				   wpa_s->parent->p2p_oob_dev_pw,
-				   wpa_s->parent->p2p_oob_dev_pw_id, 1,
-				   wpa_s->parent->p2p_oob_dev_pw_id ==
+				   wpa_s->p2pdev->p2p_oob_dev_pw,
+				   wpa_s->p2pdev->p2p_oob_dev_pw_id, 1,
+				   wpa_s->p2pdev->p2p_oob_dev_pw_id ==
 				   DEV_PW_NFC_CONNECTION_HANDOVER ?
-				   wpa_s->parent->p2p_peer_oob_pubkey_hash :
+				   wpa_s->p2pdev->p2p_peer_oob_pubkey_hash :
 				   NULL,
 				   NULL, 0, 0);
 #endif /* CONFIG_WPS_NFC */
@@ -1662,7 +1672,7 @@
 	if (!wpa_s->ap_iface)
 		return;
 
-	persistent = wpas_p2p_get_persistent(wpa_s->parent, NULL, ssid->ssid,
+	persistent = wpas_p2p_get_persistent(wpa_s->p2pdev, NULL, ssid->ssid,
 					     ssid->ssid_len);
 	if (persistent == NULL)
 		return;
@@ -1727,8 +1737,8 @@
 static void p2p_config_write(struct wpa_supplicant *wpa_s)
 {
 #ifndef CONFIG_NO_CONFIG_WRITE
-	if (wpa_s->parent->conf->update_config &&
-	    wpa_config_write(wpa_s->parent->confname, wpa_s->parent->conf))
+	if (wpa_s->p2pdev->conf->update_config &&
+	    wpa_config_write(wpa_s->p2pdev->confname, wpa_s->p2pdev->conf))
 		wpa_printf(MSG_DEBUG, "P2P: Failed to update configuration");
 #endif /* CONFIG_NO_CONFIG_WRITE */
 }
@@ -1766,8 +1776,8 @@
 				       params->persistent_group, "");
 		wpa_s->group_formation_reported = 1;
 
-		if (wpa_s->parent->p2ps_method_config_any) {
-			if (is_zero_ether_addr(wpa_s->parent->p2ps_join_addr)) {
+		if (wpa_s->p2pdev->p2ps_method_config_any) {
+			if (is_zero_ether_addr(wpa_s->p2pdev->p2ps_join_addr)) {
 				wpa_dbg(wpa_s, MSG_DEBUG,
 					"P2PS: Setting default PIN for ANY");
 				wpa_supplicant_ap_wps_pin(wpa_s, NULL,
@@ -1776,18 +1786,18 @@
 			} else {
 				wpa_dbg(wpa_s, MSG_DEBUG,
 					"P2PS: Setting default PIN for " MACSTR,
-					MAC2STR(wpa_s->parent->p2ps_join_addr));
+					MAC2STR(wpa_s->p2pdev->p2ps_join_addr));
 				wpa_supplicant_ap_wps_pin(
-					wpa_s, wpa_s->parent->p2ps_join_addr,
+					wpa_s, wpa_s->p2pdev->p2ps_join_addr,
 					"12345670", NULL, 0, 0);
 			}
-			wpa_s->parent->p2ps_method_config_any = 0;
+			wpa_s->p2pdev->p2ps_method_config_any = 0;
 		}
 
 		os_get_reltime(&wpa_s->global->p2p_go_wait_client);
 		if (params->persistent_group) {
 			network_id = wpas_p2p_store_persistent_group(
-				wpa_s->parent, ssid,
+				wpa_s->p2pdev, ssid,
 				wpa_s->global->p2p_dev_addr);
 			wpas_p2p_add_psk_list(wpa_s, ssid);
 		}
@@ -1804,11 +1814,11 @@
 			wpa_s->p2p_go_group_formation_completed = 0;
 			wpa_s->global->p2p_group_formation = wpa_s;
 			eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
-					     wpa_s->parent, NULL);
+					     wpa_s->p2pdev, NULL);
 			eloop_register_timeout(
 				wpa_s->p2p_first_connection_timeout, 0,
 				wpas_p2p_group_formation_timeout,
-				wpa_s->parent, NULL);
+				wpa_s->p2pdev, NULL);
 		}
 
 		return;
@@ -1826,17 +1836,17 @@
 					  params->peer_device_addr);
 #ifdef CONFIG_WPS_NFC
 	} else if (params->wps_method == WPS_NFC) {
-		if (wpa_s->parent->p2p_oob_dev_pw_id !=
+		if (wpa_s->p2pdev->p2p_oob_dev_pw_id !=
 		    DEV_PW_NFC_CONNECTION_HANDOVER &&
-		    !wpa_s->parent->p2p_oob_dev_pw) {
+		    !wpa_s->p2pdev->p2p_oob_dev_pw) {
 			wpa_printf(MSG_DEBUG, "P2P: No NFC Dev Pw known");
 			return;
 		}
 		wpas_ap_wps_add_nfc_pw(
-			wpa_s, wpa_s->parent->p2p_oob_dev_pw_id,
-			wpa_s->parent->p2p_oob_dev_pw,
-			wpa_s->parent->p2p_peer_oob_pk_hash_known ?
-			wpa_s->parent->p2p_peer_oob_pubkey_hash : NULL);
+			wpa_s, wpa_s->p2pdev->p2p_oob_dev_pw_id,
+			wpa_s->p2pdev->p2p_oob_dev_pw,
+			wpa_s->p2pdev->p2p_peer_oob_pk_hash_known ?
+			wpa_s->p2pdev->p2p_peer_oob_pubkey_hash : NULL);
 #endif /* CONFIG_WPS_NFC */
 	} else if (wpa_s->p2p_pin[0])
 		wpa_supplicant_ap_wps_pin(wpa_s, params->peer_interface_addr,
@@ -1916,7 +1926,7 @@
 		os_memcpy(ssid->psk, params->psk, sizeof(ssid->psk));
 	else if (ssid->passphrase)
 		wpa_config_update_psk(ssid);
-	ssid->ap_max_inactivity = wpa_s->parent->conf->p2p_go_max_inactivity;
+	ssid->ap_max_inactivity = wpa_s->p2pdev->conf->p2p_go_max_inactivity;
 
 	wpa_s->ap_configured_cb = p2p_go_configured;
 	wpa_s->ap_configured_cb_ctx = wpa_s;
@@ -1976,6 +1986,23 @@
 }
 
 
+static void wpas_p2p_clone_config_dh(struct wpa_supplicant *dst,
+				     const struct wpa_supplicant *src)
+{
+	struct wpa_config *d;
+	const struct wpa_config *s;
+
+	d = dst->conf;
+	s = src->conf;
+
+	if (s->wps_nfc_dh_privkey && s->wps_nfc_dh_pubkey &&
+	    !d->wps_nfc_dh_privkey && !d->wps_nfc_dh_pubkey) {
+		d->wps_nfc_dh_privkey = wpabuf_dup(s->wps_nfc_dh_privkey);
+		d->wps_nfc_dh_pubkey = wpabuf_dup(s->wps_nfc_dh_pubkey);
+	}
+}
+
+
 static void wpas_p2p_get_group_ifname(struct wpa_supplicant *wpa_s,
 				      char *ifname, size_t len)
 {
@@ -2126,7 +2153,7 @@
 					    int already_deleted)
 {
 	eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
-			     wpa_s->parent, NULL);
+			     wpa_s->p2pdev, NULL);
 	if (wpa_s->global->p2p)
 		p2p_group_formation_failed(wpa_s->global->p2p);
 	wpas_group_formation_completed(wpa_s, 0, already_deleted);
@@ -2137,9 +2164,9 @@
 {
 	wpa_printf(MSG_DEBUG, "P2P: Reject group formation due to WPS provisioning failure");
 	eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
-			     wpa_s->parent, NULL);
+			     wpa_s->p2pdev, NULL);
 	eloop_register_timeout(0, 0, wpas_p2p_group_formation_timeout,
-			       wpa_s->parent, NULL);
+			       wpa_s->p2pdev, NULL);
 	wpa_s->global->p2p_fail_on_wps_complete = 0;
 }
 
@@ -2150,15 +2177,16 @@
 		return;
 	/* Speed up group formation timeout since this cannot succeed */
 	eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
-			     wpa_s->parent, NULL);
+			     wpa_s->p2pdev, NULL);
 	eloop_register_timeout(0, 0, wpas_p2p_group_formation_timeout,
-			       wpa_s->parent, NULL);
+			       wpa_s->p2pdev, NULL);
 }
 
 
 static void wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res)
 {
 	struct wpa_supplicant *wpa_s = ctx;
+	struct wpa_supplicant *group_wpa_s;
 
 	if (wpa_s->off_channel_freq || wpa_s->roc_waiting_drv_freq) {
 		wpa_drv_cancel_remain_on_channel(wpa_s);
@@ -2211,7 +2239,7 @@
 	}
 
 	if (wpa_s->create_p2p_iface) {
-		struct wpa_supplicant *group_wpa_s =
+		group_wpa_s =
 			wpas_p2p_init_group_interface(wpa_s, res->role_go);
 		if (group_wpa_s == NULL) {
 			wpas_p2p_remove_pending_group_interface(wpa_s);
@@ -2220,31 +2248,27 @@
 			wpas_p2p_group_formation_failed(wpa_s, 1);
 			return;
 		}
-		if (group_wpa_s != wpa_s) {
-			os_memcpy(group_wpa_s->p2p_pin, wpa_s->p2p_pin,
-				  sizeof(group_wpa_s->p2p_pin));
-			group_wpa_s->p2p_wps_method = wpa_s->p2p_wps_method;
-		}
 		os_memset(wpa_s->pending_interface_addr, 0, ETH_ALEN);
 		wpa_s->pending_interface_name[0] = '\0';
-		group_wpa_s->p2p_in_provisioning = 1;
-
-		if (res->role_go) {
-			wpas_start_wps_go(group_wpa_s, res, 1);
-		} else {
-			os_get_reltime(&group_wpa_s->scan_min_time);
-			wpas_start_wps_enrollee(group_wpa_s, res);
-		}
 	} else {
-		wpa_s->p2p_in_provisioning = 1;
-		wpa_s->global->p2p_group_formation = wpa_s;
+		group_wpa_s = wpa_s->parent;
+		wpa_s->global->p2p_group_formation = group_wpa_s;
+		if (group_wpa_s != wpa_s)
+			wpas_p2p_clone_config_dh(group_wpa_s, wpa_s);
+	}
 
-		if (res->role_go) {
-			wpas_start_wps_go(wpa_s, res, 1);
-		} else {
-			os_get_reltime(&wpa_s->scan_min_time);
-			wpas_start_wps_enrollee(ctx, res);
-		}
+	group_wpa_s->p2p_in_provisioning = 1;
+	group_wpa_s->p2pdev = wpa_s;
+	if (group_wpa_s != wpa_s) {
+		os_memcpy(group_wpa_s->p2p_pin, wpa_s->p2p_pin,
+			  sizeof(group_wpa_s->p2p_pin));
+		group_wpa_s->p2p_wps_method = wpa_s->p2p_wps_method;
+	}
+	if (res->role_go) {
+		wpas_start_wps_go(group_wpa_s, res, 1);
+	} else {
+		os_get_reltime(&group_wpa_s->scan_min_time);
+		wpas_start_wps_enrollee(group_wpa_s, res);
 	}
 
 	wpa_s->p2p_long_listen = 0;
@@ -2365,6 +2389,10 @@
 static void wpas_find_stopped(void *ctx)
 {
 	struct wpa_supplicant *wpa_s = ctx;
+
+	if (wpa_s->p2p_scan_work && wpas_abort_ongoing_scan(wpa_s) < 0)
+		wpa_printf(MSG_DEBUG, "P2P: Abort ongoing scan failed");
+
 	wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_FIND_STOPPED);
 	wpas_notify_p2p_find_stopped(wpa_s);
 }
@@ -2658,7 +2686,7 @@
 	if (wpa_s->p2p_fallback_to_go_neg) {
 		wpa_dbg(wpa_s, MSG_DEBUG, "P2P: PD for p2p_connect-auto "
 			"failed - fall back to GO Negotiation");
-		wpa_msg_global(wpa_s->parent, MSG_INFO,
+		wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
 			       P2P_EVENT_FALLBACK_TO_GO_NEG
 			       "reason=PD-failed");
 		wpas_p2p_fallback_to_go_neg(wpa_s, 0);
@@ -2903,7 +2931,11 @@
 				   "invitation");
 			return P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
 		}
-		os_memcpy(group_bssid, wpa_s->own_addr, ETH_ALEN);
+		if (wpa_s->p2p_mgmt)
+			os_memcpy(group_bssid, wpa_s->parent->own_addr,
+				  ETH_ALEN);
+		else
+			os_memcpy(group_bssid, wpa_s->own_addr, ETH_ALEN);
 	} else if (s->mode == WPAS_MODE_P2P_GO) {
 		*go = 1;
 		if (wpas_p2p_add_group_interface(wpa_s, WPA_IF_P2P_GO) < 0)
@@ -3091,7 +3123,7 @@
 	if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
 	    !ssid->p2p_persistent_group)
 		return; /* Not operating as a GO in persistent group */
-	ssid = wpas_p2p_get_persistent(wpa_s->parent, peer,
+	ssid = wpas_p2p_get_persistent(wpa_s->p2pdev, peer,
 				       ssid->ssid, ssid->ssid_len);
 	wpas_remove_persistent_peer(wpa_s, ssid, peer, 1);
 }
@@ -3733,6 +3765,7 @@
 		return -1;
 	}
 
+	p2pdev_wpa_s->p2pdev = p2pdev_wpa_s;
 	wpa_s->pending_interface_name[0] = '\0';
 	return 0;
 }
@@ -4514,8 +4547,7 @@
 
 static int wpas_p2p_create_iface(struct wpa_supplicant *wpa_s)
 {
-	if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
-	    wpa_s->conf->p2p_no_group_iface)
+	if (wpa_s->conf->p2p_no_group_iface)
 		return 0; /* separate interface disabled per configuration */
 	if (wpa_s->drv_flags &
 	    (WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE |
@@ -4596,7 +4628,7 @@
 				       MAC2STR(wpa_s->pending_join_dev_addr));
 			return;
 		}
-		wpa_msg_global(wpa_s->parent, MSG_INFO,
+		wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
 			       P2P_EVENT_GROUP_FORMATION_FAILURE);
 		wpas_notify_p2p_group_formation_failure(wpa_s, "");
 	}
@@ -4732,7 +4764,7 @@
 		if (join < 0) {
 			wpa_printf(MSG_DEBUG, "P2P: Peer was not found to be "
 				   "running a GO -> use GO Negotiation");
-			wpa_msg_global(wpa_s->parent, MSG_INFO,
+			wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
 				       P2P_EVENT_FALLBACK_TO_GO_NEG
 				       "reason=peer-not-running-GO");
 			wpas_p2p_connect(wpa_s, wpa_s->pending_join_dev_addr,
@@ -4754,7 +4786,7 @@
 			   "try to join the group", join ? "" :
 			   " in older scan");
 		if (!join) {
-			wpa_msg_global(wpa_s->parent, MSG_INFO,
+			wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
 				       P2P_EVENT_FALLBACK_TO_GO_NEG_ENABLED);
 			wpa_s->p2p_fallback_to_go_neg = 1;
 		}
@@ -4823,7 +4855,7 @@
 		u16 method;
 
 		if (wpas_check_freq_conflict(wpa_s, freq) > 0) {
-			wpa_msg_global(wpa_s->parent, MSG_INFO,
+			wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
 				       P2P_EVENT_GROUP_FORMATION_FAILURE
 				       "reason=FREQ_CONFLICT");
 			wpas_notify_p2p_group_formation_failure(
@@ -4904,6 +4936,7 @@
 	struct wpabuf *wps_ie, *ies;
 	size_t ielen;
 	int freqs[2] = { 0, 0 };
+	unsigned int bands;
 
 	os_memset(&params, 0, sizeof(params));
 
@@ -4929,22 +4962,6 @@
 		return;
 	}
 
-	ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p);
-	ies = wpabuf_alloc(wpabuf_len(wps_ie) + ielen);
-	if (ies == NULL) {
-		wpabuf_free(wps_ie);
-		wpas_p2p_scan_res_join(wpa_s, NULL);
-		return;
-	}
-	wpabuf_put_buf(ies, wps_ie);
-	wpabuf_free(wps_ie);
-
-	p2p_scan_ie(wpa_s->global->p2p, ies, NULL);
-
-	params.p2p_probe = 1;
-	params.extra_ies = wpabuf_head(ies);
-	params.extra_ies_len = wpabuf_len(ies);
-
 	if (!freq) {
 		int oper_freq;
 		/*
@@ -4961,6 +4978,23 @@
 		params.freqs = freqs;
 	}
 
+	ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p);
+	ies = wpabuf_alloc(wpabuf_len(wps_ie) + ielen);
+	if (ies == NULL) {
+		wpabuf_free(wps_ie);
+		wpas_p2p_scan_res_join(wpa_s, NULL);
+		return;
+	}
+	wpabuf_put_buf(ies, wps_ie);
+	wpabuf_free(wps_ie);
+
+	bands = wpas_get_bands(wpa_s, freqs);
+	p2p_scan_ie(wpa_s->global->p2p, ies, NULL, bands);
+
+	params.p2p_probe = 1;
+	params.extra_ies = wpabuf_head(ies);
+	params.extra_ies_len = wpabuf_len(ies);
+
 	/*
 	 * Run a scan to update BSS table and start Provision Discovery once
 	 * the new scan results become available.
@@ -5397,7 +5431,10 @@
 
 		if_addr = wpa_s->pending_interface_addr;
 	} else {
-		if_addr = wpa_s->own_addr;
+		if (wpa_s->p2p_mgmt)
+			if_addr = wpa_s->parent->own_addr;
+		else
+			if_addr = wpa_s->own_addr;
 		os_memset(wpa_s->go_dev_addr, 0, ETH_ALEN);
 	}
 
@@ -5943,9 +5980,20 @@
 	struct wpa_supplicant *group_wpa_s;
 
 	if (!wpas_p2p_create_iface(wpa_s)) {
-		wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Use same interface for group "
-			"operations");
+		if (wpa_s->p2p_mgmt) {
+			/*
+			 * We may be called on the p2p_dev interface which
+			 * cannot be used for group operations, so always use
+			 * the primary interface.
+			 */
+			wpa_s->parent->p2pdev = wpa_s;
+			wpa_s = wpa_s->parent;
+		}
+		wpa_dbg(wpa_s, MSG_DEBUG,
+			"P2P: Use primary interface for group operations");
 		wpa_s->p2p_first_connection_timeout = 0;
+		if (wpa_s != wpa_s->p2pdev)
+			wpas_p2p_clone_config_dh(wpa_s, wpa_s->p2pdev);
 		return wpa_s;
 	}
 
@@ -6084,11 +6132,11 @@
 	wpa_s->p2p_go_group_formation_completed = 0;
 	wpa_s->global->p2p_group_formation = wpa_s;
 
-	eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s->parent,
+	eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s->p2pdev,
 			     NULL);
 	eloop_register_timeout(P2P_MAX_INITIAL_CONN_WAIT, 0,
 			       wpas_p2p_group_formation_timeout,
-			       wpa_s->parent, NULL);
+			       wpa_s->p2pdev, NULL);
 	wpa_supplicant_select_network(wpa_s, ssid);
 
 	return 0;
@@ -6115,7 +6163,7 @@
 			   "already running");
 		if (go == 0 &&
 		    eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
-					 wpa_s->parent, NULL)) {
+					 wpa_s->p2pdev, NULL)) {
 			/*
 			 * This can happen if Invitation Response frame was lost
 			 * and the peer (GO of a persistent group) tries to
@@ -6128,7 +6176,7 @@
 				   "P2P: Reschedule group formation timeout since peer is still trying to invite us");
 			eloop_register_timeout(P2P_MAX_INITIAL_CONN_WAIT, 0,
 					       wpas_p2p_group_formation_timeout,
-					       wpa_s->parent, NULL);
+					       wpa_s->p2pdev, NULL);
 		}
 		return 0;
 	}
@@ -6311,7 +6359,7 @@
 		p2p_clear_provisioning_info(wpa_s->global->p2p, go_dev_addr);
 	}
 
-	eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s->parent,
+	eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s->p2pdev,
 			     NULL);
 	wpa_s->p2p_go_group_formation_completed = 1;
 	if (ssid && ssid->mode == WPAS_MODE_INFRA) {
@@ -6326,7 +6374,7 @@
 			P2P_MAX_INITIAL_CONN_WAIT);
 		eloop_register_timeout(P2P_MAX_INITIAL_CONN_WAIT, 0,
 				       wpas_p2p_group_formation_timeout,
-				       wpa_s->parent, NULL);
+				       wpa_s->p2pdev, NULL);
 		/* Complete group formation on successful data connection. */
 		wpa_s->p2p_go_group_formation_completed = 0;
 	} else if (ssid) {
@@ -6340,7 +6388,7 @@
 			P2P_MAX_INITIAL_CONN_WAIT_GO);
 		eloop_register_timeout(P2P_MAX_INITIAL_CONN_WAIT_GO, 0,
 				       wpas_p2p_group_formation_timeout,
-				       wpa_s->parent, NULL);
+				       wpa_s->p2pdev, NULL);
 		/*
 		 * Complete group formation on first successful data connection
 		 */
@@ -6379,7 +6427,7 @@
 		wpa_s->global->p2p_fail_on_wps_complete = 1;
 		eloop_deplete_timeout(0, 50000,
 				      wpas_p2p_group_formation_timeout,
-				      wpa_s->parent, NULL);
+				      wpa_s->p2pdev, NULL);
 	}
 }
 
@@ -6673,12 +6721,15 @@
 
 void wpas_p2p_scan_ie(struct wpa_supplicant *wpa_s, struct wpabuf *ies)
 {
+	unsigned int bands;
+
 	if (wpa_s->global->p2p_disabled)
 		return;
 	if (wpa_s->global->p2p == NULL)
 		return;
 
-	p2p_scan_ie(wpa_s->global->p2p, ies, NULL);
+	bands = wpas_get_bands(wpa_s, NULL);
+	p2p_scan_ie(wpa_s->global->p2p, ies, NULL, bands);
 }
 
 
@@ -6745,7 +6796,9 @@
 				return -1;
 			}
 			bssid = wpa_s->pending_interface_addr;
-		} else
+		} else if (wpa_s->p2p_mgmt)
+			bssid = wpa_s->parent->own_addr;
+		else
 			bssid = wpa_s->own_addr;
 	} else {
 		role = P2P_INVITE_ROLE_CLIENT;
@@ -6823,7 +6876,7 @@
 
 	wpa_s->global->p2p_invite_group = wpa_s;
 	persistent = ssid->p2p_persistent_group &&
-		wpas_p2p_get_persistent(wpa_s->parent, peer_addr,
+		wpas_p2p_get_persistent(wpa_s->p2pdev, peer_addr,
 					ssid->ssid, ssid->ssid_len);
 
 	if (ssid->mode == WPAS_MODE_P2P_GO) {
@@ -6846,7 +6899,7 @@
 		freq = wpa_s->current_bss ? wpa_s->current_bss->freq :
 			(int) wpa_s->assoc_freq;
 	}
-	wpa_s->parent->pending_invite_ssid_id = -1;
+	wpa_s->p2pdev->pending_invite_ssid_id = -1;
 
 	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
 		return -1;
@@ -6877,7 +6930,7 @@
 
 	if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION) {
 		eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
-				     wpa_s->parent, NULL);
+				     wpa_s->p2pdev, NULL);
 	}
 
 	if (!wpa_s->show_group_started || !ssid)
@@ -6928,7 +6981,7 @@
 			       ip_addr);
 
 	if (persistent)
-		network_id = wpas_p2p_store_persistent_group(wpa_s->parent,
+		network_id = wpas_p2p_store_persistent_group(wpa_s->p2pdev,
 							     ssid, go_dev_addr);
 	if (network_id < 0)
 		network_id = ssid->id;
@@ -7265,7 +7318,7 @@
 
 			iface->cross_connect_enabled = 0;
 			iface->cross_connect_in_use = 0;
-			wpa_msg_global(iface->parent, MSG_INFO,
+			wpa_msg_global(iface->p2pdev, MSG_INFO,
 				       P2P_EVENT_CROSS_CONNECT_DISABLE "%s %s",
 				       iface->ifname,
 				       iface->cross_connect_uplink);
@@ -7295,7 +7348,7 @@
 			continue;
 
 		iface->cross_connect_in_use = 1;
-		wpa_msg_global(iface->parent, MSG_INFO,
+		wpa_msg_global(iface->p2pdev, MSG_INFO,
 			       P2P_EVENT_CROSS_CONNECT_ENABLE "%s %s",
 			       iface->ifname, iface->cross_connect_uplink);
 	}
@@ -7315,7 +7368,7 @@
 		if (!iface->cross_connect_in_use)
 			continue;
 
-		wpa_msg_global(iface->parent, MSG_INFO,
+		wpa_msg_global(iface->p2pdev, MSG_INFO,
 			       P2P_EVENT_CROSS_CONNECT_DISABLE "%s %s",
 			       iface->ifname, iface->cross_connect_uplink);
 		iface->cross_connect_in_use = 0;
@@ -7378,7 +7431,7 @@
 			break;
 
 		wpa_s->cross_connect_in_use = 1;
-		wpa_msg_global(wpa_s->parent, MSG_INFO,
+		wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
 			       P2P_EVENT_CROSS_CONNECT_ENABLE "%s %s",
 			       wpa_s->ifname, wpa_s->cross_connect_uplink);
 		break;
@@ -7394,8 +7447,8 @@
 
 	wpa_printf(MSG_DEBUG, "P2P: Terminate connection due to WPS PBC "
 		   "session overlap");
-	if (wpa_s != wpa_s->parent)
-		wpa_msg_ctrl(wpa_s->parent, MSG_INFO, WPS_EVENT_OVERLAP);
+	if (wpa_s != wpa_s->p2pdev)
+		wpa_msg_ctrl(wpa_s->p2pdev, MSG_INFO, WPS_EVENT_OVERLAP);
 	wpas_p2p_group_formation_failed(wpa_s, 0);
 	return 1;
 }
@@ -7502,7 +7555,7 @@
 				   wpa_s->ifname);
 			found = 1;
 			eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
-					     wpa_s->parent, NULL);
+					     wpa_s->p2pdev, NULL);
 			if (wpa_s->p2p_in_provisioning) {
 				wpas_group_formation_completed(wpa_s, 0, 0);
 				break;
@@ -7632,7 +7685,7 @@
 {
 	if (wpa_s->p2p_in_provisioning && ssid->p2p_group &&
 	    eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
-				 wpa_s->parent, NULL) > 0) {
+				 wpa_s->p2pdev, NULL) > 0) {
 		/**
 		 * Remove the network by scheduling the group formation
 		 * timeout to happen immediately. The teardown code
@@ -7644,7 +7697,7 @@
 		wpa_printf(MSG_DEBUG, "P2P: Canceled group formation due to "
 			   "P2P group network getting removed");
 		eloop_register_timeout(0, 0, wpas_p2p_group_formation_timeout,
-				       wpa_s->parent, NULL);
+				       wpa_s->p2pdev, NULL);
 	}
 }
 
@@ -7688,7 +7741,7 @@
 				       const u8 *addr)
 {
 	if (eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
-				 wpa_s->parent, NULL) > 0) {
+				 wpa_s->p2pdev, NULL) > 0) {
 		/*
 		 * This can happen if WPS provisioning step is not terminated
 		 * cleanly (e.g., P2P Client does not send WSC_Done). Since the
@@ -7767,7 +7820,7 @@
 
 	wpa_dbg(wpa_s, MSG_DEBUG, "P2P: GO not found for p2p_connect-auto - "
 		"fallback to GO Negotiation");
-	wpa_msg_global(wpa_s->parent, MSG_INFO, P2P_EVENT_FALLBACK_TO_GO_NEG
+	wpa_msg_global(wpa_s->p2pdev, MSG_INFO, P2P_EVENT_FALLBACK_TO_GO_NEG
 		       "reason=GO-not-found");
 	res = wpas_p2p_fallback_to_go_neg(wpa_s, 1);
 
@@ -7876,7 +7929,7 @@
 		return;
 	}
 
-	persistent = wpas_p2p_get_persistent(wpa_s->parent, NULL, ssid->ssid,
+	persistent = wpas_p2p_get_persistent(wpa_s->p2pdev, NULL, ssid->ssid,
 					     ssid->ssid_len);
 	if (!persistent) {
 		wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Could not find persistent group information to store the new PSK");
@@ -7905,7 +7958,7 @@
 		os_free(last);
 	}
 
-	wpas_p2p_remove_psk_entry(wpa_s->parent, persistent,
+	wpas_p2p_remove_psk_entry(wpa_s->p2pdev, persistent,
 				  p2p_dev_addr ? p2p_dev_addr : mac_addr,
 				  p2p_dev_addr == NULL);
 	if (p2p_dev_addr) {
@@ -7917,8 +7970,8 @@
 	}
 	dl_list_add(&persistent->psk_list, &p->list);
 
-	if (wpa_s->parent->conf->update_config &&
-	    wpa_config_write(wpa_s->parent->confname, wpa_s->parent->conf))
+	if (wpa_s->p2pdev->conf->update_config &&
+	    wpa_config_write(wpa_s->p2pdev->confname, wpa_s->p2pdev->conf))
 		wpa_printf(MSG_DEBUG, "P2P: Failed to update configuration");
 }
 
@@ -8097,14 +8150,14 @@
 
 		wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Two 4-way handshake failures for a P2P group - go_dev_addr="
 			MACSTR, MAC2STR(go_dev_addr));
-		persistent = wpas_p2p_get_persistent(wpa_s->parent, go_dev_addr,
+		persistent = wpas_p2p_get_persistent(wpa_s->p2pdev, go_dev_addr,
 						     ssid->ssid,
 						     ssid->ssid_len);
 		if (persistent == NULL || persistent->mode != WPAS_MODE_INFRA) {
 			wpa_dbg(wpa_s, MSG_DEBUG, "P2P: No matching persistent group stored");
 			goto disconnect;
 		}
-		wpa_msg_global(wpa_s->parent, MSG_INFO,
+		wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
 			       P2P_EVENT_PERSISTENT_PSK_FAIL "%d",
 			       persistent->id);
 	disconnect:
@@ -8671,7 +8724,9 @@
 		}
 
 		if_addr = wpa_s->pending_interface_addr;
-	} else
+	} else if (wpa_s->p2p_mgmt)
+		if_addr = wpa_s->parent->own_addr;
+	else
 		if_addr = wpa_s->own_addr;
 
 	wpa_s->p2p_nfc_tag_enabled = enabled;
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index c333e57..3463dd9 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -1006,6 +1006,27 @@
 		}
 	}
 
+	if (!is_zero_ether_addr(wpa_s->next_scan_bssid)) {
+		struct wpa_bss *bss;
+
+		params.bssid = wpa_s->next_scan_bssid;
+		bss = wpa_bss_get_bssid_latest(wpa_s, params.bssid);
+		if (bss && bss->ssid_len && params.num_ssids == 1 &&
+		    params.ssids[0].ssid_len == 0) {
+			params.ssids[0].ssid = bss->ssid;
+			params.ssids[0].ssid_len = bss->ssid_len;
+			wpa_dbg(wpa_s, MSG_DEBUG,
+				"Scan a previously specified BSSID " MACSTR
+				" and SSID %s",
+				MAC2STR(params.bssid),
+				wpa_ssid_txt(bss->ssid, bss->ssid_len));
+		} else {
+			wpa_dbg(wpa_s, MSG_DEBUG,
+				"Scan a previously specified BSSID " MACSTR,
+				MAC2STR(params.bssid));
+		}
+	}
+
 	scan_params = &params;
 
 scan:
@@ -1066,6 +1087,8 @@
 #ifdef CONFIG_INTERWORKING
 		wpa_s->interworking_fast_assoc_tried = 0;
 #endif /* CONFIG_INTERWORKING */
+		if (params.bssid)
+			os_memset(wpa_s->next_scan_bssid, 0, ETH_ALEN);
 	}
 }
 
@@ -2259,6 +2282,17 @@
 			params->mac_addr_mask = mac_addr + ETH_ALEN;
 		}
 	}
+
+	if (src->bssid) {
+		u8 *bssid;
+
+		bssid = os_malloc(ETH_ALEN);
+		if (!bssid)
+			goto failed;
+		os_memcpy(bssid, src->bssid, ETH_ALEN);
+		params->bssid = bssid;
+	}
+
 	return params;
 
 failed:
@@ -2287,6 +2321,8 @@
 	 */
 	os_free((u8 *) params->mac_addr);
 
+	os_free((u8 *) params->bssid);
+
 	os_free(params);
 }
 
@@ -2508,7 +2544,13 @@
 
 int wpas_abort_ongoing_scan(struct wpa_supplicant *wpa_s)
 {
-	if (wpa_s->scan_work && wpa_s->own_scan_running) {
+	int scan_work = !!wpa_s->scan_work;
+
+#ifdef CONFIG_P2P
+	scan_work |= !!wpa_s->p2p_scan_work;
+#endif /* CONFIG_P2P */
+
+	if (scan_work && wpa_s->own_scan_running) {
 		wpa_dbg(wpa_s, MSG_DEBUG, "Abort an ongoing scan");
 		return wpa_drv_abort_scan(wpa_s);
 	}
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index f09534d..a6ace1a 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -1009,8 +1009,8 @@
 	if (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group)
 		params.p2p = 1;
 
-	if (wpa_s->parent->set_sta_uapsd)
-		params.uapsd = wpa_s->parent->sta_uapsd;
+	if (wpa_s->p2pdev->set_sta_uapsd)
+		params.uapsd = wpa_s->p2pdev->sta_uapsd;
 	else
 		params.uapsd = -1;
 
diff --git a/wpa_supplicant/wnm_sta.c b/wpa_supplicant/wnm_sta.c
index 0dc41dc..7d2a92f 100644
--- a/wpa_supplicant/wnm_sta.c
+++ b/wpa_supplicant/wnm_sta.c
@@ -1115,11 +1115,22 @@
 				rep = &wpa_s->wnm_neighbor_report_elements[
 					wpa_s->wnm_num_neighbor_report];
 				wnm_parse_neighbor_report(wpa_s, pos, len, rep);
+				wpa_s->wnm_num_neighbor_report++;
 			}
 
 			pos += len;
-			wpa_s->wnm_num_neighbor_report++;
 		}
+
+		if (!wpa_s->wnm_num_neighbor_report) {
+			wpa_printf(MSG_DEBUG,
+				   "WNM: Candidate list included bit is set, but no candidates found");
+			wnm_send_bss_transition_mgmt_resp(
+				wpa_s, wpa_s->wnm_dialog_token,
+				WNM_BSS_TM_REJECT_NO_SUITABLE_CANDIDATES,
+				0, NULL);
+			return;
+		}
+
 		wnm_sort_cand_list(wpa_s);
 		wnm_dump_cand_list(wpa_s);
 		valid_ms = valid_int * beacon_int * 128 / 125;
@@ -1148,6 +1159,14 @@
 		}
 
 		wnm_set_scan_freqs(wpa_s);
+		if (wpa_s->wnm_num_neighbor_report == 1) {
+			os_memcpy(wpa_s->next_scan_bssid,
+				  wpa_s->wnm_neighbor_report_elements[0].bssid,
+				  ETH_ALEN);
+			wpa_printf(MSG_DEBUG,
+				   "WNM: Scan only for a specific BSSID since there is only a single candidate "
+				   MACSTR, MAC2STR(wpa_s->next_scan_bssid));
+		}
 		wpa_supplicant_req_scan(wpa_s, 0, 0);
 	} else if (reply) {
 		enum bss_trans_mgmt_status_code status;
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index f8bf6bd..eecb1dc 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -3659,6 +3659,10 @@
 	size_t len;
 	int res;
 
+	/* If no interface is specified, set the global */
+	if (!arg1)
+		arg1 = "global";
+
 	len = os_strlen(arg1) + os_strlen(arg2) + 2;
 	arg = os_malloc(len);
 	if (arg == NULL)
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index dbfc34e..136cb58 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -2490,8 +2490,8 @@
 
 	params.p2p = ssid->p2p_group;
 
-	if (wpa_s->parent->set_sta_uapsd)
-		params.uapsd = wpa_s->parent->sta_uapsd;
+	if (wpa_s->p2pdev->set_sta_uapsd)
+		params.uapsd = wpa_s->p2pdev->sta_uapsd;
 	else
 		params.uapsd = -1;
 
@@ -3510,6 +3510,7 @@
 	wpa_s->scan_interval = 5;
 	wpa_s->new_connection = 1;
 	wpa_s->parent = parent ? parent : wpa_s;
+	wpa_s->p2pdev = wpa_s->parent;
 	wpa_s->sched_scanning = 0;
 
 	dl_list_init(&wpa_s->bss_tmp_disallowed);
@@ -4021,7 +4022,7 @@
 }
 
 
-static enum wpa_radio_work_band wpas_freq_to_band(int freq)
+enum wpa_radio_work_band wpas_freq_to_band(int freq)
 {
 	if (freq < 3000)
 		return BAND_2_4_GHZ;
@@ -4031,8 +4032,7 @@
 }
 
 
-static unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s,
-				   const int *freqs)
+unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
 {
 	int i;
 	unsigned int band = 0;
@@ -4839,6 +4839,8 @@
 
 	iface = global->ifaces;
 	while (iface) {
+		if (iface->p2pdev == wpa_s)
+			iface->p2pdev = iface->parent;
 		if (iface == wpa_s || iface->parent != wpa_s) {
 			iface = iface->next;
 			continue;
@@ -6248,7 +6250,7 @@
 	case VENDOR_ELEM_P2P_INV_RESP:
 	case VENDOR_ELEM_P2P_ASSOC_REQ:
 	case VENDOR_ELEM_P2P_ASSOC_RESP:
-		return wpa_s->parent;
+		return wpa_s->p2pdev;
 #endif /* CONFIG_P2P */
 	default:
 		return wpa_s;
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 0e3e42a..1b16d28 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -308,11 +308,6 @@
 
 #define MAX_ACTIVE_WORKS 2
 
-enum wpa_radio_work_band {
-	BAND_2_4_GHZ = BIT(0),
-	BAND_5_GHZ = BIT(1),
-	BAND_60_GHZ = BIT(2),
-};
 
 /**
  * struct wpa_radio_work - Radio work item
@@ -358,6 +353,9 @@
 	unsigned int timeout;
 };
 
+enum wpa_radio_work_band wpas_freq_to_band(int freq);
+unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs);
+
 /**
  * offchannel_send_action_result - Result of offchannel send Action frame
  */
@@ -453,6 +451,7 @@
 	struct wpa_radio *radio; /* shared radio context */
 	struct dl_list radio_list; /* list head: struct wpa_radio::ifaces */
 	struct wpa_supplicant *parent;
+	struct wpa_supplicant *p2pdev;
 	struct wpa_supplicant *next;
 	struct l2_packet_data *l2;
 	struct l2_packet_data *l2_br;
@@ -640,6 +639,7 @@
 #define MAX_SCAN_ID 16
 	int scan_id[MAX_SCAN_ID];
 	unsigned int scan_id_count;
+	u8 next_scan_bssid[ETH_ALEN];
 
 	struct wpa_ssid_value *ssids_from_scan_req;
 	unsigned int num_ssids_from_scan_req;
diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c
index 07452ad..0860eb4 100644
--- a/wpa_supplicant/wps_supplicant.c
+++ b/wpa_supplicant/wps_supplicant.c
@@ -583,8 +583,8 @@
 		m2d->dev_password_id, m2d->config_error);
 	wpas_notify_wps_event_m2d(wpa_s, m2d);
 #ifdef CONFIG_P2P
-	if (wpa_s->parent && wpa_s->parent != wpa_s) {
-		wpa_msg(wpa_s->parent, MSG_INFO, WPS_EVENT_M2D
+	if (wpa_s->p2pdev && wpa_s->p2pdev != wpa_s) {
+		wpa_msg(wpa_s->p2pdev, MSG_INFO, WPS_EVENT_M2D
 			"dev_password_id=%d config_error=%d",
 			m2d->dev_password_id, m2d->config_error);
 	}
@@ -617,8 +617,8 @@
 			WPS_EVENT_FAIL "msg=%d config_error=%d reason=%d (%s)",
 			fail->msg, fail->config_error, fail->error_indication,
 			wps_ei_str(fail->error_indication));
-		if (wpa_s->parent && wpa_s->parent != wpa_s)
-			wpa_msg(wpa_s->parent, MSG_INFO, WPS_EVENT_FAIL
+		if (wpa_s->p2pdev && wpa_s->p2pdev != wpa_s)
+			wpa_msg(wpa_s->p2pdev, MSG_INFO, WPS_EVENT_FAIL
 				"msg=%d config_error=%d reason=%d (%s)",
 				fail->msg, fail->config_error,
 				fail->error_indication,
@@ -627,8 +627,8 @@
 		wpa_msg(wpa_s, MSG_INFO,
 			WPS_EVENT_FAIL "msg=%d config_error=%d",
 			fail->msg, fail->config_error);
-		if (wpa_s->parent && wpa_s->parent != wpa_s)
-			wpa_msg(wpa_s->parent, MSG_INFO, WPS_EVENT_FAIL
+		if (wpa_s->p2pdev && wpa_s->p2pdev != wpa_s)
+			wpa_msg(wpa_s->p2pdev, MSG_INFO, WPS_EVENT_FAIL
 				"msg=%d config_error=%d",
 				fail->msg, fail->config_error);
 	}