main.c revision 818ea489ef32dcdc7c098d8a336d6e1dd8996112
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"
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"
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "config_file.h"
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_register.h"
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ctrl_iface.h"
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstruct hapd_global {
331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	void **drv_priv;
341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	size_t drv_count;
351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt};
361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic struct hapd_global global;
381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_HOSTAPD_LOGGER
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module,
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      int level, const char *txt, size_t len)
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_data *hapd = ctx;
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *format, *module_str;
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int maxlen;
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int conf_syslog_level, conf_stdout_level;
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int conf_syslog, conf_stdout;
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	maxlen = len + 100;
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	format = os_malloc(maxlen);
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!format)
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hapd && hapd->conf) {
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conf_syslog_level = hapd->conf->logger_syslog_level;
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conf_stdout_level = hapd->conf->logger_stdout_level;
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conf_syslog = hapd->conf->logger_syslog;
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conf_stdout = hapd->conf->logger_stdout;
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conf_syslog_level = conf_stdout_level = 0;
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conf_syslog = conf_stdout = (unsigned int) -1;
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (module) {
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case HOSTAPD_MODULE_IEEE80211:
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		module_str = "IEEE 802.11";
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case HOSTAPD_MODULE_IEEE8021X:
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		module_str = "IEEE 802.1X";
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case HOSTAPD_MODULE_RADIUS:
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		module_str = "RADIUS";
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case HOSTAPD_MODULE_WPA:
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		module_str = "WPA";
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case HOSTAPD_MODULE_DRIVER:
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		module_str = "DRIVER";
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case HOSTAPD_MODULE_IAPP:
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		module_str = "IAPP";
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case HOSTAPD_MODULE_MLME:
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		module_str = "MLME";
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		module_str = NULL;
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hapd && hapd->conf && addr)
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_snprintf(format, maxlen, "%s: STA " MACSTR "%s%s: %s",
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    hapd->conf->iface, MAC2STR(addr),
9596be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt			    module_str ? " " : "", module_str ? module_str : "",
9696be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt			    txt);
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (hapd && hapd->conf)
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_snprintf(format, maxlen, "%s:%s%s %s",
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    hapd->conf->iface, module_str ? " " : "",
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    module_str, txt);
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (addr)
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_snprintf(format, maxlen, "STA " MACSTR "%s%s: %s",
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    MAC2STR(addr), module_str ? " " : "",
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    module_str, txt);
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_snprintf(format, maxlen, "%s%s%s",
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    module_str, module_str ? ": " : "", txt);
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((conf_stdout & module) && level >= conf_stdout_level) {
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_debug_print_timestamp();
111cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		wpa_printf(MSG_INFO, "%s", format);
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NATIVE_WINDOWS
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((conf_syslog & module) && level >= conf_syslog_level) {
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int priority;
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		switch (level) {
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case HOSTAPD_LEVEL_DEBUG_VERBOSE:
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case HOSTAPD_LEVEL_DEBUG:
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			priority = LOG_DEBUG;
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case HOSTAPD_LEVEL_INFO:
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			priority = LOG_INFO;
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case HOSTAPD_LEVEL_NOTICE:
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			priority = LOG_NOTICE;
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case HOSTAPD_LEVEL_WARNING:
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			priority = LOG_WARNING;
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		default:
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			priority = LOG_INFO;
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		syslog(priority, "%s", format);
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(format);
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_HOSTAPD_LOGGER */
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
145cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt * hostapd_driver_init - Preparate driver interface
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_driver_init(struct hostapd_iface *iface)
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_init_params params;
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_data *hapd = iface->bss[0];
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_bss_config *conf = hapd->conf;
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *b = conf->bssid;
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_capa capa;
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hapd->driver == NULL || hapd->driver->hapd_init == NULL) {
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "No hostapd driver wrapper available");
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Initialize the driver interface */
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!(b[0] | b[1] | b[2] | b[3] | b[4] | b[5]))
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		b = NULL;
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&params, 0, sizeof(params));
1661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	for (i = 0; wpa_drivers[i]; i++) {
1671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (wpa_drivers[i] != hapd->driver)
1681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			continue;
1691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (global.drv_priv[i] == NULL &&
1711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    wpa_drivers[i]->global_init) {
1721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			global.drv_priv[i] = wpa_drivers[i]->global_init();
1731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			if (global.drv_priv[i] == NULL) {
1741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				wpa_printf(MSG_ERROR, "Failed to initialize "
1751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					   "driver '%s'",
1761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					   wpa_drivers[i]->name);
1771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				return -1;
1781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			}
1791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
1801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		params.global_priv = global.drv_priv[i];
1821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
1831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.bssid = b;
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.ifname = hapd->conf->iface;
18661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	params.ssid = hapd->conf->ssid.ssid;
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.ssid_len = hapd->conf->ssid.ssid_len;
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.test_socket = hapd->conf->test_socket;
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.use_pae_group_addr = hapd->conf->use_pae_group_addr;
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.num_bridge = hapd->iface->num_bss;
19261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	params.bridge = os_calloc(hapd->iface->num_bss, sizeof(char *));
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (params.bridge == NULL)
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < hapd->iface->num_bss; i++) {
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct hostapd_data *bss = hapd->iface->bss[i];
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (bss->conf->bridge[0])
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			params.bridge[i] = bss->conf->bridge;
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.own_addr = hapd->own_addr;
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hapd->drv_priv = hapd->driver->hapd_init(hapd, &params);
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(params.bridge);
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hapd->drv_priv == NULL) {
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "%s driver initialization failed.",
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   hapd->driver->name);
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hapd->driver = NULL;
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hapd->driver->get_capa &&
2131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    hapd->driver->get_capa(hapd->drv_priv, &capa) == 0) {
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		iface->drv_flags = capa.flags;
2151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		iface->probe_resp_offloads = capa.probe_resp_offloads;
216444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt		iface->extended_capa = capa.extended_capa;
217444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt		iface->extended_capa_mask = capa.extended_capa_mask;
218444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt		iface->extended_capa_len = capa.extended_capa_len;
2198bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt		iface->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
2201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
226cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt/**
227cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt * hostapd_interface_init - Read configuration file and init BSS data
228cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt *
229cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt * This function is used to parse configuration file for a full interface (one
230cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt * or more BSSes sharing the same radio) and allocate memory for the BSS
231cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt * interfaces. No actiual driver operations are started.
232cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt */
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct hostapd_iface *
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidthostapd_interface_init(struct hapd_interfaces *interfaces,
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       const char *config_fname, int debug)
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_iface *iface;
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int k;
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_ERROR, "Configuration file: %s", config_fname);
241cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	iface = hostapd_init(interfaces, config_fname);
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!iface)
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	iface->interfaces = interfaces;
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (k = 0; k < debug; k++) {
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (iface->bss[0]->conf->logger_stdout_level > 0)
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			iface->bss[0]->conf->logger_stdout_level--;
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
251cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	if (iface->conf->bss[0]->iface[0] == '\0' &&
2524b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	    !hostapd_drv_none(iface->bss[0])) {
2534b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		wpa_printf(MSG_ERROR, "Interface name not specified in %s",
2544b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt			   config_fname);
2554b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		hostapd_interface_deinit_free(iface);
2564b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		return NULL;
2574b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	}
2584b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return iface;
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * handle_term - SIGINT and SIGTERM handler to terminate hostapd process
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void handle_term(int sig, void *signal_ctx)
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "Signal %d received - terminating", sig);
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_terminate();
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NATIVE_WINDOWS
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int handle_reload_iface(struct hostapd_iface *iface, void *ctx)
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hostapd_reload_config(iface) < 0) {
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_WARNING, "Failed to read new configuration "
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "file - continuing with old.");
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * handle_reload - SIGHUP handler to reload configuration
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void handle_reload(int sig, void *signal_ctx)
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hapd_interfaces *interfaces = signal_ctx;
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "Signal %d received - reloading configuration",
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   sig);
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hostapd_for_each_interface(interfaces, handle_reload_iface, NULL);
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void handle_dump_state(int sig, void *signal_ctx)
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
299fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	/* Not used anymore - ignore signal */
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenstatic int hostapd_global_init(struct hapd_interfaces *interfaces,
30575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			       const char *entropy_file)
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int i;
3081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
3091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_memset(&global, 0, sizeof(global));
3101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hostapd_logger_register_cb(hostapd_logger_cb);
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap_server_register_methods()) {
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Failed to register EAP methods");
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eloop_init()) {
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Failed to initialize event loop");
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	random_init(entropy_file);
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NATIVE_WINDOWS
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_signal(SIGHUP, handle_reload, interfaces);
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_signal(SIGUSR1, handle_dump_state, interfaces);
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_signal_terminate(handle_term, interfaces);
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NATIVE_WINDOWS
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	openlog("hostapd", 0, LOG_DAEMON);
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	for (i = 0; wpa_drivers[i]; i++)
3361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		global.drv_count++;
3371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (global.drv_count == 0) {
3381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_printf(MSG_ERROR, "No drivers enabled");
3391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return -1;
3401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
34161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	global.drv_priv = os_calloc(global.drv_count, sizeof(void *));
3421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (global.drv_priv == NULL)
3431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return -1;
3441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void hostapd_global_deinit(const char *pid_file)
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int i;
3521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
3531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	for (i = 0; wpa_drivers[i] && global.drv_priv; i++) {
3541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (!global.drv_priv[i])
3551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			continue;
3561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_drivers[i]->global_deinit(global.drv_priv[i]);
3571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
3581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_free(global.drv_priv);
3591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	global.drv_priv = NULL;
3601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_TNC
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tncs_global_deinit();
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_TNC */
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	random_deinit();
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_destroy();
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NATIVE_WINDOWS
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	closelog();
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_server_unregister_methods();
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_daemonize_terminate(pid_file);
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_global_run(struct hapd_interfaces *ifaces, int daemonize,
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      const char *pid_file)
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_TNC
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int tnc = 0;
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i, k;
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; !tnc && i < ifaces->count; i++) {
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (k = 0; k < ifaces->iface[i]->num_bss; k++) {
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (ifaces->iface[i]->bss[0]->conf->tnc) {
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				tnc++;
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tnc && tncs_global_init() < 0) {
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Failed to initialize TNCS");
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_TNC */
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (daemonize && os_daemonize(pid_file)) {
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		perror("daemon");
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_run();
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void show_version(void)
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fprintf(stderr,
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"hostapd v" VERSION_STR "\n"
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"User space daemon for IEEE 802.11 AP management,\n"
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n"
418fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		"Copyright (c) 2002-2014, Jouni Malinen <j@w1.fi> "
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"and contributors\n");
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void usage(void)
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	show_version();
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fprintf(stderr,
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"\n"
42875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		"usage: hostapd [-hdBKtv] [-P <PID file>] [-e <entropy file>] "
42961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		"\\\n"
4300ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt		"         [-g <global ctrl_iface>] [-G <group>] \\\n"
4310ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt		"         <configuration file(s)>\n"
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"\n"
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"options:\n"
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"   -h   show this usage\n"
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"   -d   show more debug messages (-dd for even more)\n"
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"   -B   run daemon in the background\n"
43775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		"   -e   entropy file\n"
43861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		"   -g   global control interface path\n"
4390ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt		"   -G   group for control interfaces\n"
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"   -P   PID file\n"
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"   -K   include key data in debug messages\n"
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_DEBUG_FILE
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"   -f   log output to debug file instead of stdout\n"
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_DEBUG_FILE */
445cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt#ifdef CONFIG_DEBUG_LINUX_TRACING
446cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		"   -T = record to Linux tracing in addition to logging\n"
447cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		"        (records all messages regardless of debug verbosity)\n"
448cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt#endif /* CONFIG_DEBUG_LINUX_TRACING */
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"   -t   include timestamps in some debug messages\n"
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"   -v   show hostapd version\n");
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	exit(1);
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * hostapd_msg_ifname_cb(void *ctx)
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_data *hapd = ctx;
459cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	if (hapd && hapd->iconf && hapd->iconf->bss &&
460cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	    hapd->iconf->num_bss > 0 && hapd->iconf->bss[0])
461cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		return hapd->iconf->bss[0]->iface;
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int hostapd_get_global_ctrl_iface(struct hapd_interfaces *interfaces,
46761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					 const char *path)
46861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
46961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	char *pos;
47061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	os_free(interfaces->global_iface_path);
47161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	interfaces->global_iface_path = os_strdup(path);
47261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (interfaces->global_iface_path == NULL)
47361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return -1;
47461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	pos = os_strrchr(interfaces->global_iface_path, '/');
47561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (pos == NULL) {
4761e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt		wpa_printf(MSG_ERROR, "No '/' in the global control interface "
4771e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt			   "file");
47861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		os_free(interfaces->global_iface_path);
47961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		interfaces->global_iface_path = NULL;
48061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return -1;
48161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
48261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
48361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	*pos = '\0';
48461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	interfaces->global_iface_name = pos + 1;
48561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
48661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
48761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
48861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
48961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
4900ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidtstatic int hostapd_get_ctrl_iface_group(struct hapd_interfaces *interfaces,
4910ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt					const char *group)
4920ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt{
4930ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt#ifndef CONFIG_NATIVE_WINDOWS
4940ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt	struct group *grp;
4950ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt	grp = getgrnam(group);
4960ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt	if (grp == NULL) {
4970ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt		wpa_printf(MSG_ERROR, "Unknown group '%s'", group);
4980ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt		return -1;
4990ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt	}
5000ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt	interfaces->ctrl_iface_group = grp->gr_gid;
5010ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */
5020ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt	return 0;
5030ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt}
5040ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt
5050ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt
50696be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt#ifdef CONFIG_WPS
50796be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidtstatic int gen_uuid(const char *txt_addr)
50896be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt{
50996be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt	u8 addr[ETH_ALEN];
51096be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt	u8 uuid[UUID_LEN];
51196be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt	char buf[100];
51296be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt
51396be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt	if (hwaddr_aton(txt_addr, addr) < 0)
51496be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt		return -1;
51596be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt
51696be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt	uuid_gen_mac_addr(addr, uuid);
51796be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt	if (uuid_bin2str(uuid, buf, sizeof(buf)) < 0)
51896be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt		return -1;
51996be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt
52096be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt	printf("%s\n", buf);
52196be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt
52296be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt	return 0;
52396be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt}
52496be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt#endif /* CONFIG_WPS */
52596be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt
52696be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint main(int argc, char *argv[])
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hapd_interfaces interfaces;
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret = 1;
531cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	size_t i, j;
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int c, debug = 0, daemonize = 0;
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *pid_file = NULL;
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *log_file = NULL;
53575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	const char *entropy_file = NULL;
536cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	char **bss_config = NULL, **tmp_bss;
537cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	size_t num_bss_configs = 0;
538cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt#ifdef CONFIG_DEBUG_LINUX_TRACING
539cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	int enable_trace_dbg = 0;
540cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt#endif /* CONFIG_DEBUG_LINUX_TRACING */
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_program_init())
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
54561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	os_memset(&interfaces, 0, sizeof(interfaces));
54661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	interfaces.reload_config = hostapd_reload_config;
54761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	interfaces.config_read_cb = hostapd_config_read;
54861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	interfaces.for_each_interface = hostapd_for_each_interface;
54961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	interfaces.ctrl_iface_init = hostapd_ctrl_iface_init;
55061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	interfaces.ctrl_iface_deinit = hostapd_ctrl_iface_deinit;
55161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	interfaces.driver_init = hostapd_driver_init;
55261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	interfaces.global_iface_path = NULL;
55361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	interfaces.global_iface_name = NULL;
55461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	interfaces.global_ctrl_sock = -1;
55561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (;;) {
55796be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt		c = getopt(argc, argv, "b:Bde:f:hKP:Ttu:vg:G:");
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (c < 0)
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		switch (c) {
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'h':
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			usage();
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'd':
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			debug++;
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (wpa_debug_level > 0)
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_debug_level--;
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'B':
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			daemonize++;
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
57275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		case 'e':
57375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			entropy_file = optarg;
57475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			break;
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'f':
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			log_file = optarg;
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'K':
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_debug_show_keys++;
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'P':
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(pid_file);
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pid_file = os_rel2abs_path(optarg);
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 't':
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_debug_timestamp++;
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
588cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt#ifdef CONFIG_DEBUG_LINUX_TRACING
589cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		case 'T':
590cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			enable_trace_dbg = 1;
591cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			break;
592cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt#endif /* CONFIG_DEBUG_LINUX_TRACING */
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'v':
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			show_version();
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			exit(1);
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
59761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		case 'g':
5981e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt			if (hostapd_get_global_ctrl_iface(&interfaces, optarg))
5991e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt				return -1;
60061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			break;
6010ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt		case 'G':
6021e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt			if (hostapd_get_ctrl_iface_group(&interfaces, optarg))
6031e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt				return -1;
6040ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt			break;
605cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		case 'b':
606cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			tmp_bss = os_realloc_array(bss_config,
607cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt						   num_bss_configs + 1,
608cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt						   sizeof(char *));
609cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			if (tmp_bss == NULL)
610cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt				goto out;
611cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			bss_config = tmp_bss;
612cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			bss_config[num_bss_configs++] = optarg;
613cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			break;
61496be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt#ifdef CONFIG_WPS
61596be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt		case 'u':
61696be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt			return gen_uuid(optarg);
61796be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt#endif /* CONFIG_WPS */
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		default:
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			usage();
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
624cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	if (optind == argc && interfaces.global_iface_path == NULL &&
625cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	    num_bss_configs == 0)
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		usage();
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg_register_ifname_cb(hostapd_msg_ifname_cb);
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (log_file)
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_debug_open_file(log_file);
632cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt#ifdef CONFIG_DEBUG_LINUX_TRACING
633cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	if (enable_trace_dbg) {
634cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		int tret = wpa_debug_open_linux_tracing();
635cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		if (tret) {
636cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			wpa_printf(MSG_ERROR, "Failed to enable trace logging");
637cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			return -1;
638cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		}
639cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	}
640cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt#endif /* CONFIG_DEBUG_LINUX_TRACING */
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	interfaces.count = argc - optind;
643cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	if (interfaces.count || num_bss_configs) {
644cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		interfaces.iface = os_calloc(interfaces.count + num_bss_configs,
64561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					     sizeof(struct hostapd_iface *));
64661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (interfaces.iface == NULL) {
64761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpa_printf(MSG_ERROR, "malloc failed");
64861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
64961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6524b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	if (hostapd_global_init(&interfaces, entropy_file)) {
6534b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		wpa_printf(MSG_ERROR, "Failed to initilize global context");
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6554b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	}
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
657cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	/* Allocate and parse configuration for full interface files */
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < interfaces.count; i++) {
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		interfaces.iface[i] = hostapd_interface_init(&interfaces,
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							     argv[optind + i],
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							     debug);
6624b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		if (!interfaces.iface[i]) {
6634b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt			wpa_printf(MSG_ERROR, "Failed to initialize interface");
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto out;
6654b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		}
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
668cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	/* Allocate and parse configuration for per-BSS files */
669cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	for (i = 0; i < num_bss_configs; i++) {
670cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		struct hostapd_iface *iface;
671cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		char *fname;
672cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt
673cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		wpa_printf(MSG_INFO, "BSS config: %s", bss_config[i]);
674cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		fname = os_strchr(bss_config[i], ':');
675cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		if (fname == NULL) {
676cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			wpa_printf(MSG_ERROR,
677cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt				   "Invalid BSS config identifier '%s'",
678cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt				   bss_config[i]);
679cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			goto out;
680cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		}
681cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		*fname++ = '\0';
682cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		iface = hostapd_interface_init_bss(&interfaces, bss_config[i],
683cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt						   fname, debug);
684cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		if (iface == NULL)
685cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			goto out;
686cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		for (j = 0; j < interfaces.count; j++) {
687cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			if (interfaces.iface[j] == iface)
688cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt				break;
689cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		}
690cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		if (j == interfaces.count) {
691cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			struct hostapd_iface **tmp;
692cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			tmp = os_realloc_array(interfaces.iface,
693cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt					       interfaces.count + 1,
694cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt					       sizeof(struct hostapd_iface *));
695cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			if (tmp == NULL) {
696cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt				hostapd_interface_deinit_free(iface);
697cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt				goto out;
698cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			}
699cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			interfaces.iface = tmp;
700cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			interfaces.iface[interfaces.count++] = iface;
701cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		}
702cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	}
703cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt
704cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	/*
705cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	 * Enable configured interfaces. Depending on channel configuration,
706cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	 * this may complete full initialization before returning or use a
707cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	 * callback mechanism to complete setup in case of operations like HT
708cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	 * co-ex scans, ACS, or DFS are needed to determine channel parameters.
709cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	 * In such case, the interface will be enabled from eloop context within
710cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	 * hostapd_global_run().
711cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	 */
712b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt	interfaces.terminate_on_error = interfaces.count;
713cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	for (i = 0; i < interfaces.count; i++) {
714cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		if (hostapd_driver_init(interfaces.iface[i]) ||
715cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		    hostapd_setup_interface(interfaces.iface[i]))
716cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			goto out;
717cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	}
718cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt
71961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	hostapd_global_ctrl_iface_init(&interfaces);
72061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
7214b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	if (hostapd_global_run(&interfaces, daemonize, pid_file)) {
7224b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		wpa_printf(MSG_ERROR, "Failed to start eloop");
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
7244b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	}
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = 0;
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt out:
72961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	hostapd_global_ctrl_iface_deinit(&interfaces);
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Deinitialize all interfaces */
731a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt	for (i = 0; i < interfaces.count; i++) {
732818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		if (!interfaces.iface[i])
733818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			continue;
734a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt		interfaces.iface[i]->driver_ap_teardown =
735a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt			!!(interfaces.iface[i]->drv_flags &
736a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt			   WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT);
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hostapd_interface_deinit_free(interfaces.iface[i]);
738a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt	}
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(interfaces.iface);
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hostapd_global_deinit(pid_file);
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(pid_file);
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (log_file)
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_debug_close_file();
746cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	wpa_debug_close_linux_tracing();
747cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt
748cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	os_free(bss_config);
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_program_deinit();
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
754