1 /* 2 * wpa_supplicant/hostapd / Debug prints 3 * Copyright (c) 2002-2007, Jouni Malinen <j (at) w1.fi> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * Alternatively, this software may be distributed under the terms of BSD 10 * license. 11 * 12 * See README and COPYING for more details. 13 */ 14 15 #include "includes.h" 16 17 #include "common.h" 18 19 20 #ifdef CONFIG_DEBUG_FILE 21 static FILE *out_file = NULL; 22 #endif /* CONFIG_DEBUG_FILE */ 23 int wpa_debug_level = MSG_INFO; 24 int wpa_debug_show_keys = 0; 25 int wpa_debug_timestamp = 0; 26 27 28 #ifdef CONFIG_ANDROID_LOG 29 30 #include <android/log.h> 31 32 void android_printf(int level, char *format, ...) 33 { 34 if (level >= wpa_debug_level) { 35 va_list ap; 36 if (level == MSG_ERROR) { 37 level = ANDROID_LOG_ERROR; 38 } else if (level == MSG_WARNING) { 39 level = ANDROID_LOG_WARN; 40 } else if (level == MSG_INFO) { 41 level = ANDROID_LOG_INFO; 42 } else { 43 level = ANDROID_LOG_DEBUG; 44 } 45 va_start(ap, format); 46 __android_log_vprint(level, "wpa_supplicant", format, ap); 47 va_end(ap); 48 } 49 } 50 51 #else /* CONFIG_ANDROID_LOG */ 52 53 #ifndef CONFIG_NO_STDOUT_DEBUG 54 55 void wpa_debug_print_timestamp(void) 56 { 57 struct os_time tv; 58 59 if (!wpa_debug_timestamp) 60 return; 61 62 os_get_time(&tv); 63 #ifdef CONFIG_DEBUG_FILE 64 if (out_file) { 65 fprintf(out_file, "%ld.%06u: ", (long) tv.sec, 66 (unsigned int) tv.usec); 67 } else 68 #endif /* CONFIG_DEBUG_FILE */ 69 printf("%ld.%06u: ", (long) tv.sec, (unsigned int) tv.usec); 70 } 71 72 73 /** 74 * wpa_printf - conditional printf 75 * @level: priority level (MSG_*) of the message 76 * @fmt: printf format string, followed by optional arguments 77 * 78 * This function is used to print conditional debugging and error messages. The 79 * output may be directed to stdout, stderr, and/or syslog based on 80 * configuration. 81 * 82 * Note: New line '\n' is added to the end of the text when printing to stdout. 83 */ 84 void wpa_printf(int level, const char *fmt, ...) 85 { 86 va_list ap; 87 88 va_start(ap, fmt); 89 if (level >= wpa_debug_level) { 90 wpa_debug_print_timestamp(); 91 #ifdef CONFIG_DEBUG_FILE 92 if (out_file) { 93 vfprintf(out_file, fmt, ap); 94 fprintf(out_file, "\n"); 95 } else { 96 #endif /* CONFIG_DEBUG_FILE */ 97 vprintf(fmt, ap); 98 printf("\n"); 99 #ifdef CONFIG_DEBUG_FILE 100 } 101 #endif /* CONFIG_DEBUG_FILE */ 102 } 103 va_end(ap); 104 } 105 106 107 static void _wpa_hexdump(int level, const char *title, const u8 *buf, 108 size_t len, int show) 109 { 110 size_t i; 111 if (level < wpa_debug_level) 112 return; 113 wpa_debug_print_timestamp(); 114 #ifdef CONFIG_DEBUG_FILE 115 if (out_file) { 116 fprintf(out_file, "%s - hexdump(len=%lu):", 117 title, (unsigned long) len); 118 if (buf == NULL) { 119 fprintf(out_file, " [NULL]"); 120 } else if (show) { 121 for (i = 0; i < len; i++) 122 fprintf(out_file, " %02x", buf[i]); 123 } else { 124 fprintf(out_file, " [REMOVED]"); 125 } 126 fprintf(out_file, "\n"); 127 } else { 128 #endif /* CONFIG_DEBUG_FILE */ 129 printf("%s - hexdump(len=%lu):", title, (unsigned long) len); 130 if (buf == NULL) { 131 printf(" [NULL]"); 132 } else if (show) { 133 for (i = 0; i < len; i++) 134 printf(" %02x", buf[i]); 135 } else { 136 printf(" [REMOVED]"); 137 } 138 printf("\n"); 139 #ifdef CONFIG_DEBUG_FILE 140 } 141 #endif /* CONFIG_DEBUG_FILE */ 142 } 143 144 void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len) 145 { 146 _wpa_hexdump(level, title, buf, len, 1); 147 } 148 149 150 void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len) 151 { 152 _wpa_hexdump(level, title, buf, len, wpa_debug_show_keys); 153 } 154 155 156 static void _wpa_hexdump_ascii(int level, const char *title, const u8 *buf, 157 size_t len, int show) 158 { 159 size_t i, llen; 160 const u8 *pos = buf; 161 const size_t line_len = 16; 162 163 if (level < wpa_debug_level) 164 return; 165 wpa_debug_print_timestamp(); 166 #ifdef CONFIG_DEBUG_FILE 167 if (out_file) { 168 if (!show) { 169 fprintf(out_file, 170 "%s - hexdump_ascii(len=%lu): [REMOVED]\n", 171 title, (unsigned long) len); 172 return; 173 } 174 if (buf == NULL) { 175 fprintf(out_file, 176 "%s - hexdump_ascii(len=%lu): [NULL]\n", 177 title, (unsigned long) len); 178 return; 179 } 180 fprintf(out_file, "%s - hexdump_ascii(len=%lu):\n", 181 title, (unsigned long) len); 182 while (len) { 183 llen = len > line_len ? line_len : len; 184 fprintf(out_file, " "); 185 for (i = 0; i < llen; i++) 186 fprintf(out_file, " %02x", pos[i]); 187 for (i = llen; i < line_len; i++) 188 fprintf(out_file, " "); 189 fprintf(out_file, " "); 190 for (i = 0; i < llen; i++) { 191 if (isprint(pos[i])) 192 fprintf(out_file, "%c", pos[i]); 193 else 194 fprintf(out_file, "_"); 195 } 196 for (i = llen; i < line_len; i++) 197 fprintf(out_file, " "); 198 fprintf(out_file, "\n"); 199 pos += llen; 200 len -= llen; 201 } 202 } else { 203 #endif /* CONFIG_DEBUG_FILE */ 204 if (!show) { 205 printf("%s - hexdump_ascii(len=%lu): [REMOVED]\n", 206 title, (unsigned long) len); 207 return; 208 } 209 if (buf == NULL) { 210 printf("%s - hexdump_ascii(len=%lu): [NULL]\n", 211 title, (unsigned long) len); 212 return; 213 } 214 printf("%s - hexdump_ascii(len=%lu):\n", title, (unsigned long) len); 215 while (len) { 216 llen = len > line_len ? line_len : len; 217 printf(" "); 218 for (i = 0; i < llen; i++) 219 printf(" %02x", pos[i]); 220 for (i = llen; i < line_len; i++) 221 printf(" "); 222 printf(" "); 223 for (i = 0; i < llen; i++) { 224 if (isprint(pos[i])) 225 printf("%c", pos[i]); 226 else 227 printf("_"); 228 } 229 for (i = llen; i < line_len; i++) 230 printf(" "); 231 printf("\n"); 232 pos += llen; 233 len -= llen; 234 } 235 #ifdef CONFIG_DEBUG_FILE 236 } 237 #endif /* CONFIG_DEBUG_FILE */ 238 } 239 240 241 void wpa_hexdump_ascii(int level, const char *title, const u8 *buf, size_t len) 242 { 243 _wpa_hexdump_ascii(level, title, buf, len, 1); 244 } 245 246 247 void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf, 248 size_t len) 249 { 250 _wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys); 251 } 252 253 254 int wpa_debug_open_file(const char *path) 255 { 256 #ifdef CONFIG_DEBUG_FILE 257 if (!path) 258 return 0; 259 out_file = fopen(path, "a"); 260 if (out_file == NULL) { 261 wpa_printf(MSG_ERROR, "wpa_debug_open_file: Failed to open " 262 "output file, using standard output"); 263 return -1; 264 } 265 #ifndef _WIN32 266 setvbuf(out_file, NULL, _IOLBF, 0); 267 #endif /* _WIN32 */ 268 #endif /* CONFIG_DEBUG_FILE */ 269 return 0; 270 } 271 272 273 void wpa_debug_close_file(void) 274 { 275 #ifdef CONFIG_DEBUG_FILE 276 if (!out_file) 277 return; 278 fclose(out_file); 279 out_file = NULL; 280 #endif /* CONFIG_DEBUG_FILE */ 281 } 282 283 #endif /* CONFIG_NO_STDOUT_DEBUG */ 284 285 #endif /* CONFIG_ANDROID_LOG */ 286 287 #ifndef CONFIG_NO_WPA_MSG 288 static wpa_msg_cb_func wpa_msg_cb = NULL; 289 290 void wpa_msg_register_cb(wpa_msg_cb_func func) 291 { 292 wpa_msg_cb = func; 293 } 294 295 296 void wpa_msg(void *ctx, int level, const char *fmt, ...) 297 { 298 va_list ap; 299 char *buf; 300 const int buflen = 2048; 301 int len; 302 303 buf = os_malloc(buflen); 304 if (buf == NULL) { 305 wpa_printf(MSG_ERROR, "wpa_msg: Failed to allocate message " 306 "buffer"); 307 return; 308 } 309 va_start(ap, fmt); 310 len = vsnprintf(buf, buflen, fmt, ap); 311 va_end(ap); 312 wpa_printf(level, "%s", buf); 313 if (wpa_msg_cb) 314 wpa_msg_cb(ctx, level, buf, len); 315 os_free(buf); 316 } 317 318 319 void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...) 320 { 321 va_list ap; 322 char *buf; 323 const int buflen = 2048; 324 int len; 325 326 if (!wpa_msg_cb) 327 return; 328 329 buf = os_malloc(buflen); 330 if (buf == NULL) { 331 wpa_printf(MSG_ERROR, "wpa_msg_ctrl: Failed to allocate " 332 "message buffer"); 333 return; 334 } 335 va_start(ap, fmt); 336 len = vsnprintf(buf, buflen, fmt, ap); 337 va_end(ap); 338 wpa_msg_cb(ctx, level, buf, len); 339 os_free(buf); 340 } 341 #endif /* CONFIG_NO_WPA_MSG */ 342 343 344 #ifndef CONFIG_NO_HOSTAPD_LOGGER 345 static hostapd_logger_cb_func hostapd_logger_cb = NULL; 346 347 void hostapd_logger_register_cb(hostapd_logger_cb_func func) 348 { 349 hostapd_logger_cb = func; 350 } 351 352 353 void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level, 354 const char *fmt, ...) 355 { 356 va_list ap; 357 char *buf; 358 const int buflen = 2048; 359 int len; 360 361 buf = os_malloc(buflen); 362 if (buf == NULL) { 363 wpa_printf(MSG_ERROR, "hostapd_logger: Failed to allocate " 364 "message buffer"); 365 return; 366 } 367 va_start(ap, fmt); 368 len = vsnprintf(buf, buflen, fmt, ap); 369 va_end(ap); 370 if (hostapd_logger_cb) 371 hostapd_logger_cb(ctx, addr, module, level, buf, len); 372 else 373 wpa_printf(MSG_DEBUG, "hostapd_logger: %s", buf); 374 os_free(buf); 375 } 376 #endif /* CONFIG_NO_HOSTAPD_LOGGER */ 377