18dbcf02cSchristos /* 28dbcf02cSchristos * wpa_supplicant/hostapd / Debug prints 33c260e60Schristos * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi> 48dbcf02cSchristos * 5e604d861Schristos * This software may be distributed under the terms of the BSD license. 6e604d861Schristos * See README for more details. 78dbcf02cSchristos */ 88dbcf02cSchristos 98dbcf02cSchristos #include "includes.h" 108dbcf02cSchristos 118dbcf02cSchristos #include "common.h" 128dbcf02cSchristos 138dbcf02cSchristos #ifdef CONFIG_DEBUG_SYSLOG 148dbcf02cSchristos #include <syslog.h> 158dbcf02cSchristos #endif /* CONFIG_DEBUG_SYSLOG */ 168dbcf02cSchristos 17e604d861Schristos #ifdef CONFIG_DEBUG_LINUX_TRACING 18e604d861Schristos #include <sys/types.h> 19e604d861Schristos #include <sys/stat.h> 20e604d861Schristos #include <fcntl.h> 21e604d861Schristos #include <string.h> 22e604d861Schristos #include <stdio.h> 23e604d861Schristos 24e604d861Schristos static FILE *wpa_debug_tracing_file = NULL; 25e604d861Schristos 26e604d861Schristos #define WPAS_TRACE_PFX "wpas <%d>: " 27e604d861Schristos #endif /* CONFIG_DEBUG_LINUX_TRACING */ 28e604d861Schristos 298dbcf02cSchristos 308dbcf02cSchristos int wpa_debug_level = MSG_INFO; 318dbcf02cSchristos int wpa_debug_show_keys = 0; 328dbcf02cSchristos int wpa_debug_timestamp = 0; 33*bb618362Schristos int wpa_debug_syslog = 0; 34*bb618362Schristos #ifndef CONFIG_NO_STDOUT_DEBUG 35*bb618362Schristos static FILE *out_file = NULL; 36*bb618362Schristos #endif /* CONFIG_NO_STDOUT_DEBUG */ 378dbcf02cSchristos 388dbcf02cSchristos 39111b9fd8Schristos #ifdef CONFIG_ANDROID_LOG 40111b9fd8Schristos 41111b9fd8Schristos #include <android/log.h> 42111b9fd8Schristos 43111b9fd8Schristos #ifndef ANDROID_LOG_NAME 44111b9fd8Schristos #define ANDROID_LOG_NAME "wpa_supplicant" 45111b9fd8Schristos #endif /* ANDROID_LOG_NAME */ 46111b9fd8Schristos 47e604d861Schristos static int wpa_to_android_level(int level) 48111b9fd8Schristos { 49111b9fd8Schristos if (level == MSG_ERROR) 50e604d861Schristos return ANDROID_LOG_ERROR; 51e604d861Schristos if (level == MSG_WARNING) 52e604d861Schristos return ANDROID_LOG_WARN; 53e604d861Schristos if (level == MSG_INFO) 54e604d861Schristos return ANDROID_LOG_INFO; 55e604d861Schristos return ANDROID_LOG_DEBUG; 56111b9fd8Schristos } 57111b9fd8Schristos 58e604d861Schristos #endif /* CONFIG_ANDROID_LOG */ 59111b9fd8Schristos 608dbcf02cSchristos #ifndef CONFIG_NO_STDOUT_DEBUG 618dbcf02cSchristos 62111b9fd8Schristos #ifdef CONFIG_DEBUG_FILE 630a73ee0aSchristos #include <sys/types.h> 640a73ee0aSchristos #include <sys/stat.h> 650a73ee0aSchristos #include <fcntl.h> 66111b9fd8Schristos #endif /* CONFIG_DEBUG_FILE */ 67111b9fd8Schristos 68111b9fd8Schristos 698dbcf02cSchristos void wpa_debug_print_timestamp(void) 708dbcf02cSchristos { 71e604d861Schristos #ifndef CONFIG_ANDROID_LOG 728dbcf02cSchristos struct os_time tv; 738dbcf02cSchristos 748dbcf02cSchristos if (!wpa_debug_timestamp) 758dbcf02cSchristos return; 768dbcf02cSchristos 778dbcf02cSchristos os_get_time(&tv); 788dbcf02cSchristos #ifdef CONFIG_DEBUG_FILE 79*bb618362Schristos if (out_file) 808dbcf02cSchristos fprintf(out_file, "%ld.%06u: ", (long) tv.sec, 818dbcf02cSchristos (unsigned int) tv.usec); 828dbcf02cSchristos #endif /* CONFIG_DEBUG_FILE */ 83*bb618362Schristos if (!out_file && !wpa_debug_syslog) 848dbcf02cSchristos printf("%ld.%06u: ", (long) tv.sec, (unsigned int) tv.usec); 85e604d861Schristos #endif /* CONFIG_ANDROID_LOG */ 868dbcf02cSchristos } 878dbcf02cSchristos 888dbcf02cSchristos 898dbcf02cSchristos #ifdef CONFIG_DEBUG_SYSLOG 90111b9fd8Schristos #ifndef LOG_HOSTAPD 91111b9fd8Schristos #define LOG_HOSTAPD LOG_DAEMON 92111b9fd8Schristos #endif /* LOG_HOSTAPD */ 93111b9fd8Schristos 948dbcf02cSchristos void wpa_debug_open_syslog(void) 958dbcf02cSchristos { 96111b9fd8Schristos openlog("wpa_supplicant", LOG_PID | LOG_NDELAY, LOG_HOSTAPD); 978dbcf02cSchristos wpa_debug_syslog++; 988dbcf02cSchristos } 998dbcf02cSchristos 1008dbcf02cSchristos 1018dbcf02cSchristos void wpa_debug_close_syslog(void) 1028dbcf02cSchristos { 1038dbcf02cSchristos if (wpa_debug_syslog) 1048dbcf02cSchristos closelog(); 1058dbcf02cSchristos } 1068dbcf02cSchristos 1078dbcf02cSchristos 1088dbcf02cSchristos static int syslog_priority(int level) 1098dbcf02cSchristos { 1108dbcf02cSchristos switch (level) { 1118dbcf02cSchristos case MSG_MSGDUMP: 1128dbcf02cSchristos case MSG_DEBUG: 1138dbcf02cSchristos return LOG_DEBUG; 1148dbcf02cSchristos case MSG_INFO: 1158dbcf02cSchristos return LOG_NOTICE; 1168dbcf02cSchristos case MSG_WARNING: 1178dbcf02cSchristos return LOG_WARNING; 1188dbcf02cSchristos case MSG_ERROR: 1198dbcf02cSchristos return LOG_ERR; 1208dbcf02cSchristos } 1218dbcf02cSchristos return LOG_INFO; 1228dbcf02cSchristos } 1238dbcf02cSchristos #endif /* CONFIG_DEBUG_SYSLOG */ 1248dbcf02cSchristos 1258dbcf02cSchristos 126e604d861Schristos #ifdef CONFIG_DEBUG_LINUX_TRACING 127e604d861Schristos 128e604d861Schristos int wpa_debug_open_linux_tracing(void) 129e604d861Schristos { 130e604d861Schristos int mounts, trace_fd; 131e604d861Schristos char buf[4096] = {}; 132e604d861Schristos ssize_t buflen; 133e604d861Schristos char *line, *tmp1, *path = NULL; 134e604d861Schristos 135e604d861Schristos mounts = open("/proc/mounts", O_RDONLY); 136e604d861Schristos if (mounts < 0) { 137e604d861Schristos printf("no /proc/mounts\n"); 138e604d861Schristos return -1; 139e604d861Schristos } 140e604d861Schristos 141e604d861Schristos buflen = read(mounts, buf, sizeof(buf) - 1); 142e604d861Schristos close(mounts); 143e604d861Schristos if (buflen < 0) { 144e604d861Schristos printf("failed to read /proc/mounts\n"); 145e604d861Schristos return -1; 146e604d861Schristos } 1473d6c0713Schristos buf[buflen] = '\0'; 148e604d861Schristos 149e604d861Schristos line = strtok_r(buf, "\n", &tmp1); 150e604d861Schristos while (line) { 151e604d861Schristos char *tmp2, *tmp_path, *fstype; 152e604d861Schristos /* "<dev> <mountpoint> <fs type> ..." */ 153e604d861Schristos strtok_r(line, " ", &tmp2); 154e604d861Schristos tmp_path = strtok_r(NULL, " ", &tmp2); 155e604d861Schristos fstype = strtok_r(NULL, " ", &tmp2); 15636ebd06eSchristos if (fstype && strcmp(fstype, "debugfs") == 0) { 157e604d861Schristos path = tmp_path; 158e604d861Schristos break; 159e604d861Schristos } 160e604d861Schristos 161e604d861Schristos line = strtok_r(NULL, "\n", &tmp1); 162e604d861Schristos } 163e604d861Schristos 164e604d861Schristos if (path == NULL) { 165e604d861Schristos printf("debugfs mountpoint not found\n"); 166e604d861Schristos return -1; 167e604d861Schristos } 168e604d861Schristos 169e604d861Schristos snprintf(buf, sizeof(buf) - 1, "%s/tracing/trace_marker", path); 170e604d861Schristos 171e604d861Schristos trace_fd = open(buf, O_WRONLY); 172e604d861Schristos if (trace_fd < 0) { 173e604d861Schristos printf("failed to open trace_marker file\n"); 174e604d861Schristos return -1; 175e604d861Schristos } 176e604d861Schristos wpa_debug_tracing_file = fdopen(trace_fd, "w"); 177e604d861Schristos if (wpa_debug_tracing_file == NULL) { 178e604d861Schristos close(trace_fd); 179e604d861Schristos printf("failed to fdopen()\n"); 180e604d861Schristos return -1; 181e604d861Schristos } 182e604d861Schristos 183e604d861Schristos return 0; 184e604d861Schristos } 185e604d861Schristos 186e604d861Schristos 187e604d861Schristos void wpa_debug_close_linux_tracing(void) 188e604d861Schristos { 189e604d861Schristos if (wpa_debug_tracing_file == NULL) 190e604d861Schristos return; 191e604d861Schristos fclose(wpa_debug_tracing_file); 192e604d861Schristos wpa_debug_tracing_file = NULL; 193e604d861Schristos } 194e604d861Schristos 195e604d861Schristos #endif /* CONFIG_DEBUG_LINUX_TRACING */ 196e604d861Schristos 197e604d861Schristos 1988dbcf02cSchristos /** 1998dbcf02cSchristos * wpa_printf - conditional printf 2008dbcf02cSchristos * @level: priority level (MSG_*) of the message 2018dbcf02cSchristos * @fmt: printf format string, followed by optional arguments 2028dbcf02cSchristos * 2038dbcf02cSchristos * This function is used to print conditional debugging and error messages. The 2048dbcf02cSchristos * output may be directed to stdout, stderr, and/or syslog based on 2058dbcf02cSchristos * configuration. 2068dbcf02cSchristos * 2078dbcf02cSchristos * Note: New line '\n' is added to the end of the text when printing to stdout. 2088dbcf02cSchristos */ 2098dbcf02cSchristos void wpa_printf(int level, const char *fmt, ...) 2108dbcf02cSchristos { 2118dbcf02cSchristos va_list ap; 2128dbcf02cSchristos 2138dbcf02cSchristos if (level >= wpa_debug_level) { 214e604d861Schristos #ifdef CONFIG_ANDROID_LOG 215*bb618362Schristos va_start(ap, fmt); 216e604d861Schristos __android_log_vprint(wpa_to_android_level(level), 217e604d861Schristos ANDROID_LOG_NAME, fmt, ap); 218*bb618362Schristos va_end(ap); 219e604d861Schristos #else /* CONFIG_ANDROID_LOG */ 2208dbcf02cSchristos #ifdef CONFIG_DEBUG_SYSLOG 2218dbcf02cSchristos if (wpa_debug_syslog) { 222*bb618362Schristos va_start(ap, fmt); 2238dbcf02cSchristos vsyslog(syslog_priority(level), fmt, ap); 224*bb618362Schristos va_end(ap); 225*bb618362Schristos } 2268dbcf02cSchristos #endif /* CONFIG_DEBUG_SYSLOG */ 2278dbcf02cSchristos wpa_debug_print_timestamp(); 2288dbcf02cSchristos #ifdef CONFIG_DEBUG_FILE 2298dbcf02cSchristos if (out_file) { 230*bb618362Schristos va_start(ap, fmt); 2318dbcf02cSchristos vfprintf(out_file, fmt, ap); 2328dbcf02cSchristos fprintf(out_file, "\n"); 233*bb618362Schristos va_end(ap); 234*bb618362Schristos } 2358dbcf02cSchristos #endif /* CONFIG_DEBUG_FILE */ 236*bb618362Schristos if (!wpa_debug_syslog && !out_file) { 237*bb618362Schristos va_start(ap, fmt); 2388dbcf02cSchristos vprintf(fmt, ap); 2398dbcf02cSchristos printf("\n"); 240*bb618362Schristos va_end(ap); 2418dbcf02cSchristos } 242e604d861Schristos #endif /* CONFIG_ANDROID_LOG */ 2438dbcf02cSchristos } 244e604d861Schristos 245e604d861Schristos #ifdef CONFIG_DEBUG_LINUX_TRACING 246e604d861Schristos if (wpa_debug_tracing_file != NULL) { 247e604d861Schristos va_start(ap, fmt); 248e604d861Schristos fprintf(wpa_debug_tracing_file, WPAS_TRACE_PFX, level); 249e604d861Schristos vfprintf(wpa_debug_tracing_file, fmt, ap); 250e604d861Schristos fprintf(wpa_debug_tracing_file, "\n"); 251e604d861Schristos fflush(wpa_debug_tracing_file); 252e604d861Schristos va_end(ap); 253e604d861Schristos } 254e604d861Schristos #endif /* CONFIG_DEBUG_LINUX_TRACING */ 2558dbcf02cSchristos } 2568dbcf02cSchristos 2578dbcf02cSchristos 2588dbcf02cSchristos static void _wpa_hexdump(int level, const char *title, const u8 *buf, 259*bb618362Schristos size_t len, int show, int only_syslog) 2608dbcf02cSchristos { 2618dbcf02cSchristos size_t i; 262e604d861Schristos 263e604d861Schristos #ifdef CONFIG_DEBUG_LINUX_TRACING 264e604d861Schristos if (wpa_debug_tracing_file != NULL) { 265e604d861Schristos fprintf(wpa_debug_tracing_file, 266e604d861Schristos WPAS_TRACE_PFX "%s - hexdump(len=%lu):", 267e604d861Schristos level, title, (unsigned long) len); 268e604d861Schristos if (buf == NULL) { 269e604d861Schristos fprintf(wpa_debug_tracing_file, " [NULL]\n"); 270e604d861Schristos } else if (!show) { 271e604d861Schristos fprintf(wpa_debug_tracing_file, " [REMOVED]\n"); 272e604d861Schristos } else { 273e604d861Schristos for (i = 0; i < len; i++) 274e604d861Schristos fprintf(wpa_debug_tracing_file, 275e604d861Schristos " %02x", buf[i]); 276e604d861Schristos } 277e604d861Schristos fflush(wpa_debug_tracing_file); 278e604d861Schristos } 279e604d861Schristos #endif /* CONFIG_DEBUG_LINUX_TRACING */ 280e604d861Schristos 2818dbcf02cSchristos if (level < wpa_debug_level) 2828dbcf02cSchristos return; 283e604d861Schristos #ifdef CONFIG_ANDROID_LOG 284e604d861Schristos { 285e604d861Schristos const char *display; 286e604d861Schristos char *strbuf = NULL; 287e604d861Schristos size_t slen = len; 288e604d861Schristos if (buf == NULL) { 289e604d861Schristos display = " [NULL]"; 290e604d861Schristos } else if (len == 0) { 291e604d861Schristos display = ""; 292e604d861Schristos } else if (show && len) { 293e604d861Schristos /* Limit debug message length for Android log */ 294e604d861Schristos if (slen > 32) 295e604d861Schristos slen = 32; 296e604d861Schristos strbuf = os_malloc(1 + 3 * slen); 297e604d861Schristos if (strbuf == NULL) { 298e604d861Schristos wpa_printf(MSG_ERROR, "wpa_hexdump: Failed to " 299e604d861Schristos "allocate message buffer"); 300e604d861Schristos return; 301e604d861Schristos } 302e604d861Schristos 303e604d861Schristos for (i = 0; i < slen; i++) 304e604d861Schristos os_snprintf(&strbuf[i * 3], 4, " %02x", 305e604d861Schristos buf[i]); 306e604d861Schristos 307e604d861Schristos display = strbuf; 308e604d861Schristos } else { 309e604d861Schristos display = " [REMOVED]"; 310e604d861Schristos } 311e604d861Schristos 312e604d861Schristos __android_log_print(wpa_to_android_level(level), 313e604d861Schristos ANDROID_LOG_NAME, 314e604d861Schristos "%s - hexdump(len=%lu):%s%s", 315e604d861Schristos title, (long unsigned int) len, display, 316e604d861Schristos len > slen ? " ..." : ""); 31736ebd06eSchristos bin_clear_free(strbuf, 1 + 3 * slen); 318e604d861Schristos return; 319e604d861Schristos } 320e604d861Schristos #else /* CONFIG_ANDROID_LOG */ 321111b9fd8Schristos #ifdef CONFIG_DEBUG_SYSLOG 322111b9fd8Schristos if (wpa_debug_syslog) { 323111b9fd8Schristos const char *display; 324111b9fd8Schristos char *strbuf = NULL; 325111b9fd8Schristos 326111b9fd8Schristos if (buf == NULL) { 327111b9fd8Schristos display = " [NULL]"; 328111b9fd8Schristos } else if (len == 0) { 329111b9fd8Schristos display = ""; 330111b9fd8Schristos } else if (show && len) { 331111b9fd8Schristos strbuf = os_malloc(1 + 3 * len); 332111b9fd8Schristos if (strbuf == NULL) { 333111b9fd8Schristos wpa_printf(MSG_ERROR, "wpa_hexdump: Failed to " 334111b9fd8Schristos "allocate message buffer"); 335111b9fd8Schristos return; 336111b9fd8Schristos } 337111b9fd8Schristos 338111b9fd8Schristos for (i = 0; i < len; i++) 339111b9fd8Schristos os_snprintf(&strbuf[i * 3], 4, " %02x", 340111b9fd8Schristos buf[i]); 341111b9fd8Schristos 342111b9fd8Schristos display = strbuf; 343111b9fd8Schristos } else { 344111b9fd8Schristos display = " [REMOVED]"; 345111b9fd8Schristos } 346111b9fd8Schristos 347111b9fd8Schristos syslog(syslog_priority(level), "%s - hexdump(len=%lu):%s", 348e604d861Schristos title, (unsigned long) len, display); 34936ebd06eSchristos bin_clear_free(strbuf, 1 + 3 * len); 350*bb618362Schristos if (only_syslog) 351111b9fd8Schristos return; 352111b9fd8Schristos } 353111b9fd8Schristos #endif /* CONFIG_DEBUG_SYSLOG */ 3548dbcf02cSchristos wpa_debug_print_timestamp(); 3558dbcf02cSchristos #ifdef CONFIG_DEBUG_FILE 3568dbcf02cSchristos if (out_file) { 3578dbcf02cSchristos fprintf(out_file, "%s - hexdump(len=%lu):", 3588dbcf02cSchristos title, (unsigned long) len); 3598dbcf02cSchristos if (buf == NULL) { 3608dbcf02cSchristos fprintf(out_file, " [NULL]"); 3618dbcf02cSchristos } else if (show) { 3628dbcf02cSchristos for (i = 0; i < len; i++) 3638dbcf02cSchristos fprintf(out_file, " %02x", buf[i]); 3648dbcf02cSchristos } else { 3658dbcf02cSchristos fprintf(out_file, " [REMOVED]"); 3668dbcf02cSchristos } 3678dbcf02cSchristos fprintf(out_file, "\n"); 368*bb618362Schristos } 3698dbcf02cSchristos #endif /* CONFIG_DEBUG_FILE */ 370*bb618362Schristos if (!wpa_debug_syslog && !out_file) { 3718dbcf02cSchristos printf("%s - hexdump(len=%lu):", title, (unsigned long) len); 3728dbcf02cSchristos if (buf == NULL) { 3738dbcf02cSchristos printf(" [NULL]"); 3748dbcf02cSchristos } else if (show) { 3758dbcf02cSchristos for (i = 0; i < len; i++) 3768dbcf02cSchristos printf(" %02x", buf[i]); 3778dbcf02cSchristos } else { 3788dbcf02cSchristos printf(" [REMOVED]"); 3798dbcf02cSchristos } 3808dbcf02cSchristos printf("\n"); 3818dbcf02cSchristos } 382e604d861Schristos #endif /* CONFIG_ANDROID_LOG */ 3838dbcf02cSchristos } 3848dbcf02cSchristos 3853c260e60Schristos void wpa_hexdump(int level, const char *title, const void *buf, size_t len) 3868dbcf02cSchristos { 387*bb618362Schristos _wpa_hexdump(level, title, buf, len, 1, 0); 3888dbcf02cSchristos } 3898dbcf02cSchristos 3908dbcf02cSchristos 3913c260e60Schristos void wpa_hexdump_key(int level, const char *title, const void *buf, size_t len) 3928dbcf02cSchristos { 393*bb618362Schristos _wpa_hexdump(level, title, buf, len, wpa_debug_show_keys, 0); 3948dbcf02cSchristos } 3958dbcf02cSchristos 3968dbcf02cSchristos 3973c260e60Schristos static void _wpa_hexdump_ascii(int level, const char *title, const void *buf, 3988dbcf02cSchristos size_t len, int show) 3998dbcf02cSchristos { 4008dbcf02cSchristos size_t i, llen; 4018dbcf02cSchristos const u8 *pos = buf; 4028dbcf02cSchristos const size_t line_len = 16; 4038dbcf02cSchristos 404e604d861Schristos #ifdef CONFIG_DEBUG_LINUX_TRACING 405e604d861Schristos if (wpa_debug_tracing_file != NULL) { 406e604d861Schristos fprintf(wpa_debug_tracing_file, 407e604d861Schristos WPAS_TRACE_PFX "%s - hexdump_ascii(len=%lu):", 408e604d861Schristos level, title, (unsigned long) len); 409e604d861Schristos if (buf == NULL) { 410e604d861Schristos fprintf(wpa_debug_tracing_file, " [NULL]\n"); 411e604d861Schristos } else if (!show) { 412e604d861Schristos fprintf(wpa_debug_tracing_file, " [REMOVED]\n"); 413e604d861Schristos } else { 414e604d861Schristos /* can do ascii processing in userspace */ 415e604d861Schristos for (i = 0; i < len; i++) 416e604d861Schristos fprintf(wpa_debug_tracing_file, 4173c260e60Schristos " %02x", pos[i]); 418e604d861Schristos } 419e604d861Schristos fflush(wpa_debug_tracing_file); 420e604d861Schristos } 421e604d861Schristos #endif /* CONFIG_DEBUG_LINUX_TRACING */ 422e604d861Schristos 4238dbcf02cSchristos if (level < wpa_debug_level) 4248dbcf02cSchristos return; 425e604d861Schristos #ifdef CONFIG_ANDROID_LOG 426*bb618362Schristos _wpa_hexdump(level, title, buf, len, show, 0); 427e604d861Schristos #else /* CONFIG_ANDROID_LOG */ 4283d6c0713Schristos #ifdef CONFIG_DEBUG_SYSLOG 429*bb618362Schristos if (wpa_debug_syslog) 430*bb618362Schristos _wpa_hexdump(level, title, buf, len, show, 1); 4313d6c0713Schristos #endif /* CONFIG_DEBUG_SYSLOG */ 4328dbcf02cSchristos wpa_debug_print_timestamp(); 4338dbcf02cSchristos #ifdef CONFIG_DEBUG_FILE 4348dbcf02cSchristos if (out_file) { 4358dbcf02cSchristos if (!show) { 4368dbcf02cSchristos fprintf(out_file, 4378dbcf02cSchristos "%s - hexdump_ascii(len=%lu): [REMOVED]\n", 4388dbcf02cSchristos title, (unsigned long) len); 439*bb618362Schristos goto file_done; 4408dbcf02cSchristos } 4418dbcf02cSchristos if (buf == NULL) { 4428dbcf02cSchristos fprintf(out_file, 4438dbcf02cSchristos "%s - hexdump_ascii(len=%lu): [NULL]\n", 4448dbcf02cSchristos title, (unsigned long) len); 445*bb618362Schristos goto file_done; 4468dbcf02cSchristos } 4478dbcf02cSchristos fprintf(out_file, "%s - hexdump_ascii(len=%lu):\n", 4488dbcf02cSchristos title, (unsigned long) len); 4498dbcf02cSchristos while (len) { 4508dbcf02cSchristos llen = len > line_len ? line_len : len; 4518dbcf02cSchristos fprintf(out_file, " "); 4528dbcf02cSchristos for (i = 0; i < llen; i++) 4538dbcf02cSchristos fprintf(out_file, " %02x", pos[i]); 4548dbcf02cSchristos for (i = llen; i < line_len; i++) 4558dbcf02cSchristos fprintf(out_file, " "); 4568dbcf02cSchristos fprintf(out_file, " "); 4578dbcf02cSchristos for (i = 0; i < llen; i++) { 4588dbcf02cSchristos if (isprint(pos[i])) 4598dbcf02cSchristos fprintf(out_file, "%c", pos[i]); 4608dbcf02cSchristos else 4618dbcf02cSchristos fprintf(out_file, "_"); 4628dbcf02cSchristos } 4638dbcf02cSchristos for (i = llen; i < line_len; i++) 4648dbcf02cSchristos fprintf(out_file, " "); 4658dbcf02cSchristos fprintf(out_file, "\n"); 4668dbcf02cSchristos pos += llen; 4678dbcf02cSchristos len -= llen; 4688dbcf02cSchristos } 469*bb618362Schristos } 470*bb618362Schristos file_done: 4718dbcf02cSchristos #endif /* CONFIG_DEBUG_FILE */ 472*bb618362Schristos if (!wpa_debug_syslog && !out_file) { 4738dbcf02cSchristos if (!show) { 4748dbcf02cSchristos printf("%s - hexdump_ascii(len=%lu): [REMOVED]\n", 4758dbcf02cSchristos title, (unsigned long) len); 4768dbcf02cSchristos return; 4778dbcf02cSchristos } 4788dbcf02cSchristos if (buf == NULL) { 4798dbcf02cSchristos printf("%s - hexdump_ascii(len=%lu): [NULL]\n", 4808dbcf02cSchristos title, (unsigned long) len); 4818dbcf02cSchristos return; 4828dbcf02cSchristos } 483*bb618362Schristos printf("%s - hexdump_ascii(len=%lu):\n", title, 484*bb618362Schristos (unsigned long) len); 4858dbcf02cSchristos while (len) { 4868dbcf02cSchristos llen = len > line_len ? line_len : len; 4878dbcf02cSchristos printf(" "); 4888dbcf02cSchristos for (i = 0; i < llen; i++) 4898dbcf02cSchristos printf(" %02x", pos[i]); 4908dbcf02cSchristos for (i = llen; i < line_len; i++) 4918dbcf02cSchristos printf(" "); 4928dbcf02cSchristos printf(" "); 4938dbcf02cSchristos for (i = 0; i < llen; i++) { 4948dbcf02cSchristos if (isprint(pos[i])) 4958dbcf02cSchristos printf("%c", pos[i]); 4968dbcf02cSchristos else 4978dbcf02cSchristos printf("_"); 4988dbcf02cSchristos } 4998dbcf02cSchristos for (i = llen; i < line_len; i++) 5008dbcf02cSchristos printf(" "); 5018dbcf02cSchristos printf("\n"); 5028dbcf02cSchristos pos += llen; 5038dbcf02cSchristos len -= llen; 5048dbcf02cSchristos } 5058dbcf02cSchristos } 506e604d861Schristos #endif /* CONFIG_ANDROID_LOG */ 5078dbcf02cSchristos } 5088dbcf02cSchristos 5098dbcf02cSchristos 5103c260e60Schristos void wpa_hexdump_ascii(int level, const char *title, const void *buf, 5113c260e60Schristos size_t len) 5128dbcf02cSchristos { 5138dbcf02cSchristos _wpa_hexdump_ascii(level, title, buf, len, 1); 5148dbcf02cSchristos } 5158dbcf02cSchristos 5168dbcf02cSchristos 5173c260e60Schristos void wpa_hexdump_ascii_key(int level, const char *title, const void *buf, 5188dbcf02cSchristos size_t len) 5198dbcf02cSchristos { 5208dbcf02cSchristos _wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys); 5218dbcf02cSchristos } 5228dbcf02cSchristos 5238dbcf02cSchristos 524111b9fd8Schristos #ifdef CONFIG_DEBUG_FILE 525111b9fd8Schristos static char *last_path = NULL; 526111b9fd8Schristos #endif /* CONFIG_DEBUG_FILE */ 527111b9fd8Schristos 528111b9fd8Schristos int wpa_debug_reopen_file(void) 529111b9fd8Schristos { 530111b9fd8Schristos #ifdef CONFIG_DEBUG_FILE 531111b9fd8Schristos int rv; 53236ebd06eSchristos char *tmp; 53336ebd06eSchristos 53436ebd06eSchristos if (!last_path) 53536ebd06eSchristos return 0; /* logfile not used */ 53636ebd06eSchristos 53736ebd06eSchristos tmp = os_strdup(last_path); 53836ebd06eSchristos if (!tmp) 53936ebd06eSchristos return -1; 54036ebd06eSchristos 541111b9fd8Schristos wpa_debug_close_file(); 542111b9fd8Schristos rv = wpa_debug_open_file(tmp); 543111b9fd8Schristos os_free(tmp); 544111b9fd8Schristos return rv; 545111b9fd8Schristos #else /* CONFIG_DEBUG_FILE */ 546111b9fd8Schristos return 0; 547111b9fd8Schristos #endif /* CONFIG_DEBUG_FILE */ 548111b9fd8Schristos } 549111b9fd8Schristos 550111b9fd8Schristos 5518dbcf02cSchristos int wpa_debug_open_file(const char *path) 5528dbcf02cSchristos { 5538dbcf02cSchristos #ifdef CONFIG_DEBUG_FILE 5540a73ee0aSchristos int out_fd; 5550a73ee0aSchristos 5568dbcf02cSchristos if (!path) 5578dbcf02cSchristos return 0; 558111b9fd8Schristos 559111b9fd8Schristos if (last_path == NULL || os_strcmp(last_path, path) != 0) { 560111b9fd8Schristos /* Save our path to enable re-open */ 561111b9fd8Schristos os_free(last_path); 562111b9fd8Schristos last_path = os_strdup(path); 563111b9fd8Schristos } 564111b9fd8Schristos 5650a73ee0aSchristos out_fd = open(path, O_CREAT | O_APPEND | O_WRONLY, 5660a73ee0aSchristos S_IRUSR | S_IWUSR | S_IRGRP); 5670a73ee0aSchristos if (out_fd < 0) { 5680a73ee0aSchristos wpa_printf(MSG_ERROR, 5690a73ee0aSchristos "%s: Failed to open output file descriptor, using standard output", 5700a73ee0aSchristos __func__); 5710a73ee0aSchristos return -1; 5720a73ee0aSchristos } 5730a73ee0aSchristos 5740a73ee0aSchristos #ifdef __linux__ 5750a73ee0aSchristos if (fcntl(out_fd, F_SETFD, FD_CLOEXEC) < 0) { 5760a73ee0aSchristos wpa_printf(MSG_DEBUG, 5770a73ee0aSchristos "%s: Failed to set FD_CLOEXEC - continue without: %s", 5780a73ee0aSchristos __func__, strerror(errno)); 5790a73ee0aSchristos } 5800a73ee0aSchristos #endif /* __linux__ */ 5810a73ee0aSchristos 5820a73ee0aSchristos out_file = fdopen(out_fd, "a"); 5838dbcf02cSchristos if (out_file == NULL) { 5848dbcf02cSchristos wpa_printf(MSG_ERROR, "wpa_debug_open_file: Failed to open " 5858dbcf02cSchristos "output file, using standard output"); 5860a73ee0aSchristos close(out_fd); 5878dbcf02cSchristos return -1; 5888dbcf02cSchristos } 5898dbcf02cSchristos #ifndef _WIN32 5908dbcf02cSchristos setvbuf(out_file, NULL, _IOLBF, 0); 5918dbcf02cSchristos #endif /* _WIN32 */ 592bb610346Schristos #else /* CONFIG_DEBUG_FILE */ 593bb610346Schristos (void)path; 5948dbcf02cSchristos #endif /* CONFIG_DEBUG_FILE */ 5958dbcf02cSchristos return 0; 5968dbcf02cSchristos } 5978dbcf02cSchristos 5988dbcf02cSchristos 599*bb618362Schristos void wpa_debug_stop_log(void) 6008dbcf02cSchristos { 6018dbcf02cSchristos #ifdef CONFIG_DEBUG_FILE 6028dbcf02cSchristos if (!out_file) 6038dbcf02cSchristos return; 6048dbcf02cSchristos fclose(out_file); 6058dbcf02cSchristos out_file = NULL; 606*bb618362Schristos #endif /* CONFIG_DEBUG_FILE */ 607*bb618362Schristos } 608*bb618362Schristos 609*bb618362Schristos 610*bb618362Schristos void wpa_debug_close_file(void) 611*bb618362Schristos { 612*bb618362Schristos #ifdef CONFIG_DEBUG_FILE 613*bb618362Schristos wpa_debug_stop_log(); 614111b9fd8Schristos os_free(last_path); 615111b9fd8Schristos last_path = NULL; 6168dbcf02cSchristos #endif /* CONFIG_DEBUG_FILE */ 6178dbcf02cSchristos } 6188dbcf02cSchristos 619bb610346Schristos 620bb610346Schristos void wpa_debug_setup_stdout(void) 621bb610346Schristos { 622bb610346Schristos #ifndef _WIN32 623bb610346Schristos setvbuf(stdout, NULL, _IOLBF, 0); 624bb610346Schristos #endif /* _WIN32 */ 625bb610346Schristos } 626bb610346Schristos 6278dbcf02cSchristos #endif /* CONFIG_NO_STDOUT_DEBUG */ 6288dbcf02cSchristos 6298dbcf02cSchristos 6308dbcf02cSchristos #ifndef CONFIG_NO_WPA_MSG 6318dbcf02cSchristos static wpa_msg_cb_func wpa_msg_cb = NULL; 6328dbcf02cSchristos 6338dbcf02cSchristos void wpa_msg_register_cb(wpa_msg_cb_func func) 6348dbcf02cSchristos { 6358dbcf02cSchristos wpa_msg_cb = func; 6368dbcf02cSchristos } 6378dbcf02cSchristos 6388dbcf02cSchristos 639111b9fd8Schristos static wpa_msg_get_ifname_func wpa_msg_ifname_cb = NULL; 640111b9fd8Schristos 641111b9fd8Schristos void wpa_msg_register_ifname_cb(wpa_msg_get_ifname_func func) 642111b9fd8Schristos { 643111b9fd8Schristos wpa_msg_ifname_cb = func; 644111b9fd8Schristos } 645111b9fd8Schristos 646111b9fd8Schristos 6478dbcf02cSchristos void wpa_msg(void *ctx, int level, const char *fmt, ...) 6488dbcf02cSchristos { 6498dbcf02cSchristos va_list ap; 6508dbcf02cSchristos char *buf; 6513c260e60Schristos int buflen; 6528dbcf02cSchristos int len; 653111b9fd8Schristos char prefix[130]; 6548dbcf02cSchristos 6553c260e60Schristos va_start(ap, fmt); 6563c260e60Schristos buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 6573c260e60Schristos va_end(ap); 6583c260e60Schristos 6598dbcf02cSchristos buf = os_malloc(buflen); 6608dbcf02cSchristos if (buf == NULL) { 6618dbcf02cSchristos wpa_printf(MSG_ERROR, "wpa_msg: Failed to allocate message " 6628dbcf02cSchristos "buffer"); 6638dbcf02cSchristos return; 6648dbcf02cSchristos } 6658dbcf02cSchristos va_start(ap, fmt); 666111b9fd8Schristos prefix[0] = '\0'; 667111b9fd8Schristos if (wpa_msg_ifname_cb) { 668111b9fd8Schristos const char *ifname = wpa_msg_ifname_cb(ctx); 669111b9fd8Schristos if (ifname) { 670111b9fd8Schristos int res = os_snprintf(prefix, sizeof(prefix), "%s: ", 671111b9fd8Schristos ifname); 672bb610346Schristos if (os_snprintf_error(sizeof(prefix), res)) 673111b9fd8Schristos prefix[0] = '\0'; 674111b9fd8Schristos } 675111b9fd8Schristos } 6768dbcf02cSchristos len = vsnprintf(buf, buflen, fmt, ap); 6778dbcf02cSchristos va_end(ap); 678111b9fd8Schristos wpa_printf(level, "%s%s", prefix, buf); 6798dbcf02cSchristos if (wpa_msg_cb) 68036ebd06eSchristos wpa_msg_cb(ctx, level, WPA_MSG_PER_INTERFACE, buf, len); 68136ebd06eSchristos bin_clear_free(buf, buflen); 6828dbcf02cSchristos } 6838dbcf02cSchristos 6848dbcf02cSchristos 6858dbcf02cSchristos void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...) 6868dbcf02cSchristos { 6878dbcf02cSchristos va_list ap; 6888dbcf02cSchristos char *buf; 6893c260e60Schristos int buflen; 6908dbcf02cSchristos int len; 6918dbcf02cSchristos 6928dbcf02cSchristos if (!wpa_msg_cb) 6938dbcf02cSchristos return; 6948dbcf02cSchristos 6953c260e60Schristos va_start(ap, fmt); 6963c260e60Schristos buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 6973c260e60Schristos va_end(ap); 6983c260e60Schristos 6998dbcf02cSchristos buf = os_malloc(buflen); 7008dbcf02cSchristos if (buf == NULL) { 7018dbcf02cSchristos wpa_printf(MSG_ERROR, "wpa_msg_ctrl: Failed to allocate " 7028dbcf02cSchristos "message buffer"); 7038dbcf02cSchristos return; 7048dbcf02cSchristos } 7058dbcf02cSchristos va_start(ap, fmt); 7068dbcf02cSchristos len = vsnprintf(buf, buflen, fmt, ap); 7078dbcf02cSchristos va_end(ap); 70836ebd06eSchristos wpa_msg_cb(ctx, level, WPA_MSG_PER_INTERFACE, buf, len); 70936ebd06eSchristos bin_clear_free(buf, buflen); 7108dbcf02cSchristos } 7113c260e60Schristos 7123c260e60Schristos 7133c260e60Schristos void wpa_msg_global(void *ctx, int level, const char *fmt, ...) 7143c260e60Schristos { 7153c260e60Schristos va_list ap; 7163c260e60Schristos char *buf; 7173c260e60Schristos int buflen; 7183c260e60Schristos int len; 7193c260e60Schristos 7203c260e60Schristos va_start(ap, fmt); 7213c260e60Schristos buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 7223c260e60Schristos va_end(ap); 7233c260e60Schristos 7243c260e60Schristos buf = os_malloc(buflen); 7253c260e60Schristos if (buf == NULL) { 7263c260e60Schristos wpa_printf(MSG_ERROR, "wpa_msg_global: Failed to allocate " 7273c260e60Schristos "message buffer"); 7283c260e60Schristos return; 7293c260e60Schristos } 7303c260e60Schristos va_start(ap, fmt); 7313c260e60Schristos len = vsnprintf(buf, buflen, fmt, ap); 7323c260e60Schristos va_end(ap); 7333c260e60Schristos wpa_printf(level, "%s", buf); 7343c260e60Schristos if (wpa_msg_cb) 73536ebd06eSchristos wpa_msg_cb(ctx, level, WPA_MSG_GLOBAL, buf, len); 73636ebd06eSchristos bin_clear_free(buf, buflen); 7373c260e60Schristos } 7383c260e60Schristos 7393c260e60Schristos 7403c260e60Schristos void wpa_msg_global_ctrl(void *ctx, int level, const char *fmt, ...) 7413c260e60Schristos { 7423c260e60Schristos va_list ap; 7433c260e60Schristos char *buf; 7443c260e60Schristos int buflen; 7453c260e60Schristos int len; 7463c260e60Schristos 7473c260e60Schristos if (!wpa_msg_cb) 7483c260e60Schristos return; 7493c260e60Schristos 7503c260e60Schristos va_start(ap, fmt); 7513c260e60Schristos buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 7523c260e60Schristos va_end(ap); 7533c260e60Schristos 7543c260e60Schristos buf = os_malloc(buflen); 7553c260e60Schristos if (buf == NULL) { 7563c260e60Schristos wpa_printf(MSG_ERROR, 7573c260e60Schristos "wpa_msg_global_ctrl: Failed to allocate message buffer"); 7583c260e60Schristos return; 7593c260e60Schristos } 7603c260e60Schristos va_start(ap, fmt); 7613c260e60Schristos len = vsnprintf(buf, buflen, fmt, ap); 7623c260e60Schristos va_end(ap); 76336ebd06eSchristos wpa_msg_cb(ctx, level, WPA_MSG_GLOBAL, buf, len); 76436ebd06eSchristos bin_clear_free(buf, buflen); 7653c260e60Schristos } 7663c260e60Schristos 7673c260e60Schristos 7683c260e60Schristos void wpa_msg_no_global(void *ctx, int level, const char *fmt, ...) 7693c260e60Schristos { 7703c260e60Schristos va_list ap; 7713c260e60Schristos char *buf; 7723c260e60Schristos int buflen; 7733c260e60Schristos int len; 7743c260e60Schristos 7753c260e60Schristos va_start(ap, fmt); 7763c260e60Schristos buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 7773c260e60Schristos va_end(ap); 7783c260e60Schristos 7793c260e60Schristos buf = os_malloc(buflen); 7803c260e60Schristos if (buf == NULL) { 7813c260e60Schristos wpa_printf(MSG_ERROR, "wpa_msg_no_global: Failed to allocate " 7823c260e60Schristos "message buffer"); 7833c260e60Schristos return; 7843c260e60Schristos } 7853c260e60Schristos va_start(ap, fmt); 7863c260e60Schristos len = vsnprintf(buf, buflen, fmt, ap); 7873c260e60Schristos va_end(ap); 7883c260e60Schristos wpa_printf(level, "%s", buf); 7893c260e60Schristos if (wpa_msg_cb) 79036ebd06eSchristos wpa_msg_cb(ctx, level, WPA_MSG_NO_GLOBAL, buf, len); 79136ebd06eSchristos bin_clear_free(buf, buflen); 79236ebd06eSchristos } 79336ebd06eSchristos 79436ebd06eSchristos 79536ebd06eSchristos void wpa_msg_global_only(void *ctx, int level, const char *fmt, ...) 79636ebd06eSchristos { 79736ebd06eSchristos va_list ap; 79836ebd06eSchristos char *buf; 79936ebd06eSchristos int buflen; 80036ebd06eSchristos int len; 80136ebd06eSchristos 80236ebd06eSchristos va_start(ap, fmt); 80336ebd06eSchristos buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 80436ebd06eSchristos va_end(ap); 80536ebd06eSchristos 80636ebd06eSchristos buf = os_malloc(buflen); 80736ebd06eSchristos if (buf == NULL) { 80836ebd06eSchristos wpa_printf(MSG_ERROR, "%s: Failed to allocate message buffer", 80936ebd06eSchristos __func__); 81036ebd06eSchristos return; 81136ebd06eSchristos } 81236ebd06eSchristos va_start(ap, fmt); 81336ebd06eSchristos len = vsnprintf(buf, buflen, fmt, ap); 81436ebd06eSchristos va_end(ap); 81536ebd06eSchristos wpa_printf(level, "%s", buf); 81636ebd06eSchristos if (wpa_msg_cb) 81736ebd06eSchristos wpa_msg_cb(ctx, level, WPA_MSG_ONLY_GLOBAL, buf, len); 8183c260e60Schristos os_free(buf); 8193c260e60Schristos } 8203c260e60Schristos 8218dbcf02cSchristos #endif /* CONFIG_NO_WPA_MSG */ 8228dbcf02cSchristos 8238dbcf02cSchristos 8248dbcf02cSchristos #ifndef CONFIG_NO_HOSTAPD_LOGGER 8258dbcf02cSchristos static hostapd_logger_cb_func hostapd_logger_cb = NULL; 8268dbcf02cSchristos 8278dbcf02cSchristos void hostapd_logger_register_cb(hostapd_logger_cb_func func) 8288dbcf02cSchristos { 8298dbcf02cSchristos hostapd_logger_cb = func; 8308dbcf02cSchristos } 8318dbcf02cSchristos 8328dbcf02cSchristos 8338dbcf02cSchristos void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level, 8348dbcf02cSchristos const char *fmt, ...) 8358dbcf02cSchristos { 8368dbcf02cSchristos va_list ap; 8378dbcf02cSchristos char *buf; 8383c260e60Schristos int buflen; 8398dbcf02cSchristos int len; 8408dbcf02cSchristos 8413c260e60Schristos va_start(ap, fmt); 8423c260e60Schristos buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 8433c260e60Schristos va_end(ap); 8443c260e60Schristos 8458dbcf02cSchristos buf = os_malloc(buflen); 8468dbcf02cSchristos if (buf == NULL) { 8478dbcf02cSchristos wpa_printf(MSG_ERROR, "hostapd_logger: Failed to allocate " 8488dbcf02cSchristos "message buffer"); 8498dbcf02cSchristos return; 8508dbcf02cSchristos } 8518dbcf02cSchristos va_start(ap, fmt); 8528dbcf02cSchristos len = vsnprintf(buf, buflen, fmt, ap); 8538dbcf02cSchristos va_end(ap); 8548dbcf02cSchristos if (hostapd_logger_cb) 8558dbcf02cSchristos hostapd_logger_cb(ctx, addr, module, level, buf, len); 8568dbcf02cSchristos else if (addr) 8578dbcf02cSchristos wpa_printf(MSG_DEBUG, "hostapd_logger: STA " MACSTR " - %s", 8588dbcf02cSchristos MAC2STR(addr), buf); 8598dbcf02cSchristos else 8608dbcf02cSchristos wpa_printf(MSG_DEBUG, "hostapd_logger: %s", buf); 86136ebd06eSchristos bin_clear_free(buf, buflen); 8628dbcf02cSchristos } 8638dbcf02cSchristos #endif /* CONFIG_NO_HOSTAPD_LOGGER */ 86436ebd06eSchristos 86536ebd06eSchristos 86636ebd06eSchristos const char * debug_level_str(int level) 86736ebd06eSchristos { 86836ebd06eSchristos switch (level) { 86936ebd06eSchristos case MSG_EXCESSIVE: 87036ebd06eSchristos return "EXCESSIVE"; 87136ebd06eSchristos case MSG_MSGDUMP: 87236ebd06eSchristos return "MSGDUMP"; 87336ebd06eSchristos case MSG_DEBUG: 87436ebd06eSchristos return "DEBUG"; 87536ebd06eSchristos case MSG_INFO: 87636ebd06eSchristos return "INFO"; 87736ebd06eSchristos case MSG_WARNING: 87836ebd06eSchristos return "WARNING"; 87936ebd06eSchristos case MSG_ERROR: 88036ebd06eSchristos return "ERROR"; 88136ebd06eSchristos default: 88236ebd06eSchristos return "?"; 88336ebd06eSchristos } 88436ebd06eSchristos } 88536ebd06eSchristos 88636ebd06eSchristos 88736ebd06eSchristos int str_to_debug_level(const char *s) 88836ebd06eSchristos { 88936ebd06eSchristos if (os_strcasecmp(s, "EXCESSIVE") == 0) 89036ebd06eSchristos return MSG_EXCESSIVE; 89136ebd06eSchristos if (os_strcasecmp(s, "MSGDUMP") == 0) 89236ebd06eSchristos return MSG_MSGDUMP; 89336ebd06eSchristos if (os_strcasecmp(s, "DEBUG") == 0) 89436ebd06eSchristos return MSG_DEBUG; 89536ebd06eSchristos if (os_strcasecmp(s, "INFO") == 0) 89636ebd06eSchristos return MSG_INFO; 89736ebd06eSchristos if (os_strcasecmp(s, "WARNING") == 0) 89836ebd06eSchristos return MSG_WARNING; 89936ebd06eSchristos if (os_strcasecmp(s, "ERROR") == 0) 90036ebd06eSchristos return MSG_ERROR; 90136ebd06eSchristos return -1; 90236ebd06eSchristos } 903