1e5b75505Sopenharmony_ci/* 2e5b75505Sopenharmony_ci * hostapd / main() 3e5b75505Sopenharmony_ci * Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi> 4e5b75505Sopenharmony_ci * 5e5b75505Sopenharmony_ci * This software may be distributed under the terms of the BSD license. 6e5b75505Sopenharmony_ci * See README for more details. 7e5b75505Sopenharmony_ci */ 8e5b75505Sopenharmony_ci 9e5b75505Sopenharmony_ci#include "utils/includes.h" 10e5b75505Sopenharmony_ci#ifndef CONFIG_NATIVE_WINDOWS 11e5b75505Sopenharmony_ci#include <syslog.h> 12e5b75505Sopenharmony_ci#include <grp.h> 13e5b75505Sopenharmony_ci#endif /* CONFIG_NATIVE_WINDOWS */ 14e5b75505Sopenharmony_ci 15e5b75505Sopenharmony_ci#include "utils/common.h" 16e5b75505Sopenharmony_ci#include "utils/eloop.h" 17e5b75505Sopenharmony_ci#include "utils/uuid.h" 18e5b75505Sopenharmony_ci#include "crypto/random.h" 19e5b75505Sopenharmony_ci#include "crypto/tls.h" 20e5b75505Sopenharmony_ci#include "common/version.h" 21e5b75505Sopenharmony_ci#include "common/dpp.h" 22e5b75505Sopenharmony_ci#include "drivers/driver.h" 23e5b75505Sopenharmony_ci#include "eap_server/eap.h" 24e5b75505Sopenharmony_ci#include "eap_server/tncs.h" 25e5b75505Sopenharmony_ci#include "ap/hostapd.h" 26e5b75505Sopenharmony_ci#include "ap/ap_config.h" 27e5b75505Sopenharmony_ci#include "ap/ap_drv_ops.h" 28e5b75505Sopenharmony_ci#include "ap/dpp_hostapd.h" 29e5b75505Sopenharmony_ci#include "fst/fst.h" 30e5b75505Sopenharmony_ci#include "config_file.h" 31e5b75505Sopenharmony_ci#include "eap_register.h" 32e5b75505Sopenharmony_ci#include "ctrl_iface.h" 33e5b75505Sopenharmony_ci 34e5b75505Sopenharmony_ci 35e5b75505Sopenharmony_cistruct hapd_global { 36e5b75505Sopenharmony_ci void **drv_priv; 37e5b75505Sopenharmony_ci size_t drv_count; 38e5b75505Sopenharmony_ci}; 39e5b75505Sopenharmony_ci 40e5b75505Sopenharmony_cistatic struct hapd_global global; 41e5b75505Sopenharmony_ci 42e5b75505Sopenharmony_ci 43e5b75505Sopenharmony_ci#ifndef CONFIG_NO_HOSTAPD_LOGGER 44e5b75505Sopenharmony_cistatic void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module, 45e5b75505Sopenharmony_ci int level, const char *txt, size_t len) 46e5b75505Sopenharmony_ci{ 47e5b75505Sopenharmony_ci struct hostapd_data *hapd = ctx; 48e5b75505Sopenharmony_ci char *format, *module_str; 49e5b75505Sopenharmony_ci int maxlen; 50e5b75505Sopenharmony_ci int conf_syslog_level, conf_stdout_level; 51e5b75505Sopenharmony_ci unsigned int conf_syslog, conf_stdout; 52e5b75505Sopenharmony_ci 53e5b75505Sopenharmony_ci maxlen = len + 100; 54e5b75505Sopenharmony_ci format = os_malloc(maxlen); 55e5b75505Sopenharmony_ci if (!format) 56e5b75505Sopenharmony_ci return; 57e5b75505Sopenharmony_ci 58e5b75505Sopenharmony_ci if (hapd && hapd->conf) { 59e5b75505Sopenharmony_ci conf_syslog_level = hapd->conf->logger_syslog_level; 60e5b75505Sopenharmony_ci conf_stdout_level = hapd->conf->logger_stdout_level; 61e5b75505Sopenharmony_ci conf_syslog = hapd->conf->logger_syslog; 62e5b75505Sopenharmony_ci conf_stdout = hapd->conf->logger_stdout; 63e5b75505Sopenharmony_ci } else { 64e5b75505Sopenharmony_ci conf_syslog_level = conf_stdout_level = 0; 65e5b75505Sopenharmony_ci conf_syslog = conf_stdout = (unsigned int) -1; 66e5b75505Sopenharmony_ci } 67e5b75505Sopenharmony_ci 68e5b75505Sopenharmony_ci switch (module) { 69e5b75505Sopenharmony_ci case HOSTAPD_MODULE_IEEE80211: 70e5b75505Sopenharmony_ci module_str = "IEEE 802.11"; 71e5b75505Sopenharmony_ci break; 72e5b75505Sopenharmony_ci case HOSTAPD_MODULE_IEEE8021X: 73e5b75505Sopenharmony_ci module_str = "IEEE 802.1X"; 74e5b75505Sopenharmony_ci break; 75e5b75505Sopenharmony_ci case HOSTAPD_MODULE_RADIUS: 76e5b75505Sopenharmony_ci module_str = "RADIUS"; 77e5b75505Sopenharmony_ci break; 78e5b75505Sopenharmony_ci case HOSTAPD_MODULE_WPA: 79e5b75505Sopenharmony_ci module_str = "WPA"; 80e5b75505Sopenharmony_ci break; 81e5b75505Sopenharmony_ci case HOSTAPD_MODULE_DRIVER: 82e5b75505Sopenharmony_ci module_str = "DRIVER"; 83e5b75505Sopenharmony_ci break; 84e5b75505Sopenharmony_ci case HOSTAPD_MODULE_IAPP: 85e5b75505Sopenharmony_ci module_str = "IAPP"; 86e5b75505Sopenharmony_ci break; 87e5b75505Sopenharmony_ci case HOSTAPD_MODULE_MLME: 88e5b75505Sopenharmony_ci module_str = "MLME"; 89e5b75505Sopenharmony_ci break; 90e5b75505Sopenharmony_ci default: 91e5b75505Sopenharmony_ci module_str = NULL; 92e5b75505Sopenharmony_ci break; 93e5b75505Sopenharmony_ci } 94e5b75505Sopenharmony_ci 95e5b75505Sopenharmony_ci if (hapd && hapd->conf && addr) 96e5b75505Sopenharmony_ci os_snprintf(format, maxlen, "%s: STA " MACSTR "%s%s: %s", 97e5b75505Sopenharmony_ci hapd->conf->iface, MAC2STR(addr), 98e5b75505Sopenharmony_ci module_str ? " " : "", module_str ? module_str : "", 99e5b75505Sopenharmony_ci txt); 100e5b75505Sopenharmony_ci else if (hapd && hapd->conf) 101e5b75505Sopenharmony_ci os_snprintf(format, maxlen, "%s:%s%s %s", 102e5b75505Sopenharmony_ci hapd->conf->iface, module_str ? " " : "", 103e5b75505Sopenharmony_ci module_str ? module_str : "", txt); 104e5b75505Sopenharmony_ci else if (addr) 105e5b75505Sopenharmony_ci os_snprintf(format, maxlen, "STA " MACSTR "%s%s: %s", 106e5b75505Sopenharmony_ci MAC2STR(addr), module_str ? " " : "", 107e5b75505Sopenharmony_ci module_str ? module_str : "", txt); 108e5b75505Sopenharmony_ci else 109e5b75505Sopenharmony_ci os_snprintf(format, maxlen, "%s%s%s", 110e5b75505Sopenharmony_ci module_str ? module_str : "", 111e5b75505Sopenharmony_ci module_str ? ": " : "", txt); 112e5b75505Sopenharmony_ci 113e5b75505Sopenharmony_ci#ifdef CONFIG_DEBUG_SYSLOG 114e5b75505Sopenharmony_ci if (wpa_debug_syslog) 115e5b75505Sopenharmony_ci conf_stdout = 0; 116e5b75505Sopenharmony_ci#endif /* CONFIG_DEBUG_SYSLOG */ 117e5b75505Sopenharmony_ci if ((conf_stdout & module) && level >= conf_stdout_level) { 118e5b75505Sopenharmony_ci wpa_debug_print_timestamp(); 119e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "%s", format); 120e5b75505Sopenharmony_ci } 121e5b75505Sopenharmony_ci 122e5b75505Sopenharmony_ci#ifndef CONFIG_NATIVE_WINDOWS 123e5b75505Sopenharmony_ci if ((conf_syslog & module) && level >= conf_syslog_level) { 124e5b75505Sopenharmony_ci int priority; 125e5b75505Sopenharmony_ci switch (level) { 126e5b75505Sopenharmony_ci case HOSTAPD_LEVEL_DEBUG_VERBOSE: 127e5b75505Sopenharmony_ci case HOSTAPD_LEVEL_DEBUG: 128e5b75505Sopenharmony_ci priority = LOG_DEBUG; 129e5b75505Sopenharmony_ci break; 130e5b75505Sopenharmony_ci case HOSTAPD_LEVEL_INFO: 131e5b75505Sopenharmony_ci priority = LOG_INFO; 132e5b75505Sopenharmony_ci break; 133e5b75505Sopenharmony_ci case HOSTAPD_LEVEL_NOTICE: 134e5b75505Sopenharmony_ci priority = LOG_NOTICE; 135e5b75505Sopenharmony_ci break; 136e5b75505Sopenharmony_ci case HOSTAPD_LEVEL_WARNING: 137e5b75505Sopenharmony_ci priority = LOG_WARNING; 138e5b75505Sopenharmony_ci break; 139e5b75505Sopenharmony_ci default: 140e5b75505Sopenharmony_ci priority = LOG_INFO; 141e5b75505Sopenharmony_ci break; 142e5b75505Sopenharmony_ci } 143e5b75505Sopenharmony_ci syslog(priority, "%s", format); 144e5b75505Sopenharmony_ci } 145e5b75505Sopenharmony_ci#endif /* CONFIG_NATIVE_WINDOWS */ 146e5b75505Sopenharmony_ci 147e5b75505Sopenharmony_ci os_free(format); 148e5b75505Sopenharmony_ci} 149e5b75505Sopenharmony_ci#endif /* CONFIG_NO_HOSTAPD_LOGGER */ 150e5b75505Sopenharmony_ci 151e5b75505Sopenharmony_ci 152e5b75505Sopenharmony_ci/** 153e5b75505Sopenharmony_ci * hostapd_driver_init - Preparate driver interface 154e5b75505Sopenharmony_ci */ 155e5b75505Sopenharmony_cistatic int hostapd_driver_init(struct hostapd_iface *iface) 156e5b75505Sopenharmony_ci{ 157e5b75505Sopenharmony_ci struct wpa_init_params params; 158e5b75505Sopenharmony_ci size_t i; 159e5b75505Sopenharmony_ci struct hostapd_data *hapd = iface->bss[0]; 160e5b75505Sopenharmony_ci struct hostapd_bss_config *conf = hapd->conf; 161e5b75505Sopenharmony_ci u8 *b = conf->bssid; 162e5b75505Sopenharmony_ci struct wpa_driver_capa capa; 163e5b75505Sopenharmony_ci 164e5b75505Sopenharmony_ci if (hapd->driver == NULL || hapd->driver->hapd_init == NULL) { 165e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "No hostapd driver wrapper available"); 166e5b75505Sopenharmony_ci return -1; 167e5b75505Sopenharmony_ci } 168e5b75505Sopenharmony_ci 169e5b75505Sopenharmony_ci /* Initialize the driver interface */ 170e5b75505Sopenharmony_ci if (!(b[0] | b[1] | b[2] | b[3] | b[4] | b[5])) 171e5b75505Sopenharmony_ci b = NULL; 172e5b75505Sopenharmony_ci 173e5b75505Sopenharmony_ci os_memset(¶ms, 0, sizeof(params)); 174e5b75505Sopenharmony_ci for (i = 0; wpa_drivers[i]; i++) { 175e5b75505Sopenharmony_ci if (wpa_drivers[i] != hapd->driver) 176e5b75505Sopenharmony_ci continue; 177e5b75505Sopenharmony_ci 178e5b75505Sopenharmony_ci if (global.drv_priv[i] == NULL && 179e5b75505Sopenharmony_ci wpa_drivers[i]->global_init) { 180e5b75505Sopenharmony_ci global.drv_priv[i] = 181e5b75505Sopenharmony_ci wpa_drivers[i]->global_init(iface->interfaces); 182e5b75505Sopenharmony_ci if (global.drv_priv[i] == NULL) { 183e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "Failed to initialize " 184e5b75505Sopenharmony_ci "driver '%s'", 185e5b75505Sopenharmony_ci wpa_drivers[i]->name); 186e5b75505Sopenharmony_ci return -1; 187e5b75505Sopenharmony_ci } 188e5b75505Sopenharmony_ci } 189e5b75505Sopenharmony_ci 190e5b75505Sopenharmony_ci params.global_priv = global.drv_priv[i]; 191e5b75505Sopenharmony_ci break; 192e5b75505Sopenharmony_ci } 193e5b75505Sopenharmony_ci params.bssid = b; 194e5b75505Sopenharmony_ci params.ifname = hapd->conf->iface; 195e5b75505Sopenharmony_ci params.driver_params = hapd->iconf->driver_params; 196e5b75505Sopenharmony_ci params.use_pae_group_addr = hapd->conf->use_pae_group_addr; 197e5b75505Sopenharmony_ci 198e5b75505Sopenharmony_ci params.num_bridge = hapd->iface->num_bss; 199e5b75505Sopenharmony_ci params.bridge = os_calloc(hapd->iface->num_bss, sizeof(char *)); 200e5b75505Sopenharmony_ci if (params.bridge == NULL) 201e5b75505Sopenharmony_ci return -1; 202e5b75505Sopenharmony_ci for (i = 0; i < hapd->iface->num_bss; i++) { 203e5b75505Sopenharmony_ci struct hostapd_data *bss = hapd->iface->bss[i]; 204e5b75505Sopenharmony_ci if (bss->conf->bridge[0]) 205e5b75505Sopenharmony_ci params.bridge[i] = bss->conf->bridge; 206e5b75505Sopenharmony_ci } 207e5b75505Sopenharmony_ci 208e5b75505Sopenharmony_ci params.own_addr = hapd->own_addr; 209e5b75505Sopenharmony_ci 210e5b75505Sopenharmony_ci hapd->drv_priv = hapd->driver->hapd_init(hapd, ¶ms); 211e5b75505Sopenharmony_ci os_free(params.bridge); 212e5b75505Sopenharmony_ci if (hapd->drv_priv == NULL) { 213e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "%s driver initialization failed.", 214e5b75505Sopenharmony_ci hapd->driver->name); 215e5b75505Sopenharmony_ci hapd->driver = NULL; 216e5b75505Sopenharmony_ci return -1; 217e5b75505Sopenharmony_ci } 218e5b75505Sopenharmony_ci 219e5b75505Sopenharmony_ci if (hapd->driver->get_capa && 220e5b75505Sopenharmony_ci hapd->driver->get_capa(hapd->drv_priv, &capa) == 0) { 221e5b75505Sopenharmony_ci struct wowlan_triggers *triggs; 222e5b75505Sopenharmony_ci 223e5b75505Sopenharmony_ci iface->drv_flags = capa.flags; 224e5b75505Sopenharmony_ci iface->smps_modes = capa.smps_modes; 225e5b75505Sopenharmony_ci iface->probe_resp_offloads = capa.probe_resp_offloads; 226e5b75505Sopenharmony_ci /* 227e5b75505Sopenharmony_ci * Use default extended capa values from per-radio information 228e5b75505Sopenharmony_ci */ 229e5b75505Sopenharmony_ci iface->extended_capa = capa.extended_capa; 230e5b75505Sopenharmony_ci iface->extended_capa_mask = capa.extended_capa_mask; 231e5b75505Sopenharmony_ci iface->extended_capa_len = capa.extended_capa_len; 232e5b75505Sopenharmony_ci iface->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs; 233e5b75505Sopenharmony_ci 234e5b75505Sopenharmony_ci /* 235e5b75505Sopenharmony_ci * Override extended capa with per-interface type (AP), if 236e5b75505Sopenharmony_ci * available from the driver. 237e5b75505Sopenharmony_ci */ 238e5b75505Sopenharmony_ci hostapd_get_ext_capa(iface); 239e5b75505Sopenharmony_ci 240e5b75505Sopenharmony_ci triggs = wpa_get_wowlan_triggers(conf->wowlan_triggers, &capa); 241e5b75505Sopenharmony_ci if (triggs && hapd->driver->set_wowlan) { 242e5b75505Sopenharmony_ci if (hapd->driver->set_wowlan(hapd->drv_priv, triggs)) 243e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "set_wowlan failed"); 244e5b75505Sopenharmony_ci } 245e5b75505Sopenharmony_ci os_free(triggs); 246e5b75505Sopenharmony_ci } 247e5b75505Sopenharmony_ci 248e5b75505Sopenharmony_ci return 0; 249e5b75505Sopenharmony_ci} 250e5b75505Sopenharmony_ci 251e5b75505Sopenharmony_ci 252e5b75505Sopenharmony_ci/** 253e5b75505Sopenharmony_ci * hostapd_interface_init - Read configuration file and init BSS data 254e5b75505Sopenharmony_ci * 255e5b75505Sopenharmony_ci * This function is used to parse configuration file for a full interface (one 256e5b75505Sopenharmony_ci * or more BSSes sharing the same radio) and allocate memory for the BSS 257e5b75505Sopenharmony_ci * interfaces. No actual driver operations are started. 258e5b75505Sopenharmony_ci */ 259e5b75505Sopenharmony_cistatic struct hostapd_iface * 260e5b75505Sopenharmony_cihostapd_interface_init(struct hapd_interfaces *interfaces, const char *if_name, 261e5b75505Sopenharmony_ci const char *config_fname, int debug) 262e5b75505Sopenharmony_ci{ 263e5b75505Sopenharmony_ci struct hostapd_iface *iface; 264e5b75505Sopenharmony_ci int k; 265e5b75505Sopenharmony_ci 266e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "Configuration file: %s", config_fname); 267e5b75505Sopenharmony_ci iface = hostapd_init(interfaces, config_fname); 268e5b75505Sopenharmony_ci if (!iface) 269e5b75505Sopenharmony_ci return NULL; 270e5b75505Sopenharmony_ci 271e5b75505Sopenharmony_ci if (if_name) { 272e5b75505Sopenharmony_ci os_strlcpy(iface->conf->bss[0]->iface, if_name, 273e5b75505Sopenharmony_ci sizeof(iface->conf->bss[0]->iface)); 274e5b75505Sopenharmony_ci } 275e5b75505Sopenharmony_ci 276e5b75505Sopenharmony_ci iface->interfaces = interfaces; 277e5b75505Sopenharmony_ci 278e5b75505Sopenharmony_ci for (k = 0; k < debug; k++) { 279e5b75505Sopenharmony_ci if (iface->bss[0]->conf->logger_stdout_level > 0) 280e5b75505Sopenharmony_ci iface->bss[0]->conf->logger_stdout_level--; 281e5b75505Sopenharmony_ci } 282e5b75505Sopenharmony_ci 283e5b75505Sopenharmony_ci if (iface->conf->bss[0]->iface[0] == '\0' && 284e5b75505Sopenharmony_ci !hostapd_drv_none(iface->bss[0])) { 285e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, 286e5b75505Sopenharmony_ci "Interface name not specified in %s, nor by '-i' parameter", 287e5b75505Sopenharmony_ci config_fname); 288e5b75505Sopenharmony_ci hostapd_interface_deinit_free(iface); 289e5b75505Sopenharmony_ci return NULL; 290e5b75505Sopenharmony_ci } 291e5b75505Sopenharmony_ci 292e5b75505Sopenharmony_ci return iface; 293e5b75505Sopenharmony_ci} 294e5b75505Sopenharmony_ci 295e5b75505Sopenharmony_ci 296e5b75505Sopenharmony_ci/** 297e5b75505Sopenharmony_ci * handle_term - SIGINT and SIGTERM handler to terminate hostapd process 298e5b75505Sopenharmony_ci */ 299e5b75505Sopenharmony_cistatic void handle_term(int sig, void *signal_ctx) 300e5b75505Sopenharmony_ci{ 301e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Signal %d received - terminating", sig); 302e5b75505Sopenharmony_ci eloop_terminate(); 303e5b75505Sopenharmony_ci} 304e5b75505Sopenharmony_ci 305e5b75505Sopenharmony_ci 306e5b75505Sopenharmony_ci#ifndef CONFIG_NATIVE_WINDOWS 307e5b75505Sopenharmony_ci 308e5b75505Sopenharmony_cistatic int handle_reload_iface(struct hostapd_iface *iface, void *ctx) 309e5b75505Sopenharmony_ci{ 310e5b75505Sopenharmony_ci if (hostapd_reload_config(iface) < 0) { 311e5b75505Sopenharmony_ci wpa_printf(MSG_WARNING, "Failed to read new configuration " 312e5b75505Sopenharmony_ci "file - continuing with old."); 313e5b75505Sopenharmony_ci } 314e5b75505Sopenharmony_ci return 0; 315e5b75505Sopenharmony_ci} 316e5b75505Sopenharmony_ci 317e5b75505Sopenharmony_ci 318e5b75505Sopenharmony_ci/** 319e5b75505Sopenharmony_ci * handle_reload - SIGHUP handler to reload configuration 320e5b75505Sopenharmony_ci */ 321e5b75505Sopenharmony_cistatic void handle_reload(int sig, void *signal_ctx) 322e5b75505Sopenharmony_ci{ 323e5b75505Sopenharmony_ci struct hapd_interfaces *interfaces = signal_ctx; 324e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Signal %d received - reloading configuration", 325e5b75505Sopenharmony_ci sig); 326e5b75505Sopenharmony_ci hostapd_for_each_interface(interfaces, handle_reload_iface, NULL); 327e5b75505Sopenharmony_ci} 328e5b75505Sopenharmony_ci 329e5b75505Sopenharmony_ci 330e5b75505Sopenharmony_cistatic void handle_dump_state(int sig, void *signal_ctx) 331e5b75505Sopenharmony_ci{ 332e5b75505Sopenharmony_ci /* Not used anymore - ignore signal */ 333e5b75505Sopenharmony_ci} 334e5b75505Sopenharmony_ci#endif /* CONFIG_NATIVE_WINDOWS */ 335e5b75505Sopenharmony_ci 336e5b75505Sopenharmony_ci 337e5b75505Sopenharmony_cistatic int hostapd_global_init(struct hapd_interfaces *interfaces, 338e5b75505Sopenharmony_ci const char *entropy_file) 339e5b75505Sopenharmony_ci{ 340e5b75505Sopenharmony_ci int i; 341e5b75505Sopenharmony_ci 342e5b75505Sopenharmony_ci os_memset(&global, 0, sizeof(global)); 343e5b75505Sopenharmony_ci 344e5b75505Sopenharmony_ci hostapd_logger_register_cb(hostapd_logger_cb); 345e5b75505Sopenharmony_ci 346e5b75505Sopenharmony_ci if (eap_server_register_methods()) { 347e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "Failed to register EAP methods"); 348e5b75505Sopenharmony_ci return -1; 349e5b75505Sopenharmony_ci } 350e5b75505Sopenharmony_ci 351e5b75505Sopenharmony_ci if (eloop_init()) { 352e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "Failed to initialize event loop"); 353e5b75505Sopenharmony_ci return -1; 354e5b75505Sopenharmony_ci } 355e5b75505Sopenharmony_ci interfaces->eloop_initialized = 1; 356e5b75505Sopenharmony_ci 357e5b75505Sopenharmony_ci random_init(entropy_file); 358e5b75505Sopenharmony_ci 359e5b75505Sopenharmony_ci#ifndef CONFIG_NATIVE_WINDOWS 360e5b75505Sopenharmony_ci eloop_register_signal(SIGHUP, handle_reload, interfaces); 361e5b75505Sopenharmony_ci eloop_register_signal(SIGUSR1, handle_dump_state, interfaces); 362e5b75505Sopenharmony_ci#endif /* CONFIG_NATIVE_WINDOWS */ 363e5b75505Sopenharmony_ci eloop_register_signal_terminate(handle_term, interfaces); 364e5b75505Sopenharmony_ci 365e5b75505Sopenharmony_ci#ifndef CONFIG_NATIVE_WINDOWS 366e5b75505Sopenharmony_ci openlog("hostapd", 0, LOG_DAEMON); 367e5b75505Sopenharmony_ci#endif /* CONFIG_NATIVE_WINDOWS */ 368e5b75505Sopenharmony_ci 369e5b75505Sopenharmony_ci for (i = 0; wpa_drivers[i]; i++) 370e5b75505Sopenharmony_ci global.drv_count++; 371e5b75505Sopenharmony_ci if (global.drv_count == 0) { 372e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "No drivers enabled"); 373e5b75505Sopenharmony_ci return -1; 374e5b75505Sopenharmony_ci } 375e5b75505Sopenharmony_ci global.drv_priv = os_calloc(global.drv_count, sizeof(void *)); 376e5b75505Sopenharmony_ci if (global.drv_priv == NULL) 377e5b75505Sopenharmony_ci return -1; 378e5b75505Sopenharmony_ci 379e5b75505Sopenharmony_ci return 0; 380e5b75505Sopenharmony_ci} 381e5b75505Sopenharmony_ci 382e5b75505Sopenharmony_ci 383e5b75505Sopenharmony_cistatic void hostapd_global_deinit(const char *pid_file, int eloop_initialized) 384e5b75505Sopenharmony_ci{ 385e5b75505Sopenharmony_ci int i; 386e5b75505Sopenharmony_ci 387e5b75505Sopenharmony_ci for (i = 0; wpa_drivers[i] && global.drv_priv; i++) { 388e5b75505Sopenharmony_ci if (!global.drv_priv[i]) 389e5b75505Sopenharmony_ci continue; 390e5b75505Sopenharmony_ci wpa_drivers[i]->global_deinit(global.drv_priv[i]); 391e5b75505Sopenharmony_ci } 392e5b75505Sopenharmony_ci os_free(global.drv_priv); 393e5b75505Sopenharmony_ci global.drv_priv = NULL; 394e5b75505Sopenharmony_ci 395e5b75505Sopenharmony_ci#ifdef EAP_SERVER_TNC 396e5b75505Sopenharmony_ci tncs_global_deinit(); 397e5b75505Sopenharmony_ci#endif /* EAP_SERVER_TNC */ 398e5b75505Sopenharmony_ci 399e5b75505Sopenharmony_ci random_deinit(); 400e5b75505Sopenharmony_ci 401e5b75505Sopenharmony_ci if (eloop_initialized) 402e5b75505Sopenharmony_ci eloop_destroy(); 403e5b75505Sopenharmony_ci 404e5b75505Sopenharmony_ci#ifndef CONFIG_NATIVE_WINDOWS 405e5b75505Sopenharmony_ci closelog(); 406e5b75505Sopenharmony_ci#endif /* CONFIG_NATIVE_WINDOWS */ 407e5b75505Sopenharmony_ci 408e5b75505Sopenharmony_ci eap_server_unregister_methods(); 409e5b75505Sopenharmony_ci 410e5b75505Sopenharmony_ci os_daemonize_terminate(pid_file); 411e5b75505Sopenharmony_ci} 412e5b75505Sopenharmony_ci 413e5b75505Sopenharmony_ci 414e5b75505Sopenharmony_cistatic int hostapd_global_run(struct hapd_interfaces *ifaces, int daemonize, 415e5b75505Sopenharmony_ci const char *pid_file) 416e5b75505Sopenharmony_ci{ 417e5b75505Sopenharmony_ci#ifdef EAP_SERVER_TNC 418e5b75505Sopenharmony_ci int tnc = 0; 419e5b75505Sopenharmony_ci size_t i, k; 420e5b75505Sopenharmony_ci 421e5b75505Sopenharmony_ci for (i = 0; !tnc && i < ifaces->count; i++) { 422e5b75505Sopenharmony_ci for (k = 0; k < ifaces->iface[i]->num_bss; k++) { 423e5b75505Sopenharmony_ci if (ifaces->iface[i]->bss[0]->conf->tnc) { 424e5b75505Sopenharmony_ci tnc++; 425e5b75505Sopenharmony_ci break; 426e5b75505Sopenharmony_ci } 427e5b75505Sopenharmony_ci } 428e5b75505Sopenharmony_ci } 429e5b75505Sopenharmony_ci 430e5b75505Sopenharmony_ci if (tnc && tncs_global_init() < 0) { 431e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "Failed to initialize TNCS"); 432e5b75505Sopenharmony_ci return -1; 433e5b75505Sopenharmony_ci } 434e5b75505Sopenharmony_ci#endif /* EAP_SERVER_TNC */ 435e5b75505Sopenharmony_ci 436e5b75505Sopenharmony_ci if (daemonize) { 437e5b75505Sopenharmony_ci if (os_daemonize(pid_file)) { 438e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "daemon: %s", strerror(errno)); 439e5b75505Sopenharmony_ci return -1; 440e5b75505Sopenharmony_ci } 441e5b75505Sopenharmony_ci if (eloop_sock_requeue()) { 442e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "eloop_sock_requeue: %s", 443e5b75505Sopenharmony_ci strerror(errno)); 444e5b75505Sopenharmony_ci return -1; 445e5b75505Sopenharmony_ci } 446e5b75505Sopenharmony_ci } 447e5b75505Sopenharmony_ci 448e5b75505Sopenharmony_ci eloop_run(); 449e5b75505Sopenharmony_ci 450e5b75505Sopenharmony_ci return 0; 451e5b75505Sopenharmony_ci} 452e5b75505Sopenharmony_ci 453e5b75505Sopenharmony_ci 454e5b75505Sopenharmony_cistatic void show_version(void) 455e5b75505Sopenharmony_ci{ 456e5b75505Sopenharmony_ci fprintf(stderr, 457e5b75505Sopenharmony_ci "hostapd v" VERSION_STR "\n" 458e5b75505Sopenharmony_ci "User space daemon for IEEE 802.11 AP management,\n" 459e5b75505Sopenharmony_ci "IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n" 460e5b75505Sopenharmony_ci "Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi> " 461e5b75505Sopenharmony_ci "and contributors\n"); 462e5b75505Sopenharmony_ci} 463e5b75505Sopenharmony_ci 464e5b75505Sopenharmony_ci 465e5b75505Sopenharmony_cistatic void usage(void) 466e5b75505Sopenharmony_ci{ 467e5b75505Sopenharmony_ci show_version(); 468e5b75505Sopenharmony_ci fprintf(stderr, 469e5b75505Sopenharmony_ci "\n" 470e5b75505Sopenharmony_ci "usage: hostapd [-hdBKtv] [-P <PID file>] [-e <entropy file>] " 471e5b75505Sopenharmony_ci "\\\n" 472e5b75505Sopenharmony_ci " [-g <global ctrl_iface>] [-G <group>]\\\n" 473e5b75505Sopenharmony_ci " [-i <comma-separated list of interface names>]\\\n" 474e5b75505Sopenharmony_ci " <configuration file(s)>\n" 475e5b75505Sopenharmony_ci "\n" 476e5b75505Sopenharmony_ci "options:\n" 477e5b75505Sopenharmony_ci " -h show this usage\n" 478e5b75505Sopenharmony_ci " -d show more debug messages (-dd for even more)\n" 479e5b75505Sopenharmony_ci " -B run daemon in the background\n" 480e5b75505Sopenharmony_ci " -e entropy file\n" 481e5b75505Sopenharmony_ci " -g global control interface path\n" 482e5b75505Sopenharmony_ci " -G group for control interfaces\n" 483e5b75505Sopenharmony_ci " -P PID file\n" 484e5b75505Sopenharmony_ci " -K include key data in debug messages\n" 485e5b75505Sopenharmony_ci#ifdef CONFIG_DEBUG_FILE 486e5b75505Sopenharmony_ci " -f log output to debug file instead of stdout\n" 487e5b75505Sopenharmony_ci#endif /* CONFIG_DEBUG_FILE */ 488e5b75505Sopenharmony_ci#ifdef CONFIG_DEBUG_LINUX_TRACING 489e5b75505Sopenharmony_ci " -T record to Linux tracing in addition to logging\n" 490e5b75505Sopenharmony_ci " (records all messages regardless of debug verbosity)\n" 491e5b75505Sopenharmony_ci#endif /* CONFIG_DEBUG_LINUX_TRACING */ 492e5b75505Sopenharmony_ci " -i list of interface names to use\n" 493e5b75505Sopenharmony_ci#ifdef CONFIG_DEBUG_SYSLOG 494e5b75505Sopenharmony_ci " -s log output to syslog instead of stdout\n" 495e5b75505Sopenharmony_ci#endif /* CONFIG_DEBUG_SYSLOG */ 496e5b75505Sopenharmony_ci " -S start all the interfaces synchronously\n" 497e5b75505Sopenharmony_ci " -t include timestamps in some debug messages\n" 498e5b75505Sopenharmony_ci " -v show hostapd version\n"); 499e5b75505Sopenharmony_ci 500e5b75505Sopenharmony_ci exit(1); 501e5b75505Sopenharmony_ci} 502e5b75505Sopenharmony_ci 503e5b75505Sopenharmony_ci 504e5b75505Sopenharmony_cistatic const char * hostapd_msg_ifname_cb(void *ctx) 505e5b75505Sopenharmony_ci{ 506e5b75505Sopenharmony_ci struct hostapd_data *hapd = ctx; 507e5b75505Sopenharmony_ci if (hapd && hapd->conf) 508e5b75505Sopenharmony_ci return hapd->conf->iface; 509e5b75505Sopenharmony_ci return NULL; 510e5b75505Sopenharmony_ci} 511e5b75505Sopenharmony_ci 512e5b75505Sopenharmony_ci 513e5b75505Sopenharmony_cistatic int hostapd_get_global_ctrl_iface(struct hapd_interfaces *interfaces, 514e5b75505Sopenharmony_ci const char *path) 515e5b75505Sopenharmony_ci{ 516e5b75505Sopenharmony_ci#ifndef CONFIG_CTRL_IFACE_UDP 517e5b75505Sopenharmony_ci char *pos; 518e5b75505Sopenharmony_ci#endif /* !CONFIG_CTRL_IFACE_UDP */ 519e5b75505Sopenharmony_ci 520e5b75505Sopenharmony_ci os_free(interfaces->global_iface_path); 521e5b75505Sopenharmony_ci interfaces->global_iface_path = os_strdup(path); 522e5b75505Sopenharmony_ci if (interfaces->global_iface_path == NULL) 523e5b75505Sopenharmony_ci return -1; 524e5b75505Sopenharmony_ci 525e5b75505Sopenharmony_ci#ifndef CONFIG_CTRL_IFACE_UDP 526e5b75505Sopenharmony_ci pos = os_strrchr(interfaces->global_iface_path, '/'); 527e5b75505Sopenharmony_ci if (pos == NULL) { 528e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "No '/' in the global control interface " 529e5b75505Sopenharmony_ci "file"); 530e5b75505Sopenharmony_ci os_free(interfaces->global_iface_path); 531e5b75505Sopenharmony_ci interfaces->global_iface_path = NULL; 532e5b75505Sopenharmony_ci return -1; 533e5b75505Sopenharmony_ci } 534e5b75505Sopenharmony_ci 535e5b75505Sopenharmony_ci *pos = '\0'; 536e5b75505Sopenharmony_ci interfaces->global_iface_name = pos + 1; 537e5b75505Sopenharmony_ci#endif /* !CONFIG_CTRL_IFACE_UDP */ 538e5b75505Sopenharmony_ci 539e5b75505Sopenharmony_ci return 0; 540e5b75505Sopenharmony_ci} 541e5b75505Sopenharmony_ci 542e5b75505Sopenharmony_ci 543e5b75505Sopenharmony_cistatic int hostapd_get_ctrl_iface_group(struct hapd_interfaces *interfaces, 544e5b75505Sopenharmony_ci const char *group) 545e5b75505Sopenharmony_ci{ 546e5b75505Sopenharmony_ci#ifndef CONFIG_NATIVE_WINDOWS 547e5b75505Sopenharmony_ci struct group *grp; 548e5b75505Sopenharmony_ci grp = getgrnam(group); 549e5b75505Sopenharmony_ci if (grp == NULL) { 550e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "Unknown group '%s'", group); 551e5b75505Sopenharmony_ci return -1; 552e5b75505Sopenharmony_ci } 553e5b75505Sopenharmony_ci interfaces->ctrl_iface_group = grp->gr_gid; 554e5b75505Sopenharmony_ci#endif /* CONFIG_NATIVE_WINDOWS */ 555e5b75505Sopenharmony_ci return 0; 556e5b75505Sopenharmony_ci} 557e5b75505Sopenharmony_ci 558e5b75505Sopenharmony_ci 559e5b75505Sopenharmony_cistatic int hostapd_get_interface_names(char ***if_names, 560e5b75505Sopenharmony_ci size_t *if_names_size, 561e5b75505Sopenharmony_ci char *arg) 562e5b75505Sopenharmony_ci{ 563e5b75505Sopenharmony_ci char *if_name, *tmp, **nnames; 564e5b75505Sopenharmony_ci size_t i; 565e5b75505Sopenharmony_ci 566e5b75505Sopenharmony_ci if (!arg) 567e5b75505Sopenharmony_ci return -1; 568e5b75505Sopenharmony_ci if_name = strtok_r(arg, ",", &tmp); 569e5b75505Sopenharmony_ci 570e5b75505Sopenharmony_ci while (if_name) { 571e5b75505Sopenharmony_ci nnames = os_realloc_array(*if_names, 1 + *if_names_size, 572e5b75505Sopenharmony_ci sizeof(char *)); 573e5b75505Sopenharmony_ci if (!nnames) 574e5b75505Sopenharmony_ci goto fail; 575e5b75505Sopenharmony_ci *if_names = nnames; 576e5b75505Sopenharmony_ci 577e5b75505Sopenharmony_ci (*if_names)[*if_names_size] = os_strdup(if_name); 578e5b75505Sopenharmony_ci if (!(*if_names)[*if_names_size]) 579e5b75505Sopenharmony_ci goto fail; 580e5b75505Sopenharmony_ci (*if_names_size)++; 581e5b75505Sopenharmony_ci if_name = strtok_r(NULL, ",", &tmp); 582e5b75505Sopenharmony_ci } 583e5b75505Sopenharmony_ci 584e5b75505Sopenharmony_ci return 0; 585e5b75505Sopenharmony_ci 586e5b75505Sopenharmony_cifail: 587e5b75505Sopenharmony_ci for (i = 0; i < *if_names_size; i++) 588e5b75505Sopenharmony_ci os_free((*if_names)[i]); 589e5b75505Sopenharmony_ci os_free(*if_names); 590e5b75505Sopenharmony_ci *if_names = NULL; 591e5b75505Sopenharmony_ci *if_names_size = 0; 592e5b75505Sopenharmony_ci return -1; 593e5b75505Sopenharmony_ci} 594e5b75505Sopenharmony_ci 595e5b75505Sopenharmony_ci 596e5b75505Sopenharmony_ci#ifdef CONFIG_WPS 597e5b75505Sopenharmony_cistatic int gen_uuid(const char *txt_addr) 598e5b75505Sopenharmony_ci{ 599e5b75505Sopenharmony_ci u8 addr[ETH_ALEN]; 600e5b75505Sopenharmony_ci u8 uuid[UUID_LEN]; 601e5b75505Sopenharmony_ci char buf[100]; 602e5b75505Sopenharmony_ci 603e5b75505Sopenharmony_ci if (hwaddr_aton(txt_addr, addr) < 0) 604e5b75505Sopenharmony_ci return -1; 605e5b75505Sopenharmony_ci 606e5b75505Sopenharmony_ci uuid_gen_mac_addr(addr, uuid); 607e5b75505Sopenharmony_ci if (uuid_bin2str(uuid, buf, sizeof(buf)) < 0) 608e5b75505Sopenharmony_ci return -1; 609e5b75505Sopenharmony_ci 610e5b75505Sopenharmony_ci printf("%s\n", buf); 611e5b75505Sopenharmony_ci 612e5b75505Sopenharmony_ci return 0; 613e5b75505Sopenharmony_ci} 614e5b75505Sopenharmony_ci#endif /* CONFIG_WPS */ 615e5b75505Sopenharmony_ci 616e5b75505Sopenharmony_ci 617e5b75505Sopenharmony_ci#ifndef HOSTAPD_CLEANUP_INTERVAL 618e5b75505Sopenharmony_ci#define HOSTAPD_CLEANUP_INTERVAL 10 619e5b75505Sopenharmony_ci#endif /* HOSTAPD_CLEANUP_INTERVAL */ 620e5b75505Sopenharmony_ci 621e5b75505Sopenharmony_cistatic int hostapd_periodic_call(struct hostapd_iface *iface, void *ctx) 622e5b75505Sopenharmony_ci{ 623e5b75505Sopenharmony_ci hostapd_periodic_iface(iface); 624e5b75505Sopenharmony_ci return 0; 625e5b75505Sopenharmony_ci} 626e5b75505Sopenharmony_ci 627e5b75505Sopenharmony_ci 628e5b75505Sopenharmony_ci/* Periodic cleanup tasks */ 629e5b75505Sopenharmony_cistatic void hostapd_periodic(void *eloop_ctx, void *timeout_ctx) 630e5b75505Sopenharmony_ci{ 631e5b75505Sopenharmony_ci struct hapd_interfaces *interfaces = eloop_ctx; 632e5b75505Sopenharmony_ci 633e5b75505Sopenharmony_ci eloop_register_timeout(HOSTAPD_CLEANUP_INTERVAL, 0, 634e5b75505Sopenharmony_ci hostapd_periodic, interfaces, NULL); 635e5b75505Sopenharmony_ci hostapd_for_each_interface(interfaces, hostapd_periodic_call, NULL); 636e5b75505Sopenharmony_ci} 637e5b75505Sopenharmony_ci 638e5b75505Sopenharmony_civoid set_running_hostap(); 639e5b75505Sopenharmony_ci 640e5b75505Sopenharmony_ci__attribute__ ((visibility ("default"))) int ap_main(int argc, char *argv[]) 641e5b75505Sopenharmony_ci{ 642e5b75505Sopenharmony_ci struct hapd_interfaces interfaces; 643e5b75505Sopenharmony_ci int ret = 1; 644e5b75505Sopenharmony_ci size_t i, j; 645e5b75505Sopenharmony_ci int c, debug = 0, daemonize = 0; 646e5b75505Sopenharmony_ci char *pid_file = NULL; 647e5b75505Sopenharmony_ci const char *log_file = NULL; 648e5b75505Sopenharmony_ci const char *entropy_file = NULL; 649e5b75505Sopenharmony_ci char **bss_config = NULL, **tmp_bss; 650e5b75505Sopenharmony_ci size_t num_bss_configs = 0; 651e5b75505Sopenharmony_ci#ifdef CONFIG_DEBUG_LINUX_TRACING 652e5b75505Sopenharmony_ci int enable_trace_dbg = 0; 653e5b75505Sopenharmony_ci#endif /* CONFIG_DEBUG_LINUX_TRACING */ 654e5b75505Sopenharmony_ci int start_ifaces_in_sync = 0; 655e5b75505Sopenharmony_ci char **if_names = NULL; 656e5b75505Sopenharmony_ci size_t if_names_size = 0; 657e5b75505Sopenharmony_ci#ifdef CONFIG_DPP 658e5b75505Sopenharmony_ci struct dpp_global_config dpp_conf; 659e5b75505Sopenharmony_ci#endif /* CONFIG_DPP */ 660e5b75505Sopenharmony_ci 661e5b75505Sopenharmony_ci optind = 1; 662e5b75505Sopenharmony_ci set_running_hostap(); 663e5b75505Sopenharmony_ci 664e5b75505Sopenharmony_ci if (os_program_init()) 665e5b75505Sopenharmony_ci return -1; 666e5b75505Sopenharmony_ci 667e5b75505Sopenharmony_ci os_memset(&interfaces, 0, sizeof(interfaces)); 668e5b75505Sopenharmony_ci interfaces.reload_config = hostapd_reload_config; 669e5b75505Sopenharmony_ci interfaces.config_read_cb = hostapd_config_read; 670e5b75505Sopenharmony_ci interfaces.for_each_interface = hostapd_for_each_interface; 671e5b75505Sopenharmony_ci interfaces.ctrl_iface_init = hostapd_ctrl_iface_init; 672e5b75505Sopenharmony_ci interfaces.ctrl_iface_deinit = hostapd_ctrl_iface_deinit; 673e5b75505Sopenharmony_ci interfaces.driver_init = hostapd_driver_init; 674e5b75505Sopenharmony_ci interfaces.global_iface_path = NULL; 675e5b75505Sopenharmony_ci interfaces.global_iface_name = NULL; 676e5b75505Sopenharmony_ci interfaces.global_ctrl_sock = -1; 677e5b75505Sopenharmony_ci dl_list_init(&interfaces.global_ctrl_dst); 678e5b75505Sopenharmony_ci#ifdef CONFIG_ETH_P_OUI 679e5b75505Sopenharmony_ci dl_list_init(&interfaces.eth_p_oui); 680e5b75505Sopenharmony_ci#endif /* CONFIG_ETH_P_OUI */ 681e5b75505Sopenharmony_ci#ifdef CONFIG_DPP 682e5b75505Sopenharmony_ci os_memset(&dpp_conf, 0, sizeof(dpp_conf)); 683e5b75505Sopenharmony_ci /* TODO: dpp_conf.msg_ctx? */ 684e5b75505Sopenharmony_ci interfaces.dpp = dpp_global_init(&dpp_conf); 685e5b75505Sopenharmony_ci if (!interfaces.dpp) 686e5b75505Sopenharmony_ci return -1; 687e5b75505Sopenharmony_ci#endif /* CONFIG_DPP */ 688e5b75505Sopenharmony_ci 689e5b75505Sopenharmony_ci for (;;) { 690e5b75505Sopenharmony_ci c = getopt(argc, argv, "b:Bde:f:hi:KP:sSTtu:vg:G:"); 691e5b75505Sopenharmony_ci if (c < 0) 692e5b75505Sopenharmony_ci break; 693e5b75505Sopenharmony_ci switch (c) { 694e5b75505Sopenharmony_ci case 'h': 695e5b75505Sopenharmony_ci usage(); 696e5b75505Sopenharmony_ci break; 697e5b75505Sopenharmony_ci case 'd': 698e5b75505Sopenharmony_ci debug++; 699e5b75505Sopenharmony_ci if (wpa_debug_level > 0) 700e5b75505Sopenharmony_ci wpa_debug_level--; 701e5b75505Sopenharmony_ci break; 702e5b75505Sopenharmony_ci case 'B': 703e5b75505Sopenharmony_ci daemonize++; 704e5b75505Sopenharmony_ci break; 705e5b75505Sopenharmony_ci case 'e': 706e5b75505Sopenharmony_ci entropy_file = optarg; 707e5b75505Sopenharmony_ci break; 708e5b75505Sopenharmony_ci case 'f': 709e5b75505Sopenharmony_ci log_file = optarg; 710e5b75505Sopenharmony_ci break; 711e5b75505Sopenharmony_ci case 'K': 712e5b75505Sopenharmony_ci wpa_debug_show_keys++; 713e5b75505Sopenharmony_ci break; 714e5b75505Sopenharmony_ci case 'P': 715e5b75505Sopenharmony_ci os_free(pid_file); 716e5b75505Sopenharmony_ci pid_file = os_rel2abs_path(optarg); 717e5b75505Sopenharmony_ci break; 718e5b75505Sopenharmony_ci case 't': 719e5b75505Sopenharmony_ci wpa_debug_timestamp++; 720e5b75505Sopenharmony_ci break; 721e5b75505Sopenharmony_ci#ifdef CONFIG_DEBUG_LINUX_TRACING 722e5b75505Sopenharmony_ci case 'T': 723e5b75505Sopenharmony_ci enable_trace_dbg = 1; 724e5b75505Sopenharmony_ci break; 725e5b75505Sopenharmony_ci#endif /* CONFIG_DEBUG_LINUX_TRACING */ 726e5b75505Sopenharmony_ci case 'v': 727e5b75505Sopenharmony_ci show_version(); 728e5b75505Sopenharmony_ci exit(1); 729e5b75505Sopenharmony_ci break; 730e5b75505Sopenharmony_ci case 'g': 731e5b75505Sopenharmony_ci if (hostapd_get_global_ctrl_iface(&interfaces, optarg)) 732e5b75505Sopenharmony_ci return -1; 733e5b75505Sopenharmony_ci break; 734e5b75505Sopenharmony_ci case 'G': 735e5b75505Sopenharmony_ci if (hostapd_get_ctrl_iface_group(&interfaces, optarg)) 736e5b75505Sopenharmony_ci return -1; 737e5b75505Sopenharmony_ci break; 738e5b75505Sopenharmony_ci case 'b': 739e5b75505Sopenharmony_ci tmp_bss = os_realloc_array(bss_config, 740e5b75505Sopenharmony_ci num_bss_configs + 1, 741e5b75505Sopenharmony_ci sizeof(char *)); 742e5b75505Sopenharmony_ci if (tmp_bss == NULL) 743e5b75505Sopenharmony_ci goto out; 744e5b75505Sopenharmony_ci bss_config = tmp_bss; 745e5b75505Sopenharmony_ci bss_config[num_bss_configs++] = optarg; 746e5b75505Sopenharmony_ci break; 747e5b75505Sopenharmony_ci#ifdef CONFIG_DEBUG_SYSLOG 748e5b75505Sopenharmony_ci case 's': 749e5b75505Sopenharmony_ci wpa_debug_syslog = 1; 750e5b75505Sopenharmony_ci break; 751e5b75505Sopenharmony_ci#endif /* CONFIG_DEBUG_SYSLOG */ 752e5b75505Sopenharmony_ci case 'S': 753e5b75505Sopenharmony_ci start_ifaces_in_sync = 1; 754e5b75505Sopenharmony_ci break; 755e5b75505Sopenharmony_ci#ifdef CONFIG_WPS 756e5b75505Sopenharmony_ci case 'u': 757e5b75505Sopenharmony_ci return gen_uuid(optarg); 758e5b75505Sopenharmony_ci#endif /* CONFIG_WPS */ 759e5b75505Sopenharmony_ci case 'i': 760e5b75505Sopenharmony_ci if (hostapd_get_interface_names(&if_names, 761e5b75505Sopenharmony_ci &if_names_size, optarg)) 762e5b75505Sopenharmony_ci goto out; 763e5b75505Sopenharmony_ci break; 764e5b75505Sopenharmony_ci default: 765e5b75505Sopenharmony_ci usage(); 766e5b75505Sopenharmony_ci break; 767e5b75505Sopenharmony_ci } 768e5b75505Sopenharmony_ci } 769e5b75505Sopenharmony_ci 770e5b75505Sopenharmony_ci if (optind == argc && interfaces.global_iface_path == NULL && 771e5b75505Sopenharmony_ci num_bss_configs == 0) 772e5b75505Sopenharmony_ci usage(); 773e5b75505Sopenharmony_ci 774e5b75505Sopenharmony_ci wpa_msg_register_ifname_cb(hostapd_msg_ifname_cb); 775e5b75505Sopenharmony_ci 776e5b75505Sopenharmony_ci if (log_file) 777e5b75505Sopenharmony_ci wpa_debug_open_file(log_file); 778e5b75505Sopenharmony_ci else 779e5b75505Sopenharmony_ci wpa_debug_setup_stdout(); 780e5b75505Sopenharmony_ci#ifdef CONFIG_DEBUG_SYSLOG 781e5b75505Sopenharmony_ci if (wpa_debug_syslog) 782e5b75505Sopenharmony_ci wpa_debug_open_syslog(); 783e5b75505Sopenharmony_ci#endif /* CONFIG_DEBUG_SYSLOG */ 784e5b75505Sopenharmony_ci#ifdef CONFIG_DEBUG_LINUX_TRACING 785e5b75505Sopenharmony_ci if (enable_trace_dbg) { 786e5b75505Sopenharmony_ci int tret = wpa_debug_open_linux_tracing(); 787e5b75505Sopenharmony_ci if (tret) { 788e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "Failed to enable trace logging"); 789e5b75505Sopenharmony_ci return -1; 790e5b75505Sopenharmony_ci } 791e5b75505Sopenharmony_ci } 792e5b75505Sopenharmony_ci#endif /* CONFIG_DEBUG_LINUX_TRACING */ 793e5b75505Sopenharmony_ci 794e5b75505Sopenharmony_ci interfaces.count = argc - optind; 795e5b75505Sopenharmony_ci if (interfaces.count || num_bss_configs) { 796e5b75505Sopenharmony_ci interfaces.iface = os_calloc(interfaces.count + num_bss_configs, 797e5b75505Sopenharmony_ci sizeof(struct hostapd_iface *)); 798e5b75505Sopenharmony_ci if (interfaces.iface == NULL) { 799e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "malloc failed"); 800e5b75505Sopenharmony_ci return -1; 801e5b75505Sopenharmony_ci } 802e5b75505Sopenharmony_ci } 803e5b75505Sopenharmony_ci 804e5b75505Sopenharmony_ci if (hostapd_global_init(&interfaces, entropy_file)) { 805e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "Failed to initialize global context"); 806e5b75505Sopenharmony_ci return -1; 807e5b75505Sopenharmony_ci } 808e5b75505Sopenharmony_ci 809e5b75505Sopenharmony_ci eloop_register_timeout(HOSTAPD_CLEANUP_INTERVAL, 0, 810e5b75505Sopenharmony_ci hostapd_periodic, &interfaces, NULL); 811e5b75505Sopenharmony_ci 812e5b75505Sopenharmony_ci if (fst_global_init()) { 813e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, 814e5b75505Sopenharmony_ci "Failed to initialize global FST context"); 815e5b75505Sopenharmony_ci goto out; 816e5b75505Sopenharmony_ci } 817e5b75505Sopenharmony_ci 818e5b75505Sopenharmony_ci#if defined(CONFIG_FST) && defined(CONFIG_CTRL_IFACE) 819e5b75505Sopenharmony_ci if (!fst_global_add_ctrl(fst_ctrl_cli)) 820e5b75505Sopenharmony_ci wpa_printf(MSG_WARNING, "Failed to add CLI FST ctrl"); 821e5b75505Sopenharmony_ci#endif /* CONFIG_FST && CONFIG_CTRL_IFACE */ 822e5b75505Sopenharmony_ci 823e5b75505Sopenharmony_ci /* Allocate and parse configuration for full interface files */ 824e5b75505Sopenharmony_ci for (i = 0; i < interfaces.count; i++) { 825e5b75505Sopenharmony_ci char *if_name = NULL; 826e5b75505Sopenharmony_ci 827e5b75505Sopenharmony_ci if (i < if_names_size) 828e5b75505Sopenharmony_ci if_name = if_names[i]; 829e5b75505Sopenharmony_ci 830e5b75505Sopenharmony_ci interfaces.iface[i] = hostapd_interface_init(&interfaces, 831e5b75505Sopenharmony_ci if_name, 832e5b75505Sopenharmony_ci argv[optind + i], 833e5b75505Sopenharmony_ci debug); 834e5b75505Sopenharmony_ci if (!interfaces.iface[i]) { 835e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "Failed to initialize interface"); 836e5b75505Sopenharmony_ci goto out; 837e5b75505Sopenharmony_ci } 838e5b75505Sopenharmony_ci if (start_ifaces_in_sync) 839e5b75505Sopenharmony_ci interfaces.iface[i]->need_to_start_in_sync = 1; 840e5b75505Sopenharmony_ci } 841e5b75505Sopenharmony_ci 842e5b75505Sopenharmony_ci /* Allocate and parse configuration for per-BSS files */ 843e5b75505Sopenharmony_ci for (i = 0; i < num_bss_configs; i++) { 844e5b75505Sopenharmony_ci struct hostapd_iface *iface; 845e5b75505Sopenharmony_ci char *fname; 846e5b75505Sopenharmony_ci 847e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "BSS config: %s", bss_config[i]); 848e5b75505Sopenharmony_ci fname = os_strchr(bss_config[i], ':'); 849e5b75505Sopenharmony_ci if (fname == NULL) { 850e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, 851e5b75505Sopenharmony_ci "Invalid BSS config identifier '%s'", 852e5b75505Sopenharmony_ci bss_config[i]); 853e5b75505Sopenharmony_ci goto out; 854e5b75505Sopenharmony_ci } 855e5b75505Sopenharmony_ci *fname++ = '\0'; 856e5b75505Sopenharmony_ci iface = hostapd_interface_init_bss(&interfaces, bss_config[i], 857e5b75505Sopenharmony_ci fname, debug); 858e5b75505Sopenharmony_ci if (iface == NULL) 859e5b75505Sopenharmony_ci goto out; 860e5b75505Sopenharmony_ci for (j = 0; j < interfaces.count; j++) { 861e5b75505Sopenharmony_ci if (interfaces.iface[j] == iface) 862e5b75505Sopenharmony_ci break; 863e5b75505Sopenharmony_ci } 864e5b75505Sopenharmony_ci if (j == interfaces.count) { 865e5b75505Sopenharmony_ci struct hostapd_iface **tmp; 866e5b75505Sopenharmony_ci tmp = os_realloc_array(interfaces.iface, 867e5b75505Sopenharmony_ci interfaces.count + 1, 868e5b75505Sopenharmony_ci sizeof(struct hostapd_iface *)); 869e5b75505Sopenharmony_ci if (tmp == NULL) { 870e5b75505Sopenharmony_ci hostapd_interface_deinit_free(iface); 871e5b75505Sopenharmony_ci goto out; 872e5b75505Sopenharmony_ci } 873e5b75505Sopenharmony_ci interfaces.iface = tmp; 874e5b75505Sopenharmony_ci interfaces.iface[interfaces.count++] = iface; 875e5b75505Sopenharmony_ci } 876e5b75505Sopenharmony_ci } 877e5b75505Sopenharmony_ci 878e5b75505Sopenharmony_ci /* 879e5b75505Sopenharmony_ci * Enable configured interfaces. Depending on channel configuration, 880e5b75505Sopenharmony_ci * this may complete full initialization before returning or use a 881e5b75505Sopenharmony_ci * callback mechanism to complete setup in case of operations like HT 882e5b75505Sopenharmony_ci * co-ex scans, ACS, or DFS are needed to determine channel parameters. 883e5b75505Sopenharmony_ci * In such case, the interface will be enabled from eloop context within 884e5b75505Sopenharmony_ci * hostapd_global_run(). 885e5b75505Sopenharmony_ci */ 886e5b75505Sopenharmony_ci interfaces.terminate_on_error = interfaces.count; 887e5b75505Sopenharmony_ci for (i = 0; i < interfaces.count; i++) { 888e5b75505Sopenharmony_ci if (hostapd_driver_init(interfaces.iface[i]) || 889e5b75505Sopenharmony_ci hostapd_setup_interface(interfaces.iface[i])) 890e5b75505Sopenharmony_ci goto out; 891e5b75505Sopenharmony_ci } 892e5b75505Sopenharmony_ci 893e5b75505Sopenharmony_ci hostapd_global_ctrl_iface_init(&interfaces); 894e5b75505Sopenharmony_ci 895e5b75505Sopenharmony_ci if (hostapd_global_run(&interfaces, daemonize, pid_file)) { 896e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "Failed to start eloop"); 897e5b75505Sopenharmony_ci goto out; 898e5b75505Sopenharmony_ci } 899e5b75505Sopenharmony_ci 900e5b75505Sopenharmony_ci ret = 0; 901e5b75505Sopenharmony_ci 902e5b75505Sopenharmony_ci out: 903e5b75505Sopenharmony_ci hostapd_global_ctrl_iface_deinit(&interfaces); 904e5b75505Sopenharmony_ci /* Deinitialize all interfaces */ 905e5b75505Sopenharmony_ci for (i = 0; i < interfaces.count; i++) { 906e5b75505Sopenharmony_ci if (!interfaces.iface[i]) 907e5b75505Sopenharmony_ci continue; 908e5b75505Sopenharmony_ci interfaces.iface[i]->driver_ap_teardown = 909e5b75505Sopenharmony_ci !!(interfaces.iface[i]->drv_flags & 910e5b75505Sopenharmony_ci WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT); 911e5b75505Sopenharmony_ci hostapd_interface_deinit_free(interfaces.iface[i]); 912e5b75505Sopenharmony_ci } 913e5b75505Sopenharmony_ci os_free(interfaces.iface); 914e5b75505Sopenharmony_ci 915e5b75505Sopenharmony_ci#ifdef CONFIG_DPP 916e5b75505Sopenharmony_ci dpp_global_deinit(interfaces.dpp); 917e5b75505Sopenharmony_ci#endif /* CONFIG_DPP */ 918e5b75505Sopenharmony_ci 919e5b75505Sopenharmony_ci if (interfaces.eloop_initialized) 920e5b75505Sopenharmony_ci eloop_cancel_timeout(hostapd_periodic, &interfaces, NULL); 921e5b75505Sopenharmony_ci hostapd_global_deinit(pid_file, interfaces.eloop_initialized); 922e5b75505Sopenharmony_ci os_free(pid_file); 923e5b75505Sopenharmony_ci 924e5b75505Sopenharmony_ci wpa_debug_close_syslog(); 925e5b75505Sopenharmony_ci if (log_file) 926e5b75505Sopenharmony_ci wpa_debug_close_file(); 927e5b75505Sopenharmony_ci wpa_debug_close_linux_tracing(); 928e5b75505Sopenharmony_ci 929e5b75505Sopenharmony_ci os_free(bss_config); 930e5b75505Sopenharmony_ci 931e5b75505Sopenharmony_ci for (i = 0; i < if_names_size; i++) 932e5b75505Sopenharmony_ci os_free(if_names[i]); 933e5b75505Sopenharmony_ci os_free(if_names); 934e5b75505Sopenharmony_ci 935e5b75505Sopenharmony_ci fst_global_deinit(); 936e5b75505Sopenharmony_ci 937e5b75505Sopenharmony_ci os_program_deinit(); 938e5b75505Sopenharmony_ci 939e5b75505Sopenharmony_ci return ret; 940e5b75505Sopenharmony_ci} 941