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