]> git.ipfire.org Git - thirdparty/hostap.git/blob - hostapd/main.c
Maintain internal copy of Probe Response offload capabilities
[thirdparty/hostap.git] / hostapd / main.c
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 iface->probe_resp_offloads = capa.probe_resp_offloads;
309 }
310
311 return 0;
312 }
313
314
315 static void hostapd_interface_deinit_free(struct hostapd_iface *iface)
316 {
317 const struct wpa_driver_ops *driver;
318 void *drv_priv;
319 if (iface == NULL)
320 return;
321 driver = iface->bss[0]->driver;
322 drv_priv = iface->bss[0]->drv_priv;
323 hostapd_interface_deinit(iface);
324 if (driver && driver->hapd_deinit)
325 driver->hapd_deinit(drv_priv);
326 hostapd_interface_free(iface);
327 }
328
329
330 static struct hostapd_iface *
331 hostapd_interface_init(struct hapd_interfaces *interfaces,
332 const char *config_fname, int debug)
333 {
334 struct hostapd_iface *iface;
335 int k;
336
337 wpa_printf(MSG_ERROR, "Configuration file: %s", config_fname);
338 iface = hostapd_init(config_fname);
339 if (!iface)
340 return NULL;
341 iface->interfaces = interfaces;
342
343 for (k = 0; k < debug; k++) {
344 if (iface->bss[0]->conf->logger_stdout_level > 0)
345 iface->bss[0]->conf->logger_stdout_level--;
346 }
347
348 if (hostapd_driver_init(iface) ||
349 hostapd_setup_interface(iface)) {
350 hostapd_interface_deinit_free(iface);
351 return NULL;
352 }
353
354 return iface;
355 }
356
357
358 /**
359 * handle_term - SIGINT and SIGTERM handler to terminate hostapd process
360 */
361 static void handle_term(int sig, void *signal_ctx)
362 {
363 wpa_printf(MSG_DEBUG, "Signal %d received - terminating", sig);
364 eloop_terminate();
365 }
366
367
368 #ifndef CONFIG_NATIVE_WINDOWS
369
370 static int handle_reload_iface(struct hostapd_iface *iface, void *ctx)
371 {
372 if (hostapd_reload_config(iface) < 0) {
373 wpa_printf(MSG_WARNING, "Failed to read new configuration "
374 "file - continuing with old.");
375 }
376 return 0;
377 }
378
379
380 /**
381 * handle_reload - SIGHUP handler to reload configuration
382 */
383 static void handle_reload(int sig, void *signal_ctx)
384 {
385 struct hapd_interfaces *interfaces = signal_ctx;
386 wpa_printf(MSG_DEBUG, "Signal %d received - reloading configuration",
387 sig);
388 hostapd_for_each_interface(interfaces, handle_reload_iface, NULL);
389 }
390
391
392 static void handle_dump_state(int sig, void *signal_ctx)
393 {
394 #ifdef HOSTAPD_DUMP_STATE
395 struct hapd_interfaces *interfaces = signal_ctx;
396 hostapd_for_each_interface(interfaces, handle_dump_state_iface, NULL);
397 #endif /* HOSTAPD_DUMP_STATE */
398 }
399 #endif /* CONFIG_NATIVE_WINDOWS */
400
401
402 static int hostapd_global_init(struct hapd_interfaces *interfaces,
403 const char *entropy_file)
404 {
405 int i;
406
407 os_memset(&global, 0, sizeof(global));
408
409 hostapd_logger_register_cb(hostapd_logger_cb);
410
411 if (eap_server_register_methods()) {
412 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
413 return -1;
414 }
415
416 if (eloop_init()) {
417 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
418 return -1;
419 }
420
421 random_init(entropy_file);
422
423 #ifndef CONFIG_NATIVE_WINDOWS
424 eloop_register_signal(SIGHUP, handle_reload, interfaces);
425 eloop_register_signal(SIGUSR1, handle_dump_state, interfaces);
426 #endif /* CONFIG_NATIVE_WINDOWS */
427 eloop_register_signal_terminate(handle_term, interfaces);
428
429 #ifndef CONFIG_NATIVE_WINDOWS
430 openlog("hostapd", 0, LOG_DAEMON);
431 #endif /* CONFIG_NATIVE_WINDOWS */
432
433 for (i = 0; wpa_drivers[i]; i++)
434 global.drv_count++;
435 if (global.drv_count == 0) {
436 wpa_printf(MSG_ERROR, "No drivers enabled");
437 return -1;
438 }
439 global.drv_priv = os_zalloc(global.drv_count * sizeof(void *));
440 if (global.drv_priv == NULL)
441 return -1;
442
443 return 0;
444 }
445
446
447 static void hostapd_global_deinit(const char *pid_file)
448 {
449 int i;
450
451 for (i = 0; wpa_drivers[i] && global.drv_priv; i++) {
452 if (!global.drv_priv[i])
453 continue;
454 wpa_drivers[i]->global_deinit(global.drv_priv[i]);
455 }
456 os_free(global.drv_priv);
457 global.drv_priv = NULL;
458
459 #ifdef EAP_SERVER_TNC
460 tncs_global_deinit();
461 #endif /* EAP_SERVER_TNC */
462
463 random_deinit();
464
465 eloop_destroy();
466
467 #ifndef CONFIG_NATIVE_WINDOWS
468 closelog();
469 #endif /* CONFIG_NATIVE_WINDOWS */
470
471 eap_server_unregister_methods();
472
473 os_daemonize_terminate(pid_file);
474 }
475
476
477 static int hostapd_global_run(struct hapd_interfaces *ifaces, int daemonize,
478 const char *pid_file)
479 {
480 #ifdef EAP_SERVER_TNC
481 int tnc = 0;
482 size_t i, k;
483
484 for (i = 0; !tnc && i < ifaces->count; i++) {
485 for (k = 0; k < ifaces->iface[i]->num_bss; k++) {
486 if (ifaces->iface[i]->bss[0]->conf->tnc) {
487 tnc++;
488 break;
489 }
490 }
491 }
492
493 if (tnc && tncs_global_init() < 0) {
494 wpa_printf(MSG_ERROR, "Failed to initialize TNCS");
495 return -1;
496 }
497 #endif /* EAP_SERVER_TNC */
498
499 if (daemonize && os_daemonize(pid_file)) {
500 perror("daemon");
501 return -1;
502 }
503
504 eloop_run();
505
506 return 0;
507 }
508
509
510 static void show_version(void)
511 {
512 fprintf(stderr,
513 "hostapd v" VERSION_STR "\n"
514 "User space daemon for IEEE 802.11 AP management,\n"
515 "IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n"
516 "Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi> "
517 "and contributors\n");
518 }
519
520
521 static void usage(void)
522 {
523 show_version();
524 fprintf(stderr,
525 "\n"
526 "usage: hostapd [-hdBKtv] [-P <PID file>] [-e <entropy file>] "
527 "<configuration file(s)>\n"
528 "\n"
529 "options:\n"
530 " -h show this usage\n"
531 " -d show more debug messages (-dd for even more)\n"
532 " -B run daemon in the background\n"
533 " -e entropy file\n"
534 " -P PID file\n"
535 " -K include key data in debug messages\n"
536 #ifdef CONFIG_DEBUG_FILE
537 " -f log output to debug file instead of stdout\n"
538 #endif /* CONFIG_DEBUG_FILE */
539 " -t include timestamps in some debug messages\n"
540 " -v show hostapd version\n");
541
542 exit(1);
543 }
544
545
546 static const char * hostapd_msg_ifname_cb(void *ctx)
547 {
548 struct hostapd_data *hapd = ctx;
549 if (hapd && hapd->iconf && hapd->iconf->bss)
550 return hapd->iconf->bss->iface;
551 return NULL;
552 }
553
554
555 int main(int argc, char *argv[])
556 {
557 struct hapd_interfaces interfaces;
558 int ret = 1;
559 size_t i;
560 int c, debug = 0, daemonize = 0;
561 char *pid_file = NULL;
562 const char *log_file = NULL;
563 const char *entropy_file = NULL;
564
565 if (os_program_init())
566 return -1;
567
568 for (;;) {
569 c = getopt(argc, argv, "Bde:f:hKP:tv");
570 if (c < 0)
571 break;
572 switch (c) {
573 case 'h':
574 usage();
575 break;
576 case 'd':
577 debug++;
578 if (wpa_debug_level > 0)
579 wpa_debug_level--;
580 break;
581 case 'B':
582 daemonize++;
583 break;
584 case 'e':
585 entropy_file = optarg;
586 break;
587 case 'f':
588 log_file = optarg;
589 break;
590 case 'K':
591 wpa_debug_show_keys++;
592 break;
593 case 'P':
594 os_free(pid_file);
595 pid_file = os_rel2abs_path(optarg);
596 break;
597 case 't':
598 wpa_debug_timestamp++;
599 break;
600 case 'v':
601 show_version();
602 exit(1);
603 break;
604
605 default:
606 usage();
607 break;
608 }
609 }
610
611 if (optind == argc)
612 usage();
613
614 wpa_msg_register_ifname_cb(hostapd_msg_ifname_cb);
615
616 if (log_file)
617 wpa_debug_open_file(log_file);
618
619 interfaces.count = argc - optind;
620 interfaces.iface = os_zalloc(interfaces.count *
621 sizeof(struct hostapd_iface *));
622 if (interfaces.iface == NULL) {
623 wpa_printf(MSG_ERROR, "malloc failed");
624 return -1;
625 }
626
627 if (hostapd_global_init(&interfaces, entropy_file))
628 return -1;
629
630 /* Initialize interfaces */
631 for (i = 0; i < interfaces.count; i++) {
632 interfaces.iface[i] = hostapd_interface_init(&interfaces,
633 argv[optind + i],
634 debug);
635 if (!interfaces.iface[i])
636 goto out;
637 }
638
639 if (hostapd_global_run(&interfaces, daemonize, pid_file))
640 goto out;
641
642 ret = 0;
643
644 out:
645 /* Deinitialize all interfaces */
646 for (i = 0; i < interfaces.count; i++)
647 hostapd_interface_deinit_free(interfaces.iface[i]);
648 os_free(interfaces.iface);
649
650 hostapd_global_deinit(pid_file);
651 os_free(pid_file);
652
653 if (log_file)
654 wpa_debug_close_file();
655
656 os_program_deinit();
657
658 return ret;
659 }