00001
00016 #include "includes.h"
00017 #ifndef CONFIG_NATIVE_WINDOWS
00018 #include <syslog.h>
00019 #endif
00020
00021 #include "eloop.h"
00022 #include "hostapd.h"
00023 #include "version.h"
00024 #include "config.h"
00025 #include "tls.h"
00026 #include "eap_server/eap.h"
00027 #include "eap_server/tncs.h"
00028
00029
00030 extern int wpa_debug_level;
00031 extern int wpa_debug_show_keys;
00032 extern int wpa_debug_timestamp;
00033
00034
00035 struct hapd_interfaces {
00036 size_t count;
00037 struct hostapd_iface **iface;
00038 };
00039
00040
00041 int hostapd_for_each_interface(int (*cb)(struct hostapd_iface *iface,
00042 void *ctx), void *ctx)
00043 {
00044 struct hapd_interfaces *interfaces = eloop_get_user_data();
00045 size_t i;
00046 int ret;
00047
00048 for (i = 0; i < interfaces->count; i++) {
00049 ret = cb(interfaces->iface[i], ctx);
00050 if (ret)
00051 return ret;
00052 }
00053
00054 return 0;
00055 }
00056
00057
00058 #ifndef CONFIG_NO_HOSTAPD_LOGGER
00059 static void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module,
00060 int level, const char *txt, size_t len)
00061 {
00062 struct hostapd_data *hapd = ctx;
00063 char *format, *module_str;
00064 int maxlen;
00065 int conf_syslog_level, conf_stdout_level;
00066 unsigned int conf_syslog, conf_stdout;
00067
00068 maxlen = len + 100;
00069 format = os_malloc(maxlen);
00070 if (!format)
00071 return;
00072
00073 if (hapd && hapd->conf) {
00074 conf_syslog_level = hapd->conf->logger_syslog_level;
00075 conf_stdout_level = hapd->conf->logger_stdout_level;
00076 conf_syslog = hapd->conf->logger_syslog;
00077 conf_stdout = hapd->conf->logger_stdout;
00078 } else {
00079 conf_syslog_level = conf_stdout_level = 0;
00080 conf_syslog = conf_stdout = (unsigned int) -1;
00081 }
00082
00083 switch (module) {
00084 case HOSTAPD_MODULE_IEEE80211:
00085 module_str = "IEEE 802.11";
00086 break;
00087 case HOSTAPD_MODULE_IEEE8021X:
00088 module_str = "IEEE 802.1X";
00089 break;
00090 case HOSTAPD_MODULE_RADIUS:
00091 module_str = "RADIUS";
00092 break;
00093 case HOSTAPD_MODULE_WPA:
00094 module_str = "WPA";
00095 break;
00096 case HOSTAPD_MODULE_DRIVER:
00097 module_str = "DRIVER";
00098 break;
00099 case HOSTAPD_MODULE_IAPP:
00100 module_str = "IAPP";
00101 break;
00102 case HOSTAPD_MODULE_MLME:
00103 module_str = "MLME";
00104 break;
00105 default:
00106 module_str = NULL;
00107 break;
00108 }
00109
00110 if (hapd && hapd->conf && addr)
00111 os_snprintf(format, maxlen, "%s: STA " MACSTR "%s%s: %s",
00112 hapd->conf->iface, MAC2STR(addr),
00113 module_str ? " " : "", module_str, txt);
00114 else if (hapd && hapd->conf)
00115 os_snprintf(format, maxlen, "%s:%s%s %s",
00116 hapd->conf->iface, module_str ? " " : "",
00117 module_str, txt);
00118 else if (addr)
00119 os_snprintf(format, maxlen, "STA " MACSTR "%s%s: %s",
00120 MAC2STR(addr), module_str ? " " : "",
00121 module_str, txt);
00122 else
00123 os_snprintf(format, maxlen, "%s%s%s",
00124 module_str, module_str ? ": " : "", txt);
00125
00126 if ((conf_stdout & module) && level >= conf_stdout_level) {
00127 wpa_debug_print_timestamp();
00128 printf("%s\n", format);
00129 }
00130
00131 #ifndef CONFIG_NATIVE_WINDOWS
00132 if ((conf_syslog & module) && level >= conf_syslog_level) {
00133 int priority;
00134 switch (level) {
00135 case HOSTAPD_LEVEL_DEBUG_VERBOSE:
00136 case HOSTAPD_LEVEL_DEBUG:
00137 priority = LOG_DEBUG;
00138 break;
00139 case HOSTAPD_LEVEL_INFO:
00140 priority = LOG_INFO;
00141 break;
00142 case HOSTAPD_LEVEL_NOTICE:
00143 priority = LOG_NOTICE;
00144 break;
00145 case HOSTAPD_LEVEL_WARNING:
00146 priority = LOG_WARNING;
00147 break;
00148 default:
00149 priority = LOG_INFO;
00150 break;
00151 }
00152 syslog(priority, "%s", format);
00153 }
00154 #endif
00155
00156 os_free(format);
00157 }
00158 #endif
00159
00160
00171 static struct hostapd_iface * hostapd_init(const char *config_file)
00172 {
00173 struct hostapd_iface *hapd_iface = NULL;
00174 struct hostapd_config *conf = NULL;
00175 struct hostapd_data *hapd;
00176 size_t i;
00177
00178 hapd_iface = os_zalloc(sizeof(*hapd_iface));
00179 if (hapd_iface == NULL)
00180 goto fail;
00181
00182 hapd_iface->config_fname = os_strdup(config_file);
00183 if (hapd_iface->config_fname == NULL)
00184 goto fail;
00185
00186 conf = hostapd_config_read(hapd_iface->config_fname);
00187 if (conf == NULL)
00188 goto fail;
00189 hapd_iface->conf = conf;
00190
00191 hapd_iface->num_bss = conf->num_bss;
00192 hapd_iface->bss = os_zalloc(conf->num_bss *
00193 sizeof(struct hostapd_data *));
00194 if (hapd_iface->bss == NULL)
00195 goto fail;
00196
00197 for (i = 0; i < conf->num_bss; i++) {
00198 hapd = hapd_iface->bss[i] =
00199 hostapd_alloc_bss_data(hapd_iface, conf,
00200 &conf->bss[i]);
00201 if (hapd == NULL)
00202 goto fail;
00203 }
00204
00205 return hapd_iface;
00206
00207 fail:
00208 if (conf)
00209 hostapd_config_free(conf);
00210 if (hapd_iface) {
00211 for (i = 0; hapd_iface->bss && i < hapd_iface->num_bss; i++) {
00212 hapd = hapd_iface->bss[i];
00213 if (hapd && hapd->ssl_ctx)
00214 tls_deinit(hapd->ssl_ctx);
00215 }
00216
00217 os_free(hapd_iface->config_fname);
00218 os_free(hapd_iface->bss);
00219 os_free(hapd_iface);
00220 }
00221 return NULL;
00222 }
00223
00224
00225 static struct hostapd_iface * hostapd_interface_init(const char *config_fname,
00226 int debug)
00227 {
00228 struct hostapd_iface *iface;
00229 int k;
00230
00231 wpa_printf(MSG_ERROR, "Configuration file: %s", config_fname);
00232 iface = hostapd_init(config_fname);
00233 if (!iface)
00234 return NULL;
00235
00236 for (k = 0; k < debug; k++) {
00237 if (iface->bss[0]->conf->logger_stdout_level > 0)
00238 iface->bss[0]->conf->logger_stdout_level--;
00239 }
00240
00241 if (hostapd_setup_interface(iface)) {
00242 hostapd_interface_deinit(iface);
00243 return NULL;
00244 }
00245
00246 return iface;
00247 }
00248
00249
00254 static void handle_term(int sig, void *eloop_ctx, void *signal_ctx)
00255 {
00256 wpa_printf(MSG_DEBUG, "Signal %d received - terminating", sig);
00257 eloop_terminate();
00258 }
00259
00260
00261 #ifndef CONFIG_NATIVE_WINDOWS
00262
00266 static void handle_reload(int sig, void *eloop_ctx, void *signal_ctx)
00267 {
00268 wpa_printf(MSG_DEBUG, "Signal %d received - reloading configuration",
00269 sig);
00270 hostapd_for_each_interface(handle_reload_iface, NULL);
00271 }
00272
00273
00274 static void handle_dump_state(int sig, void *eloop_ctx, void *signal_ctx)
00275 {
00276 #ifdef HOSTAPD_DUMP_STATE
00277 hostapd_for_each_interface(handle_dump_state_iface, NULL);
00278 #endif
00279 }
00280 #endif
00281
00282
00283 static int hostapd_global_init(struct hapd_interfaces *interfaces)
00284 {
00285 hostapd_logger_register_cb(hostapd_logger_cb);
00286
00287 if (eap_server_register_methods()) {
00288 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
00289 return -1;
00290 }
00291
00292 if (eloop_init(interfaces)) {
00293 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
00294 return -1;
00295 }
00296
00297 #ifndef CONFIG_NATIVE_WINDOWS
00298 eloop_register_signal(SIGHUP, handle_reload, NULL);
00299 eloop_register_signal(SIGUSR1, handle_dump_state, NULL);
00300 #endif
00301 eloop_register_signal_terminate(handle_term, NULL);
00302
00303 #ifndef CONFIG_NATIVE_WINDOWS
00304 openlog("hostapd", 0, LOG_DAEMON);
00305 #endif
00306
00307 return 0;
00308 }
00309
00310
00311 static void hostapd_global_deinit(const char *pid_file)
00312 {
00313 #ifdef EAP_SERVER_TNC
00314 tncs_global_deinit();
00315 #endif
00316
00317 eloop_destroy();
00318
00319 #ifndef CONFIG_NATIVE_WINDOWS
00320 closelog();
00321 #endif
00322
00323 eap_server_unregister_methods();
00324
00325 os_daemonize_terminate(pid_file);
00326 }
00327
00328
00329 static int hostapd_global_run(struct hapd_interfaces *ifaces, int daemonize,
00330 const char *pid_file)
00331 {
00332 #ifdef EAP_SERVER_TNC
00333 int tnc = 0;
00334 size_t i, k;
00335
00336 for (i = 0; !tnc && i < ifaces->count; i++) {
00337 for (k = 0; k < ifaces->iface[i]->num_bss; k++) {
00338 if (ifaces->iface[i]->bss[0]->conf->tnc) {
00339 tnc++;
00340 break;
00341 }
00342 }
00343 }
00344
00345 if (tnc && tncs_global_init() < 0) {
00346 wpa_printf(MSG_ERROR, "Failed to initialize TNCS");
00347 return -1;
00348 }
00349 #endif
00350
00351 if (daemonize && os_daemonize(pid_file)) {
00352 perror("daemon");
00353 return -1;
00354 }
00355
00356 eloop_run();
00357
00358 return 0;
00359 }
00360
00361
00362 static void show_version(void)
00363 {
00364 fprintf(stderr,
00365 "hostapd v" VERSION_STR "\n"
00366 "User space daemon for IEEE 802.11 AP management,\n"
00367 "IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n"
00368 "Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi> "
00369 "and contributors\n");
00370 }
00371
00372
00373 static void usage(void)
00374 {
00375 show_version();
00376 fprintf(stderr,
00377 "\n"
00378 "usage: hostapd [-hdBKtv] [-P <PID file>] "
00379 "<configuration file(s)>\n"
00380 "\n"
00381 "options:\n"
00382 " -h show this usage\n"
00383 " -d show more debug messages (-dd for even more)\n"
00384 " -B run daemon in the background\n"
00385 " -P PID file\n"
00386 " -K include key data in debug messages\n"
00387 " -t include timestamps in some debug messages\n"
00388 " -v show hostapd version\n");
00389
00390 exit(1);
00391 }
00392
00393
00394 int main(int argc, char *argv[])
00395 {
00396 struct hapd_interfaces interfaces;
00397 int ret = 1;
00398 size_t i;
00399 int c, debug = 0, daemonize = 0;
00400 char *pid_file = NULL;
00401
00402 for (;;) {
00403 c = getopt(argc, argv, "BdhKP:tv");
00404 if (c < 0)
00405 break;
00406 switch (c) {
00407 case 'h':
00408 usage();
00409 break;
00410 case 'd':
00411 debug++;
00412 if (wpa_debug_level > 0)
00413 wpa_debug_level--;
00414 break;
00415 case 'B':
00416 daemonize++;
00417 break;
00418 case 'K':
00419 wpa_debug_show_keys++;
00420 break;
00421 case 'P':
00422 os_free(pid_file);
00423 pid_file = os_rel2abs_path(optarg);
00424 break;
00425 case 't':
00426 wpa_debug_timestamp++;
00427 break;
00428 case 'v':
00429 show_version();
00430 exit(1);
00431 break;
00432
00433 default:
00434 usage();
00435 break;
00436 }
00437 }
00438
00439 if (optind == argc)
00440 usage();
00441
00442 interfaces.count = argc - optind;
00443 interfaces.iface = os_malloc(interfaces.count *
00444 sizeof(struct hostapd_iface *));
00445 if (interfaces.iface == NULL) {
00446 wpa_printf(MSG_ERROR, "malloc failed\n");
00447 return -1;
00448 }
00449
00450 if (hostapd_global_init(&interfaces))
00451 return -1;
00452
00453
00454 for (i = 0; i < interfaces.count; i++) {
00455 interfaces.iface[i] = hostapd_interface_init(argv[optind + i],
00456 debug);
00457 if (!interfaces.iface[i])
00458 goto out;
00459 }
00460
00461 if (hostapd_global_run(&interfaces, daemonize, pid_file))
00462 goto out;
00463
00464 ret = 0;
00465
00466 out:
00467
00468 for (i = 0; i < interfaces.count; i++)
00469 hostapd_interface_deinit(interfaces.iface[i]);
00470 os_free(interfaces.iface);
00471
00472 hostapd_global_deinit(pid_file);
00473 os_free(pid_file);
00474
00475 return ret;
00476 }
00477