1 /* 2 * wpa_supplicant/hostapd / Debug prints 3 * Copyright (c) 2002-2013, 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 #ifdef CONFIG_DEBUG_LINUX_TRACING 20 #include <sys/types.h> 21 #include <sys/stat.h> 22 #include <fcntl.h> 23 #include <string.h> 24 #include <stdio.h> 25 26 static FILE *wpa_debug_tracing_file = NULL; 27 28 #define WPAS_TRACE_PFX "wpas <%d>: " 29 #endif /* CONFIG_DEBUG_LINUX_TRACING */ 30 31 32 int wpa_debug_level = MSG_INFO; 33 int wpa_debug_show_keys = 0; 34 int wpa_debug_timestamp = 0; 35 36 37 #ifdef CONFIG_ANDROID_LOG 38 39 #include <android/log.h> 40 41 #ifndef ANDROID_LOG_NAME 42 #define ANDROID_LOG_NAME "wpa_supplicant" 43 #endif /* ANDROID_LOG_NAME */ 44 45 static int wpa_to_android_level(int level) 46 { 47 if (level == MSG_ERROR) 48 return ANDROID_LOG_ERROR; 49 if (level == MSG_WARNING) 50 return ANDROID_LOG_WARN; 51 if (level == MSG_INFO) 52 return ANDROID_LOG_INFO; 53 return ANDROID_LOG_DEBUG; 54 } 55 56 #endif /* CONFIG_ANDROID_LOG */ 57 58 #ifndef CONFIG_NO_STDOUT_DEBUG 59 60 #ifdef CONFIG_DEBUG_FILE 61 static FILE *out_file = NULL; 62 #endif /* CONFIG_DEBUG_FILE */ 63 64 65 void wpa_debug_print_timestamp(void) 66 { 67 #ifndef CONFIG_ANDROID_LOG 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 #endif /* CONFIG_ANDROID_LOG */ 82 } 83 84 85 #ifdef CONFIG_DEBUG_SYSLOG 86 #ifndef LOG_HOSTAPD 87 #define LOG_HOSTAPD LOG_DAEMON 88 #endif /* LOG_HOSTAPD */ 89 90 void wpa_debug_open_syslog(void) 91 { 92 openlog("wpa_supplicant", LOG_PID | LOG_NDELAY, LOG_HOSTAPD); 93 wpa_debug_syslog++; 94 } 95 96 97 void wpa_debug_close_syslog(void) 98 { 99 if (wpa_debug_syslog) 100 closelog(); 101 } 102 103 104 static int syslog_priority(int level) 105 { 106 switch (level) { 107 case MSG_MSGDUMP: 108 case MSG_DEBUG: 109 return LOG_DEBUG; 110 case MSG_INFO: 111 return LOG_NOTICE; 112 case MSG_WARNING: 113 return LOG_WARNING; 114 case MSG_ERROR: 115 return LOG_ERR; 116 } 117 return LOG_INFO; 118 } 119 #endif /* CONFIG_DEBUG_SYSLOG */ 120 121 122 #ifdef CONFIG_DEBUG_LINUX_TRACING 123 124 int wpa_debug_open_linux_tracing(void) 125 { 126 int mounts, trace_fd; 127 char buf[4096] = {}; 128 ssize_t buflen; 129 char *line, *tmp1, *path = NULL; 130 131 mounts = open("/proc/mounts", O_RDONLY); 132 if (mounts < 0) { 133 printf("no /proc/mounts\n"); 134 return -1; 135 } 136 137 buflen = read(mounts, buf, sizeof(buf) - 1); 138 close(mounts); 139 if (buflen < 0) { 140 printf("failed to read /proc/mounts\n"); 141 return -1; 142 } 143 144 line = strtok_r(buf, "\n", &tmp1); 145 while (line) { 146 char *tmp2, *tmp_path, *fstype; 147 /* "<dev> <mountpoint> <fs type> ..." */ 148 strtok_r(line, " ", &tmp2); 149 tmp_path = strtok_r(NULL, " ", &tmp2); 150 fstype = strtok_r(NULL, " ", &tmp2); 151 if (fstype && strcmp(fstype, "debugfs") == 0) { 152 path = tmp_path; 153 break; 154 } 155 156 line = strtok_r(NULL, "\n", &tmp1); 157 } 158 159 if (path == NULL) { 160 printf("debugfs mountpoint not found\n"); 161 return -1; 162 } 163 164 snprintf(buf, sizeof(buf) - 1, "%s/tracing/trace_marker", path); 165 166 trace_fd = open(buf, O_WRONLY); 167 if (trace_fd < 0) { 168 printf("failed to open trace_marker file\n"); 169 return -1; 170 } 171 wpa_debug_tracing_file = fdopen(trace_fd, "w"); 172 if (wpa_debug_tracing_file == NULL) { 173 close(trace_fd); 174 printf("failed to fdopen()\n"); 175 return -1; 176 } 177 178 return 0; 179 } 180 181 182 void wpa_debug_close_linux_tracing(void) 183 { 184 if (wpa_debug_tracing_file == NULL) 185 return; 186 fclose(wpa_debug_tracing_file); 187 wpa_debug_tracing_file = NULL; 188 } 189 190 #endif /* CONFIG_DEBUG_LINUX_TRACING */ 191 192 193 /** 194 * wpa_printf - conditional printf 195 * @level: priority level (MSG_*) of the message 196 * @fmt: printf format string, followed by optional arguments 197 * 198 * This function is used to print conditional debugging and error messages. The 199 * output may be directed to stdout, stderr, and/or syslog based on 200 * configuration. 201 * 202 * Note: New line '\n' is added to the end of the text when printing to stdout. 203 */ 204 void wpa_printf(int level, const char *fmt, ...) 205 { 206 va_list ap; 207 208 va_start(ap, fmt); 209 if (level >= wpa_debug_level) { 210 #ifdef CONFIG_ANDROID_LOG 211 __android_log_vprint(wpa_to_android_level(level), 212 ANDROID_LOG_NAME, fmt, ap); 213 #else /* CONFIG_ANDROID_LOG */ 214 #ifdef CONFIG_DEBUG_SYSLOG 215 if (wpa_debug_syslog) { 216 vsyslog(syslog_priority(level), fmt, ap); 217 } else { 218 #endif /* CONFIG_DEBUG_SYSLOG */ 219 wpa_debug_print_timestamp(); 220 #ifdef CONFIG_DEBUG_FILE 221 if (out_file) { 222 vfprintf(out_file, fmt, ap); 223 fprintf(out_file, "\n"); 224 } else { 225 #endif /* CONFIG_DEBUG_FILE */ 226 vprintf(fmt, ap); 227 printf("\n"); 228 #ifdef CONFIG_DEBUG_FILE 229 } 230 #endif /* CONFIG_DEBUG_FILE */ 231 #ifdef CONFIG_DEBUG_SYSLOG 232 } 233 #endif /* CONFIG_DEBUG_SYSLOG */ 234 #endif /* CONFIG_ANDROID_LOG */ 235 } 236 va_end(ap); 237 238 #ifdef CONFIG_DEBUG_LINUX_TRACING 239 if (wpa_debug_tracing_file != NULL) { 240 va_start(ap, fmt); 241 fprintf(wpa_debug_tracing_file, WPAS_TRACE_PFX, level); 242 vfprintf(wpa_debug_tracing_file, fmt, ap); 243 fprintf(wpa_debug_tracing_file, "\n"); 244 fflush(wpa_debug_tracing_file); 245 va_end(ap); 246 } 247 #endif /* CONFIG_DEBUG_LINUX_TRACING */ 248 } 249 250 251 static void _wpa_hexdump(int level, const char *title, const u8 *buf, 252 size_t len, int show) 253 { 254 size_t i; 255 256 #ifdef CONFIG_DEBUG_LINUX_TRACING 257 if (wpa_debug_tracing_file != NULL) { 258 fprintf(wpa_debug_tracing_file, 259 WPAS_TRACE_PFX "%s - hexdump(len=%lu):", 260 level, title, (unsigned long) len); 261 if (buf == NULL) { 262 fprintf(wpa_debug_tracing_file, " [NULL]\n"); 263 } else if (!show) { 264 fprintf(wpa_debug_tracing_file, " [REMOVED]\n"); 265 } else { 266 for (i = 0; i < len; i++) 267 fprintf(wpa_debug_tracing_file, 268 " %02x", buf[i]); 269 } 270 fflush(wpa_debug_tracing_file); 271 } 272 #endif /* CONFIG_DEBUG_LINUX_TRACING */ 273 274 if (level < wpa_debug_level) 275 return; 276 #ifdef CONFIG_ANDROID_LOG 277 { 278 const char *display; 279 char *strbuf = NULL; 280 size_t slen = len; 281 if (buf == NULL) { 282 display = " [NULL]"; 283 } else if (len == 0) { 284 display = ""; 285 } else if (show && len) { 286 /* Limit debug message length for Android log */ 287 if (slen > 32) 288 slen = 32; 289 strbuf = os_malloc(1 + 3 * slen); 290 if (strbuf == NULL) { 291 wpa_printf(MSG_ERROR, "wpa_hexdump: Failed to " 292 "allocate message buffer"); 293 return; 294 } 295 296 for (i = 0; i < slen; i++) 297 os_snprintf(&strbuf[i * 3], 4, " %02x", 298 buf[i]); 299 300 display = strbuf; 301 } else { 302 display = " [REMOVED]"; 303 } 304 305 __android_log_print(wpa_to_android_level(level), 306 ANDROID_LOG_NAME, 307 "%s - hexdump(len=%lu):%s%s", 308 title, (long unsigned int) len, display, 309 len > slen ? " ..." : ""); 310 bin_clear_free(strbuf, 1 + 3 * slen); 311 return; 312 } 313 #else /* CONFIG_ANDROID_LOG */ 314 #ifdef CONFIG_DEBUG_SYSLOG 315 if (wpa_debug_syslog) { 316 const char *display; 317 char *strbuf = NULL; 318 319 if (buf == NULL) { 320 display = " [NULL]"; 321 } else if (len == 0) { 322 display = ""; 323 } else if (show && len) { 324 strbuf = os_malloc(1 + 3 * len); 325 if (strbuf == NULL) { 326 wpa_printf(MSG_ERROR, "wpa_hexdump: Failed to " 327 "allocate message buffer"); 328 return; 329 } 330 331 for (i = 0; i < len; i++) 332 os_snprintf(&strbuf[i * 3], 4, " %02x", 333 buf[i]); 334 335 display = strbuf; 336 } else { 337 display = " [REMOVED]"; 338 } 339 340 syslog(syslog_priority(level), "%s - hexdump(len=%lu):%s", 341 title, (unsigned long) len, display); 342 bin_clear_free(strbuf, 1 + 3 * len); 343 return; 344 } 345 #endif /* CONFIG_DEBUG_SYSLOG */ 346 wpa_debug_print_timestamp(); 347 #ifdef CONFIG_DEBUG_FILE 348 if (out_file) { 349 fprintf(out_file, "%s - hexdump(len=%lu):", 350 title, (unsigned long) len); 351 if (buf == NULL) { 352 fprintf(out_file, " [NULL]"); 353 } else if (show) { 354 for (i = 0; i < len; i++) 355 fprintf(out_file, " %02x", buf[i]); 356 } else { 357 fprintf(out_file, " [REMOVED]"); 358 } 359 fprintf(out_file, "\n"); 360 } else { 361 #endif /* CONFIG_DEBUG_FILE */ 362 printf("%s - hexdump(len=%lu):", title, (unsigned long) len); 363 if (buf == NULL) { 364 printf(" [NULL]"); 365 } else if (show) { 366 for (i = 0; i < len; i++) 367 printf(" %02x", buf[i]); 368 } else { 369 printf(" [REMOVED]"); 370 } 371 printf("\n"); 372 #ifdef CONFIG_DEBUG_FILE 373 } 374 #endif /* CONFIG_DEBUG_FILE */ 375 #endif /* CONFIG_ANDROID_LOG */ 376 } 377 378 void wpa_hexdump(int level, const char *title, const void *buf, size_t len) 379 { 380 _wpa_hexdump(level, title, buf, len, 1); 381 } 382 383 384 void wpa_hexdump_key(int level, const char *title, const void *buf, size_t len) 385 { 386 _wpa_hexdump(level, title, buf, len, wpa_debug_show_keys); 387 } 388 389 390 static void _wpa_hexdump_ascii(int level, const char *title, const void *buf, 391 size_t len, int show) 392 { 393 size_t i, llen; 394 const u8 *pos = buf; 395 const size_t line_len = 16; 396 397 #ifdef CONFIG_DEBUG_LINUX_TRACING 398 if (wpa_debug_tracing_file != NULL) { 399 fprintf(wpa_debug_tracing_file, 400 WPAS_TRACE_PFX "%s - hexdump_ascii(len=%lu):", 401 level, title, (unsigned long) len); 402 if (buf == NULL) { 403 fprintf(wpa_debug_tracing_file, " [NULL]\n"); 404 } else if (!show) { 405 fprintf(wpa_debug_tracing_file, " [REMOVED]\n"); 406 } else { 407 /* can do ascii processing in userspace */ 408 for (i = 0; i < len; i++) 409 fprintf(wpa_debug_tracing_file, 410 " %02x", pos[i]); 411 } 412 fflush(wpa_debug_tracing_file); 413 } 414 #endif /* CONFIG_DEBUG_LINUX_TRACING */ 415 416 if (level < wpa_debug_level) 417 return; 418 #ifdef CONFIG_ANDROID_LOG 419 _wpa_hexdump(level, title, buf, len, show); 420 #else /* CONFIG_ANDROID_LOG */ 421 wpa_debug_print_timestamp(); 422 #ifdef CONFIG_DEBUG_FILE 423 if (out_file) { 424 if (!show) { 425 fprintf(out_file, 426 "%s - hexdump_ascii(len=%lu): [REMOVED]\n", 427 title, (unsigned long) len); 428 return; 429 } 430 if (buf == NULL) { 431 fprintf(out_file, 432 "%s - hexdump_ascii(len=%lu): [NULL]\n", 433 title, (unsigned long) len); 434 return; 435 } 436 fprintf(out_file, "%s - hexdump_ascii(len=%lu):\n", 437 title, (unsigned long) len); 438 while (len) { 439 llen = len > line_len ? line_len : len; 440 fprintf(out_file, " "); 441 for (i = 0; i < llen; i++) 442 fprintf(out_file, " %02x", pos[i]); 443 for (i = llen; i < line_len; i++) 444 fprintf(out_file, " "); 445 fprintf(out_file, " "); 446 for (i = 0; i < llen; i++) { 447 if (isprint(pos[i])) 448 fprintf(out_file, "%c", pos[i]); 449 else 450 fprintf(out_file, "_"); 451 } 452 for (i = llen; i < line_len; i++) 453 fprintf(out_file, " "); 454 fprintf(out_file, "\n"); 455 pos += llen; 456 len -= llen; 457 } 458 } else { 459 #endif /* CONFIG_DEBUG_FILE */ 460 if (!show) { 461 printf("%s - hexdump_ascii(len=%lu): [REMOVED]\n", 462 title, (unsigned long) len); 463 return; 464 } 465 if (buf == NULL) { 466 printf("%s - hexdump_ascii(len=%lu): [NULL]\n", 467 title, (unsigned long) len); 468 return; 469 } 470 printf("%s - hexdump_ascii(len=%lu):\n", title, (unsigned long) len); 471 while (len) { 472 llen = len > line_len ? line_len : len; 473 printf(" "); 474 for (i = 0; i < llen; i++) 475 printf(" %02x", pos[i]); 476 for (i = llen; i < line_len; i++) 477 printf(" "); 478 printf(" "); 479 for (i = 0; i < llen; i++) { 480 if (isprint(pos[i])) 481 printf("%c", pos[i]); 482 else 483 printf("_"); 484 } 485 for (i = llen; i < line_len; i++) 486 printf(" "); 487 printf("\n"); 488 pos += llen; 489 len -= llen; 490 } 491 #ifdef CONFIG_DEBUG_FILE 492 } 493 #endif /* CONFIG_DEBUG_FILE */ 494 #endif /* CONFIG_ANDROID_LOG */ 495 } 496 497 498 void wpa_hexdump_ascii(int level, const char *title, const void *buf, 499 size_t len) 500 { 501 _wpa_hexdump_ascii(level, title, buf, len, 1); 502 } 503 504 505 void wpa_hexdump_ascii_key(int level, const char *title, const void *buf, 506 size_t len) 507 { 508 _wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys); 509 } 510 511 512 #ifdef CONFIG_DEBUG_FILE 513 static char *last_path = NULL; 514 #endif /* CONFIG_DEBUG_FILE */ 515 516 int wpa_debug_reopen_file(void) 517 { 518 #ifdef CONFIG_DEBUG_FILE 519 int rv; 520 char *tmp; 521 522 if (!last_path) 523 return 0; /* logfile not used */ 524 525 tmp = os_strdup(last_path); 526 if (!tmp) 527 return -1; 528 529 wpa_debug_close_file(); 530 rv = wpa_debug_open_file(tmp); 531 os_free(tmp); 532 return rv; 533 #else /* CONFIG_DEBUG_FILE */ 534 return 0; 535 #endif /* CONFIG_DEBUG_FILE */ 536 } 537 538 539 int wpa_debug_open_file(const char *path) 540 { 541 #ifdef CONFIG_DEBUG_FILE 542 if (!path) 543 return 0; 544 545 if (last_path == NULL || os_strcmp(last_path, path) != 0) { 546 /* Save our path to enable re-open */ 547 os_free(last_path); 548 last_path = os_strdup(path); 549 } 550 551 out_file = fopen(path, "a"); 552 if (out_file == NULL) { 553 wpa_printf(MSG_ERROR, "wpa_debug_open_file: Failed to open " 554 "output file, using standard output"); 555 return -1; 556 } 557 #ifndef _WIN32 558 setvbuf(out_file, NULL, _IOLBF, 0); 559 #endif /* _WIN32 */ 560 #else /* CONFIG_DEBUG_FILE */ 561 (void)path; 562 #endif /* CONFIG_DEBUG_FILE */ 563 return 0; 564 } 565 566 567 void wpa_debug_close_file(void) 568 { 569 #ifdef CONFIG_DEBUG_FILE 570 if (!out_file) 571 return; 572 fclose(out_file); 573 out_file = NULL; 574 os_free(last_path); 575 last_path = NULL; 576 #endif /* CONFIG_DEBUG_FILE */ 577 } 578 579 580 void wpa_debug_setup_stdout(void) 581 { 582 #ifndef _WIN32 583 setvbuf(stdout, NULL, _IOLBF, 0); 584 #endif /* _WIN32 */ 585 } 586 587 #endif /* CONFIG_NO_STDOUT_DEBUG */ 588 589 590 #ifndef CONFIG_NO_WPA_MSG 591 static wpa_msg_cb_func wpa_msg_cb = NULL; 592 593 void wpa_msg_register_cb(wpa_msg_cb_func func) 594 { 595 wpa_msg_cb = func; 596 } 597 598 599 static wpa_msg_get_ifname_func wpa_msg_ifname_cb = NULL; 600 601 void wpa_msg_register_ifname_cb(wpa_msg_get_ifname_func func) 602 { 603 wpa_msg_ifname_cb = func; 604 } 605 606 607 void wpa_msg(void *ctx, int level, const char *fmt, ...) 608 { 609 va_list ap; 610 char *buf; 611 int buflen; 612 int len; 613 char prefix[130]; 614 615 va_start(ap, fmt); 616 buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 617 va_end(ap); 618 619 buf = os_malloc(buflen); 620 if (buf == NULL) { 621 wpa_printf(MSG_ERROR, "wpa_msg: Failed to allocate message " 622 "buffer"); 623 return; 624 } 625 va_start(ap, fmt); 626 prefix[0] = '\0'; 627 if (wpa_msg_ifname_cb) { 628 const char *ifname = wpa_msg_ifname_cb(ctx); 629 if (ifname) { 630 int res = os_snprintf(prefix, sizeof(prefix), "%s: ", 631 ifname); 632 if (os_snprintf_error(sizeof(prefix), res)) 633 prefix[0] = '\0'; 634 } 635 } 636 len = vsnprintf(buf, buflen, fmt, ap); 637 va_end(ap); 638 wpa_printf(level, "%s%s", prefix, buf); 639 if (wpa_msg_cb) 640 wpa_msg_cb(ctx, level, WPA_MSG_PER_INTERFACE, buf, len); 641 bin_clear_free(buf, buflen); 642 } 643 644 645 void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...) 646 { 647 va_list ap; 648 char *buf; 649 int buflen; 650 int len; 651 652 if (!wpa_msg_cb) 653 return; 654 655 va_start(ap, fmt); 656 buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 657 va_end(ap); 658 659 buf = os_malloc(buflen); 660 if (buf == NULL) { 661 wpa_printf(MSG_ERROR, "wpa_msg_ctrl: Failed to allocate " 662 "message buffer"); 663 return; 664 } 665 va_start(ap, fmt); 666 len = vsnprintf(buf, buflen, fmt, ap); 667 va_end(ap); 668 wpa_msg_cb(ctx, level, WPA_MSG_PER_INTERFACE, buf, len); 669 bin_clear_free(buf, buflen); 670 } 671 672 673 void wpa_msg_global(void *ctx, int level, const char *fmt, ...) 674 { 675 va_list ap; 676 char *buf; 677 int buflen; 678 int len; 679 680 va_start(ap, fmt); 681 buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 682 va_end(ap); 683 684 buf = os_malloc(buflen); 685 if (buf == NULL) { 686 wpa_printf(MSG_ERROR, "wpa_msg_global: Failed to allocate " 687 "message buffer"); 688 return; 689 } 690 va_start(ap, fmt); 691 len = vsnprintf(buf, buflen, fmt, ap); 692 va_end(ap); 693 wpa_printf(level, "%s", buf); 694 if (wpa_msg_cb) 695 wpa_msg_cb(ctx, level, WPA_MSG_GLOBAL, buf, len); 696 bin_clear_free(buf, buflen); 697 } 698 699 700 void wpa_msg_global_ctrl(void *ctx, int level, const char *fmt, ...) 701 { 702 va_list ap; 703 char *buf; 704 int buflen; 705 int len; 706 707 if (!wpa_msg_cb) 708 return; 709 710 va_start(ap, fmt); 711 buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 712 va_end(ap); 713 714 buf = os_malloc(buflen); 715 if (buf == NULL) { 716 wpa_printf(MSG_ERROR, 717 "wpa_msg_global_ctrl: Failed to allocate message buffer"); 718 return; 719 } 720 va_start(ap, fmt); 721 len = vsnprintf(buf, buflen, fmt, ap); 722 va_end(ap); 723 wpa_msg_cb(ctx, level, WPA_MSG_GLOBAL, buf, len); 724 bin_clear_free(buf, buflen); 725 } 726 727 728 void wpa_msg_no_global(void *ctx, int level, const char *fmt, ...) 729 { 730 va_list ap; 731 char *buf; 732 int buflen; 733 int len; 734 735 va_start(ap, fmt); 736 buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 737 va_end(ap); 738 739 buf = os_malloc(buflen); 740 if (buf == NULL) { 741 wpa_printf(MSG_ERROR, "wpa_msg_no_global: Failed to allocate " 742 "message buffer"); 743 return; 744 } 745 va_start(ap, fmt); 746 len = vsnprintf(buf, buflen, fmt, ap); 747 va_end(ap); 748 wpa_printf(level, "%s", buf); 749 if (wpa_msg_cb) 750 wpa_msg_cb(ctx, level, WPA_MSG_NO_GLOBAL, buf, len); 751 bin_clear_free(buf, buflen); 752 } 753 754 755 void wpa_msg_global_only(void *ctx, int level, const char *fmt, ...) 756 { 757 va_list ap; 758 char *buf; 759 int buflen; 760 int len; 761 762 va_start(ap, fmt); 763 buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 764 va_end(ap); 765 766 buf = os_malloc(buflen); 767 if (buf == NULL) { 768 wpa_printf(MSG_ERROR, "%s: Failed to allocate message buffer", 769 __func__); 770 return; 771 } 772 va_start(ap, fmt); 773 len = vsnprintf(buf, buflen, fmt, ap); 774 va_end(ap); 775 wpa_printf(level, "%s", buf); 776 if (wpa_msg_cb) 777 wpa_msg_cb(ctx, level, WPA_MSG_ONLY_GLOBAL, buf, len); 778 os_free(buf); 779 } 780 781 #endif /* CONFIG_NO_WPA_MSG */ 782 783 784 #ifndef CONFIG_NO_HOSTAPD_LOGGER 785 static hostapd_logger_cb_func hostapd_logger_cb = NULL; 786 787 void hostapd_logger_register_cb(hostapd_logger_cb_func func) 788 { 789 hostapd_logger_cb = func; 790 } 791 792 793 void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level, 794 const char *fmt, ...) 795 { 796 va_list ap; 797 char *buf; 798 int buflen; 799 int len; 800 801 va_start(ap, fmt); 802 buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 803 va_end(ap); 804 805 buf = os_malloc(buflen); 806 if (buf == NULL) { 807 wpa_printf(MSG_ERROR, "hostapd_logger: Failed to allocate " 808 "message buffer"); 809 return; 810 } 811 va_start(ap, fmt); 812 len = vsnprintf(buf, buflen, fmt, ap); 813 va_end(ap); 814 if (hostapd_logger_cb) 815 hostapd_logger_cb(ctx, addr, module, level, buf, len); 816 else if (addr) 817 wpa_printf(MSG_DEBUG, "hostapd_logger: STA " MACSTR " - %s", 818 MAC2STR(addr), buf); 819 else 820 wpa_printf(MSG_DEBUG, "hostapd_logger: %s", buf); 821 bin_clear_free(buf, buflen); 822 } 823 #endif /* CONFIG_NO_HOSTAPD_LOGGER */ 824 825 826 const char * debug_level_str(int level) 827 { 828 switch (level) { 829 case MSG_EXCESSIVE: 830 return "EXCESSIVE"; 831 case MSG_MSGDUMP: 832 return "MSGDUMP"; 833 case MSG_DEBUG: 834 return "DEBUG"; 835 case MSG_INFO: 836 return "INFO"; 837 case MSG_WARNING: 838 return "WARNING"; 839 case MSG_ERROR: 840 return "ERROR"; 841 default: 842 return "?"; 843 } 844 } 845 846 847 int str_to_debug_level(const char *s) 848 { 849 if (os_strcasecmp(s, "EXCESSIVE") == 0) 850 return MSG_EXCESSIVE; 851 if (os_strcasecmp(s, "MSGDUMP") == 0) 852 return MSG_MSGDUMP; 853 if (os_strcasecmp(s, "DEBUG") == 0) 854 return MSG_DEBUG; 855 if (os_strcasecmp(s, "INFO") == 0) 856 return MSG_INFO; 857 if (os_strcasecmp(s, "WARNING") == 0) 858 return MSG_WARNING; 859 if (os_strcasecmp(s, "ERROR") == 0) 860 return MSG_ERROR; 861 return -1; 862 } 863