]>
Commit | Line | Data |
---|---|---|
6fc6879b JM |
1 | /* |
2 | * wpa_supplicant/hostapd / Debug prints | |
47bfe49c | 3 | * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi> |
6fc6879b | 4 | * |
0f3d578e JM |
5 | * This software may be distributed under the terms of the BSD license. |
6 | * See README for more details. | |
6fc6879b JM |
7 | */ |
8 | ||
9 | #include "includes.h" | |
10 | ||
11 | #include "common.h" | |
12 | ||
daa70d49 SL |
13 | #ifdef CONFIG_DEBUG_SYSLOG |
14 | #include <syslog.h> | |
15 | ||
cc3dae85 | 16 | int wpa_debug_syslog = 0; |
daa70d49 SL |
17 | #endif /* CONFIG_DEBUG_SYSLOG */ |
18 | ||
4f68895e JB |
19 | #ifdef CONFIG_DEBUG_LINUX_TRACING |
20 | #include <sys/types.h> | |
21 | #include <sys/stat.h> | |
22 | #include <fcntl.h> | |
23 | #include <string.h> | |
24 | #include <stdio.h> | |
25 | ||
26 | static FILE *wpa_debug_tracing_file = NULL; | |
27 | ||
28 | #define WPAS_TRACE_PFX "wpas <%d>: " | |
29 | #endif /* CONFIG_DEBUG_LINUX_TRACING */ | |
30 | ||
6fc6879b | 31 | |
6fc6879b JM |
32 | int wpa_debug_level = MSG_INFO; |
33 | int wpa_debug_show_keys = 0; | |
34 | int wpa_debug_timestamp = 0; | |
35 | ||
36 | ||
193f439a DS |
37 | #ifdef CONFIG_ANDROID_LOG |
38 | ||
39 | #include <android/log.h> | |
40 | ||
8f5b9aa1 DS |
41 | #ifndef ANDROID_LOG_NAME |
42 | #define ANDROID_LOG_NAME "wpa_supplicant" | |
43 | #endif /* ANDROID_LOG_NAME */ | |
44 | ||
4a0d25f0 | 45 | static int wpa_to_android_level(int level) |
193f439a | 46 | { |
4a0d25f0 JM |
47 | if (level == MSG_ERROR) |
48 | return ANDROID_LOG_ERROR; | |
49 | if (level == MSG_WARNING) | |
50 | return ANDROID_LOG_WARN; | |
51 | if (level == MSG_INFO) | |
52 | return ANDROID_LOG_INFO; | |
53 | return ANDROID_LOG_DEBUG; | |
193f439a DS |
54 | } |
55 | ||
4a0d25f0 | 56 | #endif /* CONFIG_ANDROID_LOG */ |
193f439a | 57 | |
6fc6879b JM |
58 | #ifndef CONFIG_NO_STDOUT_DEBUG |
59 | ||
50b16da1 | 60 | #ifdef CONFIG_DEBUG_FILE |
1737eb39 KB |
61 | #include <sys/types.h> |
62 | #include <sys/stat.h> | |
63 | #include <fcntl.h> | |
64 | ||
50b16da1 JM |
65 | static FILE *out_file = NULL; |
66 | #endif /* CONFIG_DEBUG_FILE */ | |
67 | ||
68 | ||
6fc6879b JM |
69 | void wpa_debug_print_timestamp(void) |
70 | { | |
4a0d25f0 | 71 | #ifndef CONFIG_ANDROID_LOG |
6fc6879b JM |
72 | struct os_time tv; |
73 | ||
74 | if (!wpa_debug_timestamp) | |
75 | return; | |
76 | ||
77 | os_get_time(&tv); | |
78 | #ifdef CONFIG_DEBUG_FILE | |
79 | if (out_file) { | |
80 | fprintf(out_file, "%ld.%06u: ", (long) tv.sec, | |
81 | (unsigned int) tv.usec); | |
82 | } else | |
83 | #endif /* CONFIG_DEBUG_FILE */ | |
84 | printf("%ld.%06u: ", (long) tv.sec, (unsigned int) tv.usec); | |
4a0d25f0 | 85 | #endif /* CONFIG_ANDROID_LOG */ |
6fc6879b JM |
86 | } |
87 | ||
88 | ||
daa70d49 | 89 | #ifdef CONFIG_DEBUG_SYSLOG |
3e199621 SL |
90 | #ifndef LOG_HOSTAPD |
91 | #define LOG_HOSTAPD LOG_DAEMON | |
92 | #endif /* LOG_HOSTAPD */ | |
93 | ||
daa70d49 SL |
94 | void wpa_debug_open_syslog(void) |
95 | { | |
3e199621 | 96 | openlog("wpa_supplicant", LOG_PID | LOG_NDELAY, LOG_HOSTAPD); |
daa70d49 SL |
97 | wpa_debug_syslog++; |
98 | } | |
99 | ||
100 | ||
101 | void wpa_debug_close_syslog(void) | |
102 | { | |
103 | if (wpa_debug_syslog) | |
104 | closelog(); | |
105 | } | |
106 | ||
107 | ||
108 | static int syslog_priority(int level) | |
109 | { | |
110 | switch (level) { | |
111 | case MSG_MSGDUMP: | |
112 | case MSG_DEBUG: | |
113 | return LOG_DEBUG; | |
114 | case MSG_INFO: | |
115 | return LOG_NOTICE; | |
116 | case MSG_WARNING: | |
117 | return LOG_WARNING; | |
118 | case MSG_ERROR: | |
119 | return LOG_ERR; | |
120 | } | |
121 | return LOG_INFO; | |
122 | } | |
123 | #endif /* CONFIG_DEBUG_SYSLOG */ | |
124 | ||
125 | ||
4f68895e JB |
126 | #ifdef CONFIG_DEBUG_LINUX_TRACING |
127 | ||
128 | int wpa_debug_open_linux_tracing(void) | |
129 | { | |
130 | int mounts, trace_fd; | |
131 | char buf[4096] = {}; | |
132 | ssize_t buflen; | |
133 | char *line, *tmp1, *path = NULL; | |
134 | ||
135 | mounts = open("/proc/mounts", O_RDONLY); | |
136 | if (mounts < 0) { | |
137 | printf("no /proc/mounts\n"); | |
138 | return -1; | |
139 | } | |
140 | ||
141 | buflen = read(mounts, buf, sizeof(buf) - 1); | |
142 | close(mounts); | |
143 | if (buflen < 0) { | |
144 | printf("failed to read /proc/mounts\n"); | |
145 | return -1; | |
146 | } | |
4eab3659 | 147 | buf[buflen] = '\0'; |
4f68895e JB |
148 | |
149 | line = strtok_r(buf, "\n", &tmp1); | |
150 | while (line) { | |
151 | char *tmp2, *tmp_path, *fstype; | |
152 | /* "<dev> <mountpoint> <fs type> ..." */ | |
153 | strtok_r(line, " ", &tmp2); | |
154 | tmp_path = strtok_r(NULL, " ", &tmp2); | |
155 | fstype = strtok_r(NULL, " ", &tmp2); | |
819ad5b7 | 156 | if (fstype && strcmp(fstype, "debugfs") == 0) { |
4f68895e JB |
157 | path = tmp_path; |
158 | break; | |
159 | } | |
160 | ||
161 | line = strtok_r(NULL, "\n", &tmp1); | |
162 | } | |
163 | ||
164 | if (path == NULL) { | |
165 | printf("debugfs mountpoint not found\n"); | |
166 | return -1; | |
167 | } | |
168 | ||
169 | snprintf(buf, sizeof(buf) - 1, "%s/tracing/trace_marker", path); | |
170 | ||
171 | trace_fd = open(buf, O_WRONLY); | |
172 | if (trace_fd < 0) { | |
173 | printf("failed to open trace_marker file\n"); | |
174 | return -1; | |
175 | } | |
176 | wpa_debug_tracing_file = fdopen(trace_fd, "w"); | |
177 | if (wpa_debug_tracing_file == NULL) { | |
178 | close(trace_fd); | |
179 | printf("failed to fdopen()\n"); | |
180 | return -1; | |
181 | } | |
182 | ||
183 | return 0; | |
184 | } | |
185 | ||
186 | ||
187 | void wpa_debug_close_linux_tracing(void) | |
188 | { | |
189 | if (wpa_debug_tracing_file == NULL) | |
190 | return; | |
191 | fclose(wpa_debug_tracing_file); | |
192 | wpa_debug_tracing_file = NULL; | |
193 | } | |
194 | ||
195 | #endif /* CONFIG_DEBUG_LINUX_TRACING */ | |
196 | ||
197 | ||
6fc6879b JM |
198 | /** |
199 | * wpa_printf - conditional printf | |
200 | * @level: priority level (MSG_*) of the message | |
201 | * @fmt: printf format string, followed by optional arguments | |
202 | * | |
203 | * This function is used to print conditional debugging and error messages. The | |
204 | * output may be directed to stdout, stderr, and/or syslog based on | |
205 | * configuration. | |
206 | * | |
207 | * Note: New line '\n' is added to the end of the text when printing to stdout. | |
208 | */ | |
0de4da91 | 209 | void wpa_printf(int level, const char *fmt, ...) |
6fc6879b JM |
210 | { |
211 | va_list ap; | |
212 | ||
213 | va_start(ap, fmt); | |
214 | if (level >= wpa_debug_level) { | |
4a0d25f0 JM |
215 | #ifdef CONFIG_ANDROID_LOG |
216 | __android_log_vprint(wpa_to_android_level(level), | |
217 | ANDROID_LOG_NAME, fmt, ap); | |
218 | #else /* CONFIG_ANDROID_LOG */ | |
daa70d49 SL |
219 | #ifdef CONFIG_DEBUG_SYSLOG |
220 | if (wpa_debug_syslog) { | |
221 | vsyslog(syslog_priority(level), fmt, ap); | |
222 | } else { | |
223 | #endif /* CONFIG_DEBUG_SYSLOG */ | |
6fc6879b JM |
224 | wpa_debug_print_timestamp(); |
225 | #ifdef CONFIG_DEBUG_FILE | |
226 | if (out_file) { | |
227 | vfprintf(out_file, fmt, ap); | |
228 | fprintf(out_file, "\n"); | |
229 | } else { | |
230 | #endif /* CONFIG_DEBUG_FILE */ | |
231 | vprintf(fmt, ap); | |
232 | printf("\n"); | |
233 | #ifdef CONFIG_DEBUG_FILE | |
234 | } | |
235 | #endif /* CONFIG_DEBUG_FILE */ | |
daa70d49 SL |
236 | #ifdef CONFIG_DEBUG_SYSLOG |
237 | } | |
238 | #endif /* CONFIG_DEBUG_SYSLOG */ | |
4a0d25f0 | 239 | #endif /* CONFIG_ANDROID_LOG */ |
6fc6879b JM |
240 | } |
241 | va_end(ap); | |
4f68895e JB |
242 | |
243 | #ifdef CONFIG_DEBUG_LINUX_TRACING | |
244 | if (wpa_debug_tracing_file != NULL) { | |
245 | va_start(ap, fmt); | |
246 | fprintf(wpa_debug_tracing_file, WPAS_TRACE_PFX, level); | |
247 | vfprintf(wpa_debug_tracing_file, fmt, ap); | |
248 | fprintf(wpa_debug_tracing_file, "\n"); | |
249 | fflush(wpa_debug_tracing_file); | |
250 | va_end(ap); | |
251 | } | |
252 | #endif /* CONFIG_DEBUG_LINUX_TRACING */ | |
6fc6879b JM |
253 | } |
254 | ||
255 | ||
256 | static void _wpa_hexdump(int level, const char *title, const u8 *buf, | |
257 | size_t len, int show) | |
258 | { | |
259 | size_t i; | |
4f68895e JB |
260 | |
261 | #ifdef CONFIG_DEBUG_LINUX_TRACING | |
262 | if (wpa_debug_tracing_file != NULL) { | |
263 | fprintf(wpa_debug_tracing_file, | |
264 | WPAS_TRACE_PFX "%s - hexdump(len=%lu):", | |
265 | level, title, (unsigned long) len); | |
266 | if (buf == NULL) { | |
267 | fprintf(wpa_debug_tracing_file, " [NULL]\n"); | |
268 | } else if (!show) { | |
269 | fprintf(wpa_debug_tracing_file, " [REMOVED]\n"); | |
270 | } else { | |
271 | for (i = 0; i < len; i++) | |
272 | fprintf(wpa_debug_tracing_file, | |
273 | " %02x", buf[i]); | |
274 | } | |
275 | fflush(wpa_debug_tracing_file); | |
276 | } | |
277 | #endif /* CONFIG_DEBUG_LINUX_TRACING */ | |
278 | ||
6fc6879b JM |
279 | if (level < wpa_debug_level) |
280 | return; | |
4a0d25f0 JM |
281 | #ifdef CONFIG_ANDROID_LOG |
282 | { | |
283 | const char *display; | |
284 | char *strbuf = NULL; | |
285 | size_t slen = len; | |
286 | if (buf == NULL) { | |
287 | display = " [NULL]"; | |
288 | } else if (len == 0) { | |
289 | display = ""; | |
290 | } else if (show && len) { | |
291 | /* Limit debug message length for Android log */ | |
292 | if (slen > 32) | |
293 | slen = 32; | |
294 | strbuf = os_malloc(1 + 3 * slen); | |
295 | if (strbuf == NULL) { | |
296 | wpa_printf(MSG_ERROR, "wpa_hexdump: Failed to " | |
297 | "allocate message buffer"); | |
298 | return; | |
299 | } | |
300 | ||
301 | for (i = 0; i < slen; i++) | |
302 | os_snprintf(&strbuf[i * 3], 4, " %02x", | |
303 | buf[i]); | |
304 | ||
305 | display = strbuf; | |
306 | } else { | |
307 | display = " [REMOVED]"; | |
308 | } | |
309 | ||
310 | __android_log_print(wpa_to_android_level(level), | |
311 | ANDROID_LOG_NAME, | |
312 | "%s - hexdump(len=%lu):%s%s", | |
313 | title, (long unsigned int) len, display, | |
314 | len > slen ? " ..." : ""); | |
b4c0f584 | 315 | bin_clear_free(strbuf, 1 + 3 * slen); |
4a0d25f0 JM |
316 | return; |
317 | } | |
318 | #else /* CONFIG_ANDROID_LOG */ | |
f31e19df NC |
319 | #ifdef CONFIG_DEBUG_SYSLOG |
320 | if (wpa_debug_syslog) { | |
321 | const char *display; | |
322 | char *strbuf = NULL; | |
323 | ||
324 | if (buf == NULL) { | |
325 | display = " [NULL]"; | |
326 | } else if (len == 0) { | |
327 | display = ""; | |
328 | } else if (show && len) { | |
329 | strbuf = os_malloc(1 + 3 * len); | |
330 | if (strbuf == NULL) { | |
331 | wpa_printf(MSG_ERROR, "wpa_hexdump: Failed to " | |
332 | "allocate message buffer"); | |
333 | return; | |
334 | } | |
335 | ||
336 | for (i = 0; i < len; i++) | |
337 | os_snprintf(&strbuf[i * 3], 4, " %02x", | |
338 | buf[i]); | |
339 | ||
340 | display = strbuf; | |
341 | } else { | |
342 | display = " [REMOVED]"; | |
343 | } | |
344 | ||
345 | syslog(syslog_priority(level), "%s - hexdump(len=%lu):%s", | |
e09e61c2 | 346 | title, (unsigned long) len, display); |
b4c0f584 | 347 | bin_clear_free(strbuf, 1 + 3 * len); |
f31e19df NC |
348 | return; |
349 | } | |
350 | #endif /* CONFIG_DEBUG_SYSLOG */ | |
6fc6879b JM |
351 | wpa_debug_print_timestamp(); |
352 | #ifdef CONFIG_DEBUG_FILE | |
353 | if (out_file) { | |
354 | fprintf(out_file, "%s - hexdump(len=%lu):", | |
355 | title, (unsigned long) len); | |
356 | if (buf == NULL) { | |
357 | fprintf(out_file, " [NULL]"); | |
358 | } else if (show) { | |
359 | for (i = 0; i < len; i++) | |
360 | fprintf(out_file, " %02x", buf[i]); | |
361 | } else { | |
362 | fprintf(out_file, " [REMOVED]"); | |
363 | } | |
364 | fprintf(out_file, "\n"); | |
365 | } else { | |
366 | #endif /* CONFIG_DEBUG_FILE */ | |
367 | printf("%s - hexdump(len=%lu):", title, (unsigned long) len); | |
368 | if (buf == NULL) { | |
369 | printf(" [NULL]"); | |
370 | } else if (show) { | |
371 | for (i = 0; i < len; i++) | |
372 | printf(" %02x", buf[i]); | |
373 | } else { | |
374 | printf(" [REMOVED]"); | |
375 | } | |
376 | printf("\n"); | |
377 | #ifdef CONFIG_DEBUG_FILE | |
378 | } | |
379 | #endif /* CONFIG_DEBUG_FILE */ | |
4a0d25f0 | 380 | #endif /* CONFIG_ANDROID_LOG */ |
6fc6879b JM |
381 | } |
382 | ||
35c20062 | 383 | void wpa_hexdump(int level, const char *title, const void *buf, size_t len) |
6fc6879b JM |
384 | { |
385 | _wpa_hexdump(level, title, buf, len, 1); | |
386 | } | |
387 | ||
388 | ||
35c20062 | 389 | void wpa_hexdump_key(int level, const char *title, const void *buf, size_t len) |
6fc6879b JM |
390 | { |
391 | _wpa_hexdump(level, title, buf, len, wpa_debug_show_keys); | |
392 | } | |
393 | ||
394 | ||
35c20062 | 395 | static void _wpa_hexdump_ascii(int level, const char *title, const void *buf, |
6fc6879b JM |
396 | size_t len, int show) |
397 | { | |
398 | size_t i, llen; | |
399 | const u8 *pos = buf; | |
400 | const size_t line_len = 16; | |
401 | ||
4f68895e JB |
402 | #ifdef CONFIG_DEBUG_LINUX_TRACING |
403 | if (wpa_debug_tracing_file != NULL) { | |
404 | fprintf(wpa_debug_tracing_file, | |
405 | WPAS_TRACE_PFX "%s - hexdump_ascii(len=%lu):", | |
406 | level, title, (unsigned long) len); | |
407 | if (buf == NULL) { | |
408 | fprintf(wpa_debug_tracing_file, " [NULL]\n"); | |
409 | } else if (!show) { | |
410 | fprintf(wpa_debug_tracing_file, " [REMOVED]\n"); | |
411 | } else { | |
412 | /* can do ascii processing in userspace */ | |
413 | for (i = 0; i < len; i++) | |
414 | fprintf(wpa_debug_tracing_file, | |
35c20062 | 415 | " %02x", pos[i]); |
4f68895e JB |
416 | } |
417 | fflush(wpa_debug_tracing_file); | |
418 | } | |
419 | #endif /* CONFIG_DEBUG_LINUX_TRACING */ | |
420 | ||
6fc6879b JM |
421 | if (level < wpa_debug_level) |
422 | return; | |
4a0d25f0 JM |
423 | #ifdef CONFIG_ANDROID_LOG |
424 | _wpa_hexdump(level, title, buf, len, show); | |
425 | #else /* CONFIG_ANDROID_LOG */ | |
e47c5227 AK |
426 | #ifdef CONFIG_DEBUG_SYSLOG |
427 | if (wpa_debug_syslog) { | |
428 | _wpa_hexdump(level, title, buf, len, show); | |
429 | return; | |
430 | } | |
431 | #endif /* CONFIG_DEBUG_SYSLOG */ | |
6fc6879b JM |
432 | wpa_debug_print_timestamp(); |
433 | #ifdef CONFIG_DEBUG_FILE | |
434 | if (out_file) { | |
435 | if (!show) { | |
436 | fprintf(out_file, | |
437 | "%s - hexdump_ascii(len=%lu): [REMOVED]\n", | |
438 | title, (unsigned long) len); | |
439 | return; | |
440 | } | |
441 | if (buf == NULL) { | |
442 | fprintf(out_file, | |
443 | "%s - hexdump_ascii(len=%lu): [NULL]\n", | |
444 | title, (unsigned long) len); | |
445 | return; | |
446 | } | |
447 | fprintf(out_file, "%s - hexdump_ascii(len=%lu):\n", | |
448 | title, (unsigned long) len); | |
449 | while (len) { | |
450 | llen = len > line_len ? line_len : len; | |
451 | fprintf(out_file, " "); | |
452 | for (i = 0; i < llen; i++) | |
453 | fprintf(out_file, " %02x", pos[i]); | |
454 | for (i = llen; i < line_len; i++) | |
455 | fprintf(out_file, " "); | |
456 | fprintf(out_file, " "); | |
457 | for (i = 0; i < llen; i++) { | |
458 | if (isprint(pos[i])) | |
459 | fprintf(out_file, "%c", pos[i]); | |
460 | else | |
461 | fprintf(out_file, "_"); | |
462 | } | |
463 | for (i = llen; i < line_len; i++) | |
464 | fprintf(out_file, " "); | |
465 | fprintf(out_file, "\n"); | |
466 | pos += llen; | |
467 | len -= llen; | |
468 | } | |
469 | } else { | |
470 | #endif /* CONFIG_DEBUG_FILE */ | |
471 | if (!show) { | |
472 | printf("%s - hexdump_ascii(len=%lu): [REMOVED]\n", | |
473 | title, (unsigned long) len); | |
474 | return; | |
475 | } | |
476 | if (buf == NULL) { | |
477 | printf("%s - hexdump_ascii(len=%lu): [NULL]\n", | |
478 | title, (unsigned long) len); | |
479 | return; | |
480 | } | |
481 | printf("%s - hexdump_ascii(len=%lu):\n", title, (unsigned long) len); | |
482 | while (len) { | |
483 | llen = len > line_len ? line_len : len; | |
484 | printf(" "); | |
485 | for (i = 0; i < llen; i++) | |
486 | printf(" %02x", pos[i]); | |
487 | for (i = llen; i < line_len; i++) | |
488 | printf(" "); | |
489 | printf(" "); | |
490 | for (i = 0; i < llen; i++) { | |
491 | if (isprint(pos[i])) | |
492 | printf("%c", pos[i]); | |
493 | else | |
494 | printf("_"); | |
495 | } | |
496 | for (i = llen; i < line_len; i++) | |
497 | printf(" "); | |
498 | printf("\n"); | |
499 | pos += llen; | |
500 | len -= llen; | |
501 | } | |
502 | #ifdef CONFIG_DEBUG_FILE | |
503 | } | |
504 | #endif /* CONFIG_DEBUG_FILE */ | |
4a0d25f0 | 505 | #endif /* CONFIG_ANDROID_LOG */ |
6fc6879b JM |
506 | } |
507 | ||
508 | ||
35c20062 JM |
509 | void wpa_hexdump_ascii(int level, const char *title, const void *buf, |
510 | size_t len) | |
6fc6879b JM |
511 | { |
512 | _wpa_hexdump_ascii(level, title, buf, len, 1); | |
513 | } | |
514 | ||
515 | ||
35c20062 | 516 | void wpa_hexdump_ascii_key(int level, const char *title, const void *buf, |
6fc6879b JM |
517 | size_t len) |
518 | { | |
519 | _wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys); | |
520 | } | |
521 | ||
522 | ||
ac6912b5 BG |
523 | #ifdef CONFIG_DEBUG_FILE |
524 | static char *last_path = NULL; | |
525 | #endif /* CONFIG_DEBUG_FILE */ | |
526 | ||
527 | int wpa_debug_reopen_file(void) | |
528 | { | |
529 | #ifdef CONFIG_DEBUG_FILE | |
530 | int rv; | |
d8fd633e JM |
531 | char *tmp; |
532 | ||
533 | if (!last_path) | |
534 | return 0; /* logfile not used */ | |
535 | ||
536 | tmp = os_strdup(last_path); | |
537 | if (!tmp) | |
538 | return -1; | |
539 | ||
540 | wpa_debug_close_file(); | |
541 | rv = wpa_debug_open_file(tmp); | |
542 | os_free(tmp); | |
ac6912b5 BG |
543 | return rv; |
544 | #else /* CONFIG_DEBUG_FILE */ | |
545 | return 0; | |
546 | #endif /* CONFIG_DEBUG_FILE */ | |
547 | } | |
548 | ||
549 | ||
6fc6879b JM |
550 | int wpa_debug_open_file(const char *path) |
551 | { | |
552 | #ifdef CONFIG_DEBUG_FILE | |
1737eb39 KB |
553 | int out_fd; |
554 | ||
6fc6879b JM |
555 | if (!path) |
556 | return 0; | |
ac6912b5 BG |
557 | |
558 | if (last_path == NULL || os_strcmp(last_path, path) != 0) { | |
559 | /* Save our path to enable re-open */ | |
560 | os_free(last_path); | |
561 | last_path = os_strdup(path); | |
562 | } | |
563 | ||
1737eb39 KB |
564 | out_fd = open(path, O_CREAT | O_APPEND | O_WRONLY, |
565 | S_IRUSR | S_IWUSR | S_IRGRP); | |
566 | if (out_fd < 0) { | |
567 | wpa_printf(MSG_ERROR, | |
568 | "%s: Failed to open output file descriptor, using standard output", | |
569 | __func__); | |
570 | return -1; | |
571 | } | |
572 | ||
ac1f5915 KB |
573 | #ifdef __linux__ |
574 | if (fcntl(out_fd, F_SETFD, FD_CLOEXEC) < 0) { | |
575 | wpa_printf(MSG_DEBUG, | |
576 | "%s: Failed to set FD_CLOEXEC - continue without: %s", | |
577 | __func__, strerror(errno)); | |
578 | } | |
579 | #endif /* __linux__ */ | |
580 | ||
1737eb39 | 581 | out_file = fdopen(out_fd, "a"); |
6fc6879b JM |
582 | if (out_file == NULL) { |
583 | wpa_printf(MSG_ERROR, "wpa_debug_open_file: Failed to open " | |
584 | "output file, using standard output"); | |
1737eb39 | 585 | close(out_fd); |
6fc6879b JM |
586 | return -1; |
587 | } | |
588 | #ifndef _WIN32 | |
589 | setvbuf(out_file, NULL, _IOLBF, 0); | |
590 | #endif /* _WIN32 */ | |
f5c649b7 TG |
591 | #else /* CONFIG_DEBUG_FILE */ |
592 | (void)path; | |
6fc6879b JM |
593 | #endif /* CONFIG_DEBUG_FILE */ |
594 | return 0; | |
595 | } | |
596 | ||
597 | ||
598 | void wpa_debug_close_file(void) | |
599 | { | |
600 | #ifdef CONFIG_DEBUG_FILE | |
601 | if (!out_file) | |
602 | return; | |
603 | fclose(out_file); | |
604 | out_file = NULL; | |
ac6912b5 BG |
605 | os_free(last_path); |
606 | last_path = NULL; | |
6fc6879b JM |
607 | #endif /* CONFIG_DEBUG_FILE */ |
608 | } | |
609 | ||
de27bc76 PS |
610 | |
611 | void wpa_debug_setup_stdout(void) | |
612 | { | |
613 | #ifndef _WIN32 | |
614 | setvbuf(stdout, NULL, _IOLBF, 0); | |
615 | #endif /* _WIN32 */ | |
616 | } | |
617 | ||
6fc6879b JM |
618 | #endif /* CONFIG_NO_STDOUT_DEBUG */ |
619 | ||
620 | ||
621 | #ifndef CONFIG_NO_WPA_MSG | |
622 | static wpa_msg_cb_func wpa_msg_cb = NULL; | |
623 | ||
624 | void wpa_msg_register_cb(wpa_msg_cb_func func) | |
625 | { | |
626 | wpa_msg_cb = func; | |
627 | } | |
628 | ||
629 | ||
4f1495ae BG |
630 | static wpa_msg_get_ifname_func wpa_msg_ifname_cb = NULL; |
631 | ||
632 | void wpa_msg_register_ifname_cb(wpa_msg_get_ifname_func func) | |
633 | { | |
634 | wpa_msg_ifname_cb = func; | |
635 | } | |
636 | ||
637 | ||
0de4da91 | 638 | void wpa_msg(void *ctx, int level, const char *fmt, ...) |
6fc6879b JM |
639 | { |
640 | va_list ap; | |
641 | char *buf; | |
9e388364 | 642 | int buflen; |
6fc6879b | 643 | int len; |
4f1495ae | 644 | char prefix[130]; |
6fc6879b | 645 | |
9e388364 AK |
646 | va_start(ap, fmt); |
647 | buflen = vsnprintf(NULL, 0, fmt, ap) + 1; | |
648 | va_end(ap); | |
649 | ||
6fc6879b JM |
650 | buf = os_malloc(buflen); |
651 | if (buf == NULL) { | |
652 | wpa_printf(MSG_ERROR, "wpa_msg: Failed to allocate message " | |
653 | "buffer"); | |
654 | return; | |
655 | } | |
656 | va_start(ap, fmt); | |
4f1495ae BG |
657 | prefix[0] = '\0'; |
658 | if (wpa_msg_ifname_cb) { | |
659 | const char *ifname = wpa_msg_ifname_cb(ctx); | |
660 | if (ifname) { | |
661 | int res = os_snprintf(prefix, sizeof(prefix), "%s: ", | |
662 | ifname); | |
d85e1fc8 | 663 | if (os_snprintf_error(sizeof(prefix), res)) |
4f1495ae BG |
664 | prefix[0] = '\0'; |
665 | } | |
666 | } | |
6fc6879b JM |
667 | len = vsnprintf(buf, buflen, fmt, ap); |
668 | va_end(ap); | |
4f1495ae | 669 | wpa_printf(level, "%s%s", prefix, buf); |
6fc6879b | 670 | if (wpa_msg_cb) |
995a3a06 | 671 | wpa_msg_cb(ctx, level, WPA_MSG_PER_INTERFACE, buf, len); |
b4c0f584 | 672 | bin_clear_free(buf, buflen); |
6fc6879b | 673 | } |
69856fad JM |
674 | |
675 | ||
0de4da91 | 676 | void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...) |
69856fad JM |
677 | { |
678 | va_list ap; | |
679 | char *buf; | |
9e388364 | 680 | int buflen; |
69856fad JM |
681 | int len; |
682 | ||
683 | if (!wpa_msg_cb) | |
684 | return; | |
685 | ||
9e388364 AK |
686 | va_start(ap, fmt); |
687 | buflen = vsnprintf(NULL, 0, fmt, ap) + 1; | |
688 | va_end(ap); | |
689 | ||
69856fad JM |
690 | buf = os_malloc(buflen); |
691 | if (buf == NULL) { | |
692 | wpa_printf(MSG_ERROR, "wpa_msg_ctrl: Failed to allocate " | |
693 | "message buffer"); | |
694 | return; | |
695 | } | |
696 | va_start(ap, fmt); | |
697 | len = vsnprintf(buf, buflen, fmt, ap); | |
698 | va_end(ap); | |
995a3a06 | 699 | wpa_msg_cb(ctx, level, WPA_MSG_PER_INTERFACE, buf, len); |
b4c0f584 | 700 | bin_clear_free(buf, buflen); |
69856fad | 701 | } |
47bfe49c JM |
702 | |
703 | ||
704 | void wpa_msg_global(void *ctx, int level, const char *fmt, ...) | |
705 | { | |
706 | va_list ap; | |
707 | char *buf; | |
9e388364 | 708 | int buflen; |
47bfe49c JM |
709 | int len; |
710 | ||
9e388364 AK |
711 | va_start(ap, fmt); |
712 | buflen = vsnprintf(NULL, 0, fmt, ap) + 1; | |
713 | va_end(ap); | |
714 | ||
47bfe49c JM |
715 | buf = os_malloc(buflen); |
716 | if (buf == NULL) { | |
717 | wpa_printf(MSG_ERROR, "wpa_msg_global: Failed to allocate " | |
718 | "message buffer"); | |
719 | return; | |
720 | } | |
721 | va_start(ap, fmt); | |
722 | len = vsnprintf(buf, buflen, fmt, ap); | |
723 | va_end(ap); | |
724 | wpa_printf(level, "%s", buf); | |
725 | if (wpa_msg_cb) | |
995a3a06 | 726 | wpa_msg_cb(ctx, level, WPA_MSG_GLOBAL, buf, len); |
b4c0f584 | 727 | bin_clear_free(buf, buflen); |
47bfe49c JM |
728 | } |
729 | ||
c4bf83a7 | 730 | |
905c7223 JM |
731 | void wpa_msg_global_ctrl(void *ctx, int level, const char *fmt, ...) |
732 | { | |
733 | va_list ap; | |
734 | char *buf; | |
735 | int buflen; | |
736 | int len; | |
737 | ||
738 | if (!wpa_msg_cb) | |
739 | return; | |
740 | ||
741 | va_start(ap, fmt); | |
742 | buflen = vsnprintf(NULL, 0, fmt, ap) + 1; | |
743 | va_end(ap); | |
744 | ||
745 | buf = os_malloc(buflen); | |
746 | if (buf == NULL) { | |
747 | wpa_printf(MSG_ERROR, | |
748 | "wpa_msg_global_ctrl: Failed to allocate message buffer"); | |
749 | return; | |
750 | } | |
751 | va_start(ap, fmt); | |
752 | len = vsnprintf(buf, buflen, fmt, ap); | |
753 | va_end(ap); | |
995a3a06 | 754 | wpa_msg_cb(ctx, level, WPA_MSG_GLOBAL, buf, len); |
b4c0f584 | 755 | bin_clear_free(buf, buflen); |
905c7223 JM |
756 | } |
757 | ||
758 | ||
c4bf83a7 JM |
759 | void wpa_msg_no_global(void *ctx, int level, const char *fmt, ...) |
760 | { | |
761 | va_list ap; | |
762 | char *buf; | |
9e388364 | 763 | int buflen; |
c4bf83a7 JM |
764 | int len; |
765 | ||
9e388364 AK |
766 | va_start(ap, fmt); |
767 | buflen = vsnprintf(NULL, 0, fmt, ap) + 1; | |
768 | va_end(ap); | |
769 | ||
c4bf83a7 JM |
770 | buf = os_malloc(buflen); |
771 | if (buf == NULL) { | |
772 | wpa_printf(MSG_ERROR, "wpa_msg_no_global: Failed to allocate " | |
773 | "message buffer"); | |
774 | return; | |
775 | } | |
776 | va_start(ap, fmt); | |
777 | len = vsnprintf(buf, buflen, fmt, ap); | |
778 | va_end(ap); | |
779 | wpa_printf(level, "%s", buf); | |
780 | if (wpa_msg_cb) | |
995a3a06 | 781 | wpa_msg_cb(ctx, level, WPA_MSG_NO_GLOBAL, buf, len); |
b4c0f584 | 782 | bin_clear_free(buf, buflen); |
c4bf83a7 JM |
783 | } |
784 | ||
ee1e3f57 AN |
785 | |
786 | void wpa_msg_global_only(void *ctx, int level, const char *fmt, ...) | |
787 | { | |
788 | va_list ap; | |
789 | char *buf; | |
790 | int buflen; | |
791 | int len; | |
792 | ||
793 | va_start(ap, fmt); | |
794 | buflen = vsnprintf(NULL, 0, fmt, ap) + 1; | |
795 | va_end(ap); | |
796 | ||
797 | buf = os_malloc(buflen); | |
798 | if (buf == NULL) { | |
799 | wpa_printf(MSG_ERROR, "%s: Failed to allocate message buffer", | |
800 | __func__); | |
801 | return; | |
802 | } | |
803 | va_start(ap, fmt); | |
804 | len = vsnprintf(buf, buflen, fmt, ap); | |
805 | va_end(ap); | |
806 | wpa_printf(level, "%s", buf); | |
807 | if (wpa_msg_cb) | |
808 | wpa_msg_cb(ctx, level, WPA_MSG_ONLY_GLOBAL, buf, len); | |
809 | os_free(buf); | |
810 | } | |
811 | ||
6fc6879b JM |
812 | #endif /* CONFIG_NO_WPA_MSG */ |
813 | ||
814 | ||
815 | #ifndef CONFIG_NO_HOSTAPD_LOGGER | |
816 | static hostapd_logger_cb_func hostapd_logger_cb = NULL; | |
817 | ||
818 | void hostapd_logger_register_cb(hostapd_logger_cb_func func) | |
819 | { | |
820 | hostapd_logger_cb = func; | |
821 | } | |
822 | ||
823 | ||
824 | void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level, | |
825 | const char *fmt, ...) | |
826 | { | |
827 | va_list ap; | |
828 | char *buf; | |
9e388364 | 829 | int buflen; |
6fc6879b JM |
830 | int len; |
831 | ||
9e388364 AK |
832 | va_start(ap, fmt); |
833 | buflen = vsnprintf(NULL, 0, fmt, ap) + 1; | |
834 | va_end(ap); | |
835 | ||
6fc6879b JM |
836 | buf = os_malloc(buflen); |
837 | if (buf == NULL) { | |
838 | wpa_printf(MSG_ERROR, "hostapd_logger: Failed to allocate " | |
839 | "message buffer"); | |
840 | return; | |
841 | } | |
842 | va_start(ap, fmt); | |
843 | len = vsnprintf(buf, buflen, fmt, ap); | |
844 | va_end(ap); | |
845 | if (hostapd_logger_cb) | |
846 | hostapd_logger_cb(ctx, addr, module, level, buf, len); | |
ade07077 JM |
847 | else if (addr) |
848 | wpa_printf(MSG_DEBUG, "hostapd_logger: STA " MACSTR " - %s", | |
849 | MAC2STR(addr), buf); | |
6fc6879b JM |
850 | else |
851 | wpa_printf(MSG_DEBUG, "hostapd_logger: %s", buf); | |
b4c0f584 | 852 | bin_clear_free(buf, buflen); |
6fc6879b JM |
853 | } |
854 | #endif /* CONFIG_NO_HOSTAPD_LOGGER */ | |
ab62f96f JM |
855 | |
856 | ||
857 | const char * debug_level_str(int level) | |
858 | { | |
859 | switch (level) { | |
860 | case MSG_EXCESSIVE: | |
861 | return "EXCESSIVE"; | |
862 | case MSG_MSGDUMP: | |
863 | return "MSGDUMP"; | |
864 | case MSG_DEBUG: | |
865 | return "DEBUG"; | |
866 | case MSG_INFO: | |
867 | return "INFO"; | |
868 | case MSG_WARNING: | |
869 | return "WARNING"; | |
870 | case MSG_ERROR: | |
871 | return "ERROR"; | |
872 | default: | |
873 | return "?"; | |
874 | } | |
875 | } | |
876 | ||
877 | ||
878 | int str_to_debug_level(const char *s) | |
879 | { | |
880 | if (os_strcasecmp(s, "EXCESSIVE") == 0) | |
881 | return MSG_EXCESSIVE; | |
882 | if (os_strcasecmp(s, "MSGDUMP") == 0) | |
883 | return MSG_MSGDUMP; | |
884 | if (os_strcasecmp(s, "DEBUG") == 0) | |
885 | return MSG_DEBUG; | |
886 | if (os_strcasecmp(s, "INFO") == 0) | |
887 | return MSG_INFO; | |
888 | if (os_strcasecmp(s, "WARNING") == 0) | |
889 | return MSG_WARNING; | |
890 | if (os_strcasecmp(s, "ERROR") == 0) | |
891 | return MSG_ERROR; | |
892 | return -1; | |
893 | } |