Cumulative patch from commit d3b204694a39e6c57a4c6689b87f4192e1b93a06

d3b2046 P2P: Make the default p2p_find delay value configurable
3dacd3e atheros: Add support for new GCMP/CCMP/CMAC/GMAC cipher suites
737754d EAP-IKEv2: Remove obsolete ccns.pl project workarounds
aa6bf6d eap_proxy: Check sm != NULL more consistently
4f4d51e TDLS: Add extra validation step for responder RSN IE length
a01acc5 Check for EVENT_ASSOC data to be present for AP mode operation
1fde15a GAS server: Explicitly check that home realm is available
aff0bee GAS server: Remove unused function parameter
86388af WPS: Check for theoretical gmtime() failure
d75a5ae WPS ER: Fix UDN parser to handle missing field
0bbaa9b Validate driver extended capabilities length against buffer length
9c6c558 Interworking: Reject EAP configuration with unsupported inner method
f2ca0e9 Check eap_get_name() return against NULL to silence static analyzer
bc32bb7 Make a code path easier for static analyzers to understand
fb958ea Check current_ssid on unexpected association event
2a57c33 Reserve QCA vendor specific nl80211 commands 20..33
84df167 nl80211: Add vendor attribute for interface index
9949483 The master branch is now used for v2.3 development

Change-Id: Ib39c204aaa3ebcc909057f815e5e291e15e5df88
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index 2a4acf2..73dffe2 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -220,7 +220,7 @@
 			continue; /* can use same entry */
 		}
 
-		if (start) {
+		if (start && prev) {
 			pos = hostapd_eid_country_add(pos, end, chan_spacing,
 						      start, prev);
 			start = NULL;
diff --git a/src/ap/gas_serv.c b/src/ap/gas_serv.c
index b406880..52d1b24 100644
--- a/src/ap/gas_serv.c
+++ b/src/ap/gas_serv.c
@@ -414,7 +414,7 @@
 			gas_anqp_set_element_len(buf, realm_data_len);
 		}
 		gas_anqp_set_element_len(buf, len);
-	} else if (nai_home_realm && hapd->conf->nai_realm_data) {
+	} else if (nai_home_realm && hapd->conf->nai_realm_data && home_realm) {
 		hs20_add_nai_home_realm_matches(hapd, buf, home_realm,
 						home_realm_len);
 	}
@@ -686,7 +686,6 @@
 static struct wpabuf *
 gas_serv_build_gas_resp_payload(struct hostapd_data *hapd,
 				unsigned int request,
-				struct gas_dialog_info *di,
 				const u8 *home_realm, size_t home_realm_len,
 				const u8 *icon_name, size_t icon_name_len)
 {
@@ -962,7 +961,7 @@
 {
 	struct wpabuf *buf, *tx_buf;
 
-	buf = gas_serv_build_gas_resp_payload(hapd, qi->request, NULL,
+	buf = gas_serv_build_gas_resp_payload(hapd, qi->request,
 					      qi->home_realm_query,
 					      qi->home_realm_query_len,
 					      qi->icon_name, qi->icon_name_len);
diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h
index a56b188..4d9efd5 100644
--- a/src/common/qca-vendor.h
+++ b/src/common/qca-vendor.h
@@ -52,7 +52,7 @@
 	QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY =  11,
 	QCA_NL80211_VENDOR_SUBCMD_NAN =  12,
 	QCA_NL80211_VENDOR_SUBMCD_STATS_EXT = 13,
-	/* 14..19 - reserved for QCA */
+	/* 14..33 - reserved for QCA */
 };
 
 
@@ -64,6 +64,8 @@
 	QCA_WLAN_VENDOR_ATTR_NAN     = 2,
 	/* used by QCA_NL80211_VENDOR_SUBCMD_STATS_EXT */
 	QCA_WLAN_VENDOR_ATTR_STATS_EXT     = 3,
+	/* used by QCA_NL80211_VENDOR_SUBCMD_STATS_EXT */
+	QCA_WLAN_VENDOR_ATTR_IFINDEX     = 4,
 	/* keep last */
 	QCA_WLAN_VENDOR_ATTR_AFTER_LAST,
 	QCA_WLAN_VENDOR_ATTR_MAX	= QCA_WLAN_VENDOR_ATTR_AFTER_LAST - 1,
diff --git a/src/common/version.h b/src/common/version.h
index 340afc7..1f25432 100644
--- a/src/common/version.h
+++ b/src/common/version.h
@@ -5,6 +5,6 @@
 #define VERSION_STR_POSTFIX ""
 #endif /* VERSION_STR_POSTFIX */
 
-#define VERSION_STR "2.2" VERSION_STR_POSTFIX
+#define VERSION_STR "2.3-devel" VERSION_STR_POSTFIX
 
 #endif /* VERSION_H */
diff --git a/src/drivers/driver_atheros.c b/src/drivers/driver_atheros.c
index c146cdc..b569a0a 100644
--- a/src/drivers/driver_atheros.c
+++ b/src/drivers/driver_atheros.c
@@ -260,6 +260,17 @@
 	case WPA_CIPHER_CCMP:
 		v = IEEE80211_CIPHER_AES_CCM;
 		break;
+#ifdef ATH_GCM_SUPPORT
+	case WPA_CIPHER_CCMP_256:
+		v = IEEE80211_CIPHER_AES_CCM_256;
+		break;
+	case WPA_CIPHER_GCMP:
+		v = IEEE80211_CIPHER_AES_GCM;
+		break;
+	case WPA_CIPHER_GCMP_256:
+		v = IEEE80211_CIPHER_AES_GCM_256;
+		break;
+#endif /* ATH_GCM_SUPPORT */
 	case WPA_CIPHER_TKIP:
 		v = IEEE80211_CIPHER_TKIP;
 		break;
@@ -294,6 +305,14 @@
 	v = 0;
 	if (params->wpa_pairwise & WPA_CIPHER_CCMP)
 		v |= 1<<IEEE80211_CIPHER_AES_CCM;
+#ifdef ATH_GCM_SUPPORT
+	if (params->wpa_pairwise & WPA_CIPHER_CCMP_256)
+		v |= 1<<IEEE80211_CIPHER_AES_CCM_256;
+	if (params->wpa_pairwise & WPA_CIPHER_GCMP)
+		v |= 1<<IEEE80211_CIPHER_AES_GCM;
+	if (params->wpa_pairwise & WPA_CIPHER_GCMP_256)
+		v |= 1<<IEEE80211_CIPHER_AES_GCM_256;
+#endif /* ATH_GCM_SUPPORT */
 	if (params->wpa_pairwise & WPA_CIPHER_TKIP)
 		v |= 1<<IEEE80211_CIPHER_TKIP;
 	if (params->wpa_pairwise & WPA_CIPHER_NONE)
@@ -471,10 +490,32 @@
 	case WPA_ALG_CCMP:
 		cipher = IEEE80211_CIPHER_AES_CCM;
 		break;
+#ifdef ATH_GCM_SUPPORT
+	case WPA_ALG_CCMP_256:
+		cipher = IEEE80211_CIPHER_AES_CCM_256;
+		break;
+	case WPA_ALG_GCMP:
+		cipher = IEEE80211_CIPHER_AES_GCM;
+		break;
+	case WPA_ALG_GCMP_256:
+		cipher = IEEE80211_CIPHER_AES_GCM_256;
+		break;
+#endif /* ATH_GCM_SUPPORT */
 #ifdef CONFIG_IEEE80211W
 	case WPA_ALG_IGTK:
 		cipher = IEEE80211_CIPHER_AES_CMAC;
 		break;
+#ifdef ATH_GCM_SUPPORT
+	case WPA_ALG_BIP_CMAC_256:
+		cipher = IEEE80211_CIPHER_AES_CMAC_256;
+		break;
+	case WPA_ALG_BIP_GMAC_128:
+		cipher = IEEE80211_CIPHER_AES_GMAC;
+		break;
+	case WPA_ALG_BIP_GMAC_256:
+		cipher = IEEE80211_CIPHER_AES_GMAC_256;
+		break;
+#endif /* ATH_GCM_SUPPORT */
 #endif /* CONFIG_IEEE80211W */
 	default:
 		printf("%s: unknown/unsupported algorithm %d\n",
diff --git a/src/drivers/drivers.mak b/src/drivers/drivers.mak
index 7e175f4..40aaba5 100644
--- a/src/drivers/drivers.mak
+++ b/src/drivers/drivers.mak
@@ -105,6 +105,9 @@
 CONFIG_L2_PACKET=linux
 NEED_NETLINK=y
 NEED_LINUX_IOCTL=y
+ifdef ATH_GCM_SUPPORT
+CFLAGS += -DATH_GCM_SUPPORT
+endif
 endif
 
 ##### PURE CLIENT DRIVERS
diff --git a/src/eap_common/eap_ikev2_common.c b/src/eap_common/eap_ikev2_common.c
index 6095fd8..da9f3cc 100644
--- a/src/eap_common/eap_ikev2_common.c
+++ b/src/eap_common/eap_ikev2_common.c
@@ -52,22 +52,12 @@
 {
 	struct wpabuf *msg;
 
-#ifdef CCNS_PL
-	msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, 1, code, id);
-	if (msg == NULL) {
-		wpa_printf(MSG_ERROR, "EAP-IKEV2: Failed to allocate memory "
-			   "for fragment ack");
-		return NULL;
-	}
-	wpabuf_put_u8(msg, 0); /* Flags */
-#else /* CCNS_PL */
 	msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, 0, code, id);
 	if (msg == NULL) {
 		wpa_printf(MSG_ERROR, "EAP-IKEV2: Failed to allocate memory "
 			   "for fragment ack");
 		return NULL;
 	}
-#endif /* CCNS_PL */
 
 	wpa_printf(MSG_DEBUG, "EAP-IKEV2: Send fragment ack");
 
diff --git a/src/eap_common/eap_ikev2_common.h b/src/eap_common/eap_ikev2_common.h
index 329ccc4..e7502d7 100644
--- a/src/eap_common/eap_ikev2_common.h
+++ b/src/eap_common/eap_ikev2_common.h
@@ -9,16 +9,9 @@
 #ifndef EAP_IKEV2_COMMON_H
 #define EAP_IKEV2_COMMON_H
 
-#ifdef CCNS_PL
-/* incorrect bit order */
-#define IKEV2_FLAGS_LENGTH_INCLUDED 0x01
-#define IKEV2_FLAGS_MORE_FRAGMENTS 0x02
-#define IKEV2_FLAGS_ICV_INCLUDED 0x04
-#else /* CCNS_PL */
 #define IKEV2_FLAGS_LENGTH_INCLUDED 0x80
 #define IKEV2_FLAGS_MORE_FRAGMENTS 0x40
 #define IKEV2_FLAGS_ICV_INCLUDED 0x20
-#endif /* CCNS_PL */
 
 #define IKEV2_FRAGMENT_SIZE 1400
 
diff --git a/src/eap_common/ikev2_common.c b/src/eap_common/ikev2_common.c
index f061866..b98a3e8 100644
--- a/src/eap_common/ikev2_common.c
+++ b/src/eap_common/ikev2_common.c
@@ -173,46 +173,12 @@
 }
 
 
-#ifdef CCNS_PL
-/* from des.c */
-struct des3_key_s {
-	u32 ek[3][32];
-	u32 dk[3][32];
-};
-
-void des3_key_setup(const u8 *key, struct des3_key_s *dkey);
-void des3_encrypt(const u8 *plain, const struct des3_key_s *key, u8 *crypt);
-void des3_decrypt(const u8 *crypt, const struct des3_key_s *key, u8 *plain);
-#endif /* CCNS_PL */
-
-
 int ikev2_encr_encrypt(int alg, const u8 *key, size_t key_len, const u8 *iv,
 		       const u8 *plain, u8 *crypt, size_t len)
 {
 	struct crypto_cipher *cipher;
 	int encr_alg;
 
-#ifdef CCNS_PL
-	if (alg == ENCR_3DES) {
-		struct des3_key_s des3key;
-		size_t i, blocks;
-		u8 *pos;
-
-		/* ECB mode is used incorrectly for 3DES!? */
-		if (key_len != 24) {
-			wpa_printf(MSG_INFO, "IKEV2: Invalid encr key length");
-			return -1;
-		}
-		des3_key_setup(key, &des3key);
-
-		blocks = len / 8;
-		pos = crypt;
-		for (i = 0; i < blocks; i++) {
-			des3_encrypt(pos, &des3key, pos);
-			pos += 8;
-		}
-	} else {
-#endif /* CCNS_PL */
 	switch (alg) {
 	case ENCR_3DES:
 		encr_alg = CRYPTO_CIPHER_ALG_3DES;
@@ -237,9 +203,6 @@
 		return -1;
 	}
 	crypto_cipher_deinit(cipher);
-#ifdef CCNS_PL
-	}
-#endif /* CCNS_PL */
 
 	return 0;
 }
@@ -251,31 +214,6 @@
 	struct crypto_cipher *cipher;
 	int encr_alg;
 
-#ifdef CCNS_PL
-	if (alg == ENCR_3DES) {
-		struct des3_key_s des3key;
-		size_t i, blocks;
-
-		/* ECB mode is used incorrectly for 3DES!? */
-		if (key_len != 24) {
-			wpa_printf(MSG_INFO, "IKEV2: Invalid encr key length");
-			return -1;
-		}
-		des3_key_setup(key, &des3key);
-
-		if (len % 8) {
-			wpa_printf(MSG_INFO, "IKEV2: Invalid encrypted "
-				   "length");
-			return -1;
-		}
-		blocks = len / 8;
-		for (i = 0; i < blocks; i++) {
-			des3_decrypt(crypt, &des3key, plain);
-			plain += 8;
-			crypt += 8;
-		}
-	} else {
-#endif /* CCNS_PL */
 	switch (alg) {
 	case ENCR_3DES:
 		encr_alg = CRYPTO_CIPHER_ALG_3DES;
@@ -300,9 +238,6 @@
 		return -1;
 	}
 	crypto_cipher_deinit(cipher);
-#ifdef CCNS_PL
-	}
-#endif /* CCNS_PL */
 
 	return 0;
 }
@@ -706,10 +641,6 @@
 	keys->SK_integ_len = integ->key_len;
 	keys->SK_encr_len = encr->key_len;
 	keys->SK_prf_len = prf->key_len;
-#ifdef CCNS_PL
-	/* Uses encryption key length for SK_d; should be PRF length */
-	keys->SK_d_len = keys->SK_encr_len;
-#endif /* CCNS_PL */
 
 	keybuf_len = keys->SK_d_len + 2 * keys->SK_integ_len +
 		2 * keys->SK_encr_len + 2 * keys->SK_prf_len;
diff --git a/src/eap_common/ikev2_common.h b/src/eap_common/ikev2_common.h
index 45c970b..8a7982a 100644
--- a/src/eap_common/ikev2_common.h
+++ b/src/eap_common/ikev2_common.h
@@ -70,11 +70,7 @@
 /* Current IKEv2 version from RFC 4306 */
 #define IKEV2_MjVer 2
 #define IKEV2_MnVer 0
-#ifdef CCNS_PL
-#define IKEV2_VERSION ((IKEV2_MjVer) | ((IKEV2_MnVer) << 4))
-#else /* CCNS_PL */
 #define IKEV2_VERSION (((IKEV2_MjVer) << 4) | (IKEV2_MnVer))
-#endif /* CCNS_PL */
 
 /* IKEv2 Exchange Types */
 enum {
diff --git a/src/eap_peer/eap_ikev2.c b/src/eap_peer/eap_ikev2.c
index 45945fe..568a448 100644
--- a/src/eap_peer/eap_ikev2.c
+++ b/src/eap_peer/eap_ikev2.c
@@ -154,12 +154,6 @@
 			send_len -= 4;
 		}
 	}
-#ifdef CCNS_PL
-	/* Some issues figuring out the length of the message if Message Length
-	 * field not included?! */
-	if (!(flags & IKEV2_FLAGS_LENGTH_INCLUDED))
-		flags |= IKEV2_FLAGS_LENGTH_INCLUDED;
-#endif /* CCNS_PL */
 
 	plen = 1 + send_len;
 	if (flags & IKEV2_FLAGS_LENGTH_INCLUDED)
@@ -381,12 +375,7 @@
 		   "Message Length %u", flags, message_length);
 
 	if (data->state == WAIT_FRAG_ACK) {
-#ifdef CCNS_PL
-		if (len > 1) /* Empty Flags field included in ACK */
-#else /* CCNS_PL */
-		if (len != 0)
-#endif /* CCNS_PL */
-		{
+		if (len != 0) {
 			wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unexpected payload "
 				   "in WAIT_FRAG_ACK state");
 			ret->ignore = TRUE;
diff --git a/src/eap_peer/ikev2.c b/src/eap_peer/ikev2.c
index 1ccc352..fb2f619 100644
--- a/src/eap_peer/ikev2.c
+++ b/src/eap_peer/ikev2.c
@@ -72,27 +72,10 @@
 	os_memcpy(pos, data->i_spi, IKEV2_SPI_LEN);
 	pos += IKEV2_SPI_LEN;
 	os_memcpy(pos, data->r_spi, IKEV2_SPI_LEN);
-#ifdef CCNS_PL
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-	{
-		int i;
-		u8 *tmp = pos - IKEV2_SPI_LEN;
-		/* Incorrect byte re-ordering on little endian hosts.. */
-		for (i = 0; i < IKEV2_SPI_LEN; i++)
-			*tmp++ = data->i_spi[IKEV2_SPI_LEN - 1 - i];
-		for (i = 0; i < IKEV2_SPI_LEN; i++)
-			*tmp++ = data->r_spi[IKEV2_SPI_LEN - 1 - i];
-	}
-#endif
-#endif /* CCNS_PL */
 
 	/* SKEYSEED = prf(Ni | Nr, g^ir) */
 	/* Use zero-padding per RFC 4306, Sect. 2.14 */
 	pad_len = data->dh->prime_len - wpabuf_len(shared);
-#ifdef CCNS_PL
-	/* Shared secret is not zero-padded correctly */
-	pad_len = 0;
-#endif /* CCNS_PL */
 	pad = os_zalloc(pad_len ? pad_len : 1);
 	if (pad == NULL) {
 		wpabuf_free(shared);
@@ -179,21 +162,12 @@
 						   "Transform Attr for AES");
 					break;
 				}
-#ifdef CCNS_PL
-				if (WPA_GET_BE16(pos) != 0x001d /* ?? */) {
-					wpa_printf(MSG_DEBUG, "IKEV2: Not a "
-						   "Key Size attribute for "
-						   "AES");
-					break;
-				}
-#else /* CCNS_PL */
 				if (WPA_GET_BE16(pos) != 0x800e) {
 					wpa_printf(MSG_DEBUG, "IKEV2: Not a "
 						   "Key Size attribute for "
 						   "AES");
 					break;
 				}
-#endif /* CCNS_PL */
 				if (WPA_GET_BE16(pos + 2) != 128) {
 					wpa_printf(MSG_DEBUG, "IKEV2: "
 						   "Unsupported AES key size "
@@ -456,14 +430,6 @@
 		return -1;
 	}
 
-#ifdef CCNS_PL
-	/* Zeros are removed incorrectly from the beginning of the nonces */
-	while (ni_len > 1 && *ni == 0) {
-		ni_len--;
-		ni++;
-	}
-#endif /* CCNS_PL */
-
 	data->i_nonce_len = ni_len;
 	os_memcpy(data->i_nonce, ni, ni_len);
 	wpa_hexdump(MSG_MSGDUMP, "IKEV2: Ni",
@@ -887,16 +853,7 @@
 	phdr->flags = 0;
 
 	p = wpabuf_put(msg, sizeof(*p));
-#ifdef CCNS_PL
-	/* Seems to require that the Proposal # is 1 even though RFC 4306
-	 * Sect 3.3.1 has following requirement "When a proposal is accepted,
-	 * all of the proposal numbers in the SA payload MUST be the same and
-	 * MUST match the number on the proposal sent that was accepted.".
-	 */
-	p->proposal_num = 1;
-#else /* CCNS_PL */
 	p->proposal_num = data->proposal.proposal_num;
-#endif /* CCNS_PL */
 	p->protocol_id = IKEV2_PROTOCOL_IKE;
 	p->num_transforms = 4;
 
@@ -906,11 +863,7 @@
 	WPA_PUT_BE16(t->transform_id, data->proposal.encr);
 	if (data->proposal.encr == ENCR_AES_CBC) {
 		/* Transform Attribute: Key Len = 128 bits */
-#ifdef CCNS_PL
-		wpabuf_put_be16(msg, 0x001d); /* ?? */
-#else /* CCNS_PL */
 		wpabuf_put_be16(msg, 0x800e); /* AF=1, AttrType=14 */
-#endif /* CCNS_PL */
 		wpabuf_put_be16(msg, 128); /* 128-bit key */
 	}
 	plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) t;
@@ -1082,11 +1035,7 @@
 	phdr = wpabuf_put(msg, sizeof(*phdr));
 	phdr->next_payload = next_payload;
 	phdr->flags = 0;
-#ifdef CCNS_PL
-	wpabuf_put_u8(msg, 1); /* Protocol ID: IKE_SA notification */
-#else /* CCNS_PL */
 	wpabuf_put_u8(msg, 0); /* Protocol ID: no existing SA */
-#endif /* CCNS_PL */
 	wpabuf_put_u8(msg, 0); /* SPI Size */
 	wpabuf_put_be16(msg, data->error_type);
 
@@ -1130,13 +1079,6 @@
 	data->r_nonce_len = IKEV2_NONCE_MIN_LEN;
 	if (random_get_bytes(data->r_nonce, data->r_nonce_len))
 		return NULL;
-#ifdef CCNS_PL
-	/* Zeros are removed incorrectly from the beginning of the nonces in
-	 * key derivation; as a workaround, make sure Nr does not start with
-	 * zero.. */
-	if (data->r_nonce[0] == 0)
-		data->r_nonce[0] = 1;
-#endif /* CCNS_PL */
 	wpa_hexdump(MSG_DEBUG, "IKEV2: Nr", data->r_nonce, data->r_nonce_len);
 
 	msg = wpabuf_alloc(sizeof(struct ikev2_hdr) + data->IDr_len + 1500);
diff --git a/src/eapol_supp/eapol_supp_sm.c b/src/eapol_supp/eapol_supp_sm.c
index 1004b1a..e00dea3 100644
--- a/src/eapol_supp/eapol_supp_sm.c
+++ b/src/eapol_supp/eapol_supp_sm.c
@@ -1523,7 +1523,7 @@
 	size_t eap_len;
 
 #ifdef CONFIG_EAP_PROXY
-	if (sm->use_eap_proxy) {
+	if (sm && sm->use_eap_proxy) {
 		/* Get key from EAP proxy */
 		if (sm == NULL || !eap_proxy_key_available(sm->eap_proxy)) {
 			wpa_printf(MSG_DEBUG, "EAPOL: EAP key not available");
diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c
index 3b14656..84b7c1b 100644
--- a/src/rsn_supp/tdls.c
+++ b/src/rsn_supp/tdls.c
@@ -2098,6 +2098,13 @@
 	wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Received from TPK M2",
 		    kde.rsn_ie, kde.rsn_ie_len);
 
+	if (kde.rsn_ie_len > TDLS_MAX_IE_LEN) {
+		wpa_printf(MSG_INFO,
+			   "TDLS: Too long Responder RSN IE in TPK M2");
+		status = WLAN_STATUS_INVALID_RSNIE;
+		goto error;
+	}
+
 	/*
 	 * FIX: bitwise comparison of RSN IE is not the correct way of
 	 * validation this. It can be different, but certain fields must
diff --git a/src/wps/wps_er.c b/src/wps/wps_er.c
index 8b2675e..078ff72 100644
--- a/src/wps/wps_er.c
+++ b/src/wps/wps_er.c
@@ -579,12 +579,15 @@
 	wpa_printf(MSG_DEBUG, "WPS ER: serialNumber='%s'", ap->serial_number);
 
 	ap->udn = xml_get_first_item(data, "UDN");
-	wpa_printf(MSG_DEBUG, "WPS ER: UDN='%s'", ap->udn);
-	pos = os_strstr(ap->udn, "uuid:");
-	if (pos) {
-		pos += 5;
-		if (uuid_str2bin(pos, ap->uuid) < 0)
-			wpa_printf(MSG_DEBUG, "WPS ER: Invalid UUID in UDN");
+	if (ap->udn) {
+		wpa_printf(MSG_DEBUG, "WPS ER: UDN='%s'", ap->udn);
+		pos = os_strstr(ap->udn, "uuid:");
+		if (pos) {
+			pos += 5;
+			if (uuid_str2bin(pos, ap->uuid) < 0)
+				wpa_printf(MSG_DEBUG,
+					   "WPS ER: Invalid UUID in UDN");
+		}
 	}
 
 	ap->upc = xml_get_first_item(data, "UPC");
diff --git a/src/wps/wps_upnp.c b/src/wps/wps_upnp.c
index 6fb3d4c..f62b49e 100644
--- a/src/wps/wps_upnp.c
+++ b/src/wps/wps_upnp.c
@@ -227,6 +227,8 @@
 
 	t = time(NULL);
 	date = gmtime(&t);
+	if (date == NULL)
+		return;
 	wpabuf_printf(buf, "%s, %02d %s %d %02d:%02d:%02d GMT",
 		      &weekday_str[date->tm_wday * 4], date->tm_mday,
 		      &month_str[date->tm_mon * 4], date->tm_year + 1900,
diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
index eaf9705..43c3eed 100644
--- a/wpa_supplicant/Android.mk
+++ b/wpa_supplicant/Android.mk
@@ -38,10 +38,6 @@
 L_CFLAGS += -DCONFIG_NO_ROAMING
 endif
 
-ifeq ($(BOARD_WLAN_DEVICE), bcmdhd)
-L_CFLAGS += -DP2P_CONCURRENT_SEARCH_DELAY=0
-endif
-
 # Use Android specific directory for control interface sockets
 L_CFLAGS += -DCONFIG_CTRL_IFACE_CLIENT_DIR=\"/data/misc/wifi/sockets\"
 L_CFLAGS += -DCONFIG_CTRL_IFACE_DIR=\"/data/system/wpa_supplicant\"
diff --git a/wpa_supplicant/README-P2P b/wpa_supplicant/README-P2P
index bfad501..5c1e4f9 100644
--- a/wpa_supplicant/README-P2P
+++ b/wpa_supplicant/README-P2P
@@ -554,6 +554,13 @@
 
 Set country code (this is included in some P2P messages).
 
+set p2p_search_delay <delay>
+
+Set p2p_search_delay which adds extra delay in milliseconds between
+concurrent search iterations to make p2p_find friendlier to concurrent
+operations by avoiding it from taking 100% of radio resources. The
+default value is 500 ms.
+
 Status
 
 p2p_peers [discovered]
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index e60bc05..278ec9b 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -3266,6 +3266,7 @@
 	config->wmm_ac_params[1] = ac_bk;
 	config->wmm_ac_params[2] = ac_vi;
 	config->wmm_ac_params[3] = ac_vo;
+	config->p2p_search_delay = DEFAULT_P2P_SEARCH_DELAY;
 
 	if (ctrl_interface)
 		config->ctrl_interface = os_strdup(ctrl_interface);
@@ -3884,6 +3885,7 @@
 	{ INT(tdls_external_control), 0},
 	{ STR(osu_dir), 0 },
 	{ STR(wowlan_triggers), 0 },
+	{ INT(p2p_search_delay), 0},
 };
 
 #undef FUNC
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index bf3f3f7..9b7e21d 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -25,6 +25,7 @@
 #define DEFAULT_MAX_NUM_STA 128
 #define DEFAULT_ACCESS_NETWORK_TYPE 15
 #define DEFAULT_SCAN_CUR_FREQ 0
+#define DEFAULT_P2P_SEARCH_DELAY 500
 
 #include "config_ssid.h"
 #include "wps/wps.h"
@@ -1029,6 +1030,16 @@
 	 * If set, these wowlan triggers will be configured.
 	 */
 	char *wowlan_triggers;
+
+	/**
+	 * p2p_search_delay - Extra delay between concurrent search iterations
+	 *
+	 * Add extra delay (in milliseconds) between search iterations when
+	 * there is a concurrent operation to make p2p_find friendlier to
+	 * concurrent operations by avoiding it from taking 100% of radio
+	 * resources.
+	 */
+	unsigned int p2p_search_delay;
 };
 
 
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index 4dc4d12..d09b942 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -790,7 +790,8 @@
 		const char *name;
 		name = eap_get_name(cred->eap_method[0].vendor,
 				    cred->eap_method[0].method);
-		fprintf(f, "\teap=%s\n", name);
+		if (name)
+			fprintf(f, "\teap=%s\n", name);
 	}
 	if (cred->phase1)
 		fprintf(f, "\tphase1=\"%s\"\n", cred->phase1);
@@ -1164,6 +1165,10 @@
 
 	if (config->bgscan)
 		fprintf(f, "bgscan=\"%s\"\n", config->bgscan);
+
+	if (config->p2p_search_delay != DEFAULT_P2P_SEARCH_DELAY)
+		fprintf(f, "p2p_search_delay=%u\n",
+			config->p2p_search_delay);
 }
 
 #endif /* CONFIG_NO_CONFIG_WRITE */
diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
index 20cbeed..8be8288 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
@@ -834,6 +834,11 @@
 	    !dbus_message_iter_close_container(iter, &variant_iter))
 		goto err_no_mem;
 
+	/* P2P Search Delay */
+	if (!wpa_dbus_dict_append_uint32(&dict_iter, "p2p_search_delay",
+					 wpa_s->conf->p2p_search_delay))
+		goto err_no_mem;
+
 	return TRUE;
 
 err_no_mem:
@@ -982,6 +987,9 @@
 		else if (os_strcmp(entry.key, "NoGroupIface") == 0 &&
 			 entry.type == DBUS_TYPE_BOOLEAN)
 			wpa_s->conf->p2p_no_group_iface = entry.bool_value;
+		else if (os_strcmp(entry.key, "p2p_search_delay") == 0 &&
+			 entry.type == DBUS_TYPE_UINT32)
+			wpa_s->conf->p2p_search_delay = entry.uint32_value;
 		else
 			goto error;
 
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 0b9077b..f511e1a 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -1872,6 +1872,8 @@
 
 #ifdef CONFIG_AP
 	if (wpa_s->ap_iface) {
+		if (!data)
+			return;
 		hostapd_notif_assoc(wpa_s->ap_iface->bss[0],
 				    data->assoc_info.addr,
 				    data->assoc_info.req_ies,
@@ -1960,7 +1962,8 @@
 	    wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE ||
 	    (wpa_s->current_ssid &&
 	     wpa_s->current_ssid->mode == IEEE80211_MODE_IBSS)) {
-		if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE &&
+		if (wpa_s->current_ssid &&
+		    wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE &&
 		    (wpa_s->drv_flags &
 		     WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE)) {
 			/*
diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
index 6d1539c..bbee951 100644
--- a/wpa_supplicant/interworking.c
+++ b/wpa_supplicant/interworking.c
@@ -1515,6 +1515,7 @@
 	u16 count, i;
 	char buf[100];
 	int excluded = 0, *excl = allow_excluded ? &excluded : NULL;
+	const char *name;
 
 	if (wpa_s->conf->cred == NULL || bss == NULL)
 		return -1;
@@ -1728,11 +1729,12 @@
 		if (wpa_config_set(ssid, "pac_file",
 				   "\"blob://pac_interworking\"", 0) < 0)
 			goto fail;
-		os_snprintf(buf, sizeof(buf), "\"auth=%s\"",
-			    eap_get_name(EAP_VENDOR_IETF,
-					 eap->inner_method ?
-					 eap->inner_method :
-					 EAP_TYPE_MSCHAPV2));
+		name = eap_get_name(EAP_VENDOR_IETF,
+				    eap->inner_method ? eap->inner_method :
+				    EAP_TYPE_MSCHAPV2);
+		if (name == NULL)
+			goto fail;
+		os_snprintf(buf, sizeof(buf), "\"auth=%s\"", name);
 		if (wpa_config_set(ssid, "phase2", buf, 0) < 0)
 			goto fail;
 		break;
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 393f13b..50ee1e0 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -82,10 +82,6 @@
 #define P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE 15
 #endif /* P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE */
 
-#ifndef P2P_CONCURRENT_SEARCH_DELAY
-#define P2P_CONCURRENT_SEARCH_DELAY 500
-#endif /* P2P_CONCURRENT_SEARCH_DELAY */
-
 #define P2P_MGMT_DEVICE_PREFIX		"p2p-dev-"
 
 enum p2p_group_removal_reason {
@@ -6764,8 +6760,8 @@
 	if (wpa_s->wpa_state > WPA_SCANNING) {
 		wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Use %u ms search delay due to "
 			"concurrent operation",
-			P2P_CONCURRENT_SEARCH_DELAY);
-		return P2P_CONCURRENT_SEARCH_DELAY;
+			wpa_s->conf->p2p_search_delay);
+		return wpa_s->conf->p2p_search_delay;
 	}
 
 	dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
@@ -6774,8 +6770,9 @@
 			wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Use %u ms search "
 				"delay due to concurrent operation on "
 				"interface %s",
-				P2P_CONCURRENT_SEARCH_DELAY, ifs->ifname);
-			return P2P_CONCURRENT_SEARCH_DELAY;
+				wpa_s->conf->p2p_search_delay,
+				ifs->ifname);
+			return wpa_s->conf->p2p_search_delay;
 		}
 	}
 
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index 9b6667a..82aef0d 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -151,7 +151,7 @@
 #endif /* CONFIG_IEEE80211R */
 	int i, bssid_changed;
 	struct wpabuf *resp = NULL;
-	u8 ext_capab[10];
+	u8 ext_capab[18];
 	int ext_capab_len;
 
 	if (bss == NULL) {
@@ -371,7 +371,8 @@
 	}
 #endif /* CONFIG_HS20 */
 
-	ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab);
+	ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
+					     sizeof(ext_capab));
 	if (ext_capab_len > 0) {
 		u8 *pos = wpa_s->sme.assoc_req_ie;
 		if (wpa_s->sme.assoc_req_ie_len > 0 && pos[0] == WLAN_EID_RSN)
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index b3812ca..8811d6f 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -628,7 +628,7 @@
 		"p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
 		"sae_groups", "dtim_period", "beacon_int", "ap_vendor_elements",
 		"ignore_old_scan_res", "freq_list", "external_sim",
-		"tdls_external_control"
+		"tdls_external_control", "p2p_search_delay"
 	};
 	int i, num_fields = ARRAY_SIZE(fields);
 
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 0b871d0..ffba0f5 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -1272,13 +1272,18 @@
 }
 
 
-int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf)
+int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
 {
 	u8 *pos = buf;
 	u8 len = 6, i;
 
 	if (len < wpa_s->extended_capa_len)
 		len = wpa_s->extended_capa_len;
+	if (buflen < (size_t) len + 2) {
+		wpa_printf(MSG_INFO,
+			   "Not enough room for building extended capabilities element");
+		return -1;
+	}
 
 	*pos++ = WLAN_EID_EXT_CAPAB;
 	*pos++ = len;
@@ -1666,9 +1671,10 @@
 	 * interoperability issues.
 	 */
 	if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
-		u8 ext_capab[10];
+		u8 ext_capab[18];
 		int ext_capab_len;
-		ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab);
+		ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
+						     sizeof(ext_capab));
 		if (ext_capab_len > 0) {
 			u8 *pos = wpa_ie;
 			if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index 243787f..191f206 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -269,6 +269,13 @@
 # inactive stations.
 #p2p_go_max_inactivity=300
 
+# Extra delay between concurrent P2P search iterations
+#
+# This value adds extra delay in milliseconds between concurrent search
+# iterations to make p2p_find friendlier to concurrent operations by avoiding
+# it from taking 100% of radio resources. The default value is 500 ms.
+#p2p_search_delay=500
+
 # Opportunistic Key Caching (also known as Proactive Key Caching) default
 # This parameter can be used to set the default behavior for the
 # proactive_key_caching parameter. By default, OKC is disabled unless enabled
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index a83c8cd..56434c4 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -941,7 +941,7 @@
 int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
 		    size_t ssid_len);
 void wpas_request_connection(struct wpa_supplicant *wpa_s);
-int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf);
+int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen);
 
 /**
  * wpa_supplicant_ctrl_iface_ctrl_rsp_handle - Handle a control response