main.c revision 4b06059785b935dd1f4f09314e4e12c417d2c6a4
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd / main()
38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/includes.h"
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NATIVE_WINDOWS
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <syslog.h>
120ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt#include <grp.h>
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/common.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/eloop.h"
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/random.h"
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/tls.h"
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/version.h"
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "drivers/driver.h"
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_server/eap.h"
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_server/tncs.h"
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ap/hostapd.h"
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ap/ap_config.h"
2504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#include "ap/ap_drv_ops.h"
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "config_file.h"
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_register.h"
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "dump_state.h"
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ctrl_iface.h"
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtextern int wpa_debug_level;
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtextern int wpa_debug_show_keys;
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtextern int wpa_debug_timestamp;
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtextern struct wpa_driver_ops *wpa_drivers[];
371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstruct hapd_global {
401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	void **drv_priv;
411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	size_t drv_count;
421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt};
431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic struct hapd_global global;
451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_HOSTAPD_LOGGER
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module,
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      int level, const char *txt, size_t len)
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_data *hapd = ctx;
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *format, *module_str;
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int maxlen;
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int conf_syslog_level, conf_stdout_level;
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int conf_syslog, conf_stdout;
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	maxlen = len + 100;
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	format = os_malloc(maxlen);
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!format)
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hapd && hapd->conf) {
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conf_syslog_level = hapd->conf->logger_syslog_level;
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conf_stdout_level = hapd->conf->logger_stdout_level;
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conf_syslog = hapd->conf->logger_syslog;
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conf_stdout = hapd->conf->logger_stdout;
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conf_syslog_level = conf_stdout_level = 0;
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conf_syslog = conf_stdout = (unsigned int) -1;
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (module) {
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case HOSTAPD_MODULE_IEEE80211:
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		module_str = "IEEE 802.11";
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case HOSTAPD_MODULE_IEEE8021X:
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		module_str = "IEEE 802.1X";
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case HOSTAPD_MODULE_RADIUS:
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		module_str = "RADIUS";
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case HOSTAPD_MODULE_WPA:
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		module_str = "WPA";
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case HOSTAPD_MODULE_DRIVER:
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		module_str = "DRIVER";
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case HOSTAPD_MODULE_IAPP:
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		module_str = "IAPP";
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case HOSTAPD_MODULE_MLME:
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		module_str = "MLME";
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		module_str = NULL;
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hapd && hapd->conf && addr)
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_snprintf(format, maxlen, "%s: STA " MACSTR "%s%s: %s",
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    hapd->conf->iface, MAC2STR(addr),
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    module_str ? " " : "", module_str, txt);
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (hapd && hapd->conf)
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_snprintf(format, maxlen, "%s:%s%s %s",
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    hapd->conf->iface, module_str ? " " : "",
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    module_str, txt);
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (addr)
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_snprintf(format, maxlen, "STA " MACSTR "%s%s: %s",
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    MAC2STR(addr), module_str ? " " : "",
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    module_str, txt);
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_snprintf(format, maxlen, "%s%s%s",
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    module_str, module_str ? ": " : "", txt);
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((conf_stdout & module) && level >= conf_stdout_level) {
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_debug_print_timestamp();
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("%s\n", format);
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NATIVE_WINDOWS
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((conf_syslog & module) && level >= conf_syslog_level) {
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int priority;
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		switch (level) {
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case HOSTAPD_LEVEL_DEBUG_VERBOSE:
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case HOSTAPD_LEVEL_DEBUG:
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			priority = LOG_DEBUG;
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case HOSTAPD_LEVEL_INFO:
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			priority = LOG_INFO;
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case HOSTAPD_LEVEL_NOTICE:
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			priority = LOG_NOTICE;
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case HOSTAPD_LEVEL_WARNING:
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			priority = LOG_WARNING;
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		default:
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			priority = LOG_INFO;
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		syslog(priority, "%s", format);
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(format);
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_HOSTAPD_LOGGER */
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd_init - Allocate and initialize per-interface data
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @config_file: Path to the configuration file
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the allocated interface data or %NULL on failure
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used to allocate main data structures for per-interface
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * data. The allocated data buffer will be freed by calling
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd_cleanup_iface().
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct hostapd_iface * hostapd_init(const char *config_file)
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_iface *hapd_iface = NULL;
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_config *conf = NULL;
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_data *hapd;
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hapd_iface = os_zalloc(sizeof(*hapd_iface));
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hapd_iface == NULL)
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hapd_iface->config_fname = os_strdup(config_file);
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hapd_iface->config_fname == NULL)
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conf = hostapd_config_read(hapd_iface->config_fname);
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conf == NULL)
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hapd_iface->conf = conf;
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hapd_iface->num_bss = conf->num_bss;
18061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	hapd_iface->bss = os_calloc(conf->num_bss,
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    sizeof(struct hostapd_data *));
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hapd_iface->bss == NULL)
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < conf->num_bss; i++) {
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hapd = hapd_iface->bss[i] =
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			hostapd_alloc_bss_data(hapd_iface, conf,
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       &conf->bss[i]);
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (hapd == NULL)
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto fail;
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hapd->msg_ctx = hapd;
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return hapd_iface;
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail:
1974b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	wpa_printf(MSG_ERROR, "Failed to set up interface with %s",
1984b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		   config_file);
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conf)
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hostapd_config_free(conf);
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hapd_iface) {
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(hapd_iface->config_fname);
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(hapd_iface->bss);
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(hapd_iface);
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_driver_init(struct hostapd_iface *iface)
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_init_params params;
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_data *hapd = iface->bss[0];
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_bss_config *conf = hapd->conf;
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *b = conf->bssid;
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_capa capa;
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hapd->driver == NULL || hapd->driver->hapd_init == NULL) {
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "No hostapd driver wrapper available");
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Initialize the driver interface */
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!(b[0] | b[1] | b[2] | b[3] | b[4] | b[5]))
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		b = NULL;
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&params, 0, sizeof(params));
2291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	for (i = 0; wpa_drivers[i]; i++) {
2301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (wpa_drivers[i] != hapd->driver)
2311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			continue;
2321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (global.drv_priv[i] == NULL &&
2341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    wpa_drivers[i]->global_init) {
2351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			global.drv_priv[i] = wpa_drivers[i]->global_init();
2361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			if (global.drv_priv[i] == NULL) {
2371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				wpa_printf(MSG_ERROR, "Failed to initialize "
2381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					   "driver '%s'",
2391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					   wpa_drivers[i]->name);
2401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				return -1;
2411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			}
2421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
2431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		params.global_priv = global.drv_priv[i];
2451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
2461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.bssid = b;
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.ifname = hapd->conf->iface;
24961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	params.ssid = hapd->conf->ssid.ssid;
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.ssid_len = hapd->conf->ssid.ssid_len;
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.test_socket = hapd->conf->test_socket;
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.use_pae_group_addr = hapd->conf->use_pae_group_addr;
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.num_bridge = hapd->iface->num_bss;
25561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	params.bridge = os_calloc(hapd->iface->num_bss, sizeof(char *));
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (params.bridge == NULL)
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < hapd->iface->num_bss; i++) {
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct hostapd_data *bss = hapd->iface->bss[i];
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (bss->conf->bridge[0])
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			params.bridge[i] = bss->conf->bridge;
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.own_addr = hapd->own_addr;
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hapd->drv_priv = hapd->driver->hapd_init(hapd, &params);
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(params.bridge);
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hapd->drv_priv == NULL) {
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "%s driver initialization failed.",
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   hapd->driver->name);
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hapd->driver = NULL;
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hapd->driver->get_capa &&
2761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    hapd->driver->get_capa(hapd->drv_priv, &capa) == 0) {
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		iface->drv_flags = capa.flags;
2781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		iface->probe_resp_offloads = capa.probe_resp_offloads;
279444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt		iface->extended_capa = capa.extended_capa;
280444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt		iface->extended_capa_mask = capa.extended_capa_mask;
281444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt		iface->extended_capa_len = capa.extended_capa_len;
2821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct hostapd_iface *
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidthostapd_interface_init(struct hapd_interfaces *interfaces,
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       const char *config_fname, int debug)
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_iface *iface;
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int k;
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_ERROR, "Configuration file: %s", config_fname);
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	iface = hostapd_init(config_fname);
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!iface)
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	iface->interfaces = interfaces;
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (k = 0; k < debug; k++) {
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (iface->bss[0]->conf->logger_stdout_level > 0)
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			iface->bss[0]->conf->logger_stdout_level--;
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3064b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	if (iface->conf->bss[0].iface[0] == '\0' &&
3074b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	    !hostapd_drv_none(iface->bss[0])) {
3084b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		wpa_printf(MSG_ERROR, "Interface name not specified in %s",
3094b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt			   config_fname);
3104b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		hostapd_interface_deinit_free(iface);
3114b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		return NULL;
3124b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	}
3134b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt
3144b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	if (hostapd_driver_init(iface) ||
3154b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	    hostapd_setup_interface(iface)) {
3164b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		hostapd_interface_deinit_free(iface);
3174b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		return NULL;
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return iface;
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * handle_term - SIGINT and SIGTERM handler to terminate hostapd process
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void handle_term(int sig, void *signal_ctx)
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "Signal %d received - terminating", sig);
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_terminate();
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NATIVE_WINDOWS
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int handle_reload_iface(struct hostapd_iface *iface, void *ctx)
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hostapd_reload_config(iface) < 0) {
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_WARNING, "Failed to read new configuration "
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "file - continuing with old.");
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * handle_reload - SIGHUP handler to reload configuration
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void handle_reload(int sig, void *signal_ctx)
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hapd_interfaces *interfaces = signal_ctx;
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "Signal %d received - reloading configuration",
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   sig);
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hostapd_for_each_interface(interfaces, handle_reload_iface, NULL);
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void handle_dump_state(int sig, void *signal_ctx)
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef HOSTAPD_DUMP_STATE
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hapd_interfaces *interfaces = signal_ctx;
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hostapd_for_each_interface(interfaces, handle_dump_state_iface, NULL);
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* HOSTAPD_DUMP_STATE */
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenstatic int hostapd_global_init(struct hapd_interfaces *interfaces,
36975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			       const char *entropy_file)
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int i;
3721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
3731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_memset(&global, 0, sizeof(global));
3741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hostapd_logger_register_cb(hostapd_logger_cb);
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap_server_register_methods()) {
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Failed to register EAP methods");
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eloop_init()) {
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Failed to initialize event loop");
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	random_init(entropy_file);
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NATIVE_WINDOWS
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_signal(SIGHUP, handle_reload, interfaces);
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_signal(SIGUSR1, handle_dump_state, interfaces);
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_signal_terminate(handle_term, interfaces);
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NATIVE_WINDOWS
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	openlog("hostapd", 0, LOG_DAEMON);
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	for (i = 0; wpa_drivers[i]; i++)
4001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		global.drv_count++;
4011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (global.drv_count == 0) {
4021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_printf(MSG_ERROR, "No drivers enabled");
4031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return -1;
4041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
40561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	global.drv_priv = os_calloc(global.drv_count, sizeof(void *));
4061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (global.drv_priv == NULL)
4071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return -1;
4081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void hostapd_global_deinit(const char *pid_file)
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int i;
4161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
4171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	for (i = 0; wpa_drivers[i] && global.drv_priv; i++) {
4181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (!global.drv_priv[i])
4191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			continue;
4201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_drivers[i]->global_deinit(global.drv_priv[i]);
4211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
4221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_free(global.drv_priv);
4231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	global.drv_priv = NULL;
4241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_TNC
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tncs_global_deinit();
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_TNC */
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	random_deinit();
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_destroy();
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NATIVE_WINDOWS
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	closelog();
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_server_unregister_methods();
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_daemonize_terminate(pid_file);
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_global_run(struct hapd_interfaces *ifaces, int daemonize,
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      const char *pid_file)
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_TNC
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int tnc = 0;
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i, k;
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; !tnc && i < ifaces->count; i++) {
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (k = 0; k < ifaces->iface[i]->num_bss; k++) {
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (ifaces->iface[i]->bss[0]->conf->tnc) {
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				tnc++;
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tnc && tncs_global_init() < 0) {
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Failed to initialize TNCS");
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_TNC */
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (daemonize && os_daemonize(pid_file)) {
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		perror("daemon");
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_run();
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void show_version(void)
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fprintf(stderr,
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"hostapd v" VERSION_STR "\n"
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"User space daemon for IEEE 802.11 AP management,\n"
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n"
482a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		"Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi> "
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"and contributors\n");
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void usage(void)
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	show_version();
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fprintf(stderr,
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"\n"
49275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		"usage: hostapd [-hdBKtv] [-P <PID file>] [-e <entropy file>] "
49361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		"\\\n"
4940ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt		"         [-g <global ctrl_iface>] [-G <group>] \\\n"
4950ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt		"         <configuration file(s)>\n"
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"\n"
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"options:\n"
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"   -h   show this usage\n"
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"   -d   show more debug messages (-dd for even more)\n"
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"   -B   run daemon in the background\n"
50175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		"   -e   entropy file\n"
50261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		"   -g   global control interface path\n"
5030ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt		"   -G   group for control interfaces\n"
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"   -P   PID file\n"
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"   -K   include key data in debug messages\n"
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_DEBUG_FILE
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"   -f   log output to debug file instead of stdout\n"
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_DEBUG_FILE */
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"   -t   include timestamps in some debug messages\n"
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"   -v   show hostapd version\n");
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	exit(1);
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * hostapd_msg_ifname_cb(void *ctx)
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_data *hapd = ctx;
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hapd && hapd->iconf && hapd->iconf->bss)
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return hapd->iconf->bss->iface;
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
52561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int hostapd_get_global_ctrl_iface(struct hapd_interfaces *interfaces,
52661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					 const char *path)
52761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
52861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	char *pos;
52961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	os_free(interfaces->global_iface_path);
53061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	interfaces->global_iface_path = os_strdup(path);
53161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (interfaces->global_iface_path == NULL)
53261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return -1;
53361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	pos = os_strrchr(interfaces->global_iface_path, '/');
53461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (pos == NULL) {
5351e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt		wpa_printf(MSG_ERROR, "No '/' in the global control interface "
5361e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt			   "file");
53761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		os_free(interfaces->global_iface_path);
53861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		interfaces->global_iface_path = NULL;
53961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return -1;
54061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
54161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
54261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	*pos = '\0';
54361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	interfaces->global_iface_name = pos + 1;
54461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
54561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
54661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
54761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
54861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
5490ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidtstatic int hostapd_get_ctrl_iface_group(struct hapd_interfaces *interfaces,
5500ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt					const char *group)
5510ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt{
5520ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt#ifndef CONFIG_NATIVE_WINDOWS
5530ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt	struct group *grp;
5540ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt	grp = getgrnam(group);
5550ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt	if (grp == NULL) {
5560ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt		wpa_printf(MSG_ERROR, "Unknown group '%s'", group);
5570ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt		return -1;
5580ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt	}
5590ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt	interfaces->ctrl_iface_group = grp->gr_gid;
5600ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */
5610ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt	return 0;
5620ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt}
5630ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt
5640ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint main(int argc, char *argv[])
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hapd_interfaces interfaces;
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret = 1;
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int c, debug = 0, daemonize = 0;
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *pid_file = NULL;
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *log_file = NULL;
57375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	const char *entropy_file = NULL;
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_program_init())
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
57861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	os_memset(&interfaces, 0, sizeof(interfaces));
57961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	interfaces.reload_config = hostapd_reload_config;
58061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	interfaces.config_read_cb = hostapd_config_read;
58161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	interfaces.for_each_interface = hostapd_for_each_interface;
58261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	interfaces.ctrl_iface_init = hostapd_ctrl_iface_init;
58361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	interfaces.ctrl_iface_deinit = hostapd_ctrl_iface_deinit;
58461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	interfaces.driver_init = hostapd_driver_init;
58561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	interfaces.global_iface_path = NULL;
58661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	interfaces.global_iface_name = NULL;
58761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	interfaces.global_ctrl_sock = -1;
58861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (;;) {
5900ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt		c = getopt(argc, argv, "Bde:f:hKP:tvg:G:");
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (c < 0)
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		switch (c) {
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'h':
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			usage();
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'd':
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			debug++;
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (wpa_debug_level > 0)
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_debug_level--;
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'B':
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			daemonize++;
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
60575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		case 'e':
60675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			entropy_file = optarg;
60775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			break;
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'f':
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			log_file = optarg;
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'K':
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_debug_show_keys++;
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'P':
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(pid_file);
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pid_file = os_rel2abs_path(optarg);
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 't':
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_debug_timestamp++;
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'v':
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			show_version();
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			exit(1);
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
62561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		case 'g':
6261e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt			if (hostapd_get_global_ctrl_iface(&interfaces, optarg))
6271e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt				return -1;
62861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			break;
6290ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt		case 'G':
6301e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt			if (hostapd_get_ctrl_iface_group(&interfaces, optarg))
6311e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt				return -1;
6320ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt			break;
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		default:
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			usage();
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
63961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (optind == argc && interfaces.global_iface_path == NULL)
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		usage();
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg_register_ifname_cb(hostapd_msg_ifname_cb);
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (log_file)
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_debug_open_file(log_file);
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	interfaces.count = argc - optind;
64861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (interfaces.count) {
64961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		interfaces.iface = os_calloc(interfaces.count,
65061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					     sizeof(struct hostapd_iface *));
65161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (interfaces.iface == NULL) {
65261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpa_printf(MSG_ERROR, "malloc failed");
65361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
65461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6574b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	if (hostapd_global_init(&interfaces, entropy_file)) {
6584b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		wpa_printf(MSG_ERROR, "Failed to initilize global context");
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6604b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	}
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Initialize interfaces */
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < interfaces.count; i++) {
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		interfaces.iface[i] = hostapd_interface_init(&interfaces,
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							     argv[optind + i],
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							     debug);
6674b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		if (!interfaces.iface[i]) {
6684b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt			wpa_printf(MSG_ERROR, "Failed to initialize interface");
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto out;
6704b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		}
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
67361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	hostapd_global_ctrl_iface_init(&interfaces);
67461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
6754b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	if (hostapd_global_run(&interfaces, daemonize, pid_file)) {
6764b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		wpa_printf(MSG_ERROR, "Failed to start eloop");
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
6784b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	}
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = 0;
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt out:
68361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	hostapd_global_ctrl_iface_deinit(&interfaces);
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Deinitialize all interfaces */
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < interfaces.count; i++)
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hostapd_interface_deinit_free(interfaces.iface[i]);
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(interfaces.iface);
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hostapd_global_deinit(pid_file);
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(pid_file);
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (log_file)
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_debug_close_file();
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_program_deinit();
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
699