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 
     20 #ifdef CONFIG_DEBUG_FILE
     21 static FILE *out_file = NULL;
     22 #endif /* CONFIG_DEBUG_FILE */
     23 #ifdef CONFIG_ANDROID_LOG
     24 int wpa_debug_level = MSG_WARNING;
     25 #else
     26 int wpa_debug_level = MSG_INFO;
     27 #endif
     28 int wpa_debug_show_keys = 0;
     29 int wpa_debug_timestamp = 0;
     30 
     31 
     32 #ifdef CONFIG_ANDROID_LOG
     33 
     34 #include <android/log.h>
     35 
     36 void android_printf(int level, char *format, ...)
     37 {
     38 	if (level >= wpa_debug_level) {
     39 		va_list ap;
     40 		if (level == MSG_ERROR) {
     41 			level = ANDROID_LOG_ERROR;
     42 		} else if (level == MSG_WARNING) {
     43 			level = ANDROID_LOG_WARN;
     44 		} else if (level == MSG_INFO) {
     45 			level = ANDROID_LOG_INFO;
     46 		} else {
     47 			level = ANDROID_LOG_DEBUG;
     48 		}
     49 		va_start(ap, format);
     50 		__android_log_vprint(level, "wpa_supplicant", format, ap);
     51 		va_end(ap);
     52 	}
     53 }
     54 
     55 #else /* CONFIG_ANDROID_LOG */
     56 
     57 #ifndef CONFIG_NO_STDOUT_DEBUG
     58 
     59 void wpa_debug_print_timestamp(void)
     60 {
     61 	struct os_time tv;
     62 
     63 	if (!wpa_debug_timestamp)
     64 		return;
     65 
     66 	os_get_time(&tv);
     67 #ifdef CONFIG_DEBUG_FILE
     68 	if (out_file) {
     69 		fprintf(out_file, "%ld.%06u: ", (long) tv.sec,
     70 			(unsigned int) tv.usec);
     71 	} else
     72 #endif /* CONFIG_DEBUG_FILE */
     73 	printf("%ld.%06u: ", (long) tv.sec, (unsigned int) tv.usec);
     74 }
     75 
     76 
     77 /**
     78  * wpa_printf - conditional printf
     79  * @level: priority level (MSG_*) of the message
     80  * @fmt: printf format string, followed by optional arguments
     81  *
     82  * This function is used to print conditional debugging and error messages. The
     83  * output may be directed to stdout, stderr, and/or syslog based on
     84  * configuration.
     85  *
     86  * Note: New line '\n' is added to the end of the text when printing to stdout.
     87  */
     88 void wpa_printf(int level, const char *fmt, ...)
     89 {
     90 	va_list ap;
     91 
     92 	va_start(ap, fmt);
     93 	if (level >= wpa_debug_level) {
     94 		wpa_debug_print_timestamp();
     95 #ifdef CONFIG_DEBUG_FILE
     96 		if (out_file) {
     97 			vfprintf(out_file, fmt, ap);
     98 			fprintf(out_file, "\n");
     99 		} else {
    100 #endif /* CONFIG_DEBUG_FILE */
    101 		vprintf(fmt, ap);
    102 		printf("\n");
    103 #ifdef CONFIG_DEBUG_FILE
    104 		}
    105 #endif /* CONFIG_DEBUG_FILE */
    106 	}
    107 	va_end(ap);
    108 }
    109 
    110 
    111 static void _wpa_hexdump(int level, const char *title, const u8 *buf,
    112 			 size_t len, int show)
    113 {
    114 	size_t i;
    115 	if (level < wpa_debug_level)
    116 		return;
    117 	wpa_debug_print_timestamp();
    118 #ifdef CONFIG_DEBUG_FILE
    119 	if (out_file) {
    120 		fprintf(out_file, "%s - hexdump(len=%lu):",
    121 			title, (unsigned long) len);
    122 		if (buf == NULL) {
    123 			fprintf(out_file, " [NULL]");
    124 		} else if (show) {
    125 			for (i = 0; i < len; i++)
    126 				fprintf(out_file, " %02x", buf[i]);
    127 		} else {
    128 			fprintf(out_file, " [REMOVED]");
    129 		}
    130 		fprintf(out_file, "\n");
    131 	} else {
    132 #endif /* CONFIG_DEBUG_FILE */
    133 	printf("%s - hexdump(len=%lu):", title, (unsigned long) len);
    134 	if (buf == NULL) {
    135 		printf(" [NULL]");
    136 	} else if (show) {
    137 		for (i = 0; i < len; i++)
    138 			printf(" %02x", buf[i]);
    139 	} else {
    140 		printf(" [REMOVED]");
    141 	}
    142 	printf("\n");
    143 #ifdef CONFIG_DEBUG_FILE
    144 	}
    145 #endif /* CONFIG_DEBUG_FILE */
    146 }
    147 
    148 void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len)
    149 {
    150 	_wpa_hexdump(level, title, buf, len, 1);
    151 }
    152 
    153 
    154 void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len)
    155 {
    156 	_wpa_hexdump(level, title, buf, len, wpa_debug_show_keys);
    157 }
    158 
    159 
    160 static void _wpa_hexdump_ascii(int level, const char *title, const u8 *buf,
    161 			       size_t len, int show)
    162 {
    163 	size_t i, llen;
    164 	const u8 *pos = buf;
    165 	const size_t line_len = 16;
    166 
    167 	if (level < wpa_debug_level)
    168 		return;
    169 	wpa_debug_print_timestamp();
    170 #ifdef CONFIG_DEBUG_FILE
    171 	if (out_file) {
    172 		if (!show) {
    173 			fprintf(out_file,
    174 				"%s - hexdump_ascii(len=%lu): [REMOVED]\n",
    175 				title, (unsigned long) len);
    176 			return;
    177 		}
    178 		if (buf == NULL) {
    179 			fprintf(out_file,
    180 				"%s - hexdump_ascii(len=%lu): [NULL]\n",
    181 				title, (unsigned long) len);
    182 			return;
    183 		}
    184 		fprintf(out_file, "%s - hexdump_ascii(len=%lu):\n",
    185 			title, (unsigned long) len);
    186 		while (len) {
    187 			llen = len > line_len ? line_len : len;
    188 			fprintf(out_file, "    ");
    189 			for (i = 0; i < llen; i++)
    190 				fprintf(out_file, " %02x", pos[i]);
    191 			for (i = llen; i < line_len; i++)
    192 				fprintf(out_file, "   ");
    193 			fprintf(out_file, "   ");
    194 			for (i = 0; i < llen; i++) {
    195 				if (isprint(pos[i]))
    196 					fprintf(out_file, "%c", pos[i]);
    197 				else
    198 					fprintf(out_file, "_");
    199 			}
    200 			for (i = llen; i < line_len; i++)
    201 				fprintf(out_file, " ");
    202 			fprintf(out_file, "\n");
    203 			pos += llen;
    204 			len -= llen;
    205 		}
    206 	} else {
    207 #endif /* CONFIG_DEBUG_FILE */
    208 	if (!show) {
    209 		printf("%s - hexdump_ascii(len=%lu): [REMOVED]\n",
    210 		       title, (unsigned long) len);
    211 		return;
    212 	}
    213 	if (buf == NULL) {
    214 		printf("%s - hexdump_ascii(len=%lu): [NULL]\n",
    215 		       title, (unsigned long) len);
    216 		return;
    217 	}
    218 	printf("%s - hexdump_ascii(len=%lu):\n", title, (unsigned long) len);
    219 	while (len) {
    220 		llen = len > line_len ? line_len : len;
    221 		printf("    ");
    222 		for (i = 0; i < llen; i++)
    223 			printf(" %02x", pos[i]);
    224 		for (i = llen; i < line_len; i++)
    225 			printf("   ");
    226 		printf("   ");
    227 		for (i = 0; i < llen; i++) {
    228 			if (isprint(pos[i]))
    229 				printf("%c", pos[i]);
    230 			else
    231 				printf("_");
    232 		}
    233 		for (i = llen; i < line_len; i++)
    234 			printf(" ");
    235 		printf("\n");
    236 		pos += llen;
    237 		len -= llen;
    238 	}
    239 #ifdef CONFIG_DEBUG_FILE
    240 	}
    241 #endif /* CONFIG_DEBUG_FILE */
    242 }
    243 
    244 
    245 void wpa_hexdump_ascii(int level, const char *title, const u8 *buf, size_t len)
    246 {
    247 	_wpa_hexdump_ascii(level, title, buf, len, 1);
    248 }
    249 
    250 
    251 void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf,
    252 			   size_t len)
    253 {
    254 	_wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys);
    255 }
    256 
    257 
    258 int wpa_debug_open_file(const char *path)
    259 {
    260 #ifdef CONFIG_DEBUG_FILE
    261 	if (!path)
    262 		return 0;
    263 	out_file = fopen(path, "a");
    264 	if (out_file == NULL) {
    265 		wpa_printf(MSG_ERROR, "wpa_debug_open_file: Failed to open "
    266 			   "output file, using standard output");
    267 		return -1;
    268 	}
    269 #ifndef _WIN32
    270 	setvbuf(out_file, NULL, _IOLBF, 0);
    271 #endif /* _WIN32 */
    272 #endif /* CONFIG_DEBUG_FILE */
    273 	return 0;
    274 }
    275 
    276 
    277 void wpa_debug_close_file(void)
    278 {
    279 #ifdef CONFIG_DEBUG_FILE
    280 	if (!out_file)
    281 		return;
    282 	fclose(out_file);
    283 	out_file = NULL;
    284 #endif /* CONFIG_DEBUG_FILE */
    285 }
    286 
    287 #endif /* CONFIG_NO_STDOUT_DEBUG */
    288 
    289 #endif /* CONFIG_ANDROID_LOG */
    290 
    291 #ifndef CONFIG_NO_WPA_MSG
    292 static wpa_msg_cb_func wpa_msg_cb = NULL;
    293 
    294 void wpa_msg_register_cb(wpa_msg_cb_func func)
    295 {
    296 	wpa_msg_cb = func;
    297 }
    298 
    299 
    300 void wpa_msg(void *ctx, int level, const char *fmt, ...)
    301 {
    302 	va_list ap;
    303 	char *buf;
    304 	const int buflen = 2048;
    305 	int len;
    306 
    307 	buf = os_malloc(buflen);
    308 	if (buf == NULL) {
    309 		wpa_printf(MSG_ERROR, "wpa_msg: Failed to allocate message "
    310 			   "buffer");
    311 		return;
    312 	}
    313 	va_start(ap, fmt);
    314 	len = vsnprintf(buf, buflen, fmt, ap);
    315 	va_end(ap);
    316 	wpa_printf(level, "%s", buf);
    317 	if (wpa_msg_cb)
    318 		wpa_msg_cb(ctx, level, buf, len);
    319 	os_free(buf);
    320 }
    321 
    322 
    323 void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...)
    324 {
    325 	va_list ap;
    326 	char *buf;
    327 	const int buflen = 2048;
    328 	int len;
    329 
    330 	if (!wpa_msg_cb)
    331 		return;
    332 
    333 	buf = os_malloc(buflen);
    334 	if (buf == NULL) {
    335 		wpa_printf(MSG_ERROR, "wpa_msg_ctrl: Failed to allocate "
    336 			   "message buffer");
    337 		return;
    338 	}
    339 	va_start(ap, fmt);
    340 	len = vsnprintf(buf, buflen, fmt, ap);
    341 	va_end(ap);
    342 	wpa_msg_cb(ctx, level, buf, len);
    343 	os_free(buf);
    344 }
    345 #endif /* CONFIG_NO_WPA_MSG */
    346 
    347 
    348 #ifndef CONFIG_NO_HOSTAPD_LOGGER
    349 static hostapd_logger_cb_func hostapd_logger_cb = NULL;
    350 
    351 void hostapd_logger_register_cb(hostapd_logger_cb_func func)
    352 {
    353 	hostapd_logger_cb = func;
    354 }
    355 
    356 
    357 void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level,
    358 		    const char *fmt, ...)
    359 {
    360 	va_list ap;
    361 	char *buf;
    362 	const int buflen = 2048;
    363 	int len;
    364 
    365 	buf = os_malloc(buflen);
    366 	if (buf == NULL) {
    367 		wpa_printf(MSG_ERROR, "hostapd_logger: Failed to allocate "
    368 			   "message buffer");
    369 		return;
    370 	}
    371 	va_start(ap, fmt);
    372 	len = vsnprintf(buf, buflen, fmt, ap);
    373 	va_end(ap);
    374 	if (hostapd_logger_cb)
    375 		hostapd_logger_cb(ctx, addr, module, level, buf, len);
    376 	else
    377 		wpa_printf(MSG_DEBUG, "hostapd_logger: %s", buf);
    378 	os_free(buf);
    379 }
    380 #endif /* CONFIG_NO_HOSTAPD_LOGGER */
    381