diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index c21c8a017..d6865bb7d 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -747,6 +747,36 @@ static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd, } +static int hostapd_ctrl_iface_enable(struct hostapd_iface *iface) +{ + if (hostapd_enable_iface(iface) < 0) { + wpa_printf(MSG_ERROR, "Enabling of interface failed"); + return -1; + } + return 0; +} + + +static int hostapd_ctrl_iface_reload(struct hostapd_iface *iface) +{ + if (hostapd_reload_iface(iface) < 0) { + wpa_printf(MSG_ERROR, "Reloading of interface failed"); + return -1; + } + return 0; +} + + +static int hostapd_ctrl_iface_disable(struct hostapd_iface *iface) +{ + if (hostapd_disable_iface(iface) < 0) { + wpa_printf(MSG_ERROR, "Disabling of interface failed"); + return -1; + } + return 0; +} + + static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx, void *sock_ctx) { @@ -899,6 +929,15 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx, } else if (os_strncmp(buf, "GET ", 4) == 0) { reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply, reply_size); + } else if (os_strncmp(buf, "ENABLE", 6) == 0) { + if (hostapd_ctrl_iface_enable(hapd->iface)) + reply_len = -1; + } else if (os_strncmp(buf, "RELOAD", 6) == 0) { + if (hostapd_ctrl_iface_reload(hapd->iface)) + reply_len = -1; + } else if (os_strncmp(buf, "DISABLE", 7) == 0) { + if (hostapd_ctrl_iface_disable(hapd->iface)) + reply_len = -1; } else { os_memcpy(reply, "UNKNOWN COMMAND\n", 16); reply_len = 16; diff --git a/hostapd/main.c b/hostapd/main.c index 94b90beb2..d6c914a9f 100644 --- a/hostapd/main.c +++ b/hostapd/main.c @@ -279,21 +279,6 @@ static int hostapd_driver_init(struct hostapd_iface *iface) } -static void hostapd_interface_deinit_free(struct hostapd_iface *iface) -{ - const struct wpa_driver_ops *driver; - void *drv_priv; - if (iface == NULL) - return; - driver = iface->bss[0]->driver; - drv_priv = iface->bss[0]->drv_priv; - hostapd_interface_deinit(iface); - if (driver && driver->hapd_deinit && drv_priv) - driver->hapd_deinit(drv_priv); - hostapd_interface_free(iface); -} - - static struct hostapd_iface * hostapd_interface_init(struct hapd_interfaces *interfaces, const char *config_fname, int debug) @@ -565,6 +550,7 @@ int main(int argc, char *argv[]) interfaces.for_each_interface = hostapd_for_each_interface; interfaces.ctrl_iface_init = hostapd_ctrl_iface_init; interfaces.ctrl_iface_deinit = hostapd_ctrl_iface_deinit; + interfaces.driver_init = hostapd_driver_init; interfaces.global_iface_path = NULL; interfaces.global_iface_name = NULL; interfaces.global_ctrl_sock = -1; diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index 9c0bd9b69..35ceb02b6 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -1048,6 +1048,108 @@ void hostapd_interface_free(struct hostapd_iface *iface) } +#ifdef HOSTAPD + +void hostapd_interface_deinit_free(struct hostapd_iface *iface) +{ + const struct wpa_driver_ops *driver; + void *drv_priv; + if (iface == NULL) + return; + driver = iface->bss[0]->driver; + drv_priv = iface->bss[0]->drv_priv; + hostapd_interface_deinit(iface); + if (driver && driver->hapd_deinit && drv_priv) + driver->hapd_deinit(drv_priv); + hostapd_interface_free(iface); +} + + +int hostapd_enable_iface(struct hostapd_iface *hapd_iface) +{ + if (hapd_iface->bss[0]->drv_priv != NULL) { + wpa_printf(MSG_ERROR, "Interface %s already enabled", + hapd_iface->conf->bss[0].iface); + return -1; + } + + wpa_printf(MSG_DEBUG, "Enable interface %s", + hapd_iface->conf->bss[0].iface); + + if (hapd_iface->interfaces == NULL || + hapd_iface->interfaces->driver_init == NULL || + hapd_iface->interfaces->driver_init(hapd_iface) || + hostapd_setup_interface(hapd_iface)) { + hostapd_interface_deinit_free(hapd_iface); + return -1; + } + return 0; +} + + +int hostapd_reload_iface(struct hostapd_iface *hapd_iface) +{ + size_t j; + + wpa_printf(MSG_DEBUG, "Reload interface %s", + hapd_iface->conf->bss[0].iface); + for (j = 0; j < hapd_iface->num_bss; j++) { + hostapd_flush_old_stations(hapd_iface->bss[j], + WLAN_REASON_PREV_AUTH_NOT_VALID); + +#ifndef CONFIG_NO_RADIUS + /* TODO: update dynamic data based on changed configuration + * items (e.g., open/close sockets, etc.) */ + radius_client_flush(hapd_iface->bss[j]->radius, 0); +#endif /* CONFIG_NO_RADIUS */ + + hostapd_reload_bss(hapd_iface->bss[j]); + } + return 0; +} + + +int hostapd_disable_iface(struct hostapd_iface *hapd_iface) +{ + size_t j; + struct hostapd_bss_config *bss = hapd_iface->bss[0]->conf; + const struct wpa_driver_ops *driver; + void *drv_priv; + + if (hapd_iface == NULL) + return -1; + driver = hapd_iface->bss[0]->driver; + drv_priv = hapd_iface->bss[0]->drv_priv; + + /* whatever hostapd_interface_deinit does */ + for (j = 0; j < hapd_iface->num_bss; j++) { + struct hostapd_data *hapd = hapd_iface->bss[j]; + hostapd_free_stas(hapd); + hostapd_flush_old_stations(hapd, WLAN_REASON_DEAUTH_LEAVING); + hostapd_clear_wep(hapd); + hostapd_free_hapd_data(hapd); + } + + if (driver && driver->hapd_deinit && drv_priv) { + driver->hapd_deinit(drv_priv); + hapd_iface->bss[0]->drv_priv = NULL; + } + + /* From hostapd_cleanup_iface: These were initialized in + * hostapd_setup_interface and hostapd_setup_interface_complete + */ + hostapd_cleanup_iface_partial(hapd_iface); + bss->wpa = 0; + bss->wpa_key_mgmt = -1; + bss->wpa_pairwise = -1; + + wpa_printf(MSG_DEBUG, "Interface %s disabled", bss->iface); + return 0; +} + +#endif /* HOSTAPD */ + + /** * hostapd_new_assoc_sta - Notify that a new station associated with the AP * @hapd: Pointer to BSS data diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h index 3b79e1286..2c348322c 100644 --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h @@ -33,6 +33,7 @@ struct hapd_interfaces { int (*for_each_interface)(struct hapd_interfaces *interfaces, int (*cb)(struct hostapd_iface *iface, void *ctx), void *ctx); + int (*driver_init)(struct hostapd_iface *iface); size_t count; int global_ctrl_sock; @@ -269,6 +270,10 @@ void hostapd_interface_deinit(struct hostapd_iface *iface); void hostapd_interface_free(struct hostapd_iface *iface); void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta, int reassoc); +void hostapd_interface_deinit_free(struct hostapd_iface *iface); +int hostapd_enable_iface(struct hostapd_iface *hapd_iface); +int hostapd_reload_iface(struct hostapd_iface *hapd_iface); +int hostapd_disable_iface(struct hostapd_iface *hapd_iface); /* utils.c */ int hostapd_register_probereq_cb(struct hostapd_data *hapd,