1 /* 2 * hostapd / main() 3 * Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * Alternatively, this software may be distributed under the terms of BSD 10 * license. 11 * 12 * See README and COPYING for more details. 13 */ 14 15 #include "utils/includes.h" 16 #ifndef CONFIG_NATIVE_WINDOWS 17 #include <syslog.h> 18 #endif /* CONFIG_NATIVE_WINDOWS */ 19 20 #include "utils/common.h" 21 #include "utils/eloop.h" 22 #include "crypto/random.h" 23 #include "crypto/tls.h" 24 #include "common/version.h" 25 #include "drivers/driver.h" 26 #include "eap_server/eap.h" 27 #include "eap_server/tncs.h" 28 #include "ap/hostapd.h" 29 #include "ap/ap_config.h" 30 #include "config_file.h" 31 #include "eap_register.h" 32 #include "dump_state.h" 33 #include "ctrl_iface.h" 34 35 36 extern int wpa_debug_level; 37 extern int wpa_debug_show_keys; 38 extern int wpa_debug_timestamp; 39 40 extern struct wpa_driver_ops *wpa_drivers[]; 41 42 43 struct hapd_global { 44 void **drv_priv; 45 size_t drv_count; 46 }; 47 48 static struct hapd_global global; 49 50 51 struct hapd_interfaces { 52 size_t count; 53 struct hostapd_iface **iface; 54 }; 55 56 57 static int hostapd_for_each_interface(struct hapd_interfaces *interfaces, 58 int (*cb)(struct hostapd_iface *iface, 59 void *ctx), void *ctx) 60 { 61 size_t i; 62 int ret; 63 64 for (i = 0; i < interfaces->count; i++) { 65 ret = cb(interfaces->iface[i], ctx); 66 if (ret) 67 return ret; 68 } 69 70 return 0; 71 } 72 73 74 #ifndef CONFIG_NO_HOSTAPD_LOGGER 75 static void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module, 76 int level, const char *txt, size_t len) 77 { 78 struct hostapd_data *hapd = ctx; 79 char *format, *module_str; 80 int maxlen; 81 int conf_syslog_level, conf_stdout_level; 82 unsigned int conf_syslog, conf_stdout; 83 84 maxlen = len + 100; 85 format = os_malloc(maxlen); 86 if (!format) 87 return; 88 89 if (hapd && hapd->conf) { 90 conf_syslog_level = hapd->conf->logger_syslog_level; 91 conf_stdout_level = hapd->conf->logger_stdout_level; 92 conf_syslog = hapd->conf->logger_syslog; 93 conf_stdout = hapd->conf->logger_stdout; 94 } else { 95 conf_syslog_level = conf_stdout_level = 0; 96 conf_syslog = conf_stdout = (unsigned int) -1; 97 } 98 99 switch (module) { 100 case HOSTAPD_MODULE_IEEE80211: 101 module_str = "IEEE 802.11"; 102 break; 103 case HOSTAPD_MODULE_IEEE8021X: 104 module_str = "IEEE 802.1X"; 105 break; 106 case HOSTAPD_MODULE_RADIUS: 107 module_str = "RADIUS"; 108 break; 109 case HOSTAPD_MODULE_WPA: 110 module_str = "WPA"; 111 break; 112 case HOSTAPD_MODULE_DRIVER: 113 module_str = "DRIVER"; 114 break; 115 case HOSTAPD_MODULE_IAPP: 116 module_str = "IAPP"; 117 break; 118 case HOSTAPD_MODULE_MLME: 119 module_str = "MLME"; 120 break; 121 default: 122 module_str = NULL; 123 break; 124 } 125 126 if (hapd && hapd->conf && addr) 127 os_snprintf(format, maxlen, "%s: STA " MACSTR "%s%s: %s", 128 hapd->conf->iface, MAC2STR(addr), 129 module_str ? " " : "", module_str, txt); 130 else if (hapd && hapd->conf) 131 os_snprintf(format, maxlen, "%s:%s%s %s", 132 hapd->conf->iface, module_str ? " " : "", 133 module_str, txt); 134 else if (addr) 135 os_snprintf(format, maxlen, "STA " MACSTR "%s%s: %s", 136 MAC2STR(addr), module_str ? " " : "", 137 module_str, txt); 138 else 139 os_snprintf(format, maxlen, "%s%s%s", 140 module_str, module_str ? ": " : "", txt); 141 142 if ((conf_stdout & module) && level >= conf_stdout_level) { 143 wpa_debug_print_timestamp(); 144 printf("%s\n", format); 145 } 146 147 #ifndef CONFIG_NATIVE_WINDOWS 148 if ((conf_syslog & module) && level >= conf_syslog_level) { 149 int priority; 150 switch (level) { 151 case HOSTAPD_LEVEL_DEBUG_VERBOSE: 152 case HOSTAPD_LEVEL_DEBUG: 153 priority = LOG_DEBUG; 154 break; 155 case HOSTAPD_LEVEL_INFO: 156 priority = LOG_INFO; 157 break; 158 case HOSTAPD_LEVEL_NOTICE: 159 priority = LOG_NOTICE; 160 break; 161 case HOSTAPD_LEVEL_WARNING: 162 priority = LOG_WARNING; 163 break; 164 default: 165 priority = LOG_INFO; 166 break; 167 } 168 syslog(priority, "%s", format); 169 } 170 #endif /* CONFIG_NATIVE_WINDOWS */ 171 172 os_free(format); 173 } 174 #endif /* CONFIG_NO_HOSTAPD_LOGGER */ 175 176 177 /** 178 * hostapd_init - Allocate and initialize per-interface data 179 * @config_file: Path to the configuration file 180 * Returns: Pointer to the allocated interface data or %NULL on failure 181 * 182 * This function is used to allocate main data structures for per-interface 183 * data. The allocated data buffer will be freed by calling 184 * hostapd_cleanup_iface(). 185 */ 186 static struct hostapd_iface * hostapd_init(const char *config_file) 187 { 188 struct hostapd_iface *hapd_iface = NULL; 189 struct hostapd_config *conf = NULL; 190 struct hostapd_data *hapd; 191 size_t i; 192 193 hapd_iface = os_zalloc(sizeof(*hapd_iface)); 194 if (hapd_iface == NULL) 195 goto fail; 196 197 hapd_iface->reload_config = hostapd_reload_config; 198 hapd_iface->config_read_cb = hostapd_config_read; 199 hapd_iface->config_fname = os_strdup(config_file); 200 if (hapd_iface->config_fname == NULL) 201 goto fail; 202 hapd_iface->ctrl_iface_init = hostapd_ctrl_iface_init; 203 hapd_iface->ctrl_iface_deinit = hostapd_ctrl_iface_deinit; 204 hapd_iface->for_each_interface = hostapd_for_each_interface; 205 206 conf = hostapd_config_read(hapd_iface->config_fname); 207 if (conf == NULL) 208 goto fail; 209 hapd_iface->conf = conf; 210 211 hapd_iface->num_bss = conf->num_bss; 212 hapd_iface->bss = os_zalloc(conf->num_bss * 213 sizeof(struct hostapd_data *)); 214 if (hapd_iface->bss == NULL) 215 goto fail; 216 217 for (i = 0; i < conf->num_bss; i++) { 218 hapd = hapd_iface->bss[i] = 219 hostapd_alloc_bss_data(hapd_iface, conf, 220 &conf->bss[i]); 221 if (hapd == NULL) 222 goto fail; 223 hapd->msg_ctx = hapd; 224 } 225 226 return hapd_iface; 227 228 fail: 229 if (conf) 230 hostapd_config_free(conf); 231 if (hapd_iface) { 232 os_free(hapd_iface->config_fname); 233 os_free(hapd_iface->bss); 234 os_free(hapd_iface); 235 } 236 return NULL; 237 } 238 239 240 static int hostapd_driver_init(struct hostapd_iface *iface) 241 { 242 struct wpa_init_params params; 243 size_t i; 244 struct hostapd_data *hapd = iface->bss[0]; 245 struct hostapd_bss_config *conf = hapd->conf; 246 u8 *b = conf->bssid; 247 struct wpa_driver_capa capa; 248 249 if (hapd->driver == NULL || hapd->driver->hapd_init == NULL) { 250 wpa_printf(MSG_ERROR, "No hostapd driver wrapper available"); 251 return -1; 252 } 253 254 /* Initialize the driver interface */ 255 if (!(b[0] | b[1] | b[2] | b[3] | b[4] | b[5])) 256 b = NULL; 257 258 os_memset(¶ms, 0, sizeof(params)); 259 for (i = 0; wpa_drivers[i]; i++) { 260 if (wpa_drivers[i] != hapd->driver) 261 continue; 262 263 if (global.drv_priv[i] == NULL && 264 wpa_drivers[i]->global_init) { 265 global.drv_priv[i] = wpa_drivers[i]->global_init(); 266 if (global.drv_priv[i] == NULL) { 267 wpa_printf(MSG_ERROR, "Failed to initialize " 268 "driver '%s'", 269 wpa_drivers[i]->name); 270 return -1; 271 } 272 } 273 274 params.global_priv = global.drv_priv[i]; 275 break; 276 } 277 params.bssid = b; 278 params.ifname = hapd->conf->iface; 279 params.ssid = (const u8 *) hapd->conf->ssid.ssid; 280 params.ssid_len = hapd->conf->ssid.ssid_len; 281 params.test_socket = hapd->conf->test_socket; 282 params.use_pae_group_addr = hapd->conf->use_pae_group_addr; 283 284 params.num_bridge = hapd->iface->num_bss; 285 params.bridge = os_zalloc(hapd->iface->num_bss * sizeof(char *)); 286 if (params.bridge == NULL) 287 return -1; 288 for (i = 0; i < hapd->iface->num_bss; i++) { 289 struct hostapd_data *bss = hapd->iface->bss[i]; 290 if (bss->conf->bridge[0]) 291 params.bridge[i] = bss->conf->bridge; 292 } 293 294 params.own_addr = hapd->own_addr; 295 296 hapd->drv_priv = hapd->driver->hapd_init(hapd, ¶ms); 297 os_free(params.bridge); 298 if (hapd->drv_priv == NULL) { 299 wpa_printf(MSG_ERROR, "%s driver initialization failed.", 300 hapd->driver->name); 301 hapd->driver = NULL; 302 return -1; 303 } 304 305 if (hapd->driver->get_capa && 306 hapd->driver->get_capa(hapd->drv_priv, &capa) == 0) 307 iface->drv_flags = capa.flags; 308 309 return 0; 310 } 311 312 313 static void hostapd_interface_deinit_free(struct hostapd_iface *iface) 314 { 315 const struct wpa_driver_ops *driver; 316 void *drv_priv; 317 if (iface == NULL) 318 return; 319 driver = iface->bss[0]->driver; 320 drv_priv = iface->bss[0]->drv_priv; 321 hostapd_interface_deinit(iface); 322 if (driver && driver->hapd_deinit) 323 driver->hapd_deinit(drv_priv); 324 hostapd_interface_free(iface); 325 } 326 327 328 static struct hostapd_iface * 329 hostapd_interface_init(struct hapd_interfaces *interfaces, 330 const char *config_fname, int debug) 331 { 332 struct hostapd_iface *iface; 333 int k; 334 335 wpa_printf(MSG_ERROR, "Configuration file: %s", config_fname); 336 iface = hostapd_init(config_fname); 337 if (!iface) 338 return NULL; 339 iface->interfaces = interfaces; 340 341 for (k = 0; k < debug; k++) { 342 if (iface->bss[0]->conf->logger_stdout_level > 0) 343 iface->bss[0]->conf->logger_stdout_level--; 344 } 345 346 if (hostapd_driver_init(iface) || 347 hostapd_setup_interface(iface)) { 348 hostapd_interface_deinit_free(iface); 349 return NULL; 350 } 351 352 return iface; 353 } 354 355 356 /** 357 * handle_term - SIGINT and SIGTERM handler to terminate hostapd process 358 */ 359 static void handle_term(int sig, void *signal_ctx) 360 { 361 wpa_printf(MSG_DEBUG, "Signal %d received - terminating", sig); 362 eloop_terminate(); 363 } 364 365 366 #ifndef CONFIG_NATIVE_WINDOWS 367 368 static int handle_reload_iface(struct hostapd_iface *iface, void *ctx) 369 { 370 if (hostapd_reload_config(iface) < 0) { 371 wpa_printf(MSG_WARNING, "Failed to read new configuration " 372 "file - continuing with old."); 373 } 374 return 0; 375 } 376 377 378 /** 379 * handle_reload - SIGHUP handler to reload configuration 380 */ 381 static void handle_reload(int sig, void *signal_ctx) 382 { 383 struct hapd_interfaces *interfaces = signal_ctx; 384 wpa_printf(MSG_DEBUG, "Signal %d received - reloading configuration", 385 sig); 386 hostapd_for_each_interface(interfaces, handle_reload_iface, NULL); 387 } 388 389 390 static void handle_dump_state(int sig, void *signal_ctx) 391 { 392 #ifdef HOSTAPD_DUMP_STATE 393 struct hapd_interfaces *interfaces = signal_ctx; 394 hostapd_for_each_interface(interfaces, handle_dump_state_iface, NULL); 395 #endif /* HOSTAPD_DUMP_STATE */ 396 } 397 #endif /* CONFIG_NATIVE_WINDOWS */ 398 399 400 static int hostapd_global_init(struct hapd_interfaces *interfaces, 401 const char *entropy_file) 402 { 403 int i; 404 405 os_memset(&global, 0, sizeof(global)); 406 407 hostapd_logger_register_cb(hostapd_logger_cb); 408 409 if (eap_server_register_methods()) { 410 wpa_printf(MSG_ERROR, "Failed to register EAP methods"); 411 return -1; 412 } 413 414 if (eloop_init()) { 415 wpa_printf(MSG_ERROR, "Failed to initialize event loop"); 416 return -1; 417 } 418 419 random_init(entropy_file); 420 421 #ifndef CONFIG_NATIVE_WINDOWS 422 eloop_register_signal(SIGHUP, handle_reload, interfaces); 423 eloop_register_signal(SIGUSR1, handle_dump_state, interfaces); 424 #endif /* CONFIG_NATIVE_WINDOWS */ 425 eloop_register_signal_terminate(handle_term, interfaces); 426 427 #ifndef CONFIG_NATIVE_WINDOWS 428 openlog("hostapd", 0, LOG_DAEMON); 429 #endif /* CONFIG_NATIVE_WINDOWS */ 430 431 for (i = 0; wpa_drivers[i]; i++) 432 global.drv_count++; 433 if (global.drv_count == 0) { 434 wpa_printf(MSG_ERROR, "No drivers enabled"); 435 return -1; 436 } 437 global.drv_priv = os_zalloc(global.drv_count * sizeof(void *)); 438 if (global.drv_priv == NULL) 439 return -1; 440 441 return 0; 442 } 443 444 445 static void hostapd_global_deinit(const char *pid_file) 446 { 447 int i; 448 449 for (i = 0; wpa_drivers[i] && global.drv_priv; i++) { 450 if (!global.drv_priv[i]) 451 continue; 452 wpa_drivers[i]->global_deinit(global.drv_priv[i]); 453 } 454 os_free(global.drv_priv); 455 global.drv_priv = NULL; 456 457 #ifdef EAP_SERVER_TNC 458 tncs_global_deinit(); 459 #endif /* EAP_SERVER_TNC */ 460 461 random_deinit(); 462 463 eloop_destroy(); 464 465 #ifndef CONFIG_NATIVE_WINDOWS 466 closelog(); 467 #endif /* CONFIG_NATIVE_WINDOWS */ 468 469 eap_server_unregister_methods(); 470 471 os_daemonize_terminate(pid_file); 472 } 473 474 475 static int hostapd_global_run(struct hapd_interfaces *ifaces, int daemonize, 476 const char *pid_file) 477 { 478 #ifdef EAP_SERVER_TNC 479 int tnc = 0; 480 size_t i, k; 481 482 for (i = 0; !tnc && i < ifaces->count; i++) { 483 for (k = 0; k < ifaces->iface[i]->num_bss; k++) { 484 if (ifaces->iface[i]->bss[0]->conf->tnc) { 485 tnc++; 486 break; 487 } 488 } 489 } 490 491 if (tnc && tncs_global_init() < 0) { 492 wpa_printf(MSG_ERROR, "Failed to initialize TNCS"); 493 return -1; 494 } 495 #endif /* EAP_SERVER_TNC */ 496 497 if (daemonize && os_daemonize(pid_file)) { 498 perror("daemon"); 499 return -1; 500 } 501 502 eloop_run(); 503 504 return 0; 505 } 506 507 508 static void show_version(void) 509 { 510 fprintf(stderr, 511 "hostapd v" VERSION_STR "\n" 512 "User space daemon for IEEE 802.11 AP management,\n" 513 "IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n" 514 "Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi> " 515 "and contributors\n"); 516 } 517 518 519 static void usage(void) 520 { 521 show_version(); 522 fprintf(stderr, 523 "\n" 524 "usage: hostapd [-hdBKtv] [-P <PID file>] [-e <entropy file>] " 525 "<configuration file(s)>\n" 526 "\n" 527 "options:\n" 528 " -h show this usage\n" 529 " -d show more debug messages (-dd for even more)\n" 530 " -B run daemon in the background\n" 531 " -e entropy file\n" 532 " -P PID file\n" 533 " -K include key data in debug messages\n" 534 #ifdef CONFIG_DEBUG_FILE 535 " -f log output to debug file instead of stdout\n" 536 #endif /* CONFIG_DEBUG_FILE */ 537 " -t include timestamps in some debug messages\n" 538 " -v show hostapd version\n"); 539 540 exit(1); 541 } 542 543 544 static const char * hostapd_msg_ifname_cb(void *ctx) 545 { 546 struct hostapd_data *hapd = ctx; 547 if (hapd && hapd->iconf && hapd->iconf->bss) 548 return hapd->iconf->bss->iface; 549 return NULL; 550 } 551 552 553 int main(int argc, char *argv[]) 554 { 555 struct hapd_interfaces interfaces; 556 int ret = 1; 557 size_t i; 558 int c, debug = 0, daemonize = 0; 559 char *pid_file = NULL; 560 const char *log_file = NULL; 561 const char *entropy_file = NULL; 562 563 if (os_program_init()) 564 return -1; 565 566 for (;;) { 567 c = getopt(argc, argv, "Bde:f:hKP:tv"); 568 if (c < 0) 569 break; 570 switch (c) { 571 case 'h': 572 usage(); 573 break; 574 case 'd': 575 debug++; 576 if (wpa_debug_level > 0) 577 wpa_debug_level--; 578 break; 579 case 'B': 580 daemonize++; 581 break; 582 case 'e': 583 entropy_file = optarg; 584 break; 585 case 'f': 586 log_file = optarg; 587 break; 588 case 'K': 589 wpa_debug_show_keys++; 590 break; 591 case 'P': 592 os_free(pid_file); 593 pid_file = os_rel2abs_path(optarg); 594 break; 595 case 't': 596 wpa_debug_timestamp++; 597 break; 598 case 'v': 599 show_version(); 600 exit(1); 601 break; 602 603 default: 604 usage(); 605 break; 606 } 607 } 608 609 if (optind == argc) 610 usage(); 611 612 wpa_msg_register_ifname_cb(hostapd_msg_ifname_cb); 613 614 if (log_file) 615 wpa_debug_open_file(log_file); 616 617 interfaces.count = argc - optind; 618 interfaces.iface = os_zalloc(interfaces.count * 619 sizeof(struct hostapd_iface *)); 620 if (interfaces.iface == NULL) { 621 wpa_printf(MSG_ERROR, "malloc failed"); 622 return -1; 623 } 624 625 if (hostapd_global_init(&interfaces, entropy_file)) 626 return -1; 627 628 /* Initialize interfaces */ 629 for (i = 0; i < interfaces.count; i++) { 630 interfaces.iface[i] = hostapd_interface_init(&interfaces, 631 argv[optind + i], 632 debug); 633 if (!interfaces.iface[i]) 634 goto out; 635 } 636 637 if (hostapd_global_run(&interfaces, daemonize, pid_file)) 638 goto out; 639 640 ret = 0; 641 642 out: 643 /* Deinitialize all interfaces */ 644 for (i = 0; i < interfaces.count; i++) 645 hostapd_interface_deinit_free(interfaces.iface[i]); 646 os_free(interfaces.iface); 647 648 hostapd_global_deinit(pid_file); 649 os_free(pid_file); 650 651 if (log_file) 652 wpa_debug_close_file(); 653 654 os_program_deinit(); 655 656 return ret; 657 } 658