Cumulative patch from commit 31ded52e7084976c5f84caae6cb55e632dd8b013

31ded52 SME: Add more debug prints for OBSS scans and 20/40 MHz co-ex report
7f8eb34 SME: Fix OBSS scan result processing for 20/40 MHz co-ex report
b7a8d67 Allow hostapd to advertise 40 MHz intolerant HT capability
692ec30 FT: Add support for postponing FT response
6ace13a P2P: Clean up channel selection code to use helper functions
70c3523 WPS: Comment out unused AP WEP config write with WPS 2.0
c3ba70f P2P: Update op_reg_class in random social channel case
70634ee hostapd: Check driver DFS offload capability for channel disablement
65d645c nl80211: Fetch DFS offload capability from driver
a500f31 WPS: Comment out unused AP WEP config update with WPS 2.0
be4e5af Add SAE and FT-SAE key_mgmt to hostapd GET_CONFIG
1d4fe3b Remove unnecessary parameter validation
94b84bc P2P: Avoid unsafe pre-configured channel as channel preference
d3c9c35 Add freq= parameter to 'set pno' command
b998236 dbus: Implement P2P Peers info IEs buffer getter
c6f356f dbus: Export the peer's device address as a property
442adfd dbus: Declare properly ServiceDiscoveryRequest method
8903741 dbus: Cancelling a service request always reply by an error
13494c4 dbus: Remove duplicate signal declaration
513dcec Don't overwrite channel on hostapd config reload
5eae87a P2P: Fix GO failed interface init
c46235a wpa_supplicant: Fix radio_remove_interface
2ce7e4f Android: Enable CONFIG_EAP_AKA_PRIME option
95bf699 Add get_radio_name() driver wrapper for wpa_supplicant
d06ecab D-Bus: Make p2p_no_group_iface configurable
8b6b6d8 Fix hostapd.conf description of HT40+

Change-Id: I5e776f71050a106195a39e96d0c38930a387a806
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 814468d..e1f8b20 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -1067,6 +1067,8 @@
 		conf->ht_capab |= HT_CAP_INFO_DSSS_CCK40MHZ;
 	if (os_strstr(capab, "[PSMP]"))
 		conf->ht_capab |= HT_CAP_INFO_PSMP_SUPP;
+	if (os_strstr(capab, "[40-INTOLERANT]"))
+		conf->ht_capab |= HT_CAP_INFO_40MHZ_INTOLERANT;
 	if (os_strstr(capab, "[LSIG-TXOP-PROT]"))
 		conf->ht_capab |= HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT;
 
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index dbdc8c6..29d5d8b 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -940,6 +940,14 @@
 				return pos - buf;
 			pos += ret;
 		}
+#ifdef CONFIG_SAE
+		if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) {
+			ret = os_snprintf(pos, end - pos, "FT-SAE ");
+			if (ret < 0 || ret >= end - pos)
+				return pos - buf;
+			pos += ret;
+		}
+#endif /* CONFIG_SAE */
 #endif /* CONFIG_IEEE80211R */
 #ifdef CONFIG_IEEE80211W
 		if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
@@ -955,6 +963,14 @@
 			pos += ret;
 		}
 #endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_SAE
+		if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) {
+			ret = os_snprintf(pos, end - pos, "SAE ");
+			if (ret < 0 || ret >= end - pos)
+				return pos - buf;
+			pos += ret;
+		}
+#endif /* CONFIG_SAE */
 
 		ret = os_snprintf(pos, end - pos, "\n");
 		if (ret < 0 || ret >= end - pos)
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index 23ee1e5..b5770a4 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -453,7 +453,7 @@
 # LDPC coding capability: [LDPC] = supported
 # Supported channel width set: [HT40-] = both 20 MHz and 40 MHz with secondary
 #	channel below the primary channel; [HT40+] = both 20 MHz and 40 MHz
-#	with secondary channel below the primary channel
+#	with secondary channel above the primary channel
 #	(20 MHz only if neither is set)
 #	Note: There are limits on which channels can be used with HT40- and
 #	HT40+. Following table shows the channels that may be available for
@@ -481,6 +481,7 @@
 #	set)
 # DSSS/CCK Mode in 40 MHz: [DSSS_CCK-40] = allowed (not allowed if not set)
 # PSMP support: [PSMP] (disabled if not set)
+# 40 MHz intolerant [40-INTOLERANT] (not advertised if not set)
 # L-SIG TXOP protection support: [LSIG-TXOP-PROT] (disabled if not set)
 #ht_capab=[HT40-][SHORT-GI-20][SHORT-GI-40]
 
diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
index 11351c4..e1020a6 100644
--- a/src/ap/ctrl_iface_ap.c
+++ b/src/ap/ctrl_iface_ap.c
@@ -469,9 +469,6 @@
 {
 	char *end;
 
-	if (!settings)
-		return -1;
-
 	os_memset(settings, 0, sizeof(*settings));
 	settings->cs_count = strtol(pos, &end, 10);
 	if (pos == end) {
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 4ed718c..2ecaec8 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -171,6 +171,16 @@
 	for (j = 0; j < iface->num_bss; j++) {
 		hapd = iface->bss[j];
 		hapd->iconf = newconf;
+		hapd->iconf->channel = oldconf->channel;
+		hapd->iconf->ieee80211n = oldconf->ieee80211n;
+		hapd->iconf->ieee80211ac = oldconf->ieee80211ac;
+		hapd->iconf->ht_capab = oldconf->ht_capab;
+		hapd->iconf->vht_capab = oldconf->vht_capab;
+		hapd->iconf->vht_oper_chwidth = oldconf->vht_oper_chwidth;
+		hapd->iconf->vht_oper_centr_freq_seg0_idx =
+			oldconf->vht_oper_centr_freq_seg0_idx;
+		hapd->iconf->vht_oper_centr_freq_seg1_idx =
+			oldconf->vht_oper_centr_freq_seg1_idx;
 		hapd->conf = newconf->bss[j];
 		hostapd_reload_bss(hapd);
 	}
diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
index d319ce0..54a79b0 100644
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -111,10 +111,13 @@
 			if ((feature->channels[j].flag &
 			     HOSTAPD_CHAN_RADAR) && dfs_enabled) {
 				dfs = 1;
-			} else if (feature->channels[j].flag &
-				   (HOSTAPD_CHAN_NO_IBSS |
-				    HOSTAPD_CHAN_PASSIVE_SCAN |
-				    HOSTAPD_CHAN_RADAR)) {
+			} else if (((feature->channels[j].flag &
+				     HOSTAPD_CHAN_RADAR) &&
+				    !(iface->drv_flags &
+				      WPA_DRIVER_FLAGS_DFS_OFFLOAD)) ||
+				   (feature->channels[j].flag &
+				    (HOSTAPD_CHAN_NO_IBSS |
+				     HOSTAPD_CHAN_PASSIVE_SCAN))) {
 				feature->channels[j].flag |=
 					HOSTAPD_CHAN_DISABLED;
 			}
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index 4d19bb0..77e7858 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -621,6 +621,7 @@
 	}
 #ifdef CONFIG_IEEE80211R
 	os_free(sm->assoc_resp_ftie);
+	wpabuf_free(sm->ft_pending_req_ies);
 #endif /* CONFIG_IEEE80211R */
 	os_free(sm->last_rx_eapol_key);
 	os_free(sm->wpa_ie);
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index 3ab3e3d..929a253 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -42,6 +42,7 @@
 #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
 
 struct ft_r0kh_r1kh_pull_frame {
 	u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */
@@ -49,7 +50,7 @@
 	le16 data_length; /* little endian length of data (44) */
 	u8 ap_address[ETH_ALEN];
 
-	u8 nonce[16];
+	u8 nonce[FT_R0KH_R1KH_PULL_NONCE_LEN];
 	u8 pmk_r0_name[WPA_PMK_NAME_LEN];
 	u8 r1kh_id[FT_R1KH_ID_LEN];
 	u8 s1kh_id[ETH_ALEN];
@@ -63,7 +64,7 @@
 	le16 data_length; /* little endian length of data (76) */
 	u8 ap_address[ETH_ALEN];
 
-	u8 nonce[16]; /* copied from pull */
+	u8 nonce[FT_R0KH_R1KH_PULL_NONCE_LEN]; /* copied from pull */
 	u8 r1kh_id[FT_R1KH_ID_LEN]; /* copied from pull */
 	u8 s1kh_id[ETH_ALEN]; /* copied from pull */
 	u8 pmk_r1[PMK_LEN];
diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c
index c22c4cc..7701596 100644
--- a/src/ap/wpa_auth_ft.c
+++ b/src/ap/wpa_auth_ft.c
@@ -1,6 +1,6 @@
 /*
  * hostapd - IEEE 802.11r - Fast BSS Transition
- * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -9,6 +9,7 @@
 #include "utils/includes.h"
 
 #include "utils/common.h"
+#include "utils/eloop.h"
 #include "common/ieee802_11_defs.h"
 #include "common/ieee802_11_common.h"
 #include "crypto/aes_wrap.h"
@@ -22,6 +23,12 @@
 
 #ifdef CONFIG_IEEE80211R
 
+static int wpa_ft_send_rrb_auth_resp(struct wpa_state_machine *sm,
+				     const u8 *current_ap, const u8 *sta_addr,
+				     u16 status, const u8 *resp_ies,
+				     size_t resp_ies_len);
+
+
 static int wpa_ft_rrb_send(struct wpa_authenticator *wpa_auth, const u8 *dst,
 			   const u8 *data, size_t data_len)
 {
@@ -293,22 +300,25 @@
 }
 
 
-static int wpa_ft_pull_pmk_r1(struct wpa_authenticator *wpa_auth,
-			      const u8 *s1kh_id, const u8 *r0kh_id,
-			      size_t r0kh_id_len, const u8 *pmk_r0_name)
+static int wpa_ft_pull_pmk_r1(struct wpa_state_machine *sm,
+			      const u8 *ies, size_t ies_len,
+			      const u8 *pmk_r0_name)
 {
 	struct ft_remote_r0kh *r0kh;
 	struct ft_r0kh_r1kh_pull_frame frame, f;
 
-	r0kh = wpa_auth->conf.r0kh_list;
+	r0kh = sm->wpa_auth->conf.r0kh_list;
 	while (r0kh) {
-		if (r0kh->id_len == r0kh_id_len &&
-		    os_memcmp(r0kh->id, r0kh_id, r0kh_id_len) == 0)
+		if (r0kh->id_len == sm->r0kh_id_len &&
+		    os_memcmp(r0kh->id, sm->r0kh_id, sm->r0kh_id_len) == 0)
 			break;
 		r0kh = r0kh->next;
 	}
-	if (r0kh == NULL)
+	if (r0kh == NULL) {
+		wpa_hexdump(MSG_DEBUG, "FT: Did not find R0KH-ID",
+			    sm->r0kh_id, sm->r0kh_id_len);
 		return -1;
+	}
 
 	wpa_printf(MSG_DEBUG, "FT: Send PMK-R1 pull request to remote R0KH "
 		   "address " MACSTR, MAC2STR(r0kh->addr));
@@ -317,25 +327,32 @@
 	frame.frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB;
 	frame.packet_type = FT_PACKET_R0KH_R1KH_PULL;
 	frame.data_length = host_to_le16(FT_R0KH_R1KH_PULL_DATA_LEN);
-	os_memcpy(frame.ap_address, wpa_auth->addr, ETH_ALEN);
+	os_memcpy(frame.ap_address, sm->wpa_auth->addr, ETH_ALEN);
 
 	/* aes_wrap() does not support inplace encryption, so use a temporary
 	 * buffer for the data. */
-	if (random_get_bytes(f.nonce, sizeof(f.nonce))) {
+	if (random_get_bytes(f.nonce, FT_R0KH_R1KH_PULL_NONCE_LEN)) {
 		wpa_printf(MSG_DEBUG, "FT: Failed to get random data for "
 			   "nonce");
 		return -1;
 	}
+	os_memcpy(sm->ft_pending_pull_nonce, f.nonce,
+		  FT_R0KH_R1KH_PULL_NONCE_LEN);
 	os_memcpy(f.pmk_r0_name, pmk_r0_name, WPA_PMK_NAME_LEN);
-	os_memcpy(f.r1kh_id, wpa_auth->conf.r1_key_holder, FT_R1KH_ID_LEN);
-	os_memcpy(f.s1kh_id, s1kh_id, ETH_ALEN);
+	os_memcpy(f.r1kh_id, sm->wpa_auth->conf.r1_key_holder, FT_R1KH_ID_LEN);
+	os_memcpy(f.s1kh_id, sm->addr, ETH_ALEN);
 	os_memset(f.pad, 0, sizeof(f.pad));
 
 	if (aes_wrap(r0kh->key, (FT_R0KH_R1KH_PULL_DATA_LEN + 7) / 8,
 		     f.nonce, frame.nonce) < 0)
 		return -1;
 
-	wpa_ft_rrb_send(wpa_auth, r0kh->addr, (u8 *) &frame, sizeof(frame));
+	wpabuf_free(sm->ft_pending_req_ies);
+	sm->ft_pending_req_ies = wpabuf_alloc_copy(ies, ies_len);
+	if (sm->ft_pending_req_ies == NULL)
+		return -1;
+
+	wpa_ft_rrb_send(sm->wpa_auth, r0kh->addr, (u8 *) &frame, sizeof(frame));
 
 	return 0;
 }
@@ -777,7 +794,7 @@
 }
 
 
-static u16 wpa_ft_process_auth_req(struct wpa_state_machine *sm,
+static int wpa_ft_process_auth_req(struct wpa_state_machine *sm,
 				   const u8 *ies, size_t ies_len,
 				   u8 **resp_ies, size_t *resp_ies_len)
 {
@@ -848,19 +865,13 @@
 
 	if (wpa_ft_fetch_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1_name, pmk_r1,
 		    &pairwise) < 0) {
-		if (wpa_ft_pull_pmk_r1(sm->wpa_auth, sm->addr, sm->r0kh_id,
-				       sm->r0kh_id_len, parse.rsn_pmkid) < 0) {
+		if (wpa_ft_pull_pmk_r1(sm, ies, ies_len, parse.rsn_pmkid) < 0) {
 			wpa_printf(MSG_DEBUG, "FT: Did not have matching "
 				   "PMK-R1 and unknown R0KH-ID");
 			return WLAN_STATUS_INVALID_PMKID;
 		}
 
-		/*
-		 * TODO: Should return "status pending" (and the caller should
-		 * not send out response now). The real response will be sent
-		 * once the response from R0KH is received.
-		 */
-		return WLAN_STATUS_INVALID_PMKID;
+		return -1; /* Status pending */
 	}
 
 	wpa_hexdump_key(MSG_DEBUG, "FT: Selected PMK-R1", pmk_r1, PMK_LEN);
@@ -940,6 +951,7 @@
 	u16 status;
 	u8 *resp_ies;
 	size_t resp_ies_len;
+	int res;
 
 	if (sm == NULL) {
 		wpa_printf(MSG_DEBUG, "FT: Received authentication frame, but "
@@ -950,8 +962,16 @@
 	wpa_printf(MSG_DEBUG, "FT: Received authentication frame: STA=" MACSTR
 		   " BSSID=" MACSTR " transaction=%d",
 		   MAC2STR(sm->addr), MAC2STR(bssid), auth_transaction);
-	status = wpa_ft_process_auth_req(sm, ies, ies_len, &resp_ies,
-					 &resp_ies_len);
+	sm->ft_pending_cb = cb;
+	sm->ft_pending_cb_ctx = ctx;
+	sm->ft_pending_auth_transaction = auth_transaction;
+	res = wpa_ft_process_auth_req(sm, ies, ies_len, &resp_ies,
+				      &resp_ies_len);
+	if (res < 0) {
+		wpa_printf(MSG_DEBUG, "FT: Callback postponed until response is available");
+		return;
+	}
+	status = res;
 
 	wpa_printf(MSG_DEBUG, "FT: FT authentication response: dst=" MACSTR
 		   " auth_transaction=%d status=%d",
@@ -1182,15 +1202,27 @@
 }
 
 
+static void wpa_ft_rrb_rx_request_cb(void *ctx, const u8 *dst, const u8 *bssid,
+				     u16 auth_transaction, u16 resp,
+				     const u8 *ies, size_t ies_len)
+{
+	struct wpa_state_machine *sm = ctx;
+	wpa_printf(MSG_DEBUG, "FT: Over-the-DS RX request cb for " MACSTR,
+		   MAC2STR(sm->addr));
+	wpa_ft_send_rrb_auth_resp(sm, sm->ft_pending_current_ap, sm->addr,
+				  WLAN_STATUS_SUCCESS, ies, ies_len);
+}
+
+
 static int wpa_ft_rrb_rx_request(struct wpa_authenticator *wpa_auth,
 				 const u8 *current_ap, const u8 *sta_addr,
 				 const u8 *body, size_t len)
 {
 	struct wpa_state_machine *sm;
 	u16 status;
-	u8 *resp_ies, *pos;
-	size_t resp_ies_len, rlen;
-	struct ft_rrb_frame *frame;
+	u8 *resp_ies;
+	size_t resp_ies_len;
+	int res;
 
 	sm = wpa_ft_add_sta(wpa_auth, sta_addr);
 	if (sm == NULL) {
@@ -1201,8 +1233,33 @@
 
 	wpa_hexdump(MSG_MSGDUMP, "FT: RRB Request Frame body", body, len);
 
-	status = wpa_ft_process_auth_req(sm, body, len, &resp_ies,
-					 &resp_ies_len);
+	sm->ft_pending_cb = wpa_ft_rrb_rx_request_cb;
+	sm->ft_pending_cb_ctx = sm;
+	os_memcpy(sm->ft_pending_current_ap, current_ap, ETH_ALEN);
+	res = wpa_ft_process_auth_req(sm, body, len, &resp_ies,
+				      &resp_ies_len);
+	if (res < 0) {
+		wpa_printf(MSG_DEBUG, "FT: No immediate response available - wait for pull response");
+		return 0;
+	}
+	status = res;
+
+	res = wpa_ft_send_rrb_auth_resp(sm, current_ap, sta_addr, status,
+					resp_ies, resp_ies_len);
+	os_free(resp_ies);
+	return res;
+}
+
+
+static int wpa_ft_send_rrb_auth_resp(struct wpa_state_machine *sm,
+				     const u8 *current_ap, const u8 *sta_addr,
+				     u16 status, const u8 *resp_ies,
+				     size_t resp_ies_len)
+{
+	struct wpa_authenticator *wpa_auth = sm->wpa_auth;
+	size_t rlen;
+	struct ft_rrb_frame *frame;
+	u8 *pos;
 
 	wpa_printf(MSG_DEBUG, "FT: RRB authentication response: STA=" MACSTR
 		   " CurrentAP=" MACSTR " status=%d",
@@ -1218,10 +1275,8 @@
 	rlen = 2 + 2 * ETH_ALEN + 2 + resp_ies_len;
 
 	frame = os_malloc(sizeof(*frame) + rlen);
-	if (frame == NULL) {
-		os_free(resp_ies);
+	if (frame == NULL)
 		return -1;
-	}
 	frame->frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB;
 	frame->packet_type = FT_PACKET_RESPONSE;
 	frame->action_length = host_to_le16(rlen);
@@ -1235,10 +1290,8 @@
 	pos += ETH_ALEN;
 	WPA_PUT_LE16(pos, status);
 	pos += 2;
-	if (resp_ies) {
+	if (resp_ies)
 		os_memcpy(pos, resp_ies, resp_ies_len);
-		os_free(resp_ies);
-	}
 
 	wpa_ft_rrb_send(wpa_auth, current_ap, (u8 *) frame,
 			sizeof(*frame) + rlen);
@@ -1290,7 +1343,7 @@
 		    f.nonce, sizeof(f.nonce));
 	wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - PMKR0Name",
 		    f.pmk_r0_name, WPA_PMK_NAME_LEN);
-	wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull - R1KH-ID=" MACSTR "S1KH-ID="
+	wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull - R1KH-ID=" MACSTR " S1KH-ID="
 		   MACSTR, MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id));
 
 	os_memset(&resp, 0, sizeof(resp));
@@ -1333,13 +1386,58 @@
 }
 
 
+static void ft_pull_resp_cb_finish(void *eloop_ctx, void *timeout_ctx)
+{
+	struct wpa_state_machine *sm = eloop_ctx;
+	int res;
+	u8 *resp_ies;
+	size_t resp_ies_len;
+	u16 status;
+
+	res = wpa_ft_process_auth_req(sm, wpabuf_head(sm->ft_pending_req_ies),
+				      wpabuf_len(sm->ft_pending_req_ies),
+				      &resp_ies, &resp_ies_len);
+	wpabuf_free(sm->ft_pending_req_ies);
+	sm->ft_pending_req_ies = NULL;
+	if (res < 0)
+		res = WLAN_STATUS_UNSPECIFIED_FAILURE;
+	status = res;
+	wpa_printf(MSG_DEBUG, "FT: Postponed auth callback result for " MACSTR
+		   " - status %u", MAC2STR(sm->addr), status);
+
+	sm->ft_pending_cb(sm->ft_pending_cb_ctx, sm->addr, sm->wpa_auth->addr,
+			  sm->ft_pending_auth_transaction + 1, status,
+			  resp_ies, resp_ies_len);
+	os_free(resp_ies);
+}
+
+
+static int ft_pull_resp_cb(struct wpa_state_machine *sm, void *ctx)
+{
+	struct ft_r0kh_r1kh_resp_frame *frame = ctx;
+
+	if (os_memcmp(frame->s1kh_id, sm->addr, ETH_ALEN) != 0)
+		return 0;
+	if (os_memcmp(frame->nonce, sm->ft_pending_pull_nonce,
+		      FT_R0KH_R1KH_PULL_NONCE_LEN) != 0)
+		return 0;
+	if (sm->ft_pending_cb == NULL || sm->ft_pending_req_ies == NULL)
+		return 0;
+
+	wpa_printf(MSG_DEBUG, "FT: Response to a pending pull request for "
+		   MACSTR " - process from timeout", MAC2STR(sm->addr));
+	eloop_register_timeout(0, 0, ft_pull_resp_cb_finish, sm, NULL);
+	return 1;
+}
+
+
 static int wpa_ft_rrb_rx_resp(struct wpa_authenticator *wpa_auth,
 			      const u8 *src_addr,
 			      const u8 *data, size_t data_len)
 {
 	struct ft_r0kh_r1kh_resp_frame *frame, f;
 	struct ft_remote_r0kh *r0kh;
-	int pairwise;
+	int pairwise, res;
 
 	wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 pull response");
 
@@ -1376,14 +1474,10 @@
 		return -1;
 	}
 
-	/* TODO: verify that <nonce,s1kh_id> matches with a pending request
-	 * and call this requests callback function to finish request
-	 * processing */
-
 	pairwise = le_to_host16(f.pairwise);
 	wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - nonce",
 		    f.nonce, sizeof(f.nonce));
-	wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull - R1KH-ID=" MACSTR "S1KH-ID="
+	wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull - R1KH-ID=" MACSTR " S1KH-ID="
 		   MACSTR " pairwise=0x%x",
 		   MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id), pairwise);
 	wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1 pull - PMK-R1",
@@ -1391,11 +1485,13 @@
 	wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - PMKR1Name",
 			f.pmk_r1_name, WPA_PMK_NAME_LEN);
 
-	wpa_ft_store_pmk_r1(wpa_auth, f.s1kh_id, f.pmk_r1, f.pmk_r1_name,
-			    pairwise);
+	res = wpa_ft_store_pmk_r1(wpa_auth, f.s1kh_id, f.pmk_r1, f.pmk_r1_name,
+				  pairwise);
+	wpa_printf(MSG_DEBUG, "FT: Look for pending pull request");
+	wpa_auth_for_each_sta(wpa_auth, ft_pull_resp_cb, &f);
 	os_memset(f.pmk_r1, 0, PMK_LEN);
 
-	return 0;
+	return res ? 0 : -1;
 }
 
 
diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h
index 2e1bdcf..6960ff3 100644
--- a/src/ap/wpa_auth_i.h
+++ b/src/ap/wpa_auth_i.h
@@ -118,6 +118,15 @@
 	u8 sup_pmk_r1_name[WPA_PMK_NAME_LEN]; /* PMKR1Name from EAPOL-Key
 					       * message 2/4 */
 	u8 *assoc_resp_ftie;
+
+	void (*ft_pending_cb)(void *ctx, const u8 *dst, const u8 *bssid,
+			      u16 auth_transaction, u16 status,
+			      const u8 *ies, size_t ies_len);
+	void *ft_pending_cb_ctx;
+	struct wpabuf *ft_pending_req_ies;
+	u8 ft_pending_pull_nonce[FT_R0KH_R1KH_PULL_NONCE_LEN];
+	u8 ft_pending_auth_transaction;
+	u8 ft_pending_current_ap[ETH_ALEN];
 #endif /* CONFIG_IEEE80211R */
 
 	int pending_1_of_4_timeout;
diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c
index 62cd03c..e0033ce 100644
--- a/src/ap/wps_hostapd.c
+++ b/src/ap/wps_hostapd.c
@@ -378,6 +378,13 @@
 		}
 		bss->auth_algs = 1;
 	} else {
+#ifdef CONFIG_WPS2
+		/*
+		 * WPS 2.0 does not allow WEP to be configured, so no need to
+		 * process that option here either.
+		 */
+		bss->auth_algs = 1;
+#else /* CONFIG_WPS2 */
 		if ((cred->auth_type & WPS_AUTH_OPEN) &&
 		    (cred->auth_type & WPS_AUTH_SHARED))
 			bss->auth_algs = 3;
@@ -412,6 +419,7 @@
 			}
 			wep->keys_set = 1;
 		}
+#endif /* CONFIG_WPS2 */
 	}
 
 	/* Schedule configuration reload after short period of time to allow
@@ -586,6 +594,13 @@
 
 		fprintf(nconf, "auth_algs=1\n");
 	} else {
+#ifdef CONFIG_WPS2
+		/*
+		 * WPS 2.0 does not allow WEP to be configured, so no need to
+		 * process that option here either.
+		 */
+		fprintf(nconf, "auth_algs=1\n");
+#else /* CONFIG_WPS2 */
 		if ((cred->auth_type & WPS_AUTH_OPEN) &&
 		    (cred->auth_type & WPS_AUTH_SHARED))
 			fprintf(nconf, "auth_algs=3\n");
@@ -611,6 +626,7 @@
 			}
 			fprintf(nconf, "\n");
 		}
+#endif /* CONFIG_WPS2 */
 	}
 
 	fprintf(nconf, "# WPS configuration - END\n");
diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h
index 0d83920..80bad4f 100644
--- a/src/common/qca-vendor.h
+++ b/src/common/qca-vendor.h
@@ -29,12 +29,16 @@
  *	ranges to avoid to reduce issues due to interference or internal
  *	co-existence information in the driver. The event data structure is
  *	defined in struct qca_avoid_freq_list.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY: Command to check driver support
+ *	for DFS offloading.
  */
 enum qca_nl80211_vendor_subcmds {
 	QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0,
 	QCA_NL80211_VENDOR_SUBCMD_TEST = 1,
 	/* subcmds 2..9 not yet allocated */
 	QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY = 10,
+	QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY =  11,
 };
 
 
@@ -48,4 +52,13 @@
 	struct qca_avoid_freq_range range[0];
 } STRUCT_PACKED;
 
+enum qca_wlan_vendor_attr {
+	QCA_WLAN_VENDOR_ATTR_INVALID = 0,
+	/* used by QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY */
+	QCA_WLAN_VENDOR_ATTR_DFS     = 1,
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_MAX	= QCA_WLAN_VENDOR_ATTR_AFTER_LAST - 1,
+};
+
 #endif /* QCA_VENDOR_H */
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 2eafc14..5935273 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -897,7 +897,8 @@
 #define WPA_DRIVER_FLAGS_DRIVER_IE	0x00000001
 /* Driver needs static WEP key setup after association command */
 #define WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC 0x00000002
-/* unused: 0x00000004 */
+/* Driver takes care of all DFS operations */
+#define WPA_DRIVER_FLAGS_DFS_OFFLOAD			0x00000004
 /* Driver takes care of RSN 4-way handshake internally; PMK is configured with
  * struct wpa_driver_ops::set_key using alg = WPA_ALG_PMK */
 #define WPA_DRIVER_FLAGS_4WAY_HANDSHAKE 0x00000008
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index dcd002e..c3449ac 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -303,6 +303,7 @@
 	unsigned int start_iface_up:1;
 	unsigned int test_use_roc_tx:1;
 	unsigned int ignore_deauth_event:1;
+	unsigned int dfs_vendor_cmd_avail:1;
 
 	u64 remain_on_chan_cookie;
 	u64 send_action_cookie;
@@ -3725,6 +3726,10 @@
 				continue;
 			}
 			vinfo = nla_data(nl);
+			if (vinfo->subcmd ==
+			    QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY)
+				drv->dfs_vendor_cmd_avail = 1;
+
 			wpa_printf(MSG_DEBUG, "nl80211: Supported vendor command: vendor_id=0x%x subcmd=%u",
 				   vinfo->vendor_id, vinfo->subcmd);
 		}
@@ -8889,11 +8894,44 @@
 }
 
 
+static int dfs_info_handler(struct nl_msg *msg, void *arg)
+{
+	struct nlattr *tb[NL80211_ATTR_MAX + 1];
+	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+	int *dfs_capability_ptr = arg;
+
+	nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+		  genlmsg_attrlen(gnlh, 0), NULL);
+
+	if (tb[NL80211_ATTR_VENDOR_DATA]) {
+		struct nlattr *nl_vend = tb[NL80211_ATTR_VENDOR_DATA];
+		struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_MAX + 1];
+
+		nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_MAX,
+			  nla_data(nl_vend), nla_len(nl_vend), NULL);
+
+		if (tb_vendor[QCA_WLAN_VENDOR_ATTR_DFS]) {
+			u32 val;
+			val = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_DFS]);
+			wpa_printf(MSG_DEBUG, "nl80211: DFS offload capability: %u",
+				   val);
+			*dfs_capability_ptr = val;
+		}
+	}
+
+	return NL_SKIP;
+}
+
+
 static int wpa_driver_nl80211_get_capa(void *priv,
 				       struct wpa_driver_capa *capa)
 {
 	struct i802_bss *bss = priv;
 	struct wpa_driver_nl80211_data *drv = bss->drv;
+	struct nl_msg *msg;
+	int dfs_capability = 0;
+	int ret = 0;
+
 	if (!drv->has_capability)
 		return -1;
 	os_memcpy(capa, &drv->capa, sizeof(*capa));
@@ -8909,7 +8947,31 @@
 		capa->flags &= ~WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE;
 	}
 
-	return 0;
+	if (drv->dfs_vendor_cmd_avail == 1) {
+		msg = nlmsg_alloc();
+		if (!msg)
+			return -ENOMEM;
+
+		nl80211_cmd(drv, msg, 0, NL80211_CMD_VENDOR);
+
+		NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+		NLA_PUT_U32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA);
+		NLA_PUT_U32(msg, NL80211_ATTR_VENDOR_SUBCMD,
+			    QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY);
+
+		ret = send_and_recv_msgs(drv, msg, dfs_info_handler,
+					 &dfs_capability);
+		if (!ret) {
+			if (dfs_capability)
+				capa->flags |= WPA_DRIVER_FLAGS_DFS_OFFLOAD;
+		}
+	}
+
+	return ret;
+
+ nla_put_failure:
+	nlmsg_free(msg);
+	return -ENOBUFS;
 }
 
 
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index c5bf41f..a1325d3 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -1208,10 +1208,25 @@
 		   0) {
 		p2p_dbg(p2p, "Select possible 5 GHz channel (op_class %u channel %u) as operating channel preference",
 			p2p->op_reg_class, p2p->op_channel);
-	} else {
+	} else if (p2p_channels_includes(&p2p->cfg->channels,
+					 p2p->cfg->op_reg_class,
+					 p2p->cfg->op_channel)) {
 		p2p_dbg(p2p, "Select pre-configured channel as operating channel preference");
 		p2p->op_reg_class = p2p->cfg->op_reg_class;
 		p2p->op_channel = p2p->cfg->op_channel;
+	} else if (p2p_channel_random_social(&p2p->cfg->channels,
+					     &p2p->op_reg_class,
+					     &p2p->op_channel) == 0) {
+		p2p_dbg(p2p, "Select random available social channel %d from 2.4 GHz band as operating channel preference",
+			p2p->op_channel);
+	} else {
+		/* Select any random available channel from the first available
+		 * operating class */
+		p2p_channel_select(&p2p->cfg->channels, NULL,
+				   &p2p->op_reg_class,
+				   &p2p->op_channel);
+		p2p_dbg(p2p, "Select random available channel %d from operating class %d as operating channel preference",
+			p2p->op_channel, p2p->op_reg_class);
 	}
 
 	os_memcpy(&p2p->channels, &p2p->cfg->channels,
diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h
index 420c739..8c225ec 100644
--- a/src/p2p/p2p_i.h
+++ b/src/p2p/p2p_i.h
@@ -592,6 +592,8 @@
 		       const struct p2p_channels *chan);
 int p2p_channel_select(struct p2p_channels *chans, const int *classes,
 		       u8 *op_class, u8 *op_channel);
+int p2p_channel_random_social(struct p2p_channels *chans, u8 *op_class,
+			      u8 *op_channel);
 
 /* p2p_parse.c */
 int p2p_parse_p2p_ie(const struct wpabuf *buf, struct p2p_message *msg);
diff --git a/src/p2p/p2p_utils.c b/src/p2p/p2p_utils.c
index 161a402..de47c12 100644
--- a/src/p2p/p2p_utils.c
+++ b/src/p2p/p2p_utils.c
@@ -441,31 +441,65 @@
 }
 
 
+static u8 p2p_channel_pick_random(const u8 *channels, unsigned int num_channels)
+{
+	unsigned int r;
+	os_get_random((u8 *) &r, sizeof(r));
+	r %= num_channels;
+	return channels[r];
+}
+
+
 int p2p_channel_select(struct p2p_channels *chans, const int *classes,
 		       u8 *op_class, u8 *op_channel)
 {
-	unsigned int i, j, r;
+	unsigned int i, j;
 
-	for (j = 0; classes[j]; j++) {
+	for (j = 0; classes == NULL || classes[j]; j++) {
 		for (i = 0; i < chans->reg_classes; i++) {
 			struct p2p_reg_class *c = &chans->reg_class[i];
 
 			if (c->channels == 0)
 				continue;
 
-			if (c->reg_class == classes[j]) {
+			if (classes == NULL || c->reg_class == classes[j]) {
 				/*
 				 * Pick one of the available channels in the
 				 * operating class at random.
 				 */
-				os_get_random((u8 *) &r, sizeof(r));
-				r %= c->channels;
 				*op_class = c->reg_class;
-				*op_channel = c->channel[r];
+				*op_channel = p2p_channel_pick_random(
+					c->channel, c->channels);
 				return 0;
 			}
 		}
+		if (classes == NULL)
+			break;
 	}
 
 	return -1;
 }
+
+
+int p2p_channel_random_social(struct p2p_channels *chans, u8 *op_class,
+			      u8 *op_channel)
+{
+	u8 chan[3];
+	unsigned int num_channels = 0;
+
+	/* Try to find available social channels from 2.4 GHz */
+	if (p2p_channels_includes(chans, 81, 1))
+		chan[num_channels++] = 1;
+	if (p2p_channels_includes(chans, 81, 6))
+		chan[num_channels++] = 6;
+	if (p2p_channels_includes(chans, 81, 11))
+		chan[num_channels++] = 11;
+
+	if (num_channels == 0)
+		return -1;
+
+	*op_class = 81;
+	*op_channel = p2p_channel_pick_random(chan, num_channels);
+
+	return 0;
+}
diff --git a/wpa_supplicant/android.config b/wpa_supplicant/android.config
index 184b41e..7c80528 100644
--- a/wpa_supplicant/android.config
+++ b/wpa_supplicant/android.config
@@ -123,7 +123,7 @@
 
 # EAP-AKA' (enable CONFIG_PCSC, if EAP-AKA' is used).
 # This requires CONFIG_EAP_AKA to be enabled, too.
-#CONFIG_EAP_AKA_PRIME=y
+CONFIG_EAP_AKA_PRIME=y
 
 # Enable USIM simulator (Milenage) for EAP-AKA
 #CONFIG_USIM_SIMULATOR=y
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 87ed3e2..704caa1 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -46,6 +46,8 @@
 					    char *buf, int len);
 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
 						  char *buf, int len);
+static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s,
+					char *val);
 
 static int set_bssid_filter(struct wpa_supplicant *wpa_s, char *val)
 {
@@ -245,6 +247,33 @@
 }
 #endif /* CONFIG_NO_CONFIG_BLOBS */
 
+
+static int wpas_ctrl_pno(struct wpa_supplicant *wpa_s, char *cmd)
+{
+	char *params;
+	char *pos;
+	int *freqs = NULL;
+	int ret;
+
+	if (atoi(cmd)) {
+		params = os_strchr(cmd, ' ');
+		os_free(wpa_s->manual_sched_scan_freqs);
+		if (params) {
+			params++;
+			pos = os_strstr(params, "freq=");
+			if (pos)
+				freqs = freq_range_to_channel_list(wpa_s,
+								   pos + 5);
+		}
+		wpa_s->manual_sched_scan_freqs = freqs;
+		ret = wpas_start_pno(wpa_s);
+	} else {
+		ret = wpas_stop_pno(wpa_s);
+	}
+	return ret;
+}
+
+
 static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
 					 char *cmd)
 {
@@ -328,10 +357,7 @@
 		wpa_tdls_enable(wpa_s->wpa, !disabled);
 #endif /* CONFIG_TDLS */
 	} else if (os_strcasecmp(cmd, "pno") == 0) {
-		if (atoi(value))
-			ret = wpas_start_pno(wpa_s);
-		else
-			ret = wpas_stop_pno(wpa_s);
+		ret = wpas_ctrl_pno(wpa_s, value);
 	} else if (os_strcasecmp(cmd, "radio_disabled") == 0) {
 		int disabled = atoi(value);
 		if (wpa_drv_radio_disable(wpa_s, disabled) < 0)
diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c
index 5e02956..a0653f0 100644
--- a/wpa_supplicant/dbus/dbus_new.c
+++ b/wpa_supplicant/dbus/dbus_new.c
@@ -2649,6 +2649,7 @@
 	  (WPADBusMethodHandler)wpas_dbus_handler_p2p_service_sd_req,
 	  {
 		  { "args", "a{sv}", ARG_IN },
+		  { "ref", "t", ARG_OUT },
 		  END_ARGS
 	  }
 	},
@@ -2679,13 +2680,6 @@
 		  END_ARGS
 	  }
 	},
-	{ "ServiceDiscoveryExternal", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
-	  (WPADBusMethodHandler)wpas_dbus_handler_p2p_serv_disc_external,
-	  {
-		  { "arg", "i", ARG_IN },
-		  END_ARGS
-	  }
-	},
 	{ "AddPersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
 	  (WPADBusMethodHandler) wpas_dbus_handler_add_persistent_group,
 	  {
@@ -3280,6 +3274,10 @@
 	  wpas_dbus_getter_p2p_peer_ies,
 	  NULL
 	},
+	{ "DeviceAddress", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
+	  wpas_dbus_getter_p2p_peer_device_address,
+	  NULL
+	},
 	{ NULL, NULL, NULL, NULL, NULL }
 };
 
diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
index 2b83637..7857bfd 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
@@ -825,6 +825,11 @@
 					 wpa_s->conf->disassoc_low_ack))
 		goto err_no_mem;
 
+	/* No Group Iface */
+	if (!wpa_dbus_dict_append_bool(&dict_iter, "NoGroupIface",
+				       wpa_s->conf->p2p_no_group_iface))
+		goto err_no_mem;
+
 	if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
 	    !dbus_message_iter_close_container(iter, &variant_iter))
 		goto err_no_mem;
@@ -974,6 +979,9 @@
 		else if (os_strcmp(entry.key, "disassoc_low_ack") == 0 &&
 			 entry.type == DBUS_TYPE_UINT32)
 			wpa_s->conf->disassoc_low_ack = entry.uint32_value;
+		else if (os_strcmp(entry.key, "NoGroupIface") == 0 &&
+			 entry.type == DBUS_TYPE_BOOLEAN)
+			wpa_s->conf->p2p_no_group_iface = entry.bool_value;
 		else
 			goto error;
 
@@ -1470,12 +1478,46 @@
 dbus_bool_t wpas_dbus_getter_p2p_peer_ies(DBusMessageIter *iter,
 					  DBusError *error, void *user_data)
 {
-	dbus_bool_t success;
-	/* struct peer_handler_args *peer_args = user_data; */
+	struct peer_handler_args *peer_args = user_data;
+	const struct p2p_peer_info *info;
 
-	success = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
-							 NULL, 0, error);
-	return success;
+	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
+				  peer_args->p2p_device_addr, 0);
+	if (info == NULL) {
+		dbus_set_error(error, DBUS_ERROR_FAILED,
+			       "failed to find peer");
+		return FALSE;
+	}
+
+	if (info->wfd_subelems == NULL)
+		return wpas_dbus_simple_array_property_getter(iter,
+							      DBUS_TYPE_BYTE,
+							      NULL, 0, error);
+
+	return wpas_dbus_simple_array_property_getter(
+		iter, DBUS_TYPE_BYTE, (char *) info->wfd_subelems->buf,
+		info->wfd_subelems->used, error);
+}
+
+
+dbus_bool_t wpas_dbus_getter_p2p_peer_device_address(DBusMessageIter *iter,
+						     DBusError *error,
+						     void *user_data)
+{
+	struct peer_handler_args *peer_args = user_data;
+	const struct p2p_peer_info *info;
+
+	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
+				  peer_args->p2p_device_addr, 0);
+	if (info == NULL) {
+		dbus_set_error(error, DBUS_ERROR_FAILED,
+			       "failed to find peer");
+		return FALSE;
+	}
+
+	return wpas_dbus_simple_array_property_getter(
+		iter, DBUS_TYPE_BYTE, (char *) peer_args->p2p_device_addr,
+		ETH_ALEN, error);
 }
 
 
@@ -2407,7 +2449,7 @@
 	if (req == 0)
 		goto error;
 
-	if (!wpas_p2p_sd_cancel_request(wpa_s, req))
+	if (wpas_p2p_sd_cancel_request(wpa_s, req) < 0)
 		goto error;
 
 	return NULL;
diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.h b/wpa_supplicant/dbus/dbus_new_handlers_p2p.h
index a11b3c8..67e0e9d 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.h
+++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.h
@@ -147,6 +147,10 @@
 					  DBusError *error,
 					  void *user_data);
 
+dbus_bool_t wpas_dbus_getter_p2p_peer_device_address(DBusMessageIter *iter,
+						     DBusError *error,
+						     void *user_data);
+
 /*
  * P2P Group properties
  */
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index b336afb..bbcd662 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -206,6 +206,14 @@
 	return NULL;
 }
 
+static inline const char *
+wpa_driver_get_radio_name(struct wpa_supplicant *wpa_s)
+{
+	if (wpa_s->driver->get_radio_name)
+		return wpa_s->driver->get_radio_name(wpa_s->drv_priv);
+	return NULL;
+}
+
 static inline const u8 * wpa_drv_get_mac_addr(struct wpa_supplicant *wpa_s)
 {
 	if (wpa_s->driver->get_mac_addr) {
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 487d44d..6f9f217 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -1622,6 +1622,9 @@
 			wpas_p2p_init_group_interface(wpa_s, res->role_go);
 		if (group_wpa_s == NULL) {
 			wpas_p2p_remove_pending_group_interface(wpa_s);
+			eloop_cancel_timeout(wpas_p2p_long_listen_timeout,
+					     wpa_s, NULL);
+			wpas_p2p_group_formation_failed(wpa_s);
 			return;
 		}
 		if (group_wpa_s != wpa_s) {
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index 1d8e8a6..48e94b6 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -1923,6 +1923,11 @@
 	interval = wpa_s->conf->sched_scan_interval ?
 		wpa_s->conf->sched_scan_interval : 10;
 
+	if (params.freqs == NULL && wpa_s->manual_sched_scan_freqs) {
+		wpa_dbg(wpa_s, MSG_DEBUG, "Limit sched scan to specified channels");
+		params.freqs = wpa_s->manual_sched_scan_freqs;
+	}
+
 	ret = wpa_supplicant_start_sched_scan(wpa_s, &params, interval);
 	os_free(params.filter_ssids);
 	if (ret == 0)
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index 63beaef..f01844e 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -968,8 +968,11 @@
 	struct ieee80211_2040_intol_chan_report *ic_report;
 	struct wpabuf *buf;
 
-	wpa_printf(MSG_DEBUG, "SME: Send 20/40 BSS Coexistence to " MACSTR,
-		   MAC2STR(wpa_s->bssid));
+	wpa_printf(MSG_DEBUG, "SME: Send 20/40 BSS Coexistence to " MACSTR
+		   " (num_channels=%u num_intol=%u)",
+		   MAC2STR(wpa_s->bssid), num_channels, num_intol);
+	wpa_hexdump(MSG_DEBUG, "SME: 20/40 BSS Intolerant Channels",
+		    chan_list, num_channels);
 
 	buf = wpabuf_alloc(2 + /* action.category + action_code */
 			   sizeof(struct ieee80211_2040_bss_coex_ie) +
@@ -1051,8 +1054,14 @@
 
 		ie = wpa_bss_get_ie(bss, WLAN_EID_HT_CAP);
 		ht_cap = (ie && (ie[1] == 26)) ? WPA_GET_LE16(ie + 2) : 0;
+		wpa_printf(MSG_DEBUG, "SME OBSS scan BSS " MACSTR
+			   " freq=%u chan=%u ht_cap=0x%x",
+			   MAC2STR(bss->bssid), bss->freq, channel, ht_cap);
 
 		if (!ht_cap || (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT)) {
+			if (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT)
+				num_intol++;
+
 			/* Check whether the channel is already considered */
 			for (i = 0; i < num_channels; i++) {
 				if (channel == chan_list[i])
@@ -1061,9 +1070,6 @@
 			if (i != num_channels)
 				continue;
 
-			if (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT)
-				num_intol++;
-
 			chan_list[num_channels++] = channel;
 		}
 	}
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 499dcb3..dce1c00 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -460,6 +460,9 @@
 	os_free(wpa_s->manual_scan_freqs);
 	wpa_s->manual_scan_freqs = NULL;
 
+	os_free(wpa_s->manual_sched_scan_freqs);
+	wpa_s->manual_sched_scan_freqs = NULL;
+
 	gas_query_deinit(wpa_s->gas);
 	wpa_s->gas = NULL;
 
@@ -3204,15 +3207,13 @@
 	wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
 		   wpa_s->ifname, radio->name);
 	dl_list_del(&wpa_s->radio_list);
-	if (!dl_list_empty(&radio->ifaces)) {
-		wpa_s->radio = NULL;
+	radio_remove_works(wpa_s, NULL, 0);
+	wpa_s->radio = NULL;
+	if (!dl_list_empty(&radio->ifaces))
 		return; /* Interfaces remain for this radio */
-	}
 
 	wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
-	radio_remove_works(wpa_s, NULL, 0);
 	eloop_cancel_timeout(radio_start_next_work, radio, NULL);
-	wpa_s->radio = NULL;
 	os_free(radio);
 }
 
@@ -3361,10 +3362,7 @@
 		os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
 	}
 
-	if (wpa_s->driver->get_radio_name)
-		rn = wpa_s->driver->get_radio_name(wpa_s->drv_priv);
-	else
-		rn = NULL;
+	rn = wpa_driver_get_radio_name(wpa_s);
 	if (rn && rn[0] == '\0')
 		rn = NULL;
 
@@ -4534,7 +4532,7 @@
 	}
 
 	/* If get_radio_name is not supported, use only the local freq */
-	if (!wpa_s->driver->get_radio_name) {
+	if (!wpa_driver_get_radio_name(wpa_s)) {
 		freq = wpa_drv_shared_freq(wpa_s);
 		if (freq > 0 && idx < len &&
 		    (idx == 0 || freq_array[0] != freq))
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 739b11f..8a33286 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -547,6 +547,7 @@
 	int scan_runs; /* number of scan runs since WPS was started */
 	int *next_scan_freqs;
 	int *manual_scan_freqs;
+	int *manual_sched_scan_freqs;
 	unsigned int manual_scan_passive:1;
 	unsigned int manual_scan_use_id:1;
 	unsigned int manual_scan_only_new:1;