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
20 #ifdef CONFIG_DEBUG_FILE
21 static FILE *out_file = NULL;
22 #endif /* CONFIG_DEBUG_FILE */
23 #ifdef CONFIG_ANDROID_LOG
24 int wpa_debug_level = MSG_WARNING;
25 #else
26 int wpa_debug_level = MSG_INFO;
27 #endif
28 int wpa_debug_show_keys = 0;
29 int wpa_debug_timestamp = 0;
30
31
32 #ifdef CONFIG_ANDROID_LOG
33
34 #include <android/log.h>
35
android_printf(int level,char * format,...)36 void android_printf(int level, char *format, ...)
37 {
38 if (level >= wpa_debug_level) {
39 va_list ap;
40 if (level == MSG_ERROR) {
41 level = ANDROID_LOG_ERROR;
42 } else if (level == MSG_WARNING) {
43 level = ANDROID_LOG_WARN;
44 } else if (level == MSG_INFO) {
45 level = ANDROID_LOG_INFO;
46 } else {
47 level = ANDROID_LOG_DEBUG;
48 }
49 va_start(ap, format);
50 __android_log_vprint(level, "wpa_supplicant", format, ap);
51 va_end(ap);
52 }
53 }
54
55 #else /* CONFIG_ANDROID_LOG */
56
57 #ifndef CONFIG_NO_STDOUT_DEBUG
58
wpa_debug_print_timestamp(void)59 void wpa_debug_print_timestamp(void)
60 {
61 struct os_time tv;
62
63 if (!wpa_debug_timestamp)
64 return;
65
66 os_get_time(&tv);
67 #ifdef CONFIG_DEBUG_FILE
68 if (out_file) {
69 fprintf(out_file, "%ld.%06u: ", (long) tv.sec,
70 (unsigned int) tv.usec);
71 } else
72 #endif /* CONFIG_DEBUG_FILE */
73 printf("%ld.%06u: ", (long) tv.sec, (unsigned int) tv.usec);
74 }
75
76
77 /**
78 * wpa_printf - conditional printf
79 * @level: priority level (MSG_*) of the message
80 * @fmt: printf format string, followed by optional arguments
81 *
82 * This function is used to print conditional debugging and error messages. The
83 * output may be directed to stdout, stderr, and/or syslog based on
84 * configuration.
85 *
86 * Note: New line '\n' is added to the end of the text when printing to stdout.
87 */
wpa_printf(int level,const char * fmt,...)88 void wpa_printf(int level, const char *fmt, ...)
89 {
90 va_list ap;
91
92 va_start(ap, fmt);
93 if (level >= wpa_debug_level) {
94 wpa_debug_print_timestamp();
95 #ifdef CONFIG_DEBUG_FILE
96 if (out_file) {
97 vfprintf(out_file, fmt, ap);
98 fprintf(out_file, "\n");
99 } else {
100 #endif /* CONFIG_DEBUG_FILE */
101 vprintf(fmt, ap);
102 printf("\n");
103 #ifdef CONFIG_DEBUG_FILE
104 }
105 #endif /* CONFIG_DEBUG_FILE */
106 }
107 va_end(ap);
108 }
109
110
_wpa_hexdump(int level,const char * title,const u8 * buf,size_t len,int show)111 static void _wpa_hexdump(int level, const char *title, const u8 *buf,
112 size_t len, int show)
113 {
114 size_t i;
115 if (level < wpa_debug_level)
116 return;
117 wpa_debug_print_timestamp();
118 #ifdef CONFIG_DEBUG_FILE
119 if (out_file) {
120 fprintf(out_file, "%s - hexdump(len=%lu):",
121 title, (unsigned long) len);
122 if (buf == NULL) {
123 fprintf(out_file, " [NULL]");
124 } else if (show) {
125 for (i = 0; i < len; i++)
126 fprintf(out_file, " %02x", buf[i]);
127 } else {
128 fprintf(out_file, " [REMOVED]");
129 }
130 fprintf(out_file, "\n");
131 } else {
132 #endif /* CONFIG_DEBUG_FILE */
133 printf("%s - hexdump(len=%lu):", title, (unsigned long) len);
134 if (buf == NULL) {
135 printf(" [NULL]");
136 } else if (show) {
137 for (i = 0; i < len; i++)
138 printf(" %02x", buf[i]);
139 } else {
140 printf(" [REMOVED]");
141 }
142 printf("\n");
143 #ifdef CONFIG_DEBUG_FILE
144 }
145 #endif /* CONFIG_DEBUG_FILE */
146 }
147
wpa_hexdump(int level,const char * title,const u8 * buf,size_t len)148 void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len)
149 {
150 _wpa_hexdump(level, title, buf, len, 1);
151 }
152
153
wpa_hexdump_key(int level,const char * title,const u8 * buf,size_t len)154 void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len)
155 {
156 _wpa_hexdump(level, title, buf, len, wpa_debug_show_keys);
157 }
158
159
_wpa_hexdump_ascii(int level,const char * title,const u8 * buf,size_t len,int show)160 static void _wpa_hexdump_ascii(int level, const char *title, const u8 *buf,
161 size_t len, int show)
162 {
163 size_t i, llen;
164 const u8 *pos = buf;
165 const size_t line_len = 16;
166
167 if (level < wpa_debug_level)
168 return;
169 wpa_debug_print_timestamp();
170 #ifdef CONFIG_DEBUG_FILE
171 if (out_file) {
172 if (!show) {
173 fprintf(out_file,
174 "%s - hexdump_ascii(len=%lu): [REMOVED]\n",
175 title, (unsigned long) len);
176 return;
177 }
178 if (buf == NULL) {
179 fprintf(out_file,
180 "%s - hexdump_ascii(len=%lu): [NULL]\n",
181 title, (unsigned long) len);
182 return;
183 }
184 fprintf(out_file, "%s - hexdump_ascii(len=%lu):\n",
185 title, (unsigned long) len);
186 while (len) {
187 llen = len > line_len ? line_len : len;
188 fprintf(out_file, " ");
189 for (i = 0; i < llen; i++)
190 fprintf(out_file, " %02x", pos[i]);
191 for (i = llen; i < line_len; i++)
192 fprintf(out_file, " ");
193 fprintf(out_file, " ");
194 for (i = 0; i < llen; i++) {
195 if (isprint(pos[i]))
196 fprintf(out_file, "%c", pos[i]);
197 else
198 fprintf(out_file, "_");
199 }
200 for (i = llen; i < line_len; i++)
201 fprintf(out_file, " ");
202 fprintf(out_file, "\n");
203 pos += llen;
204 len -= llen;
205 }
206 } else {
207 #endif /* CONFIG_DEBUG_FILE */
208 if (!show) {
209 printf("%s - hexdump_ascii(len=%lu): [REMOVED]\n",
210 title, (unsigned long) len);
211 return;
212 }
213 if (buf == NULL) {
214 printf("%s - hexdump_ascii(len=%lu): [NULL]\n",
215 title, (unsigned long) len);
216 return;
217 }
218 printf("%s - hexdump_ascii(len=%lu):\n", title, (unsigned long) len);
219 while (len) {
220 llen = len > line_len ? line_len : len;
221 printf(" ");
222 for (i = 0; i < llen; i++)
223 printf(" %02x", pos[i]);
224 for (i = llen; i < line_len; i++)
225 printf(" ");
226 printf(" ");
227 for (i = 0; i < llen; i++) {
228 if (isprint(pos[i]))
229 printf("%c", pos[i]);
230 else
231 printf("_");
232 }
233 for (i = llen; i < line_len; i++)
234 printf(" ");
235 printf("\n");
236 pos += llen;
237 len -= llen;
238 }
239 #ifdef CONFIG_DEBUG_FILE
240 }
241 #endif /* CONFIG_DEBUG_FILE */
242 }
243
244
wpa_hexdump_ascii(int level,const char * title,const u8 * buf,size_t len)245 void wpa_hexdump_ascii(int level, const char *title, const u8 *buf, size_t len)
246 {
247 _wpa_hexdump_ascii(level, title, buf, len, 1);
248 }
249
250
wpa_hexdump_ascii_key(int level,const char * title,const u8 * buf,size_t len)251 void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf,
252 size_t len)
253 {
254 _wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys);
255 }
256
257
wpa_debug_open_file(const char * path)258 int wpa_debug_open_file(const char *path)
259 {
260 #ifdef CONFIG_DEBUG_FILE
261 if (!path)
262 return 0;
263 out_file = fopen(path, "a");
264 if (out_file == NULL) {
265 wpa_printf(MSG_ERROR, "wpa_debug_open_file: Failed to open "
266 "output file, using standard output");
267 return -1;
268 }
269 #ifndef _WIN32
270 setvbuf(out_file, NULL, _IOLBF, 0);
271 #endif /* _WIN32 */
272 #endif /* CONFIG_DEBUG_FILE */
273 return 0;
274 }
275
276
wpa_debug_close_file(void)277 void wpa_debug_close_file(void)
278 {
279 #ifdef CONFIG_DEBUG_FILE
280 if (!out_file)
281 return;
282 fclose(out_file);
283 out_file = NULL;
284 #endif /* CONFIG_DEBUG_FILE */
285 }
286
287 #endif /* CONFIG_NO_STDOUT_DEBUG */
288
289 #endif /* CONFIG_ANDROID_LOG */
290
291 #ifndef CONFIG_NO_WPA_MSG
292 static wpa_msg_cb_func wpa_msg_cb = NULL;
293
wpa_msg_register_cb(wpa_msg_cb_func func)294 void wpa_msg_register_cb(wpa_msg_cb_func func)
295 {
296 wpa_msg_cb = func;
297 }
298
299
wpa_msg(void * ctx,int level,const char * fmt,...)300 void wpa_msg(void *ctx, int level, const char *fmt, ...)
301 {
302 va_list ap;
303 char *buf;
304 const int buflen = 2048;
305 int len;
306
307 buf = os_malloc(buflen);
308 if (buf == NULL) {
309 wpa_printf(MSG_ERROR, "wpa_msg: Failed to allocate message "
310 "buffer");
311 return;
312 }
313 va_start(ap, fmt);
314 len = vsnprintf(buf, buflen, fmt, ap);
315 va_end(ap);
316 wpa_printf(level, "%s", buf);
317 if (wpa_msg_cb)
318 wpa_msg_cb(ctx, level, buf, len);
319 os_free(buf);
320 }
321
322
wpa_msg_ctrl(void * ctx,int level,const char * fmt,...)323 void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...)
324 {
325 va_list ap;
326 char *buf;
327 const int buflen = 2048;
328 int len;
329
330 if (!wpa_msg_cb)
331 return;
332
333 buf = os_malloc(buflen);
334 if (buf == NULL) {
335 wpa_printf(MSG_ERROR, "wpa_msg_ctrl: Failed to allocate "
336 "message buffer");
337 return;
338 }
339 va_start(ap, fmt);
340 len = vsnprintf(buf, buflen, fmt, ap);
341 va_end(ap);
342 wpa_msg_cb(ctx, level, buf, len);
343 os_free(buf);
344 }
345 #endif /* CONFIG_NO_WPA_MSG */
346
347
348 #ifndef CONFIG_NO_HOSTAPD_LOGGER
349 static hostapd_logger_cb_func hostapd_logger_cb = NULL;
350
hostapd_logger_register_cb(hostapd_logger_cb_func func)351 void hostapd_logger_register_cb(hostapd_logger_cb_func func)
352 {
353 hostapd_logger_cb = func;
354 }
355
356
hostapd_logger(void * ctx,const u8 * addr,unsigned int module,int level,const char * fmt,...)357 void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level,
358 const char *fmt, ...)
359 {
360 va_list ap;
361 char *buf;
362 const int buflen = 2048;
363 int len;
364
365 buf = os_malloc(buflen);
366 if (buf == NULL) {
367 wpa_printf(MSG_ERROR, "hostapd_logger: Failed to allocate "
368 "message buffer");
369 return;
370 }
371 va_start(ap, fmt);
372 len = vsnprintf(buf, buflen, fmt, ap);
373 va_end(ap);
374 if (hostapd_logger_cb)
375 hostapd_logger_cb(ctx, addr, module, level, buf, len);
376 else
377 wpa_printf(MSG_DEBUG, "hostapd_logger: %s", buf);
378 os_free(buf);
379 }
380 #endif /* CONFIG_NO_HOSTAPD_LOGGER */
381