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