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