1 /* 2 * wpa_supplicant/hostapd / common helper functions, etc. 3 * Copyright (c) 2002-2019, Jouni Malinen <j@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/ieee802_11_defs.h" 12 #include "common.h" 13 14 15 static int hex2num(char c) 16 { 17 if (c >= '0' && c <= '9') 18 return c - '0'; 19 if (c >= 'a' && c <= 'f') 20 return c - 'a' + 10; 21 if (c >= 'A' && c <= 'F') 22 return c - 'A' + 10; 23 return -1; 24 } 25 26 27 int hex2byte(const char *hex) 28 { 29 int a, b; 30 a = hex2num(*hex++); 31 if (a < 0) 32 return -1; 33 b = hex2num(*hex++); 34 if (b < 0) 35 return -1; 36 return (a << 4) | b; 37 } 38 39 40 static const char * hwaddr_parse(const char *txt, u8 *addr) 41 { 42 size_t i; 43 44 for (i = 0; i < ETH_ALEN; i++) { 45 int a; 46 47 a = hex2byte(txt); 48 if (a < 0) 49 return NULL; 50 txt += 2; 51 addr[i] = a; 52 if (i < ETH_ALEN - 1 && *txt++ != ':') 53 return NULL; 54 } 55 return txt; 56 } 57 58 59 /** 60 * hwaddr_aton - Convert ASCII string to MAC address (colon-delimited format) 61 * @txt: MAC address as a string (e.g., "00:11:22:33:44:55") 62 * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) 63 * Returns: 0 on success, -1 on failure (e.g., string not a MAC address) 64 */ 65 int hwaddr_aton(const char *txt, u8 *addr) 66 { 67 return hwaddr_parse(txt, addr) ? 0 : -1; 68 } 69 70 71 /** 72 * hwaddr_masked_aton - Convert ASCII string with optional mask to MAC address (colon-delimited format) 73 * @txt: MAC address with optional mask as a string (e.g., "00:11:22:33:44:55/ff:ff:ff:ff:00:00") 74 * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) 75 * @mask: Buffer for the MAC address mask (ETH_ALEN = 6 bytes) 76 * @maskable: Flag to indicate whether a mask is allowed 77 * Returns: 0 on success, -1 on failure (e.g., string not a MAC address) 78 */ 79 int hwaddr_masked_aton(const char *txt, u8 *addr, u8 *mask, u8 maskable) 80 { 81 const char *r; 82 83 /* parse address part */ 84 r = hwaddr_parse(txt, addr); 85 if (!r) 86 return -1; 87 88 /* check for optional mask */ 89 if (*r == '\0' || isspace((unsigned char) *r)) { 90 /* no mask specified, assume default */ 91 os_memset(mask, 0xff, ETH_ALEN); 92 } else if (maskable && *r == '/') { 93 /* mask specified and allowed */ 94 r = hwaddr_parse(r + 1, mask); 95 /* parser error? */ 96 if (!r) 97 return -1; 98 } else { 99 /* mask specified but not allowed or trailing garbage */ 100 return -1; 101 } 102 103 return 0; 104 } 105 106 107 /** 108 * hwaddr_compact_aton - Convert ASCII string to MAC address (no colon delimitors format) 109 * @txt: MAC address as a string (e.g., "001122334455") 110 * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) 111 * Returns: 0 on success, -1 on failure (e.g., string not a MAC address) 112 */ 113 int hwaddr_compact_aton(const char *txt, u8 *addr) 114 { 115 int i; 116 117 for (i = 0; i < 6; i++) { 118 int a, b; 119 120 a = hex2num(*txt++); 121 if (a < 0) 122 return -1; 123 b = hex2num(*txt++); 124 if (b < 0) 125 return -1; 126 *addr++ = (a << 4) | b; 127 } 128 129 return 0; 130 } 131 132 /** 133 * hwaddr_aton2 - Convert ASCII string to MAC address (in any known format) 134 * @txt: MAC address as a string (e.g., 00:11:22:33:44:55 or 0011.2233.4455) 135 * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) 136 * Returns: Characters used (> 0) on success, -1 on failure 137 */ 138 int hwaddr_aton2(const char *txt, u8 *addr) 139 { 140 int i; 141 const char *pos = txt; 142 143 for (i = 0; i < 6; i++) { 144 int a, b; 145 146 while (*pos == ':' || *pos == '.' || *pos == '-') 147 pos++; 148 149 a = hex2num(*pos++); 150 if (a < 0) 151 return -1; 152 b = hex2num(*pos++); 153 if (b < 0) 154 return -1; 155 *addr++ = (a << 4) | b; 156 } 157 158 return pos - txt; 159 } 160 161 162 /** 163 * hexstr2bin - Convert ASCII hex string into binary data 164 * @hex: ASCII hex string (e.g., "01ab") 165 * @buf: Buffer for the binary data 166 * @len: Length of the text to convert in bytes (of buf); hex will be double 167 * this size 168 * Returns: 0 on success, -1 on failure (invalid hex string) 169 */ 170 int hexstr2bin(const char *hex, u8 *buf, size_t len) 171 { 172 size_t i; 173 int a; 174 const char *ipos = hex; 175 u8 *opos = buf; 176 177 for (i = 0; i < len; i++) { 178 a = hex2byte(ipos); 179 if (a < 0) 180 return -1; 181 *opos++ = a; 182 ipos += 2; 183 } 184 return 0; 185 } 186 187 188 int hwaddr_mask_txt(char *buf, size_t len, const u8 *addr, const u8 *mask) 189 { 190 size_t i; 191 int print_mask = 0; 192 int res; 193 194 for (i = 0; i < ETH_ALEN; i++) { 195 if (mask[i] != 0xff) { 196 print_mask = 1; 197 break; 198 } 199 } 200 201 if (print_mask) 202 res = os_snprintf(buf, len, MACSTR "/" MACSTR, 203 MAC2STR(addr), MAC2STR(mask)); 204 else 205 res = os_snprintf(buf, len, MACSTR, MAC2STR(addr)); 206 if (os_snprintf_error(len, res)) 207 return -1; 208 return res; 209 } 210 211 212 /** 213 * inc_byte_array - Increment arbitrary length byte array by one 214 * @counter: Pointer to byte array 215 * @len: Length of the counter in bytes 216 * 217 * This function increments the last byte of the counter by one and continues 218 * rolling over to more significant bytes if the byte was incremented from 219 * 0xff to 0x00. 220 */ 221 void inc_byte_array(u8 *counter, size_t len) 222 { 223 int pos = len - 1; 224 while (pos >= 0) { 225 counter[pos]++; 226 if (counter[pos] != 0) 227 break; 228 pos--; 229 } 230 } 231 232 233 void buf_shift_right(u8 *buf, size_t len, size_t bits) 234 { 235 size_t i; 236 237 for (i = len - 1; i > 0; i--) 238 buf[i] = (buf[i - 1] << (8 - bits)) | (buf[i] >> bits); 239 buf[0] >>= bits; 240 } 241 242 243 void wpa_get_ntp_timestamp(u8 *buf) 244 { 245 struct os_time now; 246 u32 sec, usec; 247 be32 tmp; 248 249 /* 64-bit NTP timestamp (time from 1900-01-01 00:00:00) */ 250 os_get_time(&now); 251 sec = now.sec + 2208988800U; /* Epoch to 1900 */ 252 /* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */ 253 usec = now.usec; 254 usec = 4295 * usec - (usec >> 5) - (usec >> 9); 255 tmp = host_to_be32(sec); 256 os_memcpy(buf, (u8 *) &tmp, 4); 257 tmp = host_to_be32(usec); 258 os_memcpy(buf + 4, (u8 *) &tmp, 4); 259 } 260 261 /** 262 * wpa_scnprintf - Simpler-to-use snprintf function 263 * @buf: Output buffer 264 * @size: Buffer size 265 * @fmt: format 266 * 267 * Simpler snprintf version that doesn't require further error checks - the 268 * return value only indicates how many bytes were actually written, excluding 269 * the NULL byte (i.e., 0 on error, size-1 if buffer is not big enough). 270 */ 271 int wpa_scnprintf(char *buf, size_t size, const char *fmt, ...) 272 { 273 va_list ap; 274 int ret; 275 276 if (!size) 277 return 0; 278 279 va_start(ap, fmt); 280 ret = vsnprintf(buf, size, fmt, ap); 281 va_end(ap); 282 283 if (ret < 0) 284 return 0; 285 if ((size_t) ret >= size) 286 return size - 1; 287 288 return ret; 289 } 290 291 292 int wpa_snprintf_hex_sep(char *buf, size_t buf_size, const u8 *data, size_t len, 293 char sep) 294 { 295 size_t i; 296 char *pos = buf, *end = buf + buf_size; 297 int ret; 298 299 if (buf_size == 0) 300 return 0; 301 302 for (i = 0; i < len; i++) { 303 ret = os_snprintf(pos, end - pos, "%02x%c", 304 data[i], sep); 305 if (os_snprintf_error(end - pos, ret)) { 306 end[-1] = '\0'; 307 return pos - buf; 308 } 309 pos += ret; 310 } 311 pos[-1] = '\0'; 312 return pos - buf; 313 } 314 315 316 static inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, 317 size_t len, int uppercase) 318 { 319 size_t i; 320 char *pos = buf, *end = buf + buf_size; 321 int ret; 322 if (buf_size == 0) 323 return 0; 324 for (i = 0; i < len; i++) { 325 ret = os_snprintf(pos, end - pos, uppercase ? "%02X" : "%02x", 326 data[i]); 327 if (os_snprintf_error(end - pos, ret)) { 328 end[-1] = '\0'; 329 return pos - buf; 330 } 331 pos += ret; 332 } 333 end[-1] = '\0'; 334 return pos - buf; 335 } 336 337 /** 338 * wpa_snprintf_hex - Print data as a hex string into a buffer 339 * @buf: Memory area to use as the output buffer 340 * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1) 341 * @data: Data to be printed 342 * @len: Length of data in bytes 343 * Returns: Number of bytes written 344 */ 345 int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len) 346 { 347 return _wpa_snprintf_hex(buf, buf_size, data, len, 0); 348 } 349 350 351 /** 352 * wpa_snprintf_hex_uppercase - Print data as a upper case hex string into buf 353 * @buf: Memory area to use as the output buffer 354 * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1) 355 * @data: Data to be printed 356 * @len: Length of data in bytes 357 * Returns: Number of bytes written 358 */ 359 int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data, 360 size_t len) 361 { 362 return _wpa_snprintf_hex(buf, buf_size, data, len, 1); 363 } 364 365 366 #ifdef CONFIG_ANSI_C_EXTRA 367 368 #ifdef _WIN32_WCE 369 void perror(const char *s) 370 { 371 wpa_printf(MSG_ERROR, "%s: GetLastError: %d", 372 s, (int) GetLastError()); 373 } 374 #endif /* _WIN32_WCE */ 375 376 377 int optind = 1; 378 int optopt; 379 char *optarg; 380 381 int getopt(int argc, char *const argv[], const char *optstring) 382 { 383 static int optchr = 1; 384 char *cp; 385 386 if (optchr == 1) { 387 if (optind >= argc) { 388 /* all arguments processed */ 389 return EOF; 390 } 391 392 if (argv[optind][0] != '-' || argv[optind][1] == '\0') { 393 /* no option characters */ 394 return EOF; 395 } 396 } 397 398 if (os_strcmp(argv[optind], "--") == 0) { 399 /* no more options */ 400 optind++; 401 return EOF; 402 } 403 404 optopt = argv[optind][optchr]; 405 cp = os_strchr(optstring, optopt); 406 if (cp == NULL || optopt == ':') { 407 if (argv[optind][++optchr] == '\0') { 408 optchr = 1; 409 optind++; 410 } 411 return '?'; 412 } 413 414 if (cp[1] == ':') { 415 /* Argument required */ 416 optchr = 1; 417 if (argv[optind][optchr + 1]) { 418 /* No space between option and argument */ 419 optarg = &argv[optind++][optchr + 1]; 420 } else if (++optind >= argc) { 421 /* option requires an argument */ 422 return '?'; 423 } else { 424 /* Argument in the next argv */ 425 optarg = argv[optind++]; 426 } 427 } else { 428 /* No argument */ 429 if (argv[optind][++optchr] == '\0') { 430 optchr = 1; 431 optind++; 432 } 433 optarg = NULL; 434 } 435 return *cp; 436 } 437 #endif /* CONFIG_ANSI_C_EXTRA */ 438 439 440 #ifdef CONFIG_NATIVE_WINDOWS 441 /** 442 * wpa_unicode2ascii_inplace - Convert unicode string into ASCII 443 * @str: Pointer to string to convert 444 * 445 * This function converts a unicode string to ASCII using the same 446 * buffer for output. If UNICODE is not set, the buffer is not 447 * modified. 448 */ 449 void wpa_unicode2ascii_inplace(TCHAR *str) 450 { 451 #ifdef UNICODE 452 char *dst = (char *) str; 453 while (*str) 454 *dst++ = (char) *str++; 455 *dst = '\0'; 456 #endif /* UNICODE */ 457 } 458 459 460 TCHAR * wpa_strdup_tchar(const char *str) 461 { 462 #ifdef UNICODE 463 TCHAR *buf; 464 buf = os_malloc((strlen(str) + 1) * sizeof(TCHAR)); 465 if (buf == NULL) 466 return NULL; 467 wsprintf(buf, L"%S", str); 468 return buf; 469 #else /* UNICODE */ 470 return os_strdup(str); 471 #endif /* UNICODE */ 472 } 473 #endif /* CONFIG_NATIVE_WINDOWS */ 474 475 476 void printf_encode(char *txt, size_t maxlen, const u8 *data, size_t len) 477 { 478 char *end = txt + maxlen; 479 size_t i; 480 481 for (i = 0; i < len; i++) { 482 if (txt + 4 >= end) 483 break; 484 485 switch (data[i]) { 486 case '\"': 487 *txt++ = '\\'; 488 *txt++ = '\"'; 489 break; 490 case '\\': 491 *txt++ = '\\'; 492 *txt++ = '\\'; 493 break; 494 case '\033': 495 *txt++ = '\\'; 496 *txt++ = 'e'; 497 break; 498 case '\n': 499 *txt++ = '\\'; 500 *txt++ = 'n'; 501 break; 502 case '\r': 503 *txt++ = '\\'; 504 *txt++ = 'r'; 505 break; 506 case '\t': 507 *txt++ = '\\'; 508 *txt++ = 't'; 509 break; 510 default: 511 if (data[i] >= 32 && data[i] <= 126) { 512 *txt++ = data[i]; 513 } else { 514 txt += os_snprintf(txt, end - txt, "\\x%02x", 515 data[i]); 516 } 517 break; 518 } 519 } 520 521 *txt = '\0'; 522 } 523 524 525 size_t printf_decode(u8 *buf, size_t maxlen, const char *str) 526 { 527 const char *pos = str; 528 size_t len = 0; 529 int val; 530 531 while (*pos) { 532 if (len + 1 >= maxlen) 533 break; 534 switch (*pos) { 535 case '\\': 536 pos++; 537 switch (*pos) { 538 case '\\': 539 buf[len++] = '\\'; 540 pos++; 541 break; 542 case '"': 543 buf[len++] = '"'; 544 pos++; 545 break; 546 case 'n': 547 buf[len++] = '\n'; 548 pos++; 549 break; 550 case 'r': 551 buf[len++] = '\r'; 552 pos++; 553 break; 554 case 't': 555 buf[len++] = '\t'; 556 pos++; 557 break; 558 case 'e': 559 buf[len++] = '\033'; 560 pos++; 561 break; 562 case 'x': 563 pos++; 564 val = hex2byte(pos); 565 if (val < 0) { 566 val = hex2num(*pos); 567 if (val < 0) 568 break; 569 buf[len++] = val; 570 pos++; 571 } else { 572 buf[len++] = val; 573 pos += 2; 574 } 575 break; 576 case '0': 577 case '1': 578 case '2': 579 case '3': 580 case '4': 581 case '5': 582 case '6': 583 case '7': 584 val = *pos++ - '0'; 585 if (*pos >= '0' && *pos <= '7') 586 val = val * 8 + (*pos++ - '0'); 587 if (*pos >= '0' && *pos <= '7') 588 val = val * 8 + (*pos++ - '0'); 589 buf[len++] = val; 590 break; 591 default: 592 break; 593 } 594 break; 595 default: 596 buf[len++] = *pos++; 597 break; 598 } 599 } 600 if (maxlen > len) 601 buf[len] = '\0'; 602 603 return len; 604 } 605 606 607 /** 608 * wpa_ssid_txt - Convert SSID to a printable string 609 * @ssid: SSID (32-octet string) 610 * @ssid_len: Length of ssid in octets 611 * Returns: Pointer to a printable string 612 * 613 * This function can be used to convert SSIDs into printable form. In most 614 * cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard 615 * does not limit the used character set, so anything could be used in an SSID. 616 * 617 * This function uses a static buffer, so only one call can be used at the 618 * time, i.e., this is not re-entrant and the returned buffer must be used 619 * before calling this again. 620 */ 621 const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len) 622 { 623 static char ssid_txt[SSID_MAX_LEN * 4 + 1]; 624 625 if (ssid == NULL) { 626 ssid_txt[0] = '\0'; 627 return ssid_txt; 628 } 629 630 printf_encode(ssid_txt, sizeof(ssid_txt), ssid, ssid_len); 631 return ssid_txt; 632 } 633 634 635 void * __hide_aliasing_typecast(void *foo) 636 { 637 return foo; 638 } 639 640 641 char * wpa_config_parse_string(const char *value, size_t *len) 642 { 643 if (*value == '"') { 644 const char *pos; 645 char *str; 646 value++; 647 pos = os_strrchr(value, '"'); 648 if (pos == NULL || pos[1] != '\0') 649 return NULL; 650 *len = pos - value; 651 str = dup_binstr(value, *len); 652 if (str == NULL) 653 return NULL; 654 return str; 655 } else if (*value == 'P' && value[1] == '"') { 656 const char *pos; 657 char *tstr, *str; 658 size_t tlen; 659 value += 2; 660 pos = os_strrchr(value, '"'); 661 if (pos == NULL || pos[1] != '\0') 662 return NULL; 663 tlen = pos - value; 664 tstr = dup_binstr(value, tlen); 665 if (tstr == NULL) 666 return NULL; 667 668 str = os_malloc(tlen + 1); 669 if (str == NULL) { 670 os_free(tstr); 671 return NULL; 672 } 673 674 *len = printf_decode((u8 *) str, tlen + 1, tstr); 675 os_free(tstr); 676 677 return str; 678 } else { 679 u8 *str; 680 size_t tlen, hlen = os_strlen(value); 681 if (hlen & 1) 682 return NULL; 683 tlen = hlen / 2; 684 str = os_malloc(tlen + 1); 685 if (str == NULL) 686 return NULL; 687 if (hexstr2bin(value, str, tlen)) { 688 os_free(str); 689 return NULL; 690 } 691 str[tlen] = '\0'; 692 *len = tlen; 693 return (char *) str; 694 } 695 } 696 697 698 int is_hex(const u8 *data, size_t len) 699 { 700 size_t i; 701 702 for (i = 0; i < len; i++) { 703 if (data[i] < 32 || data[i] >= 127) 704 return 1; 705 } 706 return 0; 707 } 708 709 710 int has_ctrl_char(const u8 *data, size_t len) 711 { 712 size_t i; 713 714 for (i = 0; i < len; i++) { 715 if (data[i] < 32 || data[i] == 127) 716 return 1; 717 } 718 return 0; 719 } 720 721 722 int has_newline(const char *str) 723 { 724 while (*str) { 725 if (*str == '\n' || *str == '\r') 726 return 1; 727 str++; 728 } 729 return 0; 730 } 731 732 733 size_t merge_byte_arrays(u8 *res, size_t res_len, 734 const u8 *src1, size_t src1_len, 735 const u8 *src2, size_t src2_len) 736 { 737 size_t len = 0; 738 739 os_memset(res, 0, res_len); 740 741 if (src1) { 742 if (src1_len >= res_len) { 743 os_memcpy(res, src1, res_len); 744 return res_len; 745 } 746 747 os_memcpy(res, src1, src1_len); 748 len += src1_len; 749 } 750 751 if (src2) { 752 if (len + src2_len >= res_len) { 753 os_memcpy(res + len, src2, res_len - len); 754 return res_len; 755 } 756 757 os_memcpy(res + len, src2, src2_len); 758 len += src2_len; 759 } 760 761 return len; 762 } 763 764 765 char * dup_binstr(const void *src, size_t len) 766 { 767 char *res; 768 769 if (src == NULL) 770 return NULL; 771 res = os_malloc(len + 1); 772 if (res == NULL) 773 return NULL; 774 os_memcpy(res, src, len); 775 res[len] = '\0'; 776 777 return res; 778 } 779 780 781 int freq_range_list_parse(struct wpa_freq_range_list *res, const char *value) 782 { 783 struct wpa_freq_range *freq = NULL, *n; 784 unsigned int count = 0; 785 const char *pos, *pos2, *pos3; 786 787 /* 788 * Comma separated list of frequency ranges. 789 * For example: 2412-2432,2462,5000-6000 790 */ 791 pos = value; 792 while (pos && pos[0]) { 793 n = os_realloc_array(freq, count + 1, 794 sizeof(struct wpa_freq_range)); 795 if (n == NULL) { 796 os_free(freq); 797 return -1; 798 } 799 freq = n; 800 freq[count].min = atoi(pos); 801 pos2 = os_strchr(pos, '-'); 802 pos3 = os_strchr(pos, ','); 803 if (pos2 && (!pos3 || pos2 < pos3)) { 804 pos2++; 805 freq[count].max = atoi(pos2); 806 } else 807 freq[count].max = freq[count].min; 808 pos = pos3; 809 if (pos) 810 pos++; 811 count++; 812 } 813 814 os_free(res->range); 815 res->range = freq; 816 res->num = count; 817 818 return 0; 819 } 820 821 822 int freq_range_list_includes(const struct wpa_freq_range_list *list, 823 unsigned int freq) 824 { 825 unsigned int i; 826 827 if (list == NULL) 828 return 0; 829 830 for (i = 0; i < list->num; i++) { 831 if (freq >= list->range[i].min && freq <= list->range[i].max) 832 return 1; 833 } 834 835 return 0; 836 } 837 838 839 char * freq_range_list_str(const struct wpa_freq_range_list *list) 840 { 841 char *buf, *pos, *end; 842 size_t maxlen; 843 unsigned int i; 844 int res; 845 846 if (list->num == 0) 847 return NULL; 848 849 maxlen = list->num * 30; 850 buf = os_malloc(maxlen); 851 if (buf == NULL) 852 return NULL; 853 pos = buf; 854 end = buf + maxlen; 855 856 for (i = 0; i < list->num; i++) { 857 struct wpa_freq_range *range = &list->range[i]; 858 859 if (range->min == range->max) 860 res = os_snprintf(pos, end - pos, "%s%u", 861 i == 0 ? "" : ",", range->min); 862 else 863 res = os_snprintf(pos, end - pos, "%s%u-%u", 864 i == 0 ? "" : ",", 865 range->min, range->max); 866 if (os_snprintf_error(end - pos, res)) { 867 os_free(buf); 868 return NULL; 869 } 870 pos += res; 871 } 872 873 return buf; 874 } 875 876 877 int int_array_len(const int *a) 878 { 879 int i; 880 for (i = 0; a && a[i]; i++) 881 ; 882 return i; 883 } 884 885 886 void int_array_concat(int **res, const int *a) 887 { 888 int reslen, alen, i; 889 int *n; 890 891 reslen = int_array_len(*res); 892 alen = int_array_len(a); 893 894 n = os_realloc_array(*res, reslen + alen + 1, sizeof(int)); 895 if (n == NULL) { 896 os_free(*res); 897 *res = NULL; 898 return; 899 } 900 for (i = 0; i <= alen; i++) 901 n[reslen + i] = a[i]; 902 *res = n; 903 } 904 905 906 static int freq_cmp(const void *a, const void *b) 907 { 908 int _a = *(int *) a; 909 int _b = *(int *) b; 910 911 if (_a == 0) 912 return 1; 913 if (_b == 0) 914 return -1; 915 return _a - _b; 916 } 917 918 919 void int_array_sort_unique(int *a) 920 { 921 int alen; 922 int i, j; 923 924 if (a == NULL) 925 return; 926 927 alen = int_array_len(a); 928 qsort(a, alen, sizeof(int), freq_cmp); 929 930 i = 0; 931 j = 1; 932 while (a[i] && a[j]) { 933 if (a[i] == a[j]) { 934 j++; 935 continue; 936 } 937 a[++i] = a[j++]; 938 } 939 if (a[i]) 940 i++; 941 a[i] = 0; 942 } 943 944 945 void int_array_add_unique(int **res, int a) 946 { 947 int reslen; 948 int *n; 949 950 for (reslen = 0; *res && (*res)[reslen]; reslen++) { 951 if ((*res)[reslen] == a) 952 return; /* already in the list */ 953 } 954 955 n = os_realloc_array(*res, reslen + 2, sizeof(int)); 956 if (n == NULL) { 957 os_free(*res); 958 *res = NULL; 959 return; 960 } 961 962 n[reslen] = a; 963 n[reslen + 1] = 0; 964 965 *res = n; 966 } 967 968 969 void str_clear_free(char *str) 970 { 971 if (str) { 972 size_t len = os_strlen(str); 973 forced_memzero(str, len); 974 os_free(str); 975 } 976 } 977 978 979 void bin_clear_free(void *bin, size_t len) 980 { 981 if (bin) { 982 forced_memzero(bin, len); 983 os_free(bin); 984 } 985 } 986 987 988 int random_mac_addr(u8 *addr) 989 { 990 if (os_get_random(addr, ETH_ALEN) < 0) 991 return -1; 992 addr[0] &= 0xfe; /* unicast */ 993 addr[0] |= 0x02; /* locally administered */ 994 return 0; 995 } 996 997 998 int random_mac_addr_keep_oui(u8 *addr) 999 { 1000 if (os_get_random(addr + 3, 3) < 0) 1001 return -1; 1002 addr[0] &= 0xfe; /* unicast */ 1003 addr[0] |= 0x02; /* locally administered */ 1004 return 0; 1005 } 1006 1007 1008 /** 1009 * cstr_token - Get next token from const char string 1010 * @str: a constant string to tokenize 1011 * @delim: a string of delimiters 1012 * @last: a pointer to a character following the returned token 1013 * It has to be set to NULL for the first call and passed for any 1014 * further call. 1015 * Returns: a pointer to token position in str or NULL 1016 * 1017 * This function is similar to str_token, but it can be used with both 1018 * char and const char strings. Differences: 1019 * - The str buffer remains unmodified 1020 * - The returned token is not a NULL terminated string, but a token 1021 * position in str buffer. If a return value is not NULL a size 1022 * of the returned token could be calculated as (last - token). 1023 */ 1024 const char * cstr_token(const char *str, const char *delim, const char **last) 1025 { 1026 const char *end, *token = str; 1027 1028 if (!str || !delim || !last) 1029 return NULL; 1030 1031 if (*last) 1032 token = *last; 1033 1034 while (*token && os_strchr(delim, *token)) 1035 token++; 1036 1037 if (!*token) 1038 return NULL; 1039 1040 end = token + 1; 1041 1042 while (*end && !os_strchr(delim, *end)) 1043 end++; 1044 1045 *last = end; 1046 return token; 1047 } 1048 1049 1050 /** 1051 * str_token - Get next token from a string 1052 * @buf: String to tokenize. Note that the string might be modified. 1053 * @delim: String of delimiters 1054 * @context: Pointer to save our context. Should be initialized with 1055 * NULL on the first call, and passed for any further call. 1056 * Returns: The next token, NULL if there are no more valid tokens. 1057 */ 1058 char * str_token(char *str, const char *delim, char **context) 1059 { 1060 char *token = (char *) cstr_token(str, delim, (const char **) context); 1061 1062 if (token && **context) 1063 *(*context)++ = '\0'; 1064 1065 return token; 1066 } 1067 1068 1069 size_t utf8_unescape(const char *inp, size_t in_size, 1070 char *outp, size_t out_size) 1071 { 1072 size_t res_size = 0; 1073 1074 if (!inp || !outp) 1075 return 0; 1076 1077 if (!in_size) 1078 in_size = os_strlen(inp); 1079 1080 /* Advance past leading single quote */ 1081 if (*inp == '\'' && in_size) { 1082 inp++; 1083 in_size--; 1084 } 1085 1086 while (in_size) { 1087 in_size--; 1088 if (res_size >= out_size) 1089 return 0; 1090 1091 switch (*inp) { 1092 case '\'': 1093 /* Terminate on bare single quote */ 1094 *outp = '\0'; 1095 return res_size; 1096 1097 case '\\': 1098 if (!in_size) 1099 return 0; 1100 in_size--; 1101 inp++; 1102 /* fall through */ 1103 1104 default: 1105 *outp++ = *inp++; 1106 res_size++; 1107 } 1108 } 1109 1110 /* NUL terminate if space allows */ 1111 if (res_size < out_size) 1112 *outp = '\0'; 1113 1114 return res_size; 1115 } 1116 1117 1118 size_t utf8_escape(const char *inp, size_t in_size, 1119 char *outp, size_t out_size) 1120 { 1121 size_t res_size = 0; 1122 1123 if (!inp || !outp) 1124 return 0; 1125 1126 /* inp may or may not be NUL terminated, but must be if 0 size 1127 * is specified */ 1128 if (!in_size) 1129 in_size = os_strlen(inp); 1130 1131 while (in_size) { 1132 in_size--; 1133 if (res_size++ >= out_size) 1134 return 0; 1135 1136 switch (*inp) { 1137 case '\\': 1138 case '\'': 1139 if (res_size++ >= out_size) 1140 return 0; 1141 *outp++ = '\\'; 1142 /* fall through */ 1143 1144 default: 1145 *outp++ = *inp++; 1146 break; 1147 } 1148 } 1149 1150 /* NUL terminate if space allows */ 1151 if (res_size < out_size) 1152 *outp = '\0'; 1153 1154 return res_size; 1155 } 1156 1157 1158 int is_ctrl_char(char c) 1159 { 1160 return c > 0 && c < 32; 1161 } 1162 1163 1164 /** 1165 * ssid_parse - Parse a string that contains SSID in hex or text format 1166 * @buf: Input NULL terminated string that contains the SSID 1167 * @ssid: Output SSID 1168 * Returns: 0 on success, -1 otherwise 1169 * 1170 * The SSID has to be enclosed in double quotes for the text format or space 1171 * or NULL terminated string of hex digits for the hex format. buf can include 1172 * additional arguments after the SSID. 1173 */ 1174 int ssid_parse(const char *buf, struct wpa_ssid_value *ssid) 1175 { 1176 char *tmp, *res, *end; 1177 size_t len; 1178 1179 ssid->ssid_len = 0; 1180 1181 tmp = os_strdup(buf); 1182 if (!tmp) 1183 return -1; 1184 1185 if (*tmp != '"') { 1186 end = os_strchr(tmp, ' '); 1187 if (end) 1188 *end = '\0'; 1189 } else { 1190 end = os_strchr(tmp + 1, '"'); 1191 if (!end) { 1192 os_free(tmp); 1193 return -1; 1194 } 1195 1196 end[1] = '\0'; 1197 } 1198 1199 res = wpa_config_parse_string(tmp, &len); 1200 if (res && len <= SSID_MAX_LEN) { 1201 ssid->ssid_len = len; 1202 os_memcpy(ssid->ssid, res, len); 1203 } 1204 1205 os_free(tmp); 1206 os_free(res); 1207 1208 return ssid->ssid_len ? 0 : -1; 1209 } 1210 1211 1212 int str_starts(const char *str, const char *start) 1213 { 1214 return os_strncmp(str, start, os_strlen(start)) == 0; 1215 } 1216 1217 1218 /** 1219 * rssi_to_rcpi - Convert RSSI to RCPI 1220 * @rssi: RSSI to convert 1221 * Returns: RCPI corresponding to the given RSSI value, or 255 if not available. 1222 * 1223 * It's possible to estimate RCPI based on RSSI in dBm. This calculation will 1224 * not reflect the correct value for high rates, but it's good enough for Action 1225 * frames which are transmitted with up to 24 Mbps rates. 1226 */ 1227 u8 rssi_to_rcpi(int rssi) 1228 { 1229 if (!rssi) 1230 return 255; /* not available */ 1231 if (rssi < -110) 1232 return 0; 1233 if (rssi > 0) 1234 return 220; 1235 return (rssi + 110) * 2; 1236 } 1237 1238 1239 char * get_param(const char *cmd, const char *param) 1240 { 1241 const char *pos, *end; 1242 char *val; 1243 size_t len; 1244 1245 pos = os_strstr(cmd, param); 1246 if (!pos) 1247 return NULL; 1248 1249 pos += os_strlen(param); 1250 end = os_strchr(pos, ' '); 1251 if (end) 1252 len = end - pos; 1253 else 1254 len = os_strlen(pos); 1255 val = os_malloc(len + 1); 1256 if (!val) 1257 return NULL; 1258 os_memcpy(val, pos, len); 1259 val[len] = '\0'; 1260 return val; 1261 } 1262 1263 1264 /* Try to prevent most compilers from optimizing out clearing of memory that 1265 * becomes unaccessible after this function is called. This is mostly the case 1266 * for clearing local stack variables at the end of a function. This is not 1267 * exactly perfect, i.e., someone could come up with a compiler that figures out 1268 * the pointer is pointing to memset and then end up optimizing the call out, so 1269 * try go a bit further by storing the first octet (now zero) to make this even 1270 * a bit more difficult to optimize out. Once memset_s() is available, that 1271 * could be used here instead. */ 1272 static void * (* const volatile memset_func)(void *, int, size_t) = memset; 1273 static u8 forced_memzero_val; 1274 1275 void forced_memzero(void *ptr, size_t len) 1276 { 1277 memset_func(ptr, 0, len); 1278 if (len) 1279 forced_memzero_val = ((u8 *) ptr)[0]; 1280 } 1281