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