1 /* 2 * wpa_supplicant/hostapd / common helper functions, etc. 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/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 wpa_get_ntp_timestamp(u8 *buf) 234 { 235 struct os_time now; 236 u32 sec, usec; 237 be32 tmp; 238 239 /* 64-bit NTP timestamp (time from 1900-01-01 00:00:00) */ 240 os_get_time(&now); 241 sec = now.sec + 2208988800U; /* Epoch to 1900 */ 242 /* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */ 243 usec = now.usec; 244 usec = 4295 * usec - (usec >> 5) - (usec >> 9); 245 tmp = host_to_be32(sec); 246 os_memcpy(buf, (u8 *) &tmp, 4); 247 tmp = host_to_be32(usec); 248 os_memcpy(buf + 4, (u8 *) &tmp, 4); 249 } 250 251 /** 252 * wpa_scnprintf - Simpler-to-use snprintf function 253 * @buf: Output buffer 254 * @size: Buffer size 255 * @fmt: format 256 * 257 * Simpler snprintf version that doesn't require further error checks - the 258 * return value only indicates how many bytes were actually written, excluding 259 * the NULL byte (i.e., 0 on error, size-1 if buffer is not big enough). 260 */ 261 int wpa_scnprintf(char *buf, size_t size, const char *fmt, ...) 262 { 263 va_list ap; 264 int ret; 265 266 if (!size) 267 return 0; 268 269 va_start(ap, fmt); 270 ret = vsnprintf(buf, size, fmt, ap); 271 va_end(ap); 272 273 if (ret < 0) 274 return 0; 275 if ((size_t) ret >= size) 276 return size - 1; 277 278 return ret; 279 } 280 281 282 int wpa_snprintf_hex_sep(char *buf, size_t buf_size, const u8 *data, size_t len, 283 char sep) 284 { 285 size_t i; 286 char *pos = buf, *end = buf + buf_size; 287 int ret; 288 289 if (buf_size == 0) 290 return 0; 291 292 for (i = 0; i < len; i++) { 293 ret = os_snprintf(pos, end - pos, "%02x%c", 294 data[i], sep); 295 if (os_snprintf_error(end - pos, ret)) { 296 end[-1] = '\0'; 297 return pos - buf; 298 } 299 pos += ret; 300 } 301 pos[-1] = '\0'; 302 return pos - buf; 303 } 304 305 306 static inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, 307 size_t len, int uppercase) 308 { 309 size_t i; 310 char *pos = buf, *end = buf + buf_size; 311 int ret; 312 if (buf_size == 0) 313 return 0; 314 for (i = 0; i < len; i++) { 315 ret = os_snprintf(pos, end - pos, uppercase ? "%02X" : "%02x", 316 data[i]); 317 if (os_snprintf_error(end - pos, ret)) { 318 end[-1] = '\0'; 319 return pos - buf; 320 } 321 pos += ret; 322 } 323 end[-1] = '\0'; 324 return pos - buf; 325 } 326 327 /** 328 * wpa_snprintf_hex - Print data as a hex string into a buffer 329 * @buf: Memory area to use as the output buffer 330 * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1) 331 * @data: Data to be printed 332 * @len: Length of data in bytes 333 * Returns: Number of bytes written 334 */ 335 int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len) 336 { 337 return _wpa_snprintf_hex(buf, buf_size, data, len, 0); 338 } 339 340 341 /** 342 * wpa_snprintf_hex_uppercase - Print data as a upper case hex string into buf 343 * @buf: Memory area to use as the output buffer 344 * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1) 345 * @data: Data to be printed 346 * @len: Length of data in bytes 347 * Returns: Number of bytes written 348 */ 349 int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data, 350 size_t len) 351 { 352 return _wpa_snprintf_hex(buf, buf_size, data, len, 1); 353 } 354 355 356 #ifdef CONFIG_ANSI_C_EXTRA 357 358 #ifdef _WIN32_WCE 359 void perror(const char *s) 360 { 361 wpa_printf(MSG_ERROR, "%s: GetLastError: %d", 362 s, (int) GetLastError()); 363 } 364 #endif /* _WIN32_WCE */ 365 366 367 int optind = 1; 368 int optopt; 369 char *optarg; 370 371 int getopt(int argc, char *const argv[], const char *optstring) 372 { 373 static int optchr = 1; 374 char *cp; 375 376 if (optchr == 1) { 377 if (optind >= argc) { 378 /* all arguments processed */ 379 return EOF; 380 } 381 382 if (argv[optind][0] != '-' || argv[optind][1] == '\0') { 383 /* no option characters */ 384 return EOF; 385 } 386 } 387 388 if (os_strcmp(argv[optind], "--") == 0) { 389 /* no more options */ 390 optind++; 391 return EOF; 392 } 393 394 optopt = argv[optind][optchr]; 395 cp = os_strchr(optstring, optopt); 396 if (cp == NULL || optopt == ':') { 397 if (argv[optind][++optchr] == '\0') { 398 optchr = 1; 399 optind++; 400 } 401 return '?'; 402 } 403 404 if (cp[1] == ':') { 405 /* Argument required */ 406 optchr = 1; 407 if (argv[optind][optchr + 1]) { 408 /* No space between option and argument */ 409 optarg = &argv[optind++][optchr + 1]; 410 } else if (++optind >= argc) { 411 /* option requires an argument */ 412 return '?'; 413 } else { 414 /* Argument in the next argv */ 415 optarg = argv[optind++]; 416 } 417 } else { 418 /* No argument */ 419 if (argv[optind][++optchr] == '\0') { 420 optchr = 1; 421 optind++; 422 } 423 optarg = NULL; 424 } 425 return *cp; 426 } 427 #endif /* CONFIG_ANSI_C_EXTRA */ 428 429 430 #ifdef CONFIG_NATIVE_WINDOWS 431 /** 432 * wpa_unicode2ascii_inplace - Convert unicode string into ASCII 433 * @str: Pointer to string to convert 434 * 435 * This function converts a unicode string to ASCII using the same 436 * buffer for output. If UNICODE is not set, the buffer is not 437 * modified. 438 */ 439 void wpa_unicode2ascii_inplace(TCHAR *str) 440 { 441 #ifdef UNICODE 442 char *dst = (char *) str; 443 while (*str) 444 *dst++ = (char) *str++; 445 *dst = '\0'; 446 #endif /* UNICODE */ 447 } 448 449 450 TCHAR * wpa_strdup_tchar(const char *str) 451 { 452 #ifdef UNICODE 453 TCHAR *buf; 454 buf = os_malloc((strlen(str) + 1) * sizeof(TCHAR)); 455 if (buf == NULL) 456 return NULL; 457 wsprintf(buf, L"%S", str); 458 return buf; 459 #else /* UNICODE */ 460 return os_strdup(str); 461 #endif /* UNICODE */ 462 } 463 #endif /* CONFIG_NATIVE_WINDOWS */ 464 465 466 void printf_encode(char *txt, size_t maxlen, const u8 *data, size_t len) 467 { 468 char *end = txt + maxlen; 469 size_t i; 470 471 for (i = 0; i < len; i++) { 472 if (txt + 4 >= end) 473 break; 474 475 switch (data[i]) { 476 case '\"': 477 *txt++ = '\\'; 478 *txt++ = '\"'; 479 break; 480 case '\\': 481 *txt++ = '\\'; 482 *txt++ = '\\'; 483 break; 484 case '\033': 485 *txt++ = '\\'; 486 *txt++ = 'e'; 487 break; 488 case '\n': 489 *txt++ = '\\'; 490 *txt++ = 'n'; 491 break; 492 case '\r': 493 *txt++ = '\\'; 494 *txt++ = 'r'; 495 break; 496 case '\t': 497 *txt++ = '\\'; 498 *txt++ = 't'; 499 break; 500 default: 501 if (data[i] >= 32 && data[i] <= 126) { 502 *txt++ = data[i]; 503 } else { 504 txt += os_snprintf(txt, end - txt, "\\x%02x", 505 data[i]); 506 } 507 break; 508 } 509 } 510 511 *txt = '\0'; 512 } 513 514 515 size_t printf_decode(u8 *buf, size_t maxlen, const char *str) 516 { 517 const char *pos = str; 518 size_t len = 0; 519 int val; 520 521 while (*pos) { 522 if (len + 1 >= maxlen) 523 break; 524 switch (*pos) { 525 case '\\': 526 pos++; 527 switch (*pos) { 528 case '\\': 529 buf[len++] = '\\'; 530 pos++; 531 break; 532 case '"': 533 buf[len++] = '"'; 534 pos++; 535 break; 536 case 'n': 537 buf[len++] = '\n'; 538 pos++; 539 break; 540 case 'r': 541 buf[len++] = '\r'; 542 pos++; 543 break; 544 case 't': 545 buf[len++] = '\t'; 546 pos++; 547 break; 548 case 'e': 549 buf[len++] = '\033'; 550 pos++; 551 break; 552 case 'x': 553 pos++; 554 val = hex2byte(pos); 555 if (val < 0) { 556 val = hex2num(*pos); 557 if (val < 0) 558 break; 559 buf[len++] = val; 560 pos++; 561 } else { 562 buf[len++] = val; 563 pos += 2; 564 } 565 break; 566 case '0': 567 case '1': 568 case '2': 569 case '3': 570 case '4': 571 case '5': 572 case '6': 573 case '7': 574 val = *pos++ - '0'; 575 if (*pos >= '0' && *pos <= '7') 576 val = val * 8 + (*pos++ - '0'); 577 if (*pos >= '0' && *pos <= '7') 578 val = val * 8 + (*pos++ - '0'); 579 buf[len++] = val; 580 break; 581 default: 582 break; 583 } 584 break; 585 default: 586 buf[len++] = *pos++; 587 break; 588 } 589 } 590 if (maxlen > len) 591 buf[len] = '\0'; 592 593 return len; 594 } 595 596 597 /** 598 * wpa_ssid_txt - Convert SSID to a printable string 599 * @ssid: SSID (32-octet string) 600 * @ssid_len: Length of ssid in octets 601 * Returns: Pointer to a printable string 602 * 603 * This function can be used to convert SSIDs into printable form. In most 604 * cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard 605 * does not limit the used character set, so anything could be used in an SSID. 606 * 607 * This function uses a static buffer, so only one call can be used at the 608 * time, i.e., this is not re-entrant and the returned buffer must be used 609 * before calling this again. 610 */ 611 const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len) 612 { 613 static char ssid_txt[SSID_MAX_LEN * 4 + 1]; 614 615 if (ssid == NULL) { 616 ssid_txt[0] = '\0'; 617 return ssid_txt; 618 } 619 620 printf_encode(ssid_txt, sizeof(ssid_txt), ssid, ssid_len); 621 return ssid_txt; 622 } 623 624 625 void * __hide_aliasing_typecast(void *foo) 626 { 627 return foo; 628 } 629 630 631 char * wpa_config_parse_string(const char *value, size_t *len) 632 { 633 if (*value == '"') { 634 const char *pos; 635 char *str; 636 value++; 637 pos = os_strrchr(value, '"'); 638 if (pos == NULL || pos[1] != '\0') 639 return NULL; 640 *len = pos - value; 641 str = dup_binstr(value, *len); 642 if (str == NULL) 643 return NULL; 644 return str; 645 } else if (*value == 'P' && value[1] == '"') { 646 const char *pos; 647 char *tstr, *str; 648 size_t tlen; 649 value += 2; 650 pos = os_strrchr(value, '"'); 651 if (pos == NULL || pos[1] != '\0') 652 return NULL; 653 tlen = pos - value; 654 tstr = dup_binstr(value, tlen); 655 if (tstr == NULL) 656 return NULL; 657 658 str = os_malloc(tlen + 1); 659 if (str == NULL) { 660 os_free(tstr); 661 return NULL; 662 } 663 664 *len = printf_decode((u8 *) str, tlen + 1, tstr); 665 os_free(tstr); 666 667 return str; 668 } else { 669 u8 *str; 670 size_t tlen, hlen = os_strlen(value); 671 if (hlen & 1) 672 return NULL; 673 tlen = hlen / 2; 674 str = os_malloc(tlen + 1); 675 if (str == NULL) 676 return NULL; 677 if (hexstr2bin(value, str, tlen)) { 678 os_free(str); 679 return NULL; 680 } 681 str[tlen] = '\0'; 682 *len = tlen; 683 return (char *) str; 684 } 685 } 686 687 688 int is_hex(const u8 *data, size_t len) 689 { 690 size_t i; 691 692 for (i = 0; i < len; i++) { 693 if (data[i] < 32 || data[i] >= 127) 694 return 1; 695 } 696 return 0; 697 } 698 699 700 int has_ctrl_char(const u8 *data, size_t len) 701 { 702 size_t i; 703 704 for (i = 0; i < len; i++) { 705 if (data[i] < 32 || data[i] == 127) 706 return 1; 707 } 708 return 0; 709 } 710 711 712 int has_newline(const char *str) 713 { 714 while (*str) { 715 if (*str == '\n' || *str == '\r') 716 return 1; 717 str++; 718 } 719 return 0; 720 } 721 722 723 size_t merge_byte_arrays(u8 *res, size_t res_len, 724 const u8 *src1, size_t src1_len, 725 const u8 *src2, size_t src2_len) 726 { 727 size_t len = 0; 728 729 os_memset(res, 0, res_len); 730 731 if (src1) { 732 if (src1_len >= res_len) { 733 os_memcpy(res, src1, res_len); 734 return res_len; 735 } 736 737 os_memcpy(res, src1, src1_len); 738 len += src1_len; 739 } 740 741 if (src2) { 742 if (len + src2_len >= res_len) { 743 os_memcpy(res + len, src2, res_len - len); 744 return res_len; 745 } 746 747 os_memcpy(res + len, src2, src2_len); 748 len += src2_len; 749 } 750 751 return len; 752 } 753 754 755 char * dup_binstr(const void *src, size_t len) 756 { 757 char *res; 758 759 if (src == NULL) 760 return NULL; 761 res = os_malloc(len + 1); 762 if (res == NULL) 763 return NULL; 764 os_memcpy(res, src, len); 765 res[len] = '\0'; 766 767 return res; 768 } 769 770 771 int freq_range_list_parse(struct wpa_freq_range_list *res, const char *value) 772 { 773 struct wpa_freq_range *freq = NULL, *n; 774 unsigned int count = 0; 775 const char *pos, *pos2, *pos3; 776 777 /* 778 * Comma separated list of frequency ranges. 779 * For example: 2412-2432,2462,5000-6000 780 */ 781 pos = value; 782 while (pos && pos[0]) { 783 n = os_realloc_array(freq, count + 1, 784 sizeof(struct wpa_freq_range)); 785 if (n == NULL) { 786 os_free(freq); 787 return -1; 788 } 789 freq = n; 790 freq[count].min = atoi(pos); 791 pos2 = os_strchr(pos, '-'); 792 pos3 = os_strchr(pos, ','); 793 if (pos2 && (!pos3 || pos2 < pos3)) { 794 pos2++; 795 freq[count].max = atoi(pos2); 796 } else 797 freq[count].max = freq[count].min; 798 pos = pos3; 799 if (pos) 800 pos++; 801 count++; 802 } 803 804 os_free(res->range); 805 res->range = freq; 806 res->num = count; 807 808 return 0; 809 } 810 811 812 int freq_range_list_includes(const struct wpa_freq_range_list *list, 813 unsigned int freq) 814 { 815 unsigned int i; 816 817 if (list == NULL) 818 return 0; 819 820 for (i = 0; i < list->num; i++) { 821 if (freq >= list->range[i].min && freq <= list->range[i].max) 822 return 1; 823 } 824 825 return 0; 826 } 827 828 829 char * freq_range_list_str(const struct wpa_freq_range_list *list) 830 { 831 char *buf, *pos, *end; 832 size_t maxlen; 833 unsigned int i; 834 int res; 835 836 if (list->num == 0) 837 return NULL; 838 839 maxlen = list->num * 30; 840 buf = os_malloc(maxlen); 841 if (buf == NULL) 842 return NULL; 843 pos = buf; 844 end = buf + maxlen; 845 846 for (i = 0; i < list->num; i++) { 847 struct wpa_freq_range *range = &list->range[i]; 848 849 if (range->min == range->max) 850 res = os_snprintf(pos, end - pos, "%s%u", 851 i == 0 ? "" : ",", range->min); 852 else 853 res = os_snprintf(pos, end - pos, "%s%u-%u", 854 i == 0 ? "" : ",", 855 range->min, range->max); 856 if (os_snprintf_error(end - pos, res)) { 857 os_free(buf); 858 return NULL; 859 } 860 pos += res; 861 } 862 863 return buf; 864 } 865 866 867 int int_array_len(const int *a) 868 { 869 int i; 870 for (i = 0; a && a[i]; i++) 871 ; 872 return i; 873 } 874 875 876 void int_array_concat(int **res, const int *a) 877 { 878 int reslen, alen, i; 879 int *n; 880 881 reslen = int_array_len(*res); 882 alen = int_array_len(a); 883 884 n = os_realloc_array(*res, reslen + alen + 1, sizeof(int)); 885 if (n == NULL) { 886 os_free(*res); 887 *res = NULL; 888 return; 889 } 890 for (i = 0; i <= alen; i++) 891 n[reslen + i] = a[i]; 892 *res = n; 893 } 894 895 896 static int freq_cmp(const void *a, const void *b) 897 { 898 int _a = *(int *) a; 899 int _b = *(int *) b; 900 901 if (_a == 0) 902 return 1; 903 if (_b == 0) 904 return -1; 905 return _a - _b; 906 } 907 908 909 void int_array_sort_unique(int *a) 910 { 911 int alen; 912 int i, j; 913 914 if (a == NULL) 915 return; 916 917 alen = int_array_len(a); 918 qsort(a, alen, sizeof(int), freq_cmp); 919 920 i = 0; 921 j = 1; 922 while (a[i] && a[j]) { 923 if (a[i] == a[j]) { 924 j++; 925 continue; 926 } 927 a[++i] = a[j++]; 928 } 929 if (a[i]) 930 i++; 931 a[i] = 0; 932 } 933 934 935 void int_array_add_unique(int **res, int a) 936 { 937 int reslen; 938 int *n; 939 940 for (reslen = 0; *res && (*res)[reslen]; reslen++) { 941 if ((*res)[reslen] == a) 942 return; /* already in the list */ 943 } 944 945 n = os_realloc_array(*res, reslen + 2, sizeof(int)); 946 if (n == NULL) { 947 os_free(*res); 948 *res = NULL; 949 return; 950 } 951 952 n[reslen] = a; 953 n[reslen + 1] = 0; 954 955 *res = n; 956 } 957 958 959 void str_clear_free(char *str) 960 { 961 if (str) { 962 size_t len = os_strlen(str); 963 os_memset(str, 0, len); 964 os_free(str); 965 } 966 } 967 968 969 void bin_clear_free(void *bin, size_t len) 970 { 971 if (bin) { 972 os_memset(bin, 0, len); 973 os_free(bin); 974 } 975 } 976 977 978 int random_mac_addr(u8 *addr) 979 { 980 if (os_get_random(addr, ETH_ALEN) < 0) 981 return -1; 982 addr[0] &= 0xfe; /* unicast */ 983 addr[0] |= 0x02; /* locally administered */ 984 return 0; 985 } 986 987 988 int random_mac_addr_keep_oui(u8 *addr) 989 { 990 if (os_get_random(addr + 3, 3) < 0) 991 return -1; 992 addr[0] &= 0xfe; /* unicast */ 993 addr[0] |= 0x02; /* locally administered */ 994 return 0; 995 } 996 997 998 /** 999 * cstr_token - Get next token from const char string 1000 * @str: a constant string to tokenize 1001 * @delim: a string of delimiters 1002 * @last: a pointer to a character following the returned token 1003 * It has to be set to NULL for the first call and passed for any 1004 * further call. 1005 * Returns: a pointer to token position in str or NULL 1006 * 1007 * This function is similar to str_token, but it can be used with both 1008 * char and const char strings. Differences: 1009 * - The str buffer remains unmodified 1010 * - The returned token is not a NULL terminated string, but a token 1011 * position in str buffer. If a return value is not NULL a size 1012 * of the returned token could be calculated as (last - token). 1013 */ 1014 const char * cstr_token(const char *str, const char *delim, const char **last) 1015 { 1016 const char *end, *token = str; 1017 1018 if (!str || !delim || !last) 1019 return NULL; 1020 1021 if (*last) 1022 token = *last; 1023 1024 while (*token && os_strchr(delim, *token)) 1025 token++; 1026 1027 if (!*token) 1028 return NULL; 1029 1030 end = token + 1; 1031 1032 while (*end && !os_strchr(delim, *end)) 1033 end++; 1034 1035 *last = end; 1036 return token; 1037 } 1038 1039 1040 /** 1041 * str_token - Get next token from a string 1042 * @buf: String to tokenize. Note that the string might be modified. 1043 * @delim: String of delimiters 1044 * @context: Pointer to save our context. Should be initialized with 1045 * NULL on the first call, and passed for any further call. 1046 * Returns: The next token, NULL if there are no more valid tokens. 1047 */ 1048 char * str_token(char *str, const char *delim, char **context) 1049 { 1050 char *token = (char *) cstr_token(str, delim, (const char **) context); 1051 1052 if (token && **context) 1053 *(*context)++ = '\0'; 1054 1055 return token; 1056 } 1057 1058 1059 size_t utf8_unescape(const char *inp, size_t in_size, 1060 char *outp, size_t out_size) 1061 { 1062 size_t res_size = 0; 1063 1064 if (!inp || !outp) 1065 return 0; 1066 1067 if (!in_size) 1068 in_size = os_strlen(inp); 1069 1070 /* Advance past leading single quote */ 1071 if (*inp == '\'' && in_size) { 1072 inp++; 1073 in_size--; 1074 } 1075 1076 while (in_size--) { 1077 if (res_size >= out_size) 1078 return 0; 1079 1080 switch (*inp) { 1081 case '\'': 1082 /* Terminate on bare single quote */ 1083 *outp = '\0'; 1084 return res_size; 1085 1086 case '\\': 1087 if (!in_size--) 1088 return 0; 1089 inp++; 1090 /* fall through */ 1091 1092 default: 1093 *outp++ = *inp++; 1094 res_size++; 1095 } 1096 } 1097 1098 /* NUL terminate if space allows */ 1099 if (res_size < out_size) 1100 *outp = '\0'; 1101 1102 return res_size; 1103 } 1104 1105 1106 size_t utf8_escape(const char *inp, size_t in_size, 1107 char *outp, size_t out_size) 1108 { 1109 size_t res_size = 0; 1110 1111 if (!inp || !outp) 1112 return 0; 1113 1114 /* inp may or may not be NUL terminated, but must be if 0 size 1115 * is specified */ 1116 if (!in_size) 1117 in_size = os_strlen(inp); 1118 1119 while (in_size--) { 1120 if (res_size++ >= out_size) 1121 return 0; 1122 1123 switch (*inp) { 1124 case '\\': 1125 case '\'': 1126 if (res_size++ >= out_size) 1127 return 0; 1128 *outp++ = '\\'; 1129 /* fall through */ 1130 1131 default: 1132 *outp++ = *inp++; 1133 break; 1134 } 1135 } 1136 1137 /* NUL terminate if space allows */ 1138 if (res_size < out_size) 1139 *outp = '\0'; 1140 1141 return res_size; 1142 } 1143 1144 1145 int is_ctrl_char(char c) 1146 { 1147 return c > 0 && c < 32; 1148 } 1149 1150 1151 /** 1152 * ssid_parse - Parse a string that contains SSID in hex or text format 1153 * @buf: Input NULL terminated string that contains the SSID 1154 * @ssid: Output SSID 1155 * Returns: 0 on success, -1 otherwise 1156 * 1157 * The SSID has to be enclosed in double quotes for the text format or space 1158 * or NULL terminated string of hex digits for the hex format. buf can include 1159 * additional arguments after the SSID. 1160 */ 1161 int ssid_parse(const char *buf, struct wpa_ssid_value *ssid) 1162 { 1163 char *tmp, *res, *end; 1164 size_t len; 1165 1166 ssid->ssid_len = 0; 1167 1168 tmp = os_strdup(buf); 1169 if (!tmp) 1170 return -1; 1171 1172 if (*tmp != '"') { 1173 end = os_strchr(tmp, ' '); 1174 if (end) 1175 *end = '\0'; 1176 } else { 1177 end = os_strchr(tmp + 1, '"'); 1178 if (!end) { 1179 os_free(tmp); 1180 return -1; 1181 } 1182 1183 end[1] = '\0'; 1184 } 1185 1186 res = wpa_config_parse_string(tmp, &len); 1187 if (res && len <= SSID_MAX_LEN) { 1188 ssid->ssid_len = len; 1189 os_memcpy(ssid->ssid, res, len); 1190 } 1191 1192 os_free(tmp); 1193 os_free(res); 1194 1195 return ssid->ssid_len ? 0 : -1; 1196 } 1197 1198 1199 int str_starts(const char *str, const char *start) 1200 { 1201 return os_strncmp(str, start, os_strlen(start)) == 0; 1202 } 1203 1204 1205 /** 1206 * rssi_to_rcpi - Convert RSSI to RCPI 1207 * @rssi: RSSI to convert 1208 * Returns: RCPI corresponding to the given RSSI value, or 255 if not available. 1209 * 1210 * It's possible to estimate RCPI based on RSSI in dBm. This calculation will 1211 * not reflect the correct value for high rates, but it's good enough for Action 1212 * frames which are transmitted with up to 24 Mbps rates. 1213 */ 1214 u8 rssi_to_rcpi(int rssi) 1215 { 1216 if (!rssi) 1217 return 255; /* not available */ 1218 if (rssi < -110) 1219 return 0; 1220 if (rssi > 0) 1221 return 220; 1222 return (rssi + 110) * 2; 1223 } 1224