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