1 /* 2 * wpa_supplicant/hostapd / common helper functions, etc. 3 * Copyright (c) 2002-2006, 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 int wpa_debug_level = MSG_INFO; 24 int wpa_debug_show_keys = 0; 25 int wpa_debug_timestamp = 0; 26 27 28 static int hex2num(char c) 29 { 30 if (c >= '0' && c <= '9') 31 return c - '0'; 32 if (c >= 'a' && c <= 'f') 33 return c - 'a' + 10; 34 if (c >= 'A' && c <= 'F') 35 return c - 'A' + 10; 36 return -1; 37 } 38 39 40 static int hex2byte(const char *hex) 41 { 42 int a, b; 43 a = hex2num(*hex++); 44 if (a < 0) 45 return -1; 46 b = hex2num(*hex++); 47 if (b < 0) 48 return -1; 49 return (a << 4) | b; 50 } 51 52 53 /** 54 * hwaddr_aton - Convert ASCII string to MAC address 55 * @txt: MAC address as a string (e.g., "00:11:22:33:44:55") 56 * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) 57 * Returns: 0 on success, -1 on failure (e.g., string not a MAC address) 58 */ 59 int hwaddr_aton(const char *txt, u8 *addr) 60 { 61 int i; 62 63 for (i = 0; i < 6; i++) { 64 int a, b; 65 66 a = hex2num(*txt++); 67 if (a < 0) 68 return -1; 69 b = hex2num(*txt++); 70 if (b < 0) 71 return -1; 72 *addr++ = (a << 4) | b; 73 if (i < 5 && *txt++ != ':') 74 return -1; 75 } 76 77 return 0; 78 } 79 80 81 /** 82 * hexstr2bin - Convert ASCII hex string into binary data 83 * @hex: ASCII hex string (e.g., "01ab") 84 * @buf: Buffer for the binary data 85 * @len: Length of the text to convert in bytes (of buf); hex will be double 86 * this size 87 * Returns: 0 on success, -1 on failure (invalid hex string) 88 */ 89 int hexstr2bin(const char *hex, u8 *buf, size_t len) 90 { 91 size_t i; 92 int a; 93 const char *ipos = hex; 94 u8 *opos = buf; 95 96 for (i = 0; i < len; i++) { 97 a = hex2byte(ipos); 98 if (a < 0) 99 return -1; 100 *opos++ = a; 101 ipos += 2; 102 } 103 return 0; 104 } 105 106 107 /** 108 * inc_byte_array - Increment arbitrary length byte array by one 109 * @counter: Pointer to byte array 110 * @len: Length of the counter in bytes 111 * 112 * This function increments the last byte of the counter by one and continues 113 * rolling over to more significant bytes if the byte was incremented from 114 * 0xff to 0x00. 115 */ 116 void inc_byte_array(u8 *counter, size_t len) 117 { 118 int pos = len - 1; 119 while (pos >= 0) { 120 counter[pos]++; 121 if (counter[pos] != 0) 122 break; 123 pos--; 124 } 125 } 126 127 128 void wpa_get_ntp_timestamp(u8 *buf) 129 { 130 struct os_time now; 131 u32 sec, usec; 132 133 /* 64-bit NTP timestamp (time from 1900-01-01 00:00:00) */ 134 os_get_time(&now); 135 sec = host_to_be32(now.sec + 2208988800U); /* Epoch to 1900 */ 136 /* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */ 137 usec = now.usec; 138 usec = host_to_be32(4295 * usec - (usec >> 5) - (usec >> 9)); 139 os_memcpy(buf, (u8 *) &sec, 4); 140 os_memcpy(buf + 4, (u8 *) &usec, 4); 141 } 142 143 #ifdef ANDROID 144 145 #include <android/log.h> 146 147 void android_printf(int level, char *format, ...) 148 { 149 if (level >= wpa_debug_level) { 150 va_list ap; 151 if (level == MSG_ERROR) { 152 level = ANDROID_LOG_ERROR; 153 } else if (level == MSG_WARNING) { 154 level = ANDROID_LOG_WARN; 155 } else if (level == MSG_INFO) { 156 level = ANDROID_LOG_INFO; 157 } else { 158 level = ANDROID_LOG_DEBUG; 159 } 160 va_start(ap, format); 161 __android_log_vprint(level, "wpa_supplicant", format, ap); 162 va_end(ap); 163 } 164 } 165 166 #else /* ANDROID */ 167 168 #ifndef CONFIG_NO_STDOUT_DEBUG 169 170 void wpa_debug_print_timestamp(void) 171 { 172 struct os_time tv; 173 174 if (!wpa_debug_timestamp) 175 return; 176 177 os_get_time(&tv); 178 #ifdef CONFIG_DEBUG_FILE 179 if (out_file) { 180 fprintf(out_file, "%ld.%06u: ", (long) tv.sec, 181 (unsigned int) tv.usec); 182 } else 183 #endif /* CONFIG_DEBUG_FILE */ 184 printf("%ld.%06u: ", (long) tv.sec, (unsigned int) tv.usec); 185 } 186 187 188 /** 189 * wpa_printf - conditional printf 190 * @level: priority level (MSG_*) of the message 191 * @fmt: printf format string, followed by optional arguments 192 * 193 * This function is used to print conditional debugging and error messages. The 194 * output may be directed to stdout, stderr, and/or syslog based on 195 * configuration. 196 * 197 * Note: New line '\n' is added to the end of the text when printing to stdout. 198 */ 199 void wpa_printf(int level, char *fmt, ...) 200 { 201 va_list ap; 202 203 va_start(ap, fmt); 204 if (level >= wpa_debug_level) { 205 wpa_debug_print_timestamp(); 206 #ifdef CONFIG_DEBUG_FILE 207 if (out_file) { 208 vfprintf(out_file, fmt, ap); 209 fprintf(out_file, "\n"); 210 } else { 211 #endif /* CONFIG_DEBUG_FILE */ 212 vprintf(fmt, ap); 213 printf("\n"); 214 #ifdef CONFIG_DEBUG_FILE 215 } 216 #endif /* CONFIG_DEBUG_FILE */ 217 } 218 va_end(ap); 219 } 220 221 222 static void _wpa_hexdump(int level, const char *title, const u8 *buf, 223 size_t len, int show) 224 { 225 size_t i; 226 if (level < wpa_debug_level) 227 return; 228 wpa_debug_print_timestamp(); 229 #ifdef CONFIG_DEBUG_FILE 230 if (out_file) { 231 fprintf(out_file, "%s - hexdump(len=%lu):", 232 title, (unsigned long) len); 233 if (buf == NULL) { 234 fprintf(out_file, " [NULL]"); 235 } else if (show) { 236 for (i = 0; i < len; i++) 237 fprintf(out_file, " %02x", buf[i]); 238 } else { 239 fprintf(out_file, " [REMOVED]"); 240 } 241 fprintf(out_file, "\n"); 242 } else { 243 #endif /* CONFIG_DEBUG_FILE */ 244 printf("%s - hexdump(len=%lu):", title, (unsigned long) len); 245 if (buf == NULL) { 246 printf(" [NULL]"); 247 } else if (show) { 248 for (i = 0; i < len; i++) 249 printf(" %02x", buf[i]); 250 } else { 251 printf(" [REMOVED]"); 252 } 253 printf("\n"); 254 #ifdef CONFIG_DEBUG_FILE 255 } 256 #endif /* CONFIG_DEBUG_FILE */ 257 } 258 259 void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len) 260 { 261 _wpa_hexdump(level, title, buf, len, 1); 262 } 263 264 265 void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len) 266 { 267 _wpa_hexdump(level, title, buf, len, wpa_debug_show_keys); 268 } 269 270 271 static void _wpa_hexdump_ascii(int level, const char *title, const u8 *buf, 272 size_t len, int show) 273 { 274 size_t i, llen; 275 const u8 *pos = buf; 276 const size_t line_len = 16; 277 278 if (level < wpa_debug_level) 279 return; 280 wpa_debug_print_timestamp(); 281 #ifdef CONFIG_DEBUG_FILE 282 if (out_file) { 283 if (!show) { 284 fprintf(out_file, 285 "%s - hexdump_ascii(len=%lu): [REMOVED]\n", 286 title, (unsigned long) len); 287 return; 288 } 289 if (buf == NULL) { 290 fprintf(out_file, 291 "%s - hexdump_ascii(len=%lu): [NULL]\n", 292 title, (unsigned long) len); 293 return; 294 } 295 fprintf(out_file, "%s - hexdump_ascii(len=%lu):\n", 296 title, (unsigned long) len); 297 while (len) { 298 llen = len > line_len ? line_len : len; 299 fprintf(out_file, " "); 300 for (i = 0; i < llen; i++) 301 fprintf(out_file, " %02x", pos[i]); 302 for (i = llen; i < line_len; i++) 303 fprintf(out_file, " "); 304 fprintf(out_file, " "); 305 for (i = 0; i < llen; i++) { 306 if (isprint(pos[i])) 307 fprintf(out_file, "%c", pos[i]); 308 else 309 fprintf(out_file, "_"); 310 } 311 for (i = llen; i < line_len; i++) 312 fprintf(out_file, " "); 313 fprintf(out_file, "\n"); 314 pos += llen; 315 len -= llen; 316 } 317 } else { 318 #endif /* CONFIG_DEBUG_FILE */ 319 if (!show) { 320 printf("%s - hexdump_ascii(len=%lu): [REMOVED]\n", 321 title, (unsigned long) len); 322 return; 323 } 324 if (buf == NULL) { 325 printf("%s - hexdump_ascii(len=%lu): [NULL]\n", 326 title, (unsigned long) len); 327 return; 328 } 329 printf("%s - hexdump_ascii(len=%lu):\n", title, (unsigned long) len); 330 while (len) { 331 llen = len > line_len ? line_len : len; 332 printf(" "); 333 for (i = 0; i < llen; i++) 334 printf(" %02x", pos[i]); 335 for (i = llen; i < line_len; i++) 336 printf(" "); 337 printf(" "); 338 for (i = 0; i < llen; i++) { 339 if (isprint(pos[i])) 340 printf("%c", pos[i]); 341 else 342 printf("_"); 343 } 344 for (i = llen; i < line_len; i++) 345 printf(" "); 346 printf("\n"); 347 pos += llen; 348 len -= llen; 349 } 350 #ifdef CONFIG_DEBUG_FILE 351 } 352 #endif /* CONFIG_DEBUG_FILE */ 353 } 354 355 356 void wpa_hexdump_ascii(int level, const char *title, const u8 *buf, size_t len) 357 { 358 _wpa_hexdump_ascii(level, title, buf, len, 1); 359 } 360 361 362 void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf, 363 size_t len) 364 { 365 _wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys); 366 } 367 368 369 int wpa_debug_open_file(const char *path) 370 { 371 #ifdef CONFIG_DEBUG_FILE 372 if (!path) 373 return 0; 374 out_file = fopen(path, "a"); 375 if (out_file == NULL) { 376 wpa_printf(MSG_ERROR, "wpa_debug_open_file: Failed to open " 377 "output file, using standard output"); 378 return -1; 379 } 380 #ifndef _WIN32 381 setvbuf(out_file, NULL, _IOLBF, 0); 382 #endif /* _WIN32 */ 383 #endif /* CONFIG_DEBUG_FILE */ 384 return 0; 385 } 386 387 388 void wpa_debug_close_file(void) 389 { 390 #ifdef CONFIG_DEBUG_FILE 391 if (!out_file) 392 return; 393 fclose(out_file); 394 out_file = NULL; 395 #endif /* CONFIG_DEBUG_FILE */ 396 } 397 398 #endif /* CONFIG_NO_STDOUT_DEBUG */ 399 400 #endif /* ANDROID */ 401 402 #ifndef CONFIG_NO_WPA_MSG 403 static wpa_msg_cb_func wpa_msg_cb = NULL; 404 405 void wpa_msg_register_cb(wpa_msg_cb_func func) 406 { 407 wpa_msg_cb = func; 408 } 409 410 411 void wpa_msg(void *ctx, int level, char *fmt, ...) 412 { 413 va_list ap; 414 char *buf; 415 const int buflen = 2048; 416 int len; 417 418 buf = os_malloc(buflen); 419 if (buf == NULL) { 420 wpa_printf(MSG_ERROR, "wpa_msg: Failed to allocate message " 421 "buffer"); 422 return; 423 } 424 va_start(ap, fmt); 425 len = vsnprintf(buf, buflen, fmt, ap); 426 va_end(ap); 427 wpa_printf(level, "%s", buf); 428 if (wpa_msg_cb) 429 wpa_msg_cb(ctx, level, buf, len); 430 os_free(buf); 431 } 432 #endif /* CONFIG_NO_WPA_MSG */ 433 434 435 static inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, 436 size_t len, int uppercase) 437 { 438 size_t i; 439 char *pos = buf, *end = buf + buf_size; 440 int ret; 441 if (buf_size == 0) 442 return 0; 443 for (i = 0; i < len; i++) { 444 ret = os_snprintf(pos, end - pos, uppercase ? "%02X" : "%02x", 445 data[i]); 446 if (ret < 0 || ret >= end - pos) { 447 end[-1] = '\0'; 448 return pos - buf; 449 } 450 pos += ret; 451 } 452 end[-1] = '\0'; 453 return pos - buf; 454 } 455 456 /** 457 * wpa_snprintf_hex - Print data as a hex string into a buffer 458 * @buf: Memory area to use as the output buffer 459 * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1) 460 * @data: Data to be printed 461 * @len: Length of data in bytes 462 * Returns: Number of bytes written 463 */ 464 int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len) 465 { 466 return _wpa_snprintf_hex(buf, buf_size, data, len, 0); 467 } 468 469 470 /** 471 * wpa_snprintf_hex_uppercase - Print data as a upper case hex string into buf 472 * @buf: Memory area to use as the output buffer 473 * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1) 474 * @data: Data to be printed 475 * @len: Length of data in bytes 476 * Returns: Number of bytes written 477 */ 478 int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data, 479 size_t len) 480 { 481 return _wpa_snprintf_hex(buf, buf_size, data, len, 1); 482 } 483 484 485 #ifdef CONFIG_ANSI_C_EXTRA 486 487 #ifdef _WIN32_WCE 488 void perror(const char *s) 489 { 490 wpa_printf(MSG_ERROR, "%s: GetLastError: %d", 491 s, (int) GetLastError()); 492 } 493 #endif /* _WIN32_WCE */ 494 495 496 int optind = 1; 497 int optopt; 498 char *optarg; 499 500 int getopt(int argc, char *const argv[], const char *optstring) 501 { 502 static int optchr = 1; 503 char *cp; 504 505 if (optchr == 1) { 506 if (optind >= argc) { 507 /* all arguments processed */ 508 return EOF; 509 } 510 511 if (argv[optind][0] != '-' || argv[optind][1] == '\0') { 512 /* no option characters */ 513 return EOF; 514 } 515 } 516 517 if (os_strcmp(argv[optind], "--") == 0) { 518 /* no more options */ 519 optind++; 520 return EOF; 521 } 522 523 optopt = argv[optind][optchr]; 524 cp = os_strchr(optstring, optopt); 525 if (cp == NULL || optopt == ':') { 526 if (argv[optind][++optchr] == '\0') { 527 optchr = 1; 528 optind++; 529 } 530 return '?'; 531 } 532 533 if (cp[1] == ':') { 534 /* Argument required */ 535 optchr = 1; 536 if (argv[optind][optchr + 1]) { 537 /* No space between option and argument */ 538 optarg = &argv[optind++][optchr + 1]; 539 } else if (++optind >= argc) { 540 /* option requires an argument */ 541 return '?'; 542 } else { 543 /* Argument in the next argv */ 544 optarg = argv[optind++]; 545 } 546 } else { 547 /* No argument */ 548 if (argv[optind][++optchr] == '\0') { 549 optchr = 1; 550 optind++; 551 } 552 optarg = NULL; 553 } 554 return *cp; 555 } 556 #endif /* CONFIG_ANSI_C_EXTRA */ 557 558 559 #ifdef CONFIG_NATIVE_WINDOWS 560 /** 561 * wpa_unicode2ascii_inplace - Convert unicode string into ASCII 562 * @str: Pointer to string to convert 563 * 564 * This function converts a unicode string to ASCII using the same 565 * buffer for output. If UNICODE is not set, the buffer is not 566 * modified. 567 */ 568 void wpa_unicode2ascii_inplace(TCHAR *str) 569 { 570 #ifdef UNICODE 571 char *dst = (char *) str; 572 while (*str) 573 *dst++ = (char) *str++; 574 *dst = '\0'; 575 #endif /* UNICODE */ 576 } 577 578 579 TCHAR * wpa_strdup_tchar(const char *str) 580 { 581 #ifdef UNICODE 582 TCHAR *buf; 583 buf = os_malloc((strlen(str) + 1) * sizeof(TCHAR)); 584 if (buf == NULL) 585 return NULL; 586 wsprintf(buf, L"%S", str); 587 return buf; 588 #else /* UNICODE */ 589 return os_strdup(str); 590 #endif /* UNICODE */ 591 } 592 #endif /* CONFIG_NATIVE_WINDOWS */ 593 594 595 /** 596 * wpa_ssid_txt - Convert SSID to a printable string 597 * @ssid: SSID (32-octet string) 598 * @ssid_len: Length of ssid in octets 599 * Returns: Pointer to a printable string 600 * 601 * This function can be used to convert SSIDs into printable form. In most 602 * cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard 603 * does not limit the used character set, so anything could be used in an SSID. 604 * 605 * This function uses a static buffer, so only one call can be used at the 606 * time, i.e., this is not re-entrant and the returned buffer must be used 607 * before calling this again. 608 */ 609 const char * wpa_ssid_txt(u8 *ssid, size_t ssid_len) 610 { 611 static char ssid_txt[33]; 612 char *pos; 613 614 if (ssid_len > 32) 615 ssid_len = 32; 616 os_memcpy(ssid_txt, ssid, ssid_len); 617 ssid_txt[ssid_len] = '\0'; 618 for (pos = ssid_txt; *pos != '\0'; pos++) { 619 #ifndef WPA_UNICODE_SSID 620 /* Don't do this, since it prevents us from using APs with non-ASCII SSIDs */ 621 if ((u8) *pos < 32 || (u8) *pos >= 127) 622 *pos = '_'; 623 #endif 624 } 625 return ssid_txt; 626 } 627