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 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 (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 os_free(strbuf); 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 os_free(strbuf); 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 if (last_path) { 521 char *tmp = os_strdup(last_path); 522 wpa_debug_close_file(); 523 rv = wpa_debug_open_file(tmp); 524 os_free(tmp); 525 } else { 526 wpa_printf(MSG_ERROR, "Last-path was not set, cannot " 527 "re-open log file."); 528 rv = -1; 529 } 530 return rv; 531 #else /* CONFIG_DEBUG_FILE */ 532 return 0; 533 #endif /* CONFIG_DEBUG_FILE */ 534 } 535 536 537 int wpa_debug_open_file(const char *path) 538 { 539 #ifdef CONFIG_DEBUG_FILE 540 if (!path) 541 return 0; 542 543 if (last_path == NULL || os_strcmp(last_path, path) != 0) { 544 /* Save our path to enable re-open */ 545 os_free(last_path); 546 last_path = os_strdup(path); 547 } 548 549 out_file = fopen(path, "a"); 550 if (out_file == NULL) { 551 wpa_printf(MSG_ERROR, "wpa_debug_open_file: Failed to open " 552 "output file, using standard output"); 553 return -1; 554 } 555 #ifndef _WIN32 556 setvbuf(out_file, NULL, _IOLBF, 0); 557 #endif /* _WIN32 */ 558 #else /* CONFIG_DEBUG_FILE */ 559 (void)path; 560 #endif /* CONFIG_DEBUG_FILE */ 561 return 0; 562 } 563 564 565 void wpa_debug_close_file(void) 566 { 567 #ifdef CONFIG_DEBUG_FILE 568 if (!out_file) 569 return; 570 fclose(out_file); 571 out_file = NULL; 572 os_free(last_path); 573 last_path = NULL; 574 #endif /* CONFIG_DEBUG_FILE */ 575 } 576 577 578 void wpa_debug_setup_stdout(void) 579 { 580 #ifndef _WIN32 581 setvbuf(stdout, NULL, _IOLBF, 0); 582 #endif /* _WIN32 */ 583 } 584 585 #endif /* CONFIG_NO_STDOUT_DEBUG */ 586 587 588 #ifndef CONFIG_NO_WPA_MSG 589 static wpa_msg_cb_func wpa_msg_cb = NULL; 590 591 void wpa_msg_register_cb(wpa_msg_cb_func func) 592 { 593 wpa_msg_cb = func; 594 } 595 596 597 static wpa_msg_get_ifname_func wpa_msg_ifname_cb = NULL; 598 599 void wpa_msg_register_ifname_cb(wpa_msg_get_ifname_func func) 600 { 601 wpa_msg_ifname_cb = func; 602 } 603 604 605 void wpa_msg(void *ctx, int level, const char *fmt, ...) 606 { 607 va_list ap; 608 char *buf; 609 int buflen; 610 int len; 611 char prefix[130]; 612 613 va_start(ap, fmt); 614 buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 615 va_end(ap); 616 617 buf = os_malloc(buflen); 618 if (buf == NULL) { 619 wpa_printf(MSG_ERROR, "wpa_msg: Failed to allocate message " 620 "buffer"); 621 return; 622 } 623 va_start(ap, fmt); 624 prefix[0] = '\0'; 625 if (wpa_msg_ifname_cb) { 626 const char *ifname = wpa_msg_ifname_cb(ctx); 627 if (ifname) { 628 int res = os_snprintf(prefix, sizeof(prefix), "%s: ", 629 ifname); 630 if (os_snprintf_error(sizeof(prefix), res)) 631 prefix[0] = '\0'; 632 } 633 } 634 len = vsnprintf(buf, buflen, fmt, ap); 635 va_end(ap); 636 wpa_printf(level, "%s%s", prefix, buf); 637 if (wpa_msg_cb) 638 wpa_msg_cb(ctx, level, 0, buf, len); 639 os_free(buf); 640 } 641 642 643 void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...) 644 { 645 va_list ap; 646 char *buf; 647 int buflen; 648 int len; 649 650 if (!wpa_msg_cb) 651 return; 652 653 va_start(ap, fmt); 654 buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 655 va_end(ap); 656 657 buf = os_malloc(buflen); 658 if (buf == NULL) { 659 wpa_printf(MSG_ERROR, "wpa_msg_ctrl: Failed to allocate " 660 "message buffer"); 661 return; 662 } 663 va_start(ap, fmt); 664 len = vsnprintf(buf, buflen, fmt, ap); 665 va_end(ap); 666 wpa_msg_cb(ctx, level, 0, buf, len); 667 os_free(buf); 668 } 669 670 671 void wpa_msg_global(void *ctx, int level, const char *fmt, ...) 672 { 673 va_list ap; 674 char *buf; 675 int buflen; 676 int len; 677 678 va_start(ap, fmt); 679 buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 680 va_end(ap); 681 682 buf = os_malloc(buflen); 683 if (buf == NULL) { 684 wpa_printf(MSG_ERROR, "wpa_msg_global: Failed to allocate " 685 "message buffer"); 686 return; 687 } 688 va_start(ap, fmt); 689 len = vsnprintf(buf, buflen, fmt, ap); 690 va_end(ap); 691 wpa_printf(level, "%s", buf); 692 if (wpa_msg_cb) 693 wpa_msg_cb(ctx, level, 1, buf, len); 694 os_free(buf); 695 } 696 697 698 void wpa_msg_global_ctrl(void *ctx, int level, const char *fmt, ...) 699 { 700 va_list ap; 701 char *buf; 702 int buflen; 703 int len; 704 705 if (!wpa_msg_cb) 706 return; 707 708 va_start(ap, fmt); 709 buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 710 va_end(ap); 711 712 buf = os_malloc(buflen); 713 if (buf == NULL) { 714 wpa_printf(MSG_ERROR, 715 "wpa_msg_global_ctrl: Failed to allocate message buffer"); 716 return; 717 } 718 va_start(ap, fmt); 719 len = vsnprintf(buf, buflen, fmt, ap); 720 va_end(ap); 721 wpa_msg_cb(ctx, level, 1, buf, len); 722 os_free(buf); 723 } 724 725 726 void wpa_msg_no_global(void *ctx, int level, const char *fmt, ...) 727 { 728 va_list ap; 729 char *buf; 730 int buflen; 731 int len; 732 733 va_start(ap, fmt); 734 buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 735 va_end(ap); 736 737 buf = os_malloc(buflen); 738 if (buf == NULL) { 739 wpa_printf(MSG_ERROR, "wpa_msg_no_global: Failed to allocate " 740 "message buffer"); 741 return; 742 } 743 va_start(ap, fmt); 744 len = vsnprintf(buf, buflen, fmt, ap); 745 va_end(ap); 746 wpa_printf(level, "%s", buf); 747 if (wpa_msg_cb) 748 wpa_msg_cb(ctx, level, 2, buf, len); 749 os_free(buf); 750 } 751 752 #endif /* CONFIG_NO_WPA_MSG */ 753 754 755 #ifndef CONFIG_NO_HOSTAPD_LOGGER 756 static hostapd_logger_cb_func hostapd_logger_cb = NULL; 757 758 void hostapd_logger_register_cb(hostapd_logger_cb_func func) 759 { 760 hostapd_logger_cb = func; 761 } 762 763 764 void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level, 765 const char *fmt, ...) 766 { 767 va_list ap; 768 char *buf; 769 int buflen; 770 int len; 771 772 va_start(ap, fmt); 773 buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 774 va_end(ap); 775 776 buf = os_malloc(buflen); 777 if (buf == NULL) { 778 wpa_printf(MSG_ERROR, "hostapd_logger: Failed to allocate " 779 "message buffer"); 780 return; 781 } 782 va_start(ap, fmt); 783 len = vsnprintf(buf, buflen, fmt, ap); 784 va_end(ap); 785 if (hostapd_logger_cb) 786 hostapd_logger_cb(ctx, addr, module, level, buf, len); 787 else if (addr) 788 wpa_printf(MSG_DEBUG, "hostapd_logger: STA " MACSTR " - %s", 789 MAC2STR(addr), buf); 790 else 791 wpa_printf(MSG_DEBUG, "hostapd_logger: %s", buf); 792 os_free(buf); 793 } 794 #endif /* CONFIG_NO_HOSTAPD_LOGGER */ 795