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