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