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 #endif /* CONFIG_DEBUG_SYSLOG */ 22 23 24 #ifdef CONFIG_DEBUG_FILE 25 static FILE *out_file = NULL; 26 #endif /* CONFIG_DEBUG_FILE */ 27 int wpa_debug_level = MSG_INFO; 28 int wpa_debug_show_keys = 0; 29 int wpa_debug_timestamp = 0; 30 int wpa_debug_syslog = 0; 31 32 33 #ifndef CONFIG_NO_STDOUT_DEBUG 34 35 void wpa_debug_print_timestamp(void) 36 { 37 struct os_time tv; 38 39 if (!wpa_debug_timestamp) 40 return; 41 42 os_get_time(&tv); 43 #ifdef CONFIG_DEBUG_FILE 44 if (out_file) { 45 fprintf(out_file, "%ld.%06u: ", (long) tv.sec, 46 (unsigned int) tv.usec); 47 } else 48 #endif /* CONFIG_DEBUG_FILE */ 49 printf("%ld.%06u: ", (long) tv.sec, (unsigned int) tv.usec); 50 } 51 52 void wpa_debug_open_syslog(void) 53 { 54 #ifdef CONFIG_DEBUG_SYSLOG 55 openlog("wpa_supplicant", LOG_PID | LOG_NDELAY, LOG_DAEMON); 56 wpa_debug_syslog++; 57 #endif 58 } 59 60 void wpa_debug_close_syslog(void) 61 { 62 #ifdef CONFIG_DEBUG_SYSLOG 63 if (wpa_debug_syslog) 64 closelog(); 65 #endif 66 } 67 68 #ifdef CONFIG_DEBUG_SYSLOG 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, 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, 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 #endif /* CONFIG_NO_WPA_MSG */ 339 340 341 #ifndef CONFIG_NO_HOSTAPD_LOGGER 342 static hostapd_logger_cb_func hostapd_logger_cb = NULL; 343 344 void hostapd_logger_register_cb(hostapd_logger_cb_func func) 345 { 346 hostapd_logger_cb = func; 347 } 348 349 350 void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level, 351 const char *fmt, ...) 352 { 353 va_list ap; 354 char *buf; 355 const int buflen = 2048; 356 int len; 357 358 buf = os_malloc(buflen); 359 if (buf == NULL) { 360 wpa_printf(MSG_ERROR, "hostapd_logger: Failed to allocate " 361 "message buffer"); 362 return; 363 } 364 va_start(ap, fmt); 365 len = vsnprintf(buf, buflen, fmt, ap); 366 va_end(ap); 367 if (hostapd_logger_cb) 368 hostapd_logger_cb(ctx, addr, module, level, buf, len); 369 else 370 wpa_printf(MSG_DEBUG, "hostapd_logger: %s", buf); 371 os_free(buf); 372 } 373 #endif /* CONFIG_NO_HOSTAPD_LOGGER */ 374