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_close_file(void) 600 { 601 #ifdef CONFIG_DEBUG_FILE 602 if (!out_file) 603 return; 604 fclose(out_file); 605 out_file = NULL; 606 os_free(last_path); 607 last_path = NULL; 608 #endif /* CONFIG_DEBUG_FILE */ 609 } 610 611 612 void wpa_debug_setup_stdout(void) 613 { 614 #ifndef _WIN32 615 setvbuf(stdout, NULL, _IOLBF, 0); 616 #endif /* _WIN32 */ 617 } 618 619 #endif /* CONFIG_NO_STDOUT_DEBUG */ 620 621 622 #ifndef CONFIG_NO_WPA_MSG 623 static wpa_msg_cb_func wpa_msg_cb = NULL; 624 625 void wpa_msg_register_cb(wpa_msg_cb_func func) 626 { 627 wpa_msg_cb = func; 628 } 629 630 631 static wpa_msg_get_ifname_func wpa_msg_ifname_cb = NULL; 632 633 void wpa_msg_register_ifname_cb(wpa_msg_get_ifname_func func) 634 { 635 wpa_msg_ifname_cb = func; 636 } 637 638 639 void wpa_msg(void *ctx, int level, const char *fmt, ...) 640 { 641 va_list ap; 642 char *buf; 643 int buflen; 644 int len; 645 char prefix[130]; 646 647 va_start(ap, fmt); 648 buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 649 va_end(ap); 650 651 buf = os_malloc(buflen); 652 if (buf == NULL) { 653 wpa_printf(MSG_ERROR, "wpa_msg: Failed to allocate message " 654 "buffer"); 655 return; 656 } 657 va_start(ap, fmt); 658 prefix[0] = '\0'; 659 if (wpa_msg_ifname_cb) { 660 const char *ifname = wpa_msg_ifname_cb(ctx); 661 if (ifname) { 662 int res = os_snprintf(prefix, sizeof(prefix), "%s: ", 663 ifname); 664 if (os_snprintf_error(sizeof(prefix), res)) 665 prefix[0] = '\0'; 666 } 667 } 668 len = vsnprintf(buf, buflen, fmt, ap); 669 va_end(ap); 670 wpa_printf(level, "%s%s", prefix, buf); 671 if (wpa_msg_cb) 672 wpa_msg_cb(ctx, level, WPA_MSG_PER_INTERFACE, buf, len); 673 bin_clear_free(buf, buflen); 674 } 675 676 677 void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...) 678 { 679 va_list ap; 680 char *buf; 681 int buflen; 682 int len; 683 684 if (!wpa_msg_cb) 685 return; 686 687 va_start(ap, fmt); 688 buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 689 va_end(ap); 690 691 buf = os_malloc(buflen); 692 if (buf == NULL) { 693 wpa_printf(MSG_ERROR, "wpa_msg_ctrl: Failed to allocate " 694 "message buffer"); 695 return; 696 } 697 va_start(ap, fmt); 698 len = vsnprintf(buf, buflen, fmt, ap); 699 va_end(ap); 700 wpa_msg_cb(ctx, level, WPA_MSG_PER_INTERFACE, buf, len); 701 bin_clear_free(buf, buflen); 702 } 703 704 705 void wpa_msg_global(void *ctx, int level, const char *fmt, ...) 706 { 707 va_list ap; 708 char *buf; 709 int buflen; 710 int len; 711 712 va_start(ap, fmt); 713 buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 714 va_end(ap); 715 716 buf = os_malloc(buflen); 717 if (buf == NULL) { 718 wpa_printf(MSG_ERROR, "wpa_msg_global: Failed to allocate " 719 "message buffer"); 720 return; 721 } 722 va_start(ap, fmt); 723 len = vsnprintf(buf, buflen, fmt, ap); 724 va_end(ap); 725 wpa_printf(level, "%s", buf); 726 if (wpa_msg_cb) 727 wpa_msg_cb(ctx, level, WPA_MSG_GLOBAL, buf, len); 728 bin_clear_free(buf, buflen); 729 } 730 731 732 void wpa_msg_global_ctrl(void *ctx, int level, const char *fmt, ...) 733 { 734 va_list ap; 735 char *buf; 736 int buflen; 737 int len; 738 739 if (!wpa_msg_cb) 740 return; 741 742 va_start(ap, fmt); 743 buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 744 va_end(ap); 745 746 buf = os_malloc(buflen); 747 if (buf == NULL) { 748 wpa_printf(MSG_ERROR, 749 "wpa_msg_global_ctrl: Failed to allocate message buffer"); 750 return; 751 } 752 va_start(ap, fmt); 753 len = vsnprintf(buf, buflen, fmt, ap); 754 va_end(ap); 755 wpa_msg_cb(ctx, level, WPA_MSG_GLOBAL, buf, len); 756 bin_clear_free(buf, buflen); 757 } 758 759 760 void wpa_msg_no_global(void *ctx, int level, const char *fmt, ...) 761 { 762 va_list ap; 763 char *buf; 764 int buflen; 765 int len; 766 767 va_start(ap, fmt); 768 buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 769 va_end(ap); 770 771 buf = os_malloc(buflen); 772 if (buf == NULL) { 773 wpa_printf(MSG_ERROR, "wpa_msg_no_global: Failed to allocate " 774 "message buffer"); 775 return; 776 } 777 va_start(ap, fmt); 778 len = vsnprintf(buf, buflen, fmt, ap); 779 va_end(ap); 780 wpa_printf(level, "%s", buf); 781 if (wpa_msg_cb) 782 wpa_msg_cb(ctx, level, WPA_MSG_NO_GLOBAL, buf, len); 783 bin_clear_free(buf, buflen); 784 } 785 786 787 void wpa_msg_global_only(void *ctx, int level, const char *fmt, ...) 788 { 789 va_list ap; 790 char *buf; 791 int buflen; 792 int len; 793 794 va_start(ap, fmt); 795 buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 796 va_end(ap); 797 798 buf = os_malloc(buflen); 799 if (buf == NULL) { 800 wpa_printf(MSG_ERROR, "%s: Failed to allocate message buffer", 801 __func__); 802 return; 803 } 804 va_start(ap, fmt); 805 len = vsnprintf(buf, buflen, fmt, ap); 806 va_end(ap); 807 wpa_printf(level, "%s", buf); 808 if (wpa_msg_cb) 809 wpa_msg_cb(ctx, level, WPA_MSG_ONLY_GLOBAL, buf, len); 810 os_free(buf); 811 } 812 813 #endif /* CONFIG_NO_WPA_MSG */ 814 815 816 #ifndef CONFIG_NO_HOSTAPD_LOGGER 817 static hostapd_logger_cb_func hostapd_logger_cb = NULL; 818 819 void hostapd_logger_register_cb(hostapd_logger_cb_func func) 820 { 821 hostapd_logger_cb = func; 822 } 823 824 825 void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level, 826 const char *fmt, ...) 827 { 828 va_list ap; 829 char *buf; 830 int buflen; 831 int len; 832 833 va_start(ap, fmt); 834 buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 835 va_end(ap); 836 837 buf = os_malloc(buflen); 838 if (buf == NULL) { 839 wpa_printf(MSG_ERROR, "hostapd_logger: Failed to allocate " 840 "message buffer"); 841 return; 842 } 843 va_start(ap, fmt); 844 len = vsnprintf(buf, buflen, fmt, ap); 845 va_end(ap); 846 if (hostapd_logger_cb) 847 hostapd_logger_cb(ctx, addr, module, level, buf, len); 848 else if (addr) 849 wpa_printf(MSG_DEBUG, "hostapd_logger: STA " MACSTR " - %s", 850 MAC2STR(addr), buf); 851 else 852 wpa_printf(MSG_DEBUG, "hostapd_logger: %s", buf); 853 bin_clear_free(buf, buflen); 854 } 855 #endif /* CONFIG_NO_HOSTAPD_LOGGER */ 856 857 858 const char * debug_level_str(int level) 859 { 860 switch (level) { 861 case MSG_EXCESSIVE: 862 return "EXCESSIVE"; 863 case MSG_MSGDUMP: 864 return "MSGDUMP"; 865 case MSG_DEBUG: 866 return "DEBUG"; 867 case MSG_INFO: 868 return "INFO"; 869 case MSG_WARNING: 870 return "WARNING"; 871 case MSG_ERROR: 872 return "ERROR"; 873 default: 874 return "?"; 875 } 876 } 877 878 879 int str_to_debug_level(const char *s) 880 { 881 if (os_strcasecmp(s, "EXCESSIVE") == 0) 882 return MSG_EXCESSIVE; 883 if (os_strcasecmp(s, "MSGDUMP") == 0) 884 return MSG_MSGDUMP; 885 if (os_strcasecmp(s, "DEBUG") == 0) 886 return MSG_DEBUG; 887 if (os_strcasecmp(s, "INFO") == 0) 888 return MSG_INFO; 889 if (os_strcasecmp(s, "WARNING") == 0) 890 return MSG_WARNING; 891 if (os_strcasecmp(s, "ERROR") == 0) 892 return MSG_ERROR; 893 return -1; 894 } 895