wpa_debug.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  1. /*
  2. * wpa_supplicant/hostapd / Debug prints
  3. * Copyright (c) 2002-2007, 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. #include "includes.h"
  9. #include "common.h"
  10. #ifdef CONFIG_DEBUG_SYSLOG
  11. #include <syslog.h>
  12. static int wpa_debug_syslog = 0;
  13. #endif /* CONFIG_DEBUG_SYSLOG */
  14. int wpa_debug_level = MSG_INFO;
  15. int wpa_debug_show_keys = 0;
  16. int wpa_debug_timestamp = 0;
  17. #ifdef CONFIG_ANDROID_LOG
  18. #include <android/log.h>
  19. #ifndef ANDROID_LOG_NAME
  20. #define ANDROID_LOG_NAME "wpa_supplicant"
  21. #endif /* ANDROID_LOG_NAME */
  22. static int wpa_to_android_level(int level)
  23. {
  24. if (level == MSG_ERROR)
  25. return ANDROID_LOG_ERROR;
  26. if (level == MSG_WARNING)
  27. return ANDROID_LOG_WARN;
  28. if (level == MSG_INFO)
  29. return ANDROID_LOG_INFO;
  30. return ANDROID_LOG_DEBUG;
  31. }
  32. #endif /* CONFIG_ANDROID_LOG */
  33. #ifndef CONFIG_NO_STDOUT_DEBUG
  34. #ifdef CONFIG_DEBUG_FILE
  35. static FILE *out_file = NULL;
  36. #endif /* CONFIG_DEBUG_FILE */
  37. void wpa_debug_print_timestamp(void)
  38. {
  39. #ifndef CONFIG_ANDROID_LOG
  40. struct os_time tv;
  41. if (!wpa_debug_timestamp)
  42. return;
  43. os_get_time(&tv);
  44. #ifdef CONFIG_DEBUG_FILE
  45. if (out_file) {
  46. fprintf(out_file, "%ld.%06u: ", (long) tv.sec,
  47. (unsigned int) tv.usec);
  48. } else
  49. #endif /* CONFIG_DEBUG_FILE */
  50. printf("%ld.%06u: ", (long) tv.sec, (unsigned int) tv.usec);
  51. #endif /* CONFIG_ANDROID_LOG */
  52. }
  53. #ifdef CONFIG_DEBUG_SYSLOG
  54. #ifndef LOG_HOSTAPD
  55. #define LOG_HOSTAPD LOG_DAEMON
  56. #endif /* LOG_HOSTAPD */
  57. void wpa_debug_open_syslog(void)
  58. {
  59. openlog("wpa_supplicant", LOG_PID | LOG_NDELAY, LOG_HOSTAPD);
  60. wpa_debug_syslog++;
  61. }
  62. void wpa_debug_close_syslog(void)
  63. {
  64. if (wpa_debug_syslog)
  65. closelog();
  66. }
  67. static int syslog_priority(int level)
  68. {
  69. switch (level) {
  70. case MSG_MSGDUMP:
  71. case MSG_DEBUG:
  72. return LOG_DEBUG;
  73. case MSG_INFO:
  74. return LOG_NOTICE;
  75. case MSG_WARNING:
  76. return LOG_WARNING;
  77. case MSG_ERROR:
  78. return LOG_ERR;
  79. }
  80. return LOG_INFO;
  81. }
  82. #endif /* CONFIG_DEBUG_SYSLOG */
  83. /**
  84. * wpa_printf - conditional printf
  85. * @level: priority level (MSG_*) of the message
  86. * @fmt: printf format string, followed by optional arguments
  87. *
  88. * This function is used to print conditional debugging and error messages. The
  89. * output may be directed to stdout, stderr, and/or syslog based on
  90. * configuration.
  91. *
  92. * Note: New line '\n' is added to the end of the text when printing to stdout.
  93. */
  94. void wpa_printf(int level, const char *fmt, ...)
  95. {
  96. va_list ap;
  97. va_start(ap, fmt);
  98. if (level >= wpa_debug_level) {
  99. #ifdef CONFIG_ANDROID_LOG
  100. __android_log_vprint(wpa_to_android_level(level),
  101. ANDROID_LOG_NAME, fmt, ap);
  102. #else /* CONFIG_ANDROID_LOG */
  103. #ifdef CONFIG_DEBUG_SYSLOG
  104. if (wpa_debug_syslog) {
  105. vsyslog(syslog_priority(level), fmt, ap);
  106. } else {
  107. #endif /* CONFIG_DEBUG_SYSLOG */
  108. wpa_debug_print_timestamp();
  109. #ifdef CONFIG_DEBUG_FILE
  110. if (out_file) {
  111. vfprintf(out_file, fmt, ap);
  112. fprintf(out_file, "\n");
  113. } else {
  114. #endif /* CONFIG_DEBUG_FILE */
  115. vprintf(fmt, ap);
  116. printf("\n");
  117. #ifdef CONFIG_DEBUG_FILE
  118. }
  119. #endif /* CONFIG_DEBUG_FILE */
  120. #ifdef CONFIG_DEBUG_SYSLOG
  121. }
  122. #endif /* CONFIG_DEBUG_SYSLOG */
  123. #endif /* CONFIG_ANDROID_LOG */
  124. }
  125. va_end(ap);
  126. }
  127. static void _wpa_hexdump(int level, const char *title, const u8 *buf,
  128. size_t len, int show)
  129. {
  130. size_t i;
  131. if (level < wpa_debug_level)
  132. return;
  133. #ifdef CONFIG_ANDROID_LOG
  134. {
  135. const char *display;
  136. char *strbuf = NULL;
  137. size_t slen = len;
  138. if (buf == NULL) {
  139. display = " [NULL]";
  140. } else if (len == 0) {
  141. display = "";
  142. } else if (show && len) {
  143. /* Limit debug message length for Android log */
  144. if (slen > 32)
  145. slen = 32;
  146. strbuf = os_malloc(1 + 3 * slen);
  147. if (strbuf == NULL) {
  148. wpa_printf(MSG_ERROR, "wpa_hexdump: Failed to "
  149. "allocate message buffer");
  150. return;
  151. }
  152. for (i = 0; i < slen; i++)
  153. os_snprintf(&strbuf[i * 3], 4, " %02x",
  154. buf[i]);
  155. display = strbuf;
  156. } else {
  157. display = " [REMOVED]";
  158. }
  159. __android_log_print(wpa_to_android_level(level),
  160. ANDROID_LOG_NAME,
  161. "%s - hexdump(len=%lu):%s%s",
  162. title, (long unsigned int) len, display,
  163. len > slen ? " ..." : "");
  164. os_free(strbuf);
  165. return;
  166. }
  167. #else /* CONFIG_ANDROID_LOG */
  168. #ifdef CONFIG_DEBUG_SYSLOG
  169. if (wpa_debug_syslog) {
  170. const char *display;
  171. char *strbuf = NULL;
  172. if (buf == NULL) {
  173. display = " [NULL]";
  174. } else if (len == 0) {
  175. display = "";
  176. } else if (show && len) {
  177. strbuf = os_malloc(1 + 3 * len);
  178. if (strbuf == NULL) {
  179. wpa_printf(MSG_ERROR, "wpa_hexdump: Failed to "
  180. "allocate message buffer");
  181. return;
  182. }
  183. for (i = 0; i < len; i++)
  184. os_snprintf(&strbuf[i * 3], 4, " %02x",
  185. buf[i]);
  186. display = strbuf;
  187. } else {
  188. display = " [REMOVED]";
  189. }
  190. syslog(syslog_priority(level), "%s - hexdump(len=%lu):%s",
  191. title, len, display);
  192. os_free(strbuf);
  193. return;
  194. }
  195. #endif /* CONFIG_DEBUG_SYSLOG */
  196. wpa_debug_print_timestamp();
  197. #ifdef CONFIG_DEBUG_FILE
  198. if (out_file) {
  199. fprintf(out_file, "%s - hexdump(len=%lu):",
  200. title, (unsigned long) len);
  201. if (buf == NULL) {
  202. fprintf(out_file, " [NULL]");
  203. } else if (show) {
  204. for (i = 0; i < len; i++)
  205. fprintf(out_file, " %02x", buf[i]);
  206. } else {
  207. fprintf(out_file, " [REMOVED]");
  208. }
  209. fprintf(out_file, "\n");
  210. } else {
  211. #endif /* CONFIG_DEBUG_FILE */
  212. printf("%s - hexdump(len=%lu):", title, (unsigned long) len);
  213. if (buf == NULL) {
  214. printf(" [NULL]");
  215. } else if (show) {
  216. for (i = 0; i < len; i++)
  217. printf(" %02x", buf[i]);
  218. } else {
  219. printf(" [REMOVED]");
  220. }
  221. printf("\n");
  222. #ifdef CONFIG_DEBUG_FILE
  223. }
  224. #endif /* CONFIG_DEBUG_FILE */
  225. #endif /* CONFIG_ANDROID_LOG */
  226. }
  227. void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len)
  228. {
  229. _wpa_hexdump(level, title, buf, len, 1);
  230. }
  231. void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len)
  232. {
  233. _wpa_hexdump(level, title, buf, len, wpa_debug_show_keys);
  234. }
  235. static void _wpa_hexdump_ascii(int level, const char *title, const u8 *buf,
  236. size_t len, int show)
  237. {
  238. size_t i, llen;
  239. const u8 *pos = buf;
  240. const size_t line_len = 16;
  241. if (level < wpa_debug_level)
  242. return;
  243. #ifdef CONFIG_ANDROID_LOG
  244. _wpa_hexdump(level, title, buf, len, show);
  245. #else /* CONFIG_ANDROID_LOG */
  246. wpa_debug_print_timestamp();
  247. #ifdef CONFIG_DEBUG_FILE
  248. if (out_file) {
  249. if (!show) {
  250. fprintf(out_file,
  251. "%s - hexdump_ascii(len=%lu): [REMOVED]\n",
  252. title, (unsigned long) len);
  253. return;
  254. }
  255. if (buf == NULL) {
  256. fprintf(out_file,
  257. "%s - hexdump_ascii(len=%lu): [NULL]\n",
  258. title, (unsigned long) len);
  259. return;
  260. }
  261. fprintf(out_file, "%s - hexdump_ascii(len=%lu):\n",
  262. title, (unsigned long) len);
  263. while (len) {
  264. llen = len > line_len ? line_len : len;
  265. fprintf(out_file, " ");
  266. for (i = 0; i < llen; i++)
  267. fprintf(out_file, " %02x", pos[i]);
  268. for (i = llen; i < line_len; i++)
  269. fprintf(out_file, " ");
  270. fprintf(out_file, " ");
  271. for (i = 0; i < llen; i++) {
  272. if (isprint(pos[i]))
  273. fprintf(out_file, "%c", pos[i]);
  274. else
  275. fprintf(out_file, "_");
  276. }
  277. for (i = llen; i < line_len; i++)
  278. fprintf(out_file, " ");
  279. fprintf(out_file, "\n");
  280. pos += llen;
  281. len -= llen;
  282. }
  283. } else {
  284. #endif /* CONFIG_DEBUG_FILE */
  285. if (!show) {
  286. printf("%s - hexdump_ascii(len=%lu): [REMOVED]\n",
  287. title, (unsigned long) len);
  288. return;
  289. }
  290. if (buf == NULL) {
  291. printf("%s - hexdump_ascii(len=%lu): [NULL]\n",
  292. title, (unsigned long) len);
  293. return;
  294. }
  295. printf("%s - hexdump_ascii(len=%lu):\n", title, (unsigned long) len);
  296. while (len) {
  297. llen = len > line_len ? line_len : len;
  298. printf(" ");
  299. for (i = 0; i < llen; i++)
  300. printf(" %02x", pos[i]);
  301. for (i = llen; i < line_len; i++)
  302. printf(" ");
  303. printf(" ");
  304. for (i = 0; i < llen; i++) {
  305. if (isprint(pos[i]))
  306. printf("%c", pos[i]);
  307. else
  308. printf("_");
  309. }
  310. for (i = llen; i < line_len; i++)
  311. printf(" ");
  312. printf("\n");
  313. pos += llen;
  314. len -= llen;
  315. }
  316. #ifdef CONFIG_DEBUG_FILE
  317. }
  318. #endif /* CONFIG_DEBUG_FILE */
  319. #endif /* CONFIG_ANDROID_LOG */
  320. }
  321. void wpa_hexdump_ascii(int level, const char *title, const u8 *buf, size_t len)
  322. {
  323. _wpa_hexdump_ascii(level, title, buf, len, 1);
  324. }
  325. void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf,
  326. size_t len)
  327. {
  328. _wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys);
  329. }
  330. #ifdef CONFIG_DEBUG_FILE
  331. static char *last_path = NULL;
  332. #endif /* CONFIG_DEBUG_FILE */
  333. int wpa_debug_reopen_file(void)
  334. {
  335. #ifdef CONFIG_DEBUG_FILE
  336. int rv;
  337. if (last_path) {
  338. char *tmp = os_strdup(last_path);
  339. wpa_debug_close_file();
  340. rv = wpa_debug_open_file(tmp);
  341. os_free(tmp);
  342. } else {
  343. wpa_printf(MSG_ERROR, "Last-path was not set, cannot "
  344. "re-open log file.");
  345. rv = -1;
  346. }
  347. return rv;
  348. #else /* CONFIG_DEBUG_FILE */
  349. return 0;
  350. #endif /* CONFIG_DEBUG_FILE */
  351. }
  352. int wpa_debug_open_file(const char *path)
  353. {
  354. #ifdef CONFIG_DEBUG_FILE
  355. if (!path)
  356. return 0;
  357. if (last_path == NULL || os_strcmp(last_path, path) != 0) {
  358. /* Save our path to enable re-open */
  359. os_free(last_path);
  360. last_path = os_strdup(path);
  361. }
  362. out_file = fopen(path, "a");
  363. if (out_file == NULL) {
  364. wpa_printf(MSG_ERROR, "wpa_debug_open_file: Failed to open "
  365. "output file, using standard output");
  366. return -1;
  367. }
  368. #ifndef _WIN32
  369. setvbuf(out_file, NULL, _IOLBF, 0);
  370. #endif /* _WIN32 */
  371. #endif /* CONFIG_DEBUG_FILE */
  372. return 0;
  373. }
  374. void wpa_debug_close_file(void)
  375. {
  376. #ifdef CONFIG_DEBUG_FILE
  377. if (!out_file)
  378. return;
  379. fclose(out_file);
  380. out_file = NULL;
  381. os_free(last_path);
  382. last_path = NULL;
  383. #endif /* CONFIG_DEBUG_FILE */
  384. }
  385. #endif /* CONFIG_NO_STDOUT_DEBUG */
  386. #ifndef CONFIG_NO_WPA_MSG
  387. static wpa_msg_cb_func wpa_msg_cb = NULL;
  388. void wpa_msg_register_cb(wpa_msg_cb_func func)
  389. {
  390. wpa_msg_cb = func;
  391. }
  392. static wpa_msg_get_ifname_func wpa_msg_ifname_cb = NULL;
  393. void wpa_msg_register_ifname_cb(wpa_msg_get_ifname_func func)
  394. {
  395. wpa_msg_ifname_cb = func;
  396. }
  397. void wpa_msg(void *ctx, int level, const char *fmt, ...)
  398. {
  399. va_list ap;
  400. char *buf;
  401. const int buflen = 2048;
  402. int len;
  403. char prefix[130];
  404. buf = os_malloc(buflen);
  405. if (buf == NULL) {
  406. wpa_printf(MSG_ERROR, "wpa_msg: Failed to allocate message "
  407. "buffer");
  408. return;
  409. }
  410. va_start(ap, fmt);
  411. prefix[0] = '\0';
  412. if (wpa_msg_ifname_cb) {
  413. const char *ifname = wpa_msg_ifname_cb(ctx);
  414. if (ifname) {
  415. int res = os_snprintf(prefix, sizeof(prefix), "%s: ",
  416. ifname);
  417. if (res < 0 || res >= (int) sizeof(prefix))
  418. prefix[0] = '\0';
  419. }
  420. }
  421. len = vsnprintf(buf, buflen, fmt, ap);
  422. va_end(ap);
  423. wpa_printf(level, "%s%s", prefix, buf);
  424. if (wpa_msg_cb)
  425. wpa_msg_cb(ctx, level, buf, len);
  426. os_free(buf);
  427. }
  428. void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...)
  429. {
  430. va_list ap;
  431. char *buf;
  432. const int buflen = 2048;
  433. int len;
  434. if (!wpa_msg_cb)
  435. return;
  436. buf = os_malloc(buflen);
  437. if (buf == NULL) {
  438. wpa_printf(MSG_ERROR, "wpa_msg_ctrl: Failed to allocate "
  439. "message buffer");
  440. return;
  441. }
  442. va_start(ap, fmt);
  443. len = vsnprintf(buf, buflen, fmt, ap);
  444. va_end(ap);
  445. wpa_msg_cb(ctx, level, buf, len);
  446. os_free(buf);
  447. }
  448. #endif /* CONFIG_NO_WPA_MSG */
  449. #ifndef CONFIG_NO_HOSTAPD_LOGGER
  450. static hostapd_logger_cb_func hostapd_logger_cb = NULL;
  451. void hostapd_logger_register_cb(hostapd_logger_cb_func func)
  452. {
  453. hostapd_logger_cb = func;
  454. }
  455. void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level,
  456. const char *fmt, ...)
  457. {
  458. va_list ap;
  459. char *buf;
  460. const int buflen = 2048;
  461. int len;
  462. buf = os_malloc(buflen);
  463. if (buf == NULL) {
  464. wpa_printf(MSG_ERROR, "hostapd_logger: Failed to allocate "
  465. "message buffer");
  466. return;
  467. }
  468. va_start(ap, fmt);
  469. len = vsnprintf(buf, buflen, fmt, ap);
  470. va_end(ap);
  471. if (hostapd_logger_cb)
  472. hostapd_logger_cb(ctx, addr, module, level, buf, len);
  473. else if (addr)
  474. wpa_printf(MSG_DEBUG, "hostapd_logger: STA " MACSTR " - %s",
  475. MAC2STR(addr), buf);
  476. else
  477. wpa_printf(MSG_DEBUG, "hostapd_logger: %s", buf);
  478. os_free(buf);
  479. }
  480. #endif /* CONFIG_NO_HOSTAPD_LOGGER */