Cumulative patch from commit efc64886b8a285440e9954b5395a5370d8c5f84f

efc6488 nl80211: Pass station supported channel and oper class info
3ed9727 TDLS: Pass peer's Supported channel and oper class info during sta_add
eed65aa hostapd: DFS setup seg0 correctly for HT40-
25592b2 hostapd: DFS/CSA check if CSA in progress
b19ef32 Android: Remove hostapd dump_file functionality
c48414a P2P: Limit join-a-group scans based on SSID from invitation
78f0c93 Flush secondary device types on FLUSH command
2b38410 P2P: Allow requested device type to be specified with p2p_find
d9bb282 Clear configuration blobs on FLUSH command
c60ba9f Skip network disabling on expected EAP failure
7185e16 EAP-FAST peer: Make debug clearer on missing pac_file configuration
7b88b64 EXT PW: Fix hash return in password fetching
08081ad hostapd: Skip full AP configuration validation on SET command
1785d2e P2P: Wait on GO Negotiation Confirm transmit
472fa21 P2P: Cancel action frame offchan wait after recv GO Neg Conf
bfdc2a3 bsd: Fix NULL pointer dereference on error path
38bbd06 bsd: Prepare event buffer on init process
3043b4f nl80211: Document how to configure for libnl 2.0 and 3.2

Change-Id: Ia592bc948eaa43dbfaf0b4a20231efca61acb11f
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/wpa_supplicant/README-P2P b/wpa_supplicant/README-P2P
index 08d39e2..7354bbf 100644
--- a/wpa_supplicant/README-P2P
+++ b/wpa_supplicant/README-P2P
@@ -72,7 +72,8 @@
 Device Discovery
 
 p2p_find [timeout in seconds] [type=<social|progressive>] \
-	[dev_id=<addr>] [delay=<search delay in ms>]
+	[dev_id=<addr>] [dev_type=<device type>] \
+	[delay=<search delay in ms>]
 
 The default behavior is to run a single full scan in the beginning and
 then scan only social channels. type=social will scan only social
@@ -87,6 +88,10 @@
 delay to be used between search iterations (e.g., to free up radio
 resources for concurrent operations).
 
+The optional dev_type option can be used to specify a single device type
+(primary or secondary) to search for, e.g.,
+"p2p_find dev_type=1-0050F204-1".
+
 p2p_listen [timeout in seconds]
 
 Start Listen-only state (become discoverable without searching for
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index 5301ed7..884acf6 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -1926,6 +1926,22 @@
 }
 
 
+void wpa_config_flush_blobs(struct wpa_config *config)
+{
+#ifndef CONFIG_NO_CONFIG_BLOBS
+	struct wpa_config_blob *blob, *prev;
+
+	blob = config->blobs;
+	config->blobs = NULL;
+	while (blob) {
+		prev = blob;
+		blob = blob->next;
+		wpa_config_free_blob(prev);
+	}
+#endif /* CONFIG_NO_CONFIG_BLOBS */
+}
+
+
 /**
  * wpa_config_free - Free configuration data
  * @config: Configuration data from wpa_config_read()
@@ -1935,9 +1951,6 @@
  */
 void wpa_config_free(struct wpa_config *config)
 {
-#ifndef CONFIG_NO_CONFIG_BLOBS
-	struct wpa_config_blob *blob, *prevblob;
-#endif /* CONFIG_NO_CONFIG_BLOBS */
 	struct wpa_ssid *ssid, *prev = NULL;
 	struct wpa_cred *cred, *cprev;
 
@@ -1955,15 +1968,7 @@
 		wpa_config_free_cred(cprev);
 	}
 
-#ifndef CONFIG_NO_CONFIG_BLOBS
-	blob = config->blobs;
-	prevblob = NULL;
-	while (blob) {
-		prevblob = blob;
-		blob = blob->next;
-		wpa_config_free_blob(prevblob);
-	}
-#endif /* CONFIG_NO_CONFIG_BLOBS */
+	wpa_config_flush_blobs(config);
 
 	wpabuf_free(config->wps_vendor_ext_m1);
 	os_free(config->ctrl_interface);
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index e24772d..a98a5aa 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -979,6 +979,7 @@
 			 struct wpa_config_blob *blob);
 void wpa_config_free_blob(struct wpa_config_blob *blob);
 int wpa_config_remove_blob(struct wpa_config *config, const char *name);
+void wpa_config_flush_blobs(struct wpa_config *config);
 
 struct wpa_cred * wpa_config_get_cred(struct wpa_config *config, int id);
 struct wpa_cred * wpa_config_add_cred(struct wpa_config *config);
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index cb299db..de97368 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -3652,6 +3652,7 @@
 	unsigned int timeout = atoi(cmd);
 	enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
 	u8 dev_id[ETH_ALEN], *_dev_id = NULL;
+	u8 dev_type[WPS_DEV_TYPE_LEN], *_dev_type = NULL;
 	char *pos;
 	unsigned int search_delay;
 
@@ -3668,6 +3669,14 @@
 		_dev_id = dev_id;
 	}
 
+	pos = os_strstr(cmd, "dev_type=");
+	if (pos) {
+		pos += 9;
+		if (wps_dev_type_str2bin(pos, dev_type) < 0)
+			return -1;
+		_dev_type = dev_type;
+	}
+
 	pos = os_strstr(cmd, "delay=");
 	if (pos) {
 		pos += 6;
@@ -3675,8 +3684,8 @@
 	} else
 		search_delay = wpas_p2p_search_delay(wpa_s);
 
-	return wpas_p2p_find(wpa_s, timeout, type, 0, NULL, _dev_id,
-			     search_delay);
+	return wpas_p2p_find(wpa_s, timeout, type, _dev_type != NULL, _dev_type,
+			     _dev_id, search_delay);
 }
 
 
@@ -5252,6 +5261,7 @@
 	wpas_p2p_service_flush(wpa_s);
 	wpa_s->global->p2p_disabled = 0;
 	wpa_s->global->p2p_per_sta_psk = 0;
+	wpa_s->conf->num_sec_device_types = 0;
 #endif /* CONFIG_P2P */
 
 #ifdef CONFIG_WPS_TESTING
@@ -5296,6 +5306,7 @@
 	wpa_s->extra_blacklist_count = 0;
 	wpa_supplicant_ctrl_iface_remove_network(wpa_s, "all");
 	wpa_supplicant_ctrl_iface_remove_cred(wpa_s, "all");
+	wpa_config_flush_blobs(wpa_s->conf);
 
 	wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 43200);
 	wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 70);
diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig
index 0627661..6684782 100644
--- a/wpa_supplicant/defconfig
+++ b/wpa_supplicant/defconfig
@@ -31,6 +31,19 @@
 # Driver interface for Linux drivers using the nl80211 kernel interface
 CONFIG_DRIVER_NL80211=y
 
+# driver_nl80211.c requires libnl. If you are compiling it yourself
+# you may need to point hostapd to your version of libnl.
+#
+#CFLAGS += -I$<path to libnl include files>
+#LIBS += -L$<path to libnl library files>
+
+# Use libnl v2.0 (or 3.0) libraries.
+#CONFIG_LIBNL20=y
+
+# Use libnl 3.2 libraries (if this is selected, CONFIG_LIBNL20 is ignored)
+#CONFIG_LIBNL32=y
+
+
 # Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
 #CONFIG_DRIVER_BSD=y
 #CFLAGS += -I/usr/local/include
diff --git a/wpa_supplicant/eapol_test.c b/wpa_supplicant/eapol_test.c
index cb71475..ac0ab0b 100644
--- a/wpa_supplicant/eapol_test.c
+++ b/wpa_supplicant/eapol_test.c
@@ -365,10 +365,11 @@
 }
 
 
-static void eapol_sm_cb(struct eapol_sm *eapol, int success, void *ctx)
+static void eapol_sm_cb(struct eapol_sm *eapol, enum eapol_supp_result result,
+			void *ctx)
 {
 	struct eapol_test_data *e = ctx;
-	printf("eapol_sm_cb: success=%d\n", success);
+	printf("eapol_sm_cb: result=%d\n", result);
 	e->eapol_test_num_reauths--;
 	if (e->eapol_test_num_reauths < 0)
 		eloop_terminate();
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 49c4058..fa265bc 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -2551,10 +2551,11 @@
 
 	wpa_supplicant_event_disassoc(wpa_s, reason_code, locally_generated);
 
-	if (reason_code == WLAN_REASON_IEEE_802_1X_AUTH_FAILED ||
-	    ((wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
-	      (wpa_s->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)) &&
-	     eapol_sm_failed(wpa_s->eapol)))
+	if (((reason_code == WLAN_REASON_IEEE_802_1X_AUTH_FAILED ||
+	      ((wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
+		(wpa_s->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)) &&
+	       eapol_sm_failed(wpa_s->eapol))) &&
+	     !wpa_s->eap_expected_failure))
 		wpas_auth_failed(wpa_s);
 
 #ifdef CONFIG_P2P
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 41d5102..3ac6713 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -104,11 +104,12 @@
 wpas_p2p_get_group_iface(struct wpa_supplicant *wpa_s, int addr_allocated,
 			 int go);
 static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s);
-static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq);
+static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq,
+				   const u8 *ssid, size_t ssid_len);
 static void wpas_p2p_join_scan(void *eloop_ctx, void *timeout_ctx);
 static int wpas_p2p_join(struct wpa_supplicant *wpa_s, const u8 *iface_addr,
 			 const u8 *dev_addr, enum p2p_wps_method wps_method,
-			 int auto_join);
+			 int auto_join, const u8 *ssid, size_t ssid_len);
 static int wpas_p2p_create_iface(struct wpa_supplicant *wpa_s);
 static void wpas_p2p_cross_connect_setup(struct wpa_supplicant *wpa_s);
 static void wpas_p2p_group_idle_timeout(void *eloop_ctx, void *timeout_ctx);
@@ -2868,7 +2869,8 @@
 
 	if (!persistent_group) {
 		wpa_printf(MSG_DEBUG, "P2P: Invitation from " MACSTR
-			   " to join an active group", MAC2STR(sa));
+			   " to join an active group (SSID: %s)",
+			   MAC2STR(sa), wpa_ssid_txt(ssid, ssid_len));
 		if (!is_zero_ether_addr(wpa_s->p2p_auth_invite) &&
 		    (os_memcmp(go_dev_addr, wpa_s->p2p_auth_invite, ETH_ALEN)
 		     == 0 ||
@@ -2991,8 +2993,8 @@
 
 	if (status == P2P_SC_SUCCESS) {
 		wpa_printf(MSG_DEBUG, "P2P: Invitation from peer " MACSTR
-			   " was accepted; op_freq=%d MHz",
-			   MAC2STR(sa), op_freq);
+			   " was accepted; op_freq=%d MHz, SSID=%s",
+			   MAC2STR(sa), op_freq, wpa_ssid_txt(ssid, ssid_len));
 		if (s) {
 			int go = s->mode == WPAS_MODE_P2P_GO;
 			wpas_p2p_group_add_persistent(
@@ -3001,7 +3003,8 @@
 		} else if (bssid) {
 			wpa_s->user_initiated_pd = 0;
 			wpas_p2p_join(wpa_s, bssid, go_dev_addr,
-				      wpa_s->p2p_wps_method, 0);
+				      wpa_s->p2p_wps_method, 0,
+				      ssid, ssid_len);
 		}
 		return;
 	}
@@ -4037,7 +4040,7 @@
 static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s,
 				   struct wpa_scan_results *scan_res)
 {
-	struct wpa_bss *bss;
+	struct wpa_bss *bss = NULL;
 	int freq;
 	u8 iface_addr[ETH_ALEN];
 
@@ -4069,7 +4072,7 @@
 					   MAC2STR(wpa_s->
 						   pending_join_dev_addr),
 					   freq);
-				wpas_p2p_join_scan_req(wpa_s, freq);
+				wpas_p2p_join_scan_req(wpa_s, freq, NULL, 0);
 				return;
 			}
 		}
@@ -4142,7 +4145,22 @@
 		wpa_printf(MSG_DEBUG, "P2P: Target GO operating frequency "
 			   "from P2P peer table: %d MHz", freq);
 	}
-	bss = wpa_bss_get_bssid_latest(wpa_s, wpa_s->pending_join_iface_addr);
+	if (wpa_s->p2p_join_ssid_len) {
+		wpa_printf(MSG_DEBUG, "P2P: Trying to find target GO BSS entry based on BSSID "
+			   MACSTR " and SSID %s",
+			   MAC2STR(wpa_s->pending_join_iface_addr),
+			   wpa_ssid_txt(wpa_s->p2p_join_ssid,
+					wpa_s->p2p_join_ssid_len));
+		bss = wpa_bss_get(wpa_s, wpa_s->pending_join_iface_addr,
+				  wpa_s->p2p_join_ssid,
+				  wpa_s->p2p_join_ssid_len);
+	}
+	if (!bss) {
+		wpa_printf(MSG_DEBUG, "P2P: Trying to find target GO BSS entry based on BSSID "
+			   MACSTR, MAC2STR(wpa_s->pending_join_iface_addr));
+		bss = wpa_bss_get_bssid_latest(wpa_s,
+					       wpa_s->pending_join_iface_addr);
+	}
 	if (bss) {
 		freq = bss->freq;
 		wpa_printf(MSG_DEBUG, "P2P: Target GO operating frequency "
@@ -4219,7 +4237,8 @@
 }
 
 
-static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq)
+static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq,
+				   const u8 *ssid, size_t ssid_len)
 {
 	int ret;
 	struct wpa_driver_scan_params params;
@@ -4241,8 +4260,16 @@
 
 	/* P2P Wildcard SSID */
 	params.num_ssids = 1;
-	params.ssids[0].ssid = (u8 *) P2P_WILDCARD_SSID;
-	params.ssids[0].ssid_len = P2P_WILDCARD_SSID_LEN;
+	if (ssid && ssid_len) {
+		params.ssids[0].ssid = ssid;
+		params.ssids[0].ssid_len = ssid_len;
+		os_memcpy(wpa_s->p2p_join_ssid, ssid, ssid_len);
+		wpa_s->p2p_join_ssid_len = ssid_len;
+	} else {
+		params.ssids[0].ssid = (u8 *) P2P_WILDCARD_SSID;
+		params.ssids[0].ssid_len = P2P_WILDCARD_SSID_LEN;
+		wpa_s->p2p_join_ssid_len = 0;
+	}
 
 	wpa_s->wps->dev.p2p = 1;
 	wps_ie = wps_build_probe_req_ie(DEV_PW_DEFAULT, &wpa_s->wps->dev,
@@ -4299,18 +4326,22 @@
 static void wpas_p2p_join_scan(void *eloop_ctx, void *timeout_ctx)
 {
 	struct wpa_supplicant *wpa_s = eloop_ctx;
-	wpas_p2p_join_scan_req(wpa_s, 0);
+	wpas_p2p_join_scan_req(wpa_s, 0, NULL, 0);
 }
 
 
 static int wpas_p2p_join(struct wpa_supplicant *wpa_s, const u8 *iface_addr,
 			 const u8 *dev_addr, enum p2p_wps_method wps_method,
-			 int auto_join)
+			 int auto_join, const u8 *ssid, size_t ssid_len)
 {
 	wpa_printf(MSG_DEBUG, "P2P: Request to join existing group (iface "
 		   MACSTR " dev " MACSTR ")%s",
 		   MAC2STR(iface_addr), MAC2STR(dev_addr),
 		   auto_join ? " (auto_join)" : "");
+	if (ssid && ssid_len) {
+		wpa_printf(MSG_DEBUG, "P2P: Group SSID specified: %s",
+			   wpa_ssid_txt(ssid, ssid_len));
+	}
 
 	wpa_s->p2p_auto_pd = 0;
 	wpa_s->p2p_auto_join = !!auto_join;
@@ -4322,7 +4353,7 @@
 	wpas_p2p_stop_find(wpa_s);
 
 	wpa_s->p2p_join_scan_count = 0;
-	wpas_p2p_join_scan(wpa_s, NULL);
+	wpas_p2p_join_scan_req(wpa_s, 0, ssid, ssid_len);
 	return 0;
 }
 
@@ -4577,7 +4608,7 @@
 		}
 		wpa_s->user_initiated_pd = 1;
 		if (wpas_p2p_join(wpa_s, iface_addr, dev_addr, wps_method,
-				  auto_join) < 0)
+				  auto_join, NULL, 0) < 0)
 			return -1;
 		return ret;
 	}
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 187e5d9..78e2749 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -1410,6 +1410,7 @@
 
 	os_memset(&params, 0, sizeof(params));
 	wpa_s->reassociate = 0;
+	wpa_s->eap_expected_failure = 0;
 	if (bss && !wpas_driver_bss_selection(wpa_s)) {
 #ifdef CONFIG_IEEE80211R
 		const u8 *ie, *md = NULL;
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index d1ea77b..3a28534 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -571,6 +571,7 @@
 	struct os_reltime pending_eapol_rx_time;
 	u8 pending_eapol_rx_src[ETH_ALEN];
 	unsigned int last_eapol_matches_bssid:1;
+	unsigned int eap_expected_failure:1;
 
 	struct ibss_rsn *ibss_rsn;
 
@@ -669,6 +670,8 @@
 	u8 pending_join_iface_addr[ETH_ALEN];
 	u8 pending_join_dev_addr[ETH_ALEN];
 	int pending_join_wps_method;
+	u8 p2p_join_ssid[32];
+	size_t p2p_join_ssid_len;
 	int p2p_join_scan_count;
 	int auto_pd_scan_retry;
 	int force_long_sd;
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index ab6cdca..ad0895b 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -216,20 +216,38 @@
 }
 
 
-static void wpa_supplicant_eapol_cb(struct eapol_sm *eapol, int success,
+static const char * result_str(enum eapol_supp_result result)
+{
+	switch (result) {
+	case EAPOL_SUPP_RESULT_FAILURE:
+		return "FAILURE";
+	case EAPOL_SUPP_RESULT_SUCCESS:
+		return "SUCCESS";
+	case EAPOL_SUPP_RESULT_EXPECTED_FAILURE:
+		return "EXPECTED_FAILURE";
+	}
+	return "?";
+}
+
+
+static void wpa_supplicant_eapol_cb(struct eapol_sm *eapol,
+				    enum eapol_supp_result result,
 				    void *ctx)
 {
 	struct wpa_supplicant *wpa_s = ctx;
 	int res, pmk_len;
 	u8 pmk[PMK_LEN];
 
-	wpa_printf(MSG_DEBUG, "EAPOL authentication completed %ssuccessfully",
-		   success ? "" : "un");
+	wpa_printf(MSG_DEBUG, "EAPOL authentication completed - result=%s",
+		   result_str(result));
 
 	if (wpas_wps_eapol_cb(wpa_s) > 0)
 		return;
 
-	if (!success) {
+	wpa_s->eap_expected_failure = result ==
+		EAPOL_SUPP_RESULT_EXPECTED_FAILURE;
+
+	if (result != EAPOL_SUPP_RESULT_SUCCESS) {
 		/*
 		 * Make sure we do not get stuck here waiting for long EAPOL
 		 * timeout if the AP does not disconnect in case of
@@ -238,7 +256,8 @@
 		wpa_supplicant_req_auth_timeout(wpa_s, 2, 0);
 	}
 
-	if (!success || !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
+	if (result != EAPOL_SUPP_RESULT_SUCCESS ||
+	    !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
 		return;
 
 	if (!wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt))
@@ -560,7 +579,9 @@
 	const u8 *supp_rates, size_t supp_rates_len,
 	const struct ieee80211_ht_capabilities *ht_capab,
 	const struct ieee80211_vht_capabilities *vht_capab,
-	u8 qosinfo, const u8 *ext_capab, size_t ext_capab_len)
+	u8 qosinfo, const u8 *ext_capab, size_t ext_capab_len,
+	const u8 *supp_channels, size_t supp_channels_len,
+	const u8 *supp_oper_classes, size_t supp_oper_classes_len)
 {
 	struct wpa_supplicant *wpa_s = ctx;
 	struct hostapd_sta_add_params params;
@@ -588,6 +609,10 @@
 	params.set = !add;
 	params.ext_capab = ext_capab;
 	params.ext_capab_len = ext_capab_len;
+	params.supp_channels = supp_channels;
+	params.supp_channels_len = supp_channels_len;
+	params.supp_oper_classes = supp_oper_classes;
+	params.supp_oper_classes_len = supp_oper_classes_len;
 
 	return wpa_drv_sta_add(wpa_s, &params);
 }