Postpone global_init() call until first driver instance is initialized
[mech_eap.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
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-2011, 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 }