1 /* 2 * wpa_supplicant/hostapd / Debug prints 3 * Copyright (c) 2002-2007, Jouni Malinen <j (at) w1.fi> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9 #include "includes.h" 10 11 #include "common.h" 12 13 #ifdef CONFIG_DEBUG_SYSLOG 14 #include <syslog.h> 15 16 static int wpa_debug_syslog = 0; 17 #endif /* CONFIG_DEBUG_SYSLOG */ 18 19 20 int wpa_debug_level = MSG_INFO; 21 int wpa_debug_show_keys = 0; 22 int wpa_debug_timestamp = 0; 23 24 25 #ifdef CONFIG_ANDROID_LOG 26 27 #include <android/log.h> 28 29 #ifndef ANDROID_LOG_NAME 30 #define ANDROID_LOG_NAME "wpa_supplicant" 31 #endif /* ANDROID_LOG_NAME */ 32 33 void android_printf(int level, char *format, ...) 34 { 35 if (level >= wpa_debug_level) { 36 va_list ap; 37 if (level == MSG_ERROR) 38 level = ANDROID_LOG_ERROR; 39 else if (level == MSG_WARNING) 40 level = ANDROID_LOG_WARN; 41 else if (level == MSG_INFO) 42 level = ANDROID_LOG_INFO; 43 else 44 level = ANDROID_LOG_DEBUG; 45 va_start(ap, format); 46 __android_log_vprint(level, ANDROID_LOG_NAME, format, ap); 47 va_end(ap); 48 } 49 } 50 51 #else /* CONFIG_ANDROID_LOG */ 52 53 #ifndef CONFIG_NO_STDOUT_DEBUG 54 55 #ifdef CONFIG_DEBUG_FILE 56 static FILE *out_file = NULL; 57 #endif /* CONFIG_DEBUG_FILE */ 58 59 60 void wpa_debug_print_timestamp(void) 61 { 62 struct os_time tv; 63 64 if (!wpa_debug_timestamp) 65 return; 66 67 os_get_time(&tv); 68 #ifdef CONFIG_DEBUG_FILE 69 if (out_file) { 70 fprintf(out_file, "%ld.%06u: ", (long) tv.sec, 71 (unsigned int) tv.usec); 72 } else 73 #endif /* CONFIG_DEBUG_FILE */ 74 printf("%ld.%06u: ", (long) tv.sec, (unsigned int) tv.usec); 75 } 76 77 78 #ifdef CONFIG_DEBUG_SYSLOG 79 #ifndef LOG_HOSTAPD 80 #define LOG_HOSTAPD LOG_DAEMON 81 #endif /* LOG_HOSTAPD */ 82 83 void wpa_debug_open_syslog(void) 84 { 85 openlog("wpa_supplicant", LOG_PID | LOG_NDELAY, LOG_HOSTAPD); 86 wpa_debug_syslog++; 87 } 88 89 90 void wpa_debug_close_syslog(void) 91 { 92 if (wpa_debug_syslog) 93 closelog(); 94 } 95 96 97 static int syslog_priority(int level) 98 { 99 switch (level) { 100 case MSG_MSGDUMP: 101 case MSG_DEBUG: 102 return LOG_DEBUG; 103 case MSG_INFO: 104 return LOG_NOTICE; 105 case MSG_WARNING: 106 return LOG_WARNING; 107 case MSG_ERROR: 108 return LOG_ERR; 109 } 110 return LOG_INFO; 111 } 112 #endif /* CONFIG_DEBUG_SYSLOG */ 113 114 115 /** 116 * wpa_printf - conditional printf 117 * @level: priority level (MSG_*) of the message 118 * @fmt: printf format string, followed by optional arguments 119 * 120 * This function is used to print conditional debugging and error messages. The 121 * output may be directed to stdout, stderr, and/or syslog based on 122 * configuration. 123 * 124 * Note: New line '\n' is added to the end of the text when printing to stdout. 125 */ 126 void wpa_printf(int level, const char *fmt, ...) 127 { 128 va_list ap; 129 130 va_start(ap, fmt); 131 if (level >= wpa_debug_level) { 132 #ifdef CONFIG_DEBUG_SYSLOG 133 if (wpa_debug_syslog) { 134 vsyslog(syslog_priority(level), fmt, ap); 135 } else { 136 #endif /* CONFIG_DEBUG_SYSLOG */ 137 wpa_debug_print_timestamp(); 138 #ifdef CONFIG_DEBUG_FILE 139 if (out_file) { 140 vfprintf(out_file, fmt, ap); 141 fprintf(out_file, "\n"); 142 } else { 143 #endif /* CONFIG_DEBUG_FILE */ 144 vprintf(fmt, ap); 145 printf("\n"); 146 #ifdef CONFIG_DEBUG_FILE 147 } 148 #endif /* CONFIG_DEBUG_FILE */ 149 #ifdef CONFIG_DEBUG_SYSLOG 150 } 151 #endif /* CONFIG_DEBUG_SYSLOG */ 152 } 153 va_end(ap); 154 } 155 156 157 static void _wpa_hexdump(int level, const char *title, const u8 *buf, 158 size_t len, int show) 159 { 160 size_t i; 161 if (level < wpa_debug_level) 162 return; 163 #ifdef CONFIG_DEBUG_SYSLOG 164 if (wpa_debug_syslog) { 165 const char *display; 166 char *strbuf = NULL; 167 168 if (buf == NULL) { 169 display = " [NULL]"; 170 } else if (len == 0) { 171 display = ""; 172 } else if (show && len) { 173 strbuf = os_malloc(1 + 3 * len); 174 if (strbuf == NULL) { 175 wpa_printf(MSG_ERROR, "wpa_hexdump: Failed to " 176 "allocate message buffer"); 177 return; 178 } 179 180 for (i = 0; i < len; i++) 181 os_snprintf(&strbuf[i * 3], 4, " %02x", 182 buf[i]); 183 184 display = strbuf; 185 } else { 186 display = " [REMOVED]"; 187 } 188 189 syslog(syslog_priority(level), "%s - hexdump(len=%lu):%s", 190 title, len, display); 191 os_free(strbuf); 192 return; 193 } 194 #endif /* CONFIG_DEBUG_SYSLOG */ 195 wpa_debug_print_timestamp(); 196 #ifdef CONFIG_DEBUG_FILE 197 if (out_file) { 198 fprintf(out_file, "%s - hexdump(len=%lu):", 199 title, (unsigned long) len); 200 if (buf == NULL) { 201 fprintf(out_file, " [NULL]"); 202 } else if (show) { 203 for (i = 0; i < len; i++) 204 fprintf(out_file, " %02x", buf[i]); 205 } else { 206 fprintf(out_file, " [REMOVED]"); 207 } 208 fprintf(out_file, "\n"); 209 } else { 210 #endif /* CONFIG_DEBUG_FILE */ 211 printf("%s - hexdump(len=%lu):", title, (unsigned long) len); 212 if (buf == NULL) { 213 printf(" [NULL]"); 214 } else if (show) { 215 for (i = 0; i < len; i++) 216 printf(" %02x", buf[i]); 217 } else { 218 printf(" [REMOVED]"); 219 } 220 printf("\n"); 221 #ifdef CONFIG_DEBUG_FILE 222 } 223 #endif /* CONFIG_DEBUG_FILE */ 224 } 225 226 void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len) 227 { 228 _wpa_hexdump(level, title, buf, len, 1); 229 } 230 231 232 void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len) 233 { 234 _wpa_hexdump(level, title, buf, len, wpa_debug_show_keys); 235 } 236 237 238 static void _wpa_hexdump_ascii(int level, const char *title, const u8 *buf, 239 size_t len, int show) 240 { 241 size_t i, llen; 242 const u8 *pos = buf; 243 const size_t line_len = 16; 244 245 if (level < wpa_debug_level) 246 return; 247 wpa_debug_print_timestamp(); 248 #ifdef CONFIG_DEBUG_FILE 249 if (out_file) { 250 if (!show) { 251 fprintf(out_file, 252 "%s - hexdump_ascii(len=%lu): [REMOVED]\n", 253 title, (unsigned long) len); 254 return; 255 } 256 if (buf == NULL) { 257 fprintf(out_file, 258 "%s - hexdump_ascii(len=%lu): [NULL]\n", 259 title, (unsigned long) len); 260 return; 261 } 262 fprintf(out_file, "%s - hexdump_ascii(len=%lu):\n", 263 title, (unsigned long) len); 264 while (len) { 265 llen = len > line_len ? line_len : len; 266 fprintf(out_file, " "); 267 for (i = 0; i < llen; i++) 268 fprintf(out_file, " %02x", pos[i]); 269 for (i = llen; i < line_len; i++) 270 fprintf(out_file, " "); 271 fprintf(out_file, " "); 272 for (i = 0; i < llen; i++) { 273 if (isprint(pos[i])) 274 fprintf(out_file, "%c", pos[i]); 275 else 276 fprintf(out_file, "_"); 277 } 278 for (i = llen; i < line_len; i++) 279 fprintf(out_file, " "); 280 fprintf(out_file, "\n"); 281 pos += llen; 282 len -= llen; 283 } 284 } else { 285 #endif /* CONFIG_DEBUG_FILE */ 286 if (!show) { 287 printf("%s - hexdump_ascii(len=%lu): [REMOVED]\n", 288 title, (unsigned long) len); 289 return; 290 } 291 if (buf == NULL) { 292 printf("%s - hexdump_ascii(len=%lu): [NULL]\n", 293 title, (unsigned long) len); 294 return; 295 } 296 printf("%s - hexdump_ascii(len=%lu):\n", title, (unsigned long) len); 297 while (len) { 298 llen = len > line_len ? line_len : len; 299 printf(" "); 300 for (i = 0; i < llen; i++) 301 printf(" %02x", pos[i]); 302 for (i = llen; i < line_len; i++) 303 printf(" "); 304 printf(" "); 305 for (i = 0; i < llen; i++) { 306 if (isprint(pos[i])) 307 printf("%c", pos[i]); 308 else 309 printf("_"); 310 } 311 for (i = llen; i < line_len; i++) 312 printf(" "); 313 printf("\n"); 314 pos += llen; 315 len -= llen; 316 } 317 #ifdef CONFIG_DEBUG_FILE 318 } 319 #endif /* CONFIG_DEBUG_FILE */ 320 } 321 322 323 void wpa_hexdump_ascii(int level, const char *title, const u8 *buf, size_t len) 324 { 325 _wpa_hexdump_ascii(level, title, buf, len, 1); 326 } 327 328 329 void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf, 330 size_t len) 331 { 332 _wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys); 333 } 334 335 336 #ifdef CONFIG_DEBUG_FILE 337 static char *last_path = NULL; 338 #endif /* CONFIG_DEBUG_FILE */ 339 340 int wpa_debug_reopen_file(void) 341 { 342 #ifdef CONFIG_DEBUG_FILE 343 int rv; 344 if (last_path) { 345 char *tmp = os_strdup(last_path); 346 wpa_debug_close_file(); 347 rv = wpa_debug_open_file(tmp); 348 os_free(tmp); 349 } else { 350 wpa_printf(MSG_ERROR, "Last-path was not set, cannot " 351 "re-open log file."); 352 rv = -1; 353 } 354 return rv; 355 #else /* CONFIG_DEBUG_FILE */ 356 return 0; 357 #endif /* CONFIG_DEBUG_FILE */ 358 } 359 360 361 int wpa_debug_open_file(const char *path) 362 { 363 #ifdef CONFIG_DEBUG_FILE 364 if (!path) 365 return 0; 366 367 if (last_path == NULL || os_strcmp(last_path, path) != 0) { 368 /* Save our path to enable re-open */ 369 os_free(last_path); 370 last_path = os_strdup(path); 371 } 372 373 out_file = fopen(path, "a"); 374 if (out_file == NULL) { 375 wpa_printf(MSG_ERROR, "wpa_debug_open_file: Failed to open " 376 "output file, using standard output"); 377 return -1; 378 } 379 #ifndef _WIN32 380 setvbuf(out_file, NULL, _IOLBF, 0); 381 #endif /* _WIN32 */ 382 #endif /* CONFIG_DEBUG_FILE */ 383 return 0; 384 } 385 386 387 void wpa_debug_close_file(void) 388 { 389 #ifdef CONFIG_DEBUG_FILE 390 if (!out_file) 391 return; 392 fclose(out_file); 393 out_file = NULL; 394 os_free(last_path); 395 last_path = NULL; 396 #endif /* CONFIG_DEBUG_FILE */ 397 } 398 399 #endif /* CONFIG_NO_STDOUT_DEBUG */ 400 401 #endif /* CONFIG_ANDROID_LOG */ 402 403 #ifndef CONFIG_NO_WPA_MSG 404 static wpa_msg_cb_func wpa_msg_cb = NULL; 405 406 void wpa_msg_register_cb(wpa_msg_cb_func func) 407 { 408 wpa_msg_cb = func; 409 } 410 411 412 static wpa_msg_get_ifname_func wpa_msg_ifname_cb = NULL; 413 414 void wpa_msg_register_ifname_cb(wpa_msg_get_ifname_func func) 415 { 416 wpa_msg_ifname_cb = func; 417 } 418 419 420 void wpa_msg(void *ctx, int level, const char *fmt, ...) 421 { 422 va_list ap; 423 char *buf; 424 const int buflen = 2048; 425 int len; 426 char prefix[130]; 427 428 buf = os_malloc(buflen); 429 if (buf == NULL) { 430 wpa_printf(MSG_ERROR, "wpa_msg: Failed to allocate message " 431 "buffer"); 432 return; 433 } 434 va_start(ap, fmt); 435 prefix[0] = '\0'; 436 if (wpa_msg_ifname_cb) { 437 const char *ifname = wpa_msg_ifname_cb(ctx); 438 if (ifname) { 439 int res = os_snprintf(prefix, sizeof(prefix), "%s: ", 440 ifname); 441 if (res < 0 || res >= (int) sizeof(prefix)) 442 prefix[0] = '\0'; 443 } 444 } 445 len = vsnprintf(buf, buflen, fmt, ap); 446 va_end(ap); 447 wpa_printf(level, "%s%s", prefix, buf); 448 if (wpa_msg_cb) 449 wpa_msg_cb(ctx, level, buf, len); 450 os_free(buf); 451 } 452 453 454 void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...) 455 { 456 va_list ap; 457 char *buf; 458 const int buflen = 2048; 459 int len; 460 461 if (!wpa_msg_cb) 462 return; 463 464 buf = os_malloc(buflen); 465 if (buf == NULL) { 466 wpa_printf(MSG_ERROR, "wpa_msg_ctrl: Failed to allocate " 467 "message buffer"); 468 return; 469 } 470 va_start(ap, fmt); 471 len = vsnprintf(buf, buflen, fmt, ap); 472 va_end(ap); 473 wpa_msg_cb(ctx, level, buf, len); 474 os_free(buf); 475 } 476 #endif /* CONFIG_NO_WPA_MSG */ 477 478 479 #ifndef CONFIG_NO_HOSTAPD_LOGGER 480 static hostapd_logger_cb_func hostapd_logger_cb = NULL; 481 482 void hostapd_logger_register_cb(hostapd_logger_cb_func func) 483 { 484 hostapd_logger_cb = func; 485 } 486 487 488 void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level, 489 const char *fmt, ...) 490 { 491 va_list ap; 492 char *buf; 493 const int buflen = 2048; 494 int len; 495 496 buf = os_malloc(buflen); 497 if (buf == NULL) { 498 wpa_printf(MSG_ERROR, "hostapd_logger: Failed to allocate " 499 "message buffer"); 500 return; 501 } 502 va_start(ap, fmt); 503 len = vsnprintf(buf, buflen, fmt, ap); 504 va_end(ap); 505 if (hostapd_logger_cb) 506 hostapd_logger_cb(ctx, addr, module, level, buf, len); 507 else if (addr) 508 wpa_printf(MSG_DEBUG, "hostapd_logger: STA " MACSTR " - %s", 509 MAC2STR(addr), buf); 510 else 511 wpa_printf(MSG_DEBUG, "hostapd_logger: %s", buf); 512 os_free(buf); 513 } 514 #endif /* CONFIG_NO_HOSTAPD_LOGGER */ 515