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