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