xref: /netbsd-src/external/bsd/wpa/dist/hostapd/main.c (revision 6a493d6bc668897c91594964a732d38505b70cbb)
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(&params, 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, &params);
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