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