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