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/src/ap/ap_config.h b/src/ap/ap_config.h
index 8b73724..09b2778 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -530,6 +530,7 @@
 	int ieee80211n;
 	int secondary_channel;
 	int require_ht;
+	int obss_interval;
 	u32 vht_capab;
 	int ieee80211ac;
 	int require_vht;
diff --git a/src/ap/gas_serv.c b/src/ap/gas_serv.c
index b3574ba..8349c4d 100644
--- a/src/ap/gas_serv.c
+++ b/src/ap/gas_serv.c
@@ -46,6 +46,8 @@
 		 * it to be that long.
 		 */
 		ap_sta_session_timeout(hapd, sta, 5);
+	} else {
+		ap_sta_replenish_timeout(hapd, sta, 5);
 	}
 
 	if (sta->gas_dialog == NULL) {
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 52be311..60224cc 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -243,6 +243,7 @@
 
 static void hostapd_free_hapd_data(struct hostapd_data *hapd)
 {
+	wpa_printf(MSG_DEBUG, "%s(%s)", __func__, hapd->conf->iface);
 	iapp_deinit(hapd->iapp);
 	hapd->iapp = NULL;
 	accounting_deinit(hapd);
@@ -260,7 +261,8 @@
 
 	authsrv_deinit(hapd);
 
-	if (hostapd_if_remove(hapd, WPA_IF_AP_BSS, hapd->conf->iface)) {
+	if (hapd->interface_added &&
+	    hostapd_if_remove(hapd, WPA_IF_AP_BSS, hapd->conf->iface)) {
 		wpa_printf(MSG_WARNING, "Failed to remove BSS interface %s",
 			   hapd->conf->iface);
 	}
@@ -293,34 +295,24 @@
  * @hapd: Pointer to BSS data
  *
  * This function is used to free all per-BSS data structures and resources.
- * This gets called in a loop for each BSS between calls to
- * hostapd_cleanup_iface_pre() and hostapd_cleanup_iface() when an interface
- * is deinitialized. Most of the modules that are initialized in
- * hostapd_setup_bss() are deinitialized here.
+ * Most of the modules that are initialized in hostapd_setup_bss() are
+ * deinitialized here.
  */
 static void hostapd_cleanup(struct hostapd_data *hapd)
 {
+	wpa_printf(MSG_DEBUG, "%s(hapd=%p (%s))", __func__, hapd,
+		   hapd->conf->iface);
 	if (hapd->iface->interfaces &&
 	    hapd->iface->interfaces->ctrl_iface_deinit)
 		hapd->iface->interfaces->ctrl_iface_deinit(hapd);
 	hostapd_free_hapd_data(hapd);
-}
-
-
-/**
- * hostapd_cleanup_iface_pre - Preliminary per-interface cleanup
- * @iface: Pointer to interface data
- *
- * This function is called before per-BSS data structures are deinitialized
- * with hostapd_cleanup().
- */
-static void hostapd_cleanup_iface_pre(struct hostapd_iface *iface)
-{
+	hapd->started = 0;
 }
 
 
 static void hostapd_cleanup_iface_partial(struct hostapd_iface *iface)
 {
+	wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
 	hostapd_free_hw_features(iface->hw_features, iface->num_hw_features);
 	iface->hw_features = NULL;
 	os_free(iface->current_rates);
@@ -340,6 +332,7 @@
  */
 static void hostapd_cleanup_iface(struct hostapd_iface *iface)
 {
+	wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
 	eloop_cancel_timeout(channel_list_update_timeout, iface, NULL);
 
 	hostapd_cleanup_iface_partial(iface);
@@ -348,6 +341,7 @@
 
 	os_free(iface->config_fname);
 	os_free(iface->bss);
+	wpa_printf(MSG_DEBUG, "%s: free iface=%p", __func__, iface);
 	os_free(iface);
 }
 
@@ -629,6 +623,16 @@
 	char force_ifname[IFNAMSIZ];
 	u8 if_addr[ETH_ALEN];
 
+	wpa_printf(MSG_DEBUG, "%s(hapd=%p (%s), first=%d)",
+		   __func__, hapd, hapd->conf->iface, first);
+
+	if (hapd->started) {
+		wpa_printf(MSG_ERROR, "%s: Interface %s was already started",
+			   __func__, hapd->conf->iface);
+		return -1;
+	}
+	hapd->started = 1;
+
 	if (!first || first == -1) {
 		if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0) {
 			/* Allocate the next available BSSID. */
@@ -649,6 +653,7 @@
 			}
 		}
 
+		hapd->interface_added = 1;
 		if (hostapd_if_add(hapd->iface->bss[0], WPA_IF_AP_BSS,
 				   hapd->conf->iface, hapd->own_addr, hapd,
 				   &hapd->drv_priv, force_ifname, if_addr,
@@ -1259,32 +1264,42 @@
 }
 
 
+static void hostapd_bss_deinit(struct hostapd_data *hapd)
+{
+	wpa_printf(MSG_DEBUG, "%s: deinit bss %s", __func__,
+		   hapd->conf->iface);
+	hostapd_free_stas(hapd);
+	hostapd_flush_old_stations(hapd, WLAN_REASON_DEAUTH_LEAVING);
+	hostapd_clear_wep(hapd);
+	hostapd_cleanup(hapd);
+}
+
+
 void hostapd_interface_deinit(struct hostapd_iface *iface)
 {
 	int j;
 
+	wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
 	if (iface == NULL)
 		return;
 
 	eloop_cancel_timeout(channel_list_update_timeout, iface, NULL);
 	iface->wait_channel_update = 0;
 
-	hostapd_cleanup_iface_pre(iface);
-	for (j = iface->num_bss - 1; j >= 0; j--) {
-		struct hostapd_data *hapd = iface->bss[j];
-		hostapd_free_stas(hapd);
-		hostapd_flush_old_stations(hapd, WLAN_REASON_DEAUTH_LEAVING);
-		hostapd_clear_wep(hapd);
-		hostapd_cleanup(hapd);
-	}
+	for (j = iface->num_bss - 1; j >= 0; j--)
+		hostapd_bss_deinit(iface->bss[j]);
 }
 
 
 void hostapd_interface_free(struct hostapd_iface *iface)
 {
 	size_t j;
-	for (j = 0; j < iface->num_bss; j++)
+	wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
+	for (j = 0; j < iface->num_bss; j++) {
+		wpa_printf(MSG_DEBUG, "%s: free hapd %p",
+			   __func__, iface->bss[j]);
 		os_free(iface->bss[j]);
+	}
 	hostapd_cleanup_iface(iface);
 }
 
@@ -1344,6 +1359,8 @@
 	if (hapd_iface) {
 		os_free(hapd_iface->config_fname);
 		os_free(hapd_iface->bss);
+		wpa_printf(MSG_DEBUG, "%s: free iface %p",
+			   __func__, hapd_iface);
 		os_free(hapd_iface);
 	}
 	return NULL;
@@ -1488,11 +1505,18 @@
 {
 	const struct wpa_driver_ops *driver;
 	void *drv_priv;
+
+	wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
 	if (iface == NULL)
 		return;
+	wpa_printf(MSG_DEBUG, "%s: num_bss=%u conf->num_bss=%u",
+		   __func__, (unsigned int) iface->num_bss,
+		   (unsigned int) iface->conf->num_bss);
 	driver = iface->bss[0]->driver;
 	drv_priv = iface->bss[0]->drv_priv;
 	hostapd_interface_deinit(iface);
+	wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit",
+		   __func__, driver, drv_priv);
 	if (driver && driver->hapd_deinit && drv_priv)
 		driver->hapd_deinit(drv_priv);
 	hostapd_interface_free(iface);
@@ -1521,6 +1545,8 @@
 
 		driver = hapd_iface->bss[0]->driver;
 		drv_priv = hapd_iface->bss[0]->drv_priv;
+		wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit",
+			   __func__, driver, drv_priv);
 		if (driver && driver->hapd_deinit && drv_priv) {
 			driver->hapd_deinit(drv_priv);
 			hapd_iface->bss[0]->drv_priv = NULL;
@@ -1573,6 +1599,8 @@
 		hostapd_free_hapd_data(hapd);
 	}
 
+	wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit",
+		   __func__, driver, drv_priv);
 	if (driver && driver->hapd_deinit && drv_priv) {
 		driver->hapd_deinit(drv_priv);
 		hapd_iface->bss[0]->drv_priv = NULL;
@@ -1740,9 +1768,12 @@
 				  ETH_ALEN);
 
 			if (start_ctrl_iface_bss(hapd) < 0 ||
-			    hostapd_setup_bss(hapd, -1)) {
+			    (hapd_iface->state == HAPD_IFACE_ENABLED &&
+			     hostapd_setup_bss(hapd, -1))) {
 				hapd_iface->conf->num_bss--;
 				hapd_iface->num_bss--;
+				wpa_printf(MSG_DEBUG, "%s: free hapd %p %s",
+					   __func__, hapd, hapd->conf->iface);
 				os_free(hapd);
 				return -1;
 			}
@@ -1806,10 +1837,21 @@
 		hostapd_config_free(conf);
 	if (hapd_iface) {
 		if (hapd_iface->bss) {
-			for (i = 0; i < hapd_iface->num_bss; i++)
+			for (i = 0; i < hapd_iface->num_bss; i++) {
+				hapd = hapd_iface->bss[i];
+				if (hapd && hapd_iface->interfaces &&
+				    hapd_iface->interfaces->ctrl_iface_deinit)
+					hapd_iface->interfaces->
+						ctrl_iface_deinit(hapd);
+				wpa_printf(MSG_DEBUG, "%s: free hapd %p (%s)",
+					   __func__, hapd_iface->bss[i],
+					hapd_iface->bss[i]->conf->iface);
 				os_free(hapd_iface->bss[i]);
+			}
 			os_free(hapd_iface->bss);
 		}
+		wpa_printf(MSG_DEBUG, "%s: free iface %p",
+			   __func__, hapd_iface);
 		os_free(hapd_iface);
 	}
 	return -1;
@@ -1818,27 +1860,31 @@
 
 static int hostapd_remove_bss(struct hostapd_iface *iface, unsigned int idx)
 {
-	struct hostapd_data *hapd;
 	size_t i;
 
-	if (idx > iface->num_bss || idx > iface->conf->num_bss)
-		return -1;
-	hapd = iface->bss[idx];
-	wpa_printf(MSG_INFO, "Remove BSS '%s'", hapd->conf->iface);
+	wpa_printf(MSG_INFO, "Remove BSS '%s'", iface->conf->bss[idx]->iface);
 
-	hostapd_free_stas(hapd);
-	hostapd_flush_old_stations(hapd, WLAN_REASON_DEAUTH_LEAVING);
-	hostapd_clear_wep(hapd);
-	hostapd_cleanup(hapd);
-	hostapd_config_free_bss(hapd->conf);
-	os_free(hapd);
+	/* Remove hostapd_data only if it has already been initialized */
+	if (idx < iface->num_bss) {
+		struct hostapd_data *hapd = iface->bss[idx];
 
-	iface->num_bss--;
-	for (i = idx; i < iface->num_bss; i++)
-		iface->bss[i] = iface->bss[i + 1];
+		hostapd_bss_deinit(hapd);
+		wpa_printf(MSG_DEBUG, "%s: free hapd %p (%s)",
+			   __func__, hapd, hapd->conf->iface);
+		hostapd_config_free_bss(hapd->conf);
+		os_free(hapd);
+
+		iface->num_bss--;
+
+		for (i = idx; i < iface->num_bss; i++)
+			iface->bss[i] = iface->bss[i + 1];
+	} else {
+		hostapd_config_free_bss(iface->conf->bss[idx]);
+		iface->conf->bss[idx] = NULL;
+	}
 
 	iface->conf->num_bss--;
-	for (i = idx; i < iface->num_bss; i++)
+	for (i = idx; i < iface->conf->num_bss; i++)
 		iface->conf->bss[i] = iface->conf->bss[i + 1];
 
 	return 0;
@@ -1854,8 +1900,7 @@
 		hapd_iface = interfaces->iface[i];
 		if (hapd_iface == NULL)
 			return -1;
-		if (hapd_iface->conf->num_bss == 1 &&
-		    !os_strcmp(hapd_iface->conf->bss[0]->iface, buf)) {
+		if (!os_strcmp(hapd_iface->conf->bss[0]->iface, buf)) {
 			wpa_printf(MSG_INFO, "Remove interface '%s'", buf);
 			hostapd_interface_deinit_free(hapd_iface);
 			k = i;
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index adb3728..1887531 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -101,6 +101,8 @@
 	struct hostapd_iface *iface;
 	struct hostapd_config *iconf;
 	struct hostapd_bss_config *conf;
+	int interface_added; /* virtual interface added for this BSS */
+	unsigned int started:1;
 
 	u8 own_addr[ETH_ALEN];
 
diff --git a/src/ap/ieee802_11_ht.c b/src/ap/ieee802_11_ht.c
index 6483e1c..2d53648 100644
--- a/src/ap/ieee802_11_ht.c
+++ b/src/ap/ieee802_11_ht.c
@@ -50,6 +50,22 @@
 
  	pos += sizeof(*cap);
 
+	if (hapd->iconf->obss_interval) {
+		struct ieee80211_obss_scan_parameters *scan_params;
+
+		*pos++ = WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS;
+		*pos++ = sizeof(*scan_params);
+
+		scan_params = (struct ieee80211_obss_scan_parameters *) pos;
+		os_memset(scan_params, 0, sizeof(*scan_params));
+		scan_params->width_trigger_scan_interval =
+			host_to_le16(hapd->iconf->obss_interval);
+
+		/* TODO: Fill in more parameters (supplicant ignores them) */
+
+		pos += sizeof(*scan_params);
+	}
+
 	return pos;
 }
 
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index 016b9b6..a6775f3 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -490,6 +490,18 @@
 }
 
 
+void ap_sta_replenish_timeout(struct hostapd_data *hapd, struct sta_info *sta,
+			      u32 session_timeout)
+{
+	if (eloop_replenish_timeout(session_timeout, 0,
+				    ap_handle_session_timer, hapd, sta)) {
+		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
+			       HOSTAPD_LEVEL_DEBUG, "setting session timeout "
+			       "to %d seconds", session_timeout);
+	}
+}
+
+
 void ap_sta_session_timeout(struct hostapd_data *hapd, struct sta_info *sta,
 			    u32 session_timeout)
 {
diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
index 197e46b..dc74219 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -162,6 +162,8 @@
 void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta);
 void hostapd_free_stas(struct hostapd_data *hapd);
 void ap_handle_timer(void *eloop_ctx, void *timeout_ctx);
+void ap_sta_replenish_timeout(struct hostapd_data *hapd, struct sta_info *sta,
+			      u32 session_timeout);
 void ap_sta_session_timeout(struct hostapd_data *hapd, struct sta_info *sta,
 			    u32 session_timeout);
 void ap_sta_no_session_timeout(struct hostapd_data *hapd,
diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c
index eb300f1..294a39d 100644
--- a/src/ap/wps_hostapd.c
+++ b/src/ap/wps_hostapd.c
@@ -1211,6 +1211,7 @@
 static void hostapd_wps_nfc_clear(struct wps_context *wps)
 {
 #ifdef CONFIG_WPS_NFC
+	wpa_printf(MSG_DEBUG, "WPS: Clear NFC Tag context %p", wps);
 	wps->ap_nfc_dev_pw_id = 0;
 	wpabuf_free(wps->ap_nfc_dh_pubkey);
 	wps->ap_nfc_dh_pubkey = NULL;
@@ -1823,6 +1824,9 @@
 		return -1;
 
 	hostapd_wps_nfc_clear(wps);
+	wpa_printf(MSG_DEBUG,
+		   "WPS: Enable NFC Tag (Dev Pw Id %u) for AP interface %s (context %p)",
+		   hapd->conf->wps_nfc_dev_pw_id, hapd->conf->iface, wps);
 	wps->ap_nfc_dev_pw_id = hapd->conf->wps_nfc_dev_pw_id;
 	wps->ap_nfc_dh_pubkey = wpabuf_dup(hapd->conf->wps_nfc_dh_pubkey);
 	wps->ap_nfc_dh_privkey = wpabuf_dup(hapd->conf->wps_nfc_dh_privkey);
@@ -1849,6 +1853,8 @@
 
 void hostapd_wps_nfc_token_disable(struct hostapd_data *hapd)
 {
+	wpa_printf(MSG_DEBUG, "WPS: Disable NFC token for AP interface %s",
+		   hapd->conf->iface);
 	hostapd_wps_nfc_clear(hapd->wps);
 }