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