18dbcf02cSchristos /* 28dbcf02cSchristos * wpa_supplicant/hostapd / common helper functions, etc. 3460bb4fcSchristos * Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi> 48dbcf02cSchristos * 5e604d861Schristos * This software may be distributed under the terms of the BSD license. 6e604d861Schristos * See README for more details. 78dbcf02cSchristos */ 88dbcf02cSchristos 98dbcf02cSchristos #include "includes.h" 10*45d3cc13Schristos #include <limits.h> 118dbcf02cSchristos 12ecc36642Schristos #include "common/ieee802_11_defs.h" 138dbcf02cSchristos #include "common.h" 148dbcf02cSchristos 158dbcf02cSchristos 16*45d3cc13Schristos int hex2num(char c) 178dbcf02cSchristos { 188dbcf02cSchristos if (c >= '0' && c <= '9') 198dbcf02cSchristos return c - '0'; 208dbcf02cSchristos if (c >= 'a' && c <= 'f') 218dbcf02cSchristos return c - 'a' + 10; 228dbcf02cSchristos if (c >= 'A' && c <= 'F') 238dbcf02cSchristos return c - 'A' + 10; 248dbcf02cSchristos return -1; 258dbcf02cSchristos } 268dbcf02cSchristos 278dbcf02cSchristos 28111b9fd8Schristos int hex2byte(const char *hex) 298dbcf02cSchristos { 308dbcf02cSchristos int a, b; 318dbcf02cSchristos a = hex2num(*hex++); 328dbcf02cSchristos if (a < 0) 338dbcf02cSchristos return -1; 348dbcf02cSchristos b = hex2num(*hex++); 358dbcf02cSchristos if (b < 0) 368dbcf02cSchristos return -1; 378dbcf02cSchristos return (a << 4) | b; 388dbcf02cSchristos } 398dbcf02cSchristos 408dbcf02cSchristos 41bb610346Schristos static const char * hwaddr_parse(const char *txt, u8 *addr) 42bb610346Schristos { 43bb610346Schristos size_t i; 44bb610346Schristos 45bb610346Schristos for (i = 0; i < ETH_ALEN; i++) { 46bb610346Schristos int a; 47bb610346Schristos 48bb610346Schristos a = hex2byte(txt); 49bb610346Schristos if (a < 0) 50bb610346Schristos return NULL; 51bb610346Schristos txt += 2; 52bb610346Schristos addr[i] = a; 53bb610346Schristos if (i < ETH_ALEN - 1 && *txt++ != ':') 54bb610346Schristos return NULL; 55bb610346Schristos } 56bb610346Schristos return txt; 57bb610346Schristos } 58bb610346Schristos 59bb610346Schristos 608dbcf02cSchristos /** 618dbcf02cSchristos * hwaddr_aton - Convert ASCII string to MAC address (colon-delimited format) 628dbcf02cSchristos * @txt: MAC address as a string (e.g., "00:11:22:33:44:55") 638dbcf02cSchristos * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) 648dbcf02cSchristos * Returns: 0 on success, -1 on failure (e.g., string not a MAC address) 658dbcf02cSchristos */ 668dbcf02cSchristos int hwaddr_aton(const char *txt, u8 *addr) 678dbcf02cSchristos { 68bb610346Schristos return hwaddr_parse(txt, addr) ? 0 : -1; 69bb610346Schristos } 708dbcf02cSchristos 718dbcf02cSchristos 72bb610346Schristos /** 73bb610346Schristos * hwaddr_masked_aton - Convert ASCII string with optional mask to MAC address (colon-delimited format) 74bb610346Schristos * @txt: MAC address with optional mask as a string (e.g., "00:11:22:33:44:55/ff:ff:ff:ff:00:00") 75bb610346Schristos * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) 76bb610346Schristos * @mask: Buffer for the MAC address mask (ETH_ALEN = 6 bytes) 77bb610346Schristos * @maskable: Flag to indicate whether a mask is allowed 78bb610346Schristos * Returns: 0 on success, -1 on failure (e.g., string not a MAC address) 79bb610346Schristos */ 80bb610346Schristos int hwaddr_masked_aton(const char *txt, u8 *addr, u8 *mask, u8 maskable) 81bb610346Schristos { 82bb610346Schristos const char *r; 83bb610346Schristos 84bb610346Schristos /* parse address part */ 85bb610346Schristos r = hwaddr_parse(txt, addr); 86bb610346Schristos if (!r) 878dbcf02cSchristos return -1; 88bb610346Schristos 89bb610346Schristos /* check for optional mask */ 90ecc36642Schristos if (*r == '\0' || isspace((unsigned char) *r)) { 91bb610346Schristos /* no mask specified, assume default */ 92bb610346Schristos os_memset(mask, 0xff, ETH_ALEN); 93bb610346Schristos } else if (maskable && *r == '/') { 94bb610346Schristos /* mask specified and allowed */ 95bb610346Schristos r = hwaddr_parse(r + 1, mask); 96bb610346Schristos /* parser error? */ 97bb610346Schristos if (!r) 988dbcf02cSchristos return -1; 99bb610346Schristos } else { 100bb610346Schristos /* mask specified but not allowed or trailing garbage */ 1018dbcf02cSchristos return -1; 1028dbcf02cSchristos } 1038dbcf02cSchristos 1048dbcf02cSchristos return 0; 1058dbcf02cSchristos } 1068dbcf02cSchristos 107bb610346Schristos 108111b9fd8Schristos /** 109111b9fd8Schristos * hwaddr_compact_aton - Convert ASCII string to MAC address (no colon delimitors format) 110111b9fd8Schristos * @txt: MAC address as a string (e.g., "001122334455") 111111b9fd8Schristos * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) 112111b9fd8Schristos * Returns: 0 on success, -1 on failure (e.g., string not a MAC address) 113111b9fd8Schristos */ 114111b9fd8Schristos int hwaddr_compact_aton(const char *txt, u8 *addr) 115111b9fd8Schristos { 116111b9fd8Schristos int i; 117111b9fd8Schristos 118111b9fd8Schristos for (i = 0; i < 6; i++) { 119111b9fd8Schristos int a, b; 120111b9fd8Schristos 121111b9fd8Schristos a = hex2num(*txt++); 122111b9fd8Schristos if (a < 0) 123111b9fd8Schristos return -1; 124111b9fd8Schristos b = hex2num(*txt++); 125111b9fd8Schristos if (b < 0) 126111b9fd8Schristos return -1; 127111b9fd8Schristos *addr++ = (a << 4) | b; 128111b9fd8Schristos } 129111b9fd8Schristos 130111b9fd8Schristos return 0; 131111b9fd8Schristos } 1328dbcf02cSchristos 1338dbcf02cSchristos /** 1348dbcf02cSchristos * hwaddr_aton2 - Convert ASCII string to MAC address (in any known format) 1358dbcf02cSchristos * @txt: MAC address as a string (e.g., 00:11:22:33:44:55 or 0011.2233.4455) 1368dbcf02cSchristos * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) 1378dbcf02cSchristos * Returns: Characters used (> 0) on success, -1 on failure 1388dbcf02cSchristos */ 1398dbcf02cSchristos int hwaddr_aton2(const char *txt, u8 *addr) 1408dbcf02cSchristos { 1418dbcf02cSchristos int i; 1428dbcf02cSchristos const char *pos = txt; 1438dbcf02cSchristos 1448dbcf02cSchristos for (i = 0; i < 6; i++) { 1458dbcf02cSchristos int a, b; 1468dbcf02cSchristos 1478dbcf02cSchristos while (*pos == ':' || *pos == '.' || *pos == '-') 1488dbcf02cSchristos pos++; 1498dbcf02cSchristos 1508dbcf02cSchristos a = hex2num(*pos++); 1518dbcf02cSchristos if (a < 0) 1528dbcf02cSchristos return -1; 1538dbcf02cSchristos b = hex2num(*pos++); 1548dbcf02cSchristos if (b < 0) 1558dbcf02cSchristos return -1; 1568dbcf02cSchristos *addr++ = (a << 4) | b; 1578dbcf02cSchristos } 1588dbcf02cSchristos 1598dbcf02cSchristos return pos - txt; 1608dbcf02cSchristos } 1618dbcf02cSchristos 1628dbcf02cSchristos 1638dbcf02cSchristos /** 1648dbcf02cSchristos * hexstr2bin - Convert ASCII hex string into binary data 1658dbcf02cSchristos * @hex: ASCII hex string (e.g., "01ab") 1668dbcf02cSchristos * @buf: Buffer for the binary data 1678dbcf02cSchristos * @len: Length of the text to convert in bytes (of buf); hex will be double 1688dbcf02cSchristos * this size 1698dbcf02cSchristos * Returns: 0 on success, -1 on failure (invalid hex string) 1708dbcf02cSchristos */ 1718dbcf02cSchristos int hexstr2bin(const char *hex, u8 *buf, size_t len) 1728dbcf02cSchristos { 1738dbcf02cSchristos size_t i; 1748dbcf02cSchristos int a; 1758dbcf02cSchristos const char *ipos = hex; 1768dbcf02cSchristos u8 *opos = buf; 1778dbcf02cSchristos 1788dbcf02cSchristos for (i = 0; i < len; i++) { 1798dbcf02cSchristos a = hex2byte(ipos); 1808dbcf02cSchristos if (a < 0) 1818dbcf02cSchristos return -1; 1828dbcf02cSchristos *opos++ = a; 1838dbcf02cSchristos ipos += 2; 1848dbcf02cSchristos } 1858dbcf02cSchristos return 0; 1868dbcf02cSchristos } 1878dbcf02cSchristos 1888dbcf02cSchristos 189bb610346Schristos int hwaddr_mask_txt(char *buf, size_t len, const u8 *addr, const u8 *mask) 190bb610346Schristos { 191bb610346Schristos size_t i; 192bb610346Schristos int print_mask = 0; 193bb610346Schristos int res; 194bb610346Schristos 195bb610346Schristos for (i = 0; i < ETH_ALEN; i++) { 196bb610346Schristos if (mask[i] != 0xff) { 197bb610346Schristos print_mask = 1; 198bb610346Schristos break; 199bb610346Schristos } 200bb610346Schristos } 201bb610346Schristos 202bb610346Schristos if (print_mask) 203bb610346Schristos res = os_snprintf(buf, len, MACSTR "/" MACSTR, 204bb610346Schristos MAC2STR(addr), MAC2STR(mask)); 205bb610346Schristos else 206bb610346Schristos res = os_snprintf(buf, len, MACSTR, MAC2STR(addr)); 207bb610346Schristos if (os_snprintf_error(len, res)) 208bb610346Schristos return -1; 209bb610346Schristos return res; 210bb610346Schristos } 211bb610346Schristos 212bb610346Schristos 2138dbcf02cSchristos /** 2148dbcf02cSchristos * inc_byte_array - Increment arbitrary length byte array by one 2158dbcf02cSchristos * @counter: Pointer to byte array 2168dbcf02cSchristos * @len: Length of the counter in bytes 2178dbcf02cSchristos * 2188dbcf02cSchristos * This function increments the last byte of the counter by one and continues 2198dbcf02cSchristos * rolling over to more significant bytes if the byte was incremented from 2208dbcf02cSchristos * 0xff to 0x00. 2218dbcf02cSchristos */ 2228dbcf02cSchristos void inc_byte_array(u8 *counter, size_t len) 2238dbcf02cSchristos { 2248dbcf02cSchristos int pos = len - 1; 2258dbcf02cSchristos while (pos >= 0) { 2268dbcf02cSchristos counter[pos]++; 2278dbcf02cSchristos if (counter[pos] != 0) 2288dbcf02cSchristos break; 2298dbcf02cSchristos pos--; 2308dbcf02cSchristos } 2318dbcf02cSchristos } 2328dbcf02cSchristos 2338dbcf02cSchristos 234460bb4fcSchristos void buf_shift_right(u8 *buf, size_t len, size_t bits) 235460bb4fcSchristos { 236460bb4fcSchristos size_t i; 237460bb4fcSchristos 238460bb4fcSchristos for (i = len - 1; i > 0; i--) 239460bb4fcSchristos buf[i] = (buf[i - 1] << (8 - bits)) | (buf[i] >> bits); 240460bb4fcSchristos buf[0] >>= bits; 241460bb4fcSchristos } 242460bb4fcSchristos 243460bb4fcSchristos 2448dbcf02cSchristos void wpa_get_ntp_timestamp(u8 *buf) 2458dbcf02cSchristos { 2468dbcf02cSchristos struct os_time now; 2478dbcf02cSchristos u32 sec, usec; 2488dbcf02cSchristos be32 tmp; 2498dbcf02cSchristos 2508dbcf02cSchristos /* 64-bit NTP timestamp (time from 1900-01-01 00:00:00) */ 2518dbcf02cSchristos os_get_time(&now); 2528dbcf02cSchristos sec = now.sec + 2208988800U; /* Epoch to 1900 */ 2538dbcf02cSchristos /* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */ 2548dbcf02cSchristos usec = now.usec; 2558dbcf02cSchristos usec = 4295 * usec - (usec >> 5) - (usec >> 9); 2568dbcf02cSchristos tmp = host_to_be32(sec); 2578dbcf02cSchristos os_memcpy(buf, (u8 *) &tmp, 4); 2588dbcf02cSchristos tmp = host_to_be32(usec); 2598dbcf02cSchristos os_memcpy(buf + 4, (u8 *) &tmp, 4); 2608dbcf02cSchristos } 2618dbcf02cSchristos 262bb610346Schristos /** 263bb610346Schristos * wpa_scnprintf - Simpler-to-use snprintf function 264bb610346Schristos * @buf: Output buffer 265bb610346Schristos * @size: Buffer size 266bb610346Schristos * @fmt: format 267bb610346Schristos * 268bb610346Schristos * Simpler snprintf version that doesn't require further error checks - the 269bb610346Schristos * return value only indicates how many bytes were actually written, excluding 270bb610346Schristos * the NULL byte (i.e., 0 on error, size-1 if buffer is not big enough). 271bb610346Schristos */ 272bb610346Schristos int wpa_scnprintf(char *buf, size_t size, const char *fmt, ...) 273bb610346Schristos { 274bb610346Schristos va_list ap; 275bb610346Schristos int ret; 276bb610346Schristos 277bb610346Schristos if (!size) 278bb610346Schristos return 0; 279bb610346Schristos 280bb610346Schristos va_start(ap, fmt); 281bb610346Schristos ret = vsnprintf(buf, size, fmt, ap); 282bb610346Schristos va_end(ap); 283bb610346Schristos 284bb610346Schristos if (ret < 0) 285bb610346Schristos return 0; 286bb610346Schristos if ((size_t) ret >= size) 287bb610346Schristos return size - 1; 288bb610346Schristos 289bb610346Schristos return ret; 290bb610346Schristos } 2918dbcf02cSchristos 292ecc36642Schristos 293ecc36642Schristos int wpa_snprintf_hex_sep(char *buf, size_t buf_size, const u8 *data, size_t len, 294ecc36642Schristos char sep) 295ecc36642Schristos { 296ecc36642Schristos size_t i; 297ecc36642Schristos char *pos = buf, *end = buf + buf_size; 298ecc36642Schristos int ret; 299ecc36642Schristos 300ecc36642Schristos if (buf_size == 0) 301ecc36642Schristos return 0; 302ecc36642Schristos 303ecc36642Schristos for (i = 0; i < len; i++) { 304ecc36642Schristos ret = os_snprintf(pos, end - pos, "%02x%c", 305ecc36642Schristos data[i], sep); 306ecc36642Schristos if (os_snprintf_error(end - pos, ret)) { 307ecc36642Schristos end[-1] = '\0'; 308ecc36642Schristos return pos - buf; 309ecc36642Schristos } 310ecc36642Schristos pos += ret; 311ecc36642Schristos } 312ecc36642Schristos pos[-1] = '\0'; 313ecc36642Schristos return pos - buf; 314ecc36642Schristos } 315ecc36642Schristos 316ecc36642Schristos 3178dbcf02cSchristos static inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, 3188dbcf02cSchristos size_t len, int uppercase) 3198dbcf02cSchristos { 3208dbcf02cSchristos size_t i; 3218dbcf02cSchristos char *pos = buf, *end = buf + buf_size; 3228dbcf02cSchristos int ret; 3238dbcf02cSchristos if (buf_size == 0) 3248dbcf02cSchristos return 0; 3258dbcf02cSchristos for (i = 0; i < len; i++) { 3268dbcf02cSchristos ret = os_snprintf(pos, end - pos, uppercase ? "%02X" : "%02x", 3278dbcf02cSchristos data[i]); 328bb610346Schristos if (os_snprintf_error(end - pos, ret)) { 3298dbcf02cSchristos end[-1] = '\0'; 3308dbcf02cSchristos return pos - buf; 3318dbcf02cSchristos } 3328dbcf02cSchristos pos += ret; 3338dbcf02cSchristos } 3348dbcf02cSchristos end[-1] = '\0'; 3358dbcf02cSchristos return pos - buf; 3368dbcf02cSchristos } 3378dbcf02cSchristos 3388dbcf02cSchristos /** 3398dbcf02cSchristos * wpa_snprintf_hex - Print data as a hex string into a buffer 3408dbcf02cSchristos * @buf: Memory area to use as the output buffer 3418dbcf02cSchristos * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1) 3428dbcf02cSchristos * @data: Data to be printed 3438dbcf02cSchristos * @len: Length of data in bytes 3448dbcf02cSchristos * Returns: Number of bytes written 3458dbcf02cSchristos */ 3468dbcf02cSchristos int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len) 3478dbcf02cSchristos { 3488dbcf02cSchristos return _wpa_snprintf_hex(buf, buf_size, data, len, 0); 3498dbcf02cSchristos } 3508dbcf02cSchristos 3518dbcf02cSchristos 3528dbcf02cSchristos /** 3538dbcf02cSchristos * wpa_snprintf_hex_uppercase - Print data as a upper case hex string into buf 3548dbcf02cSchristos * @buf: Memory area to use as the output buffer 3558dbcf02cSchristos * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1) 3568dbcf02cSchristos * @data: Data to be printed 3578dbcf02cSchristos * @len: Length of data in bytes 3588dbcf02cSchristos * Returns: Number of bytes written 3598dbcf02cSchristos */ 3608dbcf02cSchristos int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data, 3618dbcf02cSchristos size_t len) 3628dbcf02cSchristos { 3638dbcf02cSchristos return _wpa_snprintf_hex(buf, buf_size, data, len, 1); 3648dbcf02cSchristos } 3658dbcf02cSchristos 3668dbcf02cSchristos 3678dbcf02cSchristos #ifdef CONFIG_ANSI_C_EXTRA 3688dbcf02cSchristos 3698dbcf02cSchristos #ifdef _WIN32_WCE 3708dbcf02cSchristos void perror(const char *s) 3718dbcf02cSchristos { 3728dbcf02cSchristos wpa_printf(MSG_ERROR, "%s: GetLastError: %d", 3738dbcf02cSchristos s, (int) GetLastError()); 3748dbcf02cSchristos } 3758dbcf02cSchristos #endif /* _WIN32_WCE */ 3768dbcf02cSchristos 3778dbcf02cSchristos 3788dbcf02cSchristos int optind = 1; 3798dbcf02cSchristos int optopt; 3808dbcf02cSchristos char *optarg; 3818dbcf02cSchristos 3828dbcf02cSchristos int getopt(int argc, char *const argv[], const char *optstring) 3838dbcf02cSchristos { 3848dbcf02cSchristos static int optchr = 1; 3858dbcf02cSchristos char *cp; 3868dbcf02cSchristos 3878dbcf02cSchristos if (optchr == 1) { 3888dbcf02cSchristos if (optind >= argc) { 3898dbcf02cSchristos /* all arguments processed */ 3908dbcf02cSchristos return EOF; 3918dbcf02cSchristos } 3928dbcf02cSchristos 3938dbcf02cSchristos if (argv[optind][0] != '-' || argv[optind][1] == '\0') { 3948dbcf02cSchristos /* no option characters */ 3958dbcf02cSchristos return EOF; 3968dbcf02cSchristos } 3978dbcf02cSchristos } 3988dbcf02cSchristos 3998dbcf02cSchristos if (os_strcmp(argv[optind], "--") == 0) { 4008dbcf02cSchristos /* no more options */ 4018dbcf02cSchristos optind++; 4028dbcf02cSchristos return EOF; 4038dbcf02cSchristos } 4048dbcf02cSchristos 4058dbcf02cSchristos optopt = argv[optind][optchr]; 4068dbcf02cSchristos cp = os_strchr(optstring, optopt); 4078dbcf02cSchristos if (cp == NULL || optopt == ':') { 4088dbcf02cSchristos if (argv[optind][++optchr] == '\0') { 4098dbcf02cSchristos optchr = 1; 4108dbcf02cSchristos optind++; 4118dbcf02cSchristos } 4128dbcf02cSchristos return '?'; 4138dbcf02cSchristos } 4148dbcf02cSchristos 4158dbcf02cSchristos if (cp[1] == ':') { 4168dbcf02cSchristos /* Argument required */ 4178dbcf02cSchristos optchr = 1; 4188dbcf02cSchristos if (argv[optind][optchr + 1]) { 4198dbcf02cSchristos /* No space between option and argument */ 4208dbcf02cSchristos optarg = &argv[optind++][optchr + 1]; 4218dbcf02cSchristos } else if (++optind >= argc) { 4228dbcf02cSchristos /* option requires an argument */ 4238dbcf02cSchristos return '?'; 4248dbcf02cSchristos } else { 4258dbcf02cSchristos /* Argument in the next argv */ 4268dbcf02cSchristos optarg = argv[optind++]; 4278dbcf02cSchristos } 4288dbcf02cSchristos } else { 4298dbcf02cSchristos /* No argument */ 4308dbcf02cSchristos if (argv[optind][++optchr] == '\0') { 4318dbcf02cSchristos optchr = 1; 4328dbcf02cSchristos optind++; 4338dbcf02cSchristos } 4348dbcf02cSchristos optarg = NULL; 4358dbcf02cSchristos } 4368dbcf02cSchristos return *cp; 4378dbcf02cSchristos } 4388dbcf02cSchristos #endif /* CONFIG_ANSI_C_EXTRA */ 4398dbcf02cSchristos 4408dbcf02cSchristos 4418dbcf02cSchristos #ifdef CONFIG_NATIVE_WINDOWS 4428dbcf02cSchristos /** 4438dbcf02cSchristos * wpa_unicode2ascii_inplace - Convert unicode string into ASCII 4448dbcf02cSchristos * @str: Pointer to string to convert 4458dbcf02cSchristos * 4468dbcf02cSchristos * This function converts a unicode string to ASCII using the same 4478dbcf02cSchristos * buffer for output. If UNICODE is not set, the buffer is not 4488dbcf02cSchristos * modified. 4498dbcf02cSchristos */ 4508dbcf02cSchristos void wpa_unicode2ascii_inplace(TCHAR *str) 4518dbcf02cSchristos { 4528dbcf02cSchristos #ifdef UNICODE 4538dbcf02cSchristos char *dst = (char *) str; 4548dbcf02cSchristos while (*str) 4558dbcf02cSchristos *dst++ = (char) *str++; 4568dbcf02cSchristos *dst = '\0'; 4578dbcf02cSchristos #endif /* UNICODE */ 4588dbcf02cSchristos } 4598dbcf02cSchristos 4608dbcf02cSchristos 4618dbcf02cSchristos TCHAR * wpa_strdup_tchar(const char *str) 4628dbcf02cSchristos { 4638dbcf02cSchristos #ifdef UNICODE 4648dbcf02cSchristos TCHAR *buf; 4658dbcf02cSchristos buf = os_malloc((strlen(str) + 1) * sizeof(TCHAR)); 4668dbcf02cSchristos if (buf == NULL) 4678dbcf02cSchristos return NULL; 4688dbcf02cSchristos wsprintf(buf, L"%S", str); 4698dbcf02cSchristos return buf; 4708dbcf02cSchristos #else /* UNICODE */ 4718dbcf02cSchristos return os_strdup(str); 4728dbcf02cSchristos #endif /* UNICODE */ 4738dbcf02cSchristos } 4748dbcf02cSchristos #endif /* CONFIG_NATIVE_WINDOWS */ 4758dbcf02cSchristos 4768dbcf02cSchristos 477e604d861Schristos void printf_encode(char *txt, size_t maxlen, const u8 *data, size_t len) 478e604d861Schristos { 479e604d861Schristos char *end = txt + maxlen; 480e604d861Schristos size_t i; 481e604d861Schristos 482e604d861Schristos for (i = 0; i < len; i++) { 4833c260e60Schristos if (txt + 4 >= end) 484e604d861Schristos break; 485e604d861Schristos 486e604d861Schristos switch (data[i]) { 487e604d861Schristos case '\"': 488e604d861Schristos *txt++ = '\\'; 489e604d861Schristos *txt++ = '\"'; 490e604d861Schristos break; 491e604d861Schristos case '\\': 492e604d861Schristos *txt++ = '\\'; 493e604d861Schristos *txt++ = '\\'; 494e604d861Schristos break; 4953c260e60Schristos case '\033': 496e604d861Schristos *txt++ = '\\'; 497e604d861Schristos *txt++ = 'e'; 498e604d861Schristos break; 499e604d861Schristos case '\n': 500e604d861Schristos *txt++ = '\\'; 501e604d861Schristos *txt++ = 'n'; 502e604d861Schristos break; 503e604d861Schristos case '\r': 504e604d861Schristos *txt++ = '\\'; 505e604d861Schristos *txt++ = 'r'; 506e604d861Schristos break; 507e604d861Schristos case '\t': 508e604d861Schristos *txt++ = '\\'; 509e604d861Schristos *txt++ = 't'; 510e604d861Schristos break; 511e604d861Schristos default: 512ecc36642Schristos if (data[i] >= 32 && data[i] <= 126) { 513e604d861Schristos *txt++ = data[i]; 514e604d861Schristos } else { 515e604d861Schristos txt += os_snprintf(txt, end - txt, "\\x%02x", 516e604d861Schristos data[i]); 517e604d861Schristos } 518e604d861Schristos break; 519e604d861Schristos } 520e604d861Schristos } 521e604d861Schristos 522e604d861Schristos *txt = '\0'; 523e604d861Schristos } 524e604d861Schristos 525e604d861Schristos 526e604d861Schristos size_t printf_decode(u8 *buf, size_t maxlen, const char *str) 527e604d861Schristos { 528e604d861Schristos const char *pos = str; 529e604d861Schristos size_t len = 0; 530e604d861Schristos int val; 531e604d861Schristos 532e604d861Schristos while (*pos) { 5333c260e60Schristos if (len + 1 >= maxlen) 534e604d861Schristos break; 535e604d861Schristos switch (*pos) { 536e604d861Schristos case '\\': 537e604d861Schristos pos++; 538e604d861Schristos switch (*pos) { 539e604d861Schristos case '\\': 540e604d861Schristos buf[len++] = '\\'; 541e604d861Schristos pos++; 542e604d861Schristos break; 543e604d861Schristos case '"': 544e604d861Schristos buf[len++] = '"'; 545e604d861Schristos pos++; 546e604d861Schristos break; 547e604d861Schristos case 'n': 548e604d861Schristos buf[len++] = '\n'; 549e604d861Schristos pos++; 550e604d861Schristos break; 551e604d861Schristos case 'r': 552e604d861Schristos buf[len++] = '\r'; 553e604d861Schristos pos++; 554e604d861Schristos break; 555e604d861Schristos case 't': 556e604d861Schristos buf[len++] = '\t'; 557e604d861Schristos pos++; 558e604d861Schristos break; 559e604d861Schristos case 'e': 5603c260e60Schristos buf[len++] = '\033'; 561e604d861Schristos pos++; 562e604d861Schristos break; 563e604d861Schristos case 'x': 564e604d861Schristos pos++; 565e604d861Schristos val = hex2byte(pos); 566e604d861Schristos if (val < 0) { 567e604d861Schristos val = hex2num(*pos); 568e604d861Schristos if (val < 0) 569e604d861Schristos break; 570e604d861Schristos buf[len++] = val; 571e604d861Schristos pos++; 572e604d861Schristos } else { 573e604d861Schristos buf[len++] = val; 574e604d861Schristos pos += 2; 575e604d861Schristos } 576e604d861Schristos break; 577e604d861Schristos case '0': 578e604d861Schristos case '1': 579e604d861Schristos case '2': 580e604d861Schristos case '3': 581e604d861Schristos case '4': 582e604d861Schristos case '5': 583e604d861Schristos case '6': 584e604d861Schristos case '7': 585e604d861Schristos val = *pos++ - '0'; 586e604d861Schristos if (*pos >= '0' && *pos <= '7') 587e604d861Schristos val = val * 8 + (*pos++ - '0'); 588e604d861Schristos if (*pos >= '0' && *pos <= '7') 589e604d861Schristos val = val * 8 + (*pos++ - '0'); 590e604d861Schristos buf[len++] = val; 591e604d861Schristos break; 592e604d861Schristos default: 593e604d861Schristos break; 594e604d861Schristos } 595e604d861Schristos break; 596e604d861Schristos default: 597e604d861Schristos buf[len++] = *pos++; 598e604d861Schristos break; 599e604d861Schristos } 600e604d861Schristos } 6013c260e60Schristos if (maxlen > len) 6023c260e60Schristos buf[len] = '\0'; 603e604d861Schristos 604e604d861Schristos return len; 605e604d861Schristos } 606e604d861Schristos 607e604d861Schristos 6088dbcf02cSchristos /** 6098dbcf02cSchristos * wpa_ssid_txt - Convert SSID to a printable string 6108dbcf02cSchristos * @ssid: SSID (32-octet string) 6118dbcf02cSchristos * @ssid_len: Length of ssid in octets 6128dbcf02cSchristos * Returns: Pointer to a printable string 6138dbcf02cSchristos * 6148dbcf02cSchristos * This function can be used to convert SSIDs into printable form. In most 6158dbcf02cSchristos * cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard 6168dbcf02cSchristos * does not limit the used character set, so anything could be used in an SSID. 6178dbcf02cSchristos * 6188dbcf02cSchristos * This function uses a static buffer, so only one call can be used at the 6198dbcf02cSchristos * time, i.e., this is not re-entrant and the returned buffer must be used 6208dbcf02cSchristos * before calling this again. 6218dbcf02cSchristos */ 6228dbcf02cSchristos const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len) 6238dbcf02cSchristos { 624ecc36642Schristos static char ssid_txt[SSID_MAX_LEN * 4 + 1]; 6258dbcf02cSchristos 626e604d861Schristos if (ssid == NULL) { 627e604d861Schristos ssid_txt[0] = '\0'; 628e604d861Schristos return ssid_txt; 6298dbcf02cSchristos } 630e604d861Schristos 631e604d861Schristos printf_encode(ssid_txt, sizeof(ssid_txt), ssid, ssid_len); 6328dbcf02cSchristos return ssid_txt; 6338dbcf02cSchristos } 6348dbcf02cSchristos 6358dbcf02cSchristos 6368dbcf02cSchristos void * __hide_aliasing_typecast(void *foo) 6378dbcf02cSchristos { 6388dbcf02cSchristos return foo; 6398dbcf02cSchristos } 640e604d861Schristos 641e604d861Schristos 642e604d861Schristos char * wpa_config_parse_string(const char *value, size_t *len) 643e604d861Schristos { 644e604d861Schristos if (*value == '"') { 645e604d861Schristos const char *pos; 646e604d861Schristos char *str; 647e604d861Schristos value++; 648e604d861Schristos pos = os_strrchr(value, '"'); 649e604d861Schristos if (pos == NULL || pos[1] != '\0') 650e604d861Schristos return NULL; 651e604d861Schristos *len = pos - value; 6523c260e60Schristos str = dup_binstr(value, *len); 653e604d861Schristos if (str == NULL) 654e604d861Schristos return NULL; 655e604d861Schristos return str; 656e604d861Schristos } else if (*value == 'P' && value[1] == '"') { 657e604d861Schristos const char *pos; 658e604d861Schristos char *tstr, *str; 659e604d861Schristos size_t tlen; 660e604d861Schristos value += 2; 661e604d861Schristos pos = os_strrchr(value, '"'); 662e604d861Schristos if (pos == NULL || pos[1] != '\0') 663e604d861Schristos return NULL; 664e604d861Schristos tlen = pos - value; 6653c260e60Schristos tstr = dup_binstr(value, tlen); 666e604d861Schristos if (tstr == NULL) 667e604d861Schristos return NULL; 668e604d861Schristos 669e604d861Schristos str = os_malloc(tlen + 1); 670e604d861Schristos if (str == NULL) { 671e604d861Schristos os_free(tstr); 672e604d861Schristos return NULL; 673e604d861Schristos } 674e604d861Schristos 675e604d861Schristos *len = printf_decode((u8 *) str, tlen + 1, tstr); 676e604d861Schristos os_free(tstr); 677e604d861Schristos 678e604d861Schristos return str; 679e604d861Schristos } else { 680e604d861Schristos u8 *str; 681e604d861Schristos size_t tlen, hlen = os_strlen(value); 682e604d861Schristos if (hlen & 1) 683e604d861Schristos return NULL; 684e604d861Schristos tlen = hlen / 2; 685e604d861Schristos str = os_malloc(tlen + 1); 686e604d861Schristos if (str == NULL) 687e604d861Schristos return NULL; 688e604d861Schristos if (hexstr2bin(value, str, tlen)) { 689e604d861Schristos os_free(str); 690e604d861Schristos return NULL; 691e604d861Schristos } 692e604d861Schristos str[tlen] = '\0'; 693e604d861Schristos *len = tlen; 694e604d861Schristos return (char *) str; 695e604d861Schristos } 696e604d861Schristos } 697e604d861Schristos 698e604d861Schristos 699e604d861Schristos int is_hex(const u8 *data, size_t len) 700e604d861Schristos { 701e604d861Schristos size_t i; 702e604d861Schristos 703e604d861Schristos for (i = 0; i < len; i++) { 704e604d861Schristos if (data[i] < 32 || data[i] >= 127) 705e604d861Schristos return 1; 706e604d861Schristos } 707e604d861Schristos return 0; 708e604d861Schristos } 709e604d861Schristos 710e604d861Schristos 7117d146f42Schristos int has_ctrl_char(const u8 *data, size_t len) 7127d146f42Schristos { 7137d146f42Schristos size_t i; 7147d146f42Schristos 7157d146f42Schristos for (i = 0; i < len; i++) { 7167d146f42Schristos if (data[i] < 32 || data[i] == 127) 7177d146f42Schristos return 1; 7187d146f42Schristos } 7197d146f42Schristos return 0; 7207d146f42Schristos } 7217d146f42Schristos 7227d146f42Schristos 7239f37edd8Schristos int has_newline(const char *str) 7249f37edd8Schristos { 7259f37edd8Schristos while (*str) { 7269f37edd8Schristos if (*str == '\n' || *str == '\r') 7279f37edd8Schristos return 1; 7289f37edd8Schristos str++; 7299f37edd8Schristos } 7309f37edd8Schristos return 0; 7319f37edd8Schristos } 7329f37edd8Schristos 7339f37edd8Schristos 734e604d861Schristos size_t merge_byte_arrays(u8 *res, size_t res_len, 735e604d861Schristos const u8 *src1, size_t src1_len, 736e604d861Schristos const u8 *src2, size_t src2_len) 737e604d861Schristos { 738e604d861Schristos size_t len = 0; 739e604d861Schristos 740e604d861Schristos os_memset(res, 0, res_len); 741e604d861Schristos 742e604d861Schristos if (src1) { 743e604d861Schristos if (src1_len >= res_len) { 744e604d861Schristos os_memcpy(res, src1, res_len); 745e604d861Schristos return res_len; 746e604d861Schristos } 747e604d861Schristos 748e604d861Schristos os_memcpy(res, src1, src1_len); 749e604d861Schristos len += src1_len; 750e604d861Schristos } 751e604d861Schristos 752e604d861Schristos if (src2) { 753e604d861Schristos if (len + src2_len >= res_len) { 754e604d861Schristos os_memcpy(res + len, src2, res_len - len); 755e604d861Schristos return res_len; 756e604d861Schristos } 757e604d861Schristos 758e604d861Schristos os_memcpy(res + len, src2, src2_len); 759e604d861Schristos len += src2_len; 760e604d861Schristos } 761e604d861Schristos 762e604d861Schristos return len; 763e604d861Schristos } 7643c260e60Schristos 7653c260e60Schristos 7663c260e60Schristos char * dup_binstr(const void *src, size_t len) 7673c260e60Schristos { 7683c260e60Schristos char *res; 7693c260e60Schristos 7703c260e60Schristos if (src == NULL) 7713c260e60Schristos return NULL; 7723c260e60Schristos res = os_malloc(len + 1); 7733c260e60Schristos if (res == NULL) 7743c260e60Schristos return NULL; 7753c260e60Schristos os_memcpy(res, src, len); 7763c260e60Schristos res[len] = '\0'; 7773c260e60Schristos 7783c260e60Schristos return res; 7793c260e60Schristos } 7803c260e60Schristos 7813c260e60Schristos 7823c260e60Schristos int freq_range_list_parse(struct wpa_freq_range_list *res, const char *value) 7833c260e60Schristos { 7843c260e60Schristos struct wpa_freq_range *freq = NULL, *n; 7853c260e60Schristos unsigned int count = 0; 7863c260e60Schristos const char *pos, *pos2, *pos3; 7873c260e60Schristos 7883c260e60Schristos /* 7893c260e60Schristos * Comma separated list of frequency ranges. 7903c260e60Schristos * For example: 2412-2432,2462,5000-6000 7913c260e60Schristos */ 7923c260e60Schristos pos = value; 7933c260e60Schristos while (pos && pos[0]) { 794*45d3cc13Schristos if (count == UINT_MAX) { 795*45d3cc13Schristos os_free(freq); 796*45d3cc13Schristos return -1; 797*45d3cc13Schristos } 7983c260e60Schristos n = os_realloc_array(freq, count + 1, 7993c260e60Schristos sizeof(struct wpa_freq_range)); 8003c260e60Schristos if (n == NULL) { 8013c260e60Schristos os_free(freq); 8023c260e60Schristos return -1; 8033c260e60Schristos } 8043c260e60Schristos freq = n; 8053c260e60Schristos freq[count].min = atoi(pos); 8063c260e60Schristos pos2 = os_strchr(pos, '-'); 8073c260e60Schristos pos3 = os_strchr(pos, ','); 8083c260e60Schristos if (pos2 && (!pos3 || pos2 < pos3)) { 8093c260e60Schristos pos2++; 8103c260e60Schristos freq[count].max = atoi(pos2); 8113c260e60Schristos } else 8123c260e60Schristos freq[count].max = freq[count].min; 8133c260e60Schristos pos = pos3; 8143c260e60Schristos if (pos) 8153c260e60Schristos pos++; 8163c260e60Schristos count++; 8173c260e60Schristos } 8183c260e60Schristos 8193c260e60Schristos os_free(res->range); 8203c260e60Schristos res->range = freq; 8213c260e60Schristos res->num = count; 8223c260e60Schristos 8233c260e60Schristos return 0; 8243c260e60Schristos } 8253c260e60Schristos 8263c260e60Schristos 8273c260e60Schristos int freq_range_list_includes(const struct wpa_freq_range_list *list, 8283c260e60Schristos unsigned int freq) 8293c260e60Schristos { 8303c260e60Schristos unsigned int i; 8313c260e60Schristos 8323c260e60Schristos if (list == NULL) 8333c260e60Schristos return 0; 8343c260e60Schristos 8353c260e60Schristos for (i = 0; i < list->num; i++) { 8363c260e60Schristos if (freq >= list->range[i].min && freq <= list->range[i].max) 8373c260e60Schristos return 1; 8383c260e60Schristos } 8393c260e60Schristos 8403c260e60Schristos return 0; 8413c260e60Schristos } 8423c260e60Schristos 8433c260e60Schristos 8443c260e60Schristos char * freq_range_list_str(const struct wpa_freq_range_list *list) 8453c260e60Schristos { 8463c260e60Schristos char *buf, *pos, *end; 8473c260e60Schristos size_t maxlen; 8483c260e60Schristos unsigned int i; 8493c260e60Schristos int res; 8503c260e60Schristos 8513c260e60Schristos if (list->num == 0) 8523c260e60Schristos return NULL; 8533c260e60Schristos 8543c260e60Schristos maxlen = list->num * 30; 8553c260e60Schristos buf = os_malloc(maxlen); 8563c260e60Schristos if (buf == NULL) 8573c260e60Schristos return NULL; 8583c260e60Schristos pos = buf; 8593c260e60Schristos end = buf + maxlen; 8603c260e60Schristos 8613c260e60Schristos for (i = 0; i < list->num; i++) { 8623c260e60Schristos struct wpa_freq_range *range = &list->range[i]; 8633c260e60Schristos 8643c260e60Schristos if (range->min == range->max) 8653c260e60Schristos res = os_snprintf(pos, end - pos, "%s%u", 8663c260e60Schristos i == 0 ? "" : ",", range->min); 8673c260e60Schristos else 8683c260e60Schristos res = os_snprintf(pos, end - pos, "%s%u-%u", 8693c260e60Schristos i == 0 ? "" : ",", 8703c260e60Schristos range->min, range->max); 871bb610346Schristos if (os_snprintf_error(end - pos, res)) { 8723c260e60Schristos os_free(buf); 8733c260e60Schristos return NULL; 8743c260e60Schristos } 8753c260e60Schristos pos += res; 8763c260e60Schristos } 8773c260e60Schristos 8783c260e60Schristos return buf; 8793c260e60Schristos } 8803c260e60Schristos 8813c260e60Schristos 882*45d3cc13Schristos size_t int_array_len(const int *a) 8833c260e60Schristos { 884*45d3cc13Schristos size_t i; 885*45d3cc13Schristos 8863c260e60Schristos for (i = 0; a && a[i]; i++) 8873c260e60Schristos ; 8883c260e60Schristos return i; 8893c260e60Schristos } 8903c260e60Schristos 8913c260e60Schristos 8923c260e60Schristos void int_array_concat(int **res, const int *a) 8933c260e60Schristos { 894*45d3cc13Schristos size_t reslen, alen, i, max_size; 8953c260e60Schristos int *n; 8963c260e60Schristos 8973c260e60Schristos reslen = int_array_len(*res); 8983c260e60Schristos alen = int_array_len(a); 899*45d3cc13Schristos max_size = (size_t) -1; 900*45d3cc13Schristos if (alen >= max_size - reslen) { 901*45d3cc13Schristos /* This should not really happen, but if it did, something 902*45d3cc13Schristos * would overflow. Do not try to merge the arrays; instead, make 903*45d3cc13Schristos * this behave like memory allocation failure to avoid messing 904*45d3cc13Schristos * up memory. */ 905*45d3cc13Schristos os_free(*res); 906*45d3cc13Schristos *res = NULL; 907*45d3cc13Schristos return; 908*45d3cc13Schristos } 9093c260e60Schristos n = os_realloc_array(*res, reslen + alen + 1, sizeof(int)); 9103c260e60Schristos if (n == NULL) { 9113c260e60Schristos os_free(*res); 9123c260e60Schristos *res = NULL; 9133c260e60Schristos return; 9143c260e60Schristos } 9153c260e60Schristos for (i = 0; i <= alen; i++) 9163c260e60Schristos n[reslen + i] = a[i]; 9173c260e60Schristos *res = n; 9183c260e60Schristos } 9193c260e60Schristos 9203c260e60Schristos 9213c260e60Schristos static int freq_cmp(const void *a, const void *b) 9223c260e60Schristos { 9233c260e60Schristos int _a = *(int *) a; 9243c260e60Schristos int _b = *(int *) b; 9253c260e60Schristos 9263c260e60Schristos if (_a == 0) 9273c260e60Schristos return 1; 9283c260e60Schristos if (_b == 0) 9293c260e60Schristos return -1; 9303c260e60Schristos return _a - _b; 9313c260e60Schristos } 9323c260e60Schristos 9333c260e60Schristos 9343c260e60Schristos void int_array_sort_unique(int *a) 9353c260e60Schristos { 936*45d3cc13Schristos size_t alen, i, j; 9373c260e60Schristos 9383c260e60Schristos if (a == NULL) 9393c260e60Schristos return; 9403c260e60Schristos 9413c260e60Schristos alen = int_array_len(a); 9423c260e60Schristos qsort(a, alen, sizeof(int), freq_cmp); 9433c260e60Schristos 9443c260e60Schristos i = 0; 9453c260e60Schristos j = 1; 9463c260e60Schristos while (a[i] && a[j]) { 9473c260e60Schristos if (a[i] == a[j]) { 9483c260e60Schristos j++; 9493c260e60Schristos continue; 9503c260e60Schristos } 9513c260e60Schristos a[++i] = a[j++]; 9523c260e60Schristos } 9533c260e60Schristos if (a[i]) 9543c260e60Schristos i++; 9553c260e60Schristos a[i] = 0; 9563c260e60Schristos } 9573c260e60Schristos 9583c260e60Schristos 9593c260e60Schristos void int_array_add_unique(int **res, int a) 9603c260e60Schristos { 961*45d3cc13Schristos size_t reslen, max_size; 9623c260e60Schristos int *n; 9633c260e60Schristos 9643c260e60Schristos for (reslen = 0; *res && (*res)[reslen]; reslen++) { 9653c260e60Schristos if ((*res)[reslen] == a) 9663c260e60Schristos return; /* already in the list */ 9673c260e60Schristos } 9683c260e60Schristos 969*45d3cc13Schristos max_size = (size_t) -1; 970*45d3cc13Schristos if (reslen > max_size - 2) { 971*45d3cc13Schristos /* This should not really happen in practice, but if it did, 972*45d3cc13Schristos * something would overflow. Do not try to add the new value; 973*45d3cc13Schristos * instead, make this behave like memory allocation failure to 974*45d3cc13Schristos * avoid messing up memory. */ 975*45d3cc13Schristos os_free(*res); 976*45d3cc13Schristos *res = NULL; 977*45d3cc13Schristos return; 978*45d3cc13Schristos } 9793c260e60Schristos n = os_realloc_array(*res, reslen + 2, sizeof(int)); 9803c260e60Schristos if (n == NULL) { 9813c260e60Schristos os_free(*res); 9823c260e60Schristos *res = NULL; 9833c260e60Schristos return; 9843c260e60Schristos } 9853c260e60Schristos 9863c260e60Schristos n[reslen] = a; 9873c260e60Schristos n[reslen + 1] = 0; 9883c260e60Schristos 9893c260e60Schristos *res = n; 9903c260e60Schristos } 9913c260e60Schristos 9923c260e60Schristos 993*45d3cc13Schristos bool int_array_includes(int *arr, int val) 994*45d3cc13Schristos { 995*45d3cc13Schristos int i; 996*45d3cc13Schristos 997*45d3cc13Schristos for (i = 0; arr && arr[i]; i++) { 998*45d3cc13Schristos if (val == arr[i]) 999*45d3cc13Schristos return true; 1000*45d3cc13Schristos } 1001*45d3cc13Schristos 1002*45d3cc13Schristos return false; 1003*45d3cc13Schristos } 1004*45d3cc13Schristos 1005*45d3cc13Schristos 10063c260e60Schristos void str_clear_free(char *str) 10073c260e60Schristos { 10083c260e60Schristos if (str) { 10093c260e60Schristos size_t len = os_strlen(str); 1010460bb4fcSchristos forced_memzero(str, len); 10113c260e60Schristos os_free(str); 10123c260e60Schristos } 10133c260e60Schristos } 10143c260e60Schristos 10153c260e60Schristos 10163c260e60Schristos void bin_clear_free(void *bin, size_t len) 10173c260e60Schristos { 10183c260e60Schristos if (bin) { 1019460bb4fcSchristos forced_memzero(bin, len); 10203c260e60Schristos os_free(bin); 10213c260e60Schristos } 10223c260e60Schristos } 10233c260e60Schristos 10243c260e60Schristos 10253c260e60Schristos int random_mac_addr(u8 *addr) 10263c260e60Schristos { 10273c260e60Schristos if (os_get_random(addr, ETH_ALEN) < 0) 10283c260e60Schristos return -1; 10293c260e60Schristos addr[0] &= 0xfe; /* unicast */ 10303c260e60Schristos addr[0] |= 0x02; /* locally administered */ 10313c260e60Schristos return 0; 10323c260e60Schristos } 10333c260e60Schristos 10343c260e60Schristos 10353c260e60Schristos int random_mac_addr_keep_oui(u8 *addr) 10363c260e60Schristos { 10373c260e60Schristos if (os_get_random(addr + 3, 3) < 0) 10383c260e60Schristos return -1; 10393c260e60Schristos addr[0] &= 0xfe; /* unicast */ 10403c260e60Schristos addr[0] |= 0x02; /* locally administered */ 10413c260e60Schristos return 0; 10423c260e60Schristos } 1043bb610346Schristos 1044bb610346Schristos 1045bb610346Schristos /** 1046ecc36642Schristos * cstr_token - Get next token from const char string 1047ecc36642Schristos * @str: a constant string to tokenize 1048ecc36642Schristos * @delim: a string of delimiters 1049ecc36642Schristos * @last: a pointer to a character following the returned token 1050ecc36642Schristos * It has to be set to NULL for the first call and passed for any 1051ecc36642Schristos * further call. 1052ecc36642Schristos * Returns: a pointer to token position in str or NULL 1053ecc36642Schristos * 1054ecc36642Schristos * This function is similar to str_token, but it can be used with both 1055ecc36642Schristos * char and const char strings. Differences: 1056ecc36642Schristos * - The str buffer remains unmodified 1057ecc36642Schristos * - The returned token is not a NULL terminated string, but a token 1058ecc36642Schristos * position in str buffer. If a return value is not NULL a size 1059ecc36642Schristos * of the returned token could be calculated as (last - token). 1060ecc36642Schristos */ 1061ecc36642Schristos const char * cstr_token(const char *str, const char *delim, const char **last) 1062ecc36642Schristos { 1063ecc36642Schristos const char *end, *token = str; 1064ecc36642Schristos 1065ecc36642Schristos if (!str || !delim || !last) 1066ecc36642Schristos return NULL; 1067ecc36642Schristos 1068ecc36642Schristos if (*last) 1069ecc36642Schristos token = *last; 1070ecc36642Schristos 1071ecc36642Schristos while (*token && os_strchr(delim, *token)) 1072ecc36642Schristos token++; 1073ecc36642Schristos 1074ecc36642Schristos if (!*token) 1075ecc36642Schristos return NULL; 1076ecc36642Schristos 1077ecc36642Schristos end = token + 1; 1078ecc36642Schristos 1079ecc36642Schristos while (*end && !os_strchr(delim, *end)) 1080ecc36642Schristos end++; 1081ecc36642Schristos 1082ecc36642Schristos *last = end; 1083ecc36642Schristos return token; 1084ecc36642Schristos } 1085ecc36642Schristos 1086ecc36642Schristos 1087ecc36642Schristos /** 1088bb610346Schristos * str_token - Get next token from a string 1089bb610346Schristos * @buf: String to tokenize. Note that the string might be modified. 1090bb610346Schristos * @delim: String of delimiters 1091bb610346Schristos * @context: Pointer to save our context. Should be initialized with 1092bb610346Schristos * NULL on the first call, and passed for any further call. 1093bb610346Schristos * Returns: The next token, NULL if there are no more valid tokens. 1094bb610346Schristos */ 1095bb610346Schristos char * str_token(char *str, const char *delim, char **context) 1096bb610346Schristos { 1097ecc36642Schristos char *token = (char *) cstr_token(str, delim, (const char **) context); 1098bb610346Schristos 1099ecc36642Schristos if (token && **context) 1100ecc36642Schristos *(*context)++ = '\0'; 1101bb610346Schristos 1102ecc36642Schristos return token; 1103bb610346Schristos } 1104bb610346Schristos 1105bb610346Schristos 1106bb610346Schristos size_t utf8_unescape(const char *inp, size_t in_size, 1107bb610346Schristos char *outp, size_t out_size) 1108bb610346Schristos { 1109bb610346Schristos size_t res_size = 0; 1110bb610346Schristos 1111bb610346Schristos if (!inp || !outp) 1112bb610346Schristos return 0; 1113bb610346Schristos 1114bb610346Schristos if (!in_size) 1115bb610346Schristos in_size = os_strlen(inp); 1116bb610346Schristos 1117bb610346Schristos /* Advance past leading single quote */ 1118bb610346Schristos if (*inp == '\'' && in_size) { 1119bb610346Schristos inp++; 1120bb610346Schristos in_size--; 1121bb610346Schristos } 1122bb610346Schristos 1123460bb4fcSchristos while (in_size) { 1124460bb4fcSchristos in_size--; 1125bb610346Schristos if (res_size >= out_size) 1126bb610346Schristos return 0; 1127bb610346Schristos 1128bb610346Schristos switch (*inp) { 1129bb610346Schristos case '\'': 1130bb610346Schristos /* Terminate on bare single quote */ 1131bb610346Schristos *outp = '\0'; 1132bb610346Schristos return res_size; 1133bb610346Schristos 1134bb610346Schristos case '\\': 1135460bb4fcSchristos if (!in_size) 1136bb610346Schristos return 0; 1137460bb4fcSchristos in_size--; 1138bb610346Schristos inp++; 1139bb610346Schristos /* fall through */ 1140bb610346Schristos 1141bb610346Schristos default: 1142bb610346Schristos *outp++ = *inp++; 1143bb610346Schristos res_size++; 1144bb610346Schristos } 1145bb610346Schristos } 1146bb610346Schristos 1147bb610346Schristos /* NUL terminate if space allows */ 1148bb610346Schristos if (res_size < out_size) 1149bb610346Schristos *outp = '\0'; 1150bb610346Schristos 1151bb610346Schristos return res_size; 1152bb610346Schristos } 1153bb610346Schristos 1154bb610346Schristos 1155bb610346Schristos size_t utf8_escape(const char *inp, size_t in_size, 1156bb610346Schristos char *outp, size_t out_size) 1157bb610346Schristos { 1158bb610346Schristos size_t res_size = 0; 1159bb610346Schristos 1160bb610346Schristos if (!inp || !outp) 1161bb610346Schristos return 0; 1162bb610346Schristos 1163bb610346Schristos /* inp may or may not be NUL terminated, but must be if 0 size 1164bb610346Schristos * is specified */ 1165bb610346Schristos if (!in_size) 1166bb610346Schristos in_size = os_strlen(inp); 1167bb610346Schristos 1168460bb4fcSchristos while (in_size) { 1169460bb4fcSchristos in_size--; 1170bb610346Schristos if (res_size++ >= out_size) 1171bb610346Schristos return 0; 1172bb610346Schristos 1173bb610346Schristos switch (*inp) { 1174bb610346Schristos case '\\': 1175bb610346Schristos case '\'': 1176bb610346Schristos if (res_size++ >= out_size) 1177bb610346Schristos return 0; 1178bb610346Schristos *outp++ = '\\'; 1179bb610346Schristos /* fall through */ 1180bb610346Schristos 1181bb610346Schristos default: 1182bb610346Schristos *outp++ = *inp++; 1183bb610346Schristos break; 1184bb610346Schristos } 1185bb610346Schristos } 1186bb610346Schristos 1187bb610346Schristos /* NUL terminate if space allows */ 1188bb610346Schristos if (res_size < out_size) 1189bb610346Schristos *outp = '\0'; 1190bb610346Schristos 1191bb610346Schristos return res_size; 1192bb610346Schristos } 1193ecc36642Schristos 1194ecc36642Schristos 1195ecc36642Schristos int is_ctrl_char(char c) 1196ecc36642Schristos { 1197ecc36642Schristos return c > 0 && c < 32; 1198ecc36642Schristos } 1199ecc36642Schristos 1200ecc36642Schristos 1201ecc36642Schristos /** 1202ecc36642Schristos * ssid_parse - Parse a string that contains SSID in hex or text format 1203ecc36642Schristos * @buf: Input NULL terminated string that contains the SSID 1204ecc36642Schristos * @ssid: Output SSID 1205ecc36642Schristos * Returns: 0 on success, -1 otherwise 1206ecc36642Schristos * 1207ecc36642Schristos * The SSID has to be enclosed in double quotes for the text format or space 1208ecc36642Schristos * or NULL terminated string of hex digits for the hex format. buf can include 1209ecc36642Schristos * additional arguments after the SSID. 1210ecc36642Schristos */ 1211ecc36642Schristos int ssid_parse(const char *buf, struct wpa_ssid_value *ssid) 1212ecc36642Schristos { 1213ecc36642Schristos char *tmp, *res, *end; 1214ecc36642Schristos size_t len; 1215ecc36642Schristos 1216ecc36642Schristos ssid->ssid_len = 0; 1217ecc36642Schristos 1218ecc36642Schristos tmp = os_strdup(buf); 1219ecc36642Schristos if (!tmp) 1220ecc36642Schristos return -1; 1221ecc36642Schristos 1222ecc36642Schristos if (*tmp != '"') { 1223ecc36642Schristos end = os_strchr(tmp, ' '); 1224ecc36642Schristos if (end) 1225ecc36642Schristos *end = '\0'; 1226ecc36642Schristos } else { 1227ecc36642Schristos end = os_strchr(tmp + 1, '"'); 1228ecc36642Schristos if (!end) { 1229ecc36642Schristos os_free(tmp); 1230ecc36642Schristos return -1; 1231ecc36642Schristos } 1232ecc36642Schristos 1233ecc36642Schristos end[1] = '\0'; 1234ecc36642Schristos } 1235ecc36642Schristos 1236ecc36642Schristos res = wpa_config_parse_string(tmp, &len); 1237ecc36642Schristos if (res && len <= SSID_MAX_LEN) { 1238ecc36642Schristos ssid->ssid_len = len; 1239ecc36642Schristos os_memcpy(ssid->ssid, res, len); 1240ecc36642Schristos } 1241ecc36642Schristos 1242ecc36642Schristos os_free(tmp); 1243ecc36642Schristos os_free(res); 1244ecc36642Schristos 1245ecc36642Schristos return ssid->ssid_len ? 0 : -1; 1246ecc36642Schristos } 1247ecc36642Schristos 1248ecc36642Schristos 1249ecc36642Schristos int str_starts(const char *str, const char *start) 1250ecc36642Schristos { 1251ecc36642Schristos return os_strncmp(str, start, os_strlen(start)) == 0; 1252ecc36642Schristos } 1253be6b3c4dSchristos 1254be6b3c4dSchristos 1255be6b3c4dSchristos /** 1256be6b3c4dSchristos * rssi_to_rcpi - Convert RSSI to RCPI 1257be6b3c4dSchristos * @rssi: RSSI to convert 1258be6b3c4dSchristos * Returns: RCPI corresponding to the given RSSI value, or 255 if not available. 1259be6b3c4dSchristos * 1260be6b3c4dSchristos * It's possible to estimate RCPI based on RSSI in dBm. This calculation will 1261be6b3c4dSchristos * not reflect the correct value for high rates, but it's good enough for Action 1262be6b3c4dSchristos * frames which are transmitted with up to 24 Mbps rates. 1263be6b3c4dSchristos */ 1264be6b3c4dSchristos u8 rssi_to_rcpi(int rssi) 1265be6b3c4dSchristos { 1266be6b3c4dSchristos if (!rssi) 1267be6b3c4dSchristos return 255; /* not available */ 1268be6b3c4dSchristos if (rssi < -110) 1269be6b3c4dSchristos return 0; 1270be6b3c4dSchristos if (rssi > 0) 1271be6b3c4dSchristos return 220; 1272be6b3c4dSchristos return (rssi + 110) * 2; 1273be6b3c4dSchristos } 1274460bb4fcSchristos 1275460bb4fcSchristos 1276460bb4fcSchristos char * get_param(const char *cmd, const char *param) 1277460bb4fcSchristos { 1278460bb4fcSchristos const char *pos, *end; 1279460bb4fcSchristos char *val; 1280460bb4fcSchristos size_t len; 1281460bb4fcSchristos 1282460bb4fcSchristos pos = os_strstr(cmd, param); 1283460bb4fcSchristos if (!pos) 1284460bb4fcSchristos return NULL; 1285460bb4fcSchristos 1286460bb4fcSchristos pos += os_strlen(param); 1287460bb4fcSchristos end = os_strchr(pos, ' '); 1288460bb4fcSchristos if (end) 1289460bb4fcSchristos len = end - pos; 1290460bb4fcSchristos else 1291460bb4fcSchristos len = os_strlen(pos); 1292460bb4fcSchristos val = os_malloc(len + 1); 1293460bb4fcSchristos if (!val) 1294460bb4fcSchristos return NULL; 1295460bb4fcSchristos os_memcpy(val, pos, len); 1296460bb4fcSchristos val[len] = '\0'; 1297460bb4fcSchristos return val; 1298460bb4fcSchristos } 1299460bb4fcSchristos 1300460bb4fcSchristos 1301460bb4fcSchristos /* Try to prevent most compilers from optimizing out clearing of memory that 1302460bb4fcSchristos * becomes unaccessible after this function is called. This is mostly the case 1303460bb4fcSchristos * for clearing local stack variables at the end of a function. This is not 1304460bb4fcSchristos * exactly perfect, i.e., someone could come up with a compiler that figures out 1305460bb4fcSchristos * the pointer is pointing to memset and then end up optimizing the call out, so 1306460bb4fcSchristos * try go a bit further by storing the first octet (now zero) to make this even 1307460bb4fcSchristos * a bit more difficult to optimize out. Once memset_s() is available, that 1308460bb4fcSchristos * could be used here instead. */ 1309460bb4fcSchristos static void * (* const volatile memset_func)(void *, int, size_t) = memset; 1310460bb4fcSchristos static u8 forced_memzero_val; 1311460bb4fcSchristos 1312460bb4fcSchristos void forced_memzero(void *ptr, size_t len) 1313460bb4fcSchristos { 1314460bb4fcSchristos memset_func(ptr, 0, len); 1315460bb4fcSchristos if (len) 1316460bb4fcSchristos forced_memzero_val = ((u8 *) ptr)[0]; 1317460bb4fcSchristos } 1318