[1/2] AP: handle AP initalization failure in async flow

Message ID 1503333740-15176-1-git-send-email-andrei.otcheretianski@intel.com
State New
Headers show

Commit Message

Otcheretianski, Andrei Aug. 21, 2017, 4:42 p.m.
From: Tova Mussai <tova.mussai@intel.com>

When AP initialization is complete in a callback (e.g., OBSS scan),
wpa_supplicant_deinit_ap is not called in case of failure.
Fix this, by calling the setup_complete_cb in case of failure too, which
in turn calls wpa_supplicant_deinit_ap if needed.

Signed-off-by: Tova Mussai <tova.mussai@intel.com>
---
 src/ap/hostapd.c    | 28 +++++++++++++++++++++++++++-
 wpa_supplicant/ap.c |  7 +++++++
 2 files changed, 34 insertions(+), 1 deletion(-)

Patch

diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 270e818..821d583 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -56,6 +56,8 @@  static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd);
 static int hostapd_broadcast_wep_clear(struct hostapd_data *hapd);
 static int setup_interface2(struct hostapd_iface *iface);
 static void channel_list_update_timeout(void *eloop_ctx, void *timeout_ctx);
+static void hostapd_interface_setup_failure_handler(void *eloop_ctx,
+						    void *timeout_ctx);
 
 
 int hostapd_for_each_interface(struct hapd_interfaces *interfaces,
@@ -426,6 +428,8 @@  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);
+	eloop_cancel_timeout(hostapd_interface_setup_failure_handler, iface,
+			     NULL);
 
 	hostapd_cleanup_iface_partial(iface);
 	hostapd_config_free(iface->conf);
@@ -1680,6 +1684,17 @@  static void hostapd_set_own_neighbor_report(struct hostapd_data *hapd)
 }
 
 
+static void hostapd_interface_setup_failure_handler(void *eloop_ctx,
+						    void *timeout_ctx)
+{
+	struct hostapd_iface *iface = eloop_ctx;
+	struct hostapd_data *hapd = iface->bss[0];
+
+	if (hapd->setup_complete_cb)
+		hapd->setup_complete_cb(hapd->setup_complete_cb_ctx);
+}
+
+
 static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
 						 int err)
 {
@@ -1879,8 +1894,19 @@  fail:
 		iface->fst = NULL;
 	}
 #endif /* CONFIG_FST */
-	if (iface->interfaces && iface->interfaces->terminate_on_error)
+
+	if (iface->interfaces && iface->interfaces->terminate_on_error) {
 		eloop_terminate();
+	} else if (hapd->setup_complete_cb) {
+		/*
+		 * Calling hapd->setup_complete_cb directly may cause iface
+		 * deinitialization which may be accessed later by the caller.
+		 */
+		eloop_register_timeout(0, 0,
+				       hostapd_interface_setup_failure_handler,
+				       iface, NULL);
+	}
+
 	return -1;
 }
 
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index 3fc8e94..b044150 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -612,6 +612,13 @@  static void wpas_ap_configured_cb(void *ctx)
 {
 	struct wpa_supplicant *wpa_s = ctx;
 
+	wpa_printf(MSG_INFO, "ap_iface state %s",
+		   hostapd_state_text(wpa_s->ap_iface->state));
+	if (wpa_s->ap_iface->state == HAPD_IFACE_DISABLED) {
+		wpa_supplicant_ap_deinit(wpa_s);
+		return;
+	}
+
 #ifdef CONFIG_ACS
 	if (wpa_s->current_ssid && wpa_s->current_ssid->acs)
 		wpa_s->assoc_freq = wpa_s->ap_iface->freq;