1129473Spjd/* 2129473Spjd * wpa_supplicant/hostapd / Debug prints 3129473Spjd * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi> 4129473Spjd * 5129473Spjd * This software may be distributed under the terms of the BSD license. 6129473Spjd * See README for more details. 7129473Spjd */ 8129473Spjd 9129473Spjd#include "includes.h" 10129473Spjd 11129473Spjd#include "common.h" 12129473Spjd 13129473Spjd#ifdef CONFIG_DEBUG_SYSLOG 14129473Spjd#include <syslog.h> 15129473Spjd 16129473Spjdint wpa_debug_syslog = 0; 17129473Spjd#endif /* CONFIG_DEBUG_SYSLOG */ 18129473Spjd 19129473Spjd#ifdef CONFIG_DEBUG_LINUX_TRACING 20129473Spjd#include <sys/types.h> 21129473Spjd#include <sys/stat.h> 22129473Spjd#include <fcntl.h> 23129473Spjd#include <string.h> 24129473Spjd#include <stdio.h> 25129473Spjd 26129473Spjdstatic FILE *wpa_debug_tracing_file = NULL; 27129473Spjd 28129473Spjd#define WPAS_TRACE_PFX "wpas <%d>: " 29129473Spjd#endif /* CONFIG_DEBUG_LINUX_TRACING */ 30129473Spjd 31129473Spjd 32129473Spjdint wpa_debug_level = MSG_INFO; 33129473Spjdint wpa_debug_show_keys = 0; 34129473Spjdint wpa_debug_timestamp = 0; 35129473Spjd 36129473Spjd 37129473Spjd#ifdef CONFIG_ANDROID_LOG 38129473Spjd 39131878Spjd#include <android/log.h> 40129473Spjd 41129473Spjd#ifndef ANDROID_LOG_NAME 42129473Spjd#define ANDROID_LOG_NAME "wpa_supplicant" 43129473Spjd#endif /* ANDROID_LOG_NAME */ 44131878Spjd 45129473Spjdstatic int wpa_to_android_level(int level) 46129473Spjd{ 47131878Spjd if (level == MSG_ERROR) 48129473Spjd return ANDROID_LOG_ERROR; 49129473Spjd if (level == MSG_WARNING) 50129473Spjd return ANDROID_LOG_WARN; 51129473Spjd if (level == MSG_INFO) 52129473Spjd return ANDROID_LOG_INFO; 53129473Spjd return ANDROID_LOG_DEBUG; 54129473Spjd} 55129473Spjd 56131878Spjd#endif /* CONFIG_ANDROID_LOG */ 57131878Spjd 58129473Spjd#ifndef CONFIG_NO_STDOUT_DEBUG 59129473Spjd 60129473Spjd#ifdef CONFIG_DEBUG_FILE 61129473Spjd#include <sys/types.h> 62129473Spjd#include <sys/stat.h> 63131878Spjd#include <fcntl.h> 64131878Spjd 65131878Spjdstatic FILE *out_file = NULL; 66129473Spjd#endif /* CONFIG_DEBUG_FILE */ 67129473Spjd 68131878Spjd 69131878Spjdvoid wpa_debug_print_timestamp(void) 70131878Spjd{ 71131878Spjd#ifndef CONFIG_ANDROID_LOG 72131878Spjd struct os_time tv; 73131878Spjd 74131878Spjd if (!wpa_debug_timestamp) 75131878Spjd return; 76131878Spjd 77131878Spjd os_get_time(&tv); 78131878Spjd#ifdef CONFIG_DEBUG_FILE 79129473Spjd if (out_file) { 80131878Spjd fprintf(out_file, "%ld.%06u: ", (long) tv.sec, 81131878Spjd (unsigned int) tv.usec); 82131878Spjd } else 83131878Spjd#endif /* CONFIG_DEBUG_FILE */ 84131878Spjd printf("%ld.%06u: ", (long) tv.sec, (unsigned int) tv.usec); 85131878Spjd#endif /* CONFIG_ANDROID_LOG */ 86131878Spjd} 87132095Spjd 88131878Spjd 89131878Spjd#ifdef CONFIG_DEBUG_SYSLOG 90131878Spjd#ifndef LOG_HOSTAPD 91132095Spjd#define LOG_HOSTAPD LOG_DAEMON 92131878Spjd#endif /* LOG_HOSTAPD */ 93129473Spjd 94129473Spjdvoid wpa_debug_open_syslog(void) 95129473Spjd{ 96129473Spjd openlog("wpa_supplicant", LOG_PID | LOG_NDELAY, LOG_HOSTAPD); 97129473Spjd wpa_debug_syslog++; 98129473Spjd} 99129473Spjd 100129473Spjd 101129473Spjdvoid wpa_debug_close_syslog(void) 102129473Spjd{ 103129473Spjd if (wpa_debug_syslog) 104129473Spjd closelog(); 105129473Spjd} 106129473Spjd 107129473Spjd 108129473Spjdstatic int syslog_priority(int level) 109129473Spjd{ 110129473Spjd switch (level) { 111129473Spjd case MSG_MSGDUMP: 112129473Spjd case MSG_DEBUG: 113129473Spjd return LOG_DEBUG; 114129473Spjd case MSG_INFO: 115129473Spjd return LOG_NOTICE; 116129473Spjd case MSG_WARNING: 117129473Spjd return LOG_WARNING; 118129473Spjd case MSG_ERROR: 119131878Spjd return LOG_ERR; 120131878Spjd } 121131878Spjd return LOG_INFO; 122131878Spjd} 123131878Spjd#endif /* CONFIG_DEBUG_SYSLOG */ 124131878Spjd 125131878Spjd 126131878Spjd#ifdef CONFIG_DEBUG_LINUX_TRACING 127131878Spjd 128131878Spjdint wpa_debug_open_linux_tracing(void) 129131878Spjd{ 130131878Spjd int mounts, trace_fd; 131131878Spjd char buf[4096] = {}; 132131878Spjd ssize_t buflen; 133131878Spjd char *line, *tmp1, *path = NULL; 134131878Spjd 135131878Spjd mounts = open("/proc/mounts", O_RDONLY); 136129473Spjd if (mounts < 0) { 137129473Spjd printf("no /proc/mounts\n"); 138129473Spjd return -1; 139129473Spjd } 140129473Spjd 141129473Spjd buflen = read(mounts, buf, sizeof(buf) - 1); 142129473Spjd close(mounts); 143129473Spjd if (buflen < 0) { 144129473Spjd printf("failed to read /proc/mounts\n"); 145129473Spjd return -1; 146129473Spjd } 147129473Spjd buf[buflen] = '\0'; 148129473Spjd 149129473Spjd line = strtok_r(buf, "\n", &tmp1); 150129473Spjd while (line) { 151129473Spjd char *tmp2, *tmp_path, *fstype; 152129473Spjd /* "<dev> <mountpoint> <fs type> ..." */ 153129473Spjd strtok_r(line, " ", &tmp2); 154129473Spjd tmp_path = strtok_r(NULL, " ", &tmp2); 155129473Spjd fstype = strtok_r(NULL, " ", &tmp2); 156129473Spjd if (fstype && strcmp(fstype, "debugfs") == 0) { 157129473Spjd path = tmp_path; 158129473Spjd break; 159129473Spjd } 160129473Spjd 161129473Spjd line = strtok_r(NULL, "\n", &tmp1); 162129473Spjd } 163129473Spjd 164129473Spjd if (path == NULL) { 165132664Spjd printf("debugfs mountpoint not found\n"); 166129473Spjd return -1; 167129473Spjd } 168129473Spjd 169129473Spjd snprintf(buf, sizeof(buf) - 1, "%s/tracing/trace_marker", path); 170129473Spjd 171132664Spjd trace_fd = open(buf, O_WRONLY); 172129473Spjd if (trace_fd < 0) { 173129473Spjd printf("failed to open trace_marker file\n"); 174129473Spjd return -1; 175129473Spjd } 176129473Spjd wpa_debug_tracing_file = fdopen(trace_fd, "w"); 177129473Spjd if (wpa_debug_tracing_file == NULL) { 178129473Spjd close(trace_fd); 179129473Spjd printf("failed to fdopen()\n"); 180129473Spjd return -1; 181129473Spjd } 182129473Spjd 183129473Spjd return 0; 184129473Spjd} 185129473Spjd 186129473Spjd 187129473Spjdvoid wpa_debug_close_linux_tracing(void) 188129473Spjd{ 189129473Spjd if (wpa_debug_tracing_file == NULL) 190129473Spjd return; 191129473Spjd fclose(wpa_debug_tracing_file); 192129473Spjd wpa_debug_tracing_file = NULL; 193129473Spjd} 194129473Spjd 195129473Spjd#endif /* CONFIG_DEBUG_LINUX_TRACING */ 196129473Spjd 197129473Spjd 198129473Spjd/** 199129473Spjd * wpa_printf - conditional printf 200129473Spjd * @level: priority level (MSG_*) of the message 201129473Spjd * @fmt: printf format string, followed by optional arguments 202129473Spjd * 203129473Spjd * This function is used to print conditional debugging and error messages. The 204129473Spjd * output may be directed to stdout, stderr, and/or syslog based on 205129473Spjd * configuration. 206129473Spjd * 207129473Spjd * Note: New line '\n' is added to the end of the text when printing to stdout. 208129473Spjd */ 209129473Spjdvoid wpa_printf(int level, const char *fmt, ...) 210129473Spjd{ 211129473Spjd va_list ap; 212129473Spjd 213129473Spjd va_start(ap, fmt); 214129473Spjd if (level >= wpa_debug_level) { 215129473Spjd#ifdef CONFIG_ANDROID_LOG 216129473Spjd __android_log_vprint(wpa_to_android_level(level), 217129473Spjd ANDROID_LOG_NAME, fmt, ap); 218129473Spjd#else /* CONFIG_ANDROID_LOG */ 219129473Spjd#ifdef CONFIG_DEBUG_SYSLOG 220129473Spjd if (wpa_debug_syslog) { 221129473Spjd vsyslog(syslog_priority(level), fmt, ap); 222129473Spjd } else { 223129473Spjd#endif /* CONFIG_DEBUG_SYSLOG */ 224129473Spjd wpa_debug_print_timestamp(); 225129473Spjd#ifdef CONFIG_DEBUG_FILE 226129473Spjd if (out_file) { 227129473Spjd vfprintf(out_file, fmt, ap); 228129473Spjd fprintf(out_file, "\n"); 229129473Spjd } else { 230129473Spjd#endif /* CONFIG_DEBUG_FILE */ 231129473Spjd vprintf(fmt, ap); 232129473Spjd printf("\n"); 233129473Spjd#ifdef CONFIG_DEBUG_FILE 234129473Spjd } 235129473Spjd#endif /* CONFIG_DEBUG_FILE */ 236129473Spjd#ifdef CONFIG_DEBUG_SYSLOG 237129473Spjd } 238129473Spjd#endif /* CONFIG_DEBUG_SYSLOG */ 239129473Spjd#endif /* CONFIG_ANDROID_LOG */ 240129473Spjd } 241129473Spjd va_end(ap); 242129473Spjd 243129473Spjd#ifdef CONFIG_DEBUG_LINUX_TRACING 244129473Spjd if (wpa_debug_tracing_file != NULL) { 245129473Spjd va_start(ap, fmt); 246129473Spjd fprintf(wpa_debug_tracing_file, WPAS_TRACE_PFX, level); 247129473Spjd vfprintf(wpa_debug_tracing_file, fmt, ap); 248129473Spjd fprintf(wpa_debug_tracing_file, "\n"); 249129473Spjd fflush(wpa_debug_tracing_file); 250129473Spjd va_end(ap); 251131878Spjd } 252131878Spjd#endif /* CONFIG_DEBUG_LINUX_TRACING */ 253129473Spjd} 254131878Spjd 255131878Spjd 256131878Spjdstatic void _wpa_hexdump(int level, const char *title, const u8 *buf, 257131878Spjd size_t len, int show) 258131878Spjd{ 259131878Spjd size_t i; 260131878Spjd 261131878Spjd#ifdef CONFIG_DEBUG_LINUX_TRACING 262131878Spjd if (wpa_debug_tracing_file != NULL) { 263131878Spjd fprintf(wpa_debug_tracing_file, 264131878Spjd WPAS_TRACE_PFX "%s - hexdump(len=%lu):", 265131878Spjd level, title, (unsigned long) len); 266131878Spjd if (buf == NULL) { 267131878Spjd fprintf(wpa_debug_tracing_file, " [NULL]\n"); 268131878Spjd } else if (!show) { 269131878Spjd fprintf(wpa_debug_tracing_file, " [REMOVED]\n"); 270131878Spjd } else { 271131878Spjd for (i = 0; i < len; i++) 272131878Spjd fprintf(wpa_debug_tracing_file, 273131878Spjd " %02x", buf[i]); 274131878Spjd } 275131878Spjd fflush(wpa_debug_tracing_file); 276131878Spjd } 277131878Spjd#endif /* CONFIG_DEBUG_LINUX_TRACING */ 278131878Spjd 279131878Spjd if (level < wpa_debug_level) 280131878Spjd return; 281131878Spjd#ifdef CONFIG_ANDROID_LOG 282129473Spjd { 283131878Spjd const char *display; 284131878Spjd char *strbuf = NULL; 285131878Spjd size_t slen = len; 286131878Spjd if (buf == NULL) { 287131878Spjd display = " [NULL]"; 288131878Spjd } else if (len == 0) { 289131878Spjd display = ""; 290133204Spjd } else if (show && len) { 291133204Spjd /* Limit debug message length for Android log */ 292131878Spjd if (slen > 32) 293133204Spjd slen = 32; 294133204Spjd strbuf = os_malloc(1 + 3 * slen); 295131878Spjd if (strbuf == NULL) { 296131878Spjd wpa_printf(MSG_ERROR, "wpa_hexdump: Failed to " 297131878Spjd "allocate message buffer"); 298131878Spjd return; 299133204Spjd } 300133204Spjd 301131878Spjd for (i = 0; i < slen; i++) 302131878Spjd os_snprintf(&strbuf[i * 3], 4, " %02x", 303131878Spjd buf[i]); 304131878Spjd 305131878Spjd display = strbuf; 306131878Spjd } else { 307131878Spjd display = " [REMOVED]"; 308131878Spjd } 309131878Spjd 310131878Spjd __android_log_print(wpa_to_android_level(level), 311131878Spjd ANDROID_LOG_NAME, 312129473Spjd "%s - hexdump(len=%lu):%s%s", 313131878Spjd title, (long unsigned int) len, display, 314131878Spjd len > slen ? " ..." : ""); 315131878Spjd bin_clear_free(strbuf, 1 + 3 * slen); 316131878Spjd return; 317131878Spjd } 318131878Spjd#else /* CONFIG_ANDROID_LOG */ 319131878Spjd#ifdef CONFIG_DEBUG_SYSLOG 320131878Spjd if (wpa_debug_syslog) { 321131878Spjd const char *display; 322131878Spjd char *strbuf = NULL; 323131878Spjd 324131878Spjd if (buf == NULL) { 325131878Spjd display = " [NULL]"; 326131878Spjd } else if (len == 0) { 327131878Spjd display = ""; 328131878Spjd } else if (show && len) { 329131878Spjd strbuf = os_malloc(1 + 3 * len); 330131878Spjd if (strbuf == NULL) { 331131878Spjd wpa_printf(MSG_ERROR, "wpa_hexdump: Failed to " 332131878Spjd "allocate message buffer"); 333133204Spjd return; 334131878Spjd } 335133204Spjd 336131878Spjd for (i = 0; i < len; i++) 337131878Spjd os_snprintf(&strbuf[i * 3], 4, " %02x", 338131878Spjd buf[i]); 339131878Spjd 340131878Spjd display = strbuf; 341131878Spjd } else { 342131878Spjd display = " [REMOVED]"; 343131878Spjd } 344131878Spjd 345131878Spjd syslog(syslog_priority(level), "%s - hexdump(len=%lu):%s", 346131878Spjd title, (unsigned long) len, display); 347131878Spjd bin_clear_free(strbuf, 1 + 3 * len); 348131878Spjd return; 349131878Spjd } 350131878Spjd#endif /* CONFIG_DEBUG_SYSLOG */ 351131878Spjd wpa_debug_print_timestamp(); 352131878Spjd#ifdef CONFIG_DEBUG_FILE 353131878Spjd if (out_file) { 354131878Spjd fprintf(out_file, "%s - hexdump(len=%lu):", 355131878Spjd title, (unsigned long) len); 356131878Spjd if (buf == NULL) { 357131878Spjd fprintf(out_file, " [NULL]"); 358131878Spjd } else if (show) { 359133204Spjd for (i = 0; i < len; i++) 360133204Spjd fprintf(out_file, " %02x", buf[i]); 361131878Spjd } else { 362131878Spjd fprintf(out_file, " [REMOVED]"); 363131878Spjd } 364131878Spjd fprintf(out_file, "\n"); 365131878Spjd } else { 366131878Spjd#endif /* CONFIG_DEBUG_FILE */ 367131878Spjd printf("%s - hexdump(len=%lu):", title, (unsigned long) len); 368131878Spjd if (buf == NULL) { 369131878Spjd printf(" [NULL]"); 370131878Spjd } else if (show) { 371131878Spjd for (i = 0; i < len; i++) 372131878Spjd printf(" %02x", buf[i]); 373131878Spjd } else { 374131878Spjd printf(" [REMOVED]"); 375131878Spjd } 376131878Spjd printf("\n"); 377131878Spjd#ifdef CONFIG_DEBUG_FILE 378131878Spjd } 379131878Spjd#endif /* CONFIG_DEBUG_FILE */ 380131878Spjd#endif /* CONFIG_ANDROID_LOG */ 381131878Spjd} 382131878Spjd 383131878Spjdvoid wpa_hexdump(int level, const char *title, const void *buf, size_t len) 384131878Spjd{ 385133204Spjd _wpa_hexdump(level, title, buf, len, 1); 386131878Spjd} 387131878Spjd 388131878Spjd 389131878Spjdvoid wpa_hexdump_key(int level, const char *title, const void *buf, size_t len) 390131878Spjd{ 391133204Spjd _wpa_hexdump(level, title, buf, len, wpa_debug_show_keys); 392131878Spjd} 393131878Spjd 394131878Spjd 395131878Spjdstatic void _wpa_hexdump_ascii(int level, const char *title, const void *buf, 396131878Spjd size_t len, int show) 397131878Spjd{ 398131878Spjd size_t i, llen; 399131878Spjd const u8 *pos = buf; 400131878Spjd const size_t line_len = 16; 401131878Spjd 402131878Spjd#ifdef CONFIG_DEBUG_LINUX_TRACING 403133204Spjd if (wpa_debug_tracing_file != NULL) { 404133204Spjd fprintf(wpa_debug_tracing_file, 405131878Spjd WPAS_TRACE_PFX "%s - hexdump_ascii(len=%lu):", 406133204Spjd level, title, (unsigned long) len); 407131878Spjd if (buf == NULL) { 408131878Spjd fprintf(wpa_debug_tracing_file, " [NULL]\n"); 409133204Spjd } else if (!show) { 410131878Spjd fprintf(wpa_debug_tracing_file, " [REMOVED]\n"); 411131878Spjd } else { 412131878Spjd /* can do ascii processing in userspace */ 413131878Spjd for (i = 0; i < len; i++) 414131878Spjd fprintf(wpa_debug_tracing_file, 415131878Spjd " %02x", pos[i]); 416131878Spjd } 417131878Spjd fflush(wpa_debug_tracing_file); 418131878Spjd } 419131878Spjd#endif /* CONFIG_DEBUG_LINUX_TRACING */ 420131878Spjd 421131878Spjd if (level < wpa_debug_level) 422131878Spjd return; 423133204Spjd#ifdef CONFIG_ANDROID_LOG 424133204Spjd _wpa_hexdump(level, title, buf, len, show); 425133204Spjd#else /* CONFIG_ANDROID_LOG */ 426131878Spjd#ifdef CONFIG_DEBUG_SYSLOG 427133201Spjd if (wpa_debug_syslog) { 428131878Spjd _wpa_hexdump(level, title, buf, len, show); 429131878Spjd return; 430131878Spjd } 431131878Spjd#endif /* CONFIG_DEBUG_SYSLOG */ 432131878Spjd wpa_debug_print_timestamp(); 433131878Spjd#ifdef CONFIG_DEBUG_FILE 434131878Spjd if (out_file) { 435131878Spjd if (!show) { 436131878Spjd fprintf(out_file, 437131878Spjd "%s - hexdump_ascii(len=%lu): [REMOVED]\n", 438129473Spjd title, (unsigned long) len); 439131878Spjd return; 440129473Spjd } 441131878Spjd if (buf == NULL) { 442129473Spjd fprintf(out_file, 443131878Spjd "%s - hexdump_ascii(len=%lu): [NULL]\n", 444131878Spjd title, (unsigned long) len); 445131878Spjd return; 446131878Spjd } 447131878Spjd fprintf(out_file, "%s - hexdump_ascii(len=%lu):\n", 448131878Spjd title, (unsigned long) len); 449131878Spjd while (len) { 450131878Spjd llen = len > line_len ? line_len : len; 451131878Spjd fprintf(out_file, " "); 452131878Spjd for (i = 0; i < llen; i++) 453131878Spjd fprintf(out_file, " %02x", pos[i]); 454129473Spjd for (i = llen; i < line_len; i++) 455131878Spjd fprintf(out_file, " "); 456131878Spjd fprintf(out_file, " "); 457131878Spjd for (i = 0; i < llen; i++) { 458131878Spjd if (isprint(pos[i])) 459131878Spjd fprintf(out_file, "%c", pos[i]); 460131878Spjd else 461133204Spjd fprintf(out_file, "_"); 462131878Spjd } 463131878Spjd for (i = llen; i < line_len; i++) 464131878Spjd fprintf(out_file, " "); 465131878Spjd fprintf(out_file, "\n"); 466131878Spjd pos += llen; 467131878Spjd len -= llen; 468131878Spjd } 469131878Spjd } else { 470131878Spjd#endif /* CONFIG_DEBUG_FILE */ 471131878Spjd if (!show) { 472131878Spjd printf("%s - hexdump_ascii(len=%lu): [REMOVED]\n", 473131878Spjd title, (unsigned long) len); 474131878Spjd return; 475131878Spjd } 476131878Spjd if (buf == NULL) { 477131878Spjd printf("%s - hexdump_ascii(len=%lu): [NULL]\n", 478131878Spjd title, (unsigned long) len); 479131878Spjd return; 480131878Spjd } 481131878Spjd printf("%s - hexdump_ascii(len=%lu):\n", title, (unsigned long) len); 482131878Spjd while (len) { 483131878Spjd llen = len > line_len ? line_len : len; 484131878Spjd printf(" "); 485131878Spjd for (i = 0; i < llen; i++) 486131878Spjd printf(" %02x", pos[i]); 487131878Spjd for (i = llen; i < line_len; i++) 488131878Spjd printf(" "); 489131878Spjd printf(" "); 490131878Spjd for (i = 0; i < llen; i++) { 491133204Spjd if (isprint(pos[i])) 492131878Spjd printf("%c", pos[i]); 493131878Spjd else 494131878Spjd printf("_"); 495131878Spjd } 496131878Spjd for (i = llen; i < line_len; i++) 497131878Spjd printf(" "); 498131878Spjd printf("\n"); 499131878Spjd pos += llen; 500133204Spjd len -= llen; 501133204Spjd } 502131878Spjd#ifdef CONFIG_DEBUG_FILE 503131878Spjd } 504131878Spjd#endif /* CONFIG_DEBUG_FILE */ 505131878Spjd#endif /* CONFIG_ANDROID_LOG */ 506131878Spjd} 507131878Spjd 508131878Spjd 509131878Spjdvoid wpa_hexdump_ascii(int level, const char *title, const void *buf, 510133201Spjd size_t len) 511131878Spjd{ 512131878Spjd _wpa_hexdump_ascii(level, title, buf, len, 1); 513131878Spjd} 514131878Spjd 515131878Spjd 516131878Spjdvoid wpa_hexdump_ascii_key(int level, const char *title, const void *buf, 517131878Spjd size_t len) 518131878Spjd{ 519131878Spjd _wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys); 520131878Spjd} 521131878Spjd 522131878Spjd 523131878Spjd#ifdef CONFIG_DEBUG_FILE 524131878Spjdstatic char *last_path = NULL; 525131878Spjd#endif /* CONFIG_DEBUG_FILE */ 526129473Spjd 527129473Spjdint wpa_debug_reopen_file(void) 528129473Spjd{ 529129473Spjd#ifdef CONFIG_DEBUG_FILE 530129473Spjd int rv; 531129473Spjd char *tmp; 532129473Spjd 533129473Spjd if (!last_path) 534129473Spjd return 0; /* logfile not used */ 535129473Spjd 536129473Spjd tmp = os_strdup(last_path); 537129473Spjd if (!tmp) 538129473Spjd return -1; 539129473Spjd 540129473Spjd wpa_debug_close_file(); 541129473Spjd rv = wpa_debug_open_file(tmp); 542129473Spjd os_free(tmp); 543129473Spjd return rv; 544129473Spjd#else /* CONFIG_DEBUG_FILE */ 545129473Spjd return 0; 546129473Spjd#endif /* CONFIG_DEBUG_FILE */ 547129473Spjd} 548129473Spjd 549129473Spjd 550129473Spjdint wpa_debug_open_file(const char *path) 551129473Spjd{ 552129473Spjd#ifdef CONFIG_DEBUG_FILE 553131878Spjd int out_fd; 554129473Spjd 555129473Spjd if (!path) 556129473Spjd return 0; 557129473Spjd 558129473Spjd if (last_path == NULL || os_strcmp(last_path, path) != 0) { 559129473Spjd /* Save our path to enable re-open */ 560129473Spjd os_free(last_path); 561129473Spjd last_path = os_strdup(path); 562129473Spjd } 563129473Spjd 564129473Spjd out_fd = open(path, O_CREAT | O_APPEND | O_WRONLY, 565131878Spjd S_IRUSR | S_IWUSR | S_IRGRP); 566131878Spjd if (out_fd < 0) { 567129473Spjd wpa_printf(MSG_ERROR, 568129473Spjd "%s: Failed to open output file descriptor, using standard output", 569129473Spjd __func__); 570131878Spjd return -1; 571131878Spjd } 572131878Spjd 573131878Spjd#ifdef __linux__ 574131878Spjd if (fcntl(out_fd, F_SETFD, FD_CLOEXEC) < 0) { 575131878Spjd wpa_printf(MSG_DEBUG, 576131878Spjd "%s: Failed to set FD_CLOEXEC - continue without: %s", 577131878Spjd __func__, strerror(errno)); 578131878Spjd } 579131878Spjd#endif /* __linux__ */ 580131878Spjd 581131878Spjd out_file = fdopen(out_fd, "a"); 582131878Spjd if (out_file == NULL) { 583131878Spjd wpa_printf(MSG_ERROR, "wpa_debug_open_file: Failed to open " 584129473Spjd "output file, using standard output"); 585131878Spjd close(out_fd); 586131878Spjd return -1; 587131878Spjd } 588129473Spjd#ifndef _WIN32 589131878Spjd setvbuf(out_file, NULL, _IOLBF, 0); 590131878Spjd#endif /* _WIN32 */ 591131878Spjd#else /* CONFIG_DEBUG_FILE */ 592131878Spjd (void)path; 593129473Spjd#endif /* CONFIG_DEBUG_FILE */ 594131878Spjd return 0; 595131878Spjd} 596131878Spjd 597131878Spjd 598131878Spjdvoid wpa_debug_close_file(void) 599131878Spjd{ 600129473Spjd#ifdef CONFIG_DEBUG_FILE 601129473Spjd if (!out_file) 602129473Spjd return; 603129473Spjd fclose(out_file); 604129473Spjd out_file = NULL; 605129473Spjd os_free(last_path); 606129473Spjd last_path = NULL; 607129473Spjd#endif /* CONFIG_DEBUG_FILE */ 608129473Spjd} 609129473Spjd 610129473Spjd 611129473Spjdvoid wpa_debug_setup_stdout(void) 612132664Spjd{ 613132664Spjd#ifndef _WIN32 614129473Spjd setvbuf(stdout, NULL, _IOLBF, 0); 615129473Spjd#endif /* _WIN32 */ 616129473Spjd} 617129473Spjd 618129473Spjd#endif /* CONFIG_NO_STDOUT_DEBUG */ 619129473Spjd 620129473Spjd 621129473Spjd#ifndef CONFIG_NO_WPA_MSG 622129473Spjdstatic wpa_msg_cb_func wpa_msg_cb = NULL; 623129473Spjd 624129473Spjdvoid wpa_msg_register_cb(wpa_msg_cb_func func) 625129473Spjd{ 626129473Spjd wpa_msg_cb = func; 627129473Spjd} 628129473Spjd 629129473Spjd 630129473Spjdstatic wpa_msg_get_ifname_func wpa_msg_ifname_cb = NULL; 631129473Spjd 632129473Spjdvoid wpa_msg_register_ifname_cb(wpa_msg_get_ifname_func func) 633129473Spjd{ 634129473Spjd wpa_msg_ifname_cb = func; 635129473Spjd} 636132664Spjd 637129473Spjd 638129473Spjdvoid wpa_msg(void *ctx, int level, const char *fmt, ...) 639129473Spjd{ 640129473Spjd va_list ap; 641129473Spjd char *buf; 642129473Spjd int buflen; 643129473Spjd int len; 644129473Spjd char prefix[130]; 645129473Spjd 646129473Spjd va_start(ap, fmt); 647129473Spjd buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 648129473Spjd va_end(ap); 649129473Spjd 650129473Spjd buf = os_malloc(buflen); 651129473Spjd if (buf == NULL) { 652129473Spjd wpa_printf(MSG_ERROR, "wpa_msg: Failed to allocate message " 653129473Spjd "buffer"); 654129473Spjd return; 655129473Spjd } 656129473Spjd va_start(ap, fmt); 657129473Spjd prefix[0] = '\0'; 658129473Spjd if (wpa_msg_ifname_cb) { 659129473Spjd const char *ifname = wpa_msg_ifname_cb(ctx); 660129473Spjd if (ifname) { 661129473Spjd int res = os_snprintf(prefix, sizeof(prefix), "%s: ", 662129473Spjd ifname); 663129473Spjd if (os_snprintf_error(sizeof(prefix), res)) 664129473Spjd prefix[0] = '\0'; 665129473Spjd } 666129473Spjd } 667129473Spjd len = vsnprintf(buf, buflen, fmt, ap); 668129473Spjd va_end(ap); 669129473Spjd wpa_printf(level, "%s%s", prefix, buf); 670129473Spjd if (wpa_msg_cb) 671129473Spjd wpa_msg_cb(ctx, level, WPA_MSG_PER_INTERFACE, buf, len); 672129473Spjd bin_clear_free(buf, buflen); 673129473Spjd} 674129473Spjd 675129473Spjd 676129473Spjdvoid wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...) 677129473Spjd{ 678129473Spjd va_list ap; 679129473Spjd char *buf; 680129473Spjd int buflen; 681129473Spjd int len; 682129473Spjd 683129473Spjd if (!wpa_msg_cb) 684129473Spjd return; 685129473Spjd 686129473Spjd va_start(ap, fmt); 687129473Spjd buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 688129473Spjd va_end(ap); 689129473Spjd 690129473Spjd buf = os_malloc(buflen); 691129473Spjd if (buf == NULL) { 692129473Spjd wpa_printf(MSG_ERROR, "wpa_msg_ctrl: Failed to allocate " 693129473Spjd "message buffer"); 694129473Spjd return; 695129473Spjd } 696129473Spjd va_start(ap, fmt); 697129473Spjd len = vsnprintf(buf, buflen, fmt, ap); 698129473Spjd va_end(ap); 699129473Spjd wpa_msg_cb(ctx, level, WPA_MSG_PER_INTERFACE, buf, len); 700129473Spjd bin_clear_free(buf, buflen); 701129473Spjd} 702129473Spjd 703129473Spjd 704129473Spjdvoid wpa_msg_global(void *ctx, int level, const char *fmt, ...) 705129473Spjd{ 706129473Spjd va_list ap; 707129473Spjd char *buf; 708129473Spjd int buflen; 709129473Spjd int len; 710129473Spjd 711129473Spjd va_start(ap, fmt); 712129473Spjd buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 713129473Spjd va_end(ap); 714129473Spjd 715129473Spjd buf = os_malloc(buflen); 716129473Spjd if (buf == NULL) { 717129473Spjd wpa_printf(MSG_ERROR, "wpa_msg_global: Failed to allocate " 718129473Spjd "message buffer"); 719129473Spjd return; 720129473Spjd } 721129473Spjd va_start(ap, fmt); 722129473Spjd len = vsnprintf(buf, buflen, fmt, ap); 723132664Spjd va_end(ap); 724129473Spjd wpa_printf(level, "%s", buf); 725129473Spjd if (wpa_msg_cb) 726129473Spjd wpa_msg_cb(ctx, level, WPA_MSG_GLOBAL, buf, len); 727129473Spjd bin_clear_free(buf, buflen); 728129473Spjd} 729129473Spjd 730129473Spjd 731129473Spjdvoid wpa_msg_global_ctrl(void *ctx, int level, const char *fmt, ...) 732129473Spjd{ 733129473Spjd va_list ap; 734129473Spjd char *buf; 735129473Spjd int buflen; 736129473Spjd int len; 737129473Spjd 738129473Spjd if (!wpa_msg_cb) 739129473Spjd return; 740129473Spjd 741129473Spjd va_start(ap, fmt); 742129473Spjd buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 743129473Spjd va_end(ap); 744132664Spjd 745129473Spjd buf = os_malloc(buflen); 746129473Spjd if (buf == NULL) { 747129473Spjd wpa_printf(MSG_ERROR, 748132664Spjd "wpa_msg_global_ctrl: Failed to allocate message buffer"); 749132664Spjd return; 750129473Spjd } 751129473Spjd va_start(ap, fmt); 752129473Spjd len = vsnprintf(buf, buflen, fmt, ap); 753129473Spjd va_end(ap); 754129473Spjd wpa_msg_cb(ctx, level, WPA_MSG_GLOBAL, buf, len); 755132664Spjd bin_clear_free(buf, buflen); 756129473Spjd} 757129473Spjd 758129473Spjd 759129473Spjdvoid wpa_msg_no_global(void *ctx, int level, const char *fmt, ...) 760129473Spjd{ 761132664Spjd va_list ap; 762129473Spjd char *buf; 763129473Spjd int buflen; 764129473Spjd int len; 765129473Spjd 766129473Spjd va_start(ap, fmt); 767129473Spjd buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 768129473Spjd va_end(ap); 769129473Spjd 770132664Spjd buf = os_malloc(buflen); 771129473Spjd if (buf == NULL) { 772129473Spjd wpa_printf(MSG_ERROR, "wpa_msg_no_global: Failed to allocate " 773129473Spjd "message buffer"); 774132664Spjd return; 775129473Spjd } 776129473Spjd va_start(ap, fmt); 777132662Spjd len = vsnprintf(buf, buflen, fmt, ap); 778129473Spjd va_end(ap); 779129473Spjd wpa_printf(level, "%s", buf); 780129473Spjd if (wpa_msg_cb) 781129473Spjd wpa_msg_cb(ctx, level, WPA_MSG_NO_GLOBAL, buf, len); 782129473Spjd bin_clear_free(buf, buflen); 783129473Spjd} 784129473Spjd 785129473Spjd 786129473Spjdvoid wpa_msg_global_only(void *ctx, int level, const char *fmt, ...) 787129473Spjd{ 788129473Spjd va_list ap; 789129473Spjd char *buf; 790129473Spjd int buflen; 791129473Spjd int len; 792129473Spjd 793129473Spjd va_start(ap, fmt); 794129473Spjd buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 795129473Spjd va_end(ap); 796129473Spjd 797129473Spjd buf = os_malloc(buflen); 798132664Spjd if (buf == NULL) { 799129473Spjd wpa_printf(MSG_ERROR, "%s: Failed to allocate message buffer", 800129473Spjd __func__); 801129473Spjd return; 802129473Spjd } 803129473Spjd va_start(ap, fmt); 804129473Spjd len = vsnprintf(buf, buflen, fmt, ap); 805129473Spjd va_end(ap); 806129473Spjd wpa_printf(level, "%s", buf); 807129473Spjd if (wpa_msg_cb) 808129473Spjd wpa_msg_cb(ctx, level, WPA_MSG_ONLY_GLOBAL, buf, len); 809129473Spjd os_free(buf); 810129473Spjd} 811129473Spjd 812129473Spjd#endif /* CONFIG_NO_WPA_MSG */ 813129473Spjd 814129473Spjd 815129473Spjd#ifndef CONFIG_NO_HOSTAPD_LOGGER 816129473Spjdstatic hostapd_logger_cb_func hostapd_logger_cb = NULL; 817129473Spjd 818129473Spjdvoid hostapd_logger_register_cb(hostapd_logger_cb_func func) 819129473Spjd{ 820129473Spjd hostapd_logger_cb = func; 821129473Spjd} 822129473Spjd 823129473Spjd 824129473Spjdvoid hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level, 825129473Spjd const char *fmt, ...) 826129473Spjd{ 827129473Spjd va_list ap; 828129473Spjd char *buf; 829129473Spjd int buflen; 830129473Spjd int len; 831129473Spjd 832129473Spjd va_start(ap, fmt); 833129473Spjd buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 834129473Spjd va_end(ap); 835129473Spjd 836129473Spjd buf = os_malloc(buflen); 837129473Spjd if (buf == NULL) { 838129473Spjd wpa_printf(MSG_ERROR, "hostapd_logger: Failed to allocate " 839129473Spjd "message buffer"); 840129473Spjd return; 841129473Spjd } 842129473Spjd va_start(ap, fmt); 843129473Spjd len = vsnprintf(buf, buflen, fmt, ap); 844129473Spjd va_end(ap); 845129473Spjd if (hostapd_logger_cb) 846129473Spjd hostapd_logger_cb(ctx, addr, module, level, buf, len); 847129473Spjd else if (addr) 848129473Spjd wpa_printf(MSG_DEBUG, "hostapd_logger: STA " MACSTR " - %s", 849129473Spjd MAC2STR(addr), buf); 850129473Spjd else 851129473Spjd wpa_printf(MSG_DEBUG, "hostapd_logger: %s", buf); 852129473Spjd bin_clear_free(buf, buflen); 853129473Spjd} 854129473Spjd#endif /* CONFIG_NO_HOSTAPD_LOGGER */ 855129473Spjd 856129473Spjd 857129473Spjdconst char * debug_level_str(int level) 858129473Spjd{ 859129473Spjd switch (level) { 860129473Spjd case MSG_EXCESSIVE: 861129473Spjd return "EXCESSIVE"; 862129473Spjd case MSG_MSGDUMP: 863129473Spjd return "MSGDUMP"; 864129473Spjd case MSG_DEBUG: 865129473Spjd return "DEBUG"; 866129473Spjd case MSG_INFO: 867129473Spjd return "INFO"; 868129473Spjd case MSG_WARNING: 869129473Spjd return "WARNING"; 870129473Spjd case MSG_ERROR: 871129473Spjd return "ERROR"; 872129473Spjd default: 873129473Spjd return "?"; 874129473Spjd } 875129473Spjd} 876129473Spjd 877129473Spjd 878129473Spjdint str_to_debug_level(const char *s) 879129473Spjd{ 880129473Spjd if (os_strcasecmp(s, "EXCESSIVE") == 0) 881129473Spjd return MSG_EXCESSIVE; 882129473Spjd if (os_strcasecmp(s, "MSGDUMP") == 0) 883129473Spjd return MSG_MSGDUMP; 884129473Spjd if (os_strcasecmp(s, "DEBUG") == 0) 885129473Spjd return MSG_DEBUG; 886129473Spjd if (os_strcasecmp(s, "INFO") == 0) 887129473Spjd return MSG_INFO; 888129473Spjd if (os_strcasecmp(s, "WARNING") == 0) 889129473Spjd return MSG_WARNING; 890129473Spjd if (os_strcasecmp(s, "ERROR") == 0) 891129473Spjd return MSG_ERROR; 892129473Spjd return -1; 893129473Spjd} 894129473Spjd