summaryrefslogtreecommitdiff
path: root/hostapd/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'hostapd/main.c')
-rw-r--r--hostapd/main.c226
1 files changed, 159 insertions, 67 deletions
diff --git a/hostapd/main.c b/hostapd/main.c
index 9c532d4cce6e3..56f00023bea82 100644
--- a/hostapd/main.c
+++ b/hostapd/main.c
@@ -1,15 +1,9 @@
/*
* hostapd / main()
- * Copyright (c) 2002-2010, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "utils/includes.h"
@@ -19,6 +13,7 @@
#include "utils/common.h"
#include "utils/eloop.h"
+#include "crypto/random.h"
#include "crypto/tls.h"
#include "common/version.h"
#include "drivers/driver.h"
@@ -26,6 +21,7 @@
#include "eap_server/tncs.h"
#include "ap/hostapd.h"
#include "ap/ap_config.h"
+#include "ap/ap_drv_ops.h"
#include "config_file.h"
#include "eap_register.h"
#include "dump_state.h"
@@ -36,28 +32,15 @@ extern int wpa_debug_level;
extern int wpa_debug_show_keys;
extern int wpa_debug_timestamp;
+extern struct wpa_driver_ops *wpa_drivers[];
-struct hapd_interfaces {
- size_t count;
- struct hostapd_iface **iface;
-};
-
-
-static int hostapd_for_each_interface(struct hapd_interfaces *interfaces,
- int (*cb)(struct hostapd_iface *iface,
- void *ctx), void *ctx)
-{
- size_t i;
- int ret;
- for (i = 0; i < interfaces->count; i++) {
- ret = cb(interfaces->iface[i], ctx);
- if (ret)
- return ret;
- }
+struct hapd_global {
+ void **drv_priv;
+ size_t drv_count;
+};
- return 0;
-}
+static struct hapd_global global;
#ifndef CONFIG_NO_HOSTAPD_LOGGER
@@ -183,14 +166,9 @@ static struct hostapd_iface * hostapd_init(const char *config_file)
if (hapd_iface == NULL)
goto fail;
- hapd_iface->reload_config = hostapd_reload_config;
- hapd_iface->config_read_cb = hostapd_config_read;
hapd_iface->config_fname = os_strdup(config_file);
if (hapd_iface->config_fname == NULL)
goto fail;
- hapd_iface->ctrl_iface_init = hostapd_ctrl_iface_init;
- hapd_iface->ctrl_iface_deinit = hostapd_ctrl_iface_deinit;
- hapd_iface->for_each_interface = hostapd_for_each_interface;
conf = hostapd_config_read(hapd_iface->config_fname);
if (conf == NULL)
@@ -198,7 +176,7 @@ static struct hostapd_iface * hostapd_init(const char *config_file)
hapd_iface->conf = conf;
hapd_iface->num_bss = conf->num_bss;
- hapd_iface->bss = os_zalloc(conf->num_bss *
+ hapd_iface->bss = os_calloc(conf->num_bss,
sizeof(struct hostapd_data *));
if (hapd_iface->bss == NULL)
goto fail;
@@ -233,6 +211,7 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
struct hostapd_data *hapd = iface->bss[0];
struct hostapd_bss_config *conf = hapd->conf;
u8 *b = conf->bssid;
+ struct wpa_driver_capa capa;
if (hapd->driver == NULL || hapd->driver->hapd_init == NULL) {
wpa_printf(MSG_ERROR, "No hostapd driver wrapper available");
@@ -244,15 +223,33 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
b = NULL;
os_memset(&params, 0, sizeof(params));
+ for (i = 0; wpa_drivers[i]; i++) {
+ if (wpa_drivers[i] != hapd->driver)
+ continue;
+
+ if (global.drv_priv[i] == NULL &&
+ wpa_drivers[i]->global_init) {
+ global.drv_priv[i] = wpa_drivers[i]->global_init();
+ if (global.drv_priv[i] == NULL) {
+ wpa_printf(MSG_ERROR, "Failed to initialize "
+ "driver '%s'",
+ wpa_drivers[i]->name);
+ return -1;
+ }
+ }
+
+ params.global_priv = global.drv_priv[i];
+ break;
+ }
params.bssid = b;
params.ifname = hapd->conf->iface;
- params.ssid = (const u8 *) hapd->conf->ssid.ssid;
+ params.ssid = hapd->conf->ssid.ssid;
params.ssid_len = hapd->conf->ssid.ssid_len;
params.test_socket = hapd->conf->test_socket;
params.use_pae_group_addr = hapd->conf->use_pae_group_addr;
params.num_bridge = hapd->iface->num_bss;
- params.bridge = os_zalloc(hapd->iface->num_bss * sizeof(char *));
+ params.bridge = os_calloc(hapd->iface->num_bss, sizeof(char *));
if (params.bridge == NULL)
return -1;
for (i = 0; i < hapd->iface->num_bss; i++) {
@@ -272,22 +269,13 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
return -1;
}
- return 0;
-}
-
+ if (hapd->driver->get_capa &&
+ hapd->driver->get_capa(hapd->drv_priv, &capa) == 0) {
+ iface->drv_flags = capa.flags;
+ iface->probe_resp_offloads = capa.probe_resp_offloads;
+ }
-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)
- driver->hapd_deinit(drv_priv);
- hostapd_interface_free(iface);
+ return 0;
}
@@ -309,10 +297,13 @@ hostapd_interface_init(struct hapd_interfaces *interfaces,
iface->bss[0]->conf->logger_stdout_level--;
}
- if (hostapd_driver_init(iface) ||
- hostapd_setup_interface(iface)) {
- hostapd_interface_deinit_free(iface);
- return NULL;
+ if (iface->conf->bss[0].iface[0] != 0 ||
+ hostapd_drv_none(iface->bss[0])) {
+ if (hostapd_driver_init(iface) ||
+ hostapd_setup_interface(iface)) {
+ hostapd_interface_deinit_free(iface);
+ return NULL;
+ }
}
return iface;
@@ -363,8 +354,13 @@ static void handle_dump_state(int sig, void *signal_ctx)
#endif /* CONFIG_NATIVE_WINDOWS */
-static int hostapd_global_init(struct hapd_interfaces *interfaces)
+static int hostapd_global_init(struct hapd_interfaces *interfaces,
+ const char *entropy_file)
{
+ int i;
+
+ os_memset(&global, 0, sizeof(global));
+
hostapd_logger_register_cb(hostapd_logger_cb);
if (eap_server_register_methods()) {
@@ -377,6 +373,8 @@ static int hostapd_global_init(struct hapd_interfaces *interfaces)
return -1;
}
+ random_init(entropy_file);
+
#ifndef CONFIG_NATIVE_WINDOWS
eloop_register_signal(SIGHUP, handle_reload, interfaces);
eloop_register_signal(SIGUSR1, handle_dump_state, interfaces);
@@ -387,16 +385,38 @@ static int hostapd_global_init(struct hapd_interfaces *interfaces)
openlog("hostapd", 0, LOG_DAEMON);
#endif /* CONFIG_NATIVE_WINDOWS */
+ for (i = 0; wpa_drivers[i]; i++)
+ global.drv_count++;
+ if (global.drv_count == 0) {
+ wpa_printf(MSG_ERROR, "No drivers enabled");
+ return -1;
+ }
+ global.drv_priv = os_calloc(global.drv_count, sizeof(void *));
+ if (global.drv_priv == NULL)
+ return -1;
+
return 0;
}
static void hostapd_global_deinit(const char *pid_file)
{
+ int i;
+
+ for (i = 0; wpa_drivers[i] && global.drv_priv; i++) {
+ if (!global.drv_priv[i])
+ continue;
+ wpa_drivers[i]->global_deinit(global.drv_priv[i]);
+ }
+ os_free(global.drv_priv);
+ global.drv_priv = NULL;
+
#ifdef EAP_SERVER_TNC
tncs_global_deinit();
#endif /* EAP_SERVER_TNC */
+ random_deinit();
+
eloop_destroy();
#ifndef CONFIG_NATIVE_WINDOWS
@@ -448,7 +468,7 @@ static void show_version(void)
"hostapd v" VERSION_STR "\n"
"User space daemon for IEEE 802.11 AP management,\n"
"IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n"
- "Copyright (c) 2002-2010, Jouni Malinen <j@w1.fi> "
+ "Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi> "
"and contributors\n");
}
@@ -458,15 +478,21 @@ static void usage(void)
show_version();
fprintf(stderr,
"\n"
- "usage: hostapd [-hdBKtv] [-P <PID file>] "
- "<configuration file(s)>\n"
+ "usage: hostapd [-hdBKtv] [-P <PID file>] [-e <entropy file>] "
+ "\\\n"
+ " [-g <global ctrl_iface>] <configuration file(s)>\n"
"\n"
"options:\n"
" -h show this usage\n"
" -d show more debug messages (-dd for even more)\n"
" -B run daemon in the background\n"
+ " -e entropy file\n"
+ " -g global control interface path\n"
" -P PID file\n"
" -K include key data in debug messages\n"
+#ifdef CONFIG_DEBUG_FILE
+ " -f log output to debug file instead of stdout\n"
+#endif /* CONFIG_DEBUG_FILE */
" -t include timestamps in some debug messages\n"
" -v show hostapd version\n");
@@ -474,6 +500,37 @@ 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)
+ return hapd->iconf->bss->iface;
+ return NULL;
+}
+
+
+static int hostapd_get_global_ctrl_iface(struct hapd_interfaces *interfaces,
+ const char *path)
+{
+ char *pos;
+ os_free(interfaces->global_iface_path);
+ interfaces->global_iface_path = os_strdup(path);
+ if (interfaces->global_iface_path == NULL)
+ return -1;
+ pos = os_strrchr(interfaces->global_iface_path, '/');
+ if (pos == NULL) {
+ os_free(interfaces->global_iface_path);
+ interfaces->global_iface_path = NULL;
+ return -1;
+ }
+
+ *pos = '\0';
+ interfaces->global_iface_name = pos + 1;
+
+ return 0;
+}
+
+
int main(int argc, char *argv[])
{
struct hapd_interfaces interfaces;
@@ -481,12 +538,25 @@ int main(int argc, char *argv[])
size_t i;
int c, debug = 0, daemonize = 0;
char *pid_file = NULL;
+ const char *log_file = NULL;
+ const char *entropy_file = NULL;
if (os_program_init())
return -1;
+ os_memset(&interfaces, 0, sizeof(interfaces));
+ interfaces.reload_config = hostapd_reload_config;
+ interfaces.config_read_cb = hostapd_config_read;
+ 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;
+
for (;;) {
- c = getopt(argc, argv, "BdhKP:tv");
+ c = getopt(argc, argv, "Bde:f:hKP:tvg:");
if (c < 0)
break;
switch (c) {
@@ -501,6 +571,12 @@ int main(int argc, char *argv[])
case 'B':
daemonize++;
break;
+ case 'e':
+ entropy_file = optarg;
+ break;
+ case 'f':
+ log_file = optarg;
+ break;
case 'K':
wpa_debug_show_keys++;
break;
@@ -515,6 +591,9 @@ int main(int argc, char *argv[])
show_version();
exit(1);
break;
+ case 'g':
+ hostapd_get_global_ctrl_iface(&interfaces, optarg);
+ break;
default:
usage();
@@ -522,18 +601,25 @@ int main(int argc, char *argv[])
}
}
- if (optind == argc)
+ if (optind == argc && interfaces.global_iface_path == NULL)
usage();
+ wpa_msg_register_ifname_cb(hostapd_msg_ifname_cb);
+
+ if (log_file)
+ wpa_debug_open_file(log_file);
+
interfaces.count = argc - optind;
- interfaces.iface = os_malloc(interfaces.count *
- sizeof(struct hostapd_iface *));
- if (interfaces.iface == NULL) {
- wpa_printf(MSG_ERROR, "malloc failed\n");
- return -1;
+ if (interfaces.count) {
+ interfaces.iface = os_calloc(interfaces.count,
+ sizeof(struct hostapd_iface *));
+ if (interfaces.iface == NULL) {
+ wpa_printf(MSG_ERROR, "malloc failed");
+ return -1;
+ }
}
- if (hostapd_global_init(&interfaces))
+ if (hostapd_global_init(&interfaces, entropy_file))
return -1;
/* Initialize interfaces */
@@ -545,12 +631,15 @@ int main(int argc, char *argv[])
goto out;
}
+ hostapd_global_ctrl_iface_init(&interfaces);
+
if (hostapd_global_run(&interfaces, daemonize, pid_file))
goto out;
ret = 0;
out:
+ hostapd_global_ctrl_iface_deinit(&interfaces);
/* Deinitialize all interfaces */
for (i = 0; i < interfaces.count; i++)
hostapd_interface_deinit_free(interfaces.iface[i]);
@@ -559,6 +648,9 @@ int main(int argc, char *argv[])
hostapd_global_deinit(pid_file);
os_free(pid_file);
+ if (log_file)
+ wpa_debug_close_file();
+
os_program_deinit();
return ret;