]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
AP: Handle AP initalization failure in async flow
authorTova Mussai <tova.mussai@intel.com>
Mon, 21 Aug 2017 16:42:19 +0000 (19:42 +0300)
committerJouni Malinen <j@w1.fi>
Thu, 19 Apr 2018 21:48:49 +0000 (00:48 +0300)
When AP initialization is completed in a callback (e.g., OBSS scan),
wpa_supplicant_deinit_ap() is not called in case of failure. Fix this by
calling 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
wpa_supplicant/ap.c

index 0b6db7bc28db2f73852fdf2c04da63bd4ed5a010..d2eb0441c417baf8c11d442f47b1665161cf1272 100644 (file)
@@ -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,
@@ -429,6 +431,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);
@@ -1779,6 +1783,20 @@ static void hostapd_owe_update_trans(struct hostapd_iface *iface)
 }
 
 
+static void hostapd_interface_setup_failure_handler(void *eloop_ctx,
+                                                   void *timeout_ctx)
+{
+       struct hostapd_iface *iface = eloop_ctx;
+       struct hostapd_data *hapd;
+
+       if (iface->num_bss < 1 || !iface->bss || !iface->bss[0])
+               return;
+       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)
 {
@@ -1979,8 +1997,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;
 }
 
index fe7ffe1bd69f2b8e5ac57e0770dfe0f6ee4e7499..9e4fc1c54063a918423473d3469cd00087edc284 100644 (file)
@@ -633,6 +633,13 @@ static void wpas_ap_configured_cb(void *ctx)
 {
        struct wpa_supplicant *wpa_s = ctx;
 
+       wpa_printf(MSG_DEBUG, "AP interface setup completed - 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;