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