Accumulative patch from commit 6ea1f4135b72199988393f34dd7f5ad8040b7a42

6ea1f41 Try to set WPA-None key after IBSS-joined event
66562e9 Use cached driver capabilities instead of new fetch for each operation
55293aa TDLS: Do not overwrite the reason code in the Tear Down Request
4aa8186 Add a configration parameter for sched_scan interval
03565bc Synchronize with wireless-testing.git include/uapi/linux/nl80211.h
f11b72c TDLS: Move AID=1 workaround into driver_nl80211.c
7853369 TDLS: Pass peer's AID information to kernel
55a2df4 HS 2.0: Include HS 2.0 Indication element only for HS 2.0 association
ad0685e edit: Fix history processing on running old command
9be3714 wpa_cli: Fetch the current BSSID list when starting interactive mode
69aa334 wpa_cli: Add BSSID tab completion for set bssid_filter
2156587 wpa_cli: Replace set command help with completion routine
f1fb042 wpa_cli: Allow space in the set command value
f5ffc34 wpa_supplicant: Allow global scan frequencies configuration
abfc3ad Synchronize build config comments for wpa_supplicant
a01e10d Android: Enable WPS ER and NFC support in the build
11e5a49 WPS: Do not use void* in arithmetic
0f105f9 HS 2.0: Move Probe Request Indication IE addition to proper place
8543ed8 WPA: Print pairwise EAPOL-Key flag as a bool
7af092a hostapd: Add Key MIC in group EAPOL-Key frames corruption test option
b691dcb nl80211: Fix max_remain_on_chan capability reading
41b1a76 P2P: Clone beacon_int when initializing new group interface
741ed9f WPS: Remove duplicate networks after WPS

Change-Id: I9a2a0cb2acf87dfd7548318d2bda5f342b815884
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 0d97a21..7ecbc65 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -57,3 +57,5 @@
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/wpa_cli_intermediates/*)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/wpa_supplicant_intermediates/*)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/hostapd_intermediates/*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/wpa_supplicant_intermediates/*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/hostapd_intermediates/*)
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 21104d3..62136ca 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -2893,6 +2893,7 @@
 		PARSE_TEST_PROBABILITY(ignore_auth_probability)
 		PARSE_TEST_PROBABILITY(ignore_assoc_probability)
 		PARSE_TEST_PROBABILITY(ignore_reassoc_probability)
+		PARSE_TEST_PROBABILITY(corrupt_gtk_rekey_mic_probability)
 #endif /* CONFIG_TESTING_OPTIONS */
 		} else if (os_strcmp(buf, "vendor_elements") == 0) {
 			struct wpabuf *elems;
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index 6a1c500..86015bf 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -1540,6 +1540,9 @@
 #
 # Ignore reassociation requests with the given probability
 #ignore_reassoc_probability=0.0
+#
+# Corrupt Key MIC in GTK rekey EAPOL-Key frames with the given probability
+#corrupt_gtk_rekey_mic_probability=0.0
 
 ##### Multiple BSSID support ##################################################
 #
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index 70b26a6..7ab86fc 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -168,6 +168,7 @@
 	conf->ignore_auth_probability = 0.0d;
 	conf->ignore_assoc_probability = 0.0d;
 	conf->ignore_reassoc_probability = 0.0d;
+	conf->corrupt_gtk_rekey_mic_probability = 0.0d;
 #endif /* CONFIG_TESTING_OPTIONS */
 
 	return conf;
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index f9629a2..16134da 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -526,6 +526,7 @@
 	double ignore_auth_probability;
 	double ignore_assoc_probability;
 	double ignore_reassoc_probability;
+	double corrupt_gtk_rekey_mic_probability;
 #endif /* CONFIG_TESTING_OPTIONS */
 };
 
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index 4f1f6fb..18ae86c 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -1232,7 +1232,7 @@
 	else
 		version = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
 
-	pairwise = key_info & WPA_KEY_INFO_KEY_TYPE;
+	pairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE);
 
 	wpa_printf(MSG_DEBUG, "WPA: Send EAPOL(version=%d secure=%d mic=%d "
 		   "ack=%d install=%d pairwise=%d kde_len=%lu keyidx=%d "
@@ -1347,6 +1347,16 @@
 		}
 		wpa_eapol_key_mic(sm->PTK.kck, version, (u8 *) hdr, len,
 				  key->key_mic);
+#ifdef CONFIG_TESTING_OPTIONS
+		if (!pairwise &&
+		    wpa_auth->conf.corrupt_gtk_rekey_mic_probability > 0.0d &&
+		    drand48() <
+		    wpa_auth->conf.corrupt_gtk_rekey_mic_probability) {
+			wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+					"Corrupting group EAPOL-Key Key MIC");
+			key->key_mic[0]++;
+		}
+#endif /* CONFIG_TESTING_OPTIONS */
 	}
 
 	wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_inc_EapolFramesTx,
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index 465eec6..9126b90 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -160,6 +160,9 @@
 #endif /* CONFIG_IEEE80211R */
 	int disable_gtk;
 	int ap_mlme;
+#ifdef CONFIG_TESTING_OPTIONS
+	double corrupt_gtk_rekey_mic_probability;
+#endif /* CONFIG_TESTING_OPTIONS */
 };
 
 typedef enum {
diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
index fdaaaff..e2be1ea 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -28,6 +28,7 @@
 
 
 static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
+				  struct hostapd_config *iconf,
 				  struct wpa_auth_config *wconf)
 {
 	os_memset(wconf, 0, sizeof(*wconf));
@@ -74,6 +75,10 @@
 #ifdef CONFIG_HS20
 	wconf->disable_gtk = conf->disable_dgaf;
 #endif /* CONFIG_HS20 */
+#ifdef CONFIG_TESTING_OPTIONS
+	wconf->corrupt_gtk_rekey_mic_probability =
+		iconf->corrupt_gtk_rekey_mic_probability;
+#endif /* CONFIG_TESTING_OPTIONS */
 }
 
 
@@ -509,7 +514,7 @@
 	const u8 *wpa_ie;
 	size_t wpa_ie_len;
 
-	hostapd_wpa_auth_conf(hapd->conf, &_conf);
+	hostapd_wpa_auth_conf(hapd->conf, hapd->iconf, &_conf);
 	if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_EAPOL_TX_STATUS)
 		_conf.tx_status = 1;
 	if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_MLME)
@@ -583,7 +588,7 @@
 void hostapd_reconfig_wpa(struct hostapd_data *hapd)
 {
 	struct wpa_auth_config wpa_auth_conf;
-	hostapd_wpa_auth_conf(hapd->conf, &wpa_auth_conf);
+	hostapd_wpa_auth_conf(hapd->conf, hapd->iconf, &wpa_auth_conf);
 	wpa_reconfig(hapd->wpa_auth, &wpa_auth_conf);
 }
 
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 6125015..213f3c3 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -2747,9 +2747,6 @@
 static void wiphy_info_max_roc(struct wpa_driver_capa *capa,
 			       struct nlattr *tb)
 {
-	/* default to 5000 since early versions of mac80211 don't set it */
-	capa->max_remain_on_chan = 5000;
-
 	if (tb)
 		capa->max_remain_on_chan = nla_get_u32(tb);
 }
@@ -2941,6 +2938,11 @@
 			   "concurrent (driver advertised support)");
 		drv->capa.flags |= WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT;
 	}
+
+	/* default to 5000 since early versions of mac80211 don't set it */
+	if (!drv->capa.max_remain_on_chan)
+		drv->capa.max_remain_on_chan = 5000;
+
 	return 0;
 nla_put_failure:
 	nlmsg_free(msg);
@@ -6092,8 +6094,18 @@
 	wpa_hexdump(MSG_DEBUG, "  * supported rates", params->supp_rates,
 		    params->supp_rates_len);
 	if (!params->set) {
-		wpa_printf(MSG_DEBUG, "  * aid=%u", params->aid);
-		NLA_PUT_U16(msg, NL80211_ATTR_STA_AID, params->aid);
+		if (params->aid) {
+			wpa_printf(MSG_DEBUG, "  * aid=%u", params->aid);
+			NLA_PUT_U16(msg, NL80211_ATTR_STA_AID, params->aid);
+		} else {
+			/*
+			 * cfg80211 validates that AID is non-zero, so we have
+			 * to make this a non-zero value for the TDLS case where
+			 * a dummy STA entry is used for now.
+			 */
+			wpa_printf(MSG_DEBUG, "  * aid=1 (TDLS workaround)");
+			NLA_PUT_U16(msg, NL80211_ATTR_STA_AID, 1);
+		}
 		wpa_printf(MSG_DEBUG, "  * listen_interval=%u",
 			   params->listen_interval);
 		NLA_PUT_U16(msg, NL80211_ATTR_STA_LISTEN_INTERVAL,
diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h
index 79da871..d1e48b5 100644
--- a/src/drivers/nl80211_copy.h
+++ b/src/drivers/nl80211_copy.h
@@ -639,6 +639,13 @@
  *	with the relevant Information Elements. This event is used to report
  *	received FT IEs (MDIE, FTIE, RSN IE, TIE, RICIE).
  *
+ * @NL80211_CMD_CRIT_PROTOCOL_START: Indicates user-space will start running
+ *	a critical protocol that needs more reliability in the connection to
+ *	complete.
+ *
+ * @NL80211_CMD_CRIT_PROTOCOL_STOP: Indicates the connection reliability can
+ *	return back to normal.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -798,6 +805,9 @@
 	NL80211_CMD_UPDATE_FT_IES,
 	NL80211_CMD_FT_EVENT,
 
+	NL80211_CMD_CRIT_PROTOCOL_START,
+	NL80211_CMD_CRIT_PROTOCOL_STOP,
+
 	/* add new commands above here */
 
 	/* used to define NL80211_CMD_MAX below */
@@ -1414,6 +1424,11 @@
  * @NL80211_ATTR_IE_RIC: Resource Information Container Information
  *	Element
  *
+ * @NL80211_ATTR_CRIT_PROT_ID: critical protocol identifier requiring increased
+ *	reliability, see &enum nl80211_crit_proto_id (u16).
+ * @NL80211_ATTR_MAX_CRIT_PROT_DURATION: duration in milliseconds in which
+ *      the connection should have increased reliability (u16).
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -1709,6 +1724,9 @@
 	NL80211_ATTR_MDID,
 	NL80211_ATTR_IE_RIC,
 
+	NL80211_ATTR_CRIT_PROT_ID,
+	NL80211_ATTR_MAX_CRIT_PROT_DURATION,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -3682,4 +3700,25 @@
 	NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP =	1 << 0,
 };
 
+/**
+ * enum nl80211_crit_proto_id - nl80211 critical protocol identifiers
+ *
+ * @NL80211_CRIT_PROTO_UNSPEC: protocol unspecified.
+ * @NL80211_CRIT_PROTO_DHCP: BOOTP or DHCPv6 protocol.
+ * @NL80211_CRIT_PROTO_EAPOL: EAPOL protocol.
+ * @NL80211_CRIT_PROTO_APIPA: APIPA protocol.
+ * @NUM_NL80211_CRIT_PROTO: must be kept last.
+ */
+enum nl80211_crit_proto_id {
+	NL80211_CRIT_PROTO_UNSPEC,
+	NL80211_CRIT_PROTO_DHCP,
+	NL80211_CRIT_PROTO_EAPOL,
+	NL80211_CRIT_PROTO_APIPA,
+	/* add other protocols before this one */
+	NUM_NL80211_CRIT_PROTO
+};
+
+/* maximum duration for critical protocol measures */
+#define NL80211_CRIT_PROTO_MAX_DURATION		5000 /* msec */
+
 #endif /* __LINUX_NL80211_H */
diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c
index 069e22b..81e2a5c 100644
--- a/src/rsn_supp/tdls.c
+++ b/src/rsn_supp/tdls.c
@@ -127,6 +127,8 @@
 
 	u8 qos_info;
 
+	u16 aid;
+
 	u8 *ext_capab;
 	size_t ext_capab_len;
 };
@@ -696,13 +698,8 @@
 		return -1;
 	pos = rbuf;
 
-	if (!wpa_tdls_get_privacy(sm) || !peer->tpk_set || !peer->tpk_success) {
-		if (reason_code != WLAN_REASON_DEAUTH_LEAVING) {
-			/* Overwrite the reason code */
-			reason_code = WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED;
-		}
+	if (!wpa_tdls_get_privacy(sm) || !peer->tpk_set || !peer->tpk_success)
 		goto skip_ies;
-	}
 
 	ftie = (struct wpa_tdls_ftie *) pos;
 	ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION;
@@ -1558,6 +1555,8 @@
 
 	peer->qos_info = kde.qosinfo;
 
+	peer->aid = kde.aid;
+
 #ifdef CONFIG_TDLS_TESTING
 	if (tdls_testing & TDLS_TESTING_CONCURRENT_INIT) {
 		peer = wpa_tdls_add_peer(sm, src_addr, NULL);
@@ -1735,7 +1734,7 @@
 
 skip_rsn_check:
 	/* add the peer to the driver as a "setup in progress" peer */
-	wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, NULL, 0, NULL, NULL, 0,
+	wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0,
 				NULL, 0);
 
 	wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Response / TPK M2");
@@ -1777,7 +1776,8 @@
 	}
 
 	/* add supported rates, capabilities, and qos_info to the TDLS peer */
-	if (wpa_sm_tdls_peer_addset(sm, peer->addr, 0, peer->capability,
+	if (wpa_sm_tdls_peer_addset(sm, peer->addr, 0, peer->aid,
+				    peer->capability,
 				    peer->supp_rates, peer->supp_rates_len,
 				    peer->ht_capabilities,
 				    peer->vht_capabilities,
@@ -1908,6 +1908,8 @@
 
 	peer->qos_info = kde.qosinfo;
 
+	peer->aid = kde.aid;
+
 	if (!wpa_tdls_get_privacy(sm)) {
 		peer->rsnie_p_len = 0;
 		peer->cipher = WPA_CIPHER_NONE;
@@ -2235,7 +2237,7 @@
 	peer->initiator = 1;
 
 	/* add the peer to the driver as a "setup in progress" peer */
-	wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, NULL, 0, NULL, NULL, 0,
+	wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0,
 				NULL, 0);
 
 	if (wpa_tdls_send_tpk_m1(sm, peer) < 0) {
diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
index d4533a8..78dfb52 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -56,7 +56,7 @@
 			      u8 action_code, u8 dialog_token,
 			      u16 status_code, const u8 *buf, size_t len);
 	int (*tdls_oper)(void *ctx, int oper, const u8 *peer);
-	int (*tdls_peer_addset)(void *ctx, const u8 *addr, int add,
+	int (*tdls_peer_addset)(void *ctx, const u8 *addr, int add, u16 aid,
 				u16 capability, const u8 *supp_rates,
 				size_t supp_rates_len,
 				const struct ieee80211_ht_capabilities *ht_capab,
diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h
index 877e6de..0e0d373 100644
--- a/src/rsn_supp/wpa_i.h
+++ b/src/rsn_supp/wpa_i.h
@@ -282,7 +282,7 @@
 
 static inline int
 wpa_sm_tdls_peer_addset(struct wpa_sm *sm, const u8 *addr, int add,
-			u16 capability, const u8 *supp_rates,
+			u16 aid, u16 capability, const u8 *supp_rates,
 			size_t supp_rates_len,
 			const struct ieee80211_ht_capabilities *ht_capab,
 			const struct ieee80211_vht_capabilities *vht_capab,
@@ -290,7 +290,7 @@
 {
 	if (sm->ctx->tdls_peer_addset)
 		return sm->ctx->tdls_peer_addset(sm->ctx->ctx, addr, add,
-						 capability, supp_rates,
+						 aid, capability, supp_rates,
 						 supp_rates_len, ht_capab,
 						 vht_capab, qosinfo,
 						 ext_capab, ext_capab_len);
diff --git a/src/rsn_supp/wpa_ie.c b/src/rsn_supp/wpa_ie.c
index 652197f..ba203e6 100644
--- a/src/rsn_supp/wpa_ie.c
+++ b/src/rsn_supp/wpa_ie.c
@@ -430,6 +430,9 @@
 		} else if (*pos == WLAN_EID_HT_CAP) {
 			ie->ht_capabilities = pos + 2;
 			ie->ht_capabilities_len = pos[1];
+		} else if (*pos == WLAN_EID_VHT_AID) {
+			if (pos[1] >= 2)
+				ie->aid = WPA_GET_LE16(pos + 2);
 		} else if (*pos == WLAN_EID_VHT_CAP) {
 			ie->vht_capabilities = pos + 2;
 			ie->vht_capabilities_len = pos[1];
diff --git a/src/rsn_supp/wpa_ie.h b/src/rsn_supp/wpa_ie.h
index 82a5c08..2c78801 100644
--- a/src/rsn_supp/wpa_ie.h
+++ b/src/rsn_supp/wpa_ie.h
@@ -54,6 +54,7 @@
 	const u8 *vht_capabilities;
 	size_t vht_capabilities_len;
 	u8 qosinfo;
+	u16 aid;
 };
 
 int wpa_supplicant_parse_ies(const u8 *buf, size_t len,
diff --git a/src/utils/edit.c b/src/utils/edit.c
index b01e08d..177ecf4 100644
--- a/src/utils/edit.c
+++ b/src/utils/edit.c
@@ -345,7 +345,7 @@
 
 static void process_cmd(void)
 {
-
+	currbuf_valid = 0;
 	if (cmdbuf_len == 0) {
 		printf("\n%s> ", ps2 ? ps2 : "");
 		fflush(stdout);
diff --git a/src/wps/http_client.c b/src/wps/http_client.c
index c6d6c7f..0290013 100644
--- a/src/wps/http_client.c
+++ b/src/wps/http_client.c
@@ -92,7 +92,7 @@
 		   (unsigned long) wpabuf_len(c->req),
 		   (unsigned long) wpabuf_len(c->req) - c->req_pos);
 
-	res = send(c->sd, wpabuf_head(c->req) + c->req_pos,
+	res = send(c->sd, wpabuf_head_u8(c->req) + c->req_pos,
 		   wpabuf_len(c->req) - c->req_pos, 0);
 	if (res < 0) {
 		wpa_printf(MSG_DEBUG, "HTTP: Failed to send buffer: %s",
diff --git a/wpa_supplicant/android.config b/wpa_supplicant/android.config
index b86c4c7..331940c 100644
--- a/wpa_supplicant/android.config
+++ b/wpa_supplicant/android.config
@@ -176,7 +176,7 @@
 CONFIG_EAP_LEAP=y
 
 # EAP-AKA (enable CONFIG_PCSC, if EAP-AKA is used)
-#CONFIG_EAP_AKA=y
+CONFIG_EAP_AKA=y
 
 # EAP-AKA' (enable CONFIG_PCSC, if EAP-AKA' is used).
 # This requires CONFIG_EAP_AKA to be enabled, too.
@@ -201,10 +201,12 @@
 # Enable WSC 2.0 support
 CONFIG_WPS2=y
 # Enable WPS external registrar functionality
-#CONFIG_WPS_ER=y
+CONFIG_WPS_ER=y
 # Disable credentials for an open network by default when acting as a WPS
 # registrar.
 #CONFIG_WPS_REG_DISABLE_OPEN=y
+# Enable WPS support with NFC config method
+CONFIG_WPS_NFC=y
 
 # EAP-IKEv2
 #CONFIG_EAP_IKEV2=y
@@ -234,6 +236,7 @@
 # unix = UNIX domain sockets (default for Linux/*BSD)
 # udp = UDP sockets using localhost (127.0.0.1)
 # named_pipe = Windows Named Pipe (default for Windows)
+# udp-remote = UDP sockets with remote access (only for tests systems/purpose)
 # y = use default (backwards compatibility)
 # If this option is commented out, control interface is not included in the
 # build.
@@ -325,9 +328,7 @@
 # PeerKey handshake for Station to Station Link (IEEE 802.11e DLS)
 CONFIG_PEERKEY=y
 
-# IEEE 802.11w (management frame protection)
-# This version is an experimental implementation based on IEEE 802.11w/D1.0
-# draft and is subject to change since the standard has not yet been finalized.
+# IEEE 802.11w (management frame protection), also known as PMF
 # Driver support is also needed for IEEE 802.11w.
 #CONFIG_IEEE80211W=y
 
@@ -486,6 +487,10 @@
 # IEEE 802.11n (High Throughput) support (mainly for AP mode)
 CONFIG_IEEE80211N=y
 
+# Wireless Network Management (IEEE Std 802.11v-2011)
+# Note: This is experimental and not complete implementation.
+#CONFIG_WNM=y
+
 # Interworking (IEEE 802.11u)
 # This can be used to enable functionality to improve interworking with
 # external networks (GAS/ANQP to learn more about the networks and network
@@ -498,12 +503,39 @@
 # Disable roaming in wpa_supplicant
 CONFIG_NO_ROAMING=y
 
-# Enable TDLS
-CONFIG_TDLS=y
-
-# Enable P2P
-CONFIG_P2P=y
+# AP mode operations with wpa_supplicant
+# This can be used for controlling AP mode operations with wpa_supplicant. It
+# should be noted that this is mainly aimed at simple cases like
+# WPA2-Personal while more complex configurations like WPA2-Enterprise with an
+# external RADIUS server can be supported with hostapd.
 CONFIG_AP=y
 
+# P2P (Wi-Fi Direct)
+# This can be used to enable P2P support in wpa_supplicant. See README-P2P for
+# more information on P2P operations.
+CONFIG_P2P=y
+
+CONFIG_TDLS=y
+
 #Enable Wifi Display
 CONFIG_WIFI_DISPLAY=y
+
+# Autoscan
+# This can be used to enable automatic scan support in wpa_supplicant.
+# See wpa_supplicant.conf for more information on autoscan usage.
+#
+# Enabling directly a module will enable autoscan support.
+# For exponential module:
+#CONFIG_AUTOSCAN_EXPONENTIAL=y
+# For periodic module:
+#CONFIG_AUTOSCAN_PERIODIC=y
+
+# Password (and passphrase, etc.) backend for external storage
+# These optional mechanisms can be used to add support for storing passwords
+# and other secrets in external (to wpa_supplicant) location. This allows, for
+# example, operating system specific key storage to be used
+#
+# External password backend for testing purposes (developer use)
+#CONFIG_EXT_PASSWORD_TEST=y
+
+include $(wildcard $(LOCAL_PATH)/android_config_*.inc)
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index 2de7845..b25e0f6 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -1826,6 +1826,7 @@
 	os_free(config->pssid);
 	os_free(config->p2p_pref_chan);
 	os_free(config->autoscan);
+	os_free(config->freq_list);
 	wpabuf_free(config->wps_nfc_dh_pubkey);
 	wpabuf_free(config->wps_nfc_dh_privkey);
 	wpabuf_free(config->wps_nfc_dev_pw);
@@ -2733,6 +2734,21 @@
 }
 
 
+static int wpa_config_process_freq_list(const struct global_parse_data *data,
+					struct wpa_config *config, int line,
+					const char *value)
+{
+	int *freqs;
+
+	freqs = wpa_config_parse_int_array(value);
+	if (freqs == NULL)
+		return -1;
+	os_free(config->freq_list);
+	config->freq_list = freqs;
+	return 0;
+}
+
+
 static int wpa_config_process_country(const struct global_parse_data *data,
 				      struct wpa_config *config, int line,
 				      const char *pos)
@@ -3088,6 +3104,8 @@
 	{ INT(beacon_int), 0 },
 	{ FUNC(ap_vendor_elements), 0 },
 	{ INT_RANGE(ignore_old_scan_res, 0, 1), 0 },
+	{ FUNC(freq_list), 0 },
+	{ INT(sched_scan_interval), 0 },
 };
 
 #undef FUNC
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index 4a175ce..a1a5239 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -645,6 +645,14 @@
 	unsigned int max_num_sta;
 
 	/**
+	 * freq_list - Array of allowed scan frequencies or %NULL for all
+	 *
+	 * This is an optional zero-terminated array of frequencies in
+	 * megahertz (MHz) to allow for narrowing scanning range.
+	 */
+	int *freq_list;
+
+	/**
 	 * changed_parameters - Bitmap of changed parameters since last update
 	 */
 	unsigned int changed_parameters;
@@ -854,6 +862,11 @@
 	 * allowing it to update the internal BSS table.
 	 */
 	int ignore_old_scan_res;
+
+	/**
+	 * sched_scan_interval -  schedule scan interval
+	 */
+	unsigned int sched_scan_interval;
 };
 
 
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index 8604ae8..8ff4285 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -1015,6 +1015,20 @@
 	if (config->ignore_old_scan_res)
 		fprintf(f, "ignore_old_scan_res=%d\n",
 			config->ignore_old_scan_res);
+
+	if (config->freq_list && config->freq_list[0]) {
+		int i;
+		fprintf(f, "freq_list=");
+		for (i = 0; config->freq_list[i]; i++) {
+			fprintf(f, "%s%u", i > 0 ? " " : "",
+				config->freq_list[i]);
+		}
+		fprintf(f, "\n");
+	}
+
+	if (config->sched_scan_interval)
+		fprintf(f, "sched_scan_interval=%u\n",
+			config->sched_scan_interval);
 }
 
 #endif /* CONFIG_NO_CONFIG_WRITE */
diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig
index e867bae..5663a5f 100644
--- a/wpa_supplicant/defconfig
+++ b/wpa_supplicant/defconfig
@@ -423,6 +423,10 @@
 # same file, e.g., using trace-cmd.
 #CONFIG_DEBUG_LINUX_TRACING=y
 
+# Add support for writing debug log to Android logcat instead of standard
+# output
+#CONFIG_ANDROID_LOG=y
+
 # Enable privilege separation (see README 'Privilege separation' for details)
 #CONFIG_PRIVSEP=y
 
@@ -495,6 +499,9 @@
 # Hotspot 2.0
 #CONFIG_HS20=y
 
+# Disable roaming in wpa_supplicant
+#CONFIG_NO_ROAMING=y
+
 # AP mode operations with wpa_supplicant
 # This can be used for controlling AP mode operations with wpa_supplicant. It
 # should be noted that this is mainly aimed at simple cases like
@@ -507,6 +514,9 @@
 # more information on P2P operations.
 #CONFIG_P2P=y
 
+# Enable TDLS support
+#CONFIG_TDLS=y
+
 # Autoscan
 # This can be used to enable automatic scan support in wpa_supplicant.
 # See wpa_supplicant.conf for more information on autoscan usage.
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 650221a..cf2800e 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -1679,7 +1679,6 @@
 {
 	u8 bssid[ETH_ALEN];
 	int ft_completed;
-	struct wpa_driver_capa capa;
 
 #ifdef CONFIG_AP
 	if (wpa_s->ap_iface) {
@@ -1785,6 +1784,16 @@
 	    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 &&
+		    (wpa_s->drv_flags &
+		     WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE)) {
+			/*
+			 * Set the key after having received joined-IBSS event
+			 * from the driver.
+			 */
+			wpa_supplicant_set_wpa_none_key(wpa_s,
+							wpa_s->current_ssid);
+		}
 		wpa_supplicant_cancel_auth_timeout(wpa_s);
 		wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
 	} else if (!ft_completed) {
@@ -1845,8 +1854,8 @@
 
 	if ((wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
 	     wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) &&
-	    wpa_s->current_ssid && wpa_drv_get_capa(wpa_s, &capa) == 0 &&
-	    capa.flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE) {
+	    wpa_s->current_ssid &&
+	    (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE)) {
 		/* Set static WEP keys again */
 		wpa_set_wep_keys(wpa_s, wpa_s->current_ssid);
 	}
diff --git a/wpa_supplicant/hs20_supplicant.c b/wpa_supplicant/hs20_supplicant.c
index 1404241..4048cf7 100644
--- a/wpa_supplicant/hs20_supplicant.c
+++ b/wpa_supplicant/hs20_supplicant.c
@@ -33,6 +33,35 @@
 }
 
 
+int is_hs20_network(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
+		    struct wpa_bss *bss)
+{
+	if (!wpa_s->conf->hs20 || !ssid)
+		return 0;
+
+	if (ssid->parent_cred)
+		return 1;
+
+	if (bss && !wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE))
+		return 0;
+
+	/*
+	 * This may catch some non-Hotspot 2.0 cases, but it is safer to do that
+	 * than cause Hotspot 2.0 connections without indication element getting
+	 * added. Non-Hotspot 2.0 APs should ignore the unknown vendor element.
+	 */
+
+	if (!(ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X))
+		return 0;
+	if (!(ssid->pairwise_cipher & WPA_CIPHER_CCMP))
+		return 0;
+	if (ssid->proto != WPA_PROTO_RSN)
+		return 0;
+
+	return 1;
+}
+
+
 struct wpabuf * hs20_build_anqp_req(u32 stypes, const u8 *payload,
 				    size_t payload_len)
 {
diff --git a/wpa_supplicant/hs20_supplicant.h b/wpa_supplicant/hs20_supplicant.h
index 6eb3926..1c8481b 100644
--- a/wpa_supplicant/hs20_supplicant.h
+++ b/wpa_supplicant/hs20_supplicant.h
@@ -16,5 +16,7 @@
 				    size_t payload_len);
 void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s,
 				  const u8 *sa, const u8 *data, size_t slen);
+int is_hs20_network(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
+		    struct wpa_bss *bss);
 
 #endif /* HS20_SUPPLICANT_H */
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 5fcaf29..f1e15ff 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -1003,6 +1003,7 @@
 	d->max_num_sta = s->max_num_sta;
 	d->pbc_in_m1 = s->pbc_in_m1;
 	d->ignore_old_scan_res = s->ignore_old_scan_res;
+	d->beacon_int = s->beacon_int;
 }
 
 
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index db73a18..02c11b0 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -453,6 +453,11 @@
 
 #endif /* CONFIG_WPS */
 
+#ifdef CONFIG_HS20
+	if (wpa_s->conf->hs20 && wpabuf_resize(&extra_ie, 7) == 0)
+		wpas_hs20_add_indication(extra_ie);
+#endif /* CONFIG_HS20 */
+
 	return extra_ie;
 }
 
@@ -749,11 +754,6 @@
 	wpa_supplicant_optimize_freqs(wpa_s, &params);
 	extra_ie = wpa_supplicant_extra_ies(wpa_s);
 
-#ifdef CONFIG_HS20
-	if (wpa_s->conf->hs20 && wpabuf_resize(&extra_ie, 7) == 0)
-		wpas_hs20_add_indication(extra_ie);
-#endif /* CONFIG_HS20 */
-
 	if (params.freqs == NULL && wpa_s->next_scan_freqs) {
 		wpa_dbg(wpa_s, MSG_DEBUG, "Optimize scan based on previously "
 			"generated frequency list");
@@ -762,6 +762,13 @@
 		os_free(wpa_s->next_scan_freqs);
 	wpa_s->next_scan_freqs = NULL;
 
+	/* See if user specified frequencies. If so, scan only those. */
+	if (wpa_s->conf->freq_list && !params.freqs) {
+		wpa_dbg(wpa_s, MSG_DEBUG,
+			"Optimize scan based on conf->freq_list");
+		int_array_concat(&params.freqs, wpa_s->conf->freq_list);
+	}
+
 	params.filter_ssids = wpa_supplicant_build_filter_ssids(
 		wpa_s->conf, &params.num_filter_ssids);
 	if (extra_ie) {
@@ -1028,7 +1035,9 @@
 
 	if (!ssid || !wpa_s->prev_sched_ssid) {
 		wpa_dbg(wpa_s, MSG_DEBUG, "Beginning of SSID list");
-
+		if (wpa_s->conf->sched_scan_interval)
+			wpa_s->sched_scan_interval =
+				wpa_s->conf->sched_scan_interval;
 		if (wpa_s->sched_scan_interval == 0)
 			wpa_s->sched_scan_interval = 10;
 		wpa_s->sched_scan_timeout = max_sched_scan_ssids * 2;
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index 982e124..0371628 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -353,7 +353,7 @@
 #endif /* CONFIG_P2P */
 
 #ifdef CONFIG_HS20
-	if (wpa_s->conf->hs20) {
+	if (is_hs20_network(wpa_s, ssid, bss)) {
 		struct wpabuf *hs20;
 		hs20 = wpabuf_alloc(20);
 		if (hs20) {
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index 204d13e..b66dcd0 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -582,52 +582,81 @@
 }
 
 
-static void wpa_cli_show_variables(void)
-{
-	printf("set variables:\n"
-	       "  EAPOL::heldPeriod (EAPOL state machine held period, "
-	       "in seconds)\n"
-	       "  EAPOL::authPeriod (EAPOL state machine authentication "
-	       "period, in seconds)\n"
-	       "  EAPOL::startPeriod (EAPOL state machine start period, in "
-	       "seconds)\n"
-	       "  EAPOL::maxStart (EAPOL state machine maximum start "
-	       "attempts)\n");
-	printf("  dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
-	       "seconds)\n"
-	       "  dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
-	       " threshold\n\tpercentage)\n"
-	       "  dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
-	       "security\n\tassociation in seconds)\n");
-}
-
-
 static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
 	char cmd[256];
 	int res;
 
-	if (argc == 0) {
-		wpa_cli_show_variables();
-		return 0;
-	}
-
-	if (argc != 1 && argc != 2) {
-		printf("Invalid SET command: needs two arguments (variable "
-		       "name and value)\n");
-		return -1;
-	}
-
-	if (argc == 1)
+	if (argc == 1) {
 		res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]);
-	else
-		res = os_snprintf(cmd, sizeof(cmd), "SET %s %s",
-				  argv[0], argv[1]);
-	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
-		printf("Too long SET command.\n");
-		return -1;
+		if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
+			printf("Too long SET command.\n");
+			return -1;
+		}
+		return wpa_ctrl_command(ctrl, cmd);
 	}
-	return wpa_ctrl_command(ctrl, cmd);
+
+	return wpa_cli_cmd(ctrl, "SET", 2, argc, argv);
+}
+
+
+static char ** wpa_cli_complete_set(const char *str, int pos)
+{
+	int arg = get_cmd_arg_num(str, pos);
+	const char *fields[] = {
+		/* runtime values */
+		"EAPOL::heldPeriod", "EAPOL::authPeriod", "EAPOL::startPeriod",
+		"EAPOL::maxStart", "dot11RSNAConfigPMKLifetime",
+		"dot11RSNAConfigPMKReauthThreshold", "dot11RSNAConfigSATimeout",
+		"wps_fragment_size", "wps_version_number", "ampdu",
+		"tdls_testing", "tdls_disabled", "pno", "radio_disabled",
+		"uapsd", "ps", "wifi_display", "bssid_filter", "disallow_aps",
+		"no_keep_alive",
+		/* global configuration parameters */
+		"eapol_version", "ap_scan", "disable_scan_offload",
+		"fast_reauth", "opensc_engine_path", "pkcs11_engine_path",
+		"pkcs11_module_path", "pcsc_reader", "pcsc_pin",
+		"driver_param", "dot11RSNAConfigPMKLifetime",
+		"dot11RSNAConfigPMKReauthThreshold",
+		"dot11RSNAConfigSATimeout",
+		"update_config", "load_dynamic_eap", "uuid", "device_name",
+		"manufacturer", "model_name", "model_number", "serial_number",
+		"device_type", "os_version", "config_methods",
+		"wps_cred_processing", "wps_vendor_ext_m1", "sec_device_type",
+		"p2p_listen_reg_class", "p2p_listen_channel",
+		"p2p_oper_reg_class", "p2p_oper_channel",
+		"p2p_go_intent", "p2p_ssid_postfix", "persistent_reconnect",
+		"p2p_intra_bss", "p2p_group_idle", "p2p_pref_chan",
+		"p2p_go_ht40", "p2p_disabled", "p2p_no_group_iface",
+		"p2p_ignore_shared_freq", "country", "bss_max_count",
+		"bss_expiration_age", "bss_expiration_scan_count",
+		"filter_ssids", "filter_rssi", "max_num_sta",
+		"disassoc_low_ack", "hs20", "interworking", "hessid",
+		"access_network_type", "pbc_in_m1", "autoscan",
+		"wps_nfc_dev_pw_id", "wps_nfc_dh_pubkey", "wps_nfc_dh_privkey",
+		"wps_nfc_dev_pw", "ext_password_backend",
+		"p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
+		"sae_groups", "dtim_period", "beacon_int", "ap_vendor_elements",
+		"ignore_old_scan_res", "freq_list"
+	};
+	int i, num_fields = sizeof(fields) / sizeof(fields[0]);
+
+	if (arg == 1) {
+		char **res = os_calloc(num_fields + 1, sizeof(char *));
+		if (res == NULL)
+			return NULL;
+		for (i = 0; i < num_fields; i++) {
+			res[i] = os_strdup(fields[i]);
+			if (res[i] == NULL)
+				return res;
+		}
+		return res;
+	}
+
+	if (arg > 1 && os_strncasecmp(str, "set bssid_filter ", 17) == 0)
+		return cli_txt_list_array(&bsses);
+
+	return NULL;
 }
 
 
@@ -2372,7 +2401,7 @@
 	{ "quit", wpa_cli_cmd_quit, NULL,
 	  cli_cmd_flag_none,
 	  "= exit wpa_cli" },
-	{ "set", wpa_cli_cmd_set, NULL,
+	{ "set", wpa_cli_cmd_set, wpa_cli_complete_set,
 	  cli_cmd_flag_none,
 	  "= set variables (shows list of variables when run without "
 	  "arguments)" },
@@ -3316,6 +3345,37 @@
 }
 
 
+static void update_bssid_list(struct wpa_ctrl *ctrl)
+{
+	char buf[4096];
+	size_t len = sizeof(buf);
+	int ret;
+	char *cmd = "BSS RANGE=ALL MASK=0x2";
+	char *pos, *end;
+
+	if (ctrl == NULL)
+		return;
+	ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
+	if (ret < 0)
+		return;
+	buf[len] = '\0';
+
+	pos = buf;
+	while (pos) {
+		pos = os_strstr(pos, "bssid=");
+		if (pos == NULL)
+			break;
+		pos += 6;
+		end = os_strchr(pos, '\n');
+		if (end == NULL)
+			break;
+		*end = '\0';
+		cli_txt_list_add(&bsses, pos);
+		pos = end + 1;
+	}
+}
+
+
 static void try_connection(void *eloop_ctx, void *timeout_ctx)
 {
 	if (ctrl_ifname == NULL)
@@ -3331,6 +3391,8 @@
 		return;
 	}
 
+	update_bssid_list(ctrl_conn);
+
 	if (warning_displayed)
 		printf("Connection established.\n");
 
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index a66f654..c807888 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -126,8 +126,8 @@
 }
 
 
-static int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
-					   struct wpa_ssid *ssid)
+int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
+				    struct wpa_ssid *ssid)
 {
 	u8 key[32];
 	size_t keylen;
@@ -1271,7 +1271,6 @@
 	enum wpa_cipher cipher_pairwise, cipher_group;
 	struct wpa_driver_associate_params params;
 	int wep_keys_set = 0;
-	struct wpa_driver_capa capa;
 	int assoc_failed = 0;
 	struct wpa_ssid *old_ssid;
 	u8 ext_capab[10];
@@ -1475,7 +1474,7 @@
 #endif /* CONFIG_P2P */
 
 #ifdef CONFIG_HS20
-	if (wpa_s->conf->hs20) {
+	if (is_hs20_network(wpa_s, ssid, bss)) {
 		struct wpabuf *hs20;
 		hs20 = wpabuf_alloc(20);
 		if (hs20) {
@@ -1686,8 +1685,8 @@
 		wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
 	}
 
-	if (wep_keys_set && wpa_drv_get_capa(wpa_s, &capa) == 0 &&
-	    capa.flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC) {
+	if (wep_keys_set &&
+	    (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
 		/* Set static WEP keys again */
 		wpa_set_wep_keys(wpa_s, ssid);
 	}
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index 0935a06..87dd397 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -524,6 +524,9 @@
 # set, scan results that do not match any of the specified frequencies are not
 # considered when selecting a BSS.
 #
+# This can also be set on the outside of the network block. In this case,
+# it limits the frequencies that will be scanned.
+#
 # bgscan: Background scanning
 # wpa_supplicant behavior for background scanning can be specified by
 # configuring a bgscan module. These modules are responsible for requesting
@@ -1231,3 +1234,10 @@
 network={
 	key_mgmt=NONE
 }
+
+
+# Example config file that will only scan on channel 36.
+freq_list=5180
+network={
+	key_mgmt=NONE
+}
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index f96b245..c53421d 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -702,6 +702,8 @@
 	struct wpa_driver_associate_params *params);
 
 int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
+int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
+				    struct wpa_ssid *ssid);
 
 int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s);
 
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index cd51873..1a64df3 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -551,7 +551,7 @@
 
 
 static int wpa_supplicant_tdls_peer_addset(
-	void *ctx, const u8 *peer, int add, u16 capability,
+	void *ctx, const u8 *peer, int add, u16 aid, u16 capability,
 	const u8 *supp_rates, size_t supp_rates_len,
 	const struct ieee80211_ht_capabilities *ht_capab,
 	const struct ieee80211_vht_capabilities *vht_capab,
@@ -563,7 +563,7 @@
 	os_memset(&params, 0, sizeof(params));
 
 	params.addr = peer;
-	params.aid = 1;
+	params.aid = aid;
 	params.capability = capability;
 	params.flags = WPA_STA_TDLS_PEER | WPA_STA_AUTHORIZED;
 
diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c
index 9af6084..b376fb0 100644
--- a/wpa_supplicant/wps_supplicant.c
+++ b/wpa_supplicant/wps_supplicant.c
@@ -219,6 +219,80 @@
 }
 
 
+static void wpas_wps_remove_dup_network(struct wpa_supplicant *wpa_s,
+					struct wpa_ssid *new_ssid)
+{
+	struct wpa_ssid *ssid, *next;
+
+	for (ssid = wpa_s->conf->ssid, next = ssid ? ssid->next : NULL; ssid;
+	     ssid = next, next = ssid ? ssid->next : NULL) {
+		/*
+		 * new_ssid has already been added to the list in
+		 * wpas_wps_add_network(), so skip it.
+		 */
+		if (ssid == new_ssid)
+			continue;
+
+		if (ssid->bssid_set || new_ssid->bssid_set) {
+			if (ssid->bssid_set != new_ssid->bssid_set)
+				continue;
+			if (os_memcmp(ssid->bssid, new_ssid->bssid, ETH_ALEN) !=
+			    0)
+				continue;
+		}
+
+		/* compare SSID */
+		if (ssid->ssid_len == 0 || ssid->ssid_len != new_ssid->ssid_len)
+			continue;
+
+		if (ssid->ssid && new_ssid->ssid) {
+			if (os_memcmp(ssid->ssid, new_ssid->ssid,
+				      ssid->ssid_len) != 0)
+				continue;
+		} else if (ssid->ssid || new_ssid->ssid)
+			continue;
+
+		/* compare security parameters */
+		if (ssid->auth_alg != new_ssid->auth_alg ||
+		    ssid->key_mgmt != new_ssid->key_mgmt ||
+		    ssid->proto != new_ssid->proto ||
+		    ssid->pairwise_cipher != new_ssid->pairwise_cipher ||
+		    ssid->group_cipher != new_ssid->group_cipher)
+			continue;
+
+		if (ssid->passphrase && new_ssid->passphrase) {
+			if (os_strlen(ssid->passphrase) !=
+			    os_strlen(new_ssid->passphrase))
+				continue;
+			if (os_strcmp(ssid->passphrase, new_ssid->passphrase) !=
+			    0)
+				continue;
+		} else if (ssid->passphrase || new_ssid->passphrase)
+			continue;
+
+		if ((ssid->psk_set || new_ssid->psk_set) &&
+		    os_memcmp(ssid->psk, new_ssid->psk, sizeof(ssid->psk)) != 0)
+			continue;
+
+		if (ssid->auth_alg == WPA_ALG_WEP) {
+			if (ssid->wep_tx_keyidx != new_ssid->wep_tx_keyidx)
+				continue;
+			if (os_memcmp(ssid->wep_key, new_ssid->wep_key,
+				      sizeof(ssid->wep_key)))
+				continue;
+			if (os_memcmp(ssid->wep_key_len, new_ssid->wep_key_len,
+				      sizeof(ssid->wep_key_len)))
+				continue;
+		}
+
+		/* Remove the duplicated older network entry. */
+		wpa_printf(MSG_DEBUG, "Remove duplicate network %d", ssid->id);
+		wpas_notify_network_removed(wpa_s, ssid);
+		wpa_config_remove_network(wpa_s->conf, ssid->id);
+	}
+}
+
+
 static int wpa_supplicant_wps_cred(void *ctx,
 				   const struct wps_credential *cred)
 {
@@ -438,6 +512,8 @@
 	if (cred->ap_channel)
 		wpa_s->wps_ap_channel = cred->ap_channel;
 
+	wpas_wps_remove_dup_network(wpa_s, ssid);
+
 #ifndef CONFIG_NO_CONFIG_WRITE
 	if (wpa_s->conf->update_config &&
 	    wpa_config_write(wpa_s->confname, wpa_s->conf)) {