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 #endif /* CONFIG_DEBUG_SYSLOG */ 16 17 #ifdef CONFIG_DEBUG_LINUX_TRACING 18 #include <sys/types.h> 19 #include <sys/stat.h> 20 #include <fcntl.h> 21 #include <string.h> 22 #include <stdio.h> 23 24 static FILE *wpa_debug_tracing_file = NULL; 25 26 #define WPAS_TRACE_PFX "wpas <%d>: " 27 #endif /* CONFIG_DEBUG_LINUX_TRACING */ 28 29 30 int wpa_debug_level = MSG_INFO; 31 int wpa_debug_show_keys = 0; 32 int wpa_debug_timestamp = 0; 33 int wpa_debug_syslog = 0; 34 #ifndef CONFIG_NO_STDOUT_DEBUG 35 static FILE *out_file = NULL; 36 #endif /* CONFIG_NO_STDOUT_DEBUG */ 37 38 39 #ifdef CONFIG_ANDROID_LOG 40 41 #include <android/log.h> 42 43 #ifndef ANDROID_LOG_NAME 44 #define ANDROID_LOG_NAME "wpa_supplicant" 45 #endif /* ANDROID_LOG_NAME */ 46 47 static int wpa_to_android_level(int level) 48 { 49 if (level == MSG_ERROR) 50 return ANDROID_LOG_ERROR; 51 if (level == MSG_WARNING) 52 return ANDROID_LOG_WARN; 53 if (level == MSG_INFO) 54 return ANDROID_LOG_INFO; 55 return ANDROID_LOG_DEBUG; 56 } 57 58 #endif /* CONFIG_ANDROID_LOG */ 59 60 #ifndef CONFIG_NO_STDOUT_DEBUG 61 62 #ifdef CONFIG_DEBUG_FILE 63 #include <sys/types.h> 64 #include <sys/stat.h> 65 #include <fcntl.h> 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 #endif /* CONFIG_DEBUG_FILE */ 83 if (!out_file && !wpa_debug_syslog) 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 if (level >= wpa_debug_level) { 214 #ifdef CONFIG_ANDROID_LOG 215 va_start(ap, fmt); 216 __android_log_vprint(wpa_to_android_level(level), 217 ANDROID_LOG_NAME, fmt, ap); 218 va_end(ap); 219 #else /* CONFIG_ANDROID_LOG */ 220 #ifdef CONFIG_DEBUG_SYSLOG 221 if (wpa_debug_syslog) { 222 va_start(ap, fmt); 223 vsyslog(syslog_priority(level), fmt, ap); 224 va_end(ap); 225 } 226 #endif /* CONFIG_DEBUG_SYSLOG */ 227 wpa_debug_print_timestamp(); 228 #ifdef CONFIG_DEBUG_FILE 229 if (out_file) { 230 va_start(ap, fmt); 231 vfprintf(out_file, fmt, ap); 232 fprintf(out_file, "\n"); 233 va_end(ap); 234 } 235 #endif /* CONFIG_DEBUG_FILE */ 236 if (!wpa_debug_syslog && !out_file) { 237 va_start(ap, fmt); 238 vprintf(fmt, ap); 239 printf("\n"); 240 va_end(ap); 241 } 242 #endif /* CONFIG_ANDROID_LOG */ 243 } 244 245 #ifdef CONFIG_DEBUG_LINUX_TRACING 246 if (wpa_debug_tracing_file != NULL) { 247 va_start(ap, fmt); 248 fprintf(wpa_debug_tracing_file, WPAS_TRACE_PFX, level); 249 vfprintf(wpa_debug_tracing_file, fmt, ap); 250 fprintf(wpa_debug_tracing_file, "\n"); 251 fflush(wpa_debug_tracing_file); 252 va_end(ap); 253 } 254 #endif /* CONFIG_DEBUG_LINUX_TRACING */ 255 } 256 257 258 static void _wpa_hexdump(int level, const char *title, const u8 *buf, 259 size_t len, int show, int only_syslog) 260 { 261 size_t i; 262 263 #ifdef CONFIG_DEBUG_LINUX_TRACING 264 if (wpa_debug_tracing_file != NULL) { 265 fprintf(wpa_debug_tracing_file, 266 WPAS_TRACE_PFX "%s - hexdump(len=%lu):", 267 level, title, (unsigned long) len); 268 if (buf == NULL) { 269 fprintf(wpa_debug_tracing_file, " [NULL]\n"); 270 } else if (!show) { 271 fprintf(wpa_debug_tracing_file, " [REMOVED]\n"); 272 } else { 273 for (i = 0; i < len; i++) 274 fprintf(wpa_debug_tracing_file, 275 " %02x", buf[i]); 276 } 277 fflush(wpa_debug_tracing_file); 278 } 279 #endif /* CONFIG_DEBUG_LINUX_TRACING */ 280 281 if (level < wpa_debug_level) 282 return; 283 #ifdef CONFIG_ANDROID_LOG 284 { 285 const char *display; 286 char *strbuf = NULL; 287 size_t slen = len; 288 if (buf == NULL) { 289 display = " [NULL]"; 290 } else if (len == 0) { 291 display = ""; 292 } else if (show && len) { 293 /* Limit debug message length for Android log */ 294 if (slen > 32) 295 slen = 32; 296 strbuf = os_malloc(1 + 3 * slen); 297 if (strbuf == NULL) { 298 wpa_printf(MSG_ERROR, "wpa_hexdump: Failed to " 299 "allocate message buffer"); 300 return; 301 } 302 303 for (i = 0; i < slen; i++) 304 os_snprintf(&strbuf[i * 3], 4, " %02x", 305 buf[i]); 306 307 display = strbuf; 308 } else { 309 display = " [REMOVED]"; 310 } 311 312 __android_log_print(wpa_to_android_level(level), 313 ANDROID_LOG_NAME, 314 "%s - hexdump(len=%lu):%s%s", 315 title, (long unsigned int) len, display, 316 len > slen ? " ..." : ""); 317 bin_clear_free(strbuf, 1 + 3 * slen); 318 return; 319 } 320 #else /* CONFIG_ANDROID_LOG */ 321 #ifdef CONFIG_DEBUG_SYSLOG 322 if (wpa_debug_syslog) { 323 const char *display; 324 char *strbuf = NULL; 325 326 if (buf == NULL) { 327 display = " [NULL]"; 328 } else if (len == 0) { 329 display = ""; 330 } else if (show && len) { 331 strbuf = os_malloc(1 + 3 * len); 332 if (strbuf == NULL) { 333 wpa_printf(MSG_ERROR, "wpa_hexdump: Failed to " 334 "allocate message buffer"); 335 return; 336 } 337 338 for (i = 0; i < len; i++) 339 os_snprintf(&strbuf[i * 3], 4, " %02x", 340 buf[i]); 341 342 display = strbuf; 343 } else { 344 display = " [REMOVED]"; 345 } 346 347 syslog(syslog_priority(level), "%s - hexdump(len=%lu):%s", 348 title, (unsigned long) len, display); 349 bin_clear_free(strbuf, 1 + 3 * len); 350 if (only_syslog) 351 return; 352 } 353 #endif /* CONFIG_DEBUG_SYSLOG */ 354 wpa_debug_print_timestamp(); 355 #ifdef CONFIG_DEBUG_FILE 356 if (out_file) { 357 fprintf(out_file, "%s - hexdump(len=%lu):", 358 title, (unsigned long) len); 359 if (buf == NULL) { 360 fprintf(out_file, " [NULL]"); 361 } else if (show) { 362 for (i = 0; i < len; i++) 363 fprintf(out_file, " %02x", buf[i]); 364 } else { 365 fprintf(out_file, " [REMOVED]"); 366 } 367 fprintf(out_file, "\n"); 368 } 369 #endif /* CONFIG_DEBUG_FILE */ 370 if (!wpa_debug_syslog && !out_file) { 371 printf("%s - hexdump(len=%lu):", title, (unsigned long) len); 372 if (buf == NULL) { 373 printf(" [NULL]"); 374 } else if (show) { 375 for (i = 0; i < len; i++) 376 printf(" %02x", buf[i]); 377 } else { 378 printf(" [REMOVED]"); 379 } 380 printf("\n"); 381 } 382 #endif /* CONFIG_ANDROID_LOG */ 383 } 384 385 void wpa_hexdump(int level, const char *title, const void *buf, size_t len) 386 { 387 _wpa_hexdump(level, title, buf, len, 1, 0); 388 } 389 390 391 void wpa_hexdump_key(int level, const char *title, const void *buf, size_t len) 392 { 393 _wpa_hexdump(level, title, buf, len, wpa_debug_show_keys, 0); 394 } 395 396 397 static void _wpa_hexdump_ascii(int level, const char *title, const void *buf, 398 size_t len, int show) 399 { 400 size_t i, llen; 401 const u8 *pos = buf; 402 const size_t line_len = 16; 403 404 #ifdef CONFIG_DEBUG_LINUX_TRACING 405 if (wpa_debug_tracing_file != NULL) { 406 fprintf(wpa_debug_tracing_file, 407 WPAS_TRACE_PFX "%s - hexdump_ascii(len=%lu):", 408 level, title, (unsigned long) len); 409 if (buf == NULL) { 410 fprintf(wpa_debug_tracing_file, " [NULL]\n"); 411 } else if (!show) { 412 fprintf(wpa_debug_tracing_file, " [REMOVED]\n"); 413 } else { 414 /* can do ascii processing in userspace */ 415 for (i = 0; i < len; i++) 416 fprintf(wpa_debug_tracing_file, 417 " %02x", pos[i]); 418 } 419 fflush(wpa_debug_tracing_file); 420 } 421 #endif /* CONFIG_DEBUG_LINUX_TRACING */ 422 423 if (level < wpa_debug_level) 424 return; 425 #ifdef CONFIG_ANDROID_LOG 426 _wpa_hexdump(level, title, buf, len, show, 0); 427 #else /* CONFIG_ANDROID_LOG */ 428 #ifdef CONFIG_DEBUG_SYSLOG 429 if (wpa_debug_syslog) 430 _wpa_hexdump(level, title, buf, len, show, 1); 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 goto file_done; 440 } 441 if (buf == NULL) { 442 fprintf(out_file, 443 "%s - hexdump_ascii(len=%lu): [NULL]\n", 444 title, (unsigned long) len); 445 goto file_done; 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 } 470 file_done: 471 #endif /* CONFIG_DEBUG_FILE */ 472 if (!wpa_debug_syslog && !out_file) { 473 if (!show) { 474 printf("%s - hexdump_ascii(len=%lu): [REMOVED]\n", 475 title, (unsigned long) len); 476 return; 477 } 478 if (buf == NULL) { 479 printf("%s - hexdump_ascii(len=%lu): [NULL]\n", 480 title, (unsigned long) len); 481 return; 482 } 483 printf("%s - hexdump_ascii(len=%lu):\n", title, 484 (unsigned long) len); 485 while (len) { 486 llen = len > line_len ? line_len : len; 487 printf(" "); 488 for (i = 0; i < llen; i++) 489 printf(" %02x", pos[i]); 490 for (i = llen; i < line_len; i++) 491 printf(" "); 492 printf(" "); 493 for (i = 0; i < llen; i++) { 494 if (isprint(pos[i])) 495 printf("%c", pos[i]); 496 else 497 printf("_"); 498 } 499 for (i = llen; i < line_len; i++) 500 printf(" "); 501 printf("\n"); 502 pos += llen; 503 len -= llen; 504 } 505 } 506 #endif /* CONFIG_ANDROID_LOG */ 507 } 508 509 510 void wpa_hexdump_ascii(int level, const char *title, const void *buf, 511 size_t len) 512 { 513 _wpa_hexdump_ascii(level, title, buf, len, 1); 514 } 515 516 517 void wpa_hexdump_ascii_key(int level, const char *title, const void *buf, 518 size_t len) 519 { 520 _wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys); 521 } 522 523 524 #ifdef CONFIG_DEBUG_FILE 525 static char *last_path = NULL; 526 #endif /* CONFIG_DEBUG_FILE */ 527 528 int wpa_debug_reopen_file(void) 529 { 530 #ifdef CONFIG_DEBUG_FILE 531 int rv; 532 char *tmp; 533 534 if (!last_path) 535 return 0; /* logfile not used */ 536 537 tmp = os_strdup(last_path); 538 if (!tmp) 539 return -1; 540 541 wpa_debug_close_file(); 542 rv = wpa_debug_open_file(tmp); 543 os_free(tmp); 544 return rv; 545 #else /* CONFIG_DEBUG_FILE */ 546 return 0; 547 #endif /* CONFIG_DEBUG_FILE */ 548 } 549 550 551 int wpa_debug_open_file(const char *path) 552 { 553 #ifdef CONFIG_DEBUG_FILE 554 int out_fd; 555 556 if (!path) 557 return 0; 558 559 if (last_path == NULL || os_strcmp(last_path, path) != 0) { 560 /* Save our path to enable re-open */ 561 os_free(last_path); 562 last_path = os_strdup(path); 563 } 564 565 out_fd = open(path, O_CREAT | O_APPEND | O_WRONLY, 566 S_IRUSR | S_IWUSR | S_IRGRP); 567 if (out_fd < 0) { 568 wpa_printf(MSG_ERROR, 569 "%s: Failed to open output file descriptor, using standard output", 570 __func__); 571 return -1; 572 } 573 574 #ifdef __linux__ 575 if (fcntl(out_fd, F_SETFD, FD_CLOEXEC) < 0) { 576 wpa_printf(MSG_DEBUG, 577 "%s: Failed to set FD_CLOEXEC - continue without: %s", 578 __func__, strerror(errno)); 579 } 580 #endif /* __linux__ */ 581 582 out_file = fdopen(out_fd, "a"); 583 if (out_file == NULL) { 584 wpa_printf(MSG_ERROR, "wpa_debug_open_file: Failed to open " 585 "output file, using standard output"); 586 close(out_fd); 587 return -1; 588 } 589 #ifndef _WIN32 590 setvbuf(out_file, NULL, _IOLBF, 0); 591 #endif /* _WIN32 */ 592 #else /* CONFIG_DEBUG_FILE */ 593 (void)path; 594 #endif /* CONFIG_DEBUG_FILE */ 595 return 0; 596 } 597 598 599 void wpa_debug_stop_log(void) 600 { 601 #ifdef CONFIG_DEBUG_FILE 602 if (!out_file) 603 return; 604 fclose(out_file); 605 out_file = NULL; 606 #endif /* CONFIG_DEBUG_FILE */ 607 } 608 609 610 void wpa_debug_close_file(void) 611 { 612 #ifdef CONFIG_DEBUG_FILE 613 wpa_debug_stop_log(); 614 os_free(last_path); 615 last_path = NULL; 616 #endif /* CONFIG_DEBUG_FILE */ 617 } 618 619 620 void wpa_debug_setup_stdout(void) 621 { 622 #ifndef _WIN32 623 setvbuf(stdout, NULL, _IOLBF, 0); 624 #endif /* _WIN32 */ 625 } 626 627 #endif /* CONFIG_NO_STDOUT_DEBUG */ 628 629 630 #ifndef CONFIG_NO_WPA_MSG 631 static wpa_msg_cb_func wpa_msg_cb = NULL; 632 633 void wpa_msg_register_cb(wpa_msg_cb_func func) 634 { 635 wpa_msg_cb = func; 636 } 637 638 639 static wpa_msg_get_ifname_func wpa_msg_ifname_cb = NULL; 640 641 void wpa_msg_register_ifname_cb(wpa_msg_get_ifname_func func) 642 { 643 wpa_msg_ifname_cb = func; 644 } 645 646 647 void wpa_msg(void *ctx, int level, const char *fmt, ...) 648 { 649 va_list ap; 650 char *buf; 651 int buflen; 652 int len; 653 char prefix[130]; 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: Failed to allocate message " 662 "buffer"); 663 return; 664 } 665 va_start(ap, fmt); 666 prefix[0] = '\0'; 667 if (wpa_msg_ifname_cb) { 668 const char *ifname = wpa_msg_ifname_cb(ctx); 669 if (ifname) { 670 int res = os_snprintf(prefix, sizeof(prefix), "%s: ", 671 ifname); 672 if (os_snprintf_error(sizeof(prefix), res)) 673 prefix[0] = '\0'; 674 } 675 } 676 len = vsnprintf(buf, buflen, fmt, ap); 677 va_end(ap); 678 wpa_printf(level, "%s%s", prefix, buf); 679 if (wpa_msg_cb) 680 wpa_msg_cb(ctx, level, WPA_MSG_PER_INTERFACE, buf, len); 681 bin_clear_free(buf, buflen); 682 } 683 684 685 void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...) 686 { 687 va_list ap; 688 char *buf; 689 int buflen; 690 int len; 691 692 if (!wpa_msg_cb) 693 return; 694 695 va_start(ap, fmt); 696 buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 697 va_end(ap); 698 699 buf = os_malloc(buflen); 700 if (buf == NULL) { 701 wpa_printf(MSG_ERROR, "wpa_msg_ctrl: Failed to allocate " 702 "message buffer"); 703 return; 704 } 705 va_start(ap, fmt); 706 len = vsnprintf(buf, buflen, fmt, ap); 707 va_end(ap); 708 wpa_msg_cb(ctx, level, WPA_MSG_PER_INTERFACE, buf, len); 709 bin_clear_free(buf, buflen); 710 } 711 712 713 void wpa_msg_global(void *ctx, int level, const char *fmt, ...) 714 { 715 va_list ap; 716 char *buf; 717 int buflen; 718 int len; 719 720 va_start(ap, fmt); 721 buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 722 va_end(ap); 723 724 buf = os_malloc(buflen); 725 if (buf == NULL) { 726 wpa_printf(MSG_ERROR, "wpa_msg_global: Failed to allocate " 727 "message buffer"); 728 return; 729 } 730 va_start(ap, fmt); 731 len = vsnprintf(buf, buflen, fmt, ap); 732 va_end(ap); 733 wpa_printf(level, "%s", buf); 734 if (wpa_msg_cb) 735 wpa_msg_cb(ctx, level, WPA_MSG_GLOBAL, buf, len); 736 bin_clear_free(buf, buflen); 737 } 738 739 740 void wpa_msg_global_ctrl(void *ctx, int level, const char *fmt, ...) 741 { 742 va_list ap; 743 char *buf; 744 int buflen; 745 int len; 746 747 if (!wpa_msg_cb) 748 return; 749 750 va_start(ap, fmt); 751 buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 752 va_end(ap); 753 754 buf = os_malloc(buflen); 755 if (buf == NULL) { 756 wpa_printf(MSG_ERROR, 757 "wpa_msg_global_ctrl: Failed to allocate message buffer"); 758 return; 759 } 760 va_start(ap, fmt); 761 len = vsnprintf(buf, buflen, fmt, ap); 762 va_end(ap); 763 wpa_msg_cb(ctx, level, WPA_MSG_GLOBAL, buf, len); 764 bin_clear_free(buf, buflen); 765 } 766 767 768 void wpa_msg_no_global(void *ctx, int level, const char *fmt, ...) 769 { 770 va_list ap; 771 char *buf; 772 int buflen; 773 int len; 774 775 va_start(ap, fmt); 776 buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 777 va_end(ap); 778 779 buf = os_malloc(buflen); 780 if (buf == NULL) { 781 wpa_printf(MSG_ERROR, "wpa_msg_no_global: Failed to allocate " 782 "message buffer"); 783 return; 784 } 785 va_start(ap, fmt); 786 len = vsnprintf(buf, buflen, fmt, ap); 787 va_end(ap); 788 wpa_printf(level, "%s", buf); 789 if (wpa_msg_cb) 790 wpa_msg_cb(ctx, level, WPA_MSG_NO_GLOBAL, buf, len); 791 bin_clear_free(buf, buflen); 792 } 793 794 795 void wpa_msg_global_only(void *ctx, int level, const char *fmt, ...) 796 { 797 va_list ap; 798 char *buf; 799 int buflen; 800 int len; 801 802 va_start(ap, fmt); 803 buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 804 va_end(ap); 805 806 buf = os_malloc(buflen); 807 if (buf == NULL) { 808 wpa_printf(MSG_ERROR, "%s: Failed to allocate message buffer", 809 __func__); 810 return; 811 } 812 va_start(ap, fmt); 813 len = vsnprintf(buf, buflen, fmt, ap); 814 va_end(ap); 815 wpa_printf(level, "%s", buf); 816 if (wpa_msg_cb) 817 wpa_msg_cb(ctx, level, WPA_MSG_ONLY_GLOBAL, buf, len); 818 os_free(buf); 819 } 820 821 #endif /* CONFIG_NO_WPA_MSG */ 822 823 824 #ifndef CONFIG_NO_HOSTAPD_LOGGER 825 static hostapd_logger_cb_func hostapd_logger_cb = NULL; 826 827 void hostapd_logger_register_cb(hostapd_logger_cb_func func) 828 { 829 hostapd_logger_cb = func; 830 } 831 832 833 void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level, 834 const char *fmt, ...) 835 { 836 va_list ap; 837 char *buf; 838 int buflen; 839 int len; 840 841 va_start(ap, fmt); 842 buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 843 va_end(ap); 844 845 buf = os_malloc(buflen); 846 if (buf == NULL) { 847 wpa_printf(MSG_ERROR, "hostapd_logger: Failed to allocate " 848 "message buffer"); 849 return; 850 } 851 va_start(ap, fmt); 852 len = vsnprintf(buf, buflen, fmt, ap); 853 va_end(ap); 854 if (hostapd_logger_cb) 855 hostapd_logger_cb(ctx, addr, module, level, buf, len); 856 else if (addr) 857 wpa_printf(MSG_DEBUG, "hostapd_logger: STA " MACSTR " - %s", 858 MAC2STR(addr), buf); 859 else 860 wpa_printf(MSG_DEBUG, "hostapd_logger: %s", buf); 861 bin_clear_free(buf, buflen); 862 } 863 #endif /* CONFIG_NO_HOSTAPD_LOGGER */ 864 865 866 const char * debug_level_str(int level) 867 { 868 switch (level) { 869 case MSG_EXCESSIVE: 870 return "EXCESSIVE"; 871 case MSG_MSGDUMP: 872 return "MSGDUMP"; 873 case MSG_DEBUG: 874 return "DEBUG"; 875 case MSG_INFO: 876 return "INFO"; 877 case MSG_WARNING: 878 return "WARNING"; 879 case MSG_ERROR: 880 return "ERROR"; 881 default: 882 return "?"; 883 } 884 } 885 886 887 int str_to_debug_level(const char *s) 888 { 889 if (os_strcasecmp(s, "EXCESSIVE") == 0) 890 return MSG_EXCESSIVE; 891 if (os_strcasecmp(s, "MSGDUMP") == 0) 892 return MSG_MSGDUMP; 893 if (os_strcasecmp(s, "DEBUG") == 0) 894 return MSG_DEBUG; 895 if (os_strcasecmp(s, "INFO") == 0) 896 return MSG_INFO; 897 if (os_strcasecmp(s, "WARNING") == 0) 898 return MSG_WARNING; 899 if (os_strcasecmp(s, "ERROR") == 0) 900 return MSG_ERROR; 901 return -1; 902 } 903