139beb93cSSam Leffler /* 239beb93cSSam Leffler * wpa_supplicant/hostapd / common helper functions, etc. 34bc52338SCy Schubert * Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi> 439beb93cSSam Leffler * 5f05cddf9SRui Paulo * This software may be distributed under the terms of the BSD license. 6f05cddf9SRui Paulo * See README for more details. 739beb93cSSam Leffler */ 839beb93cSSam Leffler 939beb93cSSam Leffler #include "includes.h" 10c1d255d3SCy Schubert #include <limits.h> 1139beb93cSSam Leffler 12325151a3SRui Paulo #include "common/ieee802_11_defs.h" 1339beb93cSSam Leffler #include "common.h" 1439beb93cSSam Leffler 1539beb93cSSam Leffler 16*a90b9d01SCy Schubert int hex2num(char c) 1739beb93cSSam Leffler { 1839beb93cSSam Leffler if (c >= '0' && c <= '9') 1939beb93cSSam Leffler return c - '0'; 2039beb93cSSam Leffler if (c >= 'a' && c <= 'f') 2139beb93cSSam Leffler return c - 'a' + 10; 2239beb93cSSam Leffler if (c >= 'A' && c <= 'F') 2339beb93cSSam Leffler return c - 'A' + 10; 2439beb93cSSam Leffler return -1; 2539beb93cSSam Leffler } 2639beb93cSSam Leffler 2739beb93cSSam Leffler 28f05cddf9SRui Paulo int hex2byte(const char *hex) 2939beb93cSSam Leffler { 3039beb93cSSam Leffler int a, b; 3139beb93cSSam Leffler a = hex2num(*hex++); 3239beb93cSSam Leffler if (a < 0) 3339beb93cSSam Leffler return -1; 3439beb93cSSam Leffler b = hex2num(*hex++); 3539beb93cSSam Leffler if (b < 0) 3639beb93cSSam Leffler return -1; 3739beb93cSSam Leffler return (a << 4) | b; 3839beb93cSSam Leffler } 3939beb93cSSam Leffler 4039beb93cSSam Leffler 415b9c547cSRui Paulo static const char * hwaddr_parse(const char *txt, u8 *addr) 425b9c547cSRui Paulo { 435b9c547cSRui Paulo size_t i; 445b9c547cSRui Paulo 455b9c547cSRui Paulo for (i = 0; i < ETH_ALEN; i++) { 465b9c547cSRui Paulo int a; 475b9c547cSRui Paulo 485b9c547cSRui Paulo a = hex2byte(txt); 495b9c547cSRui Paulo if (a < 0) 505b9c547cSRui Paulo return NULL; 515b9c547cSRui Paulo txt += 2; 525b9c547cSRui Paulo addr[i] = a; 535b9c547cSRui Paulo if (i < ETH_ALEN - 1 && *txt++ != ':') 545b9c547cSRui Paulo return NULL; 555b9c547cSRui Paulo } 565b9c547cSRui Paulo return txt; 575b9c547cSRui Paulo } 585b9c547cSRui Paulo 595b9c547cSRui Paulo 6039beb93cSSam Leffler /** 61e28a4053SRui Paulo * hwaddr_aton - Convert ASCII string to MAC address (colon-delimited format) 6239beb93cSSam Leffler * @txt: MAC address as a string (e.g., "00:11:22:33:44:55") 6339beb93cSSam Leffler * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) 6439beb93cSSam Leffler * Returns: 0 on success, -1 on failure (e.g., string not a MAC address) 6539beb93cSSam Leffler */ 6639beb93cSSam Leffler int hwaddr_aton(const char *txt, u8 *addr) 6739beb93cSSam Leffler { 685b9c547cSRui Paulo return hwaddr_parse(txt, addr) ? 0 : -1; 695b9c547cSRui Paulo } 7039beb93cSSam Leffler 7139beb93cSSam Leffler 725b9c547cSRui Paulo /** 735b9c547cSRui Paulo * hwaddr_masked_aton - Convert ASCII string with optional mask to MAC address (colon-delimited format) 745b9c547cSRui Paulo * @txt: MAC address with optional mask as a string (e.g., "00:11:22:33:44:55/ff:ff:ff:ff:00:00") 755b9c547cSRui Paulo * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) 765b9c547cSRui Paulo * @mask: Buffer for the MAC address mask (ETH_ALEN = 6 bytes) 775b9c547cSRui Paulo * @maskable: Flag to indicate whether a mask is allowed 785b9c547cSRui Paulo * Returns: 0 on success, -1 on failure (e.g., string not a MAC address) 795b9c547cSRui Paulo */ 805b9c547cSRui Paulo int hwaddr_masked_aton(const char *txt, u8 *addr, u8 *mask, u8 maskable) 815b9c547cSRui Paulo { 825b9c547cSRui Paulo const char *r; 835b9c547cSRui Paulo 845b9c547cSRui Paulo /* parse address part */ 855b9c547cSRui Paulo r = hwaddr_parse(txt, addr); 865b9c547cSRui Paulo if (!r) 8739beb93cSSam Leffler return -1; 885b9c547cSRui Paulo 895b9c547cSRui Paulo /* check for optional mask */ 90780fb4a2SCy Schubert if (*r == '\0' || isspace((unsigned char) *r)) { 915b9c547cSRui Paulo /* no mask specified, assume default */ 925b9c547cSRui Paulo os_memset(mask, 0xff, ETH_ALEN); 935b9c547cSRui Paulo } else if (maskable && *r == '/') { 945b9c547cSRui Paulo /* mask specified and allowed */ 955b9c547cSRui Paulo r = hwaddr_parse(r + 1, mask); 965b9c547cSRui Paulo /* parser error? */ 975b9c547cSRui Paulo if (!r) 9839beb93cSSam Leffler return -1; 995b9c547cSRui Paulo } else { 1005b9c547cSRui Paulo /* mask specified but not allowed or trailing garbage */ 10139beb93cSSam Leffler return -1; 10239beb93cSSam Leffler } 10339beb93cSSam Leffler 10439beb93cSSam Leffler return 0; 10539beb93cSSam Leffler } 10639beb93cSSam Leffler 1075b9c547cSRui Paulo 108f05cddf9SRui Paulo /** 109f05cddf9SRui Paulo * hwaddr_compact_aton - Convert ASCII string to MAC address (no colon delimitors format) 110f05cddf9SRui Paulo * @txt: MAC address as a string (e.g., "001122334455") 111f05cddf9SRui Paulo * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) 112f05cddf9SRui Paulo * Returns: 0 on success, -1 on failure (e.g., string not a MAC address) 113f05cddf9SRui Paulo */ 114f05cddf9SRui Paulo int hwaddr_compact_aton(const char *txt, u8 *addr) 115f05cddf9SRui Paulo { 116f05cddf9SRui Paulo int i; 117f05cddf9SRui Paulo 118f05cddf9SRui Paulo for (i = 0; i < 6; i++) { 119f05cddf9SRui Paulo int a, b; 120f05cddf9SRui Paulo 121f05cddf9SRui Paulo a = hex2num(*txt++); 122f05cddf9SRui Paulo if (a < 0) 123f05cddf9SRui Paulo return -1; 124f05cddf9SRui Paulo b = hex2num(*txt++); 125f05cddf9SRui Paulo if (b < 0) 126f05cddf9SRui Paulo return -1; 127f05cddf9SRui Paulo *addr++ = (a << 4) | b; 128f05cddf9SRui Paulo } 129f05cddf9SRui Paulo 130f05cddf9SRui Paulo return 0; 131f05cddf9SRui Paulo } 13239beb93cSSam Leffler 13339beb93cSSam Leffler /** 134e28a4053SRui Paulo * hwaddr_aton2 - Convert ASCII string to MAC address (in any known format) 135e28a4053SRui Paulo * @txt: MAC address as a string (e.g., 00:11:22:33:44:55 or 0011.2233.4455) 136e28a4053SRui Paulo * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) 137e28a4053SRui Paulo * Returns: Characters used (> 0) on success, -1 on failure 138e28a4053SRui Paulo */ 139e28a4053SRui Paulo int hwaddr_aton2(const char *txt, u8 *addr) 140e28a4053SRui Paulo { 141e28a4053SRui Paulo int i; 142e28a4053SRui Paulo const char *pos = txt; 143e28a4053SRui Paulo 144e28a4053SRui Paulo for (i = 0; i < 6; i++) { 145e28a4053SRui Paulo int a, b; 146e28a4053SRui Paulo 147e28a4053SRui Paulo while (*pos == ':' || *pos == '.' || *pos == '-') 148e28a4053SRui Paulo pos++; 149e28a4053SRui Paulo 150e28a4053SRui Paulo a = hex2num(*pos++); 151e28a4053SRui Paulo if (a < 0) 152e28a4053SRui Paulo return -1; 153e28a4053SRui Paulo b = hex2num(*pos++); 154e28a4053SRui Paulo if (b < 0) 155e28a4053SRui Paulo return -1; 156e28a4053SRui Paulo *addr++ = (a << 4) | b; 157e28a4053SRui Paulo } 158e28a4053SRui Paulo 159e28a4053SRui Paulo return pos - txt; 160e28a4053SRui Paulo } 161e28a4053SRui Paulo 162e28a4053SRui Paulo 163e28a4053SRui Paulo /** 16439beb93cSSam Leffler * hexstr2bin - Convert ASCII hex string into binary data 16539beb93cSSam Leffler * @hex: ASCII hex string (e.g., "01ab") 16639beb93cSSam Leffler * @buf: Buffer for the binary data 16739beb93cSSam Leffler * @len: Length of the text to convert in bytes (of buf); hex will be double 16839beb93cSSam Leffler * this size 16939beb93cSSam Leffler * Returns: 0 on success, -1 on failure (invalid hex string) 17039beb93cSSam Leffler */ 17139beb93cSSam Leffler int hexstr2bin(const char *hex, u8 *buf, size_t len) 17239beb93cSSam Leffler { 17339beb93cSSam Leffler size_t i; 17439beb93cSSam Leffler int a; 17539beb93cSSam Leffler const char *ipos = hex; 17639beb93cSSam Leffler u8 *opos = buf; 17739beb93cSSam Leffler 17839beb93cSSam Leffler for (i = 0; i < len; i++) { 17939beb93cSSam Leffler a = hex2byte(ipos); 18039beb93cSSam Leffler if (a < 0) 18139beb93cSSam Leffler return -1; 18239beb93cSSam Leffler *opos++ = a; 18339beb93cSSam Leffler ipos += 2; 18439beb93cSSam Leffler } 18539beb93cSSam Leffler return 0; 18639beb93cSSam Leffler } 18739beb93cSSam Leffler 18839beb93cSSam Leffler 1895b9c547cSRui Paulo int hwaddr_mask_txt(char *buf, size_t len, const u8 *addr, const u8 *mask) 1905b9c547cSRui Paulo { 1915b9c547cSRui Paulo size_t i; 1925b9c547cSRui Paulo int print_mask = 0; 1935b9c547cSRui Paulo int res; 1945b9c547cSRui Paulo 1955b9c547cSRui Paulo for (i = 0; i < ETH_ALEN; i++) { 1965b9c547cSRui Paulo if (mask[i] != 0xff) { 1975b9c547cSRui Paulo print_mask = 1; 1985b9c547cSRui Paulo break; 1995b9c547cSRui Paulo } 2005b9c547cSRui Paulo } 2015b9c547cSRui Paulo 2025b9c547cSRui Paulo if (print_mask) 2035b9c547cSRui Paulo res = os_snprintf(buf, len, MACSTR "/" MACSTR, 2045b9c547cSRui Paulo MAC2STR(addr), MAC2STR(mask)); 2055b9c547cSRui Paulo else 2065b9c547cSRui Paulo res = os_snprintf(buf, len, MACSTR, MAC2STR(addr)); 2075b9c547cSRui Paulo if (os_snprintf_error(len, res)) 2085b9c547cSRui Paulo return -1; 2095b9c547cSRui Paulo return res; 2105b9c547cSRui Paulo } 2115b9c547cSRui Paulo 2125b9c547cSRui Paulo 21339beb93cSSam Leffler /** 21439beb93cSSam Leffler * inc_byte_array - Increment arbitrary length byte array by one 21539beb93cSSam Leffler * @counter: Pointer to byte array 21639beb93cSSam Leffler * @len: Length of the counter in bytes 21739beb93cSSam Leffler * 21839beb93cSSam Leffler * This function increments the last byte of the counter by one and continues 21939beb93cSSam Leffler * rolling over to more significant bytes if the byte was incremented from 22039beb93cSSam Leffler * 0xff to 0x00. 22139beb93cSSam Leffler */ 22239beb93cSSam Leffler void inc_byte_array(u8 *counter, size_t len) 22339beb93cSSam Leffler { 22439beb93cSSam Leffler int pos = len - 1; 22539beb93cSSam Leffler while (pos >= 0) { 22639beb93cSSam Leffler counter[pos]++; 22739beb93cSSam Leffler if (counter[pos] != 0) 22839beb93cSSam Leffler break; 22939beb93cSSam Leffler pos--; 23039beb93cSSam Leffler } 23139beb93cSSam Leffler } 23239beb93cSSam Leffler 23339beb93cSSam Leffler 234206b73d0SCy Schubert void buf_shift_right(u8 *buf, size_t len, size_t bits) 235206b73d0SCy Schubert { 236206b73d0SCy Schubert size_t i; 237206b73d0SCy Schubert 238206b73d0SCy Schubert for (i = len - 1; i > 0; i--) 239206b73d0SCy Schubert buf[i] = (buf[i - 1] << (8 - bits)) | (buf[i] >> bits); 240206b73d0SCy Schubert buf[0] >>= bits; 241206b73d0SCy Schubert } 242206b73d0SCy Schubert 243206b73d0SCy Schubert 24439beb93cSSam Leffler void wpa_get_ntp_timestamp(u8 *buf) 24539beb93cSSam Leffler { 24639beb93cSSam Leffler struct os_time now; 24739beb93cSSam Leffler u32 sec, usec; 24839beb93cSSam Leffler be32 tmp; 24939beb93cSSam Leffler 25039beb93cSSam Leffler /* 64-bit NTP timestamp (time from 1900-01-01 00:00:00) */ 25139beb93cSSam Leffler os_get_time(&now); 25239beb93cSSam Leffler sec = now.sec + 2208988800U; /* Epoch to 1900 */ 25339beb93cSSam Leffler /* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */ 25439beb93cSSam Leffler usec = now.usec; 25539beb93cSSam Leffler usec = 4295 * usec - (usec >> 5) - (usec >> 9); 25639beb93cSSam Leffler tmp = host_to_be32(sec); 25739beb93cSSam Leffler os_memcpy(buf, (u8 *) &tmp, 4); 25839beb93cSSam Leffler tmp = host_to_be32(usec); 25939beb93cSSam Leffler os_memcpy(buf + 4, (u8 *) &tmp, 4); 26039beb93cSSam Leffler } 26139beb93cSSam Leffler 2625b9c547cSRui Paulo /** 2635b9c547cSRui Paulo * wpa_scnprintf - Simpler-to-use snprintf function 2645b9c547cSRui Paulo * @buf: Output buffer 2655b9c547cSRui Paulo * @size: Buffer size 2665b9c547cSRui Paulo * @fmt: format 2675b9c547cSRui Paulo * 2685b9c547cSRui Paulo * Simpler snprintf version that doesn't require further error checks - the 2695b9c547cSRui Paulo * return value only indicates how many bytes were actually written, excluding 2705b9c547cSRui Paulo * the NULL byte (i.e., 0 on error, size-1 if buffer is not big enough). 2715b9c547cSRui Paulo */ 2725b9c547cSRui Paulo int wpa_scnprintf(char *buf, size_t size, const char *fmt, ...) 2735b9c547cSRui Paulo { 2745b9c547cSRui Paulo va_list ap; 2755b9c547cSRui Paulo int ret; 2765b9c547cSRui Paulo 2775b9c547cSRui Paulo if (!size) 2785b9c547cSRui Paulo return 0; 2795b9c547cSRui Paulo 2805b9c547cSRui Paulo va_start(ap, fmt); 2815b9c547cSRui Paulo ret = vsnprintf(buf, size, fmt, ap); 2825b9c547cSRui Paulo va_end(ap); 2835b9c547cSRui Paulo 2845b9c547cSRui Paulo if (ret < 0) 2855b9c547cSRui Paulo return 0; 2865b9c547cSRui Paulo if ((size_t) ret >= size) 2875b9c547cSRui Paulo return size - 1; 2885b9c547cSRui Paulo 2895b9c547cSRui Paulo return ret; 2905b9c547cSRui Paulo } 29139beb93cSSam Leffler 292325151a3SRui Paulo 293325151a3SRui Paulo int wpa_snprintf_hex_sep(char *buf, size_t buf_size, const u8 *data, size_t len, 294325151a3SRui Paulo char sep) 295325151a3SRui Paulo { 296325151a3SRui Paulo size_t i; 297325151a3SRui Paulo char *pos = buf, *end = buf + buf_size; 298325151a3SRui Paulo int ret; 299325151a3SRui Paulo 300325151a3SRui Paulo if (buf_size == 0) 301325151a3SRui Paulo return 0; 302325151a3SRui Paulo 303325151a3SRui Paulo for (i = 0; i < len; i++) { 304325151a3SRui Paulo ret = os_snprintf(pos, end - pos, "%02x%c", 305325151a3SRui Paulo data[i], sep); 306325151a3SRui Paulo if (os_snprintf_error(end - pos, ret)) { 307325151a3SRui Paulo end[-1] = '\0'; 308325151a3SRui Paulo return pos - buf; 309325151a3SRui Paulo } 310325151a3SRui Paulo pos += ret; 311325151a3SRui Paulo } 312325151a3SRui Paulo pos[-1] = '\0'; 313325151a3SRui Paulo return pos - buf; 314325151a3SRui Paulo } 315325151a3SRui Paulo 316325151a3SRui Paulo 31739beb93cSSam Leffler static inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, 31839beb93cSSam Leffler size_t len, int uppercase) 31939beb93cSSam Leffler { 32039beb93cSSam Leffler size_t i; 32139beb93cSSam Leffler char *pos = buf, *end = buf + buf_size; 32239beb93cSSam Leffler int ret; 32339beb93cSSam Leffler if (buf_size == 0) 32439beb93cSSam Leffler return 0; 32539beb93cSSam Leffler for (i = 0; i < len; i++) { 32639beb93cSSam Leffler ret = os_snprintf(pos, end - pos, uppercase ? "%02X" : "%02x", 32739beb93cSSam Leffler data[i]); 3285b9c547cSRui Paulo if (os_snprintf_error(end - pos, ret)) { 32939beb93cSSam Leffler end[-1] = '\0'; 33039beb93cSSam Leffler return pos - buf; 33139beb93cSSam Leffler } 33239beb93cSSam Leffler pos += ret; 33339beb93cSSam Leffler } 33439beb93cSSam Leffler end[-1] = '\0'; 33539beb93cSSam Leffler return pos - buf; 33639beb93cSSam Leffler } 33739beb93cSSam Leffler 33839beb93cSSam Leffler /** 33939beb93cSSam Leffler * wpa_snprintf_hex - Print data as a hex string into a buffer 34039beb93cSSam Leffler * @buf: Memory area to use as the output buffer 34139beb93cSSam Leffler * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1) 34239beb93cSSam Leffler * @data: Data to be printed 34339beb93cSSam Leffler * @len: Length of data in bytes 34439beb93cSSam Leffler * Returns: Number of bytes written 34539beb93cSSam Leffler */ 34639beb93cSSam Leffler int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len) 34739beb93cSSam Leffler { 34839beb93cSSam Leffler return _wpa_snprintf_hex(buf, buf_size, data, len, 0); 34939beb93cSSam Leffler } 35039beb93cSSam Leffler 35139beb93cSSam Leffler 35239beb93cSSam Leffler /** 35339beb93cSSam Leffler * wpa_snprintf_hex_uppercase - Print data as a upper case hex string into buf 35439beb93cSSam Leffler * @buf: Memory area to use as the output buffer 35539beb93cSSam Leffler * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1) 35639beb93cSSam Leffler * @data: Data to be printed 35739beb93cSSam Leffler * @len: Length of data in bytes 35839beb93cSSam Leffler * Returns: Number of bytes written 35939beb93cSSam Leffler */ 36039beb93cSSam Leffler int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data, 36139beb93cSSam Leffler size_t len) 36239beb93cSSam Leffler { 36339beb93cSSam Leffler return _wpa_snprintf_hex(buf, buf_size, data, len, 1); 36439beb93cSSam Leffler } 36539beb93cSSam Leffler 36639beb93cSSam Leffler 36739beb93cSSam Leffler #ifdef CONFIG_ANSI_C_EXTRA 36839beb93cSSam Leffler 36939beb93cSSam Leffler #ifdef _WIN32_WCE 37039beb93cSSam Leffler void perror(const char *s) 37139beb93cSSam Leffler { 37239beb93cSSam Leffler wpa_printf(MSG_ERROR, "%s: GetLastError: %d", 37339beb93cSSam Leffler s, (int) GetLastError()); 37439beb93cSSam Leffler } 37539beb93cSSam Leffler #endif /* _WIN32_WCE */ 37639beb93cSSam Leffler 37739beb93cSSam Leffler 37839beb93cSSam Leffler int optind = 1; 37939beb93cSSam Leffler int optopt; 38039beb93cSSam Leffler char *optarg; 38139beb93cSSam Leffler 38239beb93cSSam Leffler int getopt(int argc, char *const argv[], const char *optstring) 38339beb93cSSam Leffler { 38439beb93cSSam Leffler static int optchr = 1; 38539beb93cSSam Leffler char *cp; 38639beb93cSSam Leffler 38739beb93cSSam Leffler if (optchr == 1) { 38839beb93cSSam Leffler if (optind >= argc) { 38939beb93cSSam Leffler /* all arguments processed */ 39039beb93cSSam Leffler return EOF; 39139beb93cSSam Leffler } 39239beb93cSSam Leffler 39339beb93cSSam Leffler if (argv[optind][0] != '-' || argv[optind][1] == '\0') { 39439beb93cSSam Leffler /* no option characters */ 39539beb93cSSam Leffler return EOF; 39639beb93cSSam Leffler } 39739beb93cSSam Leffler } 39839beb93cSSam Leffler 39939beb93cSSam Leffler if (os_strcmp(argv[optind], "--") == 0) { 40039beb93cSSam Leffler /* no more options */ 40139beb93cSSam Leffler optind++; 40239beb93cSSam Leffler return EOF; 40339beb93cSSam Leffler } 40439beb93cSSam Leffler 40539beb93cSSam Leffler optopt = argv[optind][optchr]; 40639beb93cSSam Leffler cp = os_strchr(optstring, optopt); 40739beb93cSSam Leffler if (cp == NULL || optopt == ':') { 40839beb93cSSam Leffler if (argv[optind][++optchr] == '\0') { 40939beb93cSSam Leffler optchr = 1; 41039beb93cSSam Leffler optind++; 41139beb93cSSam Leffler } 41239beb93cSSam Leffler return '?'; 41339beb93cSSam Leffler } 41439beb93cSSam Leffler 41539beb93cSSam Leffler if (cp[1] == ':') { 41639beb93cSSam Leffler /* Argument required */ 41739beb93cSSam Leffler optchr = 1; 41839beb93cSSam Leffler if (argv[optind][optchr + 1]) { 41939beb93cSSam Leffler /* No space between option and argument */ 42039beb93cSSam Leffler optarg = &argv[optind++][optchr + 1]; 42139beb93cSSam Leffler } else if (++optind >= argc) { 42239beb93cSSam Leffler /* option requires an argument */ 42339beb93cSSam Leffler return '?'; 42439beb93cSSam Leffler } else { 42539beb93cSSam Leffler /* Argument in the next argv */ 42639beb93cSSam Leffler optarg = argv[optind++]; 42739beb93cSSam Leffler } 42839beb93cSSam Leffler } else { 42939beb93cSSam Leffler /* No argument */ 43039beb93cSSam Leffler if (argv[optind][++optchr] == '\0') { 43139beb93cSSam Leffler optchr = 1; 43239beb93cSSam Leffler optind++; 43339beb93cSSam Leffler } 43439beb93cSSam Leffler optarg = NULL; 43539beb93cSSam Leffler } 43639beb93cSSam Leffler return *cp; 43739beb93cSSam Leffler } 43839beb93cSSam Leffler #endif /* CONFIG_ANSI_C_EXTRA */ 43939beb93cSSam Leffler 44039beb93cSSam Leffler 44139beb93cSSam Leffler #ifdef CONFIG_NATIVE_WINDOWS 44239beb93cSSam Leffler /** 44339beb93cSSam Leffler * wpa_unicode2ascii_inplace - Convert unicode string into ASCII 44439beb93cSSam Leffler * @str: Pointer to string to convert 44539beb93cSSam Leffler * 44639beb93cSSam Leffler * This function converts a unicode string to ASCII using the same 44739beb93cSSam Leffler * buffer for output. If UNICODE is not set, the buffer is not 44839beb93cSSam Leffler * modified. 44939beb93cSSam Leffler */ 45039beb93cSSam Leffler void wpa_unicode2ascii_inplace(TCHAR *str) 45139beb93cSSam Leffler { 45239beb93cSSam Leffler #ifdef UNICODE 45339beb93cSSam Leffler char *dst = (char *) str; 45439beb93cSSam Leffler while (*str) 45539beb93cSSam Leffler *dst++ = (char) *str++; 45639beb93cSSam Leffler *dst = '\0'; 45739beb93cSSam Leffler #endif /* UNICODE */ 45839beb93cSSam Leffler } 45939beb93cSSam Leffler 46039beb93cSSam Leffler 46139beb93cSSam Leffler TCHAR * wpa_strdup_tchar(const char *str) 46239beb93cSSam Leffler { 46339beb93cSSam Leffler #ifdef UNICODE 46439beb93cSSam Leffler TCHAR *buf; 46539beb93cSSam Leffler buf = os_malloc((strlen(str) + 1) * sizeof(TCHAR)); 46639beb93cSSam Leffler if (buf == NULL) 46739beb93cSSam Leffler return NULL; 46839beb93cSSam Leffler wsprintf(buf, L"%S", str); 46939beb93cSSam Leffler return buf; 47039beb93cSSam Leffler #else /* UNICODE */ 47139beb93cSSam Leffler return os_strdup(str); 47239beb93cSSam Leffler #endif /* UNICODE */ 47339beb93cSSam Leffler } 47439beb93cSSam Leffler #endif /* CONFIG_NATIVE_WINDOWS */ 47539beb93cSSam Leffler 47639beb93cSSam Leffler 477f05cddf9SRui Paulo void printf_encode(char *txt, size_t maxlen, const u8 *data, size_t len) 478f05cddf9SRui Paulo { 479f05cddf9SRui Paulo char *end = txt + maxlen; 480f05cddf9SRui Paulo size_t i; 481f05cddf9SRui Paulo 482f05cddf9SRui Paulo for (i = 0; i < len; i++) { 4835b9c547cSRui Paulo if (txt + 4 >= end) 484f05cddf9SRui Paulo break; 485f05cddf9SRui Paulo 486f05cddf9SRui Paulo switch (data[i]) { 487f05cddf9SRui Paulo case '\"': 488f05cddf9SRui Paulo *txt++ = '\\'; 489f05cddf9SRui Paulo *txt++ = '\"'; 490f05cddf9SRui Paulo break; 491f05cddf9SRui Paulo case '\\': 492f05cddf9SRui Paulo *txt++ = '\\'; 493f05cddf9SRui Paulo *txt++ = '\\'; 494f05cddf9SRui Paulo break; 4955b9c547cSRui Paulo case '\033': 496f05cddf9SRui Paulo *txt++ = '\\'; 497f05cddf9SRui Paulo *txt++ = 'e'; 498f05cddf9SRui Paulo break; 499f05cddf9SRui Paulo case '\n': 500f05cddf9SRui Paulo *txt++ = '\\'; 501f05cddf9SRui Paulo *txt++ = 'n'; 502f05cddf9SRui Paulo break; 503f05cddf9SRui Paulo case '\r': 504f05cddf9SRui Paulo *txt++ = '\\'; 505f05cddf9SRui Paulo *txt++ = 'r'; 506f05cddf9SRui Paulo break; 507f05cddf9SRui Paulo case '\t': 508f05cddf9SRui Paulo *txt++ = '\\'; 509f05cddf9SRui Paulo *txt++ = 't'; 510f05cddf9SRui Paulo break; 511f05cddf9SRui Paulo default: 512780fb4a2SCy Schubert if (data[i] >= 32 && data[i] <= 126) { 513f05cddf9SRui Paulo *txt++ = data[i]; 514f05cddf9SRui Paulo } else { 515f05cddf9SRui Paulo txt += os_snprintf(txt, end - txt, "\\x%02x", 516f05cddf9SRui Paulo data[i]); 517f05cddf9SRui Paulo } 518f05cddf9SRui Paulo break; 519f05cddf9SRui Paulo } 520f05cddf9SRui Paulo } 521f05cddf9SRui Paulo 522f05cddf9SRui Paulo *txt = '\0'; 523f05cddf9SRui Paulo } 524f05cddf9SRui Paulo 525f05cddf9SRui Paulo 526f05cddf9SRui Paulo size_t printf_decode(u8 *buf, size_t maxlen, const char *str) 527f05cddf9SRui Paulo { 528f05cddf9SRui Paulo const char *pos = str; 529f05cddf9SRui Paulo size_t len = 0; 530f05cddf9SRui Paulo int val; 531f05cddf9SRui Paulo 532f05cddf9SRui Paulo while (*pos) { 5335b9c547cSRui Paulo if (len + 1 >= maxlen) 534f05cddf9SRui Paulo break; 535f05cddf9SRui Paulo switch (*pos) { 536f05cddf9SRui Paulo case '\\': 537f05cddf9SRui Paulo pos++; 538f05cddf9SRui Paulo switch (*pos) { 539f05cddf9SRui Paulo case '\\': 540f05cddf9SRui Paulo buf[len++] = '\\'; 541f05cddf9SRui Paulo pos++; 542f05cddf9SRui Paulo break; 543f05cddf9SRui Paulo case '"': 544f05cddf9SRui Paulo buf[len++] = '"'; 545f05cddf9SRui Paulo pos++; 546f05cddf9SRui Paulo break; 547f05cddf9SRui Paulo case 'n': 548f05cddf9SRui Paulo buf[len++] = '\n'; 549f05cddf9SRui Paulo pos++; 550f05cddf9SRui Paulo break; 551f05cddf9SRui Paulo case 'r': 552f05cddf9SRui Paulo buf[len++] = '\r'; 553f05cddf9SRui Paulo pos++; 554f05cddf9SRui Paulo break; 555f05cddf9SRui Paulo case 't': 556f05cddf9SRui Paulo buf[len++] = '\t'; 557f05cddf9SRui Paulo pos++; 558f05cddf9SRui Paulo break; 559f05cddf9SRui Paulo case 'e': 5605b9c547cSRui Paulo buf[len++] = '\033'; 561f05cddf9SRui Paulo pos++; 562f05cddf9SRui Paulo break; 563f05cddf9SRui Paulo case 'x': 564f05cddf9SRui Paulo pos++; 565f05cddf9SRui Paulo val = hex2byte(pos); 566f05cddf9SRui Paulo if (val < 0) { 567f05cddf9SRui Paulo val = hex2num(*pos); 568f05cddf9SRui Paulo if (val < 0) 569f05cddf9SRui Paulo break; 570f05cddf9SRui Paulo buf[len++] = val; 571f05cddf9SRui Paulo pos++; 572f05cddf9SRui Paulo } else { 573f05cddf9SRui Paulo buf[len++] = val; 574f05cddf9SRui Paulo pos += 2; 575f05cddf9SRui Paulo } 576f05cddf9SRui Paulo break; 577f05cddf9SRui Paulo case '0': 578f05cddf9SRui Paulo case '1': 579f05cddf9SRui Paulo case '2': 580f05cddf9SRui Paulo case '3': 581f05cddf9SRui Paulo case '4': 582f05cddf9SRui Paulo case '5': 583f05cddf9SRui Paulo case '6': 584f05cddf9SRui Paulo case '7': 585f05cddf9SRui Paulo val = *pos++ - '0'; 586f05cddf9SRui Paulo if (*pos >= '0' && *pos <= '7') 587f05cddf9SRui Paulo val = val * 8 + (*pos++ - '0'); 588f05cddf9SRui Paulo if (*pos >= '0' && *pos <= '7') 589f05cddf9SRui Paulo val = val * 8 + (*pos++ - '0'); 590f05cddf9SRui Paulo buf[len++] = val; 591f05cddf9SRui Paulo break; 592f05cddf9SRui Paulo default: 593f05cddf9SRui Paulo break; 594f05cddf9SRui Paulo } 595f05cddf9SRui Paulo break; 596f05cddf9SRui Paulo default: 597f05cddf9SRui Paulo buf[len++] = *pos++; 598f05cddf9SRui Paulo break; 599f05cddf9SRui Paulo } 600f05cddf9SRui Paulo } 6015b9c547cSRui Paulo if (maxlen > len) 6025b9c547cSRui Paulo buf[len] = '\0'; 603f05cddf9SRui Paulo 604f05cddf9SRui Paulo return len; 605f05cddf9SRui Paulo } 606f05cddf9SRui Paulo 607f05cddf9SRui Paulo 60839beb93cSSam Leffler /** 60939beb93cSSam Leffler * wpa_ssid_txt - Convert SSID to a printable string 61039beb93cSSam Leffler * @ssid: SSID (32-octet string) 61139beb93cSSam Leffler * @ssid_len: Length of ssid in octets 61239beb93cSSam Leffler * Returns: Pointer to a printable string 61339beb93cSSam Leffler * 61439beb93cSSam Leffler * This function can be used to convert SSIDs into printable form. In most 61539beb93cSSam Leffler * cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard 61639beb93cSSam Leffler * does not limit the used character set, so anything could be used in an SSID. 61739beb93cSSam Leffler * 61839beb93cSSam Leffler * This function uses a static buffer, so only one call can be used at the 61939beb93cSSam Leffler * time, i.e., this is not re-entrant and the returned buffer must be used 62039beb93cSSam Leffler * before calling this again. 62139beb93cSSam Leffler */ 62239beb93cSSam Leffler const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len) 62339beb93cSSam Leffler { 624325151a3SRui Paulo static char ssid_txt[SSID_MAX_LEN * 4 + 1]; 62539beb93cSSam Leffler 626f05cddf9SRui Paulo if (ssid == NULL) { 627f05cddf9SRui Paulo ssid_txt[0] = '\0'; 628f05cddf9SRui Paulo return ssid_txt; 62939beb93cSSam Leffler } 630f05cddf9SRui Paulo 631f05cddf9SRui Paulo printf_encode(ssid_txt, sizeof(ssid_txt), ssid, ssid_len); 63239beb93cSSam Leffler return ssid_txt; 63339beb93cSSam Leffler } 6343157ba21SRui Paulo 6353157ba21SRui Paulo 6363157ba21SRui Paulo void * __hide_aliasing_typecast(void *foo) 6373157ba21SRui Paulo { 6383157ba21SRui Paulo return foo; 6393157ba21SRui Paulo } 640f05cddf9SRui Paulo 641f05cddf9SRui Paulo 642f05cddf9SRui Paulo char * wpa_config_parse_string(const char *value, size_t *len) 643f05cddf9SRui Paulo { 644f05cddf9SRui Paulo if (*value == '"') { 645f05cddf9SRui Paulo const char *pos; 646f05cddf9SRui Paulo char *str; 647f05cddf9SRui Paulo value++; 648f05cddf9SRui Paulo pos = os_strrchr(value, '"'); 649f05cddf9SRui Paulo if (pos == NULL || pos[1] != '\0') 650f05cddf9SRui Paulo return NULL; 651f05cddf9SRui Paulo *len = pos - value; 6525b9c547cSRui Paulo str = dup_binstr(value, *len); 653f05cddf9SRui Paulo if (str == NULL) 654f05cddf9SRui Paulo return NULL; 655f05cddf9SRui Paulo return str; 656f05cddf9SRui Paulo } else if (*value == 'P' && value[1] == '"') { 657f05cddf9SRui Paulo const char *pos; 658f05cddf9SRui Paulo char *tstr, *str; 659f05cddf9SRui Paulo size_t tlen; 660f05cddf9SRui Paulo value += 2; 661f05cddf9SRui Paulo pos = os_strrchr(value, '"'); 662f05cddf9SRui Paulo if (pos == NULL || pos[1] != '\0') 663f05cddf9SRui Paulo return NULL; 664f05cddf9SRui Paulo tlen = pos - value; 6655b9c547cSRui Paulo tstr = dup_binstr(value, tlen); 666f05cddf9SRui Paulo if (tstr == NULL) 667f05cddf9SRui Paulo return NULL; 668f05cddf9SRui Paulo 669f05cddf9SRui Paulo str = os_malloc(tlen + 1); 670f05cddf9SRui Paulo if (str == NULL) { 671f05cddf9SRui Paulo os_free(tstr); 672f05cddf9SRui Paulo return NULL; 673f05cddf9SRui Paulo } 674f05cddf9SRui Paulo 675f05cddf9SRui Paulo *len = printf_decode((u8 *) str, tlen + 1, tstr); 676f05cddf9SRui Paulo os_free(tstr); 677f05cddf9SRui Paulo 678f05cddf9SRui Paulo return str; 679f05cddf9SRui Paulo } else { 680f05cddf9SRui Paulo u8 *str; 681f05cddf9SRui Paulo size_t tlen, hlen = os_strlen(value); 682f05cddf9SRui Paulo if (hlen & 1) 683f05cddf9SRui Paulo return NULL; 684f05cddf9SRui Paulo tlen = hlen / 2; 685f05cddf9SRui Paulo str = os_malloc(tlen + 1); 686f05cddf9SRui Paulo if (str == NULL) 687f05cddf9SRui Paulo return NULL; 688f05cddf9SRui Paulo if (hexstr2bin(value, str, tlen)) { 689f05cddf9SRui Paulo os_free(str); 690f05cddf9SRui Paulo return NULL; 691f05cddf9SRui Paulo } 692f05cddf9SRui Paulo str[tlen] = '\0'; 693f05cddf9SRui Paulo *len = tlen; 694f05cddf9SRui Paulo return (char *) str; 695f05cddf9SRui Paulo } 696f05cddf9SRui Paulo } 697f05cddf9SRui Paulo 698f05cddf9SRui Paulo 699f05cddf9SRui Paulo int is_hex(const u8 *data, size_t len) 700f05cddf9SRui Paulo { 701f05cddf9SRui Paulo size_t i; 702f05cddf9SRui Paulo 703f05cddf9SRui Paulo for (i = 0; i < len; i++) { 704f05cddf9SRui Paulo if (data[i] < 32 || data[i] >= 127) 705f05cddf9SRui Paulo return 1; 706f05cddf9SRui Paulo } 707f05cddf9SRui Paulo return 0; 708f05cddf9SRui Paulo } 709f05cddf9SRui Paulo 710f05cddf9SRui Paulo 711780fb4a2SCy Schubert int has_ctrl_char(const u8 *data, size_t len) 712780fb4a2SCy Schubert { 713780fb4a2SCy Schubert size_t i; 714780fb4a2SCy Schubert 715780fb4a2SCy Schubert for (i = 0; i < len; i++) { 716780fb4a2SCy Schubert if (data[i] < 32 || data[i] == 127) 717780fb4a2SCy Schubert return 1; 718780fb4a2SCy Schubert } 719780fb4a2SCy Schubert return 0; 720780fb4a2SCy Schubert } 721780fb4a2SCy Schubert 722780fb4a2SCy Schubert 723780fb4a2SCy Schubert int has_newline(const char *str) 724780fb4a2SCy Schubert { 725780fb4a2SCy Schubert while (*str) { 726780fb4a2SCy Schubert if (*str == '\n' || *str == '\r') 727780fb4a2SCy Schubert return 1; 728780fb4a2SCy Schubert str++; 729780fb4a2SCy Schubert } 730780fb4a2SCy Schubert return 0; 731780fb4a2SCy Schubert } 732780fb4a2SCy Schubert 733780fb4a2SCy Schubert 734f05cddf9SRui Paulo size_t merge_byte_arrays(u8 *res, size_t res_len, 735f05cddf9SRui Paulo const u8 *src1, size_t src1_len, 736f05cddf9SRui Paulo const u8 *src2, size_t src2_len) 737f05cddf9SRui Paulo { 738f05cddf9SRui Paulo size_t len = 0; 739f05cddf9SRui Paulo 740f05cddf9SRui Paulo os_memset(res, 0, res_len); 741f05cddf9SRui Paulo 742f05cddf9SRui Paulo if (src1) { 743f05cddf9SRui Paulo if (src1_len >= res_len) { 744f05cddf9SRui Paulo os_memcpy(res, src1, res_len); 745f05cddf9SRui Paulo return res_len; 746f05cddf9SRui Paulo } 747f05cddf9SRui Paulo 748f05cddf9SRui Paulo os_memcpy(res, src1, src1_len); 749f05cddf9SRui Paulo len += src1_len; 750f05cddf9SRui Paulo } 751f05cddf9SRui Paulo 752f05cddf9SRui Paulo if (src2) { 753f05cddf9SRui Paulo if (len + src2_len >= res_len) { 754f05cddf9SRui Paulo os_memcpy(res + len, src2, res_len - len); 755f05cddf9SRui Paulo return res_len; 756f05cddf9SRui Paulo } 757f05cddf9SRui Paulo 758f05cddf9SRui Paulo os_memcpy(res + len, src2, src2_len); 759f05cddf9SRui Paulo len += src2_len; 760f05cddf9SRui Paulo } 761f05cddf9SRui Paulo 762f05cddf9SRui Paulo return len; 763f05cddf9SRui Paulo } 7645b9c547cSRui Paulo 7655b9c547cSRui Paulo 7665b9c547cSRui Paulo char * dup_binstr(const void *src, size_t len) 7675b9c547cSRui Paulo { 7685b9c547cSRui Paulo char *res; 7695b9c547cSRui Paulo 7705b9c547cSRui Paulo if (src == NULL) 7715b9c547cSRui Paulo return NULL; 7725b9c547cSRui Paulo res = os_malloc(len + 1); 7735b9c547cSRui Paulo if (res == NULL) 7745b9c547cSRui Paulo return NULL; 7755b9c547cSRui Paulo os_memcpy(res, src, len); 7765b9c547cSRui Paulo res[len] = '\0'; 7775b9c547cSRui Paulo 7785b9c547cSRui Paulo return res; 7795b9c547cSRui Paulo } 7805b9c547cSRui Paulo 7815b9c547cSRui Paulo 7825b9c547cSRui Paulo int freq_range_list_parse(struct wpa_freq_range_list *res, const char *value) 7835b9c547cSRui Paulo { 7845b9c547cSRui Paulo struct wpa_freq_range *freq = NULL, *n; 7855b9c547cSRui Paulo unsigned int count = 0; 7865b9c547cSRui Paulo const char *pos, *pos2, *pos3; 7875b9c547cSRui Paulo 7885b9c547cSRui Paulo /* 7895b9c547cSRui Paulo * Comma separated list of frequency ranges. 7905b9c547cSRui Paulo * For example: 2412-2432,2462,5000-6000 7915b9c547cSRui Paulo */ 7925b9c547cSRui Paulo pos = value; 7935b9c547cSRui Paulo while (pos && pos[0]) { 794c1d255d3SCy Schubert if (count == UINT_MAX) { 795c1d255d3SCy Schubert os_free(freq); 796c1d255d3SCy Schubert return -1; 797c1d255d3SCy Schubert } 7985b9c547cSRui Paulo n = os_realloc_array(freq, count + 1, 7995b9c547cSRui Paulo sizeof(struct wpa_freq_range)); 8005b9c547cSRui Paulo if (n == NULL) { 8015b9c547cSRui Paulo os_free(freq); 8025b9c547cSRui Paulo return -1; 8035b9c547cSRui Paulo } 8045b9c547cSRui Paulo freq = n; 8055b9c547cSRui Paulo freq[count].min = atoi(pos); 8065b9c547cSRui Paulo pos2 = os_strchr(pos, '-'); 8075b9c547cSRui Paulo pos3 = os_strchr(pos, ','); 8085b9c547cSRui Paulo if (pos2 && (!pos3 || pos2 < pos3)) { 8095b9c547cSRui Paulo pos2++; 8105b9c547cSRui Paulo freq[count].max = atoi(pos2); 8115b9c547cSRui Paulo } else 8125b9c547cSRui Paulo freq[count].max = freq[count].min; 8135b9c547cSRui Paulo pos = pos3; 8145b9c547cSRui Paulo if (pos) 8155b9c547cSRui Paulo pos++; 8165b9c547cSRui Paulo count++; 8175b9c547cSRui Paulo } 8185b9c547cSRui Paulo 8195b9c547cSRui Paulo os_free(res->range); 8205b9c547cSRui Paulo res->range = freq; 8215b9c547cSRui Paulo res->num = count; 8225b9c547cSRui Paulo 8235b9c547cSRui Paulo return 0; 8245b9c547cSRui Paulo } 8255b9c547cSRui Paulo 8265b9c547cSRui Paulo 8275b9c547cSRui Paulo int freq_range_list_includes(const struct wpa_freq_range_list *list, 8285b9c547cSRui Paulo unsigned int freq) 8295b9c547cSRui Paulo { 8305b9c547cSRui Paulo unsigned int i; 8315b9c547cSRui Paulo 8325b9c547cSRui Paulo if (list == NULL) 8335b9c547cSRui Paulo return 0; 8345b9c547cSRui Paulo 8355b9c547cSRui Paulo for (i = 0; i < list->num; i++) { 8365b9c547cSRui Paulo if (freq >= list->range[i].min && freq <= list->range[i].max) 8375b9c547cSRui Paulo return 1; 8385b9c547cSRui Paulo } 8395b9c547cSRui Paulo 8405b9c547cSRui Paulo return 0; 8415b9c547cSRui Paulo } 8425b9c547cSRui Paulo 8435b9c547cSRui Paulo 8445b9c547cSRui Paulo char * freq_range_list_str(const struct wpa_freq_range_list *list) 8455b9c547cSRui Paulo { 8465b9c547cSRui Paulo char *buf, *pos, *end; 8475b9c547cSRui Paulo size_t maxlen; 8485b9c547cSRui Paulo unsigned int i; 8495b9c547cSRui Paulo int res; 8505b9c547cSRui Paulo 8515b9c547cSRui Paulo if (list->num == 0) 8525b9c547cSRui Paulo return NULL; 8535b9c547cSRui Paulo 8545b9c547cSRui Paulo maxlen = list->num * 30; 8555b9c547cSRui Paulo buf = os_malloc(maxlen); 8565b9c547cSRui Paulo if (buf == NULL) 8575b9c547cSRui Paulo return NULL; 8585b9c547cSRui Paulo pos = buf; 8595b9c547cSRui Paulo end = buf + maxlen; 8605b9c547cSRui Paulo 8615b9c547cSRui Paulo for (i = 0; i < list->num; i++) { 8625b9c547cSRui Paulo struct wpa_freq_range *range = &list->range[i]; 8635b9c547cSRui Paulo 8645b9c547cSRui Paulo if (range->min == range->max) 8655b9c547cSRui Paulo res = os_snprintf(pos, end - pos, "%s%u", 8665b9c547cSRui Paulo i == 0 ? "" : ",", range->min); 8675b9c547cSRui Paulo else 8685b9c547cSRui Paulo res = os_snprintf(pos, end - pos, "%s%u-%u", 8695b9c547cSRui Paulo i == 0 ? "" : ",", 8705b9c547cSRui Paulo range->min, range->max); 8715b9c547cSRui Paulo if (os_snprintf_error(end - pos, res)) { 8725b9c547cSRui Paulo os_free(buf); 8735b9c547cSRui Paulo return NULL; 8745b9c547cSRui Paulo } 8755b9c547cSRui Paulo pos += res; 8765b9c547cSRui Paulo } 8775b9c547cSRui Paulo 8785b9c547cSRui Paulo return buf; 8795b9c547cSRui Paulo } 8805b9c547cSRui Paulo 8815b9c547cSRui Paulo 882c1d255d3SCy Schubert size_t int_array_len(const int *a) 8835b9c547cSRui Paulo { 884c1d255d3SCy Schubert size_t i; 885c1d255d3SCy Schubert 8865b9c547cSRui Paulo for (i = 0; a && a[i]; i++) 8875b9c547cSRui Paulo ; 8885b9c547cSRui Paulo return i; 8895b9c547cSRui Paulo } 8905b9c547cSRui Paulo 8915b9c547cSRui Paulo 8925b9c547cSRui Paulo void int_array_concat(int **res, const int *a) 8935b9c547cSRui Paulo { 894c1d255d3SCy Schubert size_t reslen, alen, i, max_size; 8955b9c547cSRui Paulo int *n; 8965b9c547cSRui Paulo 8975b9c547cSRui Paulo reslen = int_array_len(*res); 8985b9c547cSRui Paulo alen = int_array_len(a); 899c1d255d3SCy Schubert max_size = (size_t) -1; 900c1d255d3SCy Schubert if (alen >= max_size - reslen) { 901c1d255d3SCy Schubert /* This should not really happen, but if it did, something 902c1d255d3SCy Schubert * would overflow. Do not try to merge the arrays; instead, make 903c1d255d3SCy Schubert * this behave like memory allocation failure to avoid messing 904c1d255d3SCy Schubert * up memory. */ 905c1d255d3SCy Schubert os_free(*res); 906c1d255d3SCy Schubert *res = NULL; 907c1d255d3SCy Schubert return; 908c1d255d3SCy Schubert } 9095b9c547cSRui Paulo n = os_realloc_array(*res, reslen + alen + 1, sizeof(int)); 9105b9c547cSRui Paulo if (n == NULL) { 9115b9c547cSRui Paulo os_free(*res); 9125b9c547cSRui Paulo *res = NULL; 9135b9c547cSRui Paulo return; 9145b9c547cSRui Paulo } 9155b9c547cSRui Paulo for (i = 0; i <= alen; i++) 9165b9c547cSRui Paulo n[reslen + i] = a[i]; 9175b9c547cSRui Paulo *res = n; 9185b9c547cSRui Paulo } 9195b9c547cSRui Paulo 9205b9c547cSRui Paulo 9215b9c547cSRui Paulo static int freq_cmp(const void *a, const void *b) 9225b9c547cSRui Paulo { 9235b9c547cSRui Paulo int _a = *(int *) a; 9245b9c547cSRui Paulo int _b = *(int *) b; 9255b9c547cSRui Paulo 9265b9c547cSRui Paulo if (_a == 0) 9275b9c547cSRui Paulo return 1; 9285b9c547cSRui Paulo if (_b == 0) 9295b9c547cSRui Paulo return -1; 9305b9c547cSRui Paulo return _a - _b; 9315b9c547cSRui Paulo } 9325b9c547cSRui Paulo 9335b9c547cSRui Paulo 9345b9c547cSRui Paulo void int_array_sort_unique(int *a) 9355b9c547cSRui Paulo { 936c1d255d3SCy Schubert size_t alen, i, j; 9375b9c547cSRui Paulo 9385b9c547cSRui Paulo if (a == NULL) 9395b9c547cSRui Paulo return; 9405b9c547cSRui Paulo 9415b9c547cSRui Paulo alen = int_array_len(a); 9425b9c547cSRui Paulo qsort(a, alen, sizeof(int), freq_cmp); 9435b9c547cSRui Paulo 9445b9c547cSRui Paulo i = 0; 9455b9c547cSRui Paulo j = 1; 9465b9c547cSRui Paulo while (a[i] && a[j]) { 9475b9c547cSRui Paulo if (a[i] == a[j]) { 9485b9c547cSRui Paulo j++; 9495b9c547cSRui Paulo continue; 9505b9c547cSRui Paulo } 9515b9c547cSRui Paulo a[++i] = a[j++]; 9525b9c547cSRui Paulo } 9535b9c547cSRui Paulo if (a[i]) 9545b9c547cSRui Paulo i++; 9555b9c547cSRui Paulo a[i] = 0; 9565b9c547cSRui Paulo } 9575b9c547cSRui Paulo 9585b9c547cSRui Paulo 9595b9c547cSRui Paulo void int_array_add_unique(int **res, int a) 9605b9c547cSRui Paulo { 961c1d255d3SCy Schubert size_t reslen, max_size; 9625b9c547cSRui Paulo int *n; 9635b9c547cSRui Paulo 9645b9c547cSRui Paulo for (reslen = 0; *res && (*res)[reslen]; reslen++) { 9655b9c547cSRui Paulo if ((*res)[reslen] == a) 9665b9c547cSRui Paulo return; /* already in the list */ 9675b9c547cSRui Paulo } 9685b9c547cSRui Paulo 969c1d255d3SCy Schubert max_size = (size_t) -1; 970c1d255d3SCy Schubert if (reslen > max_size - 2) { 971c1d255d3SCy Schubert /* This should not really happen in practice, but if it did, 972c1d255d3SCy Schubert * something would overflow. Do not try to add the new value; 973c1d255d3SCy Schubert * instead, make this behave like memory allocation failure to 974c1d255d3SCy Schubert * avoid messing up memory. */ 975c1d255d3SCy Schubert os_free(*res); 976c1d255d3SCy Schubert *res = NULL; 977c1d255d3SCy Schubert return; 978c1d255d3SCy Schubert } 9795b9c547cSRui Paulo n = os_realloc_array(*res, reslen + 2, sizeof(int)); 9805b9c547cSRui Paulo if (n == NULL) { 9815b9c547cSRui Paulo os_free(*res); 9825b9c547cSRui Paulo *res = NULL; 9835b9c547cSRui Paulo return; 9845b9c547cSRui Paulo } 9855b9c547cSRui Paulo 9865b9c547cSRui Paulo n[reslen] = a; 9875b9c547cSRui Paulo n[reslen + 1] = 0; 9885b9c547cSRui Paulo 9895b9c547cSRui Paulo *res = n; 9905b9c547cSRui Paulo } 9915b9c547cSRui Paulo 9925b9c547cSRui Paulo 993*a90b9d01SCy Schubert bool int_array_includes(int *arr, int val) 994*a90b9d01SCy Schubert { 995*a90b9d01SCy Schubert int i; 996*a90b9d01SCy Schubert 997*a90b9d01SCy Schubert for (i = 0; arr && arr[i]; i++) { 998*a90b9d01SCy Schubert if (val == arr[i]) 999*a90b9d01SCy Schubert return true; 1000*a90b9d01SCy Schubert } 1001*a90b9d01SCy Schubert 1002*a90b9d01SCy Schubert return false; 1003*a90b9d01SCy Schubert } 1004*a90b9d01SCy Schubert 1005*a90b9d01SCy Schubert 10065b9c547cSRui Paulo void str_clear_free(char *str) 10075b9c547cSRui Paulo { 10085b9c547cSRui Paulo if (str) { 10095b9c547cSRui Paulo size_t len = os_strlen(str); 1010206b73d0SCy Schubert forced_memzero(str, len); 10115b9c547cSRui Paulo os_free(str); 10125b9c547cSRui Paulo } 10135b9c547cSRui Paulo } 10145b9c547cSRui Paulo 10155b9c547cSRui Paulo 10165b9c547cSRui Paulo void bin_clear_free(void *bin, size_t len) 10175b9c547cSRui Paulo { 10185b9c547cSRui Paulo if (bin) { 1019206b73d0SCy Schubert forced_memzero(bin, len); 10205b9c547cSRui Paulo os_free(bin); 10215b9c547cSRui Paulo } 10225b9c547cSRui Paulo } 10235b9c547cSRui Paulo 10245b9c547cSRui Paulo 10255b9c547cSRui Paulo int random_mac_addr(u8 *addr) 10265b9c547cSRui Paulo { 10275b9c547cSRui Paulo if (os_get_random(addr, ETH_ALEN) < 0) 10285b9c547cSRui Paulo return -1; 10295b9c547cSRui Paulo addr[0] &= 0xfe; /* unicast */ 10305b9c547cSRui Paulo addr[0] |= 0x02; /* locally administered */ 10315b9c547cSRui Paulo return 0; 10325b9c547cSRui Paulo } 10335b9c547cSRui Paulo 10345b9c547cSRui Paulo 10355b9c547cSRui Paulo int random_mac_addr_keep_oui(u8 *addr) 10365b9c547cSRui Paulo { 10375b9c547cSRui Paulo if (os_get_random(addr + 3, 3) < 0) 10385b9c547cSRui Paulo return -1; 10395b9c547cSRui Paulo addr[0] &= 0xfe; /* unicast */ 10405b9c547cSRui Paulo addr[0] |= 0x02; /* locally administered */ 10415b9c547cSRui Paulo return 0; 10425b9c547cSRui Paulo } 10435b9c547cSRui Paulo 10445b9c547cSRui Paulo 10455b9c547cSRui Paulo /** 1046325151a3SRui Paulo * cstr_token - Get next token from const char string 1047325151a3SRui Paulo * @str: a constant string to tokenize 1048325151a3SRui Paulo * @delim: a string of delimiters 1049325151a3SRui Paulo * @last: a pointer to a character following the returned token 1050325151a3SRui Paulo * It has to be set to NULL for the first call and passed for any 1051780fb4a2SCy Schubert * further call. 1052325151a3SRui Paulo * Returns: a pointer to token position in str or NULL 1053325151a3SRui Paulo * 1054325151a3SRui Paulo * This function is similar to str_token, but it can be used with both 1055325151a3SRui Paulo * char and const char strings. Differences: 1056325151a3SRui Paulo * - The str buffer remains unmodified 1057325151a3SRui Paulo * - The returned token is not a NULL terminated string, but a token 1058325151a3SRui Paulo * position in str buffer. If a return value is not NULL a size 1059325151a3SRui Paulo * of the returned token could be calculated as (last - token). 1060325151a3SRui Paulo */ 1061325151a3SRui Paulo const char * cstr_token(const char *str, const char *delim, const char **last) 1062325151a3SRui Paulo { 1063325151a3SRui Paulo const char *end, *token = str; 1064325151a3SRui Paulo 1065325151a3SRui Paulo if (!str || !delim || !last) 1066325151a3SRui Paulo return NULL; 1067325151a3SRui Paulo 1068325151a3SRui Paulo if (*last) 1069325151a3SRui Paulo token = *last; 1070325151a3SRui Paulo 1071325151a3SRui Paulo while (*token && os_strchr(delim, *token)) 1072325151a3SRui Paulo token++; 1073325151a3SRui Paulo 1074325151a3SRui Paulo if (!*token) 1075325151a3SRui Paulo return NULL; 1076325151a3SRui Paulo 1077325151a3SRui Paulo end = token + 1; 1078325151a3SRui Paulo 1079325151a3SRui Paulo while (*end && !os_strchr(delim, *end)) 1080325151a3SRui Paulo end++; 1081325151a3SRui Paulo 1082325151a3SRui Paulo *last = end; 1083325151a3SRui Paulo return token; 1084325151a3SRui Paulo } 1085325151a3SRui Paulo 1086325151a3SRui Paulo 1087325151a3SRui Paulo /** 10885b9c547cSRui Paulo * str_token - Get next token from a string 10895b9c547cSRui Paulo * @buf: String to tokenize. Note that the string might be modified. 10905b9c547cSRui Paulo * @delim: String of delimiters 10915b9c547cSRui Paulo * @context: Pointer to save our context. Should be initialized with 10925b9c547cSRui Paulo * NULL on the first call, and passed for any further call. 10935b9c547cSRui Paulo * Returns: The next token, NULL if there are no more valid tokens. 10945b9c547cSRui Paulo */ 10955b9c547cSRui Paulo char * str_token(char *str, const char *delim, char **context) 10965b9c547cSRui Paulo { 1097325151a3SRui Paulo char *token = (char *) cstr_token(str, delim, (const char **) context); 10985b9c547cSRui Paulo 1099325151a3SRui Paulo if (token && **context) 1100325151a3SRui Paulo *(*context)++ = '\0'; 11015b9c547cSRui Paulo 1102325151a3SRui Paulo return token; 11035b9c547cSRui Paulo } 11045b9c547cSRui Paulo 11055b9c547cSRui Paulo 11065b9c547cSRui Paulo size_t utf8_unescape(const char *inp, size_t in_size, 11075b9c547cSRui Paulo char *outp, size_t out_size) 11085b9c547cSRui Paulo { 11095b9c547cSRui Paulo size_t res_size = 0; 11105b9c547cSRui Paulo 11115b9c547cSRui Paulo if (!inp || !outp) 11125b9c547cSRui Paulo return 0; 11135b9c547cSRui Paulo 11145b9c547cSRui Paulo if (!in_size) 11155b9c547cSRui Paulo in_size = os_strlen(inp); 11165b9c547cSRui Paulo 11175b9c547cSRui Paulo /* Advance past leading single quote */ 11185b9c547cSRui Paulo if (*inp == '\'' && in_size) { 11195b9c547cSRui Paulo inp++; 11205b9c547cSRui Paulo in_size--; 11215b9c547cSRui Paulo } 11225b9c547cSRui Paulo 11234bc52338SCy Schubert while (in_size) { 11244bc52338SCy Schubert in_size--; 11255b9c547cSRui Paulo if (res_size >= out_size) 11265b9c547cSRui Paulo return 0; 11275b9c547cSRui Paulo 11285b9c547cSRui Paulo switch (*inp) { 11295b9c547cSRui Paulo case '\'': 11305b9c547cSRui Paulo /* Terminate on bare single quote */ 11315b9c547cSRui Paulo *outp = '\0'; 11325b9c547cSRui Paulo return res_size; 11335b9c547cSRui Paulo 11345b9c547cSRui Paulo case '\\': 11354bc52338SCy Schubert if (!in_size) 11365b9c547cSRui Paulo return 0; 11374bc52338SCy Schubert in_size--; 11385b9c547cSRui Paulo inp++; 11395b9c547cSRui Paulo /* fall through */ 11405b9c547cSRui Paulo 11415b9c547cSRui Paulo default: 11425b9c547cSRui Paulo *outp++ = *inp++; 11435b9c547cSRui Paulo res_size++; 11445b9c547cSRui Paulo } 11455b9c547cSRui Paulo } 11465b9c547cSRui Paulo 11475b9c547cSRui Paulo /* NUL terminate if space allows */ 11485b9c547cSRui Paulo if (res_size < out_size) 11495b9c547cSRui Paulo *outp = '\0'; 11505b9c547cSRui Paulo 11515b9c547cSRui Paulo return res_size; 11525b9c547cSRui Paulo } 11535b9c547cSRui Paulo 11545b9c547cSRui Paulo 11555b9c547cSRui Paulo size_t utf8_escape(const char *inp, size_t in_size, 11565b9c547cSRui Paulo char *outp, size_t out_size) 11575b9c547cSRui Paulo { 11585b9c547cSRui Paulo size_t res_size = 0; 11595b9c547cSRui Paulo 11605b9c547cSRui Paulo if (!inp || !outp) 11615b9c547cSRui Paulo return 0; 11625b9c547cSRui Paulo 11635b9c547cSRui Paulo /* inp may or may not be NUL terminated, but must be if 0 size 11645b9c547cSRui Paulo * is specified */ 11655b9c547cSRui Paulo if (!in_size) 11665b9c547cSRui Paulo in_size = os_strlen(inp); 11675b9c547cSRui Paulo 11684bc52338SCy Schubert while (in_size) { 11694bc52338SCy Schubert in_size--; 11705b9c547cSRui Paulo if (res_size++ >= out_size) 11715b9c547cSRui Paulo return 0; 11725b9c547cSRui Paulo 11735b9c547cSRui Paulo switch (*inp) { 11745b9c547cSRui Paulo case '\\': 11755b9c547cSRui Paulo case '\'': 11765b9c547cSRui Paulo if (res_size++ >= out_size) 11775b9c547cSRui Paulo return 0; 11785b9c547cSRui Paulo *outp++ = '\\'; 11795b9c547cSRui Paulo /* fall through */ 11805b9c547cSRui Paulo 11815b9c547cSRui Paulo default: 11825b9c547cSRui Paulo *outp++ = *inp++; 11835b9c547cSRui Paulo break; 11845b9c547cSRui Paulo } 11855b9c547cSRui Paulo } 11865b9c547cSRui Paulo 11875b9c547cSRui Paulo /* NUL terminate if space allows */ 11885b9c547cSRui Paulo if (res_size < out_size) 11895b9c547cSRui Paulo *outp = '\0'; 11905b9c547cSRui Paulo 11915b9c547cSRui Paulo return res_size; 11925b9c547cSRui Paulo } 1193325151a3SRui Paulo 1194325151a3SRui Paulo 1195325151a3SRui Paulo int is_ctrl_char(char c) 1196325151a3SRui Paulo { 1197325151a3SRui Paulo return c > 0 && c < 32; 1198325151a3SRui Paulo } 1199780fb4a2SCy Schubert 1200780fb4a2SCy Schubert 1201780fb4a2SCy Schubert /** 1202780fb4a2SCy Schubert * ssid_parse - Parse a string that contains SSID in hex or text format 1203780fb4a2SCy Schubert * @buf: Input NULL terminated string that contains the SSID 1204780fb4a2SCy Schubert * @ssid: Output SSID 1205780fb4a2SCy Schubert * Returns: 0 on success, -1 otherwise 1206780fb4a2SCy Schubert * 1207780fb4a2SCy Schubert * The SSID has to be enclosed in double quotes for the text format or space 1208780fb4a2SCy Schubert * or NULL terminated string of hex digits for the hex format. buf can include 1209780fb4a2SCy Schubert * additional arguments after the SSID. 1210780fb4a2SCy Schubert */ 1211780fb4a2SCy Schubert int ssid_parse(const char *buf, struct wpa_ssid_value *ssid) 1212780fb4a2SCy Schubert { 1213780fb4a2SCy Schubert char *tmp, *res, *end; 1214780fb4a2SCy Schubert size_t len; 1215780fb4a2SCy Schubert 1216780fb4a2SCy Schubert ssid->ssid_len = 0; 1217780fb4a2SCy Schubert 1218780fb4a2SCy Schubert tmp = os_strdup(buf); 1219780fb4a2SCy Schubert if (!tmp) 1220780fb4a2SCy Schubert return -1; 1221780fb4a2SCy Schubert 1222780fb4a2SCy Schubert if (*tmp != '"') { 1223780fb4a2SCy Schubert end = os_strchr(tmp, ' '); 1224780fb4a2SCy Schubert if (end) 1225780fb4a2SCy Schubert *end = '\0'; 1226780fb4a2SCy Schubert } else { 1227780fb4a2SCy Schubert end = os_strchr(tmp + 1, '"'); 1228780fb4a2SCy Schubert if (!end) { 1229780fb4a2SCy Schubert os_free(tmp); 1230780fb4a2SCy Schubert return -1; 1231780fb4a2SCy Schubert } 1232780fb4a2SCy Schubert 1233780fb4a2SCy Schubert end[1] = '\0'; 1234780fb4a2SCy Schubert } 1235780fb4a2SCy Schubert 1236780fb4a2SCy Schubert res = wpa_config_parse_string(tmp, &len); 1237780fb4a2SCy Schubert if (res && len <= SSID_MAX_LEN) { 1238780fb4a2SCy Schubert ssid->ssid_len = len; 1239780fb4a2SCy Schubert os_memcpy(ssid->ssid, res, len); 1240780fb4a2SCy Schubert } 1241780fb4a2SCy Schubert 1242780fb4a2SCy Schubert os_free(tmp); 1243780fb4a2SCy Schubert os_free(res); 1244780fb4a2SCy Schubert 1245780fb4a2SCy Schubert return ssid->ssid_len ? 0 : -1; 1246780fb4a2SCy Schubert } 1247780fb4a2SCy Schubert 1248780fb4a2SCy Schubert 1249780fb4a2SCy Schubert int str_starts(const char *str, const char *start) 1250780fb4a2SCy Schubert { 1251780fb4a2SCy Schubert return os_strncmp(str, start, os_strlen(start)) == 0; 1252780fb4a2SCy Schubert } 125385732ac8SCy Schubert 125485732ac8SCy Schubert 125585732ac8SCy Schubert /** 125685732ac8SCy Schubert * rssi_to_rcpi - Convert RSSI to RCPI 125785732ac8SCy Schubert * @rssi: RSSI to convert 125885732ac8SCy Schubert * Returns: RCPI corresponding to the given RSSI value, or 255 if not available. 125985732ac8SCy Schubert * 126085732ac8SCy Schubert * It's possible to estimate RCPI based on RSSI in dBm. This calculation will 126185732ac8SCy Schubert * not reflect the correct value for high rates, but it's good enough for Action 126285732ac8SCy Schubert * frames which are transmitted with up to 24 Mbps rates. 126385732ac8SCy Schubert */ 126485732ac8SCy Schubert u8 rssi_to_rcpi(int rssi) 126585732ac8SCy Schubert { 126685732ac8SCy Schubert if (!rssi) 126785732ac8SCy Schubert return 255; /* not available */ 126885732ac8SCy Schubert if (rssi < -110) 126985732ac8SCy Schubert return 0; 127085732ac8SCy Schubert if (rssi > 0) 127185732ac8SCy Schubert return 220; 127285732ac8SCy Schubert return (rssi + 110) * 2; 127385732ac8SCy Schubert } 12744bc52338SCy Schubert 12754bc52338SCy Schubert 12764bc52338SCy Schubert char * get_param(const char *cmd, const char *param) 12774bc52338SCy Schubert { 12784bc52338SCy Schubert const char *pos, *end; 12794bc52338SCy Schubert char *val; 12804bc52338SCy Schubert size_t len; 12814bc52338SCy Schubert 12824bc52338SCy Schubert pos = os_strstr(cmd, param); 12834bc52338SCy Schubert if (!pos) 12844bc52338SCy Schubert return NULL; 12854bc52338SCy Schubert 12864bc52338SCy Schubert pos += os_strlen(param); 12874bc52338SCy Schubert end = os_strchr(pos, ' '); 12884bc52338SCy Schubert if (end) 12894bc52338SCy Schubert len = end - pos; 12904bc52338SCy Schubert else 12914bc52338SCy Schubert len = os_strlen(pos); 12924bc52338SCy Schubert val = os_malloc(len + 1); 12934bc52338SCy Schubert if (!val) 12944bc52338SCy Schubert return NULL; 12954bc52338SCy Schubert os_memcpy(val, pos, len); 12964bc52338SCy Schubert val[len] = '\0'; 12974bc52338SCy Schubert return val; 12984bc52338SCy Schubert } 1299206b73d0SCy Schubert 1300206b73d0SCy Schubert 1301206b73d0SCy Schubert /* Try to prevent most compilers from optimizing out clearing of memory that 1302206b73d0SCy Schubert * becomes unaccessible after this function is called. This is mostly the case 1303206b73d0SCy Schubert * for clearing local stack variables at the end of a function. This is not 1304206b73d0SCy Schubert * exactly perfect, i.e., someone could come up with a compiler that figures out 1305206b73d0SCy Schubert * the pointer is pointing to memset and then end up optimizing the call out, so 1306206b73d0SCy Schubert * try go a bit further by storing the first octet (now zero) to make this even 1307206b73d0SCy Schubert * a bit more difficult to optimize out. Once memset_s() is available, that 1308206b73d0SCy Schubert * could be used here instead. */ 1309206b73d0SCy Schubert static void * (* const volatile memset_func)(void *, int, size_t) = memset; 1310206b73d0SCy Schubert static u8 forced_memzero_val; 1311206b73d0SCy Schubert 1312206b73d0SCy Schubert void forced_memzero(void *ptr, size_t len) 1313206b73d0SCy Schubert { 1314206b73d0SCy Schubert memset_func(ptr, 0, len); 1315206b73d0SCy Schubert if (len) 1316206b73d0SCy Schubert forced_memzero_val = ((u8 *) ptr)[0]; 1317206b73d0SCy Schubert } 1318