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
15 #include "includes.h"
16
17 #include "common.h"
18
19 #ifdef CONFIG_DEBUG_SYSLOG
20 #include <syslog.h>
21
22 static int wpa_debug_syslog = 0;
23 #endif /* CONFIG_DEBUG_SYSLOG */
24
25
26 int wpa_debug_level = MSG_INFO;
27 int wpa_debug_show_keys = 0;
28 int wpa_debug_timestamp = 0;
29
30
31 #ifdef CONFIG_ANDROID_LOG
32
33 #include <android/log.h>
34
35 #ifndef ANDROID_LOG_NAME
36 #define ANDROID_LOG_NAME "wpa_supplicant"
37 #endif
38
android_printf(int level,char * format,...)39 void 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);
52 __android_log_vprint(level, ANDROID_LOG_NAME, format, ap);
53 va_end(ap);
54 }
55 }
56
57 #else /* CONFIG_ANDROID_LOG */
58
59 #ifndef CONFIG_NO_STDOUT_DEBUG
60
61 #ifdef CONFIG_DEBUG_FILE
62 static FILE *out_file = NULL;
63 #endif /* CONFIG_DEBUG_FILE */
64
65
wpa_debug_print_timestamp(void)66 void 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
wpa_debug_open_syslog(void)89 void wpa_debug_open_syslog(void)
90 {
91 openlog("wpa_supplicant", LOG_PID | LOG_NDELAY, LOG_HOSTAPD);
92 wpa_debug_syslog++;
93 }
94
95
wpa_debug_close_syslog(void)96 void wpa_debug_close_syslog(void)
97 {
98 if (wpa_debug_syslog)
99 closelog();
100 }
101
102
syslog_priority(int level)103 static 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 */
wpa_printf(int level,const char * fmt,...)132 void 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
_wpa_hexdump(int level,const char * title,const u8 * buf,size_t len,int show)163 static 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
wpa_hexdump(int level,const char * title,const u8 * buf,size_t len)200 void 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
wpa_hexdump_key(int level,const char * title,const u8 * buf,size_t len)206 void 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
_wpa_hexdump_ascii(int level,const char * title,const u8 * buf,size_t len,int show)212 static 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
wpa_hexdump_ascii(int level,const char * title,const u8 * buf,size_t len)297 void 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
wpa_hexdump_ascii_key(int level,const char * title,const u8 * buf,size_t len)303 void 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
311 static char *last_path = NULL;
312 #endif /* CONFIG_DEBUG_FILE */
313
wpa_debug_reopen_file(void)314 int 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
wpa_debug_open_file(const char * path)335 int 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
wpa_debug_close_file(void)361 void 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
378 static wpa_msg_cb_func wpa_msg_cb = NULL;
379
wpa_msg_register_cb(wpa_msg_cb_func func)380 void wpa_msg_register_cb(wpa_msg_cb_func func)
381 {
382 wpa_msg_cb = func;
383 }
384
385
386 static wpa_msg_get_ifname_func wpa_msg_ifname_cb = NULL;
387
wpa_msg_register_ifname_cb(wpa_msg_get_ifname_func func)388 void wpa_msg_register_ifname_cb(wpa_msg_get_ifname_func func)
389 {
390 wpa_msg_ifname_cb = func;
391 }
392
393
wpa_msg(void * ctx,int level,const char * fmt,...)394 void 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
wpa_msg_ctrl(void * ctx,int level,const char * fmt,...)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
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
454 static hostapd_logger_cb_func hostapd_logger_cb = NULL;
455
hostapd_logger_register_cb(hostapd_logger_cb_func func)456 void hostapd_logger_register_cb(hostapd_logger_cb_func func)
457 {
458 hostapd_logger_cb = func;
459 }
460
461
hostapd_logger(void * ctx,const u8 * addr,unsigned int module,int level,const char * fmt,...)462 void 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 */
489