Home | History | Annotate | Download | only in utils
      1 /*
      2  * wpa_supplicant/hostapd / Debug prints
      3  * Copyright (c) 2002-2007, Jouni Malinen <j (at) 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 
     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 
     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 
     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 
     96 void wpa_debug_close_syslog(void)
     97 {
     98 	if (wpa_debug_syslog)
     99 		closelog();
    100 }
    101 
    102 
    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  */
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    388 void wpa_msg_register_ifname_cb(wpa_msg_get_ifname_func func)
    389 {
    390 	wpa_msg_ifname_cb = func;
    391 }
    392 
    393 
    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 
    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 
    456 void hostapd_logger_register_cb(hostapd_logger_cb_func func)
    457 {
    458 	hostapd_logger_cb = func;
    459 }
    460 
    461 
    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