Remove the GPL notification from files contributed by Jouni Malinen
[mech_eap.git] / hostapd / main.c
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 "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@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 }