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 20#ifdef CONFIG_DEBUG_FILE 21static FILE *out_file = NULL; 22#endif /* CONFIG_DEBUG_FILE */ 23#ifdef CONFIG_ANDROID_LOG 24int wpa_debug_level = MSG_WARNING; 25#else 26int wpa_debug_level = MSG_INFO; 27#endif 28int wpa_debug_show_keys = 0; 29int wpa_debug_timestamp = 0; 30 31 32#ifdef CONFIG_ANDROID_LOG 33 34#include <android/log.h> 35 36void 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 59void 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 */ 88void 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 111static 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 148void 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 154void 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 160static 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 245void 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 251void 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 258int 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 277void 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 292static wpa_msg_cb_func wpa_msg_cb = NULL; 293 294void wpa_msg_register_cb(wpa_msg_cb_func func) 295{ 296 wpa_msg_cb = func; 297} 298 299 300void 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 323void 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 349static hostapd_logger_cb_func hostapd_logger_cb = NULL; 350 351void hostapd_logger_register_cb(hostapd_logger_cb_func func) 352{ 353 hostapd_logger_cb = func; 354} 355 356 357void 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