• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * wpa_supplicant/hostapd / Debug prints
3  * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14 
15 #include "includes.h"
16 
17 #include "common.h"
18 
19 #ifdef CONFIG_DEBUG_SYSLOG
20 #include <syslog.h>
21 
22 static int wpa_debug_syslog = 0;
23 #endif /* CONFIG_DEBUG_SYSLOG */
24 
25 
26 int wpa_debug_level = MSG_INFO;
27 int wpa_debug_show_keys = 0;
28 int wpa_debug_timestamp = 0;
29 
30 
31 #ifdef CONFIG_ANDROID_LOG
32 
33 #include <android/log.h>
34 
35 #ifndef ANDROID_LOG_NAME
36 #define ANDROID_LOG_NAME	"wpa_supplicant"
37 #endif
38 
android_printf(int level,char * format,...)39 void android_printf(int level, char *format, ...)
40 {
41 	if (level >= wpa_debug_level) {
42 		va_list ap;
43 		if (level == MSG_ERROR)
44 			level = ANDROID_LOG_ERROR;
45 		else if (level == MSG_WARNING)
46 			level = ANDROID_LOG_WARN;
47 		else if (level == MSG_INFO)
48 			level = ANDROID_LOG_INFO;
49 		else
50 			level = ANDROID_LOG_DEBUG;
51 		va_start(ap, format);
52 		__android_log_vprint(level, ANDROID_LOG_NAME, format, ap);
53 		va_end(ap);
54 	}
55 }
56 
57 #else /* CONFIG_ANDROID_LOG */
58 
59 #ifndef CONFIG_NO_STDOUT_DEBUG
60 
61 #ifdef CONFIG_DEBUG_FILE
62 static FILE *out_file = NULL;
63 #endif /* CONFIG_DEBUG_FILE */
64 
65 
wpa_debug_print_timestamp(void)66 void wpa_debug_print_timestamp(void)
67 {
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 }
82 
83 
84 #ifdef CONFIG_DEBUG_SYSLOG
85 #ifndef LOG_HOSTAPD
86 #define LOG_HOSTAPD LOG_DAEMON
87 #endif /* LOG_HOSTAPD */
88 
wpa_debug_open_syslog(void)89 void wpa_debug_open_syslog(void)
90 {
91 	openlog("wpa_supplicant", LOG_PID | LOG_NDELAY, LOG_HOSTAPD);
92 	wpa_debug_syslog++;
93 }
94 
95 
wpa_debug_close_syslog(void)96 void wpa_debug_close_syslog(void)
97 {
98 	if (wpa_debug_syslog)
99 		closelog();
100 }
101 
102 
syslog_priority(int level)103 static int syslog_priority(int level)
104 {
105 	switch (level) {
106 	case MSG_MSGDUMP:
107 	case MSG_DEBUG:
108 		return LOG_DEBUG;
109 	case MSG_INFO:
110 		return LOG_NOTICE;
111 	case MSG_WARNING:
112 		return LOG_WARNING;
113 	case MSG_ERROR:
114 		return LOG_ERR;
115 	}
116 	return LOG_INFO;
117 }
118 #endif /* CONFIG_DEBUG_SYSLOG */
119 
120 
121 /**
122  * wpa_printf - conditional printf
123  * @level: priority level (MSG_*) of the message
124  * @fmt: printf format string, followed by optional arguments
125  *
126  * This function is used to print conditional debugging and error messages. The
127  * output may be directed to stdout, stderr, and/or syslog based on
128  * configuration.
129  *
130  * Note: New line '\n' is added to the end of the text when printing to stdout.
131  */
wpa_printf(int level,const char * fmt,...)132 void wpa_printf(int level, const char *fmt, ...)
133 {
134 	va_list ap;
135 
136 	va_start(ap, fmt);
137 	if (level >= wpa_debug_level) {
138 #ifdef CONFIG_DEBUG_SYSLOG
139 		if (wpa_debug_syslog) {
140 			vsyslog(syslog_priority(level), fmt, ap);
141 		} else {
142 #endif /* CONFIG_DEBUG_SYSLOG */
143 		wpa_debug_print_timestamp();
144 #ifdef CONFIG_DEBUG_FILE
145 		if (out_file) {
146 			vfprintf(out_file, fmt, ap);
147 			fprintf(out_file, "\n");
148 		} else {
149 #endif /* CONFIG_DEBUG_FILE */
150 		vprintf(fmt, ap);
151 		printf("\n");
152 #ifdef CONFIG_DEBUG_FILE
153 		}
154 #endif /* CONFIG_DEBUG_FILE */
155 #ifdef CONFIG_DEBUG_SYSLOG
156 		}
157 #endif /* CONFIG_DEBUG_SYSLOG */
158 	}
159 	va_end(ap);
160 }
161 
162 
_wpa_hexdump(int level,const char * title,const u8 * buf,size_t len,int show)163 static void _wpa_hexdump(int level, const char *title, const u8 *buf,
164 			 size_t len, int show)
165 {
166 	size_t i;
167 	if (level < wpa_debug_level)
168 		return;
169 	wpa_debug_print_timestamp();
170 #ifdef CONFIG_DEBUG_FILE
171 	if (out_file) {
172 		fprintf(out_file, "%s - hexdump(len=%lu):",
173 			title, (unsigned long) len);
174 		if (buf == NULL) {
175 			fprintf(out_file, " [NULL]");
176 		} else if (show) {
177 			for (i = 0; i < len; i++)
178 				fprintf(out_file, " %02x", buf[i]);
179 		} else {
180 			fprintf(out_file, " [REMOVED]");
181 		}
182 		fprintf(out_file, "\n");
183 	} else {
184 #endif /* CONFIG_DEBUG_FILE */
185 	printf("%s - hexdump(len=%lu):", title, (unsigned long) len);
186 	if (buf == NULL) {
187 		printf(" [NULL]");
188 	} else if (show) {
189 		for (i = 0; i < len; i++)
190 			printf(" %02x", buf[i]);
191 	} else {
192 		printf(" [REMOVED]");
193 	}
194 	printf("\n");
195 #ifdef CONFIG_DEBUG_FILE
196 	}
197 #endif /* CONFIG_DEBUG_FILE */
198 }
199 
wpa_hexdump(int level,const char * title,const u8 * buf,size_t len)200 void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len)
201 {
202 	_wpa_hexdump(level, title, buf, len, 1);
203 }
204 
205 
wpa_hexdump_key(int level,const char * title,const u8 * buf,size_t len)206 void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len)
207 {
208 	_wpa_hexdump(level, title, buf, len, wpa_debug_show_keys);
209 }
210 
211 
_wpa_hexdump_ascii(int level,const char * title,const u8 * buf,size_t len,int show)212 static void _wpa_hexdump_ascii(int level, const char *title, const u8 *buf,
213 			       size_t len, int show)
214 {
215 	size_t i, llen;
216 	const u8 *pos = buf;
217 	const size_t line_len = 16;
218 
219 	if (level < wpa_debug_level)
220 		return;
221 	wpa_debug_print_timestamp();
222 #ifdef CONFIG_DEBUG_FILE
223 	if (out_file) {
224 		if (!show) {
225 			fprintf(out_file,
226 				"%s - hexdump_ascii(len=%lu): [REMOVED]\n",
227 				title, (unsigned long) len);
228 			return;
229 		}
230 		if (buf == NULL) {
231 			fprintf(out_file,
232 				"%s - hexdump_ascii(len=%lu): [NULL]\n",
233 				title, (unsigned long) len);
234 			return;
235 		}
236 		fprintf(out_file, "%s - hexdump_ascii(len=%lu):\n",
237 			title, (unsigned long) len);
238 		while (len) {
239 			llen = len > line_len ? line_len : len;
240 			fprintf(out_file, "    ");
241 			for (i = 0; i < llen; i++)
242 				fprintf(out_file, " %02x", pos[i]);
243 			for (i = llen; i < line_len; i++)
244 				fprintf(out_file, "   ");
245 			fprintf(out_file, "   ");
246 			for (i = 0; i < llen; i++) {
247 				if (isprint(pos[i]))
248 					fprintf(out_file, "%c", pos[i]);
249 				else
250 					fprintf(out_file, "_");
251 			}
252 			for (i = llen; i < line_len; i++)
253 				fprintf(out_file, " ");
254 			fprintf(out_file, "\n");
255 			pos += llen;
256 			len -= llen;
257 		}
258 	} else {
259 #endif /* CONFIG_DEBUG_FILE */
260 	if (!show) {
261 		printf("%s - hexdump_ascii(len=%lu): [REMOVED]\n",
262 		       title, (unsigned long) len);
263 		return;
264 	}
265 	if (buf == NULL) {
266 		printf("%s - hexdump_ascii(len=%lu): [NULL]\n",
267 		       title, (unsigned long) len);
268 		return;
269 	}
270 	printf("%s - hexdump_ascii(len=%lu):\n", title, (unsigned long) len);
271 	while (len) {
272 		llen = len > line_len ? line_len : len;
273 		printf("    ");
274 		for (i = 0; i < llen; i++)
275 			printf(" %02x", pos[i]);
276 		for (i = llen; i < line_len; i++)
277 			printf("   ");
278 		printf("   ");
279 		for (i = 0; i < llen; i++) {
280 			if (isprint(pos[i]))
281 				printf("%c", pos[i]);
282 			else
283 				printf("_");
284 		}
285 		for (i = llen; i < line_len; i++)
286 			printf(" ");
287 		printf("\n");
288 		pos += llen;
289 		len -= llen;
290 	}
291 #ifdef CONFIG_DEBUG_FILE
292 	}
293 #endif /* CONFIG_DEBUG_FILE */
294 }
295 
296 
wpa_hexdump_ascii(int level,const char * title,const u8 * buf,size_t len)297 void wpa_hexdump_ascii(int level, const char *title, const u8 *buf, size_t len)
298 {
299 	_wpa_hexdump_ascii(level, title, buf, len, 1);
300 }
301 
302 
wpa_hexdump_ascii_key(int level,const char * title,const u8 * buf,size_t len)303 void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf,
304 			   size_t len)
305 {
306 	_wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys);
307 }
308 
309 
310 #ifdef CONFIG_DEBUG_FILE
311 static char *last_path = NULL;
312 #endif /* CONFIG_DEBUG_FILE */
313 
wpa_debug_reopen_file(void)314 int wpa_debug_reopen_file(void)
315 {
316 #ifdef CONFIG_DEBUG_FILE
317 	int rv;
318 	if (last_path) {
319 		char *tmp = os_strdup(last_path);
320 		wpa_debug_close_file();
321 		rv = wpa_debug_open_file(tmp);
322 		os_free(tmp);
323 	} else {
324 		wpa_printf(MSG_ERROR, "Last-path was not set, cannot "
325 			   "re-open log file.");
326 		rv = -1;
327 	}
328 	return rv;
329 #else /* CONFIG_DEBUG_FILE */
330 	return 0;
331 #endif /* CONFIG_DEBUG_FILE */
332 }
333 
334 
wpa_debug_open_file(const char * path)335 int wpa_debug_open_file(const char *path)
336 {
337 #ifdef CONFIG_DEBUG_FILE
338 	if (!path)
339 		return 0;
340 
341 	if (last_path == NULL || os_strcmp(last_path, path) != 0) {
342 		/* Save our path to enable re-open */
343 		os_free(last_path);
344 		last_path = os_strdup(path);
345 	}
346 
347 	out_file = fopen(path, "a");
348 	if (out_file == NULL) {
349 		wpa_printf(MSG_ERROR, "wpa_debug_open_file: Failed to open "
350 			   "output file, using standard output");
351 		return -1;
352 	}
353 #ifndef _WIN32
354 	setvbuf(out_file, NULL, _IOLBF, 0);
355 #endif /* _WIN32 */
356 #endif /* CONFIG_DEBUG_FILE */
357 	return 0;
358 }
359 
360 
wpa_debug_close_file(void)361 void wpa_debug_close_file(void)
362 {
363 #ifdef CONFIG_DEBUG_FILE
364 	if (!out_file)
365 		return;
366 	fclose(out_file);
367 	out_file = NULL;
368 	os_free(last_path);
369 	last_path = NULL;
370 #endif /* CONFIG_DEBUG_FILE */
371 }
372 
373 #endif /* CONFIG_NO_STDOUT_DEBUG */
374 
375 #endif /* CONFIG_ANDROID_LOG */
376 
377 #ifndef CONFIG_NO_WPA_MSG
378 static wpa_msg_cb_func wpa_msg_cb = NULL;
379 
wpa_msg_register_cb(wpa_msg_cb_func func)380 void wpa_msg_register_cb(wpa_msg_cb_func func)
381 {
382 	wpa_msg_cb = func;
383 }
384 
385 
386 static wpa_msg_get_ifname_func wpa_msg_ifname_cb = NULL;
387 
wpa_msg_register_ifname_cb(wpa_msg_get_ifname_func func)388 void wpa_msg_register_ifname_cb(wpa_msg_get_ifname_func func)
389 {
390 	wpa_msg_ifname_cb = func;
391 }
392 
393 
wpa_msg(void * ctx,int level,const char * fmt,...)394 void wpa_msg(void *ctx, int level, const char *fmt, ...)
395 {
396 	va_list ap;
397 	char *buf;
398 	const int buflen = 2048;
399 	int len;
400 	char prefix[130];
401 
402 	buf = os_malloc(buflen);
403 	if (buf == NULL) {
404 		wpa_printf(MSG_ERROR, "wpa_msg: Failed to allocate message "
405 			   "buffer");
406 		return;
407 	}
408 	va_start(ap, fmt);
409 	prefix[0] = '\0';
410 	if (wpa_msg_ifname_cb) {
411 		const char *ifname = wpa_msg_ifname_cb(ctx);
412 		if (ifname) {
413 			int res = os_snprintf(prefix, sizeof(prefix), "%s: ",
414 					      ifname);
415 			if (res < 0 || res >= (int) sizeof(prefix))
416 				prefix[0] = '\0';
417 		}
418 	}
419 	len = vsnprintf(buf, buflen, fmt, ap);
420 	va_end(ap);
421 	wpa_printf(level, "%s%s", prefix, buf);
422 	if (wpa_msg_cb)
423 		wpa_msg_cb(ctx, level, buf, len);
424 	os_free(buf);
425 }
426 
427 
wpa_msg_ctrl(void * ctx,int level,const char * fmt,...)428 void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...)
429 {
430 	va_list ap;
431 	char *buf;
432 	const int buflen = 2048;
433 	int len;
434 
435 	if (!wpa_msg_cb)
436 		return;
437 
438 	buf = os_malloc(buflen);
439 	if (buf == NULL) {
440 		wpa_printf(MSG_ERROR, "wpa_msg_ctrl: Failed to allocate "
441 			   "message buffer");
442 		return;
443 	}
444 	va_start(ap, fmt);
445 	len = vsnprintf(buf, buflen, fmt, ap);
446 	va_end(ap);
447 	wpa_msg_cb(ctx, level, buf, len);
448 	os_free(buf);
449 }
450 #endif /* CONFIG_NO_WPA_MSG */
451 
452 
453 #ifndef CONFIG_NO_HOSTAPD_LOGGER
454 static hostapd_logger_cb_func hostapd_logger_cb = NULL;
455 
hostapd_logger_register_cb(hostapd_logger_cb_func func)456 void hostapd_logger_register_cb(hostapd_logger_cb_func func)
457 {
458 	hostapd_logger_cb = func;
459 }
460 
461 
hostapd_logger(void * ctx,const u8 * addr,unsigned int module,int level,const char * fmt,...)462 void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level,
463 		    const char *fmt, ...)
464 {
465 	va_list ap;
466 	char *buf;
467 	const int buflen = 2048;
468 	int len;
469 
470 	buf = os_malloc(buflen);
471 	if (buf == NULL) {
472 		wpa_printf(MSG_ERROR, "hostapd_logger: Failed to allocate "
473 			   "message buffer");
474 		return;
475 	}
476 	va_start(ap, fmt);
477 	len = vsnprintf(buf, buflen, fmt, ap);
478 	va_end(ap);
479 	if (hostapd_logger_cb)
480 		hostapd_logger_cb(ctx, addr, module, level, buf, len);
481 	else if (addr)
482 		wpa_printf(MSG_DEBUG, "hostapd_logger: STA " MACSTR " - %s",
483 			   MAC2STR(addr), buf);
484 	else
485 		wpa_printf(MSG_DEBUG, "hostapd_logger: %s", buf);
486 	os_free(buf);
487 }
488 #endif /* CONFIG_NO_HOSTAPD_LOGGER */
489