1 /*
2  * wpa_supplicant/hostapd / Debug prints
3  * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8 
9 #include "includes.h"
10 
11 #include "common.h"
12 
13 #ifdef CONFIG_DEBUG_SYSLOG
14 #include <syslog.h>
15 
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 
wpa_to_android_level(int level)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 
wpa_debug_print_timestamp(void)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 
wpa_debug_open_syslog(void)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 
wpa_debug_close_syslog(void)101 void wpa_debug_close_syslog(void)
102 {
103 	if (wpa_debug_syslog)
104 		closelog();
105 }
106 
107 
syslog_priority(int level)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 
wpa_debug_open_linux_tracing(void)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 
wpa_debug_close_linux_tracing(void)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  */
wpa_printf(int level,const char * fmt,...)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 
_wpa_hexdump(int level,const char * title,const u8 * buf,size_t len,int show)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 
wpa_hexdump(int level,const char * title,const void * buf,size_t len)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 
wpa_hexdump_key(int level,const char * title,const void * buf,size_t len)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 
_wpa_hexdump_ascii(int level,const char * title,const void * buf,size_t len,int show)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 
wpa_hexdump_ascii(int level,const char * title,const void * buf,size_t len)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 
wpa_hexdump_ascii_key(int level,const char * title,const void * buf,size_t len)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 
wpa_debug_reopen_file(void)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 
wpa_debug_open_file(const char * path)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 
wpa_debug_close_file(void)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 
wpa_debug_setup_stdout(void)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 
wpa_msg_register_cb(wpa_msg_cb_func func)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 
wpa_msg_register_ifname_cb(wpa_msg_get_ifname_func func)631 void wpa_msg_register_ifname_cb(wpa_msg_get_ifname_func func)
632 {
633 	wpa_msg_ifname_cb = func;
634 }
635 
636 
wpa_msg(void * ctx,int level,const char * fmt,...)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 
wpa_msg_ctrl(void * ctx,int level,const char * fmt,...)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 
wpa_msg_global(void * ctx,int level,const char * fmt,...)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 
wpa_msg_global_ctrl(void * ctx,int level,const char * fmt,...)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 
wpa_msg_no_global(void * ctx,int level,const char * fmt,...)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 
wpa_msg_global_only(void * ctx,int level,const char * fmt,...)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 
hostapd_logger_register_cb(hostapd_logger_cb_func func)817 void hostapd_logger_register_cb(hostapd_logger_cb_func func)
818 {
819 	hostapd_logger_cb = func;
820 }
821 
822 
hostapd_logger(void * ctx,const u8 * addr,unsigned int module,int level,const char * fmt,...)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 
debug_level_str(int level)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 
str_to_debug_level(const char * s)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