1214503Srpaulo/* 2214503Srpaulo * hostapd / main() 3252726Srpaulo * Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi> 4214503Srpaulo * 5252726Srpaulo * This software may be distributed under the terms of the BSD license. 6252726Srpaulo * See README for more details. 7214503Srpaulo */ 8214503Srpaulo 9214503Srpaulo#include "utils/includes.h" 10214503Srpaulo#ifndef CONFIG_NATIVE_WINDOWS 11214503Srpaulo#include <syslog.h> 12214503Srpaulo#endif /* CONFIG_NATIVE_WINDOWS */ 13214503Srpaulo 14214503Srpaulo#include "utils/common.h" 15214503Srpaulo#include "utils/eloop.h" 16252726Srpaulo#include "crypto/random.h" 17214503Srpaulo#include "crypto/tls.h" 18214503Srpaulo#include "common/version.h" 19214503Srpaulo#include "drivers/driver.h" 20214503Srpaulo#include "eap_server/eap.h" 21214503Srpaulo#include "eap_server/tncs.h" 22214503Srpaulo#include "ap/hostapd.h" 23214503Srpaulo#include "ap/ap_config.h" 24252726Srpaulo#include "ap/ap_drv_ops.h" 25214503Srpaulo#include "config_file.h" 26214503Srpaulo#include "eap_register.h" 27214503Srpaulo#include "dump_state.h" 28214503Srpaulo#include "ctrl_iface.h" 29214503Srpaulo 30214503Srpaulo 31214503Srpauloextern int wpa_debug_level; 32214503Srpauloextern int wpa_debug_show_keys; 33214503Srpauloextern int wpa_debug_timestamp; 34214503Srpaulo 35252726Srpauloextern struct wpa_driver_ops *wpa_drivers[]; 36214503Srpaulo 37252726Srpaulo 38252726Srpaulostruct hapd_global { 39252726Srpaulo void **drv_priv; 40252726Srpaulo size_t drv_count; 41214503Srpaulo}; 42214503Srpaulo 43252726Srpaulostatic struct hapd_global global; 44214503Srpaulo 45214503Srpaulo 46214503Srpaulo#ifndef CONFIG_NO_HOSTAPD_LOGGER 47214503Srpaulostatic void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module, 48214503Srpaulo int level, const char *txt, size_t len) 49214503Srpaulo{ 50214503Srpaulo struct hostapd_data *hapd = ctx; 51214503Srpaulo char *format, *module_str; 52214503Srpaulo int maxlen; 53214503Srpaulo int conf_syslog_level, conf_stdout_level; 54214503Srpaulo unsigned int conf_syslog, conf_stdout; 55214503Srpaulo 56214503Srpaulo maxlen = len + 100; 57214503Srpaulo format = os_malloc(maxlen); 58214503Srpaulo if (!format) 59214503Srpaulo return; 60214503Srpaulo 61214503Srpaulo if (hapd && hapd->conf) { 62214503Srpaulo conf_syslog_level = hapd->conf->logger_syslog_level; 63214503Srpaulo conf_stdout_level = hapd->conf->logger_stdout_level; 64214503Srpaulo conf_syslog = hapd->conf->logger_syslog; 65214503Srpaulo conf_stdout = hapd->conf->logger_stdout; 66214503Srpaulo } else { 67214503Srpaulo conf_syslog_level = conf_stdout_level = 0; 68214503Srpaulo conf_syslog = conf_stdout = (unsigned int) -1; 69214503Srpaulo } 70214503Srpaulo 71214503Srpaulo switch (module) { 72214503Srpaulo case HOSTAPD_MODULE_IEEE80211: 73214503Srpaulo module_str = "IEEE 802.11"; 74214503Srpaulo break; 75214503Srpaulo case HOSTAPD_MODULE_IEEE8021X: 76214503Srpaulo module_str = "IEEE 802.1X"; 77214503Srpaulo break; 78214503Srpaulo case HOSTAPD_MODULE_RADIUS: 79214503Srpaulo module_str = "RADIUS"; 80214503Srpaulo break; 81214503Srpaulo case HOSTAPD_MODULE_WPA: 82214503Srpaulo module_str = "WPA"; 83214503Srpaulo break; 84214503Srpaulo case HOSTAPD_MODULE_DRIVER: 85214503Srpaulo module_str = "DRIVER"; 86214503Srpaulo break; 87214503Srpaulo case HOSTAPD_MODULE_IAPP: 88214503Srpaulo module_str = "IAPP"; 89214503Srpaulo break; 90214503Srpaulo case HOSTAPD_MODULE_MLME: 91214503Srpaulo module_str = "MLME"; 92214503Srpaulo break; 93214503Srpaulo default: 94214503Srpaulo module_str = NULL; 95214503Srpaulo break; 96214503Srpaulo } 97214503Srpaulo 98214503Srpaulo if (hapd && hapd->conf && addr) 99214503Srpaulo os_snprintf(format, maxlen, "%s: STA " MACSTR "%s%s: %s", 100214503Srpaulo hapd->conf->iface, MAC2STR(addr), 101214503Srpaulo module_str ? " " : "", module_str, txt); 102214503Srpaulo else if (hapd && hapd->conf) 103214503Srpaulo os_snprintf(format, maxlen, "%s:%s%s %s", 104214503Srpaulo hapd->conf->iface, module_str ? " " : "", 105214503Srpaulo module_str, txt); 106214503Srpaulo else if (addr) 107214503Srpaulo os_snprintf(format, maxlen, "STA " MACSTR "%s%s: %s", 108214503Srpaulo MAC2STR(addr), module_str ? " " : "", 109214503Srpaulo module_str, txt); 110214503Srpaulo else 111214503Srpaulo os_snprintf(format, maxlen, "%s%s%s", 112214503Srpaulo module_str, module_str ? ": " : "", txt); 113214503Srpaulo 114214503Srpaulo if ((conf_stdout & module) && level >= conf_stdout_level) { 115214503Srpaulo wpa_debug_print_timestamp(); 116214503Srpaulo printf("%s\n", format); 117214503Srpaulo } 118214503Srpaulo 119214503Srpaulo#ifndef CONFIG_NATIVE_WINDOWS 120214503Srpaulo if ((conf_syslog & module) && level >= conf_syslog_level) { 121214503Srpaulo int priority; 122214503Srpaulo switch (level) { 123214503Srpaulo case HOSTAPD_LEVEL_DEBUG_VERBOSE: 124214503Srpaulo case HOSTAPD_LEVEL_DEBUG: 125214503Srpaulo priority = LOG_DEBUG; 126214503Srpaulo break; 127214503Srpaulo case HOSTAPD_LEVEL_INFO: 128214503Srpaulo priority = LOG_INFO; 129214503Srpaulo break; 130214503Srpaulo case HOSTAPD_LEVEL_NOTICE: 131214503Srpaulo priority = LOG_NOTICE; 132214503Srpaulo break; 133214503Srpaulo case HOSTAPD_LEVEL_WARNING: 134214503Srpaulo priority = LOG_WARNING; 135214503Srpaulo break; 136214503Srpaulo default: 137214503Srpaulo priority = LOG_INFO; 138214503Srpaulo break; 139214503Srpaulo } 140214503Srpaulo syslog(priority, "%s", format); 141214503Srpaulo } 142214503Srpaulo#endif /* CONFIG_NATIVE_WINDOWS */ 143214503Srpaulo 144214503Srpaulo os_free(format); 145214503Srpaulo} 146214503Srpaulo#endif /* CONFIG_NO_HOSTAPD_LOGGER */ 147214503Srpaulo 148214503Srpaulo 149214503Srpaulo/** 150214503Srpaulo * hostapd_init - Allocate and initialize per-interface data 151214503Srpaulo * @config_file: Path to the configuration file 152214503Srpaulo * Returns: Pointer to the allocated interface data or %NULL on failure 153214503Srpaulo * 154214503Srpaulo * This function is used to allocate main data structures for per-interface 155214503Srpaulo * data. The allocated data buffer will be freed by calling 156214503Srpaulo * hostapd_cleanup_iface(). 157214503Srpaulo */ 158214503Srpaulostatic struct hostapd_iface * hostapd_init(const char *config_file) 159214503Srpaulo{ 160214503Srpaulo struct hostapd_iface *hapd_iface = NULL; 161214503Srpaulo struct hostapd_config *conf = NULL; 162214503Srpaulo struct hostapd_data *hapd; 163214503Srpaulo size_t i; 164214503Srpaulo 165214503Srpaulo hapd_iface = os_zalloc(sizeof(*hapd_iface)); 166214503Srpaulo if (hapd_iface == NULL) 167214503Srpaulo goto fail; 168214503Srpaulo 169214503Srpaulo hapd_iface->config_fname = os_strdup(config_file); 170214503Srpaulo if (hapd_iface->config_fname == NULL) 171214503Srpaulo goto fail; 172214503Srpaulo 173214503Srpaulo conf = hostapd_config_read(hapd_iface->config_fname); 174214503Srpaulo if (conf == NULL) 175214503Srpaulo goto fail; 176214503Srpaulo hapd_iface->conf = conf; 177214503Srpaulo 178214503Srpaulo hapd_iface->num_bss = conf->num_bss; 179252726Srpaulo hapd_iface->bss = os_calloc(conf->num_bss, 180214503Srpaulo sizeof(struct hostapd_data *)); 181214503Srpaulo if (hapd_iface->bss == NULL) 182214503Srpaulo goto fail; 183214503Srpaulo 184214503Srpaulo for (i = 0; i < conf->num_bss; i++) { 185214503Srpaulo hapd = hapd_iface->bss[i] = 186214503Srpaulo hostapd_alloc_bss_data(hapd_iface, conf, 187214503Srpaulo &conf->bss[i]); 188214503Srpaulo if (hapd == NULL) 189214503Srpaulo goto fail; 190214503Srpaulo hapd->msg_ctx = hapd; 191214503Srpaulo } 192214503Srpaulo 193214503Srpaulo return hapd_iface; 194214503Srpaulo 195214503Srpaulofail: 196214503Srpaulo if (conf) 197214503Srpaulo hostapd_config_free(conf); 198214503Srpaulo if (hapd_iface) { 199214503Srpaulo os_free(hapd_iface->config_fname); 200214503Srpaulo os_free(hapd_iface->bss); 201214503Srpaulo os_free(hapd_iface); 202214503Srpaulo } 203214503Srpaulo return NULL; 204214503Srpaulo} 205214503Srpaulo 206214503Srpaulo 207214503Srpaulostatic int hostapd_driver_init(struct hostapd_iface *iface) 208214503Srpaulo{ 209214503Srpaulo struct wpa_init_params params; 210214503Srpaulo size_t i; 211214503Srpaulo struct hostapd_data *hapd = iface->bss[0]; 212214503Srpaulo struct hostapd_bss_config *conf = hapd->conf; 213214503Srpaulo u8 *b = conf->bssid; 214252726Srpaulo struct wpa_driver_capa capa; 215214503Srpaulo 216214503Srpaulo if (hapd->driver == NULL || hapd->driver->hapd_init == NULL) { 217214503Srpaulo wpa_printf(MSG_ERROR, "No hostapd driver wrapper available"); 218214503Srpaulo return -1; 219214503Srpaulo } 220214503Srpaulo 221214503Srpaulo /* Initialize the driver interface */ 222214503Srpaulo if (!(b[0] | b[1] | b[2] | b[3] | b[4] | b[5])) 223214503Srpaulo b = NULL; 224214503Srpaulo 225214503Srpaulo os_memset(¶ms, 0, sizeof(params)); 226252726Srpaulo for (i = 0; wpa_drivers[i]; i++) { 227252726Srpaulo if (wpa_drivers[i] != hapd->driver) 228252726Srpaulo continue; 229252726Srpaulo 230252726Srpaulo if (global.drv_priv[i] == NULL && 231252726Srpaulo wpa_drivers[i]->global_init) { 232252726Srpaulo global.drv_priv[i] = wpa_drivers[i]->global_init(); 233252726Srpaulo if (global.drv_priv[i] == NULL) { 234252726Srpaulo wpa_printf(MSG_ERROR, "Failed to initialize " 235252726Srpaulo "driver '%s'", 236252726Srpaulo wpa_drivers[i]->name); 237252726Srpaulo return -1; 238252726Srpaulo } 239252726Srpaulo } 240252726Srpaulo 241252726Srpaulo params.global_priv = global.drv_priv[i]; 242252726Srpaulo break; 243252726Srpaulo } 244214503Srpaulo params.bssid = b; 245214503Srpaulo params.ifname = hapd->conf->iface; 246252726Srpaulo params.ssid = hapd->conf->ssid.ssid; 247214503Srpaulo params.ssid_len = hapd->conf->ssid.ssid_len; 248214503Srpaulo params.test_socket = hapd->conf->test_socket; 249214503Srpaulo params.use_pae_group_addr = hapd->conf->use_pae_group_addr; 250214503Srpaulo 251214503Srpaulo params.num_bridge = hapd->iface->num_bss; 252252726Srpaulo params.bridge = os_calloc(hapd->iface->num_bss, sizeof(char *)); 253214503Srpaulo if (params.bridge == NULL) 254214503Srpaulo return -1; 255214503Srpaulo for (i = 0; i < hapd->iface->num_bss; i++) { 256214503Srpaulo struct hostapd_data *bss = hapd->iface->bss[i]; 257214503Srpaulo if (bss->conf->bridge[0]) 258214503Srpaulo params.bridge[i] = bss->conf->bridge; 259214503Srpaulo } 260214503Srpaulo 261214503Srpaulo params.own_addr = hapd->own_addr; 262214503Srpaulo 263214503Srpaulo hapd->drv_priv = hapd->driver->hapd_init(hapd, ¶ms); 264214503Srpaulo os_free(params.bridge); 265214503Srpaulo if (hapd->drv_priv == NULL) { 266214503Srpaulo wpa_printf(MSG_ERROR, "%s driver initialization failed.", 267214503Srpaulo hapd->driver->name); 268214503Srpaulo hapd->driver = NULL; 269214503Srpaulo return -1; 270214503Srpaulo } 271214503Srpaulo 272252726Srpaulo if (hapd->driver->get_capa && 273252726Srpaulo hapd->driver->get_capa(hapd->drv_priv, &capa) == 0) { 274252726Srpaulo iface->drv_flags = capa.flags; 275252726Srpaulo iface->probe_resp_offloads = capa.probe_resp_offloads; 276252726Srpaulo } 277252726Srpaulo 278214503Srpaulo return 0; 279214503Srpaulo} 280214503Srpaulo 281214503Srpaulo 282214503Srpaulostatic struct hostapd_iface * 283214503Srpaulohostapd_interface_init(struct hapd_interfaces *interfaces, 284214503Srpaulo const char *config_fname, int debug) 285214503Srpaulo{ 286214503Srpaulo struct hostapd_iface *iface; 287214503Srpaulo int k; 288214503Srpaulo 289214503Srpaulo wpa_printf(MSG_ERROR, "Configuration file: %s", config_fname); 290214503Srpaulo iface = hostapd_init(config_fname); 291214503Srpaulo if (!iface) 292214503Srpaulo return NULL; 293214503Srpaulo iface->interfaces = interfaces; 294214503Srpaulo 295214503Srpaulo for (k = 0; k < debug; k++) { 296214503Srpaulo if (iface->bss[0]->conf->logger_stdout_level > 0) 297214503Srpaulo iface->bss[0]->conf->logger_stdout_level--; 298214503Srpaulo } 299214503Srpaulo 300252726Srpaulo if (iface->conf->bss[0].iface[0] != 0 || 301252726Srpaulo hostapd_drv_none(iface->bss[0])) { 302252726Srpaulo if (hostapd_driver_init(iface) || 303252726Srpaulo hostapd_setup_interface(iface)) { 304252726Srpaulo hostapd_interface_deinit_free(iface); 305252726Srpaulo return NULL; 306252726Srpaulo } 307214503Srpaulo } 308214503Srpaulo 309214503Srpaulo return iface; 310214503Srpaulo} 311214503Srpaulo 312214503Srpaulo 313214503Srpaulo/** 314214503Srpaulo * handle_term - SIGINT and SIGTERM handler to terminate hostapd process 315214503Srpaulo */ 316214503Srpaulostatic void handle_term(int sig, void *signal_ctx) 317214503Srpaulo{ 318214503Srpaulo wpa_printf(MSG_DEBUG, "Signal %d received - terminating", sig); 319214503Srpaulo eloop_terminate(); 320214503Srpaulo} 321214503Srpaulo 322214503Srpaulo 323214503Srpaulo#ifndef CONFIG_NATIVE_WINDOWS 324214503Srpaulo 325214503Srpaulostatic int handle_reload_iface(struct hostapd_iface *iface, void *ctx) 326214503Srpaulo{ 327214503Srpaulo if (hostapd_reload_config(iface) < 0) { 328214503Srpaulo wpa_printf(MSG_WARNING, "Failed to read new configuration " 329214503Srpaulo "file - continuing with old."); 330214503Srpaulo } 331214503Srpaulo return 0; 332214503Srpaulo} 333214503Srpaulo 334214503Srpaulo 335214503Srpaulo/** 336214503Srpaulo * handle_reload - SIGHUP handler to reload configuration 337214503Srpaulo */ 338214503Srpaulostatic void handle_reload(int sig, void *signal_ctx) 339214503Srpaulo{ 340214503Srpaulo struct hapd_interfaces *interfaces = signal_ctx; 341214503Srpaulo wpa_printf(MSG_DEBUG, "Signal %d received - reloading configuration", 342214503Srpaulo sig); 343214503Srpaulo hostapd_for_each_interface(interfaces, handle_reload_iface, NULL); 344214503Srpaulo} 345214503Srpaulo 346214503Srpaulo 347214503Srpaulostatic void handle_dump_state(int sig, void *signal_ctx) 348214503Srpaulo{ 349214503Srpaulo#ifdef HOSTAPD_DUMP_STATE 350214503Srpaulo struct hapd_interfaces *interfaces = signal_ctx; 351214503Srpaulo hostapd_for_each_interface(interfaces, handle_dump_state_iface, NULL); 352214503Srpaulo#endif /* HOSTAPD_DUMP_STATE */ 353214503Srpaulo} 354214503Srpaulo#endif /* CONFIG_NATIVE_WINDOWS */ 355214503Srpaulo 356214503Srpaulo 357252726Srpaulostatic int hostapd_global_init(struct hapd_interfaces *interfaces, 358252726Srpaulo const char *entropy_file) 359214503Srpaulo{ 360252726Srpaulo int i; 361252726Srpaulo 362252726Srpaulo os_memset(&global, 0, sizeof(global)); 363252726Srpaulo 364214503Srpaulo hostapd_logger_register_cb(hostapd_logger_cb); 365214503Srpaulo 366214503Srpaulo if (eap_server_register_methods()) { 367214503Srpaulo wpa_printf(MSG_ERROR, "Failed to register EAP methods"); 368214503Srpaulo return -1; 369214503Srpaulo } 370214503Srpaulo 371214503Srpaulo if (eloop_init()) { 372214503Srpaulo wpa_printf(MSG_ERROR, "Failed to initialize event loop"); 373214503Srpaulo return -1; 374214503Srpaulo } 375214503Srpaulo 376252726Srpaulo random_init(entropy_file); 377252726Srpaulo 378214503Srpaulo#ifndef CONFIG_NATIVE_WINDOWS 379214503Srpaulo eloop_register_signal(SIGHUP, handle_reload, interfaces); 380214503Srpaulo eloop_register_signal(SIGUSR1, handle_dump_state, interfaces); 381214503Srpaulo#endif /* CONFIG_NATIVE_WINDOWS */ 382214503Srpaulo eloop_register_signal_terminate(handle_term, interfaces); 383214503Srpaulo 384214503Srpaulo#ifndef CONFIG_NATIVE_WINDOWS 385214503Srpaulo openlog("hostapd", 0, LOG_DAEMON); 386214503Srpaulo#endif /* CONFIG_NATIVE_WINDOWS */ 387214503Srpaulo 388252726Srpaulo for (i = 0; wpa_drivers[i]; i++) 389252726Srpaulo global.drv_count++; 390252726Srpaulo if (global.drv_count == 0) { 391252726Srpaulo wpa_printf(MSG_ERROR, "No drivers enabled"); 392252726Srpaulo return -1; 393252726Srpaulo } 394252726Srpaulo global.drv_priv = os_calloc(global.drv_count, sizeof(void *)); 395252726Srpaulo if (global.drv_priv == NULL) 396252726Srpaulo return -1; 397252726Srpaulo 398214503Srpaulo return 0; 399214503Srpaulo} 400214503Srpaulo 401214503Srpaulo 402214503Srpaulostatic void hostapd_global_deinit(const char *pid_file) 403214503Srpaulo{ 404252726Srpaulo int i; 405252726Srpaulo 406252726Srpaulo for (i = 0; wpa_drivers[i] && global.drv_priv; i++) { 407252726Srpaulo if (!global.drv_priv[i]) 408252726Srpaulo continue; 409252726Srpaulo wpa_drivers[i]->global_deinit(global.drv_priv[i]); 410252726Srpaulo } 411252726Srpaulo os_free(global.drv_priv); 412252726Srpaulo global.drv_priv = NULL; 413252726Srpaulo 414214503Srpaulo#ifdef EAP_SERVER_TNC 415214503Srpaulo tncs_global_deinit(); 416214503Srpaulo#endif /* EAP_SERVER_TNC */ 417214503Srpaulo 418252726Srpaulo random_deinit(); 419252726Srpaulo 420214503Srpaulo eloop_destroy(); 421214503Srpaulo 422214503Srpaulo#ifndef CONFIG_NATIVE_WINDOWS 423214503Srpaulo closelog(); 424214503Srpaulo#endif /* CONFIG_NATIVE_WINDOWS */ 425214503Srpaulo 426214503Srpaulo eap_server_unregister_methods(); 427214503Srpaulo 428214503Srpaulo os_daemonize_terminate(pid_file); 429214503Srpaulo} 430214503Srpaulo 431214503Srpaulo 432214503Srpaulostatic int hostapd_global_run(struct hapd_interfaces *ifaces, int daemonize, 433214503Srpaulo const char *pid_file) 434214503Srpaulo{ 435214503Srpaulo#ifdef EAP_SERVER_TNC 436214503Srpaulo int tnc = 0; 437214503Srpaulo size_t i, k; 438214503Srpaulo 439214503Srpaulo for (i = 0; !tnc && i < ifaces->count; i++) { 440214503Srpaulo for (k = 0; k < ifaces->iface[i]->num_bss; k++) { 441214503Srpaulo if (ifaces->iface[i]->bss[0]->conf->tnc) { 442214503Srpaulo tnc++; 443214503Srpaulo break; 444214503Srpaulo } 445214503Srpaulo } 446214503Srpaulo } 447214503Srpaulo 448214503Srpaulo if (tnc && tncs_global_init() < 0) { 449214503Srpaulo wpa_printf(MSG_ERROR, "Failed to initialize TNCS"); 450214503Srpaulo return -1; 451214503Srpaulo } 452214503Srpaulo#endif /* EAP_SERVER_TNC */ 453214503Srpaulo 454214503Srpaulo if (daemonize && os_daemonize(pid_file)) { 455214503Srpaulo perror("daemon"); 456214503Srpaulo return -1; 457214503Srpaulo } 458214503Srpaulo 459214503Srpaulo eloop_run(); 460214503Srpaulo 461214503Srpaulo return 0; 462214503Srpaulo} 463214503Srpaulo 464214503Srpaulo 465214503Srpaulostatic void show_version(void) 466214503Srpaulo{ 467214503Srpaulo fprintf(stderr, 468214503Srpaulo "hostapd v" VERSION_STR "\n" 469214503Srpaulo "User space daemon for IEEE 802.11 AP management,\n" 470214503Srpaulo "IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n" 471252726Srpaulo "Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi> " 472214503Srpaulo "and contributors\n"); 473214503Srpaulo} 474214503Srpaulo 475214503Srpaulo 476214503Srpaulostatic void usage(void) 477214503Srpaulo{ 478214503Srpaulo show_version(); 479214503Srpaulo fprintf(stderr, 480214503Srpaulo "\n" 481252726Srpaulo "usage: hostapd [-hdBKtv] [-P <PID file>] [-e <entropy file>] " 482252726Srpaulo "\\\n" 483252726Srpaulo " [-g <global ctrl_iface>] <configuration file(s)>\n" 484214503Srpaulo "\n" 485214503Srpaulo "options:\n" 486214503Srpaulo " -h show this usage\n" 487214503Srpaulo " -d show more debug messages (-dd for even more)\n" 488214503Srpaulo " -B run daemon in the background\n" 489252726Srpaulo " -e entropy file\n" 490252726Srpaulo " -g global control interface path\n" 491214503Srpaulo " -P PID file\n" 492214503Srpaulo " -K include key data in debug messages\n" 493252726Srpaulo#ifdef CONFIG_DEBUG_FILE 494252726Srpaulo " -f log output to debug file instead of stdout\n" 495252726Srpaulo#endif /* CONFIG_DEBUG_FILE */ 496214503Srpaulo " -t include timestamps in some debug messages\n" 497214503Srpaulo " -v show hostapd version\n"); 498214503Srpaulo 499214503Srpaulo exit(1); 500214503Srpaulo} 501214503Srpaulo 502214503Srpaulo 503252726Srpaulostatic const char * hostapd_msg_ifname_cb(void *ctx) 504252726Srpaulo{ 505252726Srpaulo struct hostapd_data *hapd = ctx; 506252726Srpaulo if (hapd && hapd->iconf && hapd->iconf->bss) 507252726Srpaulo return hapd->iconf->bss->iface; 508252726Srpaulo return NULL; 509252726Srpaulo} 510252726Srpaulo 511252726Srpaulo 512252726Srpaulostatic int hostapd_get_global_ctrl_iface(struct hapd_interfaces *interfaces, 513252726Srpaulo const char *path) 514252726Srpaulo{ 515252726Srpaulo char *pos; 516252726Srpaulo os_free(interfaces->global_iface_path); 517252726Srpaulo interfaces->global_iface_path = os_strdup(path); 518252726Srpaulo if (interfaces->global_iface_path == NULL) 519252726Srpaulo return -1; 520252726Srpaulo pos = os_strrchr(interfaces->global_iface_path, '/'); 521252726Srpaulo if (pos == NULL) { 522252726Srpaulo os_free(interfaces->global_iface_path); 523252726Srpaulo interfaces->global_iface_path = NULL; 524252726Srpaulo return -1; 525252726Srpaulo } 526252726Srpaulo 527252726Srpaulo *pos = '\0'; 528252726Srpaulo interfaces->global_iface_name = pos + 1; 529252726Srpaulo 530252726Srpaulo return 0; 531252726Srpaulo} 532252726Srpaulo 533252726Srpaulo 534214503Srpauloint main(int argc, char *argv[]) 535214503Srpaulo{ 536214503Srpaulo struct hapd_interfaces interfaces; 537214503Srpaulo int ret = 1; 538214503Srpaulo size_t i; 539214503Srpaulo int c, debug = 0, daemonize = 0; 540214503Srpaulo char *pid_file = NULL; 541252726Srpaulo const char *log_file = NULL; 542252726Srpaulo const char *entropy_file = NULL; 543214503Srpaulo 544214503Srpaulo if (os_program_init()) 545214503Srpaulo return -1; 546214503Srpaulo 547252726Srpaulo os_memset(&interfaces, 0, sizeof(interfaces)); 548252726Srpaulo interfaces.reload_config = hostapd_reload_config; 549252726Srpaulo interfaces.config_read_cb = hostapd_config_read; 550252726Srpaulo interfaces.for_each_interface = hostapd_for_each_interface; 551252726Srpaulo interfaces.ctrl_iface_init = hostapd_ctrl_iface_init; 552252726Srpaulo interfaces.ctrl_iface_deinit = hostapd_ctrl_iface_deinit; 553252726Srpaulo interfaces.driver_init = hostapd_driver_init; 554252726Srpaulo interfaces.global_iface_path = NULL; 555252726Srpaulo interfaces.global_iface_name = NULL; 556252726Srpaulo interfaces.global_ctrl_sock = -1; 557252726Srpaulo 558214503Srpaulo for (;;) { 559252726Srpaulo c = getopt(argc, argv, "Bde:f:hKP:tvg:"); 560214503Srpaulo if (c < 0) 561214503Srpaulo break; 562214503Srpaulo switch (c) { 563214503Srpaulo case 'h': 564214503Srpaulo usage(); 565214503Srpaulo break; 566214503Srpaulo case 'd': 567214503Srpaulo debug++; 568214503Srpaulo if (wpa_debug_level > 0) 569214503Srpaulo wpa_debug_level--; 570214503Srpaulo break; 571214503Srpaulo case 'B': 572214503Srpaulo daemonize++; 573214503Srpaulo break; 574252726Srpaulo case 'e': 575252726Srpaulo entropy_file = optarg; 576252726Srpaulo break; 577252726Srpaulo case 'f': 578252726Srpaulo log_file = optarg; 579252726Srpaulo break; 580214503Srpaulo case 'K': 581214503Srpaulo wpa_debug_show_keys++; 582214503Srpaulo break; 583214503Srpaulo case 'P': 584214503Srpaulo os_free(pid_file); 585214503Srpaulo pid_file = os_rel2abs_path(optarg); 586214503Srpaulo break; 587214503Srpaulo case 't': 588214503Srpaulo wpa_debug_timestamp++; 589214503Srpaulo break; 590214503Srpaulo case 'v': 591214503Srpaulo show_version(); 592214503Srpaulo exit(1); 593214503Srpaulo break; 594252726Srpaulo case 'g': 595252726Srpaulo hostapd_get_global_ctrl_iface(&interfaces, optarg); 596252726Srpaulo break; 597214503Srpaulo 598214503Srpaulo default: 599214503Srpaulo usage(); 600214503Srpaulo break; 601214503Srpaulo } 602214503Srpaulo } 603214503Srpaulo 604252726Srpaulo if (optind == argc && interfaces.global_iface_path == NULL) 605214503Srpaulo usage(); 606214503Srpaulo 607252726Srpaulo wpa_msg_register_ifname_cb(hostapd_msg_ifname_cb); 608252726Srpaulo 609252726Srpaulo if (log_file) 610252726Srpaulo wpa_debug_open_file(log_file); 611252726Srpaulo 612214503Srpaulo interfaces.count = argc - optind; 613252726Srpaulo if (interfaces.count) { 614252726Srpaulo interfaces.iface = os_calloc(interfaces.count, 615252726Srpaulo sizeof(struct hostapd_iface *)); 616252726Srpaulo if (interfaces.iface == NULL) { 617252726Srpaulo wpa_printf(MSG_ERROR, "malloc failed"); 618252726Srpaulo return -1; 619252726Srpaulo } 620214503Srpaulo } 621214503Srpaulo 622252726Srpaulo if (hostapd_global_init(&interfaces, entropy_file)) 623214503Srpaulo return -1; 624214503Srpaulo 625214503Srpaulo /* Initialize interfaces */ 626214503Srpaulo for (i = 0; i < interfaces.count; i++) { 627214503Srpaulo interfaces.iface[i] = hostapd_interface_init(&interfaces, 628214503Srpaulo argv[optind + i], 629214503Srpaulo debug); 630214503Srpaulo if (!interfaces.iface[i]) 631214503Srpaulo goto out; 632214503Srpaulo } 633214503Srpaulo 634252726Srpaulo hostapd_global_ctrl_iface_init(&interfaces); 635252726Srpaulo 636214503Srpaulo if (hostapd_global_run(&interfaces, daemonize, pid_file)) 637214503Srpaulo goto out; 638214503Srpaulo 639214503Srpaulo ret = 0; 640214503Srpaulo 641214503Srpaulo out: 642252726Srpaulo hostapd_global_ctrl_iface_deinit(&interfaces); 643214503Srpaulo /* Deinitialize all interfaces */ 644214503Srpaulo for (i = 0; i < interfaces.count; i++) 645214503Srpaulo hostapd_interface_deinit_free(interfaces.iface[i]); 646214503Srpaulo os_free(interfaces.iface); 647214503Srpaulo 648214503Srpaulo hostapd_global_deinit(pid_file); 649214503Srpaulo os_free(pid_file); 650214503Srpaulo 651252726Srpaulo if (log_file) 652252726Srpaulo wpa_debug_close_file(); 653252726Srpaulo 654214503Srpaulo os_program_deinit(); 655214503Srpaulo 656214503Srpaulo return ret; 657214503Srpaulo} 658