Home | History | Annotate | 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 
     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 }
    893