common.c revision 252726
1189251Ssam/*
2189251Ssam * wpa_supplicant/hostapd / common helper functions, etc.
3189251Ssam * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
4189251Ssam *
5252726Srpaulo * This software may be distributed under the terms of the BSD license.
6252726Srpaulo * See README for more details.
7189251Ssam */
8189251Ssam
9189251Ssam#include "includes.h"
10189251Ssam
11189251Ssam#include "common.h"
12189251Ssam
13189251Ssam
14189251Ssamstatic int hex2num(char c)
15189251Ssam{
16189251Ssam	if (c >= '0' && c <= '9')
17189251Ssam		return c - '0';
18189251Ssam	if (c >= 'a' && c <= 'f')
19189251Ssam		return c - 'a' + 10;
20189251Ssam	if (c >= 'A' && c <= 'F')
21189251Ssam		return c - 'A' + 10;
22189251Ssam	return -1;
23189251Ssam}
24189251Ssam
25189251Ssam
26252726Srpauloint hex2byte(const char *hex)
27189251Ssam{
28189251Ssam	int a, b;
29189251Ssam	a = hex2num(*hex++);
30189251Ssam	if (a < 0)
31189251Ssam		return -1;
32189251Ssam	b = hex2num(*hex++);
33189251Ssam	if (b < 0)
34189251Ssam		return -1;
35189251Ssam	return (a << 4) | b;
36189251Ssam}
37189251Ssam
38189251Ssam
39189251Ssam/**
40214734Srpaulo * hwaddr_aton - Convert ASCII string to MAC address (colon-delimited format)
41189251Ssam * @txt: MAC address as a string (e.g., "00:11:22:33:44:55")
42189251Ssam * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
43189251Ssam * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
44189251Ssam */
45189251Ssamint hwaddr_aton(const char *txt, u8 *addr)
46189251Ssam{
47189251Ssam	int i;
48189251Ssam
49189251Ssam	for (i = 0; i < 6; i++) {
50189251Ssam		int a, b;
51189251Ssam
52189251Ssam		a = hex2num(*txt++);
53189251Ssam		if (a < 0)
54189251Ssam			return -1;
55189251Ssam		b = hex2num(*txt++);
56189251Ssam		if (b < 0)
57189251Ssam			return -1;
58189251Ssam		*addr++ = (a << 4) | b;
59189251Ssam		if (i < 5 && *txt++ != ':')
60189251Ssam			return -1;
61189251Ssam	}
62189251Ssam
63189251Ssam	return 0;
64189251Ssam}
65189251Ssam
66252726Srpaulo/**
67252726Srpaulo * hwaddr_compact_aton - Convert ASCII string to MAC address (no colon delimitors format)
68252726Srpaulo * @txt: MAC address as a string (e.g., "001122334455")
69252726Srpaulo * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
70252726Srpaulo * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
71252726Srpaulo */
72252726Srpauloint hwaddr_compact_aton(const char *txt, u8 *addr)
73252726Srpaulo{
74252726Srpaulo	int i;
75189251Ssam
76252726Srpaulo	for (i = 0; i < 6; i++) {
77252726Srpaulo		int a, b;
78252726Srpaulo
79252726Srpaulo		a = hex2num(*txt++);
80252726Srpaulo		if (a < 0)
81252726Srpaulo			return -1;
82252726Srpaulo		b = hex2num(*txt++);
83252726Srpaulo		if (b < 0)
84252726Srpaulo			return -1;
85252726Srpaulo		*addr++ = (a << 4) | b;
86252726Srpaulo	}
87252726Srpaulo
88252726Srpaulo	return 0;
89252726Srpaulo}
90252726Srpaulo
91189251Ssam/**
92214734Srpaulo * hwaddr_aton2 - Convert ASCII string to MAC address (in any known format)
93214734Srpaulo * @txt: MAC address as a string (e.g., 00:11:22:33:44:55 or 0011.2233.4455)
94214734Srpaulo * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
95214734Srpaulo * Returns: Characters used (> 0) on success, -1 on failure
96214734Srpaulo */
97214734Srpauloint hwaddr_aton2(const char *txt, u8 *addr)
98214734Srpaulo{
99214734Srpaulo	int i;
100214734Srpaulo	const char *pos = txt;
101214734Srpaulo
102214734Srpaulo	for (i = 0; i < 6; i++) {
103214734Srpaulo		int a, b;
104214734Srpaulo
105214734Srpaulo		while (*pos == ':' || *pos == '.' || *pos == '-')
106214734Srpaulo			pos++;
107214734Srpaulo
108214734Srpaulo		a = hex2num(*pos++);
109214734Srpaulo		if (a < 0)
110214734Srpaulo			return -1;
111214734Srpaulo		b = hex2num(*pos++);
112214734Srpaulo		if (b < 0)
113214734Srpaulo			return -1;
114214734Srpaulo		*addr++ = (a << 4) | b;
115214734Srpaulo	}
116214734Srpaulo
117214734Srpaulo	return pos - txt;
118214734Srpaulo}
119214734Srpaulo
120214734Srpaulo
121214734Srpaulo/**
122189251Ssam * hexstr2bin - Convert ASCII hex string into binary data
123189251Ssam * @hex: ASCII hex string (e.g., "01ab")
124189251Ssam * @buf: Buffer for the binary data
125189251Ssam * @len: Length of the text to convert in bytes (of buf); hex will be double
126189251Ssam * this size
127189251Ssam * Returns: 0 on success, -1 on failure (invalid hex string)
128189251Ssam */
129189251Ssamint hexstr2bin(const char *hex, u8 *buf, size_t len)
130189251Ssam{
131189251Ssam	size_t i;
132189251Ssam	int a;
133189251Ssam	const char *ipos = hex;
134189251Ssam	u8 *opos = buf;
135189251Ssam
136189251Ssam	for (i = 0; i < len; i++) {
137189251Ssam		a = hex2byte(ipos);
138189251Ssam		if (a < 0)
139189251Ssam			return -1;
140189251Ssam		*opos++ = a;
141189251Ssam		ipos += 2;
142189251Ssam	}
143189251Ssam	return 0;
144189251Ssam}
145189251Ssam
146189251Ssam
147189251Ssam/**
148189251Ssam * inc_byte_array - Increment arbitrary length byte array by one
149189251Ssam * @counter: Pointer to byte array
150189251Ssam * @len: Length of the counter in bytes
151189251Ssam *
152189251Ssam * This function increments the last byte of the counter by one and continues
153189251Ssam * rolling over to more significant bytes if the byte was incremented from
154189251Ssam * 0xff to 0x00.
155189251Ssam */
156189251Ssamvoid inc_byte_array(u8 *counter, size_t len)
157189251Ssam{
158189251Ssam	int pos = len - 1;
159189251Ssam	while (pos >= 0) {
160189251Ssam		counter[pos]++;
161189251Ssam		if (counter[pos] != 0)
162189251Ssam			break;
163189251Ssam		pos--;
164189251Ssam	}
165189251Ssam}
166189251Ssam
167189251Ssam
168189251Ssamvoid wpa_get_ntp_timestamp(u8 *buf)
169189251Ssam{
170189251Ssam	struct os_time now;
171189251Ssam	u32 sec, usec;
172189251Ssam	be32 tmp;
173189251Ssam
174189251Ssam	/* 64-bit NTP timestamp (time from 1900-01-01 00:00:00) */
175189251Ssam	os_get_time(&now);
176189251Ssam	sec = now.sec + 2208988800U; /* Epoch to 1900 */
177189251Ssam	/* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */
178189251Ssam	usec = now.usec;
179189251Ssam	usec = 4295 * usec - (usec >> 5) - (usec >> 9);
180189251Ssam	tmp = host_to_be32(sec);
181189251Ssam	os_memcpy(buf, (u8 *) &tmp, 4);
182189251Ssam	tmp = host_to_be32(usec);
183189251Ssam	os_memcpy(buf + 4, (u8 *) &tmp, 4);
184189251Ssam}
185189251Ssam
186189251Ssam
187189251Ssamstatic inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data,
188189251Ssam				    size_t len, int uppercase)
189189251Ssam{
190189251Ssam	size_t i;
191189251Ssam	char *pos = buf, *end = buf + buf_size;
192189251Ssam	int ret;
193189251Ssam	if (buf_size == 0)
194189251Ssam		return 0;
195189251Ssam	for (i = 0; i < len; i++) {
196189251Ssam		ret = os_snprintf(pos, end - pos, uppercase ? "%02X" : "%02x",
197189251Ssam				  data[i]);
198189251Ssam		if (ret < 0 || ret >= end - pos) {
199189251Ssam			end[-1] = '\0';
200189251Ssam			return pos - buf;
201189251Ssam		}
202189251Ssam		pos += ret;
203189251Ssam	}
204189251Ssam	end[-1] = '\0';
205189251Ssam	return pos - buf;
206189251Ssam}
207189251Ssam
208189251Ssam/**
209189251Ssam * wpa_snprintf_hex - Print data as a hex string into a buffer
210189251Ssam * @buf: Memory area to use as the output buffer
211189251Ssam * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1)
212189251Ssam * @data: Data to be printed
213189251Ssam * @len: Length of data in bytes
214189251Ssam * Returns: Number of bytes written
215189251Ssam */
216189251Ssamint wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len)
217189251Ssam{
218189251Ssam	return _wpa_snprintf_hex(buf, buf_size, data, len, 0);
219189251Ssam}
220189251Ssam
221189251Ssam
222189251Ssam/**
223189251Ssam * wpa_snprintf_hex_uppercase - Print data as a upper case hex string into buf
224189251Ssam * @buf: Memory area to use as the output buffer
225189251Ssam * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1)
226189251Ssam * @data: Data to be printed
227189251Ssam * @len: Length of data in bytes
228189251Ssam * Returns: Number of bytes written
229189251Ssam */
230189251Ssamint wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data,
231189251Ssam			       size_t len)
232189251Ssam{
233189251Ssam	return _wpa_snprintf_hex(buf, buf_size, data, len, 1);
234189251Ssam}
235189251Ssam
236189251Ssam
237189251Ssam#ifdef CONFIG_ANSI_C_EXTRA
238189251Ssam
239189251Ssam#ifdef _WIN32_WCE
240189251Ssamvoid perror(const char *s)
241189251Ssam{
242189251Ssam	wpa_printf(MSG_ERROR, "%s: GetLastError: %d",
243189251Ssam		   s, (int) GetLastError());
244189251Ssam}
245189251Ssam#endif /* _WIN32_WCE */
246189251Ssam
247189251Ssam
248189251Ssamint optind = 1;
249189251Ssamint optopt;
250189251Ssamchar *optarg;
251189251Ssam
252189251Ssamint getopt(int argc, char *const argv[], const char *optstring)
253189251Ssam{
254189251Ssam	static int optchr = 1;
255189251Ssam	char *cp;
256189251Ssam
257189251Ssam	if (optchr == 1) {
258189251Ssam		if (optind >= argc) {
259189251Ssam			/* all arguments processed */
260189251Ssam			return EOF;
261189251Ssam		}
262189251Ssam
263189251Ssam		if (argv[optind][0] != '-' || argv[optind][1] == '\0') {
264189251Ssam			/* no option characters */
265189251Ssam			return EOF;
266189251Ssam		}
267189251Ssam	}
268189251Ssam
269189251Ssam	if (os_strcmp(argv[optind], "--") == 0) {
270189251Ssam		/* no more options */
271189251Ssam		optind++;
272189251Ssam		return EOF;
273189251Ssam	}
274189251Ssam
275189251Ssam	optopt = argv[optind][optchr];
276189251Ssam	cp = os_strchr(optstring, optopt);
277189251Ssam	if (cp == NULL || optopt == ':') {
278189251Ssam		if (argv[optind][++optchr] == '\0') {
279189251Ssam			optchr = 1;
280189251Ssam			optind++;
281189251Ssam		}
282189251Ssam		return '?';
283189251Ssam	}
284189251Ssam
285189251Ssam	if (cp[1] == ':') {
286189251Ssam		/* Argument required */
287189251Ssam		optchr = 1;
288189251Ssam		if (argv[optind][optchr + 1]) {
289189251Ssam			/* No space between option and argument */
290189251Ssam			optarg = &argv[optind++][optchr + 1];
291189251Ssam		} else if (++optind >= argc) {
292189251Ssam			/* option requires an argument */
293189251Ssam			return '?';
294189251Ssam		} else {
295189251Ssam			/* Argument in the next argv */
296189251Ssam			optarg = argv[optind++];
297189251Ssam		}
298189251Ssam	} else {
299189251Ssam		/* No argument */
300189251Ssam		if (argv[optind][++optchr] == '\0') {
301189251Ssam			optchr = 1;
302189251Ssam			optind++;
303189251Ssam		}
304189251Ssam		optarg = NULL;
305189251Ssam	}
306189251Ssam	return *cp;
307189251Ssam}
308189251Ssam#endif /* CONFIG_ANSI_C_EXTRA */
309189251Ssam
310189251Ssam
311189251Ssam#ifdef CONFIG_NATIVE_WINDOWS
312189251Ssam/**
313189251Ssam * wpa_unicode2ascii_inplace - Convert unicode string into ASCII
314189251Ssam * @str: Pointer to string to convert
315189251Ssam *
316189251Ssam * This function converts a unicode string to ASCII using the same
317189251Ssam * buffer for output. If UNICODE is not set, the buffer is not
318189251Ssam * modified.
319189251Ssam */
320189251Ssamvoid wpa_unicode2ascii_inplace(TCHAR *str)
321189251Ssam{
322189251Ssam#ifdef UNICODE
323189251Ssam	char *dst = (char *) str;
324189251Ssam	while (*str)
325189251Ssam		*dst++ = (char) *str++;
326189251Ssam	*dst = '\0';
327189251Ssam#endif /* UNICODE */
328189251Ssam}
329189251Ssam
330189251Ssam
331189251SsamTCHAR * wpa_strdup_tchar(const char *str)
332189251Ssam{
333189251Ssam#ifdef UNICODE
334189251Ssam	TCHAR *buf;
335189251Ssam	buf = os_malloc((strlen(str) + 1) * sizeof(TCHAR));
336189251Ssam	if (buf == NULL)
337189251Ssam		return NULL;
338189251Ssam	wsprintf(buf, L"%S", str);
339189251Ssam	return buf;
340189251Ssam#else /* UNICODE */
341189251Ssam	return os_strdup(str);
342189251Ssam#endif /* UNICODE */
343189251Ssam}
344189251Ssam#endif /* CONFIG_NATIVE_WINDOWS */
345189251Ssam
346189251Ssam
347252726Srpaulovoid printf_encode(char *txt, size_t maxlen, const u8 *data, size_t len)
348252726Srpaulo{
349252726Srpaulo	char *end = txt + maxlen;
350252726Srpaulo	size_t i;
351252726Srpaulo
352252726Srpaulo	for (i = 0; i < len; i++) {
353252726Srpaulo		if (txt + 4 > end)
354252726Srpaulo			break;
355252726Srpaulo
356252726Srpaulo		switch (data[i]) {
357252726Srpaulo		case '\"':
358252726Srpaulo			*txt++ = '\\';
359252726Srpaulo			*txt++ = '\"';
360252726Srpaulo			break;
361252726Srpaulo		case '\\':
362252726Srpaulo			*txt++ = '\\';
363252726Srpaulo			*txt++ = '\\';
364252726Srpaulo			break;
365252726Srpaulo		case '\e':
366252726Srpaulo			*txt++ = '\\';
367252726Srpaulo			*txt++ = 'e';
368252726Srpaulo			break;
369252726Srpaulo		case '\n':
370252726Srpaulo			*txt++ = '\\';
371252726Srpaulo			*txt++ = 'n';
372252726Srpaulo			break;
373252726Srpaulo		case '\r':
374252726Srpaulo			*txt++ = '\\';
375252726Srpaulo			*txt++ = 'r';
376252726Srpaulo			break;
377252726Srpaulo		case '\t':
378252726Srpaulo			*txt++ = '\\';
379252726Srpaulo			*txt++ = 't';
380252726Srpaulo			break;
381252726Srpaulo		default:
382252726Srpaulo			if (data[i] >= 32 && data[i] <= 127) {
383252726Srpaulo				*txt++ = data[i];
384252726Srpaulo			} else {
385252726Srpaulo				txt += os_snprintf(txt, end - txt, "\\x%02x",
386252726Srpaulo						   data[i]);
387252726Srpaulo			}
388252726Srpaulo			break;
389252726Srpaulo		}
390252726Srpaulo	}
391252726Srpaulo
392252726Srpaulo	*txt = '\0';
393252726Srpaulo}
394252726Srpaulo
395252726Srpaulo
396252726Srpaulosize_t printf_decode(u8 *buf, size_t maxlen, const char *str)
397252726Srpaulo{
398252726Srpaulo	const char *pos = str;
399252726Srpaulo	size_t len = 0;
400252726Srpaulo	int val;
401252726Srpaulo
402252726Srpaulo	while (*pos) {
403252726Srpaulo		if (len == maxlen)
404252726Srpaulo			break;
405252726Srpaulo		switch (*pos) {
406252726Srpaulo		case '\\':
407252726Srpaulo			pos++;
408252726Srpaulo			switch (*pos) {
409252726Srpaulo			case '\\':
410252726Srpaulo				buf[len++] = '\\';
411252726Srpaulo				pos++;
412252726Srpaulo				break;
413252726Srpaulo			case '"':
414252726Srpaulo				buf[len++] = '"';
415252726Srpaulo				pos++;
416252726Srpaulo				break;
417252726Srpaulo			case 'n':
418252726Srpaulo				buf[len++] = '\n';
419252726Srpaulo				pos++;
420252726Srpaulo				break;
421252726Srpaulo			case 'r':
422252726Srpaulo				buf[len++] = '\r';
423252726Srpaulo				pos++;
424252726Srpaulo				break;
425252726Srpaulo			case 't':
426252726Srpaulo				buf[len++] = '\t';
427252726Srpaulo				pos++;
428252726Srpaulo				break;
429252726Srpaulo			case 'e':
430252726Srpaulo				buf[len++] = '\e';
431252726Srpaulo				pos++;
432252726Srpaulo				break;
433252726Srpaulo			case 'x':
434252726Srpaulo				pos++;
435252726Srpaulo				val = hex2byte(pos);
436252726Srpaulo				if (val < 0) {
437252726Srpaulo					val = hex2num(*pos);
438252726Srpaulo					if (val < 0)
439252726Srpaulo						break;
440252726Srpaulo					buf[len++] = val;
441252726Srpaulo					pos++;
442252726Srpaulo				} else {
443252726Srpaulo					buf[len++] = val;
444252726Srpaulo					pos += 2;
445252726Srpaulo				}
446252726Srpaulo				break;
447252726Srpaulo			case '0':
448252726Srpaulo			case '1':
449252726Srpaulo			case '2':
450252726Srpaulo			case '3':
451252726Srpaulo			case '4':
452252726Srpaulo			case '5':
453252726Srpaulo			case '6':
454252726Srpaulo			case '7':
455252726Srpaulo				val = *pos++ - '0';
456252726Srpaulo				if (*pos >= '0' && *pos <= '7')
457252726Srpaulo					val = val * 8 + (*pos++ - '0');
458252726Srpaulo				if (*pos >= '0' && *pos <= '7')
459252726Srpaulo					val = val * 8 + (*pos++ - '0');
460252726Srpaulo				buf[len++] = val;
461252726Srpaulo				break;
462252726Srpaulo			default:
463252726Srpaulo				break;
464252726Srpaulo			}
465252726Srpaulo			break;
466252726Srpaulo		default:
467252726Srpaulo			buf[len++] = *pos++;
468252726Srpaulo			break;
469252726Srpaulo		}
470252726Srpaulo	}
471252726Srpaulo
472252726Srpaulo	return len;
473252726Srpaulo}
474252726Srpaulo
475252726Srpaulo
476189251Ssam/**
477189251Ssam * wpa_ssid_txt - Convert SSID to a printable string
478189251Ssam * @ssid: SSID (32-octet string)
479189251Ssam * @ssid_len: Length of ssid in octets
480189251Ssam * Returns: Pointer to a printable string
481189251Ssam *
482189251Ssam * This function can be used to convert SSIDs into printable form. In most
483189251Ssam * cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard
484189251Ssam * does not limit the used character set, so anything could be used in an SSID.
485189251Ssam *
486189251Ssam * This function uses a static buffer, so only one call can be used at the
487189251Ssam * time, i.e., this is not re-entrant and the returned buffer must be used
488189251Ssam * before calling this again.
489189251Ssam */
490189251Ssamconst char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len)
491189251Ssam{
492252726Srpaulo	static char ssid_txt[32 * 4 + 1];
493189251Ssam
494252726Srpaulo	if (ssid == NULL) {
495252726Srpaulo		ssid_txt[0] = '\0';
496252726Srpaulo		return ssid_txt;
497189251Ssam	}
498252726Srpaulo
499252726Srpaulo	printf_encode(ssid_txt, sizeof(ssid_txt), ssid, ssid_len);
500189251Ssam	return ssid_txt;
501189251Ssam}
502209158Srpaulo
503209158Srpaulo
504209158Srpaulovoid * __hide_aliasing_typecast(void *foo)
505209158Srpaulo{
506209158Srpaulo	return foo;
507209158Srpaulo}
508252726Srpaulo
509252726Srpaulo
510252726Srpaulochar * wpa_config_parse_string(const char *value, size_t *len)
511252726Srpaulo{
512252726Srpaulo	if (*value == '"') {
513252726Srpaulo		const char *pos;
514252726Srpaulo		char *str;
515252726Srpaulo		value++;
516252726Srpaulo		pos = os_strrchr(value, '"');
517252726Srpaulo		if (pos == NULL || pos[1] != '\0')
518252726Srpaulo			return NULL;
519252726Srpaulo		*len = pos - value;
520252726Srpaulo		str = os_malloc(*len + 1);
521252726Srpaulo		if (str == NULL)
522252726Srpaulo			return NULL;
523252726Srpaulo		os_memcpy(str, value, *len);
524252726Srpaulo		str[*len] = '\0';
525252726Srpaulo		return str;
526252726Srpaulo	} else if (*value == 'P' && value[1] == '"') {
527252726Srpaulo		const char *pos;
528252726Srpaulo		char *tstr, *str;
529252726Srpaulo		size_t tlen;
530252726Srpaulo		value += 2;
531252726Srpaulo		pos = os_strrchr(value, '"');
532252726Srpaulo		if (pos == NULL || pos[1] != '\0')
533252726Srpaulo			return NULL;
534252726Srpaulo		tlen = pos - value;
535252726Srpaulo		tstr = os_malloc(tlen + 1);
536252726Srpaulo		if (tstr == NULL)
537252726Srpaulo			return NULL;
538252726Srpaulo		os_memcpy(tstr, value, tlen);
539252726Srpaulo		tstr[tlen] = '\0';
540252726Srpaulo
541252726Srpaulo		str = os_malloc(tlen + 1);
542252726Srpaulo		if (str == NULL) {
543252726Srpaulo			os_free(tstr);
544252726Srpaulo			return NULL;
545252726Srpaulo		}
546252726Srpaulo
547252726Srpaulo		*len = printf_decode((u8 *) str, tlen + 1, tstr);
548252726Srpaulo		os_free(tstr);
549252726Srpaulo
550252726Srpaulo		return str;
551252726Srpaulo	} else {
552252726Srpaulo		u8 *str;
553252726Srpaulo		size_t tlen, hlen = os_strlen(value);
554252726Srpaulo		if (hlen & 1)
555252726Srpaulo			return NULL;
556252726Srpaulo		tlen = hlen / 2;
557252726Srpaulo		str = os_malloc(tlen + 1);
558252726Srpaulo		if (str == NULL)
559252726Srpaulo			return NULL;
560252726Srpaulo		if (hexstr2bin(value, str, tlen)) {
561252726Srpaulo			os_free(str);
562252726Srpaulo			return NULL;
563252726Srpaulo		}
564252726Srpaulo		str[tlen] = '\0';
565252726Srpaulo		*len = tlen;
566252726Srpaulo		return (char *) str;
567252726Srpaulo	}
568252726Srpaulo}
569252726Srpaulo
570252726Srpaulo
571252726Srpauloint is_hex(const u8 *data, size_t len)
572252726Srpaulo{
573252726Srpaulo	size_t i;
574252726Srpaulo
575252726Srpaulo	for (i = 0; i < len; i++) {
576252726Srpaulo		if (data[i] < 32 || data[i] >= 127)
577252726Srpaulo			return 1;
578252726Srpaulo	}
579252726Srpaulo	return 0;
580252726Srpaulo}
581252726Srpaulo
582252726Srpaulo
583252726Srpaulosize_t merge_byte_arrays(u8 *res, size_t res_len,
584252726Srpaulo			 const u8 *src1, size_t src1_len,
585252726Srpaulo			 const u8 *src2, size_t src2_len)
586252726Srpaulo{
587252726Srpaulo	size_t len = 0;
588252726Srpaulo
589252726Srpaulo	os_memset(res, 0, res_len);
590252726Srpaulo
591252726Srpaulo	if (src1) {
592252726Srpaulo		if (src1_len >= res_len) {
593252726Srpaulo			os_memcpy(res, src1, res_len);
594252726Srpaulo			return res_len;
595252726Srpaulo		}
596252726Srpaulo
597252726Srpaulo		os_memcpy(res, src1, src1_len);
598252726Srpaulo		len += src1_len;
599252726Srpaulo	}
600252726Srpaulo
601252726Srpaulo	if (src2) {
602252726Srpaulo		if (len + src2_len >= res_len) {
603252726Srpaulo			os_memcpy(res + len, src2, res_len - len);
604252726Srpaulo			return res_len;
605252726Srpaulo		}
606252726Srpaulo
607252726Srpaulo		os_memcpy(res + len, src2, src2_len);
608252726Srpaulo		len += src2_len;
609252726Srpaulo	}
610252726Srpaulo
611252726Srpaulo	return len;
612252726Srpaulo}
613