main.c 10 KB

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