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