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