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 <tova.mussai@intel.com>
This commit is contained in:
Tova Mussai 2017-08-21 19:42:19 +03:00 committed by Jouni Malinen
parent 86c998d37a
commit c4315e6620
2 changed files with 37 additions and 1 deletions

View 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 hostapd_broadcast_wep_clear(struct hostapd_data *hapd);
static int setup_interface2(struct hostapd_iface *iface); static int setup_interface2(struct hostapd_iface *iface);
static void channel_list_update_timeout(void *eloop_ctx, void *timeout_ctx); 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, 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); wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
eloop_cancel_timeout(channel_list_update_timeout, iface, NULL); 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_cleanup_iface_partial(iface);
hostapd_config_free(iface->conf); 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, static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
int err) int err)
{ {
@ -1979,8 +1997,19 @@ fail:
iface->fst = NULL; iface->fst = NULL;
} }
#endif /* CONFIG_FST */ #endif /* CONFIG_FST */
if (iface->interfaces && iface->interfaces->terminate_on_error)
if (iface->interfaces && iface->interfaces->terminate_on_error) {
eloop_terminate(); 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; return -1;
} }

View file

@ -633,6 +633,13 @@ static void wpas_ap_configured_cb(void *ctx)
{ {
struct wpa_supplicant *wpa_s = 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 #ifdef CONFIG_ACS
if (wpa_s->current_ssid && wpa_s->current_ssid->acs) { if (wpa_s->current_ssid && wpa_s->current_ssid->acs) {
wpa_s->assoc_freq = wpa_s->ap_iface->freq; wpa_s->assoc_freq = wpa_s->ap_iface->freq;