X-Git-Url: http://www.project-moonshot.org/gitweb/?p=mech_eap.git;a=blobdiff_plain;f=libeap%2Fsrc%2Futils%2Fwpa_debug.c;h=61c0d5ce68c79b27d61dbdb4ec429f4bd22a1aa3;hp=6f6fc69ccc44a935280c2e89acd61c93ff92cec3;hb=4f319dde67a76fe0aaf33f6d2788968012584ada;hpb=ed09b5e64dd485851310307979d5eed14678087b diff --git a/libeap/src/utils/wpa_debug.c b/libeap/src/utils/wpa_debug.c index 6f6fc69..61c0d5c 100644 --- a/libeap/src/utils/wpa_debug.c +++ b/libeap/src/utils/wpa_debug.c @@ -1,15 +1,9 @@ /* * wpa_supplicant/hostapd / Debug prints - * Copyright (c) 2002-2007, Jouni Malinen + * Copyright (c) 2002-2013, Jouni Malinen * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. + * This software may be distributed under the terms of the BSD license. + * See README for more details. */ #include "includes.h" @@ -22,19 +16,55 @@ static int wpa_debug_syslog = 0; #endif /* CONFIG_DEBUG_SYSLOG */ +#ifdef CONFIG_DEBUG_LINUX_TRACING +#include +#include +#include +#include +#include + +static FILE *wpa_debug_tracing_file = NULL; + +#define WPAS_TRACE_PFX "wpas <%d>: " +#endif /* CONFIG_DEBUG_LINUX_TRACING */ + -#ifdef CONFIG_DEBUG_FILE -static FILE *out_file = NULL; -#endif /* CONFIG_DEBUG_FILE */ int wpa_debug_level = MSG_INFO; int wpa_debug_show_keys = 0; int wpa_debug_timestamp = 0; +#ifdef CONFIG_ANDROID_LOG + +#include + +#ifndef ANDROID_LOG_NAME +#define ANDROID_LOG_NAME "wpa_supplicant" +#endif /* ANDROID_LOG_NAME */ + +static int wpa_to_android_level(int level) +{ + if (level == MSG_ERROR) + return ANDROID_LOG_ERROR; + if (level == MSG_WARNING) + return ANDROID_LOG_WARN; + if (level == MSG_INFO) + return ANDROID_LOG_INFO; + return ANDROID_LOG_DEBUG; +} + +#endif /* CONFIG_ANDROID_LOG */ + #ifndef CONFIG_NO_STDOUT_DEBUG +#ifdef CONFIG_DEBUG_FILE +static FILE *out_file = NULL; +#endif /* CONFIG_DEBUG_FILE */ + + void wpa_debug_print_timestamp(void) { +#ifndef CONFIG_ANDROID_LOG struct os_time tv; if (!wpa_debug_timestamp) @@ -48,13 +78,18 @@ void wpa_debug_print_timestamp(void) } else #endif /* CONFIG_DEBUG_FILE */ printf("%ld.%06u: ", (long) tv.sec, (unsigned int) tv.usec); +#endif /* CONFIG_ANDROID_LOG */ } #ifdef CONFIG_DEBUG_SYSLOG +#ifndef LOG_HOSTAPD +#define LOG_HOSTAPD LOG_DAEMON +#endif /* LOG_HOSTAPD */ + void wpa_debug_open_syslog(void) { - openlog("wpa_supplicant", LOG_PID | LOG_NDELAY, LOG_DAEMON); + openlog("wpa_supplicant", LOG_PID | LOG_NDELAY, LOG_HOSTAPD); wpa_debug_syslog++; } @@ -84,6 +119,77 @@ static int syslog_priority(int level) #endif /* CONFIG_DEBUG_SYSLOG */ +#ifdef CONFIG_DEBUG_LINUX_TRACING + +int wpa_debug_open_linux_tracing(void) +{ + int mounts, trace_fd; + char buf[4096] = {}; + ssize_t buflen; + char *line, *tmp1, *path = NULL; + + mounts = open("/proc/mounts", O_RDONLY); + if (mounts < 0) { + printf("no /proc/mounts\n"); + return -1; + } + + buflen = read(mounts, buf, sizeof(buf) - 1); + close(mounts); + if (buflen < 0) { + printf("failed to read /proc/mounts\n"); + return -1; + } + + line = strtok_r(buf, "\n", &tmp1); + while (line) { + char *tmp2, *tmp_path, *fstype; + /* " ..." */ + strtok_r(line, " ", &tmp2); + tmp_path = strtok_r(NULL, " ", &tmp2); + fstype = strtok_r(NULL, " ", &tmp2); + if (strcmp(fstype, "debugfs") == 0) { + path = tmp_path; + break; + } + + line = strtok_r(NULL, "\n", &tmp1); + } + + if (path == NULL) { + printf("debugfs mountpoint not found\n"); + return -1; + } + + snprintf(buf, sizeof(buf) - 1, "%s/tracing/trace_marker", path); + + trace_fd = open(buf, O_WRONLY); + if (trace_fd < 0) { + printf("failed to open trace_marker file\n"); + return -1; + } + wpa_debug_tracing_file = fdopen(trace_fd, "w"); + if (wpa_debug_tracing_file == NULL) { + close(trace_fd); + printf("failed to fdopen()\n"); + return -1; + } + + return 0; +} + + +void wpa_debug_close_linux_tracing(void) +{ + if (wpa_debug_tracing_file == NULL) + return; + fclose(wpa_debug_tracing_file); + wpa_debug_tracing_file = NULL; +} + +#endif /* CONFIG_DEBUG_LINUX_TRACING */ + + /** * wpa_printf - conditional printf * @level: priority level (MSG_*) of the message @@ -101,6 +207,10 @@ void wpa_printf(int level, const char *fmt, ...) va_start(ap, fmt); if (level >= wpa_debug_level) { +#ifdef CONFIG_ANDROID_LOG + __android_log_vprint(wpa_to_android_level(level), + ANDROID_LOG_NAME, fmt, ap); +#else /* CONFIG_ANDROID_LOG */ #ifdef CONFIG_DEBUG_SYSLOG if (wpa_debug_syslog) { vsyslog(syslog_priority(level), fmt, ap); @@ -121,8 +231,20 @@ void wpa_printf(int level, const char *fmt, ...) #ifdef CONFIG_DEBUG_SYSLOG } #endif /* CONFIG_DEBUG_SYSLOG */ +#endif /* CONFIG_ANDROID_LOG */ } va_end(ap); + +#ifdef CONFIG_DEBUG_LINUX_TRACING + if (wpa_debug_tracing_file != NULL) { + va_start(ap, fmt); + fprintf(wpa_debug_tracing_file, WPAS_TRACE_PFX, level); + vfprintf(wpa_debug_tracing_file, fmt, ap); + fprintf(wpa_debug_tracing_file, "\n"); + fflush(wpa_debug_tracing_file); + va_end(ap); + } +#endif /* CONFIG_DEBUG_LINUX_TRACING */ } @@ -130,8 +252,97 @@ static void _wpa_hexdump(int level, const char *title, const u8 *buf, size_t len, int show) { size_t i; + +#ifdef CONFIG_DEBUG_LINUX_TRACING + if (wpa_debug_tracing_file != NULL) { + fprintf(wpa_debug_tracing_file, + WPAS_TRACE_PFX "%s - hexdump(len=%lu):", + level, title, (unsigned long) len); + if (buf == NULL) { + fprintf(wpa_debug_tracing_file, " [NULL]\n"); + } else if (!show) { + fprintf(wpa_debug_tracing_file, " [REMOVED]\n"); + } else { + for (i = 0; i < len; i++) + fprintf(wpa_debug_tracing_file, + " %02x", buf[i]); + } + fflush(wpa_debug_tracing_file); + } +#endif /* CONFIG_DEBUG_LINUX_TRACING */ + if (level < wpa_debug_level) return; +#ifdef CONFIG_ANDROID_LOG + { + const char *display; + char *strbuf = NULL; + size_t slen = len; + if (buf == NULL) { + display = " [NULL]"; + } else if (len == 0) { + display = ""; + } else if (show && len) { + /* Limit debug message length for Android log */ + if (slen > 32) + slen = 32; + strbuf = os_malloc(1 + 3 * slen); + if (strbuf == NULL) { + wpa_printf(MSG_ERROR, "wpa_hexdump: Failed to " + "allocate message buffer"); + return; + } + + for (i = 0; i < slen; i++) + os_snprintf(&strbuf[i * 3], 4, " %02x", + buf[i]); + + display = strbuf; + } else { + display = " [REMOVED]"; + } + + __android_log_print(wpa_to_android_level(level), + ANDROID_LOG_NAME, + "%s - hexdump(len=%lu):%s%s", + title, (long unsigned int) len, display, + len > slen ? " ..." : ""); + bin_clear_free(strbuf, 1 + 3 * slen); + return; + } +#else /* CONFIG_ANDROID_LOG */ +#ifdef CONFIG_DEBUG_SYSLOG + if (wpa_debug_syslog) { + const char *display; + char *strbuf = NULL; + + if (buf == NULL) { + display = " [NULL]"; + } else if (len == 0) { + display = ""; + } else if (show && len) { + strbuf = os_malloc(1 + 3 * len); + if (strbuf == NULL) { + wpa_printf(MSG_ERROR, "wpa_hexdump: Failed to " + "allocate message buffer"); + return; + } + + for (i = 0; i < len; i++) + os_snprintf(&strbuf[i * 3], 4, " %02x", + buf[i]); + + display = strbuf; + } else { + display = " [REMOVED]"; + } + + syslog(syslog_priority(level), "%s - hexdump(len=%lu):%s", + title, (unsigned long) len, display); + bin_clear_free(strbuf, 1 + 3 * len); + return; + } +#endif /* CONFIG_DEBUG_SYSLOG */ wpa_debug_print_timestamp(); #ifdef CONFIG_DEBUG_FILE if (out_file) { @@ -161,29 +372,52 @@ static void _wpa_hexdump(int level, const char *title, const u8 *buf, #ifdef CONFIG_DEBUG_FILE } #endif /* CONFIG_DEBUG_FILE */ +#endif /* CONFIG_ANDROID_LOG */ } -void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len) +void wpa_hexdump(int level, const char *title, const void *buf, size_t len) { _wpa_hexdump(level, title, buf, len, 1); } -void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len) +void wpa_hexdump_key(int level, const char *title, const void *buf, size_t len) { _wpa_hexdump(level, title, buf, len, wpa_debug_show_keys); } -static void _wpa_hexdump_ascii(int level, const char *title, const u8 *buf, +static void _wpa_hexdump_ascii(int level, const char *title, const void *buf, size_t len, int show) { size_t i, llen; const u8 *pos = buf; const size_t line_len = 16; +#ifdef CONFIG_DEBUG_LINUX_TRACING + if (wpa_debug_tracing_file != NULL) { + fprintf(wpa_debug_tracing_file, + WPAS_TRACE_PFX "%s - hexdump_ascii(len=%lu):", + level, title, (unsigned long) len); + if (buf == NULL) { + fprintf(wpa_debug_tracing_file, " [NULL]\n"); + } else if (!show) { + fprintf(wpa_debug_tracing_file, " [REMOVED]\n"); + } else { + /* can do ascii processing in userspace */ + for (i = 0; i < len; i++) + fprintf(wpa_debug_tracing_file, + " %02x", pos[i]); + } + fflush(wpa_debug_tracing_file); + } +#endif /* CONFIG_DEBUG_LINUX_TRACING */ + if (level < wpa_debug_level) return; +#ifdef CONFIG_ANDROID_LOG + _wpa_hexdump(level, title, buf, len, show); +#else /* CONFIG_ANDROID_LOG */ wpa_debug_print_timestamp(); #ifdef CONFIG_DEBUG_FILE if (out_file) { @@ -257,27 +491,61 @@ static void _wpa_hexdump_ascii(int level, const char *title, const u8 *buf, #ifdef CONFIG_DEBUG_FILE } #endif /* CONFIG_DEBUG_FILE */ +#endif /* CONFIG_ANDROID_LOG */ } -void wpa_hexdump_ascii(int level, const char *title, const u8 *buf, size_t len) +void wpa_hexdump_ascii(int level, const char *title, const void *buf, + size_t len) { _wpa_hexdump_ascii(level, title, buf, len, 1); } -void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf, +void wpa_hexdump_ascii_key(int level, const char *title, const void *buf, size_t len) { _wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys); } +#ifdef CONFIG_DEBUG_FILE +static char *last_path = NULL; +#endif /* CONFIG_DEBUG_FILE */ + +int wpa_debug_reopen_file(void) +{ +#ifdef CONFIG_DEBUG_FILE + int rv; + if (last_path) { + char *tmp = os_strdup(last_path); + wpa_debug_close_file(); + rv = wpa_debug_open_file(tmp); + os_free(tmp); + } else { + wpa_printf(MSG_ERROR, "Last-path was not set, cannot " + "re-open log file."); + rv = -1; + } + return rv; +#else /* CONFIG_DEBUG_FILE */ + return 0; +#endif /* CONFIG_DEBUG_FILE */ +} + + int wpa_debug_open_file(const char *path) { #ifdef CONFIG_DEBUG_FILE if (!path) return 0; + + if (last_path == NULL || os_strcmp(last_path, path) != 0) { + /* Save our path to enable re-open */ + os_free(last_path); + last_path = os_strdup(path); + } + out_file = fopen(path, "a"); if (out_file == NULL) { wpa_printf(MSG_ERROR, "wpa_debug_open_file: Failed to open " @@ -287,6 +555,8 @@ int wpa_debug_open_file(const char *path) #ifndef _WIN32 setvbuf(out_file, NULL, _IOLBF, 0); #endif /* _WIN32 */ +#else /* CONFIG_DEBUG_FILE */ + (void)path; #endif /* CONFIG_DEBUG_FILE */ return 0; } @@ -299,9 +569,19 @@ void wpa_debug_close_file(void) return; fclose(out_file); out_file = NULL; + os_free(last_path); + last_path = NULL; #endif /* CONFIG_DEBUG_FILE */ } + +void wpa_debug_setup_stdout(void) +{ +#ifndef _WIN32 + setvbuf(stdout, NULL, _IOLBF, 0); +#endif /* _WIN32 */ +} + #endif /* CONFIG_NO_STDOUT_DEBUG */ @@ -314,12 +594,25 @@ void wpa_msg_register_cb(wpa_msg_cb_func func) } +static wpa_msg_get_ifname_func wpa_msg_ifname_cb = NULL; + +void wpa_msg_register_ifname_cb(wpa_msg_get_ifname_func func) +{ + wpa_msg_ifname_cb = func; +} + + void wpa_msg(void *ctx, int level, const char *fmt, ...) { va_list ap; char *buf; - const int buflen = 2048; + int buflen; int len; + char prefix[130]; + + va_start(ap, fmt); + buflen = vsnprintf(NULL, 0, fmt, ap) + 1; + va_end(ap); buf = os_malloc(buflen); if (buf == NULL) { @@ -328,12 +621,22 @@ void wpa_msg(void *ctx, int level, const char *fmt, ...) return; } va_start(ap, fmt); + prefix[0] = '\0'; + if (wpa_msg_ifname_cb) { + const char *ifname = wpa_msg_ifname_cb(ctx); + if (ifname) { + int res = os_snprintf(prefix, sizeof(prefix), "%s: ", + ifname); + if (os_snprintf_error(sizeof(prefix), res)) + prefix[0] = '\0'; + } + } len = vsnprintf(buf, buflen, fmt, ap); va_end(ap); - wpa_printf(level, "%s", buf); + wpa_printf(level, "%s%s", prefix, buf); if (wpa_msg_cb) - wpa_msg_cb(ctx, level, buf, len); - os_free(buf); + wpa_msg_cb(ctx, level, WPA_MSG_PER_INTERFACE, buf, len); + bin_clear_free(buf, buflen); } @@ -341,12 +644,16 @@ void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...) { va_list ap; char *buf; - const int buflen = 2048; + int buflen; int len; if (!wpa_msg_cb) return; + va_start(ap, fmt); + buflen = vsnprintf(NULL, 0, fmt, ap) + 1; + va_end(ap); + buf = os_malloc(buflen); if (buf == NULL) { wpa_printf(MSG_ERROR, "wpa_msg_ctrl: Failed to allocate " @@ -356,9 +663,119 @@ void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...) va_start(ap, fmt); len = vsnprintf(buf, buflen, fmt, ap); va_end(ap); - wpa_msg_cb(ctx, level, buf, len); + wpa_msg_cb(ctx, level, WPA_MSG_PER_INTERFACE, buf, len); + bin_clear_free(buf, buflen); +} + + +void wpa_msg_global(void *ctx, int level, const char *fmt, ...) +{ + va_list ap; + char *buf; + int buflen; + int len; + + va_start(ap, fmt); + buflen = vsnprintf(NULL, 0, fmt, ap) + 1; + va_end(ap); + + buf = os_malloc(buflen); + if (buf == NULL) { + wpa_printf(MSG_ERROR, "wpa_msg_global: Failed to allocate " + "message buffer"); + return; + } + va_start(ap, fmt); + len = vsnprintf(buf, buflen, fmt, ap); + va_end(ap); + wpa_printf(level, "%s", buf); + if (wpa_msg_cb) + wpa_msg_cb(ctx, level, WPA_MSG_GLOBAL, buf, len); + bin_clear_free(buf, buflen); +} + + +void wpa_msg_global_ctrl(void *ctx, int level, const char *fmt, ...) +{ + va_list ap; + char *buf; + int buflen; + int len; + + if (!wpa_msg_cb) + return; + + va_start(ap, fmt); + buflen = vsnprintf(NULL, 0, fmt, ap) + 1; + va_end(ap); + + buf = os_malloc(buflen); + if (buf == NULL) { + wpa_printf(MSG_ERROR, + "wpa_msg_global_ctrl: Failed to allocate message buffer"); + return; + } + va_start(ap, fmt); + len = vsnprintf(buf, buflen, fmt, ap); + va_end(ap); + wpa_msg_cb(ctx, level, WPA_MSG_GLOBAL, buf, len); + bin_clear_free(buf, buflen); +} + + +void wpa_msg_no_global(void *ctx, int level, const char *fmt, ...) +{ + va_list ap; + char *buf; + int buflen; + int len; + + va_start(ap, fmt); + buflen = vsnprintf(NULL, 0, fmt, ap) + 1; + va_end(ap); + + buf = os_malloc(buflen); + if (buf == NULL) { + wpa_printf(MSG_ERROR, "wpa_msg_no_global: Failed to allocate " + "message buffer"); + return; + } + va_start(ap, fmt); + len = vsnprintf(buf, buflen, fmt, ap); + va_end(ap); + wpa_printf(level, "%s", buf); + if (wpa_msg_cb) + wpa_msg_cb(ctx, level, WPA_MSG_NO_GLOBAL, buf, len); + bin_clear_free(buf, buflen); +} + + +void wpa_msg_global_only(void *ctx, int level, const char *fmt, ...) +{ + va_list ap; + char *buf; + int buflen; + int len; + + va_start(ap, fmt); + buflen = vsnprintf(NULL, 0, fmt, ap) + 1; + va_end(ap); + + buf = os_malloc(buflen); + if (buf == NULL) { + wpa_printf(MSG_ERROR, "%s: Failed to allocate message buffer", + __func__); + return; + } + va_start(ap, fmt); + len = vsnprintf(buf, buflen, fmt, ap); + va_end(ap); + wpa_printf(level, "%s", buf); + if (wpa_msg_cb) + wpa_msg_cb(ctx, level, WPA_MSG_ONLY_GLOBAL, buf, len); os_free(buf); } + #endif /* CONFIG_NO_WPA_MSG */ @@ -376,9 +793,13 @@ void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level, { va_list ap; char *buf; - const int buflen = 2048; + int buflen; int len; + va_start(ap, fmt); + buflen = vsnprintf(NULL, 0, fmt, ap) + 1; + va_end(ap); + buf = os_malloc(buflen); if (buf == NULL) { wpa_printf(MSG_ERROR, "hostapd_logger: Failed to allocate " @@ -395,6 +816,45 @@ void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level, MAC2STR(addr), buf); else wpa_printf(MSG_DEBUG, "hostapd_logger: %s", buf); - os_free(buf); + bin_clear_free(buf, buflen); } #endif /* CONFIG_NO_HOSTAPD_LOGGER */ + + +const char * debug_level_str(int level) +{ + switch (level) { + case MSG_EXCESSIVE: + return "EXCESSIVE"; + case MSG_MSGDUMP: + return "MSGDUMP"; + case MSG_DEBUG: + return "DEBUG"; + case MSG_INFO: + return "INFO"; + case MSG_WARNING: + return "WARNING"; + case MSG_ERROR: + return "ERROR"; + default: + return "?"; + } +} + + +int str_to_debug_level(const char *s) +{ + if (os_strcasecmp(s, "EXCESSIVE") == 0) + return MSG_EXCESSIVE; + if (os_strcasecmp(s, "MSGDUMP") == 0) + return MSG_MSGDUMP; + if (os_strcasecmp(s, "DEBUG") == 0) + return MSG_DEBUG; + if (os_strcasecmp(s, "INFO") == 0) + return MSG_INFO; + if (os_strcasecmp(s, "WARNING") == 0) + return MSG_WARNING; + if (os_strcasecmp(s, "ERROR") == 0) + return MSG_ERROR; + return -1; +}