wpa_debug.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. /*
  2. * wpa_supplicant/hostapd / Debug prints
  3. * Copyright (c) 2002-2007, 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. #include "common.h"
  16. #ifdef CONFIG_DEBUG_FILE
  17. static FILE *out_file = NULL;
  18. #endif /* CONFIG_DEBUG_FILE */
  19. int wpa_debug_level = MSG_INFO;
  20. int wpa_debug_show_keys = 0;
  21. int wpa_debug_timestamp = 0;
  22. #ifndef CONFIG_NO_STDOUT_DEBUG
  23. void wpa_debug_print_timestamp(void)
  24. {
  25. struct os_time tv;
  26. if (!wpa_debug_timestamp)
  27. return;
  28. os_get_time(&tv);
  29. #ifdef CONFIG_DEBUG_FILE
  30. if (out_file) {
  31. fprintf(out_file, "%ld.%06u: ", (long) tv.sec,
  32. (unsigned int) tv.usec);
  33. } else
  34. #endif /* CONFIG_DEBUG_FILE */
  35. printf("%ld.%06u: ", (long) tv.sec, (unsigned int) tv.usec);
  36. }
  37. /**
  38. * wpa_printf - conditional printf
  39. * @level: priority level (MSG_*) of the message
  40. * @fmt: printf format string, followed by optional arguments
  41. *
  42. * This function is used to print conditional debugging and error messages. The
  43. * output may be directed to stdout, stderr, and/or syslog based on
  44. * configuration.
  45. *
  46. * Note: New line '\n' is added to the end of the text when printing to stdout.
  47. */
  48. void wpa_printf(int level, char *fmt, ...)
  49. {
  50. va_list ap;
  51. va_start(ap, fmt);
  52. if (level >= wpa_debug_level) {
  53. wpa_debug_print_timestamp();
  54. #ifdef CONFIG_DEBUG_FILE
  55. if (out_file) {
  56. vfprintf(out_file, fmt, ap);
  57. fprintf(out_file, "\n");
  58. } else {
  59. #endif /* CONFIG_DEBUG_FILE */
  60. vprintf(fmt, ap);
  61. printf("\n");
  62. #ifdef CONFIG_DEBUG_FILE
  63. }
  64. #endif /* CONFIG_DEBUG_FILE */
  65. }
  66. va_end(ap);
  67. }
  68. static void _wpa_hexdump(int level, const char *title, const u8 *buf,
  69. size_t len, int show)
  70. {
  71. size_t i;
  72. if (level < wpa_debug_level)
  73. return;
  74. wpa_debug_print_timestamp();
  75. #ifdef CONFIG_DEBUG_FILE
  76. if (out_file) {
  77. fprintf(out_file, "%s - hexdump(len=%lu):",
  78. title, (unsigned long) len);
  79. if (buf == NULL) {
  80. fprintf(out_file, " [NULL]");
  81. } else if (show) {
  82. for (i = 0; i < len; i++)
  83. fprintf(out_file, " %02x", buf[i]);
  84. } else {
  85. fprintf(out_file, " [REMOVED]");
  86. }
  87. fprintf(out_file, "\n");
  88. } else {
  89. #endif /* CONFIG_DEBUG_FILE */
  90. printf("%s - hexdump(len=%lu):", title, (unsigned long) len);
  91. if (buf == NULL) {
  92. printf(" [NULL]");
  93. } else if (show) {
  94. for (i = 0; i < len; i++)
  95. printf(" %02x", buf[i]);
  96. } else {
  97. printf(" [REMOVED]");
  98. }
  99. printf("\n");
  100. #ifdef CONFIG_DEBUG_FILE
  101. }
  102. #endif /* CONFIG_DEBUG_FILE */
  103. }
  104. void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len)
  105. {
  106. _wpa_hexdump(level, title, buf, len, 1);
  107. }
  108. void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len)
  109. {
  110. _wpa_hexdump(level, title, buf, len, wpa_debug_show_keys);
  111. }
  112. static void _wpa_hexdump_ascii(int level, const char *title, const u8 *buf,
  113. size_t len, int show)
  114. {
  115. size_t i, llen;
  116. const u8 *pos = buf;
  117. const size_t line_len = 16;
  118. if (level < wpa_debug_level)
  119. return;
  120. wpa_debug_print_timestamp();
  121. #ifdef CONFIG_DEBUG_FILE
  122. if (out_file) {
  123. if (!show) {
  124. fprintf(out_file,
  125. "%s - hexdump_ascii(len=%lu): [REMOVED]\n",
  126. title, (unsigned long) len);
  127. return;
  128. }
  129. if (buf == NULL) {
  130. fprintf(out_file,
  131. "%s - hexdump_ascii(len=%lu): [NULL]\n",
  132. title, (unsigned long) len);
  133. return;
  134. }
  135. fprintf(out_file, "%s - hexdump_ascii(len=%lu):\n",
  136. title, (unsigned long) len);
  137. while (len) {
  138. llen = len > line_len ? line_len : len;
  139. fprintf(out_file, " ");
  140. for (i = 0; i < llen; i++)
  141. fprintf(out_file, " %02x", pos[i]);
  142. for (i = llen; i < line_len; i++)
  143. fprintf(out_file, " ");
  144. fprintf(out_file, " ");
  145. for (i = 0; i < llen; i++) {
  146. if (isprint(pos[i]))
  147. fprintf(out_file, "%c", pos[i]);
  148. else
  149. fprintf(out_file, "_");
  150. }
  151. for (i = llen; i < line_len; i++)
  152. fprintf(out_file, " ");
  153. fprintf(out_file, "\n");
  154. pos += llen;
  155. len -= llen;
  156. }
  157. } else {
  158. #endif /* CONFIG_DEBUG_FILE */
  159. if (!show) {
  160. printf("%s - hexdump_ascii(len=%lu): [REMOVED]\n",
  161. title, (unsigned long) len);
  162. return;
  163. }
  164. if (buf == NULL) {
  165. printf("%s - hexdump_ascii(len=%lu): [NULL]\n",
  166. title, (unsigned long) len);
  167. return;
  168. }
  169. printf("%s - hexdump_ascii(len=%lu):\n", title, (unsigned long) len);
  170. while (len) {
  171. llen = len > line_len ? line_len : len;
  172. printf(" ");
  173. for (i = 0; i < llen; i++)
  174. printf(" %02x", pos[i]);
  175. for (i = llen; i < line_len; i++)
  176. printf(" ");
  177. printf(" ");
  178. for (i = 0; i < llen; i++) {
  179. if (isprint(pos[i]))
  180. printf("%c", pos[i]);
  181. else
  182. printf("_");
  183. }
  184. for (i = llen; i < line_len; i++)
  185. printf(" ");
  186. printf("\n");
  187. pos += llen;
  188. len -= llen;
  189. }
  190. #ifdef CONFIG_DEBUG_FILE
  191. }
  192. #endif /* CONFIG_DEBUG_FILE */
  193. }
  194. void wpa_hexdump_ascii(int level, const char *title, const u8 *buf, size_t len)
  195. {
  196. _wpa_hexdump_ascii(level, title, buf, len, 1);
  197. }
  198. void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf,
  199. size_t len)
  200. {
  201. _wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys);
  202. }
  203. int wpa_debug_open_file(const char *path)
  204. {
  205. #ifdef CONFIG_DEBUG_FILE
  206. if (!path)
  207. return 0;
  208. out_file = fopen(path, "a");
  209. if (out_file == NULL) {
  210. wpa_printf(MSG_ERROR, "wpa_debug_open_file: Failed to open "
  211. "output file, using standard output");
  212. return -1;
  213. }
  214. #ifndef _WIN32
  215. setvbuf(out_file, NULL, _IOLBF, 0);
  216. #endif /* _WIN32 */
  217. #endif /* CONFIG_DEBUG_FILE */
  218. return 0;
  219. }
  220. void wpa_debug_close_file(void)
  221. {
  222. #ifdef CONFIG_DEBUG_FILE
  223. if (!out_file)
  224. return;
  225. fclose(out_file);
  226. out_file = NULL;
  227. #endif /* CONFIG_DEBUG_FILE */
  228. }
  229. #endif /* CONFIG_NO_STDOUT_DEBUG */
  230. #ifndef CONFIG_NO_WPA_MSG
  231. static wpa_msg_cb_func wpa_msg_cb = NULL;
  232. void wpa_msg_register_cb(wpa_msg_cb_func func)
  233. {
  234. wpa_msg_cb = func;
  235. }
  236. void wpa_msg(void *ctx, int level, char *fmt, ...)
  237. {
  238. va_list ap;
  239. char *buf;
  240. const int buflen = 2048;
  241. int len;
  242. buf = os_malloc(buflen);
  243. if (buf == NULL) {
  244. wpa_printf(MSG_ERROR, "wpa_msg: Failed to allocate message "
  245. "buffer");
  246. return;
  247. }
  248. va_start(ap, fmt);
  249. len = vsnprintf(buf, buflen, fmt, ap);
  250. va_end(ap);
  251. wpa_printf(level, "%s", buf);
  252. if (wpa_msg_cb)
  253. wpa_msg_cb(ctx, level, buf, len);
  254. os_free(buf);
  255. }
  256. #endif /* CONFIG_NO_WPA_MSG */
  257. #ifndef CONFIG_NO_HOSTAPD_LOGGER
  258. static hostapd_logger_cb_func hostapd_logger_cb = NULL;
  259. void hostapd_logger_register_cb(hostapd_logger_cb_func func)
  260. {
  261. hostapd_logger_cb = func;
  262. }
  263. void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level,
  264. const char *fmt, ...)
  265. {
  266. va_list ap;
  267. char *buf;
  268. const int buflen = 2048;
  269. int len;
  270. buf = os_malloc(buflen);
  271. if (buf == NULL) {
  272. wpa_printf(MSG_ERROR, "hostapd_logger: Failed to allocate "
  273. "message buffer");
  274. return;
  275. }
  276. va_start(ap, fmt);
  277. len = vsnprintf(buf, buflen, fmt, ap);
  278. va_end(ap);
  279. if (hostapd_logger_cb)
  280. hostapd_logger_cb(ctx, addr, module, level, buf, len);
  281. else
  282. wpa_printf(MSG_DEBUG, "hostapd_logger: %s", buf);
  283. os_free(buf);
  284. }
  285. #endif /* CONFIG_NO_HOSTAPD_LOGGER */