xref: /netbsd-src/external/bsd/wpa/dist/src/utils/common.c (revision 45d3cc13f775755ee348416d64536fb30df46e06)
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