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