Cumulative patch from commit 10222ca19217b743687be311183f58a250d3a55f

10222ca Android: Sync Android.mk with Makefile
aebfbcb Android: Sync Android.mk with Makefile
890b3a4 Android: Sync Android.mk with Makefile
736abfc Android: Set proper path to keystore include dir
bbd84e5 Android: Add CONFIG_ACS option to makefile
5e42035 Android: Fix CONFIG_EAP_PROXY option and move it to right place
643fab3 Android: Add CONFIG_IEEE80211AC option to makefile
4ba8309 Android: Add CONFIG_EAP_UNAUTH_TLS option to makefile
53414a7 Android: Add liblog
1d415f1 Android: Switch keystore to binder
4e5a4d3 Android: Get rid of LOCAL_MODULE_TAGS := user
206d813 Android: Restore OpenSSL ENGINE support
6dfdb80 Android: Remove obsolete keystore path
1176ab6 Android: Use keystore ENGINE for private key operations
6dc94a6 Android: Use correct header file path for capability.h
91f9e60 GAS: Replenish AP station session timer to 5 seconds
e5e74e5 eloop: Add support for replenishing a registered timeout
b7997e0 Android: Remove obsolete WPA_UNICODE_SSID define
2d39a4d hostapd: Allow hostapd_cli to work on Android
1c6edec nl80211: Work around nl_socket_set_nonblocking on Android
c101bb9 hostapd: Add option to send OBSS scan params
60cdfd7 Android: Fix compilation without BOARD_WPA_SUPPLICANT_DRIVER
e40634e Prohibit PNO start during assoc process and in connect state
3526ff0 Android: Add ANDROID_P2P define under BOARD_WLAN_DEVICE
d0b2735 Android: Fix CFLAGS -> L_CFLAGS
9ec8766 P2P: Allow GO P2P Device Address to be used for scan result matching
83eefb4 P2P: Add debug print of P2P Group ID SSID
b6881b5 WPS NFC: Add more debug for NFC Password Token matching
67a88a7 WPS NFC: Add debug log entry on OOB Dev Pw attribute addition
08b2677 Interworking: Use SSID from the BSS entry
5058975 Interworking: Reject BSS based on disallow_aps
6ede8a7 Interworking: Avoid duplicated network blocks
d28f4e4 Interworking: Do not reconnect if already connected
5e1a456 hostapd: Do not start secondary BSS unless interface is enabled
36501a2 hostapd: Verify hostapd_setup_bss calls
54246f8 hostapd: Share a single function for BSS deinit
6d1ca81 Remove unused hostapd_cleanup_iface_pre()
747c85f hostapd: Add more debug prints to deinit path
6023a78 Restore hapd->interface_added tracking to core hostapd
486d2ff hostapd: Deinit ctrl_iface in case of add interface failure
8540e0b hostapd: Fix DETACH command debug prints to avoid use of freed memory
cdf3fb1 Fix removal of a BSS that has not yet been fully initialized
2f99d90 Remove all BSSs on removal of the first one
1493380 drivers: Do not call hostapd_logger()
1281c0a Remove a compiler warning from -O0 build

Change-Id: I0f4905d5310c51c9a4375d811a2e874651687d4f
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
index 8667221..93652d8 100644
--- a/wpa_supplicant/interworking.c
+++ b/wpa_supplicant/interworking.c
@@ -1,6 +1,6 @@
 /*
  * Interworking (IEEE 802.11u)
- * Copyright (c) 2011-2012, Qualcomm Atheros, Inc.
+ * Copyright (c) 2011-2013, Qualcomm Atheros, Inc.
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -19,6 +19,7 @@
 #include "eap_peer/eap.h"
 #include "eap_peer/eap_methods.h"
 #include "eapol_supp/eapol_supp_sm.h"
+#include "rsn_supp/wpa.h"
 #include "wpa_supplicant_i.h"
 #include "config.h"
 #include "config_ssid.h"
@@ -750,6 +751,59 @@
 #endif /* INTERWORKING_3GPP */
 
 
+static int already_connected(struct wpa_supplicant *wpa_s,
+			     struct wpa_cred *cred, struct wpa_bss *bss)
+{
+	struct wpa_ssid *ssid;
+
+	if (wpa_s->wpa_state < WPA_ASSOCIATED || wpa_s->current_ssid == NULL)
+		return 0;
+
+	ssid = wpa_s->current_ssid;
+	if (ssid->parent_cred != cred)
+		return 0;
+
+	if (ssid->ssid_len != bss->ssid_len ||
+	    os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) != 0)
+		return 0;
+
+	return 1;
+}
+
+
+static void remove_duplicate_network(struct wpa_supplicant *wpa_s,
+				     struct wpa_cred *cred,
+				     struct wpa_bss *bss)
+{
+	struct wpa_ssid *ssid;
+
+	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
+		if (ssid->parent_cred != cred)
+			continue;
+		if (ssid->ssid_len != bss->ssid_len ||
+		    os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) != 0)
+			continue;
+
+		break;
+	}
+
+	if (ssid == NULL)
+		return;
+
+	wpa_printf(MSG_DEBUG, "Interworking: Remove duplicate network entry for the same credential");
+
+	if (ssid == wpa_s->current_ssid) {
+		wpa_sm_set_config(wpa_s->wpa, NULL);
+		eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
+		wpa_supplicant_deauthenticate(wpa_s,
+					      WLAN_REASON_DEAUTH_LEAVING);
+	}
+
+	wpas_notify_network_removed(wpa_s, ssid);
+	wpa_config_remove_network(wpa_s->conf, ssid->id);
+}
+
+
 static int interworking_set_hs20_params(struct wpa_supplicant *wpa_s,
 					struct wpa_ssid *ssid)
 {
@@ -771,7 +825,6 @@
 {
 #ifdef INTERWORKING_3GPP
 	struct wpa_ssid *ssid;
-	const u8 *ie;
 	int eap_type;
 	int res;
 	char prefix;
@@ -779,12 +832,17 @@
 	if (bss->anqp == NULL || bss->anqp->anqp_3gpp == NULL)
 		return -1;
 
-	ie = wpa_bss_get_ie(bss, WLAN_EID_SSID);
-	if (ie == NULL)
-		return -1;
 	wpa_printf(MSG_DEBUG, "Interworking: Connect with " MACSTR " (3GPP)",
 		   MAC2STR(bss->bssid));
 
+	if (already_connected(wpa_s, cred, bss)) {
+		wpa_msg(wpa_s, MSG_INFO, INTERWORKING_ALREADY_CONNECTED MACSTR,
+			MAC2STR(bss->bssid));
+		return 0;
+	}
+
+	remove_duplicate_network(wpa_s, cred, bss);
+
 	ssid = wpa_config_add_network(wpa_s->conf);
 	if (ssid == NULL)
 		return -1;
@@ -794,11 +852,11 @@
 	wpa_config_set_network_defaults(ssid);
 	ssid->priority = cred->priority;
 	ssid->temporary = 1;
-	ssid->ssid = os_zalloc(ie[1] + 1);
+	ssid->ssid = os_zalloc(bss->ssid_len + 1);
 	if (ssid->ssid == NULL)
 		goto fail;
-	os_memcpy(ssid->ssid, ie + 2, ie[1]);
-	ssid->ssid_len = ie[1];
+	os_memcpy(ssid->ssid, bss->ssid, bss->ssid_len);
+	ssid->ssid_len = bss->ssid_len;
 
 	if (interworking_set_hs20_params(wpa_s, ssid) < 0)
 		goto fail;
@@ -1137,13 +1195,21 @@
 
 static int interworking_connect_roaming_consortium(
 	struct wpa_supplicant *wpa_s, struct wpa_cred *cred,
-	struct wpa_bss *bss, const u8 *ssid_ie)
+	struct wpa_bss *bss)
 {
 	struct wpa_ssid *ssid;
 
 	wpa_printf(MSG_DEBUG, "Interworking: Connect with " MACSTR " based on "
 		   "roaming consortium match", MAC2STR(bss->bssid));
 
+	if (already_connected(wpa_s, cred, bss)) {
+		wpa_msg(wpa_s, MSG_INFO, INTERWORKING_ALREADY_CONNECTED MACSTR,
+			MAC2STR(bss->bssid));
+		return 0;
+	}
+
+	remove_duplicate_network(wpa_s, cred, bss);
+
 	ssid = wpa_config_add_network(wpa_s->conf);
 	if (ssid == NULL)
 		return -1;
@@ -1152,11 +1218,11 @@
 	wpa_config_set_network_defaults(ssid);
 	ssid->priority = cred->priority;
 	ssid->temporary = 1;
-	ssid->ssid = os_zalloc(ssid_ie[1] + 1);
+	ssid->ssid = os_zalloc(bss->ssid_len + 1);
 	if (ssid->ssid == NULL)
 		goto fail;
-	os_memcpy(ssid->ssid, ssid_ie + 2, ssid_ie[1]);
-	ssid->ssid_len = ssid_ie[1];
+	os_memcpy(ssid->ssid, bss->ssid, bss->ssid_len);
+	ssid->ssid_len = bss->ssid_len;
 
 	if (interworking_set_hs20_params(wpa_s, ssid) < 0)
 		goto fail;
@@ -1193,13 +1259,12 @@
 	struct nai_realm_eap *eap = NULL;
 	u16 count, i;
 	char buf[100];
-	const u8 *ie;
 
 	if (wpa_s->conf->cred == NULL || bss == NULL)
 		return -1;
-	ie = wpa_bss_get_ie(bss, WLAN_EID_SSID);
-	if (ie == NULL || ie[1] == 0) {
-		wpa_printf(MSG_DEBUG, "Interworking: No SSID known for "
+	if (disallowed_bssid(wpa_s, bss->bssid) ||
+	    disallowed_ssid(wpa_s, bss->ssid, bss->ssid_len)) {
+		wpa_printf(MSG_DEBUG, "Interworking: Reject connection to disallowed BSS "
 			   MACSTR, MAC2STR(bss->bssid));
 		return -1;
 	}
@@ -1239,7 +1304,7 @@
 	    (cred == NULL || cred_rc->priority >= cred->priority) &&
 	    (cred_3gpp == NULL || cred_rc->priority >= cred_3gpp->priority))
 		return interworking_connect_roaming_consortium(wpa_s, cred_rc,
-							       bss, ie);
+							       bss);
 
 	if (cred_3gpp &&
 	    (cred == NULL || cred_3gpp->priority >= cred->priority)) {
@@ -1279,6 +1344,15 @@
 	wpa_printf(MSG_DEBUG, "Interworking: Connect with " MACSTR,
 		   MAC2STR(bss->bssid));
 
+	if (already_connected(wpa_s, cred, bss)) {
+		wpa_msg(wpa_s, MSG_INFO, INTERWORKING_ALREADY_CONNECTED MACSTR,
+			MAC2STR(bss->bssid));
+		nai_realm_free(realm, count);
+		return 0;
+	}
+
+	remove_duplicate_network(wpa_s, cred, bss);
+
 	ssid = wpa_config_add_network(wpa_s->conf);
 	if (ssid == NULL) {
 		nai_realm_free(realm, count);
@@ -1289,11 +1363,11 @@
 	wpa_config_set_network_defaults(ssid);
 	ssid->priority = cred->priority;
 	ssid->temporary = 1;
-	ssid->ssid = os_zalloc(ie[1] + 1);
+	ssid->ssid = os_zalloc(bss->ssid_len + 1);
 	if (ssid->ssid == NULL)
 		goto fail;
-	os_memcpy(ssid->ssid, ie + 2, ie[1]);
-	ssid->ssid_len = ie[1];
+	os_memcpy(ssid->ssid, bss->ssid, bss->ssid_len);
+	ssid->ssid_len = bss->ssid_len;
 
 	if (interworking_set_hs20_params(wpa_s, ssid) < 0)
 		goto fail;
@@ -1518,6 +1592,13 @@
 {
 	struct wpa_cred *cred, *cred2;
 
+	if (disallowed_bssid(wpa_s, bss->bssid) ||
+	    disallowed_ssid(wpa_s, bss->ssid, bss->ssid_len)) {
+		wpa_printf(MSG_DEBUG, "Interworking: Ignore disallowed BSS "
+			   MACSTR, MAC2STR(bss->bssid));
+		return NULL;
+	}
+
 	cred = interworking_credentials_available_realm(wpa_s, bss);
 	cred2 = interworking_credentials_available_3gpp(wpa_s, bss);
 	if (cred && cred2 && cred2->priority >= cred->priority)
@@ -1804,6 +1885,9 @@
 		ie = wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB);
 		if (ie == NULL || ie[1] < 4 || !(ie[5] & 0x80))
 			continue; /* AP does not support Interworking */
+		if (disallowed_bssid(wpa_s, bss->bssid) ||
+		    disallowed_ssid(wpa_s, bss->ssid, bss->ssid_len))
+			continue; /* Disallowed BSS */
 
 		if (!(bss->flags & WPA_BSS_ANQP_FETCH_TRIED)) {
 			if (bss->anqp == NULL) {