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