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