Home | History | Annotate | Line # | Download | only in utils
      1 /*
      2  * wpa_supplicant/hostapd / Debug prints
      3  * Copyright (c) 2002-2013, Jouni Malinen <j (at) 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 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 	buf[buflen] = '\0';
    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);
    156 		if (fstype && strcmp(fstype, "debugfs") == 0) {
    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 
    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  */
    209 void wpa_printf(int level, const char *fmt, ...)
    210 {
    211 	va_list ap;
    212 
    213 	if (level >= wpa_debug_level) {
    214 #ifdef CONFIG_ANDROID_LOG
    215 		va_start(ap, fmt);
    216 		__android_log_vprint(wpa_to_android_level(level),
    217 				     ANDROID_LOG_NAME, fmt, ap);
    218 		va_end(ap);
    219 #else /* CONFIG_ANDROID_LOG */
    220 #ifdef CONFIG_DEBUG_SYSLOG
    221 		if (wpa_debug_syslog) {
    222 			va_start(ap, fmt);
    223 			vsyslog(syslog_priority(level), fmt, ap);
    224 			va_end(ap);
    225 		}
    226 #endif /* CONFIG_DEBUG_SYSLOG */
    227 		wpa_debug_print_timestamp();
    228 #ifdef CONFIG_DEBUG_FILE
    229 		if (out_file) {
    230 			va_start(ap, fmt);
    231 			vfprintf(out_file, fmt, ap);
    232 			fprintf(out_file, "\n");
    233 			va_end(ap);
    234 		}
    235 #endif /* CONFIG_DEBUG_FILE */
    236 		if (!wpa_debug_syslog && !out_file) {
    237 			va_start(ap, fmt);
    238 			vprintf(fmt, ap);
    239 			printf("\n");
    240 			va_end(ap);
    241 		}
    242 #endif /* CONFIG_ANDROID_LOG */
    243 	}
    244 
    245 #ifdef CONFIG_DEBUG_LINUX_TRACING
    246 	if (wpa_debug_tracing_file != NULL) {
    247 		va_start(ap, fmt);
    248 		fprintf(wpa_debug_tracing_file, WPAS_TRACE_PFX, level);
    249 		vfprintf(wpa_debug_tracing_file, fmt, ap);
    250 		fprintf(wpa_debug_tracing_file, "\n");
    251 		fflush(wpa_debug_tracing_file);
    252 		va_end(ap);
    253 	}
    254 #endif /* CONFIG_DEBUG_LINUX_TRACING */
    255 }
    256 
    257 
    258 static void _wpa_hexdump(int level, const char *title, const u8 *buf,
    259 			 size_t len, int show, int only_syslog)
    260 {
    261 	size_t i;
    262 
    263 #ifdef CONFIG_DEBUG_LINUX_TRACING
    264 	if (wpa_debug_tracing_file != NULL) {
    265 		fprintf(wpa_debug_tracing_file,
    266 			WPAS_TRACE_PFX "%s - hexdump(len=%lu):",
    267 			level, title, (unsigned long) len);
    268 		if (buf == NULL) {
    269 			fprintf(wpa_debug_tracing_file, " [NULL]\n");
    270 		} else if (!show) {
    271 			fprintf(wpa_debug_tracing_file, " [REMOVED]\n");
    272 		} else {
    273 			for (i = 0; i < len; i++)
    274 				fprintf(wpa_debug_tracing_file,
    275 					" %02x", buf[i]);
    276 		}
    277 		fflush(wpa_debug_tracing_file);
    278 	}
    279 #endif /* CONFIG_DEBUG_LINUX_TRACING */
    280 
    281 	if (level < wpa_debug_level)
    282 		return;
    283 #ifdef CONFIG_ANDROID_LOG
    284 	{
    285 		const char *display;
    286 		char *strbuf = NULL;
    287 		size_t slen = len;
    288 		if (buf == NULL) {
    289 			display = " [NULL]";
    290 		} else if (len == 0) {
    291 			display = "";
    292 		} else if (show && len) {
    293 			/* Limit debug message length for Android log */
    294 			if (slen > 32)
    295 				slen = 32;
    296 			strbuf = os_malloc(1 + 3 * slen);
    297 			if (strbuf == NULL) {
    298 				wpa_printf(MSG_ERROR, "wpa_hexdump: Failed to "
    299 					   "allocate message buffer");
    300 				return;
    301 			}
    302 
    303 			for (i = 0; i < slen; i++)
    304 				os_snprintf(&strbuf[i * 3], 4, " %02x",
    305 					    buf[i]);
    306 
    307 			display = strbuf;
    308 		} else {
    309 			display = " [REMOVED]";
    310 		}
    311 
    312 		__android_log_print(wpa_to_android_level(level),
    313 				    ANDROID_LOG_NAME,
    314 				    "%s - hexdump(len=%lu):%s%s",
    315 				    title, (long unsigned int) len, display,
    316 				    len > slen ? " ..." : "");
    317 		bin_clear_free(strbuf, 1 + 3 * slen);
    318 		return;
    319 	}
    320 #else /* CONFIG_ANDROID_LOG */
    321 #ifdef CONFIG_DEBUG_SYSLOG
    322 	if (wpa_debug_syslog) {
    323 		const char *display;
    324 		char *strbuf = NULL;
    325 
    326 		if (buf == NULL) {
    327 			display = " [NULL]";
    328 		} else if (len == 0) {
    329 			display = "";
    330 		} else if (show && len) {
    331 			strbuf = os_malloc(1 + 3 * len);
    332 			if (strbuf == NULL) {
    333 				wpa_printf(MSG_ERROR, "wpa_hexdump: Failed to "
    334 					   "allocate message buffer");
    335 				return;
    336 			}
    337 
    338 			for (i = 0; i < len; i++)
    339 				os_snprintf(&strbuf[i * 3], 4, " %02x",
    340 					    buf[i]);
    341 
    342 			display = strbuf;
    343 		} else {
    344 			display = " [REMOVED]";
    345 		}
    346 
    347 		syslog(syslog_priority(level), "%s - hexdump(len=%lu):%s",
    348 		       title, (unsigned long) len, display);
    349 		bin_clear_free(strbuf, 1 + 3 * len);
    350 		if (only_syslog)
    351 			return;
    352 	}
    353 #endif /* CONFIG_DEBUG_SYSLOG */
    354 	wpa_debug_print_timestamp();
    355 #ifdef CONFIG_DEBUG_FILE
    356 	if (out_file) {
    357 		fprintf(out_file, "%s - hexdump(len=%lu):",
    358 			title, (unsigned long) len);
    359 		if (buf == NULL) {
    360 			fprintf(out_file, " [NULL]");
    361 		} else if (show) {
    362 			for (i = 0; i < len; i++)
    363 				fprintf(out_file, " %02x", buf[i]);
    364 		} else {
    365 			fprintf(out_file, " [REMOVED]");
    366 		}
    367 		fprintf(out_file, "\n");
    368 	}
    369 #endif /* CONFIG_DEBUG_FILE */
    370 	if (!wpa_debug_syslog && !out_file) {
    371 		printf("%s - hexdump(len=%lu):", title, (unsigned long) len);
    372 		if (buf == NULL) {
    373 			printf(" [NULL]");
    374 		} else if (show) {
    375 			for (i = 0; i < len; i++)
    376 				printf(" %02x", buf[i]);
    377 		} else {
    378 			printf(" [REMOVED]");
    379 		}
    380 		printf("\n");
    381 	}
    382 #endif /* CONFIG_ANDROID_LOG */
    383 }
    384 
    385 void wpa_hexdump(int level, const char *title, const void *buf, size_t len)
    386 {
    387 	_wpa_hexdump(level, title, buf, len, 1, 0);
    388 }
    389 
    390 
    391 void wpa_hexdump_key(int level, const char *title, const void *buf, size_t len)
    392 {
    393 	_wpa_hexdump(level, title, buf, len, wpa_debug_show_keys, 0);
    394 }
    395 
    396 
    397 static void _wpa_hexdump_ascii(int level, const char *title, const void *buf,
    398 			       size_t len, int show)
    399 {
    400 	size_t i, llen;
    401 	const u8 *pos = buf;
    402 	const size_t line_len = 16;
    403 
    404 #ifdef CONFIG_DEBUG_LINUX_TRACING
    405 	if (wpa_debug_tracing_file != NULL) {
    406 		fprintf(wpa_debug_tracing_file,
    407 			WPAS_TRACE_PFX "%s - hexdump_ascii(len=%lu):",
    408 			level, title, (unsigned long) len);
    409 		if (buf == NULL) {
    410 			fprintf(wpa_debug_tracing_file, " [NULL]\n");
    411 		} else if (!show) {
    412 			fprintf(wpa_debug_tracing_file, " [REMOVED]\n");
    413 		} else {
    414 			/* can do ascii processing in userspace */
    415 			for (i = 0; i < len; i++)
    416 				fprintf(wpa_debug_tracing_file,
    417 					" %02x", pos[i]);
    418 		}
    419 		fflush(wpa_debug_tracing_file);
    420 	}
    421 #endif /* CONFIG_DEBUG_LINUX_TRACING */
    422 
    423 	if (level < wpa_debug_level)
    424 		return;
    425 #ifdef CONFIG_ANDROID_LOG
    426 	_wpa_hexdump(level, title, buf, len, show, 0);
    427 #else /* CONFIG_ANDROID_LOG */
    428 #ifdef CONFIG_DEBUG_SYSLOG
    429 	if (wpa_debug_syslog)
    430 		_wpa_hexdump(level, title, buf, len, show, 1);
    431 #endif /* CONFIG_DEBUG_SYSLOG */
    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 			goto file_done;
    440 		}
    441 		if (buf == NULL) {
    442 			fprintf(out_file,
    443 				"%s - hexdump_ascii(len=%lu): [NULL]\n",
    444 				title, (unsigned long) len);
    445 			goto file_done;
    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 	}
    470 file_done:
    471 #endif /* CONFIG_DEBUG_FILE */
    472 	if (!wpa_debug_syslog && !out_file) {
    473 		if (!show) {
    474 			printf("%s - hexdump_ascii(len=%lu): [REMOVED]\n",
    475 			       title, (unsigned long) len);
    476 			return;
    477 		}
    478 		if (buf == NULL) {
    479 			printf("%s - hexdump_ascii(len=%lu): [NULL]\n",
    480 			       title, (unsigned long) len);
    481 			return;
    482 		}
    483 		printf("%s - hexdump_ascii(len=%lu):\n", title,
    484 		       (unsigned long) len);
    485 		while (len) {
    486 			llen = len > line_len ? line_len : len;
    487 			printf("    ");
    488 			for (i = 0; i < llen; i++)
    489 				printf(" %02x", pos[i]);
    490 			for (i = llen; i < line_len; i++)
    491 				printf("   ");
    492 			printf("   ");
    493 			for (i = 0; i < llen; i++) {
    494 				if (isprint(pos[i]))
    495 					printf("%c", pos[i]);
    496 				else
    497 					printf("_");
    498 			}
    499 			for (i = llen; i < line_len; i++)
    500 				printf(" ");
    501 			printf("\n");
    502 			pos += llen;
    503 			len -= llen;
    504 		}
    505 	}
    506 #endif /* CONFIG_ANDROID_LOG */
    507 }
    508 
    509 
    510 void wpa_hexdump_ascii(int level, const char *title, const void *buf,
    511 		       size_t len)
    512 {
    513 	_wpa_hexdump_ascii(level, title, buf, len, 1);
    514 }
    515 
    516 
    517 void wpa_hexdump_ascii_key(int level, const char *title, const void *buf,
    518 			   size_t len)
    519 {
    520 	_wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys);
    521 }
    522 
    523 
    524 #ifdef CONFIG_DEBUG_FILE
    525 static char *last_path = NULL;
    526 #endif /* CONFIG_DEBUG_FILE */
    527 
    528 int wpa_debug_reopen_file(void)
    529 {
    530 #ifdef CONFIG_DEBUG_FILE
    531 	int rv;
    532 	char *tmp;
    533 
    534 	if (!last_path)
    535 		return 0; /* logfile not used */
    536 
    537 	tmp = os_strdup(last_path);
    538 	if (!tmp)
    539 		return -1;
    540 
    541 	wpa_debug_close_file();
    542 	rv = wpa_debug_open_file(tmp);
    543 	os_free(tmp);
    544 	return rv;
    545 #else /* CONFIG_DEBUG_FILE */
    546 	return 0;
    547 #endif /* CONFIG_DEBUG_FILE */
    548 }
    549 
    550 
    551 int wpa_debug_open_file(const char *path)
    552 {
    553 #ifdef CONFIG_DEBUG_FILE
    554 	int out_fd;
    555 
    556 	if (!path)
    557 		return 0;
    558 
    559 	if (last_path == NULL || os_strcmp(last_path, path) != 0) {
    560 		/* Save our path to enable re-open */
    561 		os_free(last_path);
    562 		last_path = os_strdup(path);
    563 	}
    564 
    565 	out_fd = open(path, O_CREAT | O_APPEND | O_WRONLY,
    566 		      S_IRUSR | S_IWUSR | S_IRGRP);
    567 	if (out_fd < 0) {
    568 		wpa_printf(MSG_ERROR,
    569 			   "%s: Failed to open output file descriptor, using standard output",
    570 			   __func__);
    571 		return -1;
    572 	}
    573 
    574 #ifdef __linux__
    575 	if (fcntl(out_fd, F_SETFD, FD_CLOEXEC) < 0) {
    576 		wpa_printf(MSG_DEBUG,
    577 			   "%s: Failed to set FD_CLOEXEC - continue without: %s",
    578 			   __func__, strerror(errno));
    579 	}
    580 #endif /* __linux__ */
    581 
    582 	out_file = fdopen(out_fd, "a");
    583 	if (out_file == NULL) {
    584 		wpa_printf(MSG_ERROR, "wpa_debug_open_file: Failed to open "
    585 			   "output file, using standard output");
    586 		close(out_fd);
    587 		return -1;
    588 	}
    589 #ifndef _WIN32
    590 	setvbuf(out_file, NULL, _IOLBF, 0);
    591 #endif /* _WIN32 */
    592 #else /* CONFIG_DEBUG_FILE */
    593 	(void)path;
    594 #endif /* CONFIG_DEBUG_FILE */
    595 	return 0;
    596 }
    597 
    598 
    599 void wpa_debug_stop_log(void)
    600 {
    601 #ifdef CONFIG_DEBUG_FILE
    602 	if (!out_file)
    603 		return;
    604 	fclose(out_file);
    605 	out_file = NULL;
    606 #endif /* CONFIG_DEBUG_FILE */
    607 }
    608 
    609 
    610 void wpa_debug_close_file(void)
    611 {
    612 #ifdef CONFIG_DEBUG_FILE
    613 	wpa_debug_stop_log();
    614 	os_free(last_path);
    615 	last_path = NULL;
    616 #endif /* CONFIG_DEBUG_FILE */
    617 }
    618 
    619 
    620 void wpa_debug_setup_stdout(void)
    621 {
    622 #ifndef _WIN32
    623 	setvbuf(stdout, NULL, _IOLBF, 0);
    624 #endif /* _WIN32 */
    625 }
    626 
    627 #endif /* CONFIG_NO_STDOUT_DEBUG */
    628 
    629 
    630 #ifndef CONFIG_NO_WPA_MSG
    631 static wpa_msg_cb_func wpa_msg_cb = NULL;
    632 
    633 void wpa_msg_register_cb(wpa_msg_cb_func func)
    634 {
    635 	wpa_msg_cb = func;
    636 }
    637 
    638 
    639 static wpa_msg_get_ifname_func wpa_msg_ifname_cb = NULL;
    640 
    641 void wpa_msg_register_ifname_cb(wpa_msg_get_ifname_func func)
    642 {
    643 	wpa_msg_ifname_cb = func;
    644 }
    645 
    646 
    647 void wpa_msg(void *ctx, int level, const char *fmt, ...)
    648 {
    649 	va_list ap;
    650 	char *buf;
    651 	int buflen;
    652 	int len;
    653 	char prefix[130];
    654 
    655 	va_start(ap, fmt);
    656 	buflen = vsnprintf(NULL, 0, fmt, ap) + 1;
    657 	va_end(ap);
    658 
    659 	buf = os_malloc(buflen);
    660 	if (buf == NULL) {
    661 		wpa_printf(MSG_ERROR, "wpa_msg: Failed to allocate message "
    662 			   "buffer");
    663 		return;
    664 	}
    665 	va_start(ap, fmt);
    666 	prefix[0] = '\0';
    667 	if (wpa_msg_ifname_cb) {
    668 		const char *ifname = wpa_msg_ifname_cb(ctx);
    669 		if (ifname) {
    670 			int res = os_snprintf(prefix, sizeof(prefix), "%s: ",
    671 					      ifname);
    672 			if (os_snprintf_error(sizeof(prefix), res))
    673 				prefix[0] = '\0';
    674 		}
    675 	}
    676 	len = vsnprintf(buf, buflen, fmt, ap);
    677 	va_end(ap);
    678 	wpa_printf(level, "%s%s", prefix, buf);
    679 	if (wpa_msg_cb)
    680 		wpa_msg_cb(ctx, level, WPA_MSG_PER_INTERFACE, buf, len);
    681 	bin_clear_free(buf, buflen);
    682 }
    683 
    684 
    685 void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...)
    686 {
    687 	va_list ap;
    688 	char *buf;
    689 	int buflen;
    690 	int len;
    691 
    692 	if (!wpa_msg_cb)
    693 		return;
    694 
    695 	va_start(ap, fmt);
    696 	buflen = vsnprintf(NULL, 0, fmt, ap) + 1;
    697 	va_end(ap);
    698 
    699 	buf = os_malloc(buflen);
    700 	if (buf == NULL) {
    701 		wpa_printf(MSG_ERROR, "wpa_msg_ctrl: Failed to allocate "
    702 			   "message buffer");
    703 		return;
    704 	}
    705 	va_start(ap, fmt);
    706 	len = vsnprintf(buf, buflen, fmt, ap);
    707 	va_end(ap);
    708 	wpa_msg_cb(ctx, level, WPA_MSG_PER_INTERFACE, buf, len);
    709 	bin_clear_free(buf, buflen);
    710 }
    711 
    712 
    713 void wpa_msg_global(void *ctx, int level, const char *fmt, ...)
    714 {
    715 	va_list ap;
    716 	char *buf;
    717 	int buflen;
    718 	int len;
    719 
    720 	va_start(ap, fmt);
    721 	buflen = vsnprintf(NULL, 0, fmt, ap) + 1;
    722 	va_end(ap);
    723 
    724 	buf = os_malloc(buflen);
    725 	if (buf == NULL) {
    726 		wpa_printf(MSG_ERROR, "wpa_msg_global: Failed to allocate "
    727 			   "message buffer");
    728 		return;
    729 	}
    730 	va_start(ap, fmt);
    731 	len = vsnprintf(buf, buflen, fmt, ap);
    732 	va_end(ap);
    733 	wpa_printf(level, "%s", buf);
    734 	if (wpa_msg_cb)
    735 		wpa_msg_cb(ctx, level, WPA_MSG_GLOBAL, buf, len);
    736 	bin_clear_free(buf, buflen);
    737 }
    738 
    739 
    740 void wpa_msg_global_ctrl(void *ctx, int level, const char *fmt, ...)
    741 {
    742 	va_list ap;
    743 	char *buf;
    744 	int buflen;
    745 	int len;
    746 
    747 	if (!wpa_msg_cb)
    748 		return;
    749 
    750 	va_start(ap, fmt);
    751 	buflen = vsnprintf(NULL, 0, fmt, ap) + 1;
    752 	va_end(ap);
    753 
    754 	buf = os_malloc(buflen);
    755 	if (buf == NULL) {
    756 		wpa_printf(MSG_ERROR,
    757 			   "wpa_msg_global_ctrl: Failed to allocate message buffer");
    758 		return;
    759 	}
    760 	va_start(ap, fmt);
    761 	len = vsnprintf(buf, buflen, fmt, ap);
    762 	va_end(ap);
    763 	wpa_msg_cb(ctx, level, WPA_MSG_GLOBAL, buf, len);
    764 	bin_clear_free(buf, buflen);
    765 }
    766 
    767 
    768 void wpa_msg_no_global(void *ctx, int level, const char *fmt, ...)
    769 {
    770 	va_list ap;
    771 	char *buf;
    772 	int buflen;
    773 	int len;
    774 
    775 	va_start(ap, fmt);
    776 	buflen = vsnprintf(NULL, 0, fmt, ap) + 1;
    777 	va_end(ap);
    778 
    779 	buf = os_malloc(buflen);
    780 	if (buf == NULL) {
    781 		wpa_printf(MSG_ERROR, "wpa_msg_no_global: Failed to allocate "
    782 			   "message buffer");
    783 		return;
    784 	}
    785 	va_start(ap, fmt);
    786 	len = vsnprintf(buf, buflen, fmt, ap);
    787 	va_end(ap);
    788 	wpa_printf(level, "%s", buf);
    789 	if (wpa_msg_cb)
    790 		wpa_msg_cb(ctx, level, WPA_MSG_NO_GLOBAL, buf, len);
    791 	bin_clear_free(buf, buflen);
    792 }
    793 
    794 
    795 void wpa_msg_global_only(void *ctx, int level, const char *fmt, ...)
    796 {
    797 	va_list ap;
    798 	char *buf;
    799 	int buflen;
    800 	int len;
    801 
    802 	va_start(ap, fmt);
    803 	buflen = vsnprintf(NULL, 0, fmt, ap) + 1;
    804 	va_end(ap);
    805 
    806 	buf = os_malloc(buflen);
    807 	if (buf == NULL) {
    808 		wpa_printf(MSG_ERROR, "%s: Failed to allocate message buffer",
    809 			   __func__);
    810 		return;
    811 	}
    812 	va_start(ap, fmt);
    813 	len = vsnprintf(buf, buflen, fmt, ap);
    814 	va_end(ap);
    815 	wpa_printf(level, "%s", buf);
    816 	if (wpa_msg_cb)
    817 		wpa_msg_cb(ctx, level, WPA_MSG_ONLY_GLOBAL, buf, len);
    818 	os_free(buf);
    819 }
    820 
    821 #endif /* CONFIG_NO_WPA_MSG */
    822 
    823 
    824 #ifndef CONFIG_NO_HOSTAPD_LOGGER
    825 static hostapd_logger_cb_func hostapd_logger_cb = NULL;
    826 
    827 void hostapd_logger_register_cb(hostapd_logger_cb_func func)
    828 {
    829 	hostapd_logger_cb = func;
    830 }
    831 
    832 
    833 void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level,
    834 		    const char *fmt, ...)
    835 {
    836 	va_list ap;
    837 	char *buf;
    838 	int buflen;
    839 	int len;
    840 
    841 	va_start(ap, fmt);
    842 	buflen = vsnprintf(NULL, 0, fmt, ap) + 1;
    843 	va_end(ap);
    844 
    845 	buf = os_malloc(buflen);
    846 	if (buf == NULL) {
    847 		wpa_printf(MSG_ERROR, "hostapd_logger: Failed to allocate "
    848 			   "message buffer");
    849 		return;
    850 	}
    851 	va_start(ap, fmt);
    852 	len = vsnprintf(buf, buflen, fmt, ap);
    853 	va_end(ap);
    854 	if (hostapd_logger_cb)
    855 		hostapd_logger_cb(ctx, addr, module, level, buf, len);
    856 	else if (addr)
    857 		wpa_printf(MSG_DEBUG, "hostapd_logger: STA " MACSTR " - %s",
    858 			   MAC2STR(addr), buf);
    859 	else
    860 		wpa_printf(MSG_DEBUG, "hostapd_logger: %s", buf);
    861 	bin_clear_free(buf, buflen);
    862 }
    863 #endif /* CONFIG_NO_HOSTAPD_LOGGER */
    864 
    865 
    866 const char * debug_level_str(int level)
    867 {
    868 	switch (level) {
    869 	case MSG_EXCESSIVE:
    870 		return "EXCESSIVE";
    871 	case MSG_MSGDUMP:
    872 		return "MSGDUMP";
    873 	case MSG_DEBUG:
    874 		return "DEBUG";
    875 	case MSG_INFO:
    876 		return "INFO";
    877 	case MSG_WARNING:
    878 		return "WARNING";
    879 	case MSG_ERROR:
    880 		return "ERROR";
    881 	default:
    882 		return "?";
    883 	}
    884 }
    885 
    886 
    887 int str_to_debug_level(const char *s)
    888 {
    889 	if (os_strcasecmp(s, "EXCESSIVE") == 0)
    890 		return MSG_EXCESSIVE;
    891 	if (os_strcasecmp(s, "MSGDUMP") == 0)
    892 		return MSG_MSGDUMP;
    893 	if (os_strcasecmp(s, "DEBUG") == 0)
    894 		return MSG_DEBUG;
    895 	if (os_strcasecmp(s, "INFO") == 0)
    896 		return MSG_INFO;
    897 	if (os_strcasecmp(s, "WARNING") == 0)
    898 		return MSG_WARNING;
    899 	if (os_strcasecmp(s, "ERROR") == 0)
    900 		return MSG_ERROR;
    901 	return -1;
    902 }
    903