From c4315e66207ba948b87cc641ce982784efc7bb19 Mon Sep 17 00:00:00 2001 From: Tova Mussai Date: Mon, 21 Aug 2017 19:42:19 +0300 Subject: [PATCH] AP: Handle AP initalization failure in async flow 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 --- src/ap/hostapd.c | 31 ++++++++++++++++++++++++++++++- wpa_supplicant/ap.c | 7 +++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index 0b6db7bc2..d2eb0441c 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, @@ -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; } diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index fe7ffe1bd..9e4fc1c54 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -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;