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