]> git.ipfire.org Git - thirdparty/hostap.git/blobdiff - hostapd/main.c
tests: sigma_dut controlled AP and transition disabled indication
[thirdparty/hostap.git] / hostapd / main.c
index db2a455824555b078eb49434fb1f1603b81c05a7..4af8e8f9c7aeeecbaa6e625ed5a55f71fb2acfd2 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * hostapd / main()
- * Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
 #include "crypto/random.h"
 #include "crypto/tls.h"
 #include "common/version.h"
+#include "common/dpp.h"
 #include "drivers/driver.h"
 #include "eap_server/eap.h"
 #include "eap_server/tncs.h"
 #include "ap/hostapd.h"
 #include "ap/ap_config.h"
 #include "ap/ap_drv_ops.h"
+#include "ap/dpp_hostapd.h"
+#include "fst/fst.h"
 #include "config_file.h"
 #include "eap_register.h"
 #include "ctrl_iface.h"
@@ -78,9 +81,6 @@ static void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module,
        case HOSTAPD_MODULE_DRIVER:
                module_str = "DRIVER";
                break;
-       case HOSTAPD_MODULE_IAPP:
-               module_str = "IAPP";
-               break;
        case HOSTAPD_MODULE_MLME:
                module_str = "MLME";
                break;
@@ -92,19 +92,25 @@ static void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module,
        if (hapd && hapd->conf && addr)
                os_snprintf(format, maxlen, "%s: STA " MACSTR "%s%s: %s",
                            hapd->conf->iface, MAC2STR(addr),
-                           module_str ? " " : "", module_str, txt);
+                           module_str ? " " : "", module_str ? module_str : "",
+                           txt);
        else if (hapd && hapd->conf)
                os_snprintf(format, maxlen, "%s:%s%s %s",
                            hapd->conf->iface, module_str ? " " : "",
-                           module_str, txt);
+                           module_str ? module_str : "", txt);
        else if (addr)
                os_snprintf(format, maxlen, "STA " MACSTR "%s%s: %s",
                            MAC2STR(addr), module_str ? " " : "",
-                           module_str, txt);
+                           module_str ? module_str : "", txt);
        else
                os_snprintf(format, maxlen, "%s%s%s",
-                           module_str, module_str ? ": " : "", txt);
+                           module_str ? module_str : "",
+                           module_str ? ": " : "", txt);
 
+#ifdef CONFIG_DEBUG_SYSLOG
+       if (wpa_debug_syslog)
+               conf_stdout = 0;
+#endif /* CONFIG_DEBUG_SYSLOG */
        if ((conf_stdout & module) && level >= conf_stdout_level) {
                wpa_debug_print_timestamp();
                wpa_printf(MSG_INFO, "%s", format);
@@ -168,7 +174,8 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
 
                if (global.drv_priv[i] == NULL &&
                    wpa_drivers[i]->global_init) {
-                       global.drv_priv[i] = wpa_drivers[i]->global_init();
+                       global.drv_priv[i] =
+                               wpa_drivers[i]->global_init(iface->interfaces);
                        if (global.drv_priv[i] == NULL) {
                                wpa_printf(MSG_ERROR, "Failed to initialize "
                                           "driver '%s'",
@@ -182,9 +189,7 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
        }
        params.bssid = b;
        params.ifname = hapd->conf->iface;
-       params.ssid = hapd->conf->ssid.ssid;
-       params.ssid_len = hapd->conf->ssid.ssid_len;
-       params.test_socket = hapd->conf->test_socket;
+       params.driver_params = hapd->iconf->driver_params;
        params.use_pae_group_addr = hapd->conf->use_pae_group_addr;
 
        params.num_bridge = hapd->iface->num_bss;
@@ -210,12 +215,30 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
 
        if (hapd->driver->get_capa &&
            hapd->driver->get_capa(hapd->drv_priv, &capa) == 0) {
+               struct wowlan_triggers *triggs;
+
                iface->drv_flags = capa.flags;
                iface->probe_resp_offloads = capa.probe_resp_offloads;
+               /*
+                * Use default extended capa values from per-radio information
+                */
                iface->extended_capa = capa.extended_capa;
                iface->extended_capa_mask = capa.extended_capa_mask;
                iface->extended_capa_len = capa.extended_capa_len;
                iface->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
+
+               /*
+                * Override extended capa with per-interface type (AP), if
+                * available from the driver.
+                */
+               hostapd_get_ext_capa(iface);
+
+               triggs = wpa_get_wowlan_triggers(conf->wowlan_triggers, &capa);
+               if (triggs && hapd->driver->set_wowlan) {
+                       if (hapd->driver->set_wowlan(hapd->drv_priv, triggs))
+                               wpa_printf(MSG_ERROR, "set_wowlan failed");
+               }
+               os_free(triggs);
        }
 
        return 0;
@@ -227,19 +250,25 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
  *
  * This function is used to parse configuration file for a full interface (one
  * or more BSSes sharing the same radio) and allocate memory for the BSS
- * interfaces. No actiual driver operations are started.
+ * interfaces. No actual driver operations are started.
  */
 static struct hostapd_iface *
-hostapd_interface_init(struct hapd_interfaces *interfaces,
+hostapd_interface_init(struct hapd_interfaces *interfaces, const char *if_name,
                       const char *config_fname, int debug)
 {
        struct hostapd_iface *iface;
        int k;
 
-       wpa_printf(MSG_ERROR, "Configuration file: %s", config_fname);
+       wpa_printf(MSG_DEBUG, "Configuration file: %s", config_fname);
        iface = hostapd_init(interfaces, config_fname);
        if (!iface)
                return NULL;
+
+       if (if_name) {
+               os_strlcpy(iface->conf->bss[0]->iface, if_name,
+                          sizeof(iface->conf->bss[0]->iface));
+       }
+
        iface->interfaces = interfaces;
 
        for (k = 0; k < debug; k++) {
@@ -249,7 +278,8 @@ hostapd_interface_init(struct hapd_interfaces *interfaces,
 
        if (iface->conf->bss[0]->iface[0] == '\0' &&
            !hostapd_drv_none(iface->bss[0])) {
-               wpa_printf(MSG_ERROR, "Interface name not specified in %s",
+               wpa_printf(MSG_ERROR,
+                          "Interface name not specified in %s, nor by '-i' parameter",
                           config_fname);
                hostapd_interface_deinit_free(iface);
                return NULL;
@@ -318,6 +348,7 @@ static int hostapd_global_init(struct hapd_interfaces *interfaces,
                wpa_printf(MSG_ERROR, "Failed to initialize event loop");
                return -1;
        }
+       interfaces->eloop_initialized = 1;
 
        random_init(entropy_file);
 
@@ -345,7 +376,7 @@ static int hostapd_global_init(struct hapd_interfaces *interfaces,
 }
 
 
-static void hostapd_global_deinit(const char *pid_file)
+static void hostapd_global_deinit(const char *pid_file, int eloop_initialized)
 {
        int i;
 
@@ -363,7 +394,8 @@ static void hostapd_global_deinit(const char *pid_file)
 
        random_deinit();
 
-       eloop_destroy();
+       if (eloop_initialized)
+               eloop_destroy();
 
 #ifndef CONFIG_NATIVE_WINDOWS
        closelog();
@@ -397,9 +429,16 @@ static int hostapd_global_run(struct hapd_interfaces *ifaces, int daemonize,
        }
 #endif /* EAP_SERVER_TNC */
 
-       if (daemonize && os_daemonize(pid_file)) {
-               perror("daemon");
-               return -1;
+       if (daemonize) {
+               if (os_daemonize(pid_file)) {
+                       wpa_printf(MSG_ERROR, "daemon: %s", strerror(errno));
+                       return -1;
+               }
+               if (eloop_sock_requeue()) {
+                       wpa_printf(MSG_ERROR, "eloop_sock_requeue: %s",
+                                  strerror(errno));
+                       return -1;
+               }
        }
 
        eloop_run();
@@ -411,11 +450,12 @@ static int hostapd_global_run(struct hapd_interfaces *ifaces, int daemonize,
 static void show_version(void)
 {
        fprintf(stderr,
-               "hostapd v" VERSION_STR "\n"
+               "hostapd v%s\n"
                "User space daemon for IEEE 802.11 AP management,\n"
                "IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n"
-               "Copyright (c) 2002-2014, Jouni Malinen <j@w1.fi> "
-               "and contributors\n");
+               "Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi> "
+               "and contributors\n",
+               VERSION_STR);
 }
 
 
@@ -426,7 +466,8 @@ static void usage(void)
                "\n"
                "usage: hostapd [-hdBKtv] [-P <PID file>] [-e <entropy file>] "
                "\\\n"
-               "         [-g <global ctrl_iface>] [-G <group>] \\\n"
+               "         [-g <global ctrl_iface>] [-G <group>]\\\n"
+               "         [-i <comma-separated list of interface names>]\\\n"
                "         <configuration file(s)>\n"
                "\n"
                "options:\n"
@@ -442,9 +483,14 @@ static void usage(void)
                "   -f   log output to debug file instead of stdout\n"
 #endif /* CONFIG_DEBUG_FILE */
 #ifdef CONFIG_DEBUG_LINUX_TRACING
-               "   -T = record to Linux tracing in addition to logging\n"
+               "   -T   record to Linux tracing in addition to logging\n"
                "        (records all messages regardless of debug verbosity)\n"
 #endif /* CONFIG_DEBUG_LINUX_TRACING */
+               "   -i   list of interface names to use\n"
+#ifdef CONFIG_DEBUG_SYSLOG
+               "   -s   log output to syslog instead of stdout\n"
+#endif /* CONFIG_DEBUG_SYSLOG */
+               "   -S   start all the interfaces synchronously\n"
                "   -t   include timestamps in some debug messages\n"
                "   -v   show hostapd version\n");
 
@@ -455,9 +501,8 @@ static void usage(void)
 static const char * hostapd_msg_ifname_cb(void *ctx)
 {
        struct hostapd_data *hapd = ctx;
-       if (hapd && hapd->iconf && hapd->iconf->bss &&
-           hapd->iconf->num_bss > 0 && hapd->iconf->bss[0])
-               return hapd->iconf->bss[0]->iface;
+       if (hapd && hapd->conf)
+               return hapd->conf->iface;
        return NULL;
 }
 
@@ -465,11 +510,16 @@ static const char * hostapd_msg_ifname_cb(void *ctx)
 static int hostapd_get_global_ctrl_iface(struct hapd_interfaces *interfaces,
                                         const char *path)
 {
+#ifndef CONFIG_CTRL_IFACE_UDP
        char *pos;
+#endif /* !CONFIG_CTRL_IFACE_UDP */
+
        os_free(interfaces->global_iface_path);
        interfaces->global_iface_path = os_strdup(path);
        if (interfaces->global_iface_path == NULL)
                return -1;
+
+#ifndef CONFIG_CTRL_IFACE_UDP
        pos = os_strrchr(interfaces->global_iface_path, '/');
        if (pos == NULL) {
                wpa_printf(MSG_ERROR, "No '/' in the global control interface "
@@ -481,6 +531,7 @@ static int hostapd_get_global_ctrl_iface(struct hapd_interfaces *interfaces,
 
        *pos = '\0';
        interfaces->global_iface_name = pos + 1;
+#endif /* !CONFIG_CTRL_IFACE_UDP */
 
        return 0;
 }
@@ -502,6 +553,43 @@ static int hostapd_get_ctrl_iface_group(struct hapd_interfaces *interfaces,
 }
 
 
+static int hostapd_get_interface_names(char ***if_names,
+                                      size_t *if_names_size,
+                                      char *arg)
+{
+       char *if_name, *tmp, **nnames;
+       size_t i;
+
+       if (!arg)
+               return -1;
+       if_name = strtok_r(arg, ",", &tmp);
+
+       while (if_name) {
+               nnames = os_realloc_array(*if_names, 1 + *if_names_size,
+                                         sizeof(char *));
+               if (!nnames)
+                       goto fail;
+               *if_names = nnames;
+
+               (*if_names)[*if_names_size] = os_strdup(if_name);
+               if (!(*if_names)[*if_names_size])
+                       goto fail;
+               (*if_names_size)++;
+               if_name = strtok_r(NULL, ",", &tmp);
+       }
+
+       return 0;
+
+fail:
+       for (i = 0; i < *if_names_size; i++)
+               os_free((*if_names)[i]);
+       os_free(*if_names);
+       *if_names = NULL;
+       *if_names_size = 0;
+       return -1;
+}
+
+
 #ifdef CONFIG_WPS
 static int gen_uuid(const char *txt_addr)
 {
@@ -523,6 +611,28 @@ static int gen_uuid(const char *txt_addr)
 #endif /* CONFIG_WPS */
 
 
+#ifndef HOSTAPD_CLEANUP_INTERVAL
+#define HOSTAPD_CLEANUP_INTERVAL 10
+#endif /* HOSTAPD_CLEANUP_INTERVAL */
+
+static int hostapd_periodic_call(struct hostapd_iface *iface, void *ctx)
+{
+       hostapd_periodic_iface(iface);
+       return 0;
+}
+
+
+/* Periodic cleanup tasks */
+static void hostapd_periodic(void *eloop_ctx, void *timeout_ctx)
+{
+       struct hapd_interfaces *interfaces = eloop_ctx;
+
+       eloop_register_timeout(HOSTAPD_CLEANUP_INTERVAL, 0,
+                              hostapd_periodic, interfaces, NULL);
+       hostapd_for_each_interface(interfaces, hostapd_periodic_call, NULL);
+}
+
+
 int main(int argc, char *argv[])
 {
        struct hapd_interfaces interfaces;
@@ -537,6 +647,12 @@ int main(int argc, char *argv[])
 #ifdef CONFIG_DEBUG_LINUX_TRACING
        int enable_trace_dbg = 0;
 #endif /* CONFIG_DEBUG_LINUX_TRACING */
+       int start_ifaces_in_sync = 0;
+       char **if_names = NULL;
+       size_t if_names_size = 0;
+#ifdef CONFIG_DPP
+       struct dpp_global_config dpp_conf;
+#endif /* CONFIG_DPP */
 
        if (os_program_init())
                return -1;
@@ -551,9 +667,20 @@ int main(int argc, char *argv[])
        interfaces.global_iface_path = NULL;
        interfaces.global_iface_name = NULL;
        interfaces.global_ctrl_sock = -1;
+       dl_list_init(&interfaces.global_ctrl_dst);
+#ifdef CONFIG_ETH_P_OUI
+       dl_list_init(&interfaces.eth_p_oui);
+#endif /* CONFIG_ETH_P_OUI */
+#ifdef CONFIG_DPP
+       os_memset(&dpp_conf, 0, sizeof(dpp_conf));
+       /* TODO: dpp_conf.msg_ctx? */
+       interfaces.dpp = dpp_global_init(&dpp_conf);
+       if (!interfaces.dpp)
+               return -1;
+#endif /* CONFIG_DPP */
 
        for (;;) {
-               c = getopt(argc, argv, "b:Bde:f:hKP:Ttu:vg:G:");
+               c = getopt(argc, argv, "b:Bde:f:hi:KP:sSTtu:vg:G:");
                if (c < 0)
                        break;
                switch (c) {
@@ -610,10 +737,23 @@ int main(int argc, char *argv[])
                        bss_config = tmp_bss;
                        bss_config[num_bss_configs++] = optarg;
                        break;
+#ifdef CONFIG_DEBUG_SYSLOG
+               case 's':
+                       wpa_debug_syslog = 1;
+                       break;
+#endif /* CONFIG_DEBUG_SYSLOG */
+               case 'S':
+                       start_ifaces_in_sync = 1;
+                       break;
 #ifdef CONFIG_WPS
                case 'u':
                        return gen_uuid(optarg);
 #endif /* CONFIG_WPS */
+               case 'i':
+                       if (hostapd_get_interface_names(&if_names,
+                                                       &if_names_size, optarg))
+                               goto out;
+                       break;
                default:
                        usage();
                        break;
@@ -628,6 +768,12 @@ int main(int argc, char *argv[])
 
        if (log_file)
                wpa_debug_open_file(log_file);
+       if (!log_file && !wpa_debug_syslog)
+               wpa_debug_setup_stdout();
+#ifdef CONFIG_DEBUG_SYSLOG
+       if (wpa_debug_syslog)
+               wpa_debug_open_syslog();
+#endif /* CONFIG_DEBUG_SYSLOG */
 #ifdef CONFIG_DEBUG_LINUX_TRACING
        if (enable_trace_dbg) {
                int tret = wpa_debug_open_linux_tracing();
@@ -649,19 +795,41 @@ int main(int argc, char *argv[])
        }
 
        if (hostapd_global_init(&interfaces, entropy_file)) {
-               wpa_printf(MSG_ERROR, "Failed to initilize global context");
+               wpa_printf(MSG_ERROR, "Failed to initialize global context");
                return -1;
        }
 
+       eloop_register_timeout(HOSTAPD_CLEANUP_INTERVAL, 0,
+                              hostapd_periodic, &interfaces, NULL);
+
+       if (fst_global_init()) {
+               wpa_printf(MSG_ERROR,
+                          "Failed to initialize global FST context");
+               goto out;
+       }
+
+#if defined(CONFIG_FST) && defined(CONFIG_CTRL_IFACE)
+       if (!fst_global_add_ctrl(fst_ctrl_cli))
+               wpa_printf(MSG_WARNING, "Failed to add CLI FST ctrl");
+#endif /* CONFIG_FST && CONFIG_CTRL_IFACE */
+
        /* Allocate and parse configuration for full interface files */
        for (i = 0; i < interfaces.count; i++) {
+               char *if_name = NULL;
+
+               if (i < if_names_size)
+                       if_name = if_names[i];
+
                interfaces.iface[i] = hostapd_interface_init(&interfaces,
+                                                            if_name,
                                                             argv[optind + i],
                                                             debug);
                if (!interfaces.iface[i]) {
                        wpa_printf(MSG_ERROR, "Failed to initialize interface");
                        goto out;
                }
+               if (start_ifaces_in_sync)
+                       interfaces.iface[i]->need_to_start_in_sync = 1;
        }
 
        /* Allocate and parse configuration for per-BSS files */
@@ -727,19 +895,38 @@ int main(int argc, char *argv[])
  out:
        hostapd_global_ctrl_iface_deinit(&interfaces);
        /* Deinitialize all interfaces */
-       for (i = 0; i < interfaces.count; i++)
+       for (i = 0; i < interfaces.count; i++) {
+               if (!interfaces.iface[i])
+                       continue;
+               interfaces.iface[i]->driver_ap_teardown =
+                       !!(interfaces.iface[i]->drv_flags &
+                          WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT);
                hostapd_interface_deinit_free(interfaces.iface[i]);
+       }
        os_free(interfaces.iface);
 
-       hostapd_global_deinit(pid_file);
+#ifdef CONFIG_DPP
+       dpp_global_deinit(interfaces.dpp);
+#endif /* CONFIG_DPP */
+
+       if (interfaces.eloop_initialized)
+               eloop_cancel_timeout(hostapd_periodic, &interfaces, NULL);
+       hostapd_global_deinit(pid_file, interfaces.eloop_initialized);
        os_free(pid_file);
 
+       wpa_debug_close_syslog();
        if (log_file)
                wpa_debug_close_file();
        wpa_debug_close_linux_tracing();
 
        os_free(bss_config);
 
+       for (i = 0; i < if_names_size; i++)
+               os_free(if_names[i]);
+       os_free(if_names);
+
+       fst_global_deinit();
+
        os_program_deinit();
 
        return ret;