18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd / main()
3de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt * Copyright (c) 2002-2016, 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"
1796be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt#include "utils/uuid.h"
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/random.h"
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/tls.h"
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/version.h"
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "drivers/driver.h"
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_server/eap.h"
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_server/tncs.h"
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ap/hostapd.h"
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ap/ap_config.h"
2604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#include "ap/ap_drv_ops.h"
27d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#include "fst/fst.h"
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "config_file.h"
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_register.h"
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ctrl_iface.h"
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstruct hapd_global {
341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	void **drv_priv;
351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	size_t drv_count;
361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt};
371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic struct hapd_global global;
391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_HOSTAPD_LOGGER
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module,
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      int level, const char *txt, size_t len)
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_data *hapd = ctx;
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *format, *module_str;
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int maxlen;
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int conf_syslog_level, conf_stdout_level;
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int conf_syslog, conf_stdout;
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	maxlen = len + 100;
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	format = os_malloc(maxlen);
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!format)
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hapd && hapd->conf) {
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conf_syslog_level = hapd->conf->logger_syslog_level;
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conf_stdout_level = hapd->conf->logger_stdout_level;
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conf_syslog = hapd->conf->logger_syslog;
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conf_stdout = hapd->conf->logger_stdout;
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conf_syslog_level = conf_stdout_level = 0;
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conf_syslog = conf_stdout = (unsigned int) -1;
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (module) {
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case HOSTAPD_MODULE_IEEE80211:
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		module_str = "IEEE 802.11";
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case HOSTAPD_MODULE_IEEE8021X:
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		module_str = "IEEE 802.1X";
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case HOSTAPD_MODULE_RADIUS:
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		module_str = "RADIUS";
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case HOSTAPD_MODULE_WPA:
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		module_str = "WPA";
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case HOSTAPD_MODULE_DRIVER:
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		module_str = "DRIVER";
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case HOSTAPD_MODULE_IAPP:
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		module_str = "IAPP";
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case HOSTAPD_MODULE_MLME:
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		module_str = "MLME";
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		module_str = NULL;
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hapd && hapd->conf && addr)
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_snprintf(format, maxlen, "%s: STA " MACSTR "%s%s: %s",
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    hapd->conf->iface, MAC2STR(addr),
9696be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt			    module_str ? " " : "", module_str ? module_str : "",
9796be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt			    txt);
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (hapd && hapd->conf)
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_snprintf(format, maxlen, "%s:%s%s %s",
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    hapd->conf->iface, module_str ? " " : "",
101661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt			    module_str ? module_str : "", txt);
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (addr)
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_snprintf(format, maxlen, "STA " MACSTR "%s%s: %s",
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    MAC2STR(addr), module_str ? " " : "",
105661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt			    module_str ? module_str : "", txt);
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_snprintf(format, maxlen, "%s%s%s",
108661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt			    module_str ? module_str : "",
109661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt			    module_str ? ": " : "", txt);
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((conf_stdout & module) && level >= conf_stdout_level) {
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_debug_print_timestamp();
113cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		wpa_printf(MSG_INFO, "%s", format);
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NATIVE_WINDOWS
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((conf_syslog & module) && level >= conf_syslog_level) {
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int priority;
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		switch (level) {
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case HOSTAPD_LEVEL_DEBUG_VERBOSE:
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case HOSTAPD_LEVEL_DEBUG:
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			priority = LOG_DEBUG;
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case HOSTAPD_LEVEL_INFO:
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			priority = LOG_INFO;
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case HOSTAPD_LEVEL_NOTICE:
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			priority = LOG_NOTICE;
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case HOSTAPD_LEVEL_WARNING:
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			priority = LOG_WARNING;
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		default:
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			priority = LOG_INFO;
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		syslog(priority, "%s", format);
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(format);
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_HOSTAPD_LOGGER */
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
147cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt * hostapd_driver_init - Preparate driver interface
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_driver_init(struct hostapd_iface *iface)
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_init_params params;
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_data *hapd = iface->bss[0];
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_bss_config *conf = hapd->conf;
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *b = conf->bssid;
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_capa capa;
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hapd->driver == NULL || hapd->driver->hapd_init == NULL) {
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "No hostapd driver wrapper available");
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Initialize the driver interface */
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!(b[0] | b[1] | b[2] | b[3] | b[4] | b[5]))
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		b = NULL;
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&params, 0, sizeof(params));
1681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	for (i = 0; wpa_drivers[i]; i++) {
1691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (wpa_drivers[i] != hapd->driver)
1701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			continue;
1711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (global.drv_priv[i] == NULL &&
1731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    wpa_drivers[i]->global_init) {
174e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt			global.drv_priv[i] =
175e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt				wpa_drivers[i]->global_init(iface->interfaces);
1761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			if (global.drv_priv[i] == NULL) {
1771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				wpa_printf(MSG_ERROR, "Failed to initialize "
1781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					   "driver '%s'",
1791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					   wpa_drivers[i]->name);
1801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				return -1;
1811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			}
1821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
1831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		params.global_priv = global.drv_priv[i];
1851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
1861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.bssid = b;
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.ifname = hapd->conf->iface;
189fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt	params.driver_params = hapd->iconf->driver_params;
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.use_pae_group_addr = hapd->conf->use_pae_group_addr;
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.num_bridge = hapd->iface->num_bss;
19361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	params.bridge = os_calloc(hapd->iface->num_bss, sizeof(char *));
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (params.bridge == NULL)
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < hapd->iface->num_bss; i++) {
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct hostapd_data *bss = hapd->iface->bss[i];
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (bss->conf->bridge[0])
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			params.bridge[i] = bss->conf->bridge;
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.own_addr = hapd->own_addr;
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hapd->drv_priv = hapd->driver->hapd_init(hapd, &params);
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(params.bridge);
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hapd->drv_priv == NULL) {
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "%s driver initialization failed.",
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   hapd->driver->name);
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hapd->driver = NULL;
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hapd->driver->get_capa &&
2141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    hapd->driver->get_capa(hapd->drv_priv, &capa) == 0) {
2150207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt		struct wowlan_triggers *triggs;
2160207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		iface->drv_flags = capa.flags;
218fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt		iface->smps_modes = capa.smps_modes;
2191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		iface->probe_resp_offloads = capa.probe_resp_offloads;
220444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt		iface->extended_capa = capa.extended_capa;
221444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt		iface->extended_capa_mask = capa.extended_capa_mask;
222444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt		iface->extended_capa_len = capa.extended_capa_len;
2238bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt		iface->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
2240207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt
2250207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt		triggs = wpa_get_wowlan_triggers(conf->wowlan_triggers, &capa);
2260207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt		if (triggs && hapd->driver->set_wowlan) {
2270207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt			if (hapd->driver->set_wowlan(hapd->drv_priv, triggs))
2280207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt				wpa_printf(MSG_ERROR, "set_wowlan failed");
2290207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt		}
2300207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt		os_free(triggs);
2311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
237cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt/**
238cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt * hostapd_interface_init - Read configuration file and init BSS data
239cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt *
240cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt * This function is used to parse configuration file for a full interface (one
241cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt * or more BSSes sharing the same radio) and allocate memory for the BSS
242cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt * interfaces. No actiual driver operations are started.
243cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt */
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct hostapd_iface *
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidthostapd_interface_init(struct hapd_interfaces *interfaces,
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       const char *config_fname, int debug)
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_iface *iface;
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int k;
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_ERROR, "Configuration file: %s", config_fname);
252cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	iface = hostapd_init(interfaces, config_fname);
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!iface)
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	iface->interfaces = interfaces;
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (k = 0; k < debug; k++) {
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (iface->bss[0]->conf->logger_stdout_level > 0)
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			iface->bss[0]->conf->logger_stdout_level--;
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
262cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	if (iface->conf->bss[0]->iface[0] == '\0' &&
2634b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	    !hostapd_drv_none(iface->bss[0])) {
2644b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		wpa_printf(MSG_ERROR, "Interface name not specified in %s",
2654b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt			   config_fname);
2664b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		hostapd_interface_deinit_free(iface);
2674b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		return NULL;
2684b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	}
2694b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return iface;
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * handle_term - SIGINT and SIGTERM handler to terminate hostapd process
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void handle_term(int sig, void *signal_ctx)
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "Signal %d received - terminating", sig);
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_terminate();
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NATIVE_WINDOWS
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int handle_reload_iface(struct hostapd_iface *iface, void *ctx)
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hostapd_reload_config(iface) < 0) {
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_WARNING, "Failed to read new configuration "
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "file - continuing with old.");
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * handle_reload - SIGHUP handler to reload configuration
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void handle_reload(int sig, void *signal_ctx)
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hapd_interfaces *interfaces = signal_ctx;
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "Signal %d received - reloading configuration",
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   sig);
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hostapd_for_each_interface(interfaces, handle_reload_iface, NULL);
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void handle_dump_state(int sig, void *signal_ctx)
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
310fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	/* Not used anymore - ignore signal */
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenstatic int hostapd_global_init(struct hapd_interfaces *interfaces,
31675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			       const char *entropy_file)
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int i;
3191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
3201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_memset(&global, 0, sizeof(global));
3211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hostapd_logger_register_cb(hostapd_logger_cb);
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap_server_register_methods()) {
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Failed to register EAP methods");
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eloop_init()) {
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Failed to initialize event loop");
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	random_init(entropy_file);
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NATIVE_WINDOWS
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_signal(SIGHUP, handle_reload, interfaces);
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_signal(SIGUSR1, handle_dump_state, interfaces);
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_signal_terminate(handle_term, interfaces);
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NATIVE_WINDOWS
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	openlog("hostapd", 0, LOG_DAEMON);
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	for (i = 0; wpa_drivers[i]; i++)
3471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		global.drv_count++;
3481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (global.drv_count == 0) {
3491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_printf(MSG_ERROR, "No drivers enabled");
3501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return -1;
3511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
35261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	global.drv_priv = os_calloc(global.drv_count, sizeof(void *));
3531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (global.drv_priv == NULL)
3541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return -1;
3551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void hostapd_global_deinit(const char *pid_file)
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int i;
3631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
3641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	for (i = 0; wpa_drivers[i] && global.drv_priv; i++) {
3651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (!global.drv_priv[i])
3661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			continue;
3671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_drivers[i]->global_deinit(global.drv_priv[i]);
3681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
3691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_free(global.drv_priv);
3701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	global.drv_priv = NULL;
3711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_TNC
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tncs_global_deinit();
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_TNC */
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	random_deinit();
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_destroy();
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NATIVE_WINDOWS
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	closelog();
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_server_unregister_methods();
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_daemonize_terminate(pid_file);
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_global_run(struct hapd_interfaces *ifaces, int daemonize,
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      const char *pid_file)
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_TNC
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int tnc = 0;
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i, k;
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; !tnc && i < ifaces->count; i++) {
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (k = 0; k < ifaces->iface[i]->num_bss; k++) {
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (ifaces->iface[i]->bss[0]->conf->tnc) {
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				tnc++;
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tnc && tncs_global_init() < 0) {
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Failed to initialize TNCS");
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_TNC */
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
412b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt	if (daemonize) {
413b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt		if (os_daemonize(pid_file)) {
414b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt			wpa_printf(MSG_ERROR, "daemon: %s", strerror(errno));
415b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt			return -1;
416b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt		}
417b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt		if (eloop_sock_requeue()) {
418b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt			wpa_printf(MSG_ERROR, "eloop_sock_requeue: %s",
419b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt				   strerror(errno));
420b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt			return -1;
421b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt		}
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_run();
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void show_version(void)
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fprintf(stderr,
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"hostapd v" VERSION_STR "\n"
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"User space daemon for IEEE 802.11 AP management,\n"
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n"
436de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt		"Copyright (c) 2002-2016, Jouni Malinen <j@w1.fi> "
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"and contributors\n");
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void usage(void)
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	show_version();
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fprintf(stderr,
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"\n"
44675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		"usage: hostapd [-hdBKtv] [-P <PID file>] [-e <entropy file>] "
44761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		"\\\n"
4480ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt		"         [-g <global ctrl_iface>] [-G <group>] \\\n"
4490ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt		"         <configuration file(s)>\n"
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"\n"
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"options:\n"
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"   -h   show this usage\n"
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"   -d   show more debug messages (-dd for even more)\n"
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"   -B   run daemon in the background\n"
45575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		"   -e   entropy file\n"
45661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		"   -g   global control interface path\n"
4570ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt		"   -G   group for control interfaces\n"
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"   -P   PID file\n"
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"   -K   include key data in debug messages\n"
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_DEBUG_FILE
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"   -f   log output to debug file instead of stdout\n"
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_DEBUG_FILE */
463cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt#ifdef CONFIG_DEBUG_LINUX_TRACING
464cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		"   -T = record to Linux tracing in addition to logging\n"
465cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		"        (records all messages regardless of debug verbosity)\n"
466cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt#endif /* CONFIG_DEBUG_LINUX_TRACING */
467d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		"   -S   start all the interfaces synchronously\n"
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"   -t   include timestamps in some debug messages\n"
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"   -v   show hostapd version\n");
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	exit(1);
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * hostapd_msg_ifname_cb(void *ctx)
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_data *hapd = ctx;
47831a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt	if (hapd && hapd->conf)
47931a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt		return hapd->conf->iface;
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
48461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int hostapd_get_global_ctrl_iface(struct hapd_interfaces *interfaces,
48561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					 const char *path)
48661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
48731a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt#ifndef CONFIG_CTRL_IFACE_UDP
48861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	char *pos;
48931a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt#endif /* !CONFIG_CTRL_IFACE_UDP */
49031a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt
49161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	os_free(interfaces->global_iface_path);
49261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	interfaces->global_iface_path = os_strdup(path);
49361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (interfaces->global_iface_path == NULL)
49461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return -1;
49531a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt
49631a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt#ifndef CONFIG_CTRL_IFACE_UDP
49761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	pos = os_strrchr(interfaces->global_iface_path, '/');
49861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (pos == NULL) {
4991e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt		wpa_printf(MSG_ERROR, "No '/' in the global control interface "
5001e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt			   "file");
50161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		os_free(interfaces->global_iface_path);
50261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		interfaces->global_iface_path = NULL;
50361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return -1;
50461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
50561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
50661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	*pos = '\0';
50761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	interfaces->global_iface_name = pos + 1;
50831a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt#endif /* !CONFIG_CTRL_IFACE_UDP */
50961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
51061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
51161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
51261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
51361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
5140ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidtstatic int hostapd_get_ctrl_iface_group(struct hapd_interfaces *interfaces,
5150ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt					const char *group)
5160ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt{
5170ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt#ifndef CONFIG_NATIVE_WINDOWS
5180ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt	struct group *grp;
5190ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt	grp = getgrnam(group);
5200ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt	if (grp == NULL) {
5210ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt		wpa_printf(MSG_ERROR, "Unknown group '%s'", group);
5220ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt		return -1;
5230ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt	}
5240ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt	interfaces->ctrl_iface_group = grp->gr_gid;
5250ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */
5260ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt	return 0;
5270ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt}
5280ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt
5290ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt
53096be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt#ifdef CONFIG_WPS
53196be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidtstatic int gen_uuid(const char *txt_addr)
53296be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt{
53396be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt	u8 addr[ETH_ALEN];
53496be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt	u8 uuid[UUID_LEN];
53596be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt	char buf[100];
53696be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt
53796be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt	if (hwaddr_aton(txt_addr, addr) < 0)
53896be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt		return -1;
53996be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt
54096be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt	uuid_gen_mac_addr(addr, uuid);
54196be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt	if (uuid_bin2str(uuid, buf, sizeof(buf)) < 0)
54296be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt		return -1;
54396be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt
54496be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt	printf("%s\n", buf);
54596be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt
54696be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt	return 0;
54796be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt}
54896be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt#endif /* CONFIG_WPS */
54996be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt
55096be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt
551d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#ifndef HOSTAPD_CLEANUP_INTERVAL
552d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#define HOSTAPD_CLEANUP_INTERVAL 10
553d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#endif /* HOSTAPD_CLEANUP_INTERVAL */
554d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
555d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic int hostapd_periodic_call(struct hostapd_iface *iface, void *ctx)
556d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
557d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	hostapd_periodic_iface(iface);
558d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return 0;
559d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
560d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
561d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
562d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt/* Periodic cleanup tasks */
563d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic void hostapd_periodic(void *eloop_ctx, void *timeout_ctx)
564d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
565d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct hapd_interfaces *interfaces = eloop_ctx;
566d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
567d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	eloop_register_timeout(HOSTAPD_CLEANUP_INTERVAL, 0,
568d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			       hostapd_periodic, interfaces, NULL);
569d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	hostapd_for_each_interface(interfaces, hostapd_periodic_call, NULL);
570d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
571d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
572d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint main(int argc, char *argv[])
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hapd_interfaces interfaces;
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret = 1;
577cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	size_t i, j;
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int c, debug = 0, daemonize = 0;
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *pid_file = NULL;
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *log_file = NULL;
58175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	const char *entropy_file = NULL;
582cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	char **bss_config = NULL, **tmp_bss;
583cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	size_t num_bss_configs = 0;
584cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt#ifdef CONFIG_DEBUG_LINUX_TRACING
585cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	int enable_trace_dbg = 0;
586cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt#endif /* CONFIG_DEBUG_LINUX_TRACING */
587d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	int start_ifaces_in_sync = 0;
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_program_init())
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
59261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	os_memset(&interfaces, 0, sizeof(interfaces));
59361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	interfaces.reload_config = hostapd_reload_config;
59461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	interfaces.config_read_cb = hostapd_config_read;
59561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	interfaces.for_each_interface = hostapd_for_each_interface;
59661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	interfaces.ctrl_iface_init = hostapd_ctrl_iface_init;
59761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	interfaces.ctrl_iface_deinit = hostapd_ctrl_iface_deinit;
59861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	interfaces.driver_init = hostapd_driver_init;
59961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	interfaces.global_iface_path = NULL;
60061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	interfaces.global_iface_name = NULL;
60161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	interfaces.global_ctrl_sock = -1;
60231a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt	dl_list_init(&interfaces.global_ctrl_dst);
60361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (;;) {
605d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		c = getopt(argc, argv, "b:Bde:f:hKP:STtu:vg:G:");
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (c < 0)
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		switch (c) {
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'h':
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			usage();
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'd':
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			debug++;
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (wpa_debug_level > 0)
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_debug_level--;
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'B':
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			daemonize++;
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
62075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		case 'e':
62175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			entropy_file = optarg;
62275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			break;
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'f':
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			log_file = optarg;
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'K':
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_debug_show_keys++;
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'P':
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(pid_file);
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pid_file = os_rel2abs_path(optarg);
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 't':
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_debug_timestamp++;
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
636cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt#ifdef CONFIG_DEBUG_LINUX_TRACING
637cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		case 'T':
638cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			enable_trace_dbg = 1;
639cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			break;
640cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt#endif /* CONFIG_DEBUG_LINUX_TRACING */
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'v':
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			show_version();
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			exit(1);
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
64561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		case 'g':
6461e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt			if (hostapd_get_global_ctrl_iface(&interfaces, optarg))
6471e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt				return -1;
64861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			break;
6490ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt		case 'G':
6501e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt			if (hostapd_get_ctrl_iface_group(&interfaces, optarg))
6511e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt				return -1;
6520ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt			break;
653cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		case 'b':
654cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			tmp_bss = os_realloc_array(bss_config,
655cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt						   num_bss_configs + 1,
656cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt						   sizeof(char *));
657cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			if (tmp_bss == NULL)
658cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt				goto out;
659cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			bss_config = tmp_bss;
660cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			bss_config[num_bss_configs++] = optarg;
661cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			break;
662d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		case 'S':
663d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			start_ifaces_in_sync = 1;
664d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			break;
66596be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt#ifdef CONFIG_WPS
66696be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt		case 'u':
66796be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt			return gen_uuid(optarg);
66896be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt#endif /* CONFIG_WPS */
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		default:
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			usage();
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
675cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	if (optind == argc && interfaces.global_iface_path == NULL &&
676cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	    num_bss_configs == 0)
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		usage();
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg_register_ifname_cb(hostapd_msg_ifname_cb);
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (log_file)
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_debug_open_file(log_file);
683fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt	else
684fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt		wpa_debug_setup_stdout();
685cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt#ifdef CONFIG_DEBUG_LINUX_TRACING
686cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	if (enable_trace_dbg) {
687cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		int tret = wpa_debug_open_linux_tracing();
688cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		if (tret) {
689cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			wpa_printf(MSG_ERROR, "Failed to enable trace logging");
690cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			return -1;
691cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		}
692cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	}
693cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt#endif /* CONFIG_DEBUG_LINUX_TRACING */
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	interfaces.count = argc - optind;
696cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	if (interfaces.count || num_bss_configs) {
697cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		interfaces.iface = os_calloc(interfaces.count + num_bss_configs,
69861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					     sizeof(struct hostapd_iface *));
69961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (interfaces.iface == NULL) {
70061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpa_printf(MSG_ERROR, "malloc failed");
70161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
70261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7054b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	if (hostapd_global_init(&interfaces, entropy_file)) {
7067a53dbb56693ee9f55c0cab1a8297436511e8613Dmitry Shmidt		wpa_printf(MSG_ERROR, "Failed to initialize global context");
7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7084b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	}
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
710d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	eloop_register_timeout(HOSTAPD_CLEANUP_INTERVAL, 0,
711d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			       hostapd_periodic, &interfaces, NULL);
712d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
713d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (fst_global_init()) {
714d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		wpa_printf(MSG_ERROR,
715d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   "Failed to initialize global FST context");
716d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		goto out;
717d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
718d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
719d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#if defined(CONFIG_FST) && defined(CONFIG_CTRL_IFACE)
720d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (!fst_global_add_ctrl(fst_ctrl_cli))
721d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		wpa_printf(MSG_WARNING, "Failed to add CLI FST ctrl");
722d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#endif /* CONFIG_FST && CONFIG_CTRL_IFACE */
723d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
724cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	/* Allocate and parse configuration for full interface files */
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < interfaces.count; i++) {
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		interfaces.iface[i] = hostapd_interface_init(&interfaces,
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							     argv[optind + i],
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							     debug);
7294b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		if (!interfaces.iface[i]) {
7304b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt			wpa_printf(MSG_ERROR, "Failed to initialize interface");
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto out;
7324b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		}
733d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (start_ifaces_in_sync)
734d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			interfaces.iface[i]->need_to_start_in_sync = 1;
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
737cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	/* Allocate and parse configuration for per-BSS files */
738cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	for (i = 0; i < num_bss_configs; i++) {
739cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		struct hostapd_iface *iface;
740cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		char *fname;
741cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt
742cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		wpa_printf(MSG_INFO, "BSS config: %s", bss_config[i]);
743cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		fname = os_strchr(bss_config[i], ':');
744cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		if (fname == NULL) {
745cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			wpa_printf(MSG_ERROR,
746cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt				   "Invalid BSS config identifier '%s'",
747cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt				   bss_config[i]);
748cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			goto out;
749cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		}
750cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		*fname++ = '\0';
751cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		iface = hostapd_interface_init_bss(&interfaces, bss_config[i],
752cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt						   fname, debug);
753cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		if (iface == NULL)
754cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			goto out;
755cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		for (j = 0; j < interfaces.count; j++) {
756cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			if (interfaces.iface[j] == iface)
757cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt				break;
758cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		}
759cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		if (j == interfaces.count) {
760cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			struct hostapd_iface **tmp;
761cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			tmp = os_realloc_array(interfaces.iface,
762cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt					       interfaces.count + 1,
763cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt					       sizeof(struct hostapd_iface *));
764cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			if (tmp == NULL) {
765cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt				hostapd_interface_deinit_free(iface);
766cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt				goto out;
767cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			}
768cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			interfaces.iface = tmp;
769cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			interfaces.iface[interfaces.count++] = iface;
770cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		}
771cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	}
772cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt
773cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	/*
774cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	 * Enable configured interfaces. Depending on channel configuration,
775cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	 * this may complete full initialization before returning or use a
776cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	 * callback mechanism to complete setup in case of operations like HT
777cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	 * co-ex scans, ACS, or DFS are needed to determine channel parameters.
778cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	 * In such case, the interface will be enabled from eloop context within
779cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	 * hostapd_global_run().
780cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	 */
781b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt	interfaces.terminate_on_error = interfaces.count;
782cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	for (i = 0; i < interfaces.count; i++) {
783cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		if (hostapd_driver_init(interfaces.iface[i]) ||
784cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		    hostapd_setup_interface(interfaces.iface[i]))
785cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			goto out;
786cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	}
787cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt
78861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	hostapd_global_ctrl_iface_init(&interfaces);
78961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
7904b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	if (hostapd_global_run(&interfaces, daemonize, pid_file)) {
7914b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		wpa_printf(MSG_ERROR, "Failed to start eloop");
7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
7934b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	}
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = 0;
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt out:
79861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	hostapd_global_ctrl_iface_deinit(&interfaces);
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Deinitialize all interfaces */
800a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt	for (i = 0; i < interfaces.count; i++) {
801818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		if (!interfaces.iface[i])
802818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			continue;
803a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt		interfaces.iface[i]->driver_ap_teardown =
804a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt			!!(interfaces.iface[i]->drv_flags &
805a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt			   WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT);
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hostapd_interface_deinit_free(interfaces.iface[i]);
807a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt	}
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(interfaces.iface);
8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
810d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	eloop_cancel_timeout(hostapd_periodic, &interfaces, NULL);
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hostapd_global_deinit(pid_file);
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(pid_file);
8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (log_file)
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_debug_close_file();
816cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	wpa_debug_close_linux_tracing();
817cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt
818cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	os_free(bss_config);
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
820d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	fst_global_deinit();
821d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_program_deinit();
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
826