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