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 size_t merge_byte_arrays(u8 *res, size_t res_len, 701 const u8 *src1, size_t src1_len, 702 const u8 *src2, size_t src2_len) 703 { 704 size_t len = 0; 705 706 os_memset(res, 0, res_len); 707 708 if (src1) { 709 if (src1_len >= res_len) { 710 os_memcpy(res, src1, res_len); 711 return res_len; 712 } 713 714 os_memcpy(res, src1, src1_len); 715 len += src1_len; 716 } 717 718 if (src2) { 719 if (len + src2_len >= res_len) { 720 os_memcpy(res + len, src2, res_len - len); 721 return res_len; 722 } 723 724 os_memcpy(res + len, src2, src2_len); 725 len += src2_len; 726 } 727 728 return len; 729 } 730 731 732 char * dup_binstr(const void *src, size_t len) 733 { 734 char *res; 735 736 if (src == NULL) 737 return NULL; 738 res = os_malloc(len + 1); 739 if (res == NULL) 740 return NULL; 741 os_memcpy(res, src, len); 742 res[len] = '\0'; 743 744 return res; 745 } 746 747 748 int freq_range_list_parse(struct wpa_freq_range_list *res, const char *value) 749 { 750 struct wpa_freq_range *freq = NULL, *n; 751 unsigned int count = 0; 752 const char *pos, *pos2, *pos3; 753 754 /* 755 * Comma separated list of frequency ranges. 756 * For example: 2412-2432,2462,5000-6000 757 */ 758 pos = value; 759 while (pos && pos[0]) { 760 n = os_realloc_array(freq, count + 1, 761 sizeof(struct wpa_freq_range)); 762 if (n == NULL) { 763 os_free(freq); 764 return -1; 765 } 766 freq = n; 767 freq[count].min = atoi(pos); 768 pos2 = os_strchr(pos, '-'); 769 pos3 = os_strchr(pos, ','); 770 if (pos2 && (!pos3 || pos2 < pos3)) { 771 pos2++; 772 freq[count].max = atoi(pos2); 773 } else 774 freq[count].max = freq[count].min; 775 pos = pos3; 776 if (pos) 777 pos++; 778 count++; 779 } 780 781 os_free(res->range); 782 res->range = freq; 783 res->num = count; 784 785 return 0; 786 } 787 788 789 int freq_range_list_includes(const struct wpa_freq_range_list *list, 790 unsigned int freq) 791 { 792 unsigned int i; 793 794 if (list == NULL) 795 return 0; 796 797 for (i = 0; i < list->num; i++) { 798 if (freq >= list->range[i].min && freq <= list->range[i].max) 799 return 1; 800 } 801 802 return 0; 803 } 804 805 806 char * freq_range_list_str(const struct wpa_freq_range_list *list) 807 { 808 char *buf, *pos, *end; 809 size_t maxlen; 810 unsigned int i; 811 int res; 812 813 if (list->num == 0) 814 return NULL; 815 816 maxlen = list->num * 30; 817 buf = os_malloc(maxlen); 818 if (buf == NULL) 819 return NULL; 820 pos = buf; 821 end = buf + maxlen; 822 823 for (i = 0; i < list->num; i++) { 824 struct wpa_freq_range *range = &list->range[i]; 825 826 if (range->min == range->max) 827 res = os_snprintf(pos, end - pos, "%s%u", 828 i == 0 ? "" : ",", range->min); 829 else 830 res = os_snprintf(pos, end - pos, "%s%u-%u", 831 i == 0 ? "" : ",", 832 range->min, range->max); 833 if (os_snprintf_error(end - pos, res)) { 834 os_free(buf); 835 return NULL; 836 } 837 pos += res; 838 } 839 840 return buf; 841 } 842 843 844 int int_array_len(const int *a) 845 { 846 int i; 847 for (i = 0; a && a[i]; i++) 848 ; 849 return i; 850 } 851 852 853 void int_array_concat(int **res, const int *a) 854 { 855 int reslen, alen, i; 856 int *n; 857 858 reslen = int_array_len(*res); 859 alen = int_array_len(a); 860 861 n = os_realloc_array(*res, reslen + alen + 1, sizeof(int)); 862 if (n == NULL) { 863 os_free(*res); 864 *res = NULL; 865 return; 866 } 867 for (i = 0; i <= alen; i++) 868 n[reslen + i] = a[i]; 869 *res = n; 870 } 871 872 873 static int freq_cmp(const void *a, const void *b) 874 { 875 int _a = *(int *) a; 876 int _b = *(int *) b; 877 878 if (_a == 0) 879 return 1; 880 if (_b == 0) 881 return -1; 882 return _a - _b; 883 } 884 885 886 void int_array_sort_unique(int *a) 887 { 888 int alen; 889 int i, j; 890 891 if (a == NULL) 892 return; 893 894 alen = int_array_len(a); 895 qsort(a, alen, sizeof(int), freq_cmp); 896 897 i = 0; 898 j = 1; 899 while (a[i] && a[j]) { 900 if (a[i] == a[j]) { 901 j++; 902 continue; 903 } 904 a[++i] = a[j++]; 905 } 906 if (a[i]) 907 i++; 908 a[i] = 0; 909 } 910 911 912 void int_array_add_unique(int **res, int a) 913 { 914 int reslen; 915 int *n; 916 917 for (reslen = 0; *res && (*res)[reslen]; reslen++) { 918 if ((*res)[reslen] == a) 919 return; /* already in the list */ 920 } 921 922 n = os_realloc_array(*res, reslen + 2, sizeof(int)); 923 if (n == NULL) { 924 os_free(*res); 925 *res = NULL; 926 return; 927 } 928 929 n[reslen] = a; 930 n[reslen + 1] = 0; 931 932 *res = n; 933 } 934 935 936 void str_clear_free(char *str) 937 { 938 if (str) { 939 size_t len = os_strlen(str); 940 os_memset(str, 0, len); 941 os_free(str); 942 } 943 } 944 945 946 void bin_clear_free(void *bin, size_t len) 947 { 948 if (bin) { 949 os_memset(bin, 0, len); 950 os_free(bin); 951 } 952 } 953 954 955 int random_mac_addr(u8 *addr) 956 { 957 if (os_get_random(addr, ETH_ALEN) < 0) 958 return -1; 959 addr[0] &= 0xfe; /* unicast */ 960 addr[0] |= 0x02; /* locally administered */ 961 return 0; 962 } 963 964 965 int random_mac_addr_keep_oui(u8 *addr) 966 { 967 if (os_get_random(addr + 3, 3) < 0) 968 return -1; 969 addr[0] &= 0xfe; /* unicast */ 970 addr[0] |= 0x02; /* locally administered */ 971 return 0; 972 } 973 974 975 /** 976 * cstr_token - Get next token from const char string 977 * @str: a constant string to tokenize 978 * @delim: a string of delimiters 979 * @last: a pointer to a character following the returned token 980 * It has to be set to NULL for the first call and passed for any 981 * futher call. 982 * Returns: a pointer to token position in str or NULL 983 * 984 * This function is similar to str_token, but it can be used with both 985 * char and const char strings. Differences: 986 * - The str buffer remains unmodified 987 * - The returned token is not a NULL terminated string, but a token 988 * position in str buffer. If a return value is not NULL a size 989 * of the returned token could be calculated as (last - token). 990 */ 991 const char * cstr_token(const char *str, const char *delim, const char **last) 992 { 993 const char *end, *token = str; 994 995 if (!str || !delim || !last) 996 return NULL; 997 998 if (*last) 999 token = *last; 1000 1001 while (*token && os_strchr(delim, *token)) 1002 token++; 1003 1004 if (!*token) 1005 return NULL; 1006 1007 end = token + 1; 1008 1009 while (*end && !os_strchr(delim, *end)) 1010 end++; 1011 1012 *last = end; 1013 return token; 1014 } 1015 1016 1017 /** 1018 * str_token - Get next token from a string 1019 * @buf: String to tokenize. Note that the string might be modified. 1020 * @delim: String of delimiters 1021 * @context: Pointer to save our context. Should be initialized with 1022 * NULL on the first call, and passed for any further call. 1023 * Returns: The next token, NULL if there are no more valid tokens. 1024 */ 1025 char * str_token(char *str, const char *delim, char **context) 1026 { 1027 char *token = (char *) cstr_token(str, delim, (const char **) context); 1028 1029 if (token && **context) 1030 *(*context)++ = '\0'; 1031 1032 return token; 1033 } 1034 1035 1036 size_t utf8_unescape(const char *inp, size_t in_size, 1037 char *outp, size_t out_size) 1038 { 1039 size_t res_size = 0; 1040 1041 if (!inp || !outp) 1042 return 0; 1043 1044 if (!in_size) 1045 in_size = os_strlen(inp); 1046 1047 /* Advance past leading single quote */ 1048 if (*inp == '\'' && in_size) { 1049 inp++; 1050 in_size--; 1051 } 1052 1053 while (in_size--) { 1054 if (res_size >= out_size) 1055 return 0; 1056 1057 switch (*inp) { 1058 case '\'': 1059 /* Terminate on bare single quote */ 1060 *outp = '\0'; 1061 return res_size; 1062 1063 case '\\': 1064 if (!in_size--) 1065 return 0; 1066 inp++; 1067 /* fall through */ 1068 1069 default: 1070 *outp++ = *inp++; 1071 res_size++; 1072 } 1073 } 1074 1075 /* NUL terminate if space allows */ 1076 if (res_size < out_size) 1077 *outp = '\0'; 1078 1079 return res_size; 1080 } 1081 1082 1083 size_t utf8_escape(const char *inp, size_t in_size, 1084 char *outp, size_t out_size) 1085 { 1086 size_t res_size = 0; 1087 1088 if (!inp || !outp) 1089 return 0; 1090 1091 /* inp may or may not be NUL terminated, but must be if 0 size 1092 * is specified */ 1093 if (!in_size) 1094 in_size = os_strlen(inp); 1095 1096 while (in_size--) { 1097 if (res_size++ >= out_size) 1098 return 0; 1099 1100 switch (*inp) { 1101 case '\\': 1102 case '\'': 1103 if (res_size++ >= out_size) 1104 return 0; 1105 *outp++ = '\\'; 1106 /* fall through */ 1107 1108 default: 1109 *outp++ = *inp++; 1110 break; 1111 } 1112 } 1113 1114 /* NUL terminate if space allows */ 1115 if (res_size < out_size) 1116 *outp = '\0'; 1117 1118 return res_size; 1119 } 1120 1121 1122 int is_ctrl_char(char c) 1123 { 1124 return c > 0 && c < 32; 1125 } 1126