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 static 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 (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 		os_free(strbuf);
    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 		os_free(strbuf);
    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 u8 *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 u8 *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 u8 *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", buf[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 u8 *buf, size_t len)
    499 {
    500 	_wpa_hexdump_ascii(level, title, buf, len, 1);
    501 }
    502 
    503 
    504 void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf,
    505 			   size_t len)
    506 {
    507 	_wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys);
    508 }
    509 
    510 
    511 #ifdef CONFIG_DEBUG_FILE
    512 static char *last_path = NULL;
    513 #endif /* CONFIG_DEBUG_FILE */
    514 
    515 int wpa_debug_reopen_file(void)
    516 {
    517 #ifdef CONFIG_DEBUG_FILE
    518 	int rv;
    519 	if (last_path) {
    520 		char *tmp = os_strdup(last_path);
    521 		wpa_debug_close_file();
    522 		rv = wpa_debug_open_file(tmp);
    523 		os_free(tmp);
    524 	} else {
    525 		wpa_printf(MSG_ERROR, "Last-path was not set, cannot "
    526 			   "re-open log file.");
    527 		rv = -1;
    528 	}
    529 	return rv;
    530 #else /* CONFIG_DEBUG_FILE */
    531 	return 0;
    532 #endif /* CONFIG_DEBUG_FILE */
    533 }
    534 
    535 
    536 int wpa_debug_open_file(const char *path)
    537 {
    538 #ifdef CONFIG_DEBUG_FILE
    539 	if (!path)
    540 		return 0;
    541 
    542 	if (last_path == NULL || os_strcmp(last_path, path) != 0) {
    543 		/* Save our path to enable re-open */
    544 		os_free(last_path);
    545 		last_path = os_strdup(path);
    546 	}
    547 
    548 	out_file = fopen(path, "a");
    549 	if (out_file == NULL) {
    550 		wpa_printf(MSG_ERROR, "wpa_debug_open_file: Failed to open "
    551 			   "output file, using standard output");
    552 		return -1;
    553 	}
    554 #ifndef _WIN32
    555 	setvbuf(out_file, NULL, _IOLBF, 0);
    556 #endif /* _WIN32 */
    557 #endif /* CONFIG_DEBUG_FILE */
    558 	return 0;
    559 }
    560 
    561 
    562 void wpa_debug_close_file(void)
    563 {
    564 #ifdef CONFIG_DEBUG_FILE
    565 	if (!out_file)
    566 		return;
    567 	fclose(out_file);
    568 	out_file = NULL;
    569 	os_free(last_path);
    570 	last_path = NULL;
    571 #endif /* CONFIG_DEBUG_FILE */
    572 }
    573 
    574 #endif /* CONFIG_NO_STDOUT_DEBUG */
    575 
    576 
    577 #ifndef CONFIG_NO_WPA_MSG
    578 static wpa_msg_cb_func wpa_msg_cb = NULL;
    579 
    580 void wpa_msg_register_cb(wpa_msg_cb_func func)
    581 {
    582 	wpa_msg_cb = func;
    583 }
    584 
    585 
    586 static wpa_msg_get_ifname_func wpa_msg_ifname_cb = NULL;
    587 
    588 void wpa_msg_register_ifname_cb(wpa_msg_get_ifname_func func)
    589 {
    590 	wpa_msg_ifname_cb = func;
    591 }
    592 
    593 
    594 void wpa_msg(void *ctx, int level, const char *fmt, ...)
    595 {
    596 	va_list ap;
    597 	char *buf;
    598 	const int buflen = 2048;
    599 	int len;
    600 	char prefix[130];
    601 
    602 	buf = os_malloc(buflen);
    603 	if (buf == NULL) {
    604 		wpa_printf(MSG_ERROR, "wpa_msg: Failed to allocate message "
    605 			   "buffer");
    606 		return;
    607 	}
    608 	va_start(ap, fmt);
    609 	prefix[0] = '\0';
    610 	if (wpa_msg_ifname_cb) {
    611 		const char *ifname = wpa_msg_ifname_cb(ctx);
    612 		if (ifname) {
    613 			int res = os_snprintf(prefix, sizeof(prefix), "%s: ",
    614 					      ifname);
    615 			if (res < 0 || res >= (int) sizeof(prefix))
    616 				prefix[0] = '\0';
    617 		}
    618 	}
    619 	len = vsnprintf(buf, buflen, fmt, ap);
    620 	va_end(ap);
    621 	wpa_printf(level, "%s%s", prefix, buf);
    622 	if (wpa_msg_cb)
    623 		wpa_msg_cb(ctx, level, 0, buf, len);
    624 	os_free(buf);
    625 }
    626 
    627 
    628 void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...)
    629 {
    630 	va_list ap;
    631 	char *buf;
    632 	const int buflen = 2048;
    633 	int len;
    634 
    635 	if (!wpa_msg_cb)
    636 		return;
    637 
    638 	buf = os_malloc(buflen);
    639 	if (buf == NULL) {
    640 		wpa_printf(MSG_ERROR, "wpa_msg_ctrl: Failed to allocate "
    641 			   "message buffer");
    642 		return;
    643 	}
    644 	va_start(ap, fmt);
    645 	len = vsnprintf(buf, buflen, fmt, ap);
    646 	va_end(ap);
    647 	wpa_msg_cb(ctx, level, 0, buf, len);
    648 	os_free(buf);
    649 }
    650 
    651 
    652 void wpa_msg_global(void *ctx, int level, const char *fmt, ...)
    653 {
    654 	va_list ap;
    655 	char *buf;
    656 	const int buflen = 2048;
    657 	int len;
    658 
    659 	buf = os_malloc(buflen);
    660 	if (buf == NULL) {
    661 		wpa_printf(MSG_ERROR, "wpa_msg_global: 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_printf(level, "%s", buf);
    669 	if (wpa_msg_cb)
    670 		wpa_msg_cb(ctx, level, 1, buf, len);
    671 	os_free(buf);
    672 }
    673 
    674 
    675 void wpa_msg_no_global(void *ctx, int level, const char *fmt, ...)
    676 {
    677 	va_list ap;
    678 	char *buf;
    679 	const int buflen = 2048;
    680 	int len;
    681 
    682 	buf = os_malloc(buflen);
    683 	if (buf == NULL) {
    684 		wpa_printf(MSG_ERROR, "wpa_msg_no_global: Failed to allocate "
    685 			   "message buffer");
    686 		return;
    687 	}
    688 	va_start(ap, fmt);
    689 	len = vsnprintf(buf, buflen, fmt, ap);
    690 	va_end(ap);
    691 	wpa_printf(level, "%s", buf);
    692 	if (wpa_msg_cb)
    693 		wpa_msg_cb(ctx, level, 2, buf, len);
    694 	os_free(buf);
    695 }
    696 
    697 #endif /* CONFIG_NO_WPA_MSG */
    698 
    699 
    700 #ifndef CONFIG_NO_HOSTAPD_LOGGER
    701 static hostapd_logger_cb_func hostapd_logger_cb = NULL;
    702 
    703 void hostapd_logger_register_cb(hostapd_logger_cb_func func)
    704 {
    705 	hostapd_logger_cb = func;
    706 }
    707 
    708 
    709 void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level,
    710 		    const char *fmt, ...)
    711 {
    712 	va_list ap;
    713 	char *buf;
    714 	const int buflen = 2048;
    715 	int len;
    716 
    717 	buf = os_malloc(buflen);
    718 	if (buf == NULL) {
    719 		wpa_printf(MSG_ERROR, "hostapd_logger: Failed to allocate "
    720 			   "message buffer");
    721 		return;
    722 	}
    723 	va_start(ap, fmt);
    724 	len = vsnprintf(buf, buflen, fmt, ap);
    725 	va_end(ap);
    726 	if (hostapd_logger_cb)
    727 		hostapd_logger_cb(ctx, addr, module, level, buf, len);
    728 	else if (addr)
    729 		wpa_printf(MSG_DEBUG, "hostapd_logger: STA " MACSTR " - %s",
    730 			   MAC2STR(addr), buf);
    731 	else
    732 		wpa_printf(MSG_DEBUG, "hostapd_logger: %s", buf);
    733 	os_free(buf);
    734 }
    735 #endif /* CONFIG_NO_HOSTAPD_LOGGER */
    736